diff options
112 files changed, 3168 insertions, 1651 deletions
diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/bus/ti-gpmc.txt index 4b87ea1194e..704be9306c9 100644 --- a/Documentation/devicetree/bindings/bus/ti-gpmc.txt +++ b/Documentation/devicetree/bindings/bus/ti-gpmc.txt @@ -95,7 +95,6 @@ GPMC chip-select settings properties for child nodes. All are optional. - gpmc,burst-wrap Enables wrap bursting - gpmc,burst-read Enables read page/burst mode - gpmc,burst-write Enables write page/burst mode -- gpmc,device-nand Device is NAND - gpmc,device-width Total width of device(s) connected to a GPMC chip-select in bytes. The GPMC supports 8-bit and 16-bit devices and so this property must be diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt new file mode 100644 index 00000000000..a1201802f90 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt @@ -0,0 +1,64 @@ +* Samsung Audio Subsystem Clock Controller + +The Samsung Audio Subsystem clock controller generates and supplies clocks +to Audio Subsystem block available in the S5PV210 and Exynos SoCs. The clock +binding described here is applicable to all SoC's in Exynos family. + +Required Properties: + +- compatible: should be one of the following: + - "samsung,exynos4210-audss-clock" - controller compatible with all Exynos4 SoCs. + - "samsung,exynos5250-audss-clock" - controller compatible with all Exynos5 SoCs. + +- reg: physical base address and length of the controller's register set. + +- #clock-cells: should be 1. + +The following is the list of clocks generated by the controller. Each clock is +assigned an identifier and client nodes use this identifier to specify the +clock which they consume. Some of the clocks are available only on a particular +Exynos4 SoC and this is specified where applicable. + +Provided clocks: + +Clock ID SoC (if specific) +----------------------------------------------- + +mout_audss 0 +mout_i2s 1 +dout_srp 2 +dout_aud_bus 3 +dout_i2s 4 +srp_clk 5 +i2s_bus 6 +sclk_i2s 7 +pcm_bus 8 +sclk_pcm 9 + +Example 1: An example of a clock controller node is listed below. + +clock_audss: audss-clock-controller@3810000 { + compatible = "samsung,exynos5250-audss-clock"; + reg = <0x03810000 0x0C>; + #clock-cells = <1>; +}; + +Example 2: I2S controller node that consumes the clock generated by the clock + controller. Refer to the standard clock bindings for information + about 'clocks' and 'clock-names' property. + +i2s0: i2s@03830000 { + compatible = "samsung,i2s-v5"; + reg = <0x03830000 0x100>; + dmas = <&pdma0 10 + &pdma0 9 + &pdma0 8>; + dma-names = "tx", "rx", "tx-sec"; + clocks = <&clock_audss EXYNOS_I2S_BUS>, + <&clock_audss EXYNOS_I2S_BUS>, + <&clock_audss EXYNOS_SCLK_I2S>, + <&clock_audss EXYNOS_MOUT_AUDSS>, + <&clock_audss EXYNOS_MOUT_I2S>; + clock-names = "iis", "i2s_opclk0", "i2s_opclk1", + "mout_audss", "mout_i2s"; +}; diff --git a/Documentation/devicetree/bindings/dma/ste-dma40.txt b/Documentation/devicetree/bindings/dma/ste-dma40.txt new file mode 100644 index 00000000000..bea5b73a739 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/ste-dma40.txt @@ -0,0 +1,66 @@ +* DMA40 DMA Controller + +Required properties: +- compatible: "stericsson,dma40" +- reg: Address range of the DMAC registers +- reg-names: Names of the above areas to use during resource look-up +- interrupt: Should contain the DMAC interrupt number +- #dma-cells: must be <3> +- memcpy-channels: Channels to be used for memcpy + +Optional properties: +- dma-channels: Number of channels supported by hardware - if not present + the driver will attempt to obtain the information from H/W +- disabled-channels: Channels which can not be used + +Example: + + dma: dma-controller@801C0000 { + compatible = "stericsson,db8500-dma40", "stericsson,dma40"; + reg = <0x801C0000 0x1000 0x40010000 0x800>; + reg-names = "base", "lcpa"; + interrupt-parent = <&intc>; + interrupts = <0 25 0x4>; + + #dma-cells = <2>; + memcpy-channels = <56 57 58 59 60>; + disabled-channels = <12>; + dma-channels = <8>; + }; + +Clients +Required properties: +- dmas: Comma separated list of dma channel requests +- dma-names: Names of the aforementioned requested channels + +Each dmas request consists of 4 cells: + 1. A phandle pointing to the DMA controller + 2. Device Type + 3. The DMA request line number (only when 'use fixed channel' is set) + 4. A 32bit mask specifying; mode, direction and endianess [NB: This list will grow] + 0x00000001: Mode: + Logical channel when unset + Physical channel when set + 0x00000002: Direction: + Memory to Device when unset + Device to Memory when set + 0x00000004: Endianess: + Little endian when unset + Big endian when set + 0x00000008: Use fixed channel: + Use automatic channel selection when unset + Use DMA request line number when set + +Example: + + uart@80120000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x80120000 0x1000>; + interrupts = <0 11 0x4>; + + dmas = <&dma 13 0 0x2>, /* Logical - DevToMem */ + <&dma 13 0 0x0>; /* Logical - MemToDev */ + dma-names = "rx", "rx"; + + status = "disabled"; + }; diff --git a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt index f1e5dfecf55..5375625e8cd 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt @@ -39,46 +39,3 @@ Example: #gpio-cells = <4>; gpio-controller; }; - - -Samsung S3C24XX GPIO Controller - -Required properties: -- compatible: Compatible property value should be "samsung,s3c24xx-gpio". - -- reg: Physical base address of the controller and length of memory mapped - region. - -- #gpio-cells: Should be 3. 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] - [flags and pull up/down] - - Values for gpio specifier: - - Pin number: depending on the controller a number from 0 up to 15. - - Mux function: Depending on the SoC and the gpio bank the gpio can be set - as input, output or a special function - - Flags and Pull Up/Down: the values to use differ for the individual SoCs - example S3C2416/S3C2450: - 0 - Pull Up/Down Disabled. - 1 - Pull Down Enabled. - 2 - Pull Up Enabled. - Bit 16 (0x00010000) - Input is active low. - Consult the user manual for the correct values of Mux and Pull Up/Down. - -- gpio-controller: Specifies that the node is a gpio controller. -- #address-cells: should be 1. -- #size-cells: should be 1. - -Example: - - gpa: gpio-controller@56000000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "samsung,s3c24xx-gpio"; - reg = <0x56000000 0x10>; - #gpio-cells = <3>; - gpio-controller; - }; diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt new file mode 100644 index 00000000000..cb3dc7bcd8e --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt @@ -0,0 +1,46 @@ +* Renesas R-Car GPIO Controller + +Required Properties: + + - compatible: should be one of the following. + - "renesas,gpio-r8a7778": for R8A7778 (R-Mobile M1) compatible GPIO controller. + - "renesas,gpio-r8a7779": for R8A7779 (R-Car H1) compatible GPIO controller. + - "renesas,gpio-r8a7790": for R8A7790 (R-Car H2) compatible GPIO controller. + - "renesas,gpio-rcar": for generic R-Car GPIO controller. + + - reg: Base address and length of each memory resource used by the GPIO + controller hardware module. + + - interrupt-parent: phandle of the parent interrupt controller. + - interrupts: Interrupt specifier for the controllers interrupt. + + - gpio-controller: Marks the device node as a gpio controller. + - #gpio-cells: Should be 2. The first cell is the GPIO number and the second + cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the + GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported. + - gpio-ranges: Range of pins managed by the GPIO controller. + +Please refer to gpio.txt in this directory for details of gpio-ranges property +and the common GPIO bindings used by client devices. + +Example: R8A7779 (R-Car H1) GPIO controller nodes + + gpio0: gpio@ffc40000 { + compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; + reg = <0xffc40000 0x2c>; + interrupt-parent = <&gic>; + interrupts = <0 141 0x4>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 0 32>; + }; + ... + gpio6: gpio@ffc46000 { + compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; + reg = <0xffc46000 0x2c>; + interrupt-parent = <&gic>; + interrupts = <0 147 0x4>; + #gpio-cells = <2>; + gpio-controller; + gpio-ranges = <&pfc 0 192 9>; + }; diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index 6a983c1d87c..df338cb5059 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt @@ -29,6 +29,13 @@ Optional properties: "bch4" 4-bit BCH ecc code "bch8" 8-bit BCH ecc code + - ti,nand-xfer-type: A string setting the data transfer type. One of: + + "prefetch-polled" Prefetch polled mode (default) + "polled" Polled mode, without prefetch + "prefetch-dma" Prefetch enabled sDMA mode + "prefetch-irq" Prefetch enabled irq mode + - elm_id: Specifies elm device node. This is required to support BCH error correction using ELM module. @@ -55,6 +62,7 @@ Example for an AM33xx board: reg = <0 0 0>; /* CS0, offset 0 */ nand-bus-width = <16>; ti,nand-ecc-opt = "bch8"; + ti,nand-xfer-type = "polled"; gpmc,sync-clk-ps = <0>; gpmc,cs-on-ns = <0>; diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt index e15cfc4bb39..72e9cd1e89b 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt @@ -7,6 +7,10 @@ on-chip controllers onto these pads. Required Properties: - compatible: should be one of the following. + - "samsung,s3c2412-pinctrl": for S3C2412-compatible pin-controller, + - "samsung,s3c2416-pinctrl": for S3C2416-compatible pin-controller, + - "samsung,s3c2440-pinctrl": for S3C2440-compatible pin-controller, + - "samsung,s3c2450-pinctrl": for S3C2450-compatible pin-controller, - "samsung,s3c64xx-pinctrl": for S3C64xx-compatible pin-controller, - "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller. - "samsung,exynos4x12-pinctrl": for Exynos4x12 compatible pin-controller. @@ -116,6 +120,10 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a - compatible: identifies the type of the external wakeup interrupt controller The possible values are: + - samsung,s3c2410-wakeup-eint: represents wakeup interrupt controller + found on Samsung S3C24xx SoCs except S3C2412 and S3C2413, + - samsung,s3c2412-wakeup-eint: represents wakeup interrupt controller + found on Samsung S3C2412 and S3C2413 SoCs, - samsung,s3c64xx-wakeup-eint: represents wakeup interrupt controller found on Samsung S3C64xx SoCs, - samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.txt b/Documentation/devicetree/bindings/sound/samsung-i2s.txt index 3070046da2e..025e66b85a4 100644 --- a/Documentation/devicetree/bindings/sound/samsung-i2s.txt +++ b/Documentation/devicetree/bindings/sound/samsung-i2s.txt @@ -8,6 +8,16 @@ Required SoC Specific Properties: - dmas: list of DMA controller phandle and DMA request line ordered pairs. - dma-names: identifier string for each DMA request line in the dmas property. These strings correspond 1:1 with the ordered pairs in dmas. +- clocks: Handle to iis clock and RCLK source clk. +- clock-names: + i2s0 uses some base clks from CMU and some are from audio subsystem internal + clock controller. The clock names for i2s0 should be "iis", "i2s_opclk0" and + "i2s_opclk1" as shown in the example below. + i2s1 and i2s2 uses clocks from CMU. The clock names for i2s1 and i2s2 should + be "iis" and "i2s_opclk0". + "iis" is the i2s bus clock and i2s_opclk0, i2s_opclk1 are sources of the root + clk. i2s0 has internal mux to select the source of root clk and i2s1 and i2s2 + doesn't have any such mux. Optional SoC Specific Properties: @@ -20,44 +30,26 @@ Optional SoC Specific Properties: then this flag is enabled. - samsung,idma-addr: Internal DMA register base address of the audio sub system(used in secondary sound source). - -Required Board Specific Properties: - -- gpios: The gpio specifier for data out,data in, LRCLK, CDCLK and SCLK - interface lines. The format of the gpio specifier depends on the gpio - controller. - The syntax of samsung gpio specifier is - <[phandle of the gpio controller node] - [pin number within the gpio controller] - [mux function] - [flags and pull up/down] - [drive strength]> +- pinctrl-0: Should specify pin control groups used for this controller. +- pinctrl-names: Should contain only one value - "default". Example: -- SoC Specific Portion: - -i2s@03830000 { +i2s0: i2s@03830000 { compatible = "samsung,i2s-v5"; reg = <0x03830000 0x100>; dmas = <&pdma0 10 &pdma0 9 &pdma0 8>; dma-names = "tx", "rx", "tx-sec"; + clocks = <&clock_audss EXYNOS_I2S_BUS>, + <&clock_audss EXYNOS_I2S_BUS>, + <&clock_audss EXYNOS_SCLK_I2S>; + clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; samsung,supports-6ch; samsung,supports-rstclr; samsung,supports-secdai; samsung,idma-addr = <0x03000000>; -}; - -- Board Specific Portion: - -i2s@03830000 { - gpios = <&gpz 0 2 0 0>, /* I2S_0_SCLK */ - <&gpz 1 2 0 0>, /* I2S_0_CDCLK */ - <&gpz 2 2 0 0>, /* I2S_0_LRCK */ - <&gpz 3 2 0 0>, /* I2S_0_SDI */ - <&gpz 4 2 0 0>, /* I2S_0_SDO[1] */ - <&gpz 5 2 0 0>, /* I2S_0_SDO[2] */ - <&gpz 6 2 0 0>; /* I2S_0_SDO[3] */ + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_bus>; }; diff --git a/Documentation/devicetree/bindings/usb/atmel-usb.txt b/Documentation/devicetree/bindings/usb/atmel-usb.txt index 60bd2150a3e..55f51af08bc 100644 --- a/Documentation/devicetree/bindings/usb/atmel-usb.txt +++ b/Documentation/devicetree/bindings/usb/atmel-usb.txt @@ -47,3 +47,85 @@ usb1: gadget@fffa4000 { interrupts = <10 4>; atmel,vbus-gpio = <&pioC 5 0>; }; + +Atmel High-Speed USB device controller + +Required properties: + - compatible: Should be "atmel,at91sam9rl-udc" + - reg: Address and length of the register set for the device + - interrupts: Should contain usba interrupt + - ep childnode: To specify the number of endpoints and their properties. + +Optional properties: + - atmel,vbus-gpio: If present, specifies a gpio that needs to be + activated for the bus to be powered. + +Required child node properties: + - name: Name of the endpoint. + - reg: Num of the endpoint. + - atmel,fifo-size: Size of the fifo. + - atmel,nb-banks: Number of banks. + - atmel,can-dma: Boolean to specify if the endpoint support DMA. + - atmel,can-isoc: Boolean to specify if the endpoint support ISOC. + +usb2: gadget@fff78000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "atmel,at91sam9rl-udc"; + reg = <0x00600000 0x80000 + 0xfff78000 0x400>; + interrupts = <27 4 0>; + atmel,vbus-gpio = <&pioB 19 0>; + + ep0 { + reg = <0>; + atmel,fifo-size = <64>; + atmel,nb-banks = <1>; + }; + + ep1 { + reg = <1>; + atmel,fifo-size = <1024>; + atmel,nb-banks = <2>; + atmel,can-dma; + atmel,can-isoc; + }; + + ep2 { + reg = <2>; + atmel,fifo-size = <1024>; + atmel,nb-banks = <2>; + atmel,can-dma; + atmel,can-isoc; + }; + + ep3 { + reg = <3>; + atmel,fifo-size = <1024>; + atmel,nb-banks = <3>; + atmel,can-dma; + }; + + ep4 { + reg = <4>; + atmel,fifo-size = <1024>; + atmel,nb-banks = <3>; + atmel,can-dma; + }; + + ep5 { + reg = <5>; + atmel,fifo-size = <1024>; + atmel,nb-banks = <3>; + atmel,can-dma; + atmel,can-isoc; + }; + + ep6 { + reg = <6>; + atmel,fifo-size = <1024>; + atmel,nb-banks = <3>; + atmel,can-dma; + atmel,can-isoc; + }; +}; diff --git a/Documentation/devicetree/bindings/usb/ux500-usb.txt b/Documentation/devicetree/bindings/usb/ux500-usb.txt new file mode 100644 index 00000000000..330d6ec1540 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/ux500-usb.txt @@ -0,0 +1,50 @@ +Ux500 MUSB + +Required properties: + - compatible : Should be "stericsson,db8500-musb" + - reg : Offset and length of registers + - interrupts : Interrupt; mode, number and trigger + - dr_mode : Dual-role; either host mode "host", peripheral mode "peripheral" + or both "otg" + +Optional properties: + - dmas : A list of dma channels; + dma-controller, event-line, fixed-channel, flags + - dma-names : An ordered list of channel names affiliated to the above + +Example: + +usb_per5@a03e0000 { + compatible = "stericsson,db8500-musb", "mentor,musb"; + reg = <0xa03e0000 0x10000>; + interrupts = <0 23 0x4>; + interrupt-names = "mc"; + + dr_mode = "otg"; + + dmas = <&dma 38 0 0x2>, /* Logical - DevToMem */ + <&dma 38 0 0x0>, /* Logical - MemToDev */ + <&dma 37 0 0x2>, /* Logical - DevToMem */ + <&dma 37 0 0x0>, /* Logical - MemToDev */ + <&dma 36 0 0x2>, /* Logical - DevToMem */ + <&dma 36 0 0x0>, /* Logical - MemToDev */ + <&dma 19 0 0x2>, /* Logical - DevToMem */ + <&dma 19 0 0x0>, /* Logical - MemToDev */ + <&dma 18 0 0x2>, /* Logical - DevToMem */ + <&dma 18 0 0x0>, /* Logical - MemToDev */ + <&dma 17 0 0x2>, /* Logical - DevToMem */ + <&dma 17 0 0x0>, /* Logical - MemToDev */ + <&dma 16 0 0x2>, /* Logical - DevToMem */ + <&dma 16 0 0x0>, /* Logical - MemToDev */ + <&dma 39 0 0x2>, /* Logical - DevToMem */ + <&dma 39 0 0x0>; /* Logical - MemToDev */ + + dma-names = "iep_1_9", "oep_1_9", + "iep_2_10", "oep_2_10", + "iep_3_11", "oep_3_11", + "iep_4_12", "oep_4_12", + "iep_5_13", "oep_5_13", + "iep_6_14", "oep_6_14", + "iep_7_15", "oep_7_15", + "iep_8", "oep_8"; +}; diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7a13c2cd7a8..49fdc432512 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2087,53 +2087,6 @@ menu "CPU Power Management" if ARCH_HAS_CPUFREQ source "drivers/cpufreq/Kconfig" - -config CPU_FREQ_S3C - bool - help - Internal configuration node for common cpufreq on Samsung SoC - -config CPU_FREQ_S3C24XX - bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)" - depends on ARCH_S3C24XX && CPU_FREQ - select CPU_FREQ_S3C - help - This enables the CPUfreq driver for the Samsung S3C24XX family - of CPUs. - - For details, take a look at <file:Documentation/cpu-freq>. - - If in doubt, say N. - -config CPU_FREQ_S3C24XX_PLL - bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)" - depends on CPU_FREQ_S3C24XX - help - Compile in support for changing the PLL frequency from the - S3C24XX series CPUfreq driver. The PLL takes time to settle - after a frequency change, so by default it is not enabled. - - This also means that the PLL tables for the selected CPU(s) will - be built which may increase the size of the kernel image. - -config CPU_FREQ_S3C24XX_DEBUG - bool "Debug CPUfreq Samsung driver core" - depends on CPU_FREQ_S3C24XX - help - Enable s3c_freq_dbg for the Samsung S3C CPUfreq core - -config CPU_FREQ_S3C24XX_IODEBUG - bool "Debug CPUfreq Samsung driver IO timing" - depends on CPU_FREQ_S3C24XX - help - Enable s3c_freq_iodbg for the Samsung S3C CPUfreq core - -config CPU_FREQ_S3C24XX_DEBUGFS - bool "Export debugfs for CPUFreq" - depends on CPU_FREQ_S3C24XX && DEBUG_FS - help - Export status information via debugfs. - endif source "drivers/cpuidle/Kconfig" diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index a082f0ba1dd..a1529455f08 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -360,6 +360,11 @@ interrupt-controller; #interrupt-cells = <2>; + ab8500_gpio: ab8500-gpio { + gpio-controller; + #gpio-cells = <2>; + }; + ab8500-rtc { compatible = "stericsson,ab8500-rtc"; interrupts = <17 IRQ_TYPE_LEVEL_HIGH diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index bed40ee2e4f..3f94fe8e370 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -19,7 +19,7 @@ * published by the Free Software Foundation. */ -/include/ "skeleton.dtsi" +#include "skeleton.dtsi" / { interrupt-parent = <&gic>; diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts index 08609b8bdaf..382d8c7e290 100644 --- a/arch/arm/boot/dts/exynos4210-origen.dts +++ b/arch/arm/boot/dts/exynos4210-origen.dts @@ -15,7 +15,7 @@ */ /dts-v1/; -/include/ "exynos4210.dtsi" +#include "exynos4210.dtsi" / { model = "Insignal Origen evaluation board based on Exynos4210"; diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts index 91332b72acf..9c01b718d29 100644 --- a/arch/arm/boot/dts/exynos4210-smdkv310.dts +++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts @@ -15,7 +15,7 @@ */ /dts-v1/; -/include/ "exynos4210.dtsi" +#include "exynos4210.dtsi" / { model = "Samsung smdkv310 evaluation board based on Exynos4210"; diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index 9a14484c7bb..94eebffe304 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -13,7 +13,7 @@ */ /dts-v1/; -/include/ "exynos4210.dtsi" +#include "exynos4210.dtsi" / { model = "Samsung Trats based on Exynos4210"; diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts index 345cdb51dcb..889cdada1ce 100644 --- a/arch/arm/boot/dts/exynos4210-universal_c210.dts +++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts @@ -13,7 +13,7 @@ */ /dts-v1/; -/include/ "exynos4210.dtsi" +#include "exynos4210.dtsi" / { model = "Samsung Universal C210 based on Exynos4210 rev0"; diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index d4f8067e89b..b7f358a93bc 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -19,8 +19,8 @@ * published by the Free Software Foundation. */ -/include/ "exynos4.dtsi" -/include/ "exynos4210-pinctrl.dtsi" +#include "exynos4.dtsi" +#include "exynos4210-pinctrl.dtsi" / { compatible = "samsung,exynos4210"; diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi index c0f60f49cea..6f34d7f6ba7 100644 --- a/arch/arm/boot/dts/exynos4212.dtsi +++ b/arch/arm/boot/dts/exynos4212.dtsi @@ -17,7 +17,7 @@ * published by the Free Software Foundation. */ -/include/ "exynos4x12.dtsi" +#include "exynos4x12.dtsi" / { compatible = "samsung,exynos4212"; diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts index 867d9452619..46c678ee119 100644 --- a/arch/arm/boot/dts/exynos4412-odroidx.dts +++ b/arch/arm/boot/dts/exynos4412-odroidx.dts @@ -12,7 +12,7 @@ */ /dts-v1/; -/include/ "exynos4412.dtsi" +#include "exynos4412.dtsi" / { model = "Hardkernel ODROID-X board based on Exynos4412"; diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts index ca73c42f77e..7993641cb32 100644 --- a/arch/arm/boot/dts/exynos4412-origen.dts +++ b/arch/arm/boot/dts/exynos4412-origen.dts @@ -13,7 +13,7 @@ */ /dts-v1/; -/include/ "exynos4412.dtsi" +#include "exynos4412.dtsi" / { model = "Insignal Origen evaluation board based on Exynos4412"; diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/exynos4412-smdk4412.dts index a8ba195c41a..ad316a1ee9e 100644 --- a/arch/arm/boot/dts/exynos4412-smdk4412.dts +++ b/arch/arm/boot/dts/exynos4412-smdk4412.dts @@ -13,7 +13,7 @@ */ /dts-v1/; -/include/ "exynos4412.dtsi" +#include "exynos4412.dtsi" / { model = "Samsung SMDK evaluation board based on Exynos4412"; diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi index 270b389e0a1..e743e677a9e 100644 --- a/arch/arm/boot/dts/exynos4412.dtsi +++ b/arch/arm/boot/dts/exynos4412.dtsi @@ -17,7 +17,7 @@ * published by the Free Software Foundation. */ -/include/ "exynos4x12.dtsi" +#include "exynos4x12.dtsi" / { compatible = "samsung,exynos4412"; diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi index 35cb2099d55..01da194ba32 100644 --- a/arch/arm/boot/dts/exynos4x12.dtsi +++ b/arch/arm/boot/dts/exynos4x12.dtsi @@ -17,8 +17,8 @@ * published by the Free Software Foundation. */ -/include/ "exynos4.dtsi" -/include/ "exynos4x12-pinctrl.dtsi" +#include "exynos4.dtsi" +#include "exynos4x12-pinctrl.dtsi" / { aliases { diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index c6db281a343..abc7272c7af 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -10,7 +10,7 @@ */ /dts-v1/; -/include/ "exynos5250.dtsi" +#include "exynos5250.dtsi" / { model = "Insignal Arndale evaluation board based on EXYNOS5250"; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 1e21200b6d8..35a66dee401 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -10,7 +10,7 @@ */ /dts-v1/; -/include/ "exynos5250.dtsi" +#include "exynos5250.dtsi" / { model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index 05244f150dd..e79331dba12 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -9,8 +9,8 @@ */ /dts-v1/; -/include/ "exynos5250.dtsi" -/include/ "cros5250-common.dtsi" +#include "exynos5250.dtsi" +#include "cros5250-common.dtsi" / { model = "Google Snow"; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 54a35e64c78..964158c1844 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -17,8 +17,10 @@ * published by the Free Software Foundation. */ -/include/ "skeleton.dtsi" -/include/ "exynos5250-pinctrl.dtsi" +#include "skeleton.dtsi" +#include "exynos5250-pinctrl.dtsi" + +#include <dt-bindings/clk/exynos-audss-clk.h> / { compatible = "samsung,exynos5250"; @@ -72,6 +74,12 @@ #clock-cells = <1>; }; + clock_audss: audss-clock-controller@3810000 { + compatible = "samsung,exynos5250-audss-clock"; + reg = <0x03810000 0x0C>; + #clock-cells = <1>; + }; + gic:interrupt-controller@10481000 { compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; @@ -451,6 +459,10 @@ &pdma0 9 &pdma0 8>; dma-names = "tx", "rx", "tx-sec"; + clocks = <&clock_audss EXYNOS_I2S_BUS>, + <&clock_audss EXYNOS_I2S_BUS>, + <&clock_audss EXYNOS_SCLK_I2S>; + clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; samsung,supports-6ch; samsung,supports-rstclr; samsung,supports-secdai; @@ -465,6 +477,8 @@ dmas = <&pdma1 12 &pdma1 11>; dma-names = "tx", "rx"; + clocks = <&clock 307>, <&clock 157>; + clock-names = "iis", "i2s_opclk0"; pinctrl-names = "default"; pinctrl-0 = <&i2s1_bus>; }; @@ -475,6 +489,8 @@ dmas = <&pdma0 12 &pdma0 11>; dma-names = "tx", "rx"; + clocks = <&clock 308>, <&clock 158>; + clock-names = "iis", "i2s_opclk0"; pinctrl-names = "default"; pinctrl-0 = <&i2s2_bus>; }; diff --git a/arch/arm/boot/dts/exynos5440-sd5v1.dts b/arch/arm/boot/dts/exynos5440-sd5v1.dts index f722a0263ac..5b22508050d 100644 --- a/arch/arm/boot/dts/exynos5440-sd5v1.dts +++ b/arch/arm/boot/dts/exynos5440-sd5v1.dts @@ -10,7 +10,7 @@ */ /dts-v1/; -/include/ "exynos5440.dtsi" +#include "exynos5440.dtsi" / { model = "SAMSUNG SD5v1 board based on EXYNOS5440"; diff --git a/arch/arm/boot/dts/exynos5440-ssdk5440.dts b/arch/arm/boot/dts/exynos5440-ssdk5440.dts index ba88cfd2486..ede772741f8 100644 --- a/arch/arm/boot/dts/exynos5440-ssdk5440.dts +++ b/arch/arm/boot/dts/exynos5440-ssdk5440.dts @@ -10,7 +10,7 @@ */ /dts-v1/; -/include/ "exynos5440.dtsi" +#include "exynos5440.dtsi" / { model = "SAMSUNG SSDK5440 board based on EXYNOS5440"; diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi index bfcb907b7e3..ff7f5d85584 100644 --- a/arch/arm/boot/dts/exynos5440.dtsi +++ b/arch/arm/boot/dts/exynos5440.dtsi @@ -9,7 +9,7 @@ * published by the Free Software Foundation. */ -/include/ "skeleton.dtsi" +#include "skeleton.dtsi" / { compatible = "samsung,exynos5440"; diff --git a/arch/arm/boot/dts/omap3430-sdp.dts b/arch/arm/boot/dts/omap3430-sdp.dts index c4a1c0a9772..e2249bcc3e6 100644 --- a/arch/arm/boot/dts/omap3430-sdp.dts +++ b/arch/arm/boot/dts/omap3430-sdp.dts @@ -106,7 +106,6 @@ nand-bus-width = <8>; ti,nand-ecc-opt = "sw"; - gpmc,device-nand; gpmc,cs-on-ns = <0>; gpmc,cs-rd-off-ns = <36>; gpmc,cs-wr-off-ns = <36>; diff --git a/arch/arm/boot/dts/s3c2416-smdk2416.dts b/arch/arm/boot/dts/s3c2416-smdk2416.dts index ad1dd09c10e..59594cf1599 100644 --- a/arch/arm/boot/dts/s3c2416-smdk2416.dts +++ b/arch/arm/boot/dts/s3c2416-smdk2416.dts @@ -9,7 +9,7 @@ */ /dts-v1/; -/include/ "s3c2416.dtsi" +#include "s3c2416.dtsi" / { model = "SMDK2416"; diff --git a/arch/arm/boot/dts/s3c2416.dtsi b/arch/arm/boot/dts/s3c2416.dtsi index 6809324934a..e6555bdd81b 100644 --- a/arch/arm/boot/dts/s3c2416.dtsi +++ b/arch/arm/boot/dts/s3c2416.dtsi @@ -8,8 +8,8 @@ * published by the Free Software Foundation. */ -/include/ "s3c24xx.dtsi" -/include/ "s3c2416-pinctrl.dtsi" +#include "s3c24xx.dtsi" +#include "s3c2416-pinctrl.dtsi" / { model = "Samsung S3C2416 SoC"; diff --git a/arch/arm/boot/dts/s3c24xx.dtsi b/arch/arm/boot/dts/s3c24xx.dtsi index cab46ff5fb4..2d1d7dc9418 100644 --- a/arch/arm/boot/dts/s3c24xx.dtsi +++ b/arch/arm/boot/dts/s3c24xx.dtsi @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ -/include/ "skeleton.dtsi" +#include "skeleton.dtsi" / { compatible = "samsung,s3c24xx"; diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts index fb9dce529da..49824be6684 100644 --- a/arch/arm/boot/dts/snowball.dts +++ b/arch/arm/boot/dts/snowball.dts @@ -22,12 +22,13 @@ en_3v3_reg: en_3v3 { compatible = "regulator-fixed"; - regulator-name = "en-3v3-fixed-supply"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpios = <&gpio0 26 0x4>; // 26 - startup-delay-us = <5000>; - enable-active-high; + regulator-name = "en-3v3-fixed-supply"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + /* AB8500 GPIOs start from 1 - offset 25 is GPIO26. */ + gpio = <&ab8500_gpio 25 0x4>; + startup-delay-us = <5000>; + enable-active-high; }; gpio_keys { diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig index 9940f7b4e43..d74edbad18f 100644 --- a/arch/arm/configs/omap1_defconfig +++ b/arch/arm/configs/omap1_defconfig @@ -26,7 +26,8 @@ CONFIG_ARCH_OMAP=y CONFIG_ARCH_OMAP1=y CONFIG_OMAP_RESET_CLOCKS=y # CONFIG_OMAP_MUX is not set -CONFIG_OMAP_MBOX_FWK=y +CONFIG_MAILBOX=y +CONFIG_OMAP1_MBOX=y CONFIG_OMAP_32K_TIMER=y CONFIG_OMAP_DM_TIMER=y CONFIG_ARCH_OMAP730=y diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 222d58c0ae7..3889b6cd211 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -19,10 +19,6 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o # Power Management obj-$(CONFIG_PM) += pm.o sleep.o -# DSP -obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o -mailbox_mach-objs := mailbox.o - i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o obj-y += $(i2c-omap-m) $(i2c-omap-y) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 8e8c605ebef..ea5a27ff994 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -212,9 +212,6 @@ obj-$(CONFIG_SOC_OMAP5) += omap_hwmod_54xx_data.o obj-$(CONFIG_OMAP3_EMU) += emu.o obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o -obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o -mailbox_mach-objs := mailbox.o - iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o obj-y += $(iommu-m) $(iommu-y) diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index c33adea0247..fc20a61f6b2 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -112,6 +112,9 @@ struct gpmc_timings nand_default_timings[1] = { .cs_rd_off = 36, .cs_wr_off = 36, + .we_on = 6, + .oe_on = 6, + .adv_on = 6, .adv_rd_off = 24, .adv_wr_off = 36, diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 403c211e35d..aef96e45cb2 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -21,6 +21,7 @@ #include <linux/pinctrl/machine.h> #include <linux/platform_data/omap4-keypad.h> #include <linux/wl12xx.h> +#include <linux/platform_data/mailbox-omap.h> #include <asm/mach-types.h> #include <asm/mach/map.h> @@ -283,25 +284,31 @@ int __init omap4_keyboard_init(struct omap4_keypad_platform_data return 0; } -#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE) +#if defined(CONFIG_OMAP2PLUS_MBOX) || defined(CONFIG_OMAP2PLUS_MBOX_MODULE) static inline void __init omap_init_mbox(void) { struct omap_hwmod *oh; struct platform_device *pdev; + struct omap_mbox_pdata *pdata; oh = omap_hwmod_lookup("mailbox"); if (!oh) { pr_err("%s: unable to find hwmod\n", __func__); return; } + if (!oh->dev_attr) { + pr_err("%s: hwmod doesn't have valid attrs\n", __func__); + return; + } - pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0); + pdata = (struct omap_mbox_pdata *)oh->dev_attr; + pdev = omap_device_build("omap-mailbox", -1, oh, pdata, sizeof(*pdata)); WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n", __func__, PTR_ERR(pdev)); } #else static inline void omap_init_mbox(void) { } -#endif /* CONFIG_OMAP_MBOX_FWK */ +#endif /* CONFIG_OMAP2PLUS_MBOX */ static inline void omap_init_sti(void) {} diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index d9c27195caf..662c7fd633c 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -43,44 +43,6 @@ static struct platform_device gpmc_nand_device = { .resource = gpmc_nand_resource, }; -static int omap2_nand_gpmc_retime( - struct omap_nand_platform_data *gpmc_nand_data, - struct gpmc_timings *gpmc_t) -{ - struct gpmc_timings t; - int err; - - memset(&t, 0, sizeof(t)); - t.sync_clk = gpmc_t->sync_clk; - t.cs_on = gpmc_t->cs_on; - t.adv_on = gpmc_t->adv_on; - - /* Read */ - t.adv_rd_off = gpmc_t->adv_rd_off; - t.oe_on = t.adv_on; - t.access = gpmc_t->access; - t.oe_off = gpmc_t->oe_off; - t.cs_rd_off = gpmc_t->cs_rd_off; - t.rd_cycle = gpmc_t->rd_cycle; - - /* Write */ - t.adv_wr_off = gpmc_t->adv_wr_off; - t.we_on = t.oe_on; - if (cpu_is_omap34xx()) { - t.wr_data_mux_bus = gpmc_t->wr_data_mux_bus; - t.wr_access = gpmc_t->wr_access; - } - t.we_off = gpmc_t->we_off; - t.cs_wr_off = gpmc_t->cs_wr_off; - t.wr_cycle = gpmc_t->wr_cycle; - - err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t); - if (err) - return err; - - return 0; -} - static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) { /* support only OMAP3 class */ @@ -131,7 +93,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); if (gpmc_t) { - err = omap2_nand_gpmc_retime(gpmc_nand_data, gpmc_t); + err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t); if (err < 0) { dev_err(dev, "Unable to set gpmc timings: %d\n", err); return err; @@ -140,8 +102,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, if (gpmc_nand_data->of_node) { gpmc_read_settings_dt(gpmc_nand_data->of_node, &s); } else { - s.device_nand = true; - /* Enable RD PIN Monitoring Reg */ if (gpmc_nand_data->dev_ready) { s.wait_on_read = true; @@ -149,6 +109,8 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, } } + s.device_nand = true; + if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) s.device_width = GPMC_DEVWIDTH_16BIT; else diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 6c4da1254f5..1c7969e965d 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -30,6 +30,7 @@ #include <linux/of_mtd.h> #include <linux/of_device.h> #include <linux/mtd/nand.h> +#include <linux/pm_runtime.h> #include <linux/platform_data/mtd-nand-omap2.h> @@ -155,6 +156,7 @@ static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); /* Define chip-selects as reserved by default until probe completes */ static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1); +static unsigned int gpmc_cs_num = GPMC_CS_NUM; static unsigned int gpmc_nr_waitpins; static struct device *gpmc_dev; static int gpmc_irq; @@ -521,8 +523,10 @@ static int gpmc_cs_remap(int cs, u32 base) int ret; u32 old_base, size; - if (cs > GPMC_CS_NUM) + if (cs > gpmc_cs_num) { + pr_err("%s: requested chip-select is disabled\n", __func__); return -ENODEV; + } gpmc_cs_get_memconf(cs, &old_base, &size); if (base == old_base) return 0; @@ -545,9 +549,10 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) struct resource *res = &gpmc_cs_mem[cs]; int r = -1; - if (cs > GPMC_CS_NUM) + if (cs > gpmc_cs_num) { + pr_err("%s: requested chip-select is disabled\n", __func__); return -ENODEV; - + } size = gpmc_mem_align(size); if (size > (1 << GPMC_SECTION_SHIFT)) return -ENOMEM; @@ -582,7 +587,7 @@ EXPORT_SYMBOL(gpmc_cs_request); void gpmc_cs_free(int cs) { spin_lock(&gpmc_mem_lock); - if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) { + if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) { printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); BUG(); spin_unlock(&gpmc_mem_lock); @@ -777,7 +782,7 @@ static void gpmc_mem_exit(void) { int cs; - for (cs = 0; cs < GPMC_CS_NUM; cs++) { + for (cs = 0; cs < gpmc_cs_num; cs++) { if (!gpmc_cs_mem_enabled(cs)) continue; gpmc_cs_delete_mem(cs); @@ -798,7 +803,7 @@ static void gpmc_mem_init(void) gpmc_mem_root.end = GPMC_MEM_END; /* Reserve all regions that has been set up by bootloader */ - for (cs = 0; cs < GPMC_CS_NUM; cs++) { + for (cs = 0; cs < gpmc_cs_num; cs++) { u32 base, size; if (!gpmc_cs_mem_enabled(cs)) @@ -1245,7 +1250,6 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p) p->sync_read = of_property_read_bool(np, "gpmc,sync-read"); p->sync_write = of_property_read_bool(np, "gpmc,sync-write"); - p->device_nand = of_property_read_bool(np, "gpmc,device-nand"); of_property_read_u32(np, "gpmc,device-width", &p->device_width); of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data); @@ -1345,6 +1349,13 @@ static const char * const nand_ecc_opts[] = { [OMAP_ECC_BCH8_CODE_HW] = "bch8", }; +static const char * const nand_xfer_types[] = { + [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", + [NAND_OMAP_POLLED] = "polled", + [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma", + [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq", +}; + static int gpmc_probe_nand_child(struct platform_device *pdev, struct device_node *child) { @@ -1374,6 +1385,13 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, break; } + if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) + for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) + if (!strcasecmp(s, nand_xfer_types[val])) { + gpmc_nand_data->xfer_type = val; + break; + } + val = of_get_nand_bus_width(child); if (val == 16) gpmc_nand_data->devsize = NAND_BUSWIDTH_16; @@ -1513,6 +1531,20 @@ static int gpmc_probe_dt(struct platform_device *pdev) if (!of_id) return 0; + ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-cs", + &gpmc_cs_num); + if (ret < 0) { + pr_err("%s: number of chip-selects not defined\n", __func__); + return ret; + } else if (gpmc_cs_num < 1) { + pr_err("%s: all chip-selects are disabled\n", __func__); + return -EINVAL; + } else if (gpmc_cs_num > GPMC_CS_NUM) { + pr_err("%s: number of supported chip-selects cannot be > %d\n", + __func__, GPMC_CS_NUM); + return -EINVAL; + } + ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins", &gpmc_nr_waitpins); if (ret < 0) { @@ -1577,7 +1609,8 @@ static int gpmc_probe(struct platform_device *pdev) return PTR_ERR(gpmc_l3_clk); } - clk_prepare_enable(gpmc_l3_clk); + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); gpmc_dev = &pdev->dev; @@ -1610,12 +1643,14 @@ static int gpmc_probe(struct platform_device *pdev) /* Now the GPMC is initialised, unreserve the chip-selects */ gpmc_cs_map = 0; - if (!pdev->dev.of_node) + if (!pdev->dev.of_node) { + gpmc_cs_num = GPMC_CS_NUM; gpmc_nr_waitpins = GPMC_NR_WAITPINS; + } rc = gpmc_probe_dt(pdev); if (rc < 0) { - clk_disable_unprepare(gpmc_l3_clk); + pm_runtime_put_sync(&pdev->dev); clk_put(gpmc_l3_clk); dev_err(gpmc_dev, "failed to probe DT parameters\n"); return rc; @@ -1628,10 +1663,30 @@ static int gpmc_remove(struct platform_device *pdev) { gpmc_free_irq(); gpmc_mem_exit(); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); gpmc_dev = NULL; return 0; } +#ifdef CONFIG_PM_SLEEP +static int gpmc_suspend(struct device *dev) +{ + omap3_gpmc_save_context(); + pm_runtime_put_sync(dev); + return 0; +} + +static int gpmc_resume(struct device *dev) +{ + pm_runtime_get_sync(dev); + omap3_gpmc_restore_context(); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(gpmc_pm_ops, gpmc_suspend, gpmc_resume); + static struct platform_driver gpmc_driver = { .probe = gpmc_probe, .remove = gpmc_remove, @@ -1639,6 +1694,7 @@ static struct platform_driver gpmc_driver = { .name = DEVICE_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(gpmc_dt_ids), + .pm = &gpmc_pm_ops, }, }; @@ -1701,7 +1757,6 @@ static irqreturn_t gpmc_handle_irq(int irq, void *dev) return IRQ_HANDLED; } -#ifdef CONFIG_ARCH_OMAP3 static struct omap3_gpmc_regs gpmc_context; void omap3_gpmc_save_context(void) @@ -1715,7 +1770,7 @@ void omap3_gpmc_save_context(void) gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1); gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2); gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL); - for (i = 0; i < GPMC_CS_NUM; i++) { + for (i = 0; i < gpmc_cs_num; i++) { gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i); if (gpmc_context.cs_context[i].is_valid) { gpmc_context.cs_context[i].config1 = @@ -1747,7 +1802,7 @@ void omap3_gpmc_restore_context(void) gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1); gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2); gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control); - for (i = 0; i < GPMC_CS_NUM; i++) { + for (i = 0; i < gpmc_cs_num; i++) { if (gpmc_context.cs_context[i].is_valid) { gpmc_cs_write_reg(i, GPMC_CS_CONFIG1, gpmc_context.cs_context[i].config1); @@ -1766,4 +1821,3 @@ void omap3_gpmc_restore_context(void) } } } -#endif /* CONFIG_ARCH_OMAP3 */ diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index 5137cc84b50..d8b9d60f854 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -16,6 +16,7 @@ #include <linux/i2c-omap.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/omap-dma.h> +#include <linux/platform_data/mailbox-omap.h> #include <plat/dmtimer.h> #include "omap_hwmod.h" @@ -166,6 +167,18 @@ static struct omap_hwmod omap2420_dma_system_hwmod = { }; /* mailbox */ +static struct omap_mbox_dev_info omap2420_mailbox_info[] = { + { .name = "dsp", .tx_id = 0, .rx_id = 1, .irq_id = 0, .usr_id = 0 }, + { .name = "iva", .tx_id = 2, .rx_id = 3, .irq_id = 1, .usr_id = 3 }, +}; + +static struct omap_mbox_pdata omap2420_mailbox_attrs = { + .num_users = 4, + .num_fifos = 6, + .info_cnt = ARRAY_SIZE(omap2420_mailbox_info), + .info = omap2420_mailbox_info, +}; + static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = { { .name = "dsp", .irq = 26 + OMAP_INTC_START, }, { .name = "iva", .irq = 34 + OMAP_INTC_START, }, @@ -186,6 +199,7 @@ static struct omap_hwmod omap2420_mailbox_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT, }, }, + .dev_attr = &omap2420_mailbox_attrs, }; /* diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 4ce999ee3ee..5b9083461dc 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -17,6 +17,7 @@ #include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/omap-dma.h> +#include <linux/platform_data/mailbox-omap.h> #include <plat/dmtimer.h> #include "omap_hwmod.h" @@ -170,6 +171,17 @@ static struct omap_hwmod omap2430_dma_system_hwmod = { }; /* mailbox */ +static struct omap_mbox_dev_info omap2430_mailbox_info[] = { + { .name = "dsp", .tx_id = 0, .rx_id = 1 }, +}; + +static struct omap_mbox_pdata omap2430_mailbox_attrs = { + .num_users = 4, + .num_fifos = 6, + .info_cnt = ARRAY_SIZE(omap2430_mailbox_info), + .info = omap2430_mailbox_info, +}; + static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = { { .irq = 26 + OMAP_INTC_START, }, { .irq = -1 }, @@ -189,6 +201,7 @@ static struct omap_hwmod omap2430_mailbox_hwmod = { .idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT, }, }, + .dev_attr = &omap2430_mailbox_attrs, }; /* mcspi3 */ diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index fa991541144..f7a3df2fb57 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -25,6 +25,7 @@ #include <linux/platform_data/asoc-ti-mcbsp.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/iommu-omap.h> +#include <linux/platform_data/mailbox-omap.h> #include <plat/dmtimer.h> #include "am35xx.h" @@ -1504,6 +1505,17 @@ static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = { .sysc = &omap3xxx_mailbox_sysc, }; +static struct omap_mbox_dev_info omap3xxx_mailbox_info[] = { + { .name = "dsp", .tx_id = 0, .rx_id = 1 }, +}; + +static struct omap_mbox_pdata omap3xxx_mailbox_attrs = { + .num_users = 2, + .num_fifos = 2, + .info_cnt = ARRAY_SIZE(omap3xxx_mailbox_info), + .info = omap3xxx_mailbox_info, +}; + static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = { { .irq = 26 + OMAP_INTC_START, }, { .irq = -1 }, @@ -1523,6 +1535,7 @@ static struct omap_hwmod omap3xxx_mailbox_hwmod = { .idlest_idle_bit = OMAP3430_ST_MAILBOXES_SHIFT, }, }, + .dev_attr = &omap3xxx_mailbox_attrs, }; /* diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 0adb2b85f83..6d9252e081c 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -28,7 +28,7 @@ config CPU_S3C2410 select CPU_ARM920T select CPU_LLSERIAL_S3C2410 select S3C2410_CLOCK - select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX + select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ select S3C2410_PM if PM select SAMSUNG_HRT select SAMSUNG_WDT_RESET @@ -206,27 +206,38 @@ config S3C24XX_GPIO_EXTRA128 Add an extra 128 gpio numbers to the available GPIO pool. This is available for boards that need extra gpios for external devices. +config S3C24XX_PLL + bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)" + depends on ARM_S3C24XX + help + Compile in support for changing the PLL frequency from the + S3C24XX series CPUfreq driver. The PLL takes time to settle + after a frequency change, so by default it is not enabled. + + This also means that the PLL tables for the selected CPU(s) will + be built which may increase the size of the kernel image. + # cpu frequency items common between s3c2410 and s3c2440/s3c2442 config S3C2410_IOTIMING bool - depends on CPU_FREQ_S3C24XX + depends on ARM_S3C24XX_CPUFREQ help Internal node to select io timing code that is common to the s3c2410 and s3c2440/s3c2442 cpu frequency support. config S3C2410_CPUFREQ_UTILS - bool - depends on CPU_FREQ_S3C24XX - help - Internal node to select timing code that is common to the s3c2410 - and s3c2440/s3c244 cpu frequency support. + bool + depends on ARM_S3C24XX_CPUFREQ + help + Internal node to select timing code that is common to the s3c2410 + and s3c2440/s3c244 cpu frequency support. # cpu frequency support common to s3c2412, s3c2413 and s3c2442 config S3C2412_IOTIMING bool - depends on CPU_FREQ_S3C24XX && (CPU_S3C2412 || CPU_S3C2443) + depends on ARM_S3C24XX_CPUFREQ && (CPU_S3C2412 || CPU_S3C2443) help Intel node to select io timing code that is common to the s3c2412 and the s3c2443. @@ -235,16 +246,9 @@ config S3C2412_IOTIMING if CPU_S3C2410 -config S3C2410_CPUFREQ - bool - depends on CPU_FREQ_S3C24XX - select S3C2410_CPUFREQ_UTILS - help - CPU Frequency scaling support for S3C2410 - config S3C2410_PLL bool - depends on S3C2410_CPUFREQ && CPU_FREQ_S3C24XX_PLL + depends on ARM_S3C2410_CPUFREQ && S3C24XX_PLL default y help Select the PLL table for the S3C2410 @@ -280,7 +284,7 @@ config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" select ISA select MACH_BAST_IDE - select S3C2410_IOTIMING if S3C2410_CPUFREQ + select S3C2410_IOTIMING if ARM_S3C2410_CPUFREQ select S3C24XX_DCLK select S3C24XX_SIMTEC_NOR select S3C24XX_SIMTEC_PM if PM @@ -387,14 +391,6 @@ config CPU_S3C2412_ONLY !CPU_S3C2442 && !CPU_S3C2443 default y -config S3C2412_CPUFREQ - bool - depends on CPU_FREQ_S3C24XX - default y - select S3C2412_IOTIMING - help - CPU Frequency scaling support for S3C2412 and S3C2413 SoC CPUs. - config S3C2412_DMA bool help @@ -508,14 +504,6 @@ endif # CPU_S3C2416 if CPU_S3C2440 -config S3C2440_CPUFREQ - bool "S3C2440/S3C2442 CPU Frequency scaling support" - depends on CPU_FREQ_S3C24XX && (CPU_S3C2440 || CPU_S3C2442) - default y - select S3C2410_CPUFREQ_UTILS - help - CPU Frequency scaling support for S3C2440 and S3C2442 SoC CPUs. - config S3C2440_DMA bool help @@ -535,15 +523,15 @@ config S3C2440_XTAL_16934400 config S3C2440_PLL_12000000 bool - depends on S3C2440_CPUFREQ && S3C2440_XTAL_12000000 - default y if CPU_FREQ_S3C24XX_PLL + depends on ARM_S3C2440_CPUFREQ && S3C2440_XTAL_12000000 + default y if S3C24XX_PLL help PLL tables for S3C2440 or S3C2442 CPUs with 12MHz crystals. config S3C2440_PLL_16934400 bool - depends on S3C2440_CPUFREQ && S3C2440_XTAL_16934400 - default y if CPU_FREQ_S3C24XX_PLL + depends on ARM_S3C2440_CPUFREQ && S3C2440_XTAL_16934400 + default y if S3C24XX_PLL help PLL tables for S3C2440 or S3C2442 CPUs with 16.934MHz crystals. @@ -597,7 +585,7 @@ config MACH_NEXCODER_2440 config MACH_OSIRIS bool "Simtec IM2440D20 (OSIRIS) module" - select S3C2410_IOTIMING if S3C2440_CPUFREQ + select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_12000000 select S3C24XX_DCLK select S3C24XX_GPIO_EXTRA128 @@ -669,7 +657,7 @@ config MACH_RX1950 bool "HP iPAQ rx1950" select I2C select PM_H1940 if PM - select S3C2410_IOTIMING if S3C2440_CPUFREQ + select S3C2410_IOTIMING if ARM_S3C2440_CPUFREQ select S3C2440_XTAL_16934400 select S3C24XX_DCLK select S3C24XX_PWM diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 6de730bada4..7f54e5b954c 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -17,13 +17,11 @@ obj- := obj-y += common.o obj-$(CONFIG_CPU_S3C2410) += s3c2410.o -obj-$(CONFIG_S3C2410_CPUFREQ) += cpufreq-s3c2410.o obj-$(CONFIG_S3C2410_DMA) += dma-s3c2410.o obj-$(CONFIG_S3C2410_PLL) += pll-s3c2410.o obj-$(CONFIG_S3C2410_PM) += pm-s3c2410.o sleep-s3c2410.o obj-$(CONFIG_CPU_S3C2412) += s3c2412.o clock-s3c2412.o -obj-$(CONFIG_S3C2412_CPUFREQ) += cpufreq-s3c2412.o obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o @@ -34,7 +32,6 @@ obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o obj-$(CONFIG_CPU_S3C2440) += s3c2440.o clock-s3c2440.o obj-$(CONFIG_CPU_S3C2442) += s3c2442.o obj-$(CONFIG_CPU_S3C244X) += s3c244x.o clock-s3c244x.o -obj-$(CONFIG_S3C2440_CPUFREQ) += cpufreq-s3c2440.o obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o @@ -59,9 +56,6 @@ obj-$(CONFIG_S3C2412_IOTIMING) += iotiming-s3c2412.o obj-$(CONFIG_S3C2443_COMMON) += common-s3c2443.o obj-$(CONFIG_S3C2443_DMA) += dma-s3c2443.o -obj-$(CONFIG_CPU_FREQ_S3C24XX) += cpufreq.o -obj-$(CONFIG_CPU_FREQ_S3C24XX_DEBUGFS) += cpufreq-debugfs.o - # # machine support # following is ordered alphabetically by option text. diff --git a/arch/arm/mach-s3c24xx/s3c2412.h b/arch/arm/mach-s3c24xx/include/mach/s3c2412.h index 548ced42cbb..548ced42cbb 100644 --- a/arch/arm/mach-s3c24xx/s3c2412.h +++ b/arch/arm/mach-s3c24xx/include/mach/s3c2412.h diff --git a/arch/arm/mach-s3c24xx/iotiming-s3c2412.c b/arch/arm/mach-s3c24xx/iotiming-s3c2412.c index 663436d9db0..bd064c05c47 100644 --- a/arch/arm/mach-s3c24xx/iotiming-s3c2412.c +++ b/arch/arm/mach-s3c24xx/iotiming-s3c2412.c @@ -31,7 +31,7 @@ #include <plat/cpu-freq-core.h> #include <plat/clock.h> -#include "s3c2412.h" +#include <mach/s3c2412.h> #define print_ns(x) ((x) / 10), ((x) % 10) diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c index aba9e569295..bfe443daf4b 100644 --- a/arch/arm/mach-ux500/board-mop500-audio.c +++ b/arch/arm/mach-ux500/board-mop500-audio.c @@ -21,28 +21,14 @@ static struct stedma40_chan_cfg msp0_dma_rx = { .high_priority = true, - .dir = STEDMA40_PERIPH_TO_MEM, - - .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV31_MSP0_SLIM0_CH0, }; static struct stedma40_chan_cfg msp0_dma_tx = { .high_priority = true, - .dir = STEDMA40_MEM_TO_PERIPH, - - .src_dev_type = STEDMA40_DEV_DST_MEMORY, - .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV31_MSP0_SLIM0_CH0, }; struct msp_i2s_platform_data msp0_platform_data = { @@ -53,28 +39,14 @@ struct msp_i2s_platform_data msp0_platform_data = { static struct stedma40_chan_cfg msp1_dma_rx = { .high_priority = true, - .dir = STEDMA40_PERIPH_TO_MEM, - - .src_dev_type = DB8500_DMA_DEV30_MSP3_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV30_MSP3, }; static struct stedma40_chan_cfg msp1_dma_tx = { .high_priority = true, - .dir = STEDMA40_MEM_TO_PERIPH, - - .src_dev_type = STEDMA40_DEV_DST_MEMORY, - .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - - /* data_width is set during configuration */ + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV30_MSP1, }; struct msp_i2s_platform_data msp1_platform_data = { @@ -85,32 +57,16 @@ struct msp_i2s_platform_data msp1_platform_data = { static struct stedma40_chan_cfg msp2_dma_rx = { .high_priority = true, - .dir = STEDMA40_PERIPH_TO_MEM, - - .src_dev_type = DB8500_DMA_DEV14_MSP2_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - - /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */ - .src_info.psize = STEDMA40_PSIZE_LOG_1, - .dst_info.psize = STEDMA40_PSIZE_LOG_1, - - /* data_width is set during configuration */ + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV14_MSP2, }; static struct stedma40_chan_cfg msp2_dma_tx = { .high_priority = true, - .dir = STEDMA40_MEM_TO_PERIPH, - - .src_dev_type = STEDMA40_DEV_DST_MEMORY, - .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX, - - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, - + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV14_MSP2, .use_fixed_channel = true, .phy_channel = 1, - - /* data_width is set during configuration */ }; static struct platform_device *db8500_add_msp_i2s(struct device *parent, diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 43be3e0d4e3..b3e61a38e5c 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -34,20 +34,14 @@ #ifdef CONFIG_STE_DMA40 struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV29_SD_MM0, }; static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV29_SD_MM0, }; #endif @@ -89,20 +83,14 @@ void mop500_sdi_tc35892_init(struct device *parent) #ifdef CONFIG_STE_DMA40 static struct stedma40_chan_cfg sdi1_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV32_SD_MM1_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV32_SD_MM1, }; static struct stedma40_chan_cfg sdi1_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV32_SD_MM1_TX, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV32_SD_MM1, }; #endif @@ -127,20 +115,14 @@ struct mmci_platform_data mop500_sdi1_data = { #ifdef CONFIG_STE_DMA40 struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV28_SD_MM2_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV28_SD_MM2, }; static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV28_SD_MM2, }; #endif @@ -169,20 +151,14 @@ struct mmci_platform_data mop500_sdi2_data = { #ifdef CONFIG_STE_DMA40 struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV42_SD_MM4_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV42_SD_MM4, }; static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV42_SD_MM4, }; #endif diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 78389de94dd..df5d27a532e 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -413,47 +413,23 @@ static void mop500_prox_deactivate(struct device *dev) regulator_put(prox_regulator); } -void mop500_snowball_ethernet_clock_enable(void) -{ - struct clk *clk; - - clk = clk_get_sys("fsmc", NULL); - if (!IS_ERR(clk)) - clk_prepare_enable(clk); -} - static struct cryp_platform_data u8500_cryp1_platform_data = { .mem_to_engine = { - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV48_CAC1_TX, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV48_CAC1, .mode = STEDMA40_MODE_LOGICAL, - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, }, .engine_to_mem = { - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV48_CAC1_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV48_CAC1, .mode = STEDMA40_MODE_LOGICAL, - .src_info.psize = STEDMA40_PSIZE_LOG_4, - .dst_info.psize = STEDMA40_PSIZE_LOG_4, } }; static struct stedma40_chan_cfg u8500_hash_dma_cfg_tx = { - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV50_HAC1_TX, - .src_info.data_width = STEDMA40_WORD_WIDTH, - .dst_info.data_width = STEDMA40_WORD_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV50_HAC1_TX, .mode = STEDMA40_MODE_LOGICAL, - .src_info.psize = STEDMA40_PSIZE_LOG_16, - .dst_info.psize = STEDMA40_PSIZE_LOG_16, }; static struct hash_platform_data u8500_hash1_platform_data = { @@ -470,20 +446,14 @@ static struct platform_device *mop500_platform_devs[] __initdata = { #ifdef CONFIG_STE_DMA40 static struct stedma40_chan_cfg ssp0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV8_SSP0_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV8_SSP0, }; static struct stedma40_chan_cfg ssp0_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV8_SSP0_TX, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV8_SSP0, }; #endif @@ -511,56 +481,38 @@ static void __init mop500_spi_init(struct device *parent) #ifdef CONFIG_STE_DMA40 static struct stedma40_chan_cfg uart0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV13_UART0_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV13_UART0, }; static struct stedma40_chan_cfg uart0_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV13_UART0_TX, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV13_UART0, }; static struct stedma40_chan_cfg uart1_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV12_UART1_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV12_UART1, }; static struct stedma40_chan_cfg uart1_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV12_UART1_TX, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV12_UART1, }; static struct stedma40_chan_cfg uart2_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_PERIPH_TO_MEM, - .src_dev_type = DB8500_DMA_DEV11_UART2_RX, - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_DEV_TO_MEM, + .dev_type = DB8500_DMA_DEV11_UART2, }; static struct stedma40_chan_cfg uart2_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, - .dir = STEDMA40_MEM_TO_PERIPH, - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, - .dst_dev_type = DB8500_DMA_DEV11_UART2_TX, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dir = DMA_MEM_TO_DEV, + .dev_type = DB8500_DMA_DEV11_UART2, }; #endif @@ -674,7 +626,7 @@ static void __init snowball_init_machine(void) mop500_audio_init(parent); mop500_uart_init(parent); - mop500_snowball_ethernet_clock_enable(); + u8500_cryp1_hash1_init(parent); /* This board has full regulator constraints */ regulator_has_full_constraints(); diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 49514b82503..d6fab166cbf 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -93,6 +93,7 @@ extern struct amba_pl011_data uart0_plat; extern struct amba_pl011_data uart1_plat; extern struct amba_pl011_data uart2_plat; extern struct pl022_ssp_controller ssp0_plat; +extern struct stedma40_platform_data dma40_plat_data; extern void mop500_sdi_init(struct device *parent); extern void snowball_sdi_init(struct device *parent); @@ -104,7 +105,6 @@ void __init mop500_pinmaps_init(void); void __init snowball_pinmaps_init(void); void __init hrefv60_pinmaps_init(void); void mop500_audio_init(struct device *parent); -void mop500_snowball_ethernet_clock_enable(void); int __init mop500_uib_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 7669a49fb6f..12eee816752 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -162,26 +162,15 @@ static void __init db8500_add_gpios(struct device *parent) dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE); } -static int usb_db8500_rx_dma_cfg[] = { - DB8500_DMA_DEV38_USB_OTG_IEP_1_9, - DB8500_DMA_DEV37_USB_OTG_IEP_2_10, - DB8500_DMA_DEV36_USB_OTG_IEP_3_11, - DB8500_DMA_DEV19_USB_OTG_IEP_4_12, - DB8500_DMA_DEV18_USB_OTG_IEP_5_13, - DB8500_DMA_DEV17_USB_OTG_IEP_6_14, - DB8500_DMA_DEV16_USB_OTG_IEP_7_15, - DB8500_DMA_DEV39_USB_OTG_IEP_8 -}; - -static int usb_db8500_tx_dma_cfg[] = { - DB8500_DMA_DEV38_USB_OTG_OEP_1_9, - DB8500_DMA_DEV37_USB_OTG_OEP_2_10, - DB8500_DMA_DEV36_USB_OTG_OEP_3_11, - DB8500_DMA_DEV19_USB_OTG_OEP_4_12, - DB8500_DMA_DEV18_USB_OTG_OEP_5_13, - DB8500_DMA_DEV17_USB_OTG_OEP_6_14, - DB8500_DMA_DEV16_USB_OTG_OEP_7_15, - DB8500_DMA_DEV39_USB_OTG_OEP_8 +static int usb_db8500_dma_cfg[] = { + DB8500_DMA_DEV38_USB_OTG_IEP_AND_OEP_1_9, + DB8500_DMA_DEV37_USB_OTG_IEP_AND_OEP_2_10, + DB8500_DMA_DEV36_USB_OTG_IEP_AND_OEP_3_11, + DB8500_DMA_DEV19_USB_OTG_IEP_AND_OEP_4_12, + DB8500_DMA_DEV18_USB_OTG_IEP_AND_OEP_5_13, + DB8500_DMA_DEV17_USB_OTG_IEP_AND_OEP_6_14, + DB8500_DMA_DEV16_USB_OTG_IEP_AND_OEP_7_15, + DB8500_DMA_DEV39_USB_OTG_IEP_AND_OEP_8 }; static const char *db8500_read_soc_id(void) @@ -215,7 +204,7 @@ struct device * __init u8500_init_devices(void) db8500_add_rtc(parent); db8500_add_gpios(parent); - db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); + db8500_add_usb(parent, usb_db8500_dma_cfg, usb_db8500_dma_cfg); for (i = 0; i < ARRAY_SIZE(platform_devs); i++) platform_devs[i]->dev.parent = parent; @@ -226,34 +215,13 @@ struct device * __init u8500_init_devices(void) } #ifdef CONFIG_MACH_UX500_DT - -/* TODO: Once all pieces are DT:ed, remove completely. */ -static struct device * __init u8500_of_init_devices(void) -{ - struct device *parent = db8500_soc_device_init(); - - db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); - - u8500_dma40_device.dev.parent = parent; - - /* - * Devices to be DT:ed: - * u8500_dma40_device = todo - * db8500_pmu_device = done - * db8500_prcmu_device = done - */ - platform_device_register(&u8500_dma40_device); - - return parent; -} - static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { /* Requires call-back bindings. */ OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata), /* Requires DMA bindings. */ - OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat), - OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat), - OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat), + OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", NULL), + OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", NULL), + OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", NULL), OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat), OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0", &mop500_sdi0_data), OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1", &mop500_sdi1_data), @@ -294,6 +262,8 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { "ux500-msp-i2s.2", &msp2_platform_data), OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000, "ux500-msp-i2s.3", &msp3_platform_data), + /* Requires clock name bindings and channel address lookup table. */ + OF_DEV_AUXDATA("stericsson,db8500-dma40", 0x801C0000, "dma40.0", NULL), {}, }; @@ -317,22 +287,18 @@ static const struct of_device_id u8500_local_bus_nodes[] = { static void __init u8500_init_machine(void) { - struct device *parent = NULL; + struct device *parent = db8500_soc_device_init(); /* Pinmaps must be in place before devices register */ if (of_machine_is_compatible("st-ericsson,mop500")) mop500_pinmaps_init(); else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { snowball_pinmaps_init(); - mop500_snowball_ethernet_clock_enable(); } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) hrefv60_pinmaps_init(); else if (of_machine_is_compatible("st-ericsson,ccu9540")) {} /* TODO: Add pinmaps for ccu9540 board. */ - /* TODO: Export SoC, USB, cpu-freq and DMA40 */ - parent = u8500_of_init_devices(); - /* automatically probe child nodes of dbx5x0 devices */ if (of_machine_is_compatible("st-ericsson,u8540")) of_platform_populate(NULL, u8500_local_bus_nodes, diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index ddbdcda8306..516a6f57d15 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -42,128 +42,7 @@ static struct resource dma40_resources[] = { } }; -/* Default configuration for physcial memcpy */ -struct stedma40_chan_cfg dma40_memcpy_conf_phy = { - .mode = STEDMA40_MODE_PHYSICAL, - .dir = STEDMA40_MEM_TO_MEM, - - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .src_info.psize = STEDMA40_PSIZE_PHY_1, - .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, - - .dst_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.psize = STEDMA40_PSIZE_PHY_1, - .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, -}; -/* Default configuration for logical memcpy */ -struct stedma40_chan_cfg dma40_memcpy_conf_log = { - .dir = STEDMA40_MEM_TO_MEM, - - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .src_info.psize = STEDMA40_PSIZE_LOG_1, - .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, - - .dst_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.psize = STEDMA40_PSIZE_LOG_1, - .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, -}; - -/* - * Mapping between destination event lines and physical device address. - * The event line is tied to a device and therefore the address is constant. - * When the address comes from a primecell it will be configured in runtime - * and we set the address to -1 as a placeholder. - */ -static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = { - /* MUSB - these will be runtime-reconfigured */ - [DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1, - [DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1, - [DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1, - [DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1, - [DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1, - [DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1, - [DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1, - [DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1, - /* PrimeCells - run-time configured */ - [DB8500_DMA_DEV0_SPI0_TX] = -1, - [DB8500_DMA_DEV1_SD_MMC0_TX] = -1, - [DB8500_DMA_DEV2_SD_MMC1_TX] = -1, - [DB8500_DMA_DEV3_SD_MMC2_TX] = -1, - [DB8500_DMA_DEV8_SSP0_TX] = -1, - [DB8500_DMA_DEV9_SSP1_TX] = -1, - [DB8500_DMA_DEV11_UART2_TX] = -1, - [DB8500_DMA_DEV12_UART1_TX] = -1, - [DB8500_DMA_DEV13_UART0_TX] = -1, - [DB8500_DMA_DEV28_SD_MM2_TX] = -1, - [DB8500_DMA_DEV29_SD_MM0_TX] = -1, - [DB8500_DMA_DEV32_SD_MM1_TX] = -1, - [DB8500_DMA_DEV33_SPI2_TX] = -1, - [DB8500_DMA_DEV35_SPI1_TX] = -1, - [DB8500_DMA_DEV40_SPI3_TX] = -1, - [DB8500_DMA_DEV41_SD_MM3_TX] = -1, - [DB8500_DMA_DEV42_SD_MM4_TX] = -1, - [DB8500_DMA_DEV43_SD_MM5_TX] = -1, - [DB8500_DMA_DEV14_MSP2_TX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV30_MSP1_TX] = U8500_MSP1_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV48_CAC1_TX] = U8500_CRYP1_BASE + CRYP1_TX_REG_OFFSET, - [DB8500_DMA_DEV50_HAC1_TX] = U8500_HASH1_BASE + HASH1_TX_REG_OFFSET, -}; - -/* Mapping between source event lines and physical device address */ -static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = { - /* MUSB - these will be runtime-reconfigured */ - [DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1, - [DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1, - [DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1, - [DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1, - [DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1, - [DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1, - [DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1, - [DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1, - /* PrimeCells */ - [DB8500_DMA_DEV0_SPI0_RX] = -1, - [DB8500_DMA_DEV1_SD_MMC0_RX] = -1, - [DB8500_DMA_DEV2_SD_MMC1_RX] = -1, - [DB8500_DMA_DEV3_SD_MMC2_RX] = -1, - [DB8500_DMA_DEV8_SSP0_RX] = -1, - [DB8500_DMA_DEV9_SSP1_RX] = -1, - [DB8500_DMA_DEV11_UART2_RX] = -1, - [DB8500_DMA_DEV12_UART1_RX] = -1, - [DB8500_DMA_DEV13_UART0_RX] = -1, - [DB8500_DMA_DEV28_SD_MM2_RX] = -1, - [DB8500_DMA_DEV29_SD_MM0_RX] = -1, - [DB8500_DMA_DEV32_SD_MM1_RX] = -1, - [DB8500_DMA_DEV33_SPI2_RX] = -1, - [DB8500_DMA_DEV35_SPI1_RX] = -1, - [DB8500_DMA_DEV40_SPI3_RX] = -1, - [DB8500_DMA_DEV41_SD_MM3_RX] = -1, - [DB8500_DMA_DEV42_SD_MM4_RX] = -1, - [DB8500_DMA_DEV43_SD_MM5_RX] = -1, - [DB8500_DMA_DEV14_MSP2_RX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV30_MSP3_RX] = U8500_MSP3_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET, - [DB8500_DMA_DEV48_CAC1_RX] = U8500_CRYP1_BASE + CRYP1_RX_REG_OFFSET, -}; - -/* Reserved event lines for memcpy only */ -static int dma40_memcpy_event[] = { - DB8500_DMA_MEMCPY_TX_0, - DB8500_DMA_MEMCPY_TX_1, - DB8500_DMA_MEMCPY_TX_2, - DB8500_DMA_MEMCPY_TX_3, - DB8500_DMA_MEMCPY_TX_4, - DB8500_DMA_MEMCPY_TX_5, -}; - -static struct stedma40_platform_data dma40_plat_data = { - .dev_len = DB8500_DMA_NR_DEV, - .dev_rx = dma40_rx_map, - .dev_tx = dma40_tx_map, - .memcpy = dma40_memcpy_event, - .memcpy_len = ARRAY_SIZE(dma40_memcpy_event), - .memcpy_conf_phy = &dma40_memcpy_conf_phy, - .memcpy_conf_log = &dma40_memcpy_conf_log, +struct stedma40_platform_data dma40_plat_data = { .disabled_channels = {-1}, }; diff --git a/arch/arm/mach-ux500/ste-dma40-db8500.h b/arch/arm/mach-ux500/ste-dma40-db8500.h index a616419bea7..0296ae5b0fd 100644 --- a/arch/arm/mach-ux500/ste-dma40-db8500.h +++ b/arch/arm/mach-ux500/ste-dma40-db8500.h @@ -12,133 +12,74 @@ #define DB8500_DMA_NR_DEV 64 -enum dma_src_dev_type { - DB8500_DMA_DEV0_SPI0_RX = 0, - DB8500_DMA_DEV1_SD_MMC0_RX = 1, - DB8500_DMA_DEV2_SD_MMC1_RX = 2, - DB8500_DMA_DEV3_SD_MMC2_RX = 3, - DB8500_DMA_DEV4_I2C1_RX = 4, - DB8500_DMA_DEV5_I2C3_RX = 5, - DB8500_DMA_DEV6_I2C2_RX = 6, - DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */ - DB8500_DMA_DEV8_SSP0_RX = 8, - DB8500_DMA_DEV9_SSP1_RX = 9, - DB8500_DMA_DEV10_MCDE_RX = 10, - DB8500_DMA_DEV11_UART2_RX = 11, - DB8500_DMA_DEV12_UART1_RX = 12, - DB8500_DMA_DEV13_UART0_RX = 13, - DB8500_DMA_DEV14_MSP2_RX = 14, - DB8500_DMA_DEV15_I2C0_RX = 15, - DB8500_DMA_DEV16_USB_OTG_IEP_7_15 = 16, - DB8500_DMA_DEV17_USB_OTG_IEP_6_14 = 17, - DB8500_DMA_DEV18_USB_OTG_IEP_5_13 = 18, - DB8500_DMA_DEV19_USB_OTG_IEP_4_12 = 19, - DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0 = 20, - DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1 = 21, - DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2 = 22, - DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3 = 23, - DB8500_DMA_DEV24_SRC_SXA0_RX_TX = 24, - DB8500_DMA_DEV25_SRC_SXA1_RX_TX = 25, - DB8500_DMA_DEV26_SRC_SXA2_RX_TX = 26, - DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27, - DB8500_DMA_DEV28_SD_MM2_RX = 28, - DB8500_DMA_DEV29_SD_MM0_RX = 29, - DB8500_DMA_DEV30_MSP1_RX = 30, +/* + * Unless otherwise specified, all channels numbers are used for + * TX & RX, and can be used for either source or destination + * channels. + */ +enum dma_dev_type { + DB8500_DMA_DEV0_SPI0 = 0, + DB8500_DMA_DEV1_SD_MMC0 = 1, + DB8500_DMA_DEV2_SD_MMC1 = 2, + DB8500_DMA_DEV3_SD_MMC2 = 3, + DB8500_DMA_DEV4_I2C1 = 4, + DB8500_DMA_DEV5_I2C3 = 5, + DB8500_DMA_DEV6_I2C2 = 6, + DB8500_DMA_DEV7_I2C4 = 7, /* Only on V1 and later */ + DB8500_DMA_DEV8_SSP0 = 8, + DB8500_DMA_DEV9_SSP1 = 9, + DB8500_DMA_DEV10_MCDE_RX = 10, /* RX only */ + DB8500_DMA_DEV11_UART2 = 11, + DB8500_DMA_DEV12_UART1 = 12, + DB8500_DMA_DEV13_UART0 = 13, + DB8500_DMA_DEV14_MSP2 = 14, + DB8500_DMA_DEV15_I2C0 = 15, + DB8500_DMA_DEV16_USB_OTG_IEP_AND_OEP_7_15 = 16, + DB8500_DMA_DEV17_USB_OTG_IEP_AND_OEP_6_14 = 17, + DB8500_DMA_DEV18_USB_OTG_IEP_AND_OEP_5_13 = 18, + DB8500_DMA_DEV19_USB_OTG_IEP_AND_OEP_4_12 = 19, + DB8500_DMA_DEV20_SLIM0_CH0_HSI_CH0 = 20, + DB8500_DMA_DEV21_SLIM0_CH1_HSI_CH1 = 21, + DB8500_DMA_DEV22_SLIM0_CH2_HSI_CH2 = 22, + DB8500_DMA_DEV23_SLIM0_CH3_HSI_CH3 = 23, + DB8500_DMA_DEV24_SXA0 = 24, + DB8500_DMA_DEV25_SXA1 = 25, + DB8500_DMA_DEV26_SXA2 = 26, + DB8500_DMA_DEV27_SXA3 = 27, + DB8500_DMA_DEV28_SD_MM2 = 28, + DB8500_DMA_DEV29_SD_MM0 = 29, + DB8500_DMA_DEV30_MSP1 = 30, /* On DB8500v2, MSP3 RX replaces MSP1 RX */ - DB8500_DMA_DEV30_MSP3_RX = 30, - DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31, - DB8500_DMA_DEV32_SD_MM1_RX = 32, - DB8500_DMA_DEV33_SPI2_RX = 33, - DB8500_DMA_DEV34_I2C3_RX2 = 34, - DB8500_DMA_DEV35_SPI1_RX = 35, - DB8500_DMA_DEV36_USB_OTG_IEP_3_11 = 36, - DB8500_DMA_DEV37_USB_OTG_IEP_2_10 = 37, - DB8500_DMA_DEV38_USB_OTG_IEP_1_9 = 38, - DB8500_DMA_DEV39_USB_OTG_IEP_8 = 39, - DB8500_DMA_DEV40_SPI3_RX = 40, - DB8500_DMA_DEV41_SD_MM3_RX = 41, - DB8500_DMA_DEV42_SD_MM4_RX = 42, - DB8500_DMA_DEV43_SD_MM5_RX = 43, - DB8500_DMA_DEV44_SRC_SXA4_RX_TX = 44, - DB8500_DMA_DEV45_SRC_SXA5_RX_TX = 45, - DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX = 46, - DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX = 47, - DB8500_DMA_DEV48_CAC1_RX = 48, - /* 49, 50 and 51 are not used */ - DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4 = 52, - DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5 = 53, - DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6 = 54, - DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7 = 55, - /* 56, 57, 58, 59 and 60 are not used */ - DB8500_DMA_DEV61_CAC0_RX = 61, - /* 62 and 63 are not used */ -}; - -enum dma_dest_dev_type { - DB8500_DMA_DEV0_SPI0_TX = 0, - DB8500_DMA_DEV1_SD_MMC0_TX = 1, - DB8500_DMA_DEV2_SD_MMC1_TX = 2, - DB8500_DMA_DEV3_SD_MMC2_TX = 3, - DB8500_DMA_DEV4_I2C1_TX = 4, - DB8500_DMA_DEV5_I2C3_TX = 5, - DB8500_DMA_DEV6_I2C2_TX = 6, - DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */ - DB8500_DMA_DEV8_SSP0_TX = 8, - DB8500_DMA_DEV9_SSP1_TX = 9, - /* 10 is not used*/ - DB8500_DMA_DEV11_UART2_TX = 11, - DB8500_DMA_DEV12_UART1_TX = 12, - DB8500_DMA_DEV13_UART0_TX = 13, - DB8500_DMA_DEV14_MSP2_TX = 14, - DB8500_DMA_DEV15_I2C0_TX = 15, - DB8500_DMA_DEV16_USB_OTG_OEP_7_15 = 16, - DB8500_DMA_DEV17_USB_OTG_OEP_6_14 = 17, - DB8500_DMA_DEV18_USB_OTG_OEP_5_13 = 18, - DB8500_DMA_DEV19_USB_OTG_OEP_4_12 = 19, - DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0 = 20, - DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1 = 21, - DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2 = 22, - DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3 = 23, - DB8500_DMA_DEV24_DST_SXA0_RX_TX = 24, - DB8500_DMA_DEV25_DST_SXA1_RX_TX = 25, - DB8500_DMA_DEV26_DST_SXA2_RX_TX = 26, - DB8500_DMA_DEV27_DST_SXA3_RX_TX = 27, - DB8500_DMA_DEV28_SD_MM2_TX = 28, - DB8500_DMA_DEV29_SD_MM0_TX = 29, - DB8500_DMA_DEV30_MSP1_TX = 30, - DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX = 31, - DB8500_DMA_DEV32_SD_MM1_TX = 32, - DB8500_DMA_DEV33_SPI2_TX = 33, - DB8500_DMA_DEV34_I2C3_TX2 = 34, - DB8500_DMA_DEV35_SPI1_TX = 35, - DB8500_DMA_DEV36_USB_OTG_OEP_3_11 = 36, - DB8500_DMA_DEV37_USB_OTG_OEP_2_10 = 37, - DB8500_DMA_DEV38_USB_OTG_OEP_1_9 = 38, - DB8500_DMA_DEV39_USB_OTG_OEP_8 = 39, - DB8500_DMA_DEV40_SPI3_TX = 40, - DB8500_DMA_DEV41_SD_MM3_TX = 41, - DB8500_DMA_DEV42_SD_MM4_TX = 42, - DB8500_DMA_DEV43_SD_MM5_TX = 43, - DB8500_DMA_DEV44_DST_SXA4_RX_TX = 44, - DB8500_DMA_DEV45_DST_SXA5_RX_TX = 45, - DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX = 46, - DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX = 47, - DB8500_DMA_DEV48_CAC1_TX = 48, - DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49, - DB8500_DMA_DEV50_HAC1_TX = 50, - DB8500_DMA_MEMCPY_TX_0 = 51, - DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4 = 52, - DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5 = 53, - DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6 = 54, - DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7 = 55, - DB8500_DMA_MEMCPY_TX_1 = 56, - DB8500_DMA_MEMCPY_TX_2 = 57, - DB8500_DMA_MEMCPY_TX_3 = 58, - DB8500_DMA_MEMCPY_TX_4 = 59, - DB8500_DMA_MEMCPY_TX_5 = 60, - DB8500_DMA_DEV61_CAC0_TX = 61, - DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62, - DB8500_DMA_DEV63_HAC0_TX = 63, + DB8500_DMA_DEV30_MSP3 = 30, + DB8500_DMA_DEV31_MSP0_SLIM0_CH0 = 31, + DB8500_DMA_DEV32_SD_MM1 = 32, + DB8500_DMA_DEV33_SPI2 = 33, + DB8500_DMA_DEV34_I2C3_RX2_TX2 = 34, + DB8500_DMA_DEV35_SPI1 = 35, + DB8500_DMA_DEV36_USB_OTG_IEP_AND_OEP_3_11 = 36, + DB8500_DMA_DEV37_USB_OTG_IEP_AND_OEP_2_10 = 37, + DB8500_DMA_DEV38_USB_OTG_IEP_AND_OEP_1_9 = 38, + DB8500_DMA_DEV39_USB_OTG_IEP_AND_OEP_8 = 39, + DB8500_DMA_DEV40_SPI3 = 40, + DB8500_DMA_DEV41_SD_MM3 = 41, + DB8500_DMA_DEV42_SD_MM4 = 42, + DB8500_DMA_DEV43_SD_MM5 = 43, + DB8500_DMA_DEV44_SXA4 = 44, + DB8500_DMA_DEV45_SXA5 = 45, + DB8500_DMA_DEV46_SLIM0_CH8_SRC_SXA6 = 46, + DB8500_DMA_DEV47_SLIM0_CH9_SRC_SXA7 = 47, + DB8500_DMA_DEV48_CAC1 = 48, + DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49, /* TX only */ + DB8500_DMA_DEV50_HAC1_TX = 50, /* TX only */ + DB8500_DMA_MEMCPY_TX_0 = 51, /* TX only */ + DB8500_DMA_DEV52_SLIM0_CH4_HSI_CH4 = 52, + DB8500_DMA_DEV53_SLIM0_CH5_HSI_CH5 = 53, + DB8500_DMA_DEV54_SLIM0_CH6_HSI_CH6 = 54, + DB8500_DMA_DEV55_SLIM0_CH7_HSI_CH7 = 55, + /* 56 -> 60 are channels reserved for memcpy only */ + DB8500_DMA_DEV61_CAC0 = 61, + DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62, /* TX only */ + DB8500_DMA_DEV63_HAC0_TX = 63, /* TX only */ }; #endif diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index 2dfc72f7cd8..b7bd8d3a550 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c @@ -14,25 +14,15 @@ #define MUSB_DMA40_RX_CH { \ .mode = STEDMA40_MODE_LOGICAL, \ - .dir = STEDMA40_PERIPH_TO_MEM, \ - .dst_dev_type = STEDMA40_DEV_DST_MEMORY, \ - .src_info.data_width = STEDMA40_WORD_WIDTH, \ - .dst_info.data_width = STEDMA40_WORD_WIDTH, \ - .src_info.psize = STEDMA40_PSIZE_LOG_16, \ - .dst_info.psize = STEDMA40_PSIZE_LOG_16, \ + .dir = DMA_DEV_TO_MEM, \ } #define MUSB_DMA40_TX_CH { \ .mode = STEDMA40_MODE_LOGICAL, \ - .dir = STEDMA40_MEM_TO_PERIPH, \ - .src_dev_type = STEDMA40_DEV_SRC_MEMORY, \ - .src_info.data_width = STEDMA40_WORD_WIDTH, \ - .dst_info.data_width = STEDMA40_WORD_WIDTH, \ - .src_info.psize = STEDMA40_PSIZE_LOG_16, \ - .dst_info.psize = STEDMA40_PSIZE_LOG_16, \ + .dir = DMA_MEM_TO_DEV, \ } -static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS] +static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS] = { MUSB_DMA40_RX_CH, MUSB_DMA40_RX_CH, @@ -44,7 +34,7 @@ static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS] MUSB_DMA40_RX_CH }; -static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_TX_CHANNELS] +static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS] = { MUSB_DMA40_TX_CH, MUSB_DMA40_TX_CH, @@ -56,7 +46,7 @@ static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_TX_CHANNELS] MUSB_DMA40_TX_CH, }; -static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_CHANNELS] = { +static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS] = { &musb_dma_rx_ch[0], &musb_dma_rx_ch[1], &musb_dma_rx_ch[2], @@ -67,7 +57,7 @@ static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_CHANNELS] = { &musb_dma_rx_ch[7] }; -static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_TX_CHANNELS] = { +static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS] = { &musb_dma_tx_ch[0], &musb_dma_tx_ch[1], &musb_dma_tx_ch[2], @@ -81,23 +71,11 @@ static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_TX_CHANNELS] = { static struct ux500_musb_board_data musb_board_data = { .dma_rx_param_array = ux500_dma_rx_param_array, .dma_tx_param_array = ux500_dma_tx_param_array, - .num_rx_channels = UX500_MUSB_DMA_NUM_RX_CHANNELS, - .num_tx_channels = UX500_MUSB_DMA_NUM_TX_CHANNELS, .dma_filter = stedma40_filter, }; -static u64 ux500_musb_dmamask = DMA_BIT_MASK(32); - -static struct musb_hdrc_config musb_hdrc_config = { - .multipoint = true, - .dyn_fifo = true, - .num_eps = 16, - .ram_bits = 16, -}; - static struct musb_hdrc_platform_data musb_platform_data = { .mode = MUSB_OTG, - .config = &musb_hdrc_config, .board_data = &musb_board_data, }; @@ -118,27 +96,26 @@ struct platform_device ux500_musb_device = { .id = 0, .dev = { .platform_data = &musb_platform_data, - .dma_mask = &ux500_musb_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), }, .num_resources = ARRAY_SIZE(usb_resources), .resource = usb_resources, }; -static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type) +static inline void ux500_usb_dma_update_rx_ch_config(int *dev_type) { u32 idx; - for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_CHANNELS; idx++) - musb_dma_rx_ch[idx].src_dev_type = src_dev_type[idx]; + for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_TX_CHANNELS; idx++) + musb_dma_rx_ch[idx].dev_type = dev_type[idx]; } -static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type) +static inline void ux500_usb_dma_update_tx_ch_config(int *dev_type) { u32 idx; - for (idx = 0; idx < UX500_MUSB_DMA_NUM_TX_CHANNELS; idx++) - musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx]; + for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_TX_CHANNELS; idx++) + musb_dma_tx_ch[idx].dev_type = dev_type[idx]; } void ux500_add_usb(struct device *parent, resource_size_t base, int irq, diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index ce66eb9be48..f82bae2171e 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -86,22 +86,6 @@ config OMAP_MUX_WARNINGS to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect OMAP_MUX for your product. -config OMAP_MBOX_FWK - tristate "Mailbox framework support" - depends on ARCH_OMAP && !ARCH_MULTIPLATFORM - help - Say Y here if you want to use OMAP Mailbox framework support for - DSP, IVA1.0 and IVA2 in OMAP1/2/3. - -config OMAP_MBOX_KFIFO_SIZE - int "Mailbox kfifo default buffer size (bytes)" - depends on OMAP_MBOX_FWK - default 256 - help - Specify the default size of mailbox's kfifo buffers (bytes). - This can also be changed at runtime (via the mbox_kfifo_size - module parameter). - config OMAP_IOMMU_IVA2 bool diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 31199417b56..0b01b68fd03 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -17,6 +17,3 @@ obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o obj-y += $(i2c-omap-m) $(i2c-omap-y) -# OMAP mailbox framework -obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o - diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h index 95509d8eb14..d7e17150028 100644 --- a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h +++ b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h @@ -202,7 +202,7 @@ extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void); extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void); -#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS +#ifdef CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS #define s3c_cpufreq_debugfs_call(x) x #else #define s3c_cpufreq_debugfs_call(x) NULL @@ -259,17 +259,17 @@ extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg, #define s3c2412_iotiming_set NULL #endif /* CONFIG_S3C2412_IOTIMING */ -#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG +#ifdef CONFIG_ARM_S3C24XX_CPUFREQ_DEBUG #define s3c_freq_dbg(x...) printk(KERN_INFO x) #else #define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0) -#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */ +#endif /* CONFIG_ARM_S3C24XX_CPUFREQ_DEBUG */ -#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG +#ifdef CONFIG_ARM_S3C24XX_CPUFREQ_IODEBUG #define s3c_freq_iodbg(x...) printk(KERN_INFO x) #else #define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0) -#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */ +#endif /* CONFIG_ARM_S3C24XX_CPUFREQ_IODEBUG */ static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table, int index, size_t table_size, diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq.h b/arch/arm/plat-samsung/include/plat/cpu-freq.h index 80c4a809c72..85517ab962a 100644 --- a/arch/arm/plat-samsung/include/plat/cpu-freq.h +++ b/arch/arm/plat-samsung/include/plat/cpu-freq.h @@ -126,7 +126,7 @@ struct s3c_cpufreq_board { }; /* Things depending on frequency scaling. */ -#ifdef CONFIG_CPU_FREQ_S3C +#ifdef CONFIG_ARM_S3C_CPUFREQ #define __init_or_cpufreq #else #define __init_or_cpufreq __init @@ -134,7 +134,7 @@ struct s3c_cpufreq_board { /* Board functions */ -#ifdef CONFIG_CPU_FREQ_S3C +#ifdef CONFIG_ARM_S3C_CPUFREQ extern int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board); #else @@ -142,4 +142,4 @@ static inline int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) { return 0; } -#endif /* CONFIG_CPU_FREQ_S3C */ +#endif /* CONFIG_ARM_S3C_CPUFREQ */ diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index b7c232e6742..187681013bd 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o +obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c new file mode 100644 index 00000000000..9b1bbd52fd1 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Author: Padmavathi Venna <padma.v@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. + * + * Common Clock Framework support for Audio Subsystem Clock Controller. +*/ + +#include <linux/clkdev.h> +#include <linux/io.h> +#include <linux/clk-provider.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> + +#include <dt-bindings/clk/exynos-audss-clk.h> + +static DEFINE_SPINLOCK(lock); +static struct clk **clk_table; +static void __iomem *reg_base; +static struct clk_onecell_data clk_data; + +#define ASS_CLK_SRC 0x0 +#define ASS_CLK_DIV 0x4 +#define ASS_CLK_GATE 0x8 + +static unsigned long reg_save[][2] = { + {ASS_CLK_SRC, 0}, + {ASS_CLK_DIV, 0}, + {ASS_CLK_GATE, 0}, +}; + +/* list of all parent clock list */ +static const char *mout_audss_p[] = { "fin_pll", "fout_epll" }; +static const char *mout_i2s_p[] = { "mout_audss", "cdclk0", "sclk_audio0" }; + +#ifdef CONFIG_PM_SLEEP +static int exynos_audss_clk_suspend(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(reg_save); i++) + reg_save[i][1] = readl(reg_base + reg_save[i][0]); + + return 0; +} + +static void exynos_audss_clk_resume(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(reg_save); i++) + writel(reg_save[i][1], reg_base + reg_save[i][0]); +} + +static struct syscore_ops exynos_audss_clk_syscore_ops = { + .suspend = exynos_audss_clk_suspend, + .resume = exynos_audss_clk_resume, +}; +#endif /* CONFIG_PM_SLEEP */ + +/* register exynos_audss clocks */ +void __init exynos_audss_clk_init(struct device_node *np) +{ + reg_base = of_iomap(np, 0); + if (!reg_base) { + pr_err("%s: failed to map audss registers\n", __func__); + return; + } + + clk_table = kzalloc(sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, + GFP_KERNEL); + if (!clk_table) { + pr_err("%s: could not allocate clk lookup table\n", __func__); + return; + } + + clk_data.clks = clk_table; + clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS; + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", + mout_audss_p, ARRAY_SIZE(mout_audss_p), 0, + reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); + + clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s", + mout_i2s_p, ARRAY_SIZE(mout_i2s_p), 0, + reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); + + clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp", + "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, + 0, &lock); + + clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL, + "dout_aud_bus", "dout_srp", 0, + reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); + + clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s", + "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0, + &lock); + + clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk", + "dout_srp", CLK_SET_RATE_PARENT, + reg_base + ASS_CLK_GATE, 0, 0, &lock); + + clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus", + "dout_aud_bus", CLK_SET_RATE_PARENT, + reg_base + ASS_CLK_GATE, 2, 0, &lock); + + clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s", + "dout_i2s", CLK_SET_RATE_PARENT, + reg_base + ASS_CLK_GATE, 3, 0, &lock); + + clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus", + "sclk_pcm", CLK_SET_RATE_PARENT, + reg_base + ASS_CLK_GATE, 4, 0, &lock); + + clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm", + "div_pcm0", CLK_SET_RATE_PARENT, + reg_base + ASS_CLK_GATE, 5, 0, &lock); + +#ifdef CONFIG_PM_SLEEP + register_syscore_ops(&exynos_audss_clk_syscore_ops); +#endif + + pr_info("Exynos: Audss: clock setup completed\n"); +} +CLK_OF_DECLARE(exynos4210_audss_clk, "samsung,exynos4210-audss-clock", + exynos_audss_clk_init); +CLK_OF_DECLARE(exynos5250_audss_clk, "samsung,exynos5250-audss-clock", + exynos_audss_clk_init); diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 22d7699e7ce..6f767c515ec 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -87,6 +87,7 @@ enum exynos5250_clks { sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3, sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm, sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2, + div_i2s1, div_i2s2, /* gate clocks */ gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0, @@ -291,8 +292,8 @@ struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV(none, "div_pcm1", "sclk_audio1", DIV_PERIC4, 4, 8), DIV(none, "div_audio2", "mout_audio2", DIV_PERIC4, 16, 4), DIV(none, "div_pcm2", "sclk_audio2", DIV_PERIC4, 20, 8), - DIV(none, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6), - DIV(none, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6), + DIV(div_i2s1, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6), + DIV(div_i2s2, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6), DIV(sclk_pixel, "div_hdmi_pixel", "sclk_vpll", DIV_DISP1_0, 28, 4), DIV_A(none, "armclk", "div_arm", DIV_CPU0, 28, 3, "armclk"), DIV_F(none, "div_mipi1_pre", "div_mipi1", diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c index 54f3d119d99..77398f8c19a 100644 --- a/drivers/clocksource/clksrc-dbx500-prcmu.c +++ b/drivers/clocksource/clksrc-dbx500-prcmu.c @@ -10,7 +10,7 @@ * DBx500-PRCMU Timer * The PRCMU has 5 timers which are available in a always-on * power domain. We use the Timer 4 for our always-on clock - * source on DB8500 and Timer 3 on DB5500. + * source on DB8500. */ #include <linux/clockchips.h> #include <linux/clksrc-dbx500-prcmu.h> @@ -30,15 +30,14 @@ static void __iomem *clksrc_dbx500_timer_base; -static cycle_t clksrc_dbx500_prcmu_read(struct clocksource *cs) +static cycle_t notrace clksrc_dbx500_prcmu_read(struct clocksource *cs) { + void __iomem *base = clksrc_dbx500_timer_base; u32 count, count2; do { - count = readl(clksrc_dbx500_timer_base + - PRCMU_TIMER_DOWNCOUNT); - count2 = readl(clksrc_dbx500_timer_base + - PRCMU_TIMER_DOWNCOUNT); + count = readl_relaxed(base + PRCMU_TIMER_DOWNCOUNT); + count2 = readl_relaxed(base + PRCMU_TIMER_DOWNCOUNT); } while (count2 != count); /* Negate because the timer is a decrementing counter */ diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 6e57543fe0b..a9244089686 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -96,6 +96,56 @@ config ARM_OMAP2PLUS_CPUFREQ default ARCH_OMAP2PLUS select CPU_FREQ_TABLE +config ARM_S3C_CPUFREQ + bool + help + Internal configuration node for common cpufreq on Samsung SoC + +config ARM_S3C24XX_CPUFREQ + bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)" + depends on ARCH_S3C24XX + select ARM_S3C_CPUFREQ + help + This enables the CPUfreq driver for the Samsung S3C24XX family + of CPUs. + + For details, take a look at <file:Documentation/cpu-freq>. + + If in doubt, say N. + +config ARM_S3C24XX_CPUFREQ_DEBUG + bool "Debug CPUfreq Samsung driver core" + depends on ARM_S3C24XX_CPUFREQ + help + Enable s3c_freq_dbg for the Samsung S3C CPUfreq core + +config ARM_S3C24XX_CPUFREQ_IODEBUG + bool "Debug CPUfreq Samsung driver IO timing" + depends on ARM_S3C24XX_CPUFREQ + help + Enable s3c_freq_iodbg for the Samsung S3C CPUfreq core + +config ARM_S3C24XX_CPUFREQ_DEBUGFS + bool "Export debugfs for CPUFreq" + depends on ARM_S3C24XX_CPUFREQ && DEBUG_FS + help + Export status information via debugfs. + +config ARM_S3C2410_CPUFREQ + bool + depends on ARM_S3C24XX_CPUFREQ && CPU_S3C2410 + select S3C2410_CPUFREQ_UTILS + help + CPU Frequency scaling support for S3C2410 + +config ARM_S3C2412_CPUFREQ + bool + depends on ARM_S3C24XX_CPUFREQ && CPU_S3C2412 + default y + select S3C2412_IOTIMING + help + CPU Frequency scaling support for S3C2412 and S3C2413 SoC CPUs. + config ARM_S3C2416_CPUFREQ bool "S3C2416 CPU Frequency scaling support" depends on CPU_S3C2416 @@ -118,6 +168,14 @@ config ARM_S3C2416_CPUFREQ_VCORESCALE If in doubt, say N. +config ARM_S3C2440_CPUFREQ + bool "S3C2440/S3C2442 CPU Frequency scaling support" + depends on ARM_S3C24XX_CPUFREQ && (CPU_S3C2440 || CPU_S3C2442) + select S3C2410_CPUFREQ_UTILS + default y + help + CPU Frequency scaling support for S3C2440 and S3C2442 SoC CPUs. + config ARM_S3C64XX_CPUFREQ bool "Samsung S3C64XX" depends on CPU_S3C6410 diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 315b9231feb..6ad0b913ca1 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -65,7 +65,12 @@ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o obj-$(CONFIG_PXA25x) += pxa2xx-cpufreq.o obj-$(CONFIG_PXA27x) += pxa2xx-cpufreq.o obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o +obj-$(CONFIG_ARM_S3C24XX_CPUFREQ) += s3c24xx-cpufreq.o +obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o +obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o +obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o +obj-$(CONFIG_ARM_S3C2440_CPUFREQ) += s3c2440-cpufreq.o obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o diff --git a/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c b/drivers/cpufreq/s3c2410-cpufreq.c index cfa0dd8723e..cfa0dd8723e 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-s3c2410.c +++ b/drivers/cpufreq/s3c2410-cpufreq.c diff --git a/arch/arm/mach-s3c24xx/cpufreq-s3c2412.c b/drivers/cpufreq/s3c2412-cpufreq.c index 8bf0f3a7747..4645b489899 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-s3c2412.c +++ b/drivers/cpufreq/s3c2412-cpufreq.c @@ -25,13 +25,12 @@ #include <asm/mach/map.h> #include <mach/regs-clock.h> +#include <mach/s3c2412.h> #include <plat/cpu.h> #include <plat/clock.h> #include <plat/cpu-freq-core.h> -#include "s3c2412.h" - /* our clock resources. */ static struct clk *xtal; static struct clk *fclk; diff --git a/arch/arm/mach-s3c24xx/cpufreq-s3c2440.c b/drivers/cpufreq/s3c2440-cpufreq.c index 72b2cc8a5a8..72b2cc8a5a8 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-s3c2440.c +++ b/drivers/cpufreq/s3c2440-cpufreq.c diff --git a/arch/arm/mach-s3c24xx/cpufreq-debugfs.c b/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c index 9b7b4289d66..9b7b4289d66 100644 --- a/arch/arm/mach-s3c24xx/cpufreq-debugfs.c +++ b/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c diff --git a/arch/arm/mach-s3c24xx/cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 3c0e78ede0d..3c0e78ede0d 100644 --- a/arch/arm/mach-s3c24xx/cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c diff --git a/drivers/crypto/ux500/cryp/cryp.c b/drivers/crypto/ux500/cryp/cryp.c index 3eafa903ebc..43a0c8a26ab 100644 --- a/drivers/crypto/ux500/cryp/cryp.c +++ b/drivers/crypto/ux500/cryp/cryp.c @@ -291,7 +291,7 @@ void cryp_save_device_context(struct cryp_device_data *device_data, int cryp_mode) { enum cryp_algo_mode algomode; - struct cryp_register *src_reg = device_data->base; + struct cryp_register __iomem *src_reg = device_data->base; struct cryp_config *config = (struct cryp_config *)device_data->current_ctx; @@ -349,7 +349,7 @@ void cryp_save_device_context(struct cryp_device_data *device_data, void cryp_restore_device_context(struct cryp_device_data *device_data, struct cryp_device_context *ctx) { - struct cryp_register *reg = device_data->base; + struct cryp_register __iomem *reg = device_data->base; struct cryp_config *config = (struct cryp_config *)device_data->current_ctx; diff --git a/drivers/crypto/ux500/cryp/cryp.h b/drivers/crypto/ux500/cryp/cryp.h index 14cfd05b777..d1d6606fe56 100644 --- a/drivers/crypto/ux500/cryp/cryp.h +++ b/drivers/crypto/ux500/cryp/cryp.h @@ -114,6 +114,9 @@ enum cryp_status_id { }; /* Cryp DMA interface */ +#define CRYP_DMA_TX_FIFO 0x08 +#define CRYP_DMA_RX_FIFO 0x10 + enum cryp_dma_req_type { CRYP_DMA_DISABLE_BOTH, CRYP_DMA_ENABLE_IN_DATA, @@ -217,7 +220,8 @@ struct cryp_dma { /** * struct cryp_device_data - structure for a cryp device. - * @base: Pointer to the hardware base address. + * @base: Pointer to virtual base address of the cryp device. + * @phybase: Pointer to physical memory location of the cryp device. * @dev: Pointer to the devices dev structure. * @clk: Pointer to the device's clock control. * @pwr_regulator: Pointer to the device's power control. @@ -232,6 +236,7 @@ struct cryp_dma { */ struct cryp_device_data { struct cryp_register __iomem *base; + phys_addr_t phybase; struct device *dev; struct clk *clk; struct regulator *pwr_regulator; diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c index 8c2777cf02f..83d79b964d1 100644 --- a/drivers/crypto/ux500/cryp/cryp_core.c +++ b/drivers/crypto/ux500/cryp/cryp_core.c @@ -475,6 +475,19 @@ static int cryp_get_device_data(struct cryp_ctx *ctx, static void cryp_dma_setup_channel(struct cryp_device_data *device_data, struct device *dev) { + struct dma_slave_config mem2cryp = { + .direction = DMA_MEM_TO_DEV, + .dst_addr = device_data->phybase + CRYP_DMA_TX_FIFO, + .dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, + .dst_maxburst = 4, + }; + struct dma_slave_config cryp2mem = { + .direction = DMA_DEV_TO_MEM, + .src_addr = device_data->phybase + CRYP_DMA_RX_FIFO, + .src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, + .src_maxburst = 4, + }; + dma_cap_zero(device_data->dma.mask); dma_cap_set(DMA_SLAVE, device_data->dma.mask); @@ -490,6 +503,9 @@ static void cryp_dma_setup_channel(struct cryp_device_data *device_data, stedma40_filter, device_data->dma.cfg_cryp2mem); + dmaengine_slave_config(device_data->dma.chan_mem2cryp, &mem2cryp); + dmaengine_slave_config(device_data->dma.chan_cryp2mem, &cryp2mem); + init_completion(&device_data->dma.cryp_dma_complete); } @@ -537,10 +553,10 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx, dev_dbg(ctx->device->dev, "[%s]: Setting up DMA for buffer " "(TO_DEVICE)", __func__); - desc = channel->device->device_prep_slave_sg(channel, - ctx->device->dma.sg_src, - ctx->device->dma.sg_src_len, - direction, DMA_CTRL_ACK, NULL); + desc = dmaengine_prep_slave_sg(channel, + ctx->device->dma.sg_src, + ctx->device->dma.sg_src_len, + direction, DMA_CTRL_ACK); break; case DMA_FROM_DEVICE: @@ -561,12 +577,12 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx, dev_dbg(ctx->device->dev, "[%s]: Setting up DMA for buffer " "(FROM_DEVICE)", __func__); - desc = channel->device->device_prep_slave_sg(channel, - ctx->device->dma.sg_dst, - ctx->device->dma.sg_dst_len, - direction, - DMA_CTRL_ACK | - DMA_PREP_INTERRUPT, NULL); + desc = dmaengine_prep_slave_sg(channel, + ctx->device->dma.sg_dst, + ctx->device->dma.sg_dst_len, + direction, + DMA_CTRL_ACK | + DMA_PREP_INTERRUPT); desc->callback = cryp_dma_out_callback; desc->callback_param = ctx; @@ -578,7 +594,7 @@ static int cryp_set_dma_transfer(struct cryp_ctx *ctx, return -EFAULT; } - cookie = desc->tx_submit(desc); + cookie = dmaengine_submit(desc); dma_async_issue_pending(channel); return 0; @@ -591,12 +607,12 @@ static void cryp_dma_done(struct cryp_ctx *ctx) dev_dbg(ctx->device->dev, "[%s]: ", __func__); chan = ctx->device->dma.chan_mem2cryp; - chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); dma_unmap_sg(chan->device->dev, ctx->device->dma.sg_src, ctx->device->dma.sg_src_len, DMA_TO_DEVICE); chan = ctx->device->dma.chan_cryp2mem; - chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); dma_unmap_sg(chan->device->dev, ctx->device->dma.sg_dst, ctx->device->dma.sg_dst_len, DMA_FROM_DEVICE); } @@ -1431,6 +1447,7 @@ static int ux500_cryp_probe(struct platform_device *pdev) goto out_kfree; } + device_data->phybase = res->start; device_data->base = ioremap(res->start, resource_size(res)); if (!device_data->base) { dev_err(dev, "[%s]: ioremap failed!", __func__); @@ -1458,11 +1475,17 @@ static int ux500_cryp_probe(struct platform_device *pdev) goto out_regulator; } + ret = clk_prepare(device_data->clk); + if (ret) { + dev_err(dev, "[%s]: clk_prepare() failed!", __func__); + goto out_clk; + } + /* Enable device power (and clock) */ ret = cryp_enable_power(device_data->dev, device_data, false); if (ret) { dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__); - goto out_clk; + goto out_clk_unprepare; } cryp_error = cryp_check(device_data); @@ -1518,11 +1541,16 @@ static int ux500_cryp_probe(struct platform_device *pdev) goto out_power; } + dev_info(dev, "successfully registered\n"); + return 0; out_power: cryp_disable_power(device_data->dev, device_data, false); +out_clk_unprepare: + clk_unprepare(device_data->clk); + out_clk: clk_put(device_data->clk); @@ -1593,6 +1621,7 @@ static int ux500_cryp_remove(struct platform_device *pdev) dev_err(&pdev->dev, "[%s]: cryp_disable_power() failed", __func__); + clk_unprepare(device_data->clk); clk_put(device_data->clk); regulator_put(device_data->pwr_regulator); diff --git a/drivers/crypto/ux500/hash/hash_alg.h b/drivers/crypto/ux500/hash/hash_alg.h index cd9351cb24d..be6eb54da40 100644 --- a/drivers/crypto/ux500/hash/hash_alg.h +++ b/drivers/crypto/ux500/hash/hash_alg.h @@ -11,6 +11,7 @@ #include <linux/bitops.h> #define HASH_BLOCK_SIZE 64 +#define HASH_DMA_FIFO 4 #define HASH_DMA_ALIGN_SIZE 4 #define HASH_DMA_PERFORMANCE_MIN_SIZE 1024 #define HASH_BYTES_PER_WORD 4 @@ -347,7 +348,8 @@ struct hash_req_ctx { /** * struct hash_device_data - structure for a hash device. - * @base: Pointer to the hardware base address. + * @base: Pointer to virtual base address of the hash device. + * @phybase: Pointer to physical memory location of the hash device. * @list_node: For inclusion in klist. * @dev: Pointer to the device dev structure. * @ctx_lock: Spinlock for current_ctx. @@ -361,6 +363,7 @@ struct hash_req_ctx { */ struct hash_device_data { struct hash_register __iomem *base; + phys_addr_t phybase; struct klist_node list_node; struct device *dev; struct spinlock ctx_lock; diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c index 3b8f661d0ed..496ae6aae31 100644 --- a/drivers/crypto/ux500/hash/hash_core.c +++ b/drivers/crypto/ux500/hash/hash_core.c @@ -122,6 +122,13 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data, struct device *dev) { struct hash_platform_data *platform_data = dev->platform_data; + struct dma_slave_config conf = { + .direction = DMA_MEM_TO_DEV, + .dst_addr = device_data->phybase + HASH_DMA_FIFO, + .dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, + .dst_maxburst = 16, + }; + dma_cap_zero(device_data->dma.mask); dma_cap_set(DMA_SLAVE, device_data->dma.mask); @@ -131,6 +138,8 @@ static void hash_dma_setup_channel(struct hash_device_data *device_data, platform_data->dma_filter, device_data->dma.cfg_mem2hash); + dmaengine_slave_config(device_data->dma.chan_mem2hash, &conf); + init_completion(&device_data->dma.complete); } @@ -171,9 +180,9 @@ static int hash_set_dma_transfer(struct hash_ctx *ctx, struct scatterlist *sg, dev_dbg(ctx->device->dev, "[%s]: Setting up DMA for buffer " "(TO_DEVICE)", __func__); - desc = channel->device->device_prep_slave_sg(channel, + desc = dmaengine_prep_slave_sg(channel, ctx->device->dma.sg, ctx->device->dma.sg_len, - direction, DMA_CTRL_ACK | DMA_PREP_INTERRUPT, NULL); + direction, DMA_CTRL_ACK | DMA_PREP_INTERRUPT); if (!desc) { dev_err(ctx->device->dev, "[%s]: device_prep_slave_sg() failed!", __func__); @@ -183,7 +192,7 @@ static int hash_set_dma_transfer(struct hash_ctx *ctx, struct scatterlist *sg, desc->callback = hash_dma_callback; desc->callback_param = ctx; - cookie = desc->tx_submit(desc); + cookie = dmaengine_submit(desc); dma_async_issue_pending(channel); return 0; @@ -194,7 +203,7 @@ static void hash_dma_done(struct hash_ctx *ctx) struct dma_chan *chan; chan = ctx->device->dma.chan_mem2hash; - chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); dma_unmap_sg(chan->device->dev, ctx->device->dma.sg, ctx->device->dma.sg_len, DMA_TO_DEVICE); @@ -464,12 +473,12 @@ static void hash_hw_write_key(struct hash_device_data *device_data, HASH_SET_DIN(&word, nwords); } - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); HASH_SET_DCAL; - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); } @@ -652,7 +661,7 @@ static void hash_messagepad(struct hash_device_data *device_data, if (index_bytes) HASH_SET_DIN(message, nwords); - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); /* num_of_bytes == 0 => NBLW <- 0 (32 bits valid in DATAIN) */ @@ -667,7 +676,7 @@ static void hash_messagepad(struct hash_device_data *device_data, (int)(readl_relaxed(&device_data->base->str) & HASH_STR_NBLW_MASK)); - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); } @@ -767,7 +776,7 @@ void hash_begin(struct hash_device_data *device_data, struct hash_ctx *ctx) /* HW and SW initializations */ /* Note: there is no need to initialize buffer and digest members */ - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); /* @@ -783,8 +792,7 @@ void hash_begin(struct hash_device_data *device_data, struct hash_ctx *ctx) HASH_CLEAR_BITS(&device_data->base->str, HASH_STR_NBLW_MASK); } -int hash_process_data( - struct hash_device_data *device_data, +static int hash_process_data(struct hash_device_data *device_data, struct hash_ctx *ctx, struct hash_req_ctx *req_ctx, int msg_length, u8 *data_buffer, u8 *buffer, u8 *index) { @@ -953,7 +961,7 @@ static int hash_dma_final(struct ahash_request *req) wait_for_completion(&ctx->device->dma.complete); hash_dma_done(ctx); - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC && ctx->key) { @@ -983,7 +991,7 @@ out: * hash_hw_final - The final hash calculation function * @req: The hash request for the job. */ -int hash_hw_final(struct ahash_request *req) +static int hash_hw_final(struct ahash_request *req) { int ret = 0; struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); @@ -1051,7 +1059,7 @@ int hash_hw_final(struct ahash_request *req) req_ctx->state.index); } else { HASH_SET_DCAL; - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); } @@ -1180,7 +1188,7 @@ int hash_resume_state(struct hash_device_data *device_data, temp_cr = device_state->temp_cr; writel_relaxed(temp_cr & HASH_CR_RESUME_MASK, &device_data->base->cr); - if (device_data->base->cr & HASH_CR_MODE_MASK) + if (readl(&device_data->base->cr) & HASH_CR_MODE_MASK) hash_mode = HASH_OPER_MODE_HMAC; else hash_mode = HASH_OPER_MODE_HASH; @@ -1224,7 +1232,7 @@ int hash_save_state(struct hash_device_data *device_data, * actually makes sure that there isn't any ongoing calculation in the * hardware. */ - while (device_data->base->str & HASH_STR_DCAL_MASK) + while (readl(&device_data->base->str) & HASH_STR_DCAL_MASK) cpu_relax(); temp_cr = readl_relaxed(&device_data->base->cr); @@ -1233,7 +1241,7 @@ int hash_save_state(struct hash_device_data *device_data, device_state->din_reg = readl_relaxed(&device_data->base->din); - if (device_data->base->cr & HASH_CR_MODE_MASK) + if (readl(&device_data->base->cr) & HASH_CR_MODE_MASK) hash_mode = HASH_OPER_MODE_HMAC; else hash_mode = HASH_OPER_MODE_HASH; @@ -1699,6 +1707,7 @@ static int ux500_hash_probe(struct platform_device *pdev) goto out_kfree; } + device_data->phybase = res->start; device_data->base = ioremap(res->start, resource_size(res)); if (!device_data->base) { dev_err(dev, "[%s] ioremap() failed!", @@ -1726,11 +1735,17 @@ static int ux500_hash_probe(struct platform_device *pdev) goto out_regulator; } + ret = clk_prepare(device_data->clk); + if (ret) { + dev_err(dev, "[%s] clk_prepare() failed!", __func__); + goto out_clk; + } + /* Enable device power (and clock) */ ret = hash_enable_power(device_data, false); if (ret) { dev_err(dev, "[%s]: hash_enable_power() failed!", __func__); - goto out_clk; + goto out_clk_unprepare; } ret = hash_check_hw(device_data); @@ -1756,12 +1771,15 @@ static int ux500_hash_probe(struct platform_device *pdev) goto out_power; } - dev_info(dev, "[%s] successfully probed\n", __func__); + dev_info(dev, "successfully registered\n"); return 0; out_power: hash_disable_power(device_data, false); +out_clk_unprepare: + clk_unprepare(device_data->clk); + out_clk: clk_put(device_data->clk); @@ -1826,6 +1844,7 @@ static int ux500_hash_remove(struct platform_device *pdev) dev_err(dev, "[%s]: hash_disable_power() failed", __func__); + clk_unprepare(device_data->clk); clk_put(device_data->clk); regulator_put(device_data->regulator); diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 71bf4ec300e..5ab5880d5c9 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -17,6 +17,8 @@ #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/err.h> +#include <linux/of.h> +#include <linux/of_dma.h> #include <linux/amba/bus.h> #include <linux/regulator/consumer.h> #include <linux/platform_data/dma-ste-dma40.h> @@ -45,15 +47,63 @@ #define D40_LCLA_LINK_PER_EVENT_GRP 128 #define D40_LCLA_END D40_LCLA_LINK_PER_EVENT_GRP +/* Max number of logical channels per physical channel */ +#define D40_MAX_LOG_CHAN_PER_PHY 32 + /* Attempts before giving up to trying to get pages that are aligned */ #define MAX_LCLA_ALLOC_ATTEMPTS 256 /* Bit markings for allocation map */ -#define D40_ALLOC_FREE (1 << 31) -#define D40_ALLOC_PHY (1 << 30) +#define D40_ALLOC_FREE BIT(31) +#define D40_ALLOC_PHY BIT(30) #define D40_ALLOC_LOG_FREE 0 -#define MAX(a, b) (((a) < (b)) ? (b) : (a)) +#define D40_MEMCPY_MAX_CHANS 8 + +/* Reserved event lines for memcpy only. */ +#define DB8500_DMA_MEMCPY_EV_0 51 +#define DB8500_DMA_MEMCPY_EV_1 56 +#define DB8500_DMA_MEMCPY_EV_2 57 +#define DB8500_DMA_MEMCPY_EV_3 58 +#define DB8500_DMA_MEMCPY_EV_4 59 +#define DB8500_DMA_MEMCPY_EV_5 60 + +static int dma40_memcpy_channels[] = { + DB8500_DMA_MEMCPY_EV_0, + DB8500_DMA_MEMCPY_EV_1, + DB8500_DMA_MEMCPY_EV_2, + DB8500_DMA_MEMCPY_EV_3, + DB8500_DMA_MEMCPY_EV_4, + DB8500_DMA_MEMCPY_EV_5, +}; + +/* Default configuration for physcial memcpy */ +static struct stedma40_chan_cfg dma40_memcpy_conf_phy = { + .mode = STEDMA40_MODE_PHYSICAL, + .dir = DMA_MEM_TO_MEM, + + .src_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, + .src_info.psize = STEDMA40_PSIZE_PHY_1, + .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + + .dst_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, + .dst_info.psize = STEDMA40_PSIZE_PHY_1, + .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +}; + +/* Default configuration for logical memcpy */ +static struct stedma40_chan_cfg dma40_memcpy_conf_log = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = DMA_MEM_TO_MEM, + + .src_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, + .src_info.psize = STEDMA40_PSIZE_LOG_1, + .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + + .dst_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE, + .dst_info.psize = STEDMA40_PSIZE_LOG_1, + .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +}; /** * enum 40_command - The different commands and/or statuses. @@ -171,6 +221,9 @@ static u32 d40_backup_regs_chan[] = { D40_CHAN_REG_SDLNK, }; +#define BACKUP_REGS_SZ_MAX ((BACKUP_REGS_SZ_V4A > BACKUP_REGS_SZ_V4B) ? \ + BACKUP_REGS_SZ_V4A : BACKUP_REGS_SZ_V4B) + /** * struct d40_interrupt_lookup - lookup table for interrupt handler * @@ -471,6 +524,8 @@ struct d40_gen_dmac { * @phy_start: Physical memory start of the DMA registers. * @phy_size: Size of the DMA register map. * @irq: The IRQ number. + * @num_memcpy_chans: The number of channels used for memcpy (mem-to-mem + * transfers). * @num_phy_chans: The number of physical channels. Read from HW. This * is the number of available channels for this driver, not counting "Secure * mode" allocated physical channels. @@ -514,6 +569,7 @@ struct d40_base { phys_addr_t phy_start; resource_size_t phy_size; int irq; + int num_memcpy_chans; int num_phy_chans; int num_log_chans; struct device_dma_parameters dma_parms; @@ -534,7 +590,7 @@ struct d40_base { resource_size_t lcpa_size; struct kmem_cache *desc_slab; u32 reg_val_backup[BACKUP_REGS_SZ]; - u32 reg_val_backup_v4[MAX(BACKUP_REGS_SZ_V4A, BACKUP_REGS_SZ_V4B)]; + u32 reg_val_backup_v4[BACKUP_REGS_SZ_MAX]; u32 *reg_val_backup_chan; u16 gcc_pwr_off_mask; bool initialized; @@ -792,7 +848,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) * that uses linked lists. */ if (!(chan->phy_chan->use_soft_lli && - chan->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM)) + chan->dma_cfg.dir == DMA_DEV_TO_MEM)) curr_lcla = d40_lcla_alloc_one(chan, desc); first_lcla = curr_lcla; @@ -954,20 +1010,21 @@ static int d40_psize_2_burst_size(bool is_log, int psize) /* * The dma only supports transmitting packages up to - * STEDMA40_MAX_SEG_SIZE << data_width. Calculate the total number of - * dma elements required to send the entire sg list + * STEDMA40_MAX_SEG_SIZE * data_width, where data_width is stored in Bytes. + * + * Calculate the total number of dma elements required to send the entire sg list. */ static int d40_size_2_dmalen(int size, u32 data_width1, u32 data_width2) { int dmalen; u32 max_w = max(data_width1, data_width2); u32 min_w = min(data_width1, data_width2); - u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE << min_w, 1 << max_w); + u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE * min_w, max_w); if (seg_max > STEDMA40_MAX_SEG_SIZE) - seg_max -= (1 << max_w); + seg_max -= max_w; - if (!IS_ALIGNED(size, 1 << max_w)) + if (!IS_ALIGNED(size, max_w)) return -EINVAL; if (size <= seg_max) @@ -1257,21 +1314,17 @@ static void __d40_config_set_event(struct d40_chan *d40c, static void d40_config_set_event(struct d40_chan *d40c, enum d40_events event_type) { - /* Enable event line connected to device (or memcpy) */ - if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || - (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) { - u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); + u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); + /* Enable event line connected to device (or memcpy) */ + if ((d40c->dma_cfg.dir == DMA_DEV_TO_MEM) || + (d40c->dma_cfg.dir == DMA_DEV_TO_DEV)) __d40_config_set_event(d40c, event_type, event, D40_CHAN_REG_SSLNK); - } - - if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM) { - u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); + if (d40c->dma_cfg.dir != DMA_DEV_TO_MEM) __d40_config_set_event(d40c, event_type, event, D40_CHAN_REG_SDLNK); - } } static u32 d40_chan_has_events(struct d40_chan *d40c) @@ -1417,7 +1470,7 @@ static u32 d40_residue(struct d40_chan *d40c) >> D40_SREG_ELEM_PHY_ECNT_POS; } - return num_elt * (1 << d40c->dma_cfg.dst_info.data_width); + return num_elt * d40c->dma_cfg.dst_info.data_width; } static bool d40_tx_is_linked(struct d40_chan *d40c) @@ -1693,7 +1746,7 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data) } /* ACK interrupt */ - writel(1 << idx, base->virtbase + il[row].clr); + writel(BIT(idx), base->virtbase + il[row].clr); spin_lock(&d40c->lock); @@ -1715,8 +1768,6 @@ static int d40_validate_conf(struct d40_chan *d40c, struct stedma40_chan_cfg *conf) { int res = 0; - u32 dst_event_group = D40_TYPE_TO_GROUP(conf->dst_dev_type); - u32 src_event_group = D40_TYPE_TO_GROUP(conf->src_dev_type); bool is_log = conf->mode == STEDMA40_MODE_LOGICAL; if (!conf->dir) { @@ -1724,48 +1775,14 @@ static int d40_validate_conf(struct d40_chan *d40c, res = -EINVAL; } - if (conf->dst_dev_type != STEDMA40_DEV_DST_MEMORY && - d40c->base->plat_data->dev_tx[conf->dst_dev_type] == 0 && - d40c->runtime_addr == 0) { - - chan_err(d40c, "Invalid TX channel address (%d)\n", - conf->dst_dev_type); - res = -EINVAL; - } - - if (conf->src_dev_type != STEDMA40_DEV_SRC_MEMORY && - d40c->base->plat_data->dev_rx[conf->src_dev_type] == 0 && - d40c->runtime_addr == 0) { - chan_err(d40c, "Invalid RX channel address (%d)\n", - conf->src_dev_type); - res = -EINVAL; - } - - if (conf->dir == STEDMA40_MEM_TO_PERIPH && - dst_event_group == STEDMA40_DEV_DST_MEMORY) { - chan_err(d40c, "Invalid dst\n"); + if ((is_log && conf->dev_type > d40c->base->num_log_chans) || + (!is_log && conf->dev_type > d40c->base->num_phy_chans) || + (conf->dev_type < 0)) { + chan_err(d40c, "Invalid device type (%d)\n", conf->dev_type); res = -EINVAL; } - if (conf->dir == STEDMA40_PERIPH_TO_MEM && - src_event_group == STEDMA40_DEV_SRC_MEMORY) { - chan_err(d40c, "Invalid src\n"); - res = -EINVAL; - } - - if (src_event_group == STEDMA40_DEV_SRC_MEMORY && - dst_event_group == STEDMA40_DEV_DST_MEMORY && is_log) { - chan_err(d40c, "No event line\n"); - res = -EINVAL; - } - - if (conf->dir == STEDMA40_PERIPH_TO_PERIPH && - (src_event_group != dst_event_group)) { - chan_err(d40c, "Invalid event group\n"); - res = -EINVAL; - } - - if (conf->dir == STEDMA40_PERIPH_TO_PERIPH) { + if (conf->dir == DMA_DEV_TO_DEV) { /* * DMAC HW supports it. Will be added to this driver, * in case any dma client requires it. @@ -1775,9 +1792,9 @@ static int d40_validate_conf(struct d40_chan *d40c, } if (d40_psize_2_burst_size(is_log, conf->src_info.psize) * - (1 << conf->src_info.data_width) != + conf->src_info.data_width != d40_psize_2_burst_size(is_log, conf->dst_info.psize) * - (1 << conf->dst_info.data_width)) { + conf->dst_info.data_width) { /* * The DMAC hardware only supports * src (burst x width) == dst (burst x width) @@ -1819,8 +1836,8 @@ static bool d40_alloc_mask_set(struct d40_phy_res *phy, if (phy->allocated_src == D40_ALLOC_FREE) phy->allocated_src = D40_ALLOC_LOG_FREE; - if (!(phy->allocated_src & (1 << log_event_line))) { - phy->allocated_src |= 1 << log_event_line; + if (!(phy->allocated_src & BIT(log_event_line))) { + phy->allocated_src |= BIT(log_event_line); goto found; } else goto not_found; @@ -1831,8 +1848,8 @@ static bool d40_alloc_mask_set(struct d40_phy_res *phy, if (phy->allocated_dst == D40_ALLOC_FREE) phy->allocated_dst = D40_ALLOC_LOG_FREE; - if (!(phy->allocated_dst & (1 << log_event_line))) { - phy->allocated_dst |= 1 << log_event_line; + if (!(phy->allocated_dst & BIT(log_event_line))) { + phy->allocated_dst |= BIT(log_event_line); goto found; } else goto not_found; @@ -1862,11 +1879,11 @@ static bool d40_alloc_mask_free(struct d40_phy_res *phy, bool is_src, /* Logical channel */ if (is_src) { - phy->allocated_src &= ~(1 << log_event_line); + phy->allocated_src &= ~BIT(log_event_line); if (phy->allocated_src == D40_ALLOC_LOG_FREE) phy->allocated_src = D40_ALLOC_FREE; } else { - phy->allocated_dst &= ~(1 << log_event_line); + phy->allocated_dst &= ~BIT(log_event_line); if (phy->allocated_dst == D40_ALLOC_LOG_FREE) phy->allocated_dst = D40_ALLOC_FREE; } @@ -1882,7 +1899,7 @@ out: static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) { - int dev_type; + int dev_type = d40c->dma_cfg.dev_type; int event_group; int event_line; struct d40_phy_res *phys; @@ -1896,14 +1913,12 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) phys = d40c->base->phy_res; num_phy_chans = d40c->base->num_phy_chans; - if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { - dev_type = d40c->dma_cfg.src_dev_type; + if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) { log_num = 2 * dev_type; is_src = true; - } else if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || - d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { + } else if (d40c->dma_cfg.dir == DMA_MEM_TO_DEV || + d40c->dma_cfg.dir == DMA_MEM_TO_MEM) { /* dst event lines are used for logical memcpy */ - dev_type = d40c->dma_cfg.dst_dev_type; log_num = 2 * dev_type + 1; is_src = false; } else @@ -1913,7 +1928,7 @@ static int d40_allocate_channel(struct d40_chan *d40c, bool *first_phy_user) event_line = D40_TYPE_TO_EVENT(dev_type); if (!is_log) { - if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { + if (d40c->dma_cfg.dir == DMA_MEM_TO_MEM) { /* Find physical half channel */ if (d40c->dma_cfg.use_fixed_channel) { i = d40c->dma_cfg.phy_channel; @@ -2014,14 +2029,23 @@ static int d40_config_memcpy(struct d40_chan *d40c) dma_cap_mask_t cap = d40c->chan.device->cap_mask; if (dma_has_cap(DMA_MEMCPY, cap) && !dma_has_cap(DMA_SLAVE, cap)) { - d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_log; - d40c->dma_cfg.src_dev_type = STEDMA40_DEV_SRC_MEMORY; - d40c->dma_cfg.dst_dev_type = d40c->base->plat_data-> - memcpy[d40c->chan.chan_id]; + d40c->dma_cfg = dma40_memcpy_conf_log; + d40c->dma_cfg.dev_type = dma40_memcpy_channels[d40c->chan.chan_id]; + + d40_log_cfg(&d40c->dma_cfg, + &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); } else if (dma_has_cap(DMA_MEMCPY, cap) && dma_has_cap(DMA_SLAVE, cap)) { - d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_phy; + d40c->dma_cfg = dma40_memcpy_conf_phy; + + /* Generate interrrupt at end of transfer or relink. */ + d40c->dst_def_cfg |= BIT(D40_SREG_CFG_TIM_POS); + + /* Generate interrupt on error. */ + d40c->src_def_cfg |= BIT(D40_SREG_CFG_EIM_POS); + d40c->dst_def_cfg |= BIT(D40_SREG_CFG_EIM_POS); + } else { chan_err(d40c, "No memcpy\n"); return -EINVAL; @@ -2034,7 +2058,7 @@ static int d40_free_dma(struct d40_chan *d40c) { int res = 0; - u32 event; + u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); struct d40_phy_res *phy = d40c->phy_chan; bool is_src; @@ -2052,14 +2076,12 @@ static int d40_free_dma(struct d40_chan *d40c) return -EINVAL; } - if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || - d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { - event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); + if (d40c->dma_cfg.dir == DMA_MEM_TO_DEV || + d40c->dma_cfg.dir == DMA_MEM_TO_MEM) is_src = false; - } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { - event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); + else if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) is_src = true; - } else { + else { chan_err(d40c, "Unknown direction\n"); return -EINVAL; } @@ -2100,7 +2122,7 @@ static bool d40_is_paused(struct d40_chan *d40c) unsigned long flags; void __iomem *active_reg; u32 status; - u32 event; + u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dev_type); spin_lock_irqsave(&d40c->lock, flags); @@ -2119,12 +2141,10 @@ static bool d40_is_paused(struct d40_chan *d40c) goto _exit; } - if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH || - d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) { - event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type); + if (d40c->dma_cfg.dir == DMA_MEM_TO_DEV || + d40c->dma_cfg.dir == DMA_MEM_TO_MEM) { status = readl(chanbase + D40_CHAN_REG_SDLNK); - } else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) { - event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type); + } else if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) { status = readl(chanbase + D40_CHAN_REG_SSLNK); } else { chan_err(d40c, "Unknown direction\n"); @@ -2255,24 +2275,6 @@ err: return NULL; } -static dma_addr_t -d40_get_dev_addr(struct d40_chan *chan, enum dma_transfer_direction direction) -{ - struct stedma40_platform_data *plat = chan->base->plat_data; - struct stedma40_chan_cfg *cfg = &chan->dma_cfg; - dma_addr_t addr = 0; - - if (chan->runtime_addr) - return chan->runtime_addr; - - if (direction == DMA_DEV_TO_MEM) - addr = plat->dev_rx[cfg->src_dev_type]; - else if (direction == DMA_MEM_TO_DEV) - addr = plat->dev_tx[cfg->dst_dev_type]; - - return addr; -} - static struct dma_async_tx_descriptor * d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, struct scatterlist *sg_dst, unsigned int sg_len, @@ -2299,14 +2301,10 @@ d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src, if (sg_next(&sg_src[sg_len - 1]) == sg_src) desc->cyclic = true; - if (direction != DMA_TRANS_NONE) { - dma_addr_t dev_addr = d40_get_dev_addr(chan, direction); - - if (direction == DMA_DEV_TO_MEM) - src_dev_addr = dev_addr; - else if (direction == DMA_MEM_TO_DEV) - dst_dev_addr = dev_addr; - } + if (direction == DMA_DEV_TO_MEM) + src_dev_addr = chan->runtime_addr; + else if (direction == DMA_MEM_TO_DEV) + dst_dev_addr = chan->runtime_addr; if (chan_is_logical(chan)) ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst, @@ -2366,7 +2364,7 @@ static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src) u32 rtreg; u32 event = D40_TYPE_TO_EVENT(dev_type); u32 group = D40_TYPE_TO_GROUP(dev_type); - u32 bit = 1 << event; + u32 bit = BIT(event); u32 prioreg; struct d40_gen_dmac *dmac = &d40c->base->gen_dmac; @@ -2397,13 +2395,57 @@ static void d40_set_prio_realtime(struct d40_chan *d40c) if (d40c->base->rev < 3) return; - if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) || - (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) - __d40_set_prio_rt(d40c, d40c->dma_cfg.src_dev_type, true); + if ((d40c->dma_cfg.dir == DMA_DEV_TO_MEM) || + (d40c->dma_cfg.dir == DMA_DEV_TO_DEV)) + __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, true); - if ((d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH) || - (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) - __d40_set_prio_rt(d40c, d40c->dma_cfg.dst_dev_type, false); + if ((d40c->dma_cfg.dir == DMA_MEM_TO_DEV) || + (d40c->dma_cfg.dir == DMA_DEV_TO_DEV)) + __d40_set_prio_rt(d40c, d40c->dma_cfg.dev_type, false); +} + +#define D40_DT_FLAGS_MODE(flags) ((flags >> 0) & 0x1) +#define D40_DT_FLAGS_DIR(flags) ((flags >> 1) & 0x1) +#define D40_DT_FLAGS_BIG_ENDIAN(flags) ((flags >> 2) & 0x1) +#define D40_DT_FLAGS_FIXED_CHAN(flags) ((flags >> 3) & 0x1) + +static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct stedma40_chan_cfg cfg; + dma_cap_mask_t cap; + u32 flags; + + memset(&cfg, 0, sizeof(struct stedma40_chan_cfg)); + + dma_cap_zero(cap); + dma_cap_set(DMA_SLAVE, cap); + + cfg.dev_type = dma_spec->args[0]; + flags = dma_spec->args[2]; + + switch (D40_DT_FLAGS_MODE(flags)) { + case 0: cfg.mode = STEDMA40_MODE_LOGICAL; break; + case 1: cfg.mode = STEDMA40_MODE_PHYSICAL; break; + } + + switch (D40_DT_FLAGS_DIR(flags)) { + case 0: + cfg.dir = DMA_MEM_TO_DEV; + cfg.dst_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); + break; + case 1: + cfg.dir = DMA_DEV_TO_MEM; + cfg.src_info.big_endian = D40_DT_FLAGS_BIG_ENDIAN(flags); + break; + } + + if (D40_DT_FLAGS_FIXED_CHAN(flags)) { + cfg.phy_channel = dma_spec->args[1]; + cfg.use_fixed_channel = true; + } + + return dma_request_channel(cap, stedma40_filter, &cfg); } /* DMA ENGINE functions */ @@ -2435,23 +2477,21 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) } pm_runtime_get_sync(d40c->base->dev); - /* Fill in basic CFG register values */ - d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg, - &d40c->dst_def_cfg, chan_is_logical(d40c)); d40_set_prio_realtime(d40c); if (chan_is_logical(d40c)) { - d40_log_cfg(&d40c->dma_cfg, - &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); - - if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) + if (d40c->dma_cfg.dir == DMA_DEV_TO_MEM) d40c->lcpa = d40c->base->lcpa_base + - d40c->dma_cfg.src_dev_type * D40_LCPA_CHAN_SIZE; + d40c->dma_cfg.dev_type * D40_LCPA_CHAN_SIZE; else d40c->lcpa = d40c->base->lcpa_base + - d40c->dma_cfg.dst_dev_type * + d40c->dma_cfg.dev_type * D40_LCPA_CHAN_SIZE + D40_LCPA_CHAN_DST_DELTA; + + /* Unmask the Global Interrupt Mask. */ + d40c->src_def_cfg |= BIT(D40_SREG_CFG_LOG_GIM_POS); + d40c->dst_def_cfg |= BIT(D40_SREG_CFG_LOG_GIM_POS); } dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n", @@ -2641,33 +2681,10 @@ static void d40_terminate_all(struct dma_chan *chan) static int dma40_config_to_halfchannel(struct d40_chan *d40c, struct stedma40_half_channel_info *info, - enum dma_slave_buswidth width, u32 maxburst) { - enum stedma40_periph_data_width addr_width; int psize; - switch (width) { - case DMA_SLAVE_BUSWIDTH_1_BYTE: - addr_width = STEDMA40_BYTE_WIDTH; - break; - case DMA_SLAVE_BUSWIDTH_2_BYTES: - addr_width = STEDMA40_HALFWORD_WIDTH; - break; - case DMA_SLAVE_BUSWIDTH_4_BYTES: - addr_width = STEDMA40_WORD_WIDTH; - break; - case DMA_SLAVE_BUSWIDTH_8_BYTES: - addr_width = STEDMA40_DOUBLEWORD_WIDTH; - break; - default: - dev_err(d40c->base->dev, - "illegal peripheral address width " - "requested (%d)\n", - width); - return -EINVAL; - } - if (chan_is_logical(d40c)) { if (maxburst >= 16) psize = STEDMA40_PSIZE_LOG_16; @@ -2688,7 +2705,6 @@ dma40_config_to_halfchannel(struct d40_chan *d40c, psize = STEDMA40_PSIZE_PHY_1; } - info->data_width = addr_width; info->psize = psize; info->flow_ctrl = STEDMA40_NO_FLOW_CTRL; @@ -2712,21 +2728,14 @@ static int d40_set_runtime_config(struct dma_chan *chan, dst_maxburst = config->dst_maxburst; if (config->direction == DMA_DEV_TO_MEM) { - dma_addr_t dev_addr_rx = - d40c->base->plat_data->dev_rx[cfg->src_dev_type]; - config_addr = config->src_addr; - if (dev_addr_rx) - dev_dbg(d40c->base->dev, - "channel has a pre-wired RX address %08x " - "overriding with %08x\n", - dev_addr_rx, config_addr); - if (cfg->dir != STEDMA40_PERIPH_TO_MEM) + + if (cfg->dir != DMA_DEV_TO_MEM) dev_dbg(d40c->base->dev, "channel was not configured for peripheral " "to memory transfer (%d) overriding\n", cfg->dir); - cfg->dir = STEDMA40_PERIPH_TO_MEM; + cfg->dir = DMA_DEV_TO_MEM; /* Configure the memory side */ if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) @@ -2735,21 +2744,14 @@ static int d40_set_runtime_config(struct dma_chan *chan, dst_maxburst = src_maxburst; } else if (config->direction == DMA_MEM_TO_DEV) { - dma_addr_t dev_addr_tx = - d40c->base->plat_data->dev_tx[cfg->dst_dev_type]; - config_addr = config->dst_addr; - if (dev_addr_tx) - dev_dbg(d40c->base->dev, - "channel has a pre-wired TX address %08x " - "overriding with %08x\n", - dev_addr_tx, config_addr); - if (cfg->dir != STEDMA40_MEM_TO_PERIPH) + + if (cfg->dir != DMA_MEM_TO_DEV) dev_dbg(d40c->base->dev, "channel was not configured for memory " "to peripheral transfer (%d) overriding\n", cfg->dir); - cfg->dir = STEDMA40_MEM_TO_PERIPH; + cfg->dir = DMA_MEM_TO_DEV; /* Configure the memory side */ if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) @@ -2763,6 +2765,11 @@ static int d40_set_runtime_config(struct dma_chan *chan, return -EINVAL; } + if (config_addr <= 0) { + dev_err(d40c->base->dev, "no address supplied\n"); + return -EINVAL; + } + if (src_maxburst * src_addr_width != dst_maxburst * dst_addr_width) { dev_err(d40c->base->dev, "src/dst width/maxburst mismatch: %d*%d != %d*%d\n", @@ -2781,14 +2788,24 @@ static int d40_set_runtime_config(struct dma_chan *chan, src_maxburst = dst_maxburst * dst_addr_width / src_addr_width; } + /* Only valid widths are; 1, 2, 4 and 8. */ + if (src_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED || + src_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES || + dst_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED || + dst_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES || + ((src_addr_width > 1) && (src_addr_width & 1)) || + ((dst_addr_width > 1) && (dst_addr_width & 1))) + return -EINVAL; + + cfg->src_info.data_width = src_addr_width; + cfg->dst_info.data_width = dst_addr_width; + ret = dma40_config_to_halfchannel(d40c, &cfg->src_info, - src_addr_width, src_maxburst); if (ret) return ret; ret = dma40_config_to_halfchannel(d40c, &cfg->dst_info, - dst_addr_width, dst_maxburst); if (ret) return ret; @@ -2797,8 +2814,7 @@ static int d40_set_runtime_config(struct dma_chan *chan, if (chan_is_logical(d40c)) d40_log_cfg(cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3); else - d40_phy_cfg(cfg, &d40c->src_def_cfg, - &d40c->dst_def_cfg, false); + d40_phy_cfg(cfg, &d40c->src_def_cfg, &d40c->dst_def_cfg); /* These settings will take precedence later */ d40c->runtime_addr = config_addr; @@ -2929,7 +2945,7 @@ static int __init d40_dmaengine_init(struct d40_base *base, } d40_chan_init(base, &base->dma_memcpy, base->log_chans, - base->num_log_chans, base->plat_data->memcpy_len); + base->num_log_chans, base->num_memcpy_chans); dma_cap_zero(base->dma_memcpy.cap_mask); dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask); @@ -3123,13 +3139,14 @@ static int __init d40_phy_res_init(struct d40_base *base) static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) { - struct stedma40_platform_data *plat_data; + struct stedma40_platform_data *plat_data = pdev->dev.platform_data; struct clk *clk = NULL; void __iomem *virtbase = NULL; struct resource *res = NULL; struct d40_base *base = NULL; int num_log_chans = 0; int num_phy_chans; + int num_memcpy_chans; int clk_ret = -EINVAL; int i; u32 pid; @@ -3189,8 +3206,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) * DB8540v1 has revision 4 */ rev = AMBA_REV_BITS(pid); - - plat_data = pdev->dev.platform_data; + if (rev < 2) { + d40_err(&pdev->dev, "hardware revision: %d is not supported", rev); + goto failure; + } /* The number of physical channels on this HW */ if (plat_data->num_of_phy_chans) @@ -3198,26 +3217,20 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) else num_phy_chans = 4 * (readl(virtbase + D40_DREG_ICFG) & 0x7) + 4; - dev_info(&pdev->dev, "hardware revision: %d @ 0x%x with %d physical channels\n", - rev, res->start, num_phy_chans); - - if (rev < 2) { - d40_err(&pdev->dev, "hardware revision: %d is not supported", - rev); - goto failure; - } + /* The number of channels used for memcpy */ + if (plat_data->num_of_memcpy_chans) + num_memcpy_chans = plat_data->num_of_memcpy_chans; + else + num_memcpy_chans = ARRAY_SIZE(dma40_memcpy_channels); - /* Count the number of logical channels in use */ - for (i = 0; i < plat_data->dev_len; i++) - if (plat_data->dev_rx[i] != 0) - num_log_chans++; + num_log_chans = num_phy_chans * D40_MAX_LOG_CHAN_PER_PHY; - for (i = 0; i < plat_data->dev_len; i++) - if (plat_data->dev_tx[i] != 0) - num_log_chans++; + dev_info(&pdev->dev, + "hardware rev: %d @ 0x%x with %d physical and %d logical channels\n", + rev, res->start, num_phy_chans, num_log_chans); base = kzalloc(ALIGN(sizeof(struct d40_base), 4) + - (num_phy_chans + num_log_chans + plat_data->memcpy_len) * + (num_phy_chans + num_log_chans + num_memcpy_chans) * sizeof(struct d40_chan), GFP_KERNEL); if (base == NULL) { @@ -3227,6 +3240,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) base->rev = rev; base->clk = clk; + base->num_memcpy_chans = num_memcpy_chans; base->num_phy_chans = num_phy_chans; base->num_log_chans = num_log_chans; base->phy_start = res->start; @@ -3278,17 +3292,11 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev) if (!base->lookup_phy_chans) goto failure; - if (num_log_chans + plat_data->memcpy_len) { - /* - * The max number of logical channels are event lines for all - * src devices and dst devices - */ - base->lookup_log_chans = kzalloc(plat_data->dev_len * 2 * - sizeof(struct d40_chan *), - GFP_KERNEL); - if (!base->lookup_log_chans) - goto failure; - } + base->lookup_log_chans = kzalloc(num_log_chans * + sizeof(struct d40_chan *), + GFP_KERNEL); + if (!base->lookup_log_chans) + goto failure; base->reg_val_backup_chan = kmalloc(base->num_phy_chans * sizeof(d40_backup_regs_chan), @@ -3472,17 +3480,82 @@ failure: return ret; } +static int __init d40_of_probe(struct platform_device *pdev, + struct device_node *np) +{ + struct stedma40_platform_data *pdata; + int num_phy = 0, num_memcpy = 0, num_disabled = 0; + const const __be32 *list; + + pdata = devm_kzalloc(&pdev->dev, + sizeof(struct stedma40_platform_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + /* If absent this value will be obtained from h/w. */ + of_property_read_u32(np, "dma-channels", &num_phy); + if (num_phy > 0) + pdata->num_of_phy_chans = num_phy; + + list = of_get_property(np, "memcpy-channels", &num_memcpy); + num_memcpy /= sizeof(*list); + + if (num_memcpy > D40_MEMCPY_MAX_CHANS || num_memcpy <= 0) { + d40_err(&pdev->dev, + "Invalid number of memcpy channels specified (%d)\n", + num_memcpy); + return -EINVAL; + } + pdata->num_of_memcpy_chans = num_memcpy; + + of_property_read_u32_array(np, "memcpy-channels", + dma40_memcpy_channels, + num_memcpy); + + list = of_get_property(np, "disabled-channels", &num_disabled); + num_disabled /= sizeof(*list); + + if (num_disabled > STEDMA40_MAX_PHYS || num_disabled < 0) { + d40_err(&pdev->dev, + "Invalid number of disabled channels specified (%d)\n", + num_disabled); + return -EINVAL; + } + + of_property_read_u32_array(np, "disabled-channels", + pdata->disabled_channels, + num_disabled); + pdata->disabled_channels[num_disabled] = -1; + + pdev->dev.platform_data = pdata; + + return 0; +} + static int __init d40_probe(struct platform_device *pdev) { - int err; + struct stedma40_platform_data *plat_data = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; int ret = -ENOENT; - struct d40_base *base; + struct d40_base *base = NULL; struct resource *res = NULL; int num_reserved_chans; u32 val; - base = d40_hw_detect_init(pdev); + if (!plat_data) { + if (np) { + if(d40_of_probe(pdev, np)) { + ret = -ENOMEM; + goto failure; + } + } else { + d40_err(&pdev->dev, "No pdata or Device Tree provided\n"); + goto failure; + } + } + base = d40_hw_detect_init(pdev); if (!base) goto failure; @@ -3575,6 +3648,7 @@ static int __init d40_probe(struct platform_device *pdev) base->lcpa_regulator = regulator_get(base->dev, "lcla_esram"); if (IS_ERR(base->lcpa_regulator)) { d40_err(&pdev->dev, "Failed to get lcpa_regulator\n"); + ret = PTR_ERR(base->lcpa_regulator); base->lcpa_regulator = NULL; goto failure; } @@ -3590,19 +3664,26 @@ static int __init d40_probe(struct platform_device *pdev) } base->initialized = true; - err = d40_dmaengine_init(base, num_reserved_chans); - if (err) + ret = d40_dmaengine_init(base, num_reserved_chans); + if (ret) goto failure; base->dev->dma_parms = &base->dma_parms; - err = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE); - if (err) { + ret = dma_set_max_seg_size(base->dev, STEDMA40_MAX_SEG_SIZE); + if (ret) { d40_err(&pdev->dev, "Failed to set dma max seg size\n"); goto failure; } d40_hw_init(base); + if (np) { + ret = of_dma_controller_register(np, d40_xlate, NULL); + if (ret) + dev_err(&pdev->dev, + "could not register of_dma_controller\n"); + } + dev_info(base->dev, "initialized\n"); return 0; @@ -3656,11 +3737,17 @@ failure: return ret; } +static const struct of_device_id d40_match[] = { + { .compatible = "stericsson,dma40", }, + {} +}; + static struct platform_driver d40_driver = { .driver = { .owner = THIS_MODULE, .name = D40_NAME, .pm = DMA40_PM_OPS, + .of_match_table = d40_match, }, }; diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c index 7180e0d4172..27b818dee7c 100644 --- a/drivers/dma/ste_dma40_ll.c +++ b/drivers/dma/ste_dma40_ll.c @@ -10,6 +10,18 @@ #include "ste_dma40_ll.h" +u8 d40_width_to_bits(enum dma_slave_buswidth width) +{ + if (width == DMA_SLAVE_BUSWIDTH_1_BYTE) + return STEDMA40_ESIZE_8_BIT; + else if (width == DMA_SLAVE_BUSWIDTH_2_BYTES) + return STEDMA40_ESIZE_16_BIT; + else if (width == DMA_SLAVE_BUSWIDTH_8_BYTES) + return STEDMA40_ESIZE_64_BIT; + else + return STEDMA40_ESIZE_32_BIT; +} + /* Sets up proper LCSP1 and LCSP3 register for a logical channel */ void d40_log_cfg(struct stedma40_chan_cfg *cfg, u32 *lcsp1, u32 *lcsp3) @@ -18,106 +30,100 @@ void d40_log_cfg(struct stedma40_chan_cfg *cfg, u32 l1 = 0; /* src */ /* src is mem? -> increase address pos */ - if (cfg->dir == STEDMA40_MEM_TO_PERIPH || - cfg->dir == STEDMA40_MEM_TO_MEM) - l1 |= 1 << D40_MEM_LCSP1_SCFG_INCR_POS; + if (cfg->dir == DMA_MEM_TO_DEV || + cfg->dir == DMA_MEM_TO_MEM) + l1 |= BIT(D40_MEM_LCSP1_SCFG_INCR_POS); /* dst is mem? -> increase address pos */ - if (cfg->dir == STEDMA40_PERIPH_TO_MEM || - cfg->dir == STEDMA40_MEM_TO_MEM) - l3 |= 1 << D40_MEM_LCSP3_DCFG_INCR_POS; + if (cfg->dir == DMA_DEV_TO_MEM || + cfg->dir == DMA_MEM_TO_MEM) + l3 |= BIT(D40_MEM_LCSP3_DCFG_INCR_POS); /* src is hw? -> master port 1 */ - if (cfg->dir == STEDMA40_PERIPH_TO_MEM || - cfg->dir == STEDMA40_PERIPH_TO_PERIPH) - l1 |= 1 << D40_MEM_LCSP1_SCFG_MST_POS; + if (cfg->dir == DMA_DEV_TO_MEM || + cfg->dir == DMA_DEV_TO_DEV) + l1 |= BIT(D40_MEM_LCSP1_SCFG_MST_POS); /* dst is hw? -> master port 1 */ - if (cfg->dir == STEDMA40_MEM_TO_PERIPH || - cfg->dir == STEDMA40_PERIPH_TO_PERIPH) - l3 |= 1 << D40_MEM_LCSP3_DCFG_MST_POS; + if (cfg->dir == DMA_MEM_TO_DEV || + cfg->dir == DMA_DEV_TO_DEV) + l3 |= BIT(D40_MEM_LCSP3_DCFG_MST_POS); - l3 |= 1 << D40_MEM_LCSP3_DCFG_EIM_POS; + l3 |= BIT(D40_MEM_LCSP3_DCFG_EIM_POS); l3 |= cfg->dst_info.psize << D40_MEM_LCSP3_DCFG_PSIZE_POS; - l3 |= cfg->dst_info.data_width << D40_MEM_LCSP3_DCFG_ESIZE_POS; + l3 |= d40_width_to_bits(cfg->dst_info.data_width) + << D40_MEM_LCSP3_DCFG_ESIZE_POS; - l1 |= 1 << D40_MEM_LCSP1_SCFG_EIM_POS; + l1 |= BIT(D40_MEM_LCSP1_SCFG_EIM_POS); l1 |= cfg->src_info.psize << D40_MEM_LCSP1_SCFG_PSIZE_POS; - l1 |= cfg->src_info.data_width << D40_MEM_LCSP1_SCFG_ESIZE_POS; + l1 |= d40_width_to_bits(cfg->src_info.data_width) + << D40_MEM_LCSP1_SCFG_ESIZE_POS; *lcsp1 = l1; *lcsp3 = l3; } -/* Sets up SRC and DST CFG register for both logical and physical channels */ -void d40_phy_cfg(struct stedma40_chan_cfg *cfg, - u32 *src_cfg, u32 *dst_cfg, bool is_log) +void d40_phy_cfg(struct stedma40_chan_cfg *cfg, u32 *src_cfg, u32 *dst_cfg) { u32 src = 0; u32 dst = 0; - if (!is_log) { - /* Physical channel */ - if ((cfg->dir == STEDMA40_PERIPH_TO_MEM) || - (cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) { - /* Set master port to 1 */ - src |= 1 << D40_SREG_CFG_MST_POS; - src |= D40_TYPE_TO_EVENT(cfg->src_dev_type); - - if (cfg->src_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) - src |= 1 << D40_SREG_CFG_PHY_TM_POS; - else - src |= 3 << D40_SREG_CFG_PHY_TM_POS; - } - if ((cfg->dir == STEDMA40_MEM_TO_PERIPH) || - (cfg->dir == STEDMA40_PERIPH_TO_PERIPH)) { - /* Set master port to 1 */ - dst |= 1 << D40_SREG_CFG_MST_POS; - dst |= D40_TYPE_TO_EVENT(cfg->dst_dev_type); - - if (cfg->dst_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) - dst |= 1 << D40_SREG_CFG_PHY_TM_POS; - else - dst |= 3 << D40_SREG_CFG_PHY_TM_POS; - } - /* Interrupt on end of transfer for destination */ - dst |= 1 << D40_SREG_CFG_TIM_POS; - - /* Generate interrupt on error */ - src |= 1 << D40_SREG_CFG_EIM_POS; - dst |= 1 << D40_SREG_CFG_EIM_POS; - - /* PSIZE */ - if (cfg->src_info.psize != STEDMA40_PSIZE_PHY_1) { - src |= 1 << D40_SREG_CFG_PHY_PEN_POS; - src |= cfg->src_info.psize << D40_SREG_CFG_PSIZE_POS; - } - if (cfg->dst_info.psize != STEDMA40_PSIZE_PHY_1) { - dst |= 1 << D40_SREG_CFG_PHY_PEN_POS; - dst |= cfg->dst_info.psize << D40_SREG_CFG_PSIZE_POS; - } - - /* Element size */ - src |= cfg->src_info.data_width << D40_SREG_CFG_ESIZE_POS; - dst |= cfg->dst_info.data_width << D40_SREG_CFG_ESIZE_POS; - - /* Set the priority bit to high for the physical channel */ - if (cfg->high_priority) { - src |= 1 << D40_SREG_CFG_PRI_POS; - dst |= 1 << D40_SREG_CFG_PRI_POS; - } - - } else { - /* Logical channel */ - dst |= 1 << D40_SREG_CFG_LOG_GIM_POS; - src |= 1 << D40_SREG_CFG_LOG_GIM_POS; + if ((cfg->dir == DMA_DEV_TO_MEM) || + (cfg->dir == DMA_DEV_TO_DEV)) { + /* Set master port to 1 */ + src |= BIT(D40_SREG_CFG_MST_POS); + src |= D40_TYPE_TO_EVENT(cfg->dev_type); + + if (cfg->src_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) + src |= BIT(D40_SREG_CFG_PHY_TM_POS); + else + src |= 3 << D40_SREG_CFG_PHY_TM_POS; + } + if ((cfg->dir == DMA_MEM_TO_DEV) || + (cfg->dir == DMA_DEV_TO_DEV)) { + /* Set master port to 1 */ + dst |= BIT(D40_SREG_CFG_MST_POS); + dst |= D40_TYPE_TO_EVENT(cfg->dev_type); + + if (cfg->dst_info.flow_ctrl == STEDMA40_NO_FLOW_CTRL) + dst |= BIT(D40_SREG_CFG_PHY_TM_POS); + else + dst |= 3 << D40_SREG_CFG_PHY_TM_POS; + } + /* Interrupt on end of transfer for destination */ + dst |= BIT(D40_SREG_CFG_TIM_POS); + + /* Generate interrupt on error */ + src |= BIT(D40_SREG_CFG_EIM_POS); + dst |= BIT(D40_SREG_CFG_EIM_POS); + + /* PSIZE */ + if (cfg->src_info.psize != STEDMA40_PSIZE_PHY_1) { + src |= BIT(D40_SREG_CFG_PHY_PEN_POS); + src |= cfg->src_info.psize << D40_SREG_CFG_PSIZE_POS; + } + if (cfg->dst_info.psize != STEDMA40_PSIZE_PHY_1) { + dst |= BIT(D40_SREG_CFG_PHY_PEN_POS); + dst |= cfg->dst_info.psize << D40_SREG_CFG_PSIZE_POS; + } + + /* Element size */ + src |= d40_width_to_bits(cfg->src_info.data_width) + << D40_SREG_CFG_ESIZE_POS; + dst |= d40_width_to_bits(cfg->dst_info.data_width) + << D40_SREG_CFG_ESIZE_POS; + + /* Set the priority bit to high for the physical channel */ + if (cfg->high_priority) { + src |= BIT(D40_SREG_CFG_PRI_POS); + dst |= BIT(D40_SREG_CFG_PRI_POS); } if (cfg->src_info.big_endian) - src |= 1 << D40_SREG_CFG_LBE_POS; + src |= BIT(D40_SREG_CFG_LBE_POS); if (cfg->dst_info.big_endian) - dst |= 1 << D40_SREG_CFG_LBE_POS; + dst |= BIT(D40_SREG_CFG_LBE_POS); *src_cfg = src; *dst_cfg = dst; @@ -143,23 +149,22 @@ static int d40_phy_fill_lli(struct d40_phy_lli *lli, num_elems = 2 << psize; /* Must be aligned */ - if (!IS_ALIGNED(data, 0x1 << data_width)) + if (!IS_ALIGNED(data, data_width)) return -EINVAL; /* Transfer size can't be smaller than (num_elms * elem_size) */ - if (data_size < num_elems * (0x1 << data_width)) + if (data_size < num_elems * data_width) return -EINVAL; /* The number of elements. IE now many chunks */ - lli->reg_elt = (data_size >> data_width) << D40_SREG_ELEM_PHY_ECNT_POS; + lli->reg_elt = (data_size / data_width) << D40_SREG_ELEM_PHY_ECNT_POS; /* * Distance to next element sized entry. * Usually the size of the element unless you want gaps. */ if (addr_inc) - lli->reg_elt |= (0x1 << data_width) << - D40_SREG_ELEM_PHY_EIDX_POS; + lli->reg_elt |= data_width << D40_SREG_ELEM_PHY_EIDX_POS; /* Where the data is */ lli->reg_ptr = data; @@ -167,18 +172,20 @@ static int d40_phy_fill_lli(struct d40_phy_lli *lli, /* If this scatter list entry is the last one, no next link */ if (next_lli == 0) - lli->reg_lnk = 0x1 << D40_SREG_LNK_PHY_TCP_POS; + lli->reg_lnk = BIT(D40_SREG_LNK_PHY_TCP_POS); else lli->reg_lnk = next_lli; /* Set/clear interrupt generation on this link item.*/ if (term_int) - lli->reg_cfg |= 0x1 << D40_SREG_CFG_TIM_POS; + lli->reg_cfg |= BIT(D40_SREG_CFG_TIM_POS); else - lli->reg_cfg &= ~(0x1 << D40_SREG_CFG_TIM_POS); + lli->reg_cfg &= ~BIT(D40_SREG_CFG_TIM_POS); - /* Post link */ - lli->reg_lnk |= 0 << D40_SREG_LNK_PHY_PRE_POS; + /* + * Post link - D40_SREG_LNK_PHY_PRE_POS = 0 + * Relink happens after transfer completion. + */ return 0; } @@ -187,16 +194,16 @@ static int d40_seg_size(int size, int data_width1, int data_width2) { u32 max_w = max(data_width1, data_width2); u32 min_w = min(data_width1, data_width2); - u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE << min_w, 1 << max_w); + u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE * min_w, max_w); if (seg_max > STEDMA40_MAX_SEG_SIZE) - seg_max -= (1 << max_w); + seg_max -= max_w; if (size <= seg_max) return size; if (size <= 2 * seg_max) - return ALIGN(size / 2, 1 << max_w); + return ALIGN(size / 2, max_w); return seg_max; } @@ -362,10 +369,10 @@ static void d40_log_fill_lli(struct d40_log_lli *lli, lli->lcsp13 = reg_cfg; /* The number of elements to transfer */ - lli->lcsp02 = ((data_size >> data_width) << + lli->lcsp02 = ((data_size / data_width) << D40_MEM_LCSP0_ECNT_POS) & D40_MEM_LCSP0_ECNT_MASK; - BUG_ON((data_size >> data_width) > STEDMA40_MAX_SEG_SIZE); + BUG_ON((data_size / data_width) > STEDMA40_MAX_SEG_SIZE); /* 16 LSBs address of the current element */ lli->lcsp02 |= data & D40_MEM_LCSP0_SPTR_MASK; diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h index fdde8ef7754..1b47312bc57 100644 --- a/drivers/dma/ste_dma40_ll.h +++ b/drivers/dma/ste_dma40_ll.h @@ -432,8 +432,7 @@ enum d40_lli_flags { void d40_phy_cfg(struct stedma40_chan_cfg *cfg, u32 *src_cfg, - u32 *dst_cfg, - bool is_log); + u32 *dst_cfg); void d40_log_cfg(struct stedma40_chan_cfg *cfg, u32 *lcsp1, diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index d173d56dbb8..6ec82f76f01 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -51,6 +51,8 @@ struct gpio_rcar_priv { #define FILONOFF 0x28 #define BOTHEDGE 0x4c +#define RCAR_MAX_GPIO_PER_BANK 32 + static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs) { return ioread32(p->base + offs); @@ -274,9 +276,35 @@ static struct irq_domain_ops gpio_rcar_irq_domain_ops = { .map = gpio_rcar_irq_domain_map, }; +static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) +{ + struct gpio_rcar_config *pdata = p->pdev->dev.platform_data; + struct device_node *np = p->pdev->dev.of_node; + struct of_phandle_args args; + int ret; + + if (pdata) { + p->config = *pdata; + } else if (IS_ENABLED(CONFIG_OF) && np) { + ret = of_parse_phandle_with_args(np, "gpio-ranges", + "#gpio-range-cells", 0, &args); + p->config.number_of_pins = ret == 0 && args.args_count == 3 + ? args.args[2] + : RCAR_MAX_GPIO_PER_BANK; + p->config.gpio_base = -1; + } + + if (p->config.number_of_pins == 0 || + p->config.number_of_pins > RCAR_MAX_GPIO_PER_BANK) { + dev_warn(&p->pdev->dev, + "Invalid number of gpio lines %u, using %u\n", + p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK); + p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK; + } +} + static int gpio_rcar_probe(struct platform_device *pdev) { - struct gpio_rcar_config *pdata = pdev->dev.platform_data; struct gpio_rcar_priv *p; struct resource *io, *irq; struct gpio_chip *gpio_chip; @@ -291,14 +319,14 @@ static int gpio_rcar_probe(struct platform_device *pdev) goto err0; } - /* deal with driver instance configuration */ - if (pdata) - p->config = *pdata; - p->pdev = pdev; - platform_set_drvdata(pdev, p); spin_lock_init(&p->lock); + /* Get device configuration from DT node or platform data. */ + gpio_rcar_parse_pdata(p); + + platform_set_drvdata(pdev, p); + io = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -325,6 +353,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) gpio_chip->set = gpio_rcar_set; gpio_chip->to_irq = gpio_rcar_to_irq; gpio_chip->label = name; + gpio_chip->dev = &pdev->dev; gpio_chip->owner = THIS_MODULE; gpio_chip->base = p->config.gpio_base; gpio_chip->ngpio = p->config.number_of_pins; @@ -371,10 +400,12 @@ static int gpio_rcar_probe(struct platform_device *pdev) p->config.irq_base, ret); } - ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0, - gpio_chip->base, gpio_chip->ngpio); - if (ret < 0) - dev_warn(&pdev->dev, "failed to add pin range\n"); + if (p->config.pctl_name) { + ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0, + gpio_chip->base, gpio_chip->ngpio); + if (ret < 0) + dev_warn(&pdev->dev, "failed to add pin range\n"); + } return 0; @@ -397,11 +428,23 @@ static int gpio_rcar_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id gpio_rcar_of_table[] = { + { + .compatible = "renesas,gpio-rcar", + }, + { }, +}; + +MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); +#endif + static struct platform_driver gpio_rcar_device_driver = { .probe = gpio_rcar_probe, .remove = gpio_rcar_remove, .driver = { .name = "gpio_rcar", + .of_match_table = of_match_ptr(gpio_rcar_of_table), } }; diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index b22ca793374..a1392f47bbd 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -933,67 +933,6 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip) s3c_gpiolib_track(chip); } -#if defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) -static int s3c24xx_gpio_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, u32 *flags) -{ - unsigned int pin; - - if (WARN_ON(gc->of_gpio_n_cells < 3)) - return -EINVAL; - - if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) - return -EINVAL; - - if (gpiospec->args[0] > gc->ngpio) - return -EINVAL; - - pin = gc->base + gpiospec->args[0]; - - if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1]))) - pr_warn("gpio_xlate: failed to set pin function\n"); - if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff)) - pr_warn("gpio_xlate: failed to set pin pull up/down\n"); - - if (flags) - *flags = gpiospec->args[2] >> 16; - - return gpiospec->args[0]; -} - -static const struct of_device_id s3c24xx_gpio_dt_match[] __initdata = { - { .compatible = "samsung,s3c24xx-gpio", }, - {} -}; - -static __init void s3c24xx_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, - s3c24xx_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 = 3; - gc->of_xlate = s3c24xx_gpio_xlate; -} -#else -static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, - u64 base, u64 offset) -{ - return; -} -#endif /* defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) */ - static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip, int nr_chips, void __iomem *base) { @@ -1018,8 +957,6 @@ static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip, gc->direction_output = samsung_gpiolib_2bit_output; samsung_gpiolib_add(chip); - - s3c24xx_gpiolib_attach_ofnode(chip, S3C24XX_PA_GPIO, i * 0x10); } } @@ -3026,6 +2963,10 @@ static __init int samsung_gpiolib_init(void) */ struct device_node *pctrl_np; static const struct of_device_id exynos_pinctrl_ids[] = { + { .compatible = "samsung,s3c2412-pinctrl", }, + { .compatible = "samsung,s3c2416-pinctrl", }, + { .compatible = "samsung,s3c2440-pinctrl", }, + { .compatible = "samsung,s3c2450-pinctrl", }, { .compatible = "samsung,exynos4210-pinctrl", }, { .compatible = "samsung,exynos4x12-pinctrl", }, { .compatible = "samsung,exynos5250-pinctrl", }, diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 9545c9f0380..c8b5c13bcd0 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -16,4 +16,38 @@ config PL320_MBOX Management Engine, primarily for cpufreq. Say Y here if you want to use the PL320 IPCM support. +config OMAP_MBOX + tristate + help + This option is selected by any OMAP architecture specific mailbox + driver such as CONFIG_OMAP1_MBOX or CONFIG_OMAP2PLUS_MBOX. This + enables the common OMAP mailbox framework code. + +config OMAP1_MBOX + tristate "OMAP1 Mailbox framework support" + depends on ARCH_OMAP1 + select OMAP_MBOX + help + Mailbox implementation for OMAP chips with hardware for + interprocessor communication involving DSP in OMAP1. Say Y here + if you want to use OMAP1 Mailbox framework support. + +config OMAP2PLUS_MBOX + tristate "OMAP2+ Mailbox framework support" + depends on ARCH_OMAP2PLUS + select OMAP_MBOX + help + Mailbox implementation for OMAP family chips with hardware for + interprocessor communication involving DSP, IVA1.0 and IVA2 in + OMAP2/3; or IPU, IVA HD and DSP in OMAP4/5. Say Y here if you + want to use OMAP2+ Mailbox framework support. + +config OMAP_MBOX_KFIFO_SIZE + int "Mailbox kfifo default buffer size (bytes)" + depends on OMAP2PLUS_MBOX || OMAP1_MBOX + default 256 + help + Specify the default size of mailbox's kfifo buffers (bytes). + This can also be changed at runtime (via the mbox_kfifo_size + module parameter). endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 543ad6a7950..e0facb34084 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -1 +1,7 @@ obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o + +obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o +obj-$(CONFIG_OMAP1_MBOX) += mailbox_omap1.o +mailbox_omap1-objs := mailbox-omap1.o +obj-$(CONFIG_OMAP2PLUS_MBOX) += mailbox_omap2.o +mailbox_omap2-objs := mailbox-omap2.o diff --git a/arch/arm/mach-omap1/mailbox.c b/drivers/mailbox/mailbox-omap1.c index efc8f207f6f..9001b7633f1 100644 --- a/arch/arm/mach-omap1/mailbox.c +++ b/drivers/mailbox/mailbox-omap1.c @@ -13,7 +13,8 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/io.h> -#include <plat/mailbox.h> + +#include "omap-mbox.h" #define MAILBOX_ARM2DSP1 0x00 #define MAILBOX_ARM2DSP1b 0x04 @@ -86,21 +87,21 @@ static int omap1_mbox_fifo_full(struct omap_mbox *mbox) /* irq */ static void -omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) +omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { if (irq == IRQ_RX) enable_irq(mbox->irq); } static void -omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) +omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { if (irq == IRQ_RX) disable_irq(mbox->irq); } static int -omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) +omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { if (irq == IRQ_TX) return 0; @@ -152,6 +153,9 @@ static int omap1_mbox_probe(struct platform_device *pdev) list[0]->irq = platform_get_irq_byname(pdev, "dsp"); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + return -ENOENT; + mbox_base = ioremap(mem->start, resource_size(mem)); if (!mbox_base) return -ENOMEM; diff --git a/arch/arm/mach-omap2/mailbox.c b/drivers/mailbox/mailbox-omap2.c index 0b080267b7f..eba380d7b17 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/drivers/mailbox/mailbox-omap2.c @@ -11,15 +11,15 @@ */ #include <linux/module.h> +#include <linux/slab.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/io.h> #include <linux/pm_runtime.h> +#include <linux/platform_data/mailbox-omap.h> -#include <plat/mailbox.h> - -#include "soc.h" +#include "omap-mbox.h" #define MAILBOX_REVISION 0x000 #define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) @@ -59,11 +59,9 @@ struct omap_mbox2_priv { u32 notfull_bit; u32 ctx[OMAP4_MBOX_NR_REGS]; unsigned long irqdisable; + u32 intr_type; }; -static void omap2_mbox_enable_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq); - static inline unsigned int mbox_read_reg(size_t ofs) { return __raw_readl(mbox_base + ofs); @@ -124,8 +122,7 @@ static int omap2_mbox_fifo_full(struct omap_mbox *mbox) } /* Mailbox IRQ handle functions */ -static void omap2_mbox_enable_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) +static void omap2_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; @@ -135,20 +132,22 @@ static void omap2_mbox_enable_irq(struct omap_mbox *mbox, mbox_write_reg(l, p->irqenable); } -static void omap2_mbox_disable_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) +static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - if (!cpu_is_omap44xx()) + /* + * Read and update the interrupt configuration register for pre-OMAP4. + * OMAP4 and later SoCs have a dedicated interrupt disabling register. + */ + if (!p->intr_type) bit = mbox_read_reg(p->irqdisable) & ~bit; mbox_write_reg(bit, p->irqdisable); } -static void omap2_mbox_ack_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) +static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; @@ -159,8 +158,7 @@ static void omap2_mbox_ack_irq(struct omap_mbox *mbox, mbox_read_reg(p->irqstatus); } -static int omap2_mbox_is_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) +static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) { struct omap_mbox2_priv *p = mbox->priv; u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; @@ -175,7 +173,8 @@ static void omap2_mbox_save_ctx(struct omap_mbox *mbox) int i; struct omap_mbox2_priv *p = mbox->priv; int nr_regs; - if (cpu_is_omap44xx()) + + if (p->intr_type) nr_regs = OMAP4_MBOX_NR_REGS; else nr_regs = MBOX_NR_REGS; @@ -192,7 +191,8 @@ static void omap2_mbox_restore_ctx(struct omap_mbox *mbox) int i; struct omap_mbox2_priv *p = mbox->priv; int nr_regs; - if (cpu_is_omap44xx()) + + if (p->intr_type) nr_regs = OMAP4_MBOX_NR_REGS; else nr_regs = MBOX_NR_REGS; @@ -220,192 +220,120 @@ static struct omap_mbox_ops omap2_mbox_ops = { .restore_ctx = omap2_mbox_restore_ctx, }; -/* - * MAILBOX 0: ARM -> DSP, - * MAILBOX 1: ARM <- DSP. - * MAILBOX 2: ARM -> IVA, - * MAILBOX 3: ARM <- IVA. - */ - -/* FIXME: the following structs should be filled automatically by the user id */ - -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP2) -/* DSP */ -static struct omap_mbox2_priv omap2_mbox_dsp_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE(0), - .fifo_stat = MAILBOX_FIFOSTATUS(0), - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE(1), - .msg_stat = MAILBOX_MSGSTATUS(1), - }, - .irqenable = MAILBOX_IRQENABLE(0), - .irqstatus = MAILBOX_IRQSTATUS(0), - .notfull_bit = MAILBOX_IRQ_NOTFULL(0), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), - .irqdisable = MAILBOX_IRQENABLE(0), -}; - -struct omap_mbox mbox_dsp_info = { - .name = "dsp", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_dsp_priv, -}; -#endif - -#if defined(CONFIG_ARCH_OMAP3) -struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL }; -#endif - -#if defined(CONFIG_SOC_OMAP2420) -/* IVA */ -static struct omap_mbox2_priv omap2_mbox_iva_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE(2), - .fifo_stat = MAILBOX_FIFOSTATUS(2), - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE(3), - .msg_stat = MAILBOX_MSGSTATUS(3), - }, - .irqenable = MAILBOX_IRQENABLE(3), - .irqstatus = MAILBOX_IRQSTATUS(3), - .notfull_bit = MAILBOX_IRQ_NOTFULL(2), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), - .irqdisable = MAILBOX_IRQENABLE(3), -}; - -static struct omap_mbox mbox_iva_info = { - .name = "iva", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_iva_priv, -}; -#endif - -#ifdef CONFIG_ARCH_OMAP2 -struct omap_mbox *omap2_mboxes[] = { - &mbox_dsp_info, -#ifdef CONFIG_SOC_OMAP2420 - &mbox_iva_info, -#endif - NULL -}; -#endif - -#if defined(CONFIG_ARCH_OMAP4) -/* OMAP4 */ -static struct omap_mbox2_priv omap2_mbox_1_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE(0), - .fifo_stat = MAILBOX_FIFOSTATUS(0), - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE(1), - .msg_stat = MAILBOX_MSGSTATUS(1), - }, - .irqenable = OMAP4_MAILBOX_IRQENABLE(0), - .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0), - .notfull_bit = MAILBOX_IRQ_NOTFULL(0), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), - .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0), -}; - -struct omap_mbox mbox_1_info = { - .name = "mailbox-1", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_1_priv, -}; - -static struct omap_mbox2_priv omap2_mbox_2_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE(3), - .fifo_stat = MAILBOX_FIFOSTATUS(3), - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE(2), - .msg_stat = MAILBOX_MSGSTATUS(2), - }, - .irqenable = OMAP4_MAILBOX_IRQENABLE(0), - .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0), - .notfull_bit = MAILBOX_IRQ_NOTFULL(3), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(2), - .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0), -}; - -struct omap_mbox mbox_2_info = { - .name = "mailbox-2", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_2_priv, -}; - -struct omap_mbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info, NULL }; -#endif - static int omap2_mbox_probe(struct platform_device *pdev) { struct resource *mem; int ret; - struct omap_mbox **list; - - if (false) - ; -#if defined(CONFIG_ARCH_OMAP3) - else if (cpu_is_omap34xx()) { - list = omap3_mboxes; + struct omap_mbox **list, *mbox, *mboxblk; + struct omap_mbox2_priv *priv, *privblk; + struct omap_mbox_pdata *pdata = pdev->dev.platform_data; + struct omap_mbox_dev_info *info; + int i; - list[0]->irq = platform_get_irq(pdev, 0); + if (!pdata || !pdata->info_cnt || !pdata->info) { + pr_err("%s: platform not supported\n", __func__); + return -ENODEV; } -#endif -#if defined(CONFIG_ARCH_OMAP2) - else if (cpu_is_omap2430()) { - list = omap2_mboxes; - list[0]->irq = platform_get_irq(pdev, 0); - } else if (cpu_is_omap2420()) { - list = omap2_mboxes; + /* allocate one extra for marking end of list */ + list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL); + if (!list) + return -ENOMEM; - list[0]->irq = platform_get_irq_byname(pdev, "dsp"); - list[1]->irq = platform_get_irq_byname(pdev, "iva"); + mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL); + if (!mboxblk) { + ret = -ENOMEM; + goto free_list; } -#endif -#if defined(CONFIG_ARCH_OMAP4) - else if (cpu_is_omap44xx()) { - list = omap4_mboxes; - list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0); + privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL); + if (!privblk) { + ret = -ENOMEM; + goto free_mboxblk; } -#endif - else { - pr_err("%s: platform not supported\n", __func__); - return -ENODEV; + + info = pdata->info; + for (i = 0; i < pdata->info_cnt; i++, info++, priv++) { + priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id); + priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id); + priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id); + priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id); + priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id); + priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id); + if (pdata->intr_type) { + priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id); + priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id); + priv->irqdisable = + OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id); + } else { + priv->irqenable = MAILBOX_IRQENABLE(info->usr_id); + priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id); + priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id); + } + priv->intr_type = pdata->intr_type; + + mbox->priv = priv; + mbox->name = info->name; + mbox->ops = &omap2_mbox_ops; + mbox->irq = platform_get_irq(pdev, info->irq_id); + if (mbox->irq < 0) { + ret = mbox->irq; + goto free_privblk; + } + list[i] = mbox++; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + ret = -ENOENT; + goto free_privblk; + } + mbox_base = ioremap(mem->start, resource_size(mem)); - if (!mbox_base) - return -ENOMEM; + if (!mbox_base) { + ret = -ENOMEM; + goto free_privblk; + } ret = omap_mbox_register(&pdev->dev, list); - if (ret) { - iounmap(mbox_base); - return ret; - } + if (ret) + goto unmap_mbox; + platform_set_drvdata(pdev, list); return 0; + +unmap_mbox: + iounmap(mbox_base); +free_privblk: + kfree(privblk); +free_mboxblk: + kfree(mboxblk); +free_list: + kfree(list); + return ret; } static int omap2_mbox_remove(struct platform_device *pdev) { + struct omap_mbox2_priv *privblk; + struct omap_mbox **list = platform_get_drvdata(pdev); + struct omap_mbox *mboxblk = list[0]; + + privblk = mboxblk->priv; omap_mbox_unregister(); iounmap(mbox_base); + kfree(privblk); + kfree(mboxblk); + kfree(list); + platform_set_drvdata(pdev, NULL); + return 0; } static struct platform_driver omap2_mbox_driver = { - .probe = omap2_mbox_probe, - .remove = omap2_mbox_remove, - .driver = { + .probe = omap2_mbox_probe, + .remove = omap2_mbox_remove, + .driver = { .name = "omap-mailbox", }, }; diff --git a/arch/arm/plat-omap/mailbox.c b/drivers/mailbox/omap-mailbox.c index 42377ef9ea3..d79a646b904 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/drivers/mailbox/omap-mailbox.c @@ -31,7 +31,7 @@ #include <linux/notifier.h> #include <linux/module.h> -#include <plat/mailbox.h> +#include "omap-mbox.h" static struct omap_mbox **mboxes; @@ -116,6 +116,40 @@ out: } EXPORT_SYMBOL(omap_mbox_msg_send); +void omap_mbox_save_ctx(struct omap_mbox *mbox) +{ + if (!mbox->ops->save_ctx) { + dev_err(mbox->dev, "%s:\tno save\n", __func__); + return; + } + + mbox->ops->save_ctx(mbox); +} +EXPORT_SYMBOL(omap_mbox_save_ctx); + +void omap_mbox_restore_ctx(struct omap_mbox *mbox) +{ + if (!mbox->ops->restore_ctx) { + dev_err(mbox->dev, "%s:\tno restore\n", __func__); + return; + } + + mbox->ops->restore_ctx(mbox); +} +EXPORT_SYMBOL(omap_mbox_restore_ctx); + +void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + mbox->ops->enable_irq(mbox, irq); +} +EXPORT_SYMBOL(omap_mbox_enable_irq); + +void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + mbox->ops->disable_irq(mbox, irq); +} +EXPORT_SYMBOL(omap_mbox_disable_irq); + static void mbox_tx_tasklet(unsigned long tx_data) { struct omap_mbox *mbox = (struct omap_mbox *)tx_data; @@ -261,13 +295,6 @@ static int omap_mbox_startup(struct omap_mbox *mbox) } if (!mbox->use_count++) { - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, - mbox->name, mbox); - if (unlikely(ret)) { - pr_err("failed to register mailbox interrupt:%d\n", - ret); - goto fail_request_irq; - } mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); if (!mq) { ret = -ENOMEM; @@ -282,17 +309,24 @@ static int omap_mbox_startup(struct omap_mbox *mbox) } mbox->rxq = mq; mq->mbox = mbox; + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, + mbox->name, mbox); + if (unlikely(ret)) { + pr_err("failed to register mailbox interrupt:%d\n", + ret); + goto fail_request_irq; + } omap_mbox_enable_irq(mbox, IRQ_RX); } mutex_unlock(&mbox_configured_lock); return 0; +fail_request_irq: + mbox_queue_free(mbox->rxq); fail_alloc_rxq: mbox_queue_free(mbox->txq); fail_alloc_txq: - free_irq(mbox->irq, mbox); -fail_request_irq: if (mbox->ops->shutdown) mbox->ops->shutdown(mbox); mbox->use_count--; diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/drivers/mailbox/omap-mbox.h index cc3921e9059..6cd38fc6859 100644 --- a/arch/arm/plat-omap/include/plat/mailbox.h +++ b/drivers/mailbox/omap-mbox.h @@ -1,20 +1,20 @@ -/* mailbox.h */ +/* + * omap-mbox.h: OMAP mailbox internal definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ -#ifndef MAILBOX_H -#define MAILBOX_H +#ifndef OMAP_MBOX_H +#define OMAP_MBOX_H -#include <linux/spinlock.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> #include <linux/device.h> +#include <linux/interrupt.h> #include <linux/kfifo.h> - -typedef u32 mbox_msg_t; -struct omap_mbox; - -typedef int __bitwise omap_mbox_irq_t; -#define IRQ_TX ((__force omap_mbox_irq_t) 1) -#define IRQ_RX ((__force omap_mbox_irq_t) 2) +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/omap-mailbox.h> typedef int __bitwise omap_mbox_type_t; #define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1) @@ -51,55 +51,17 @@ struct omap_mbox_queue { }; struct omap_mbox { - char *name; + const char *name; unsigned int irq; struct omap_mbox_queue *txq, *rxq; struct omap_mbox_ops *ops; struct device *dev; void *priv; int use_count; - struct blocking_notifier_head notifier; + struct blocking_notifier_head notifier; }; -int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); -void omap_mbox_init_seq(struct omap_mbox *); - -struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb); -void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb); - int omap_mbox_register(struct device *parent, struct omap_mbox **); int omap_mbox_unregister(void); -static inline void omap_mbox_save_ctx(struct omap_mbox *mbox) -{ - if (!mbox->ops->save_ctx) { - dev_err(mbox->dev, "%s:\tno save\n", __func__); - return; - } - - mbox->ops->save_ctx(mbox); -} - -static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox) -{ - if (!mbox->ops->restore_ctx) { - dev_err(mbox->dev, "%s:\tno restore\n", __func__); - return; - } - - mbox->ops->restore_ctx(mbox); -} - -static inline void omap_mbox_enable_irq(struct omap_mbox *mbox, - omap_mbox_irq_t irq) -{ - mbox->ops->enable_irq(mbox, irq); -} - -static inline void omap_mbox_disable_irq(struct omap_mbox *mbox, - omap_mbox_irq_t irq) -{ - mbox->ops->disable_irq(mbox, irq); -} - -#endif /* MAILBOX_H */ +#endif /* OMAP_MBOX_H */ diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index a1c6dd32e14..901a388dbea 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -217,6 +217,11 @@ config PINCTRL_EXYNOS5440 select PINMUX select PINCONF +config PINCTRL_S3C24XX + bool "Samsung S3C24XX SoC pinctrl driver" + depends on ARCH_S3C24XX + select PINCTRL_SAMSUNG + config PINCTRL_S3C64XX bool "Samsung S3C64XX SoC pinctrl driver" depends on ARCH_S3C64XX diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 9bdaeb8785c..f90b645fb60 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o +obj-$(CONFIG_PINCTRL_S3C24XX) += pinctrl-s3c24xx.o obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o diff --git a/drivers/pinctrl/pinctrl-s3c24xx.c b/drivers/pinctrl/pinctrl-s3c24xx.c new file mode 100644 index 00000000000..24446daaad7 --- /dev/null +++ b/drivers/pinctrl/pinctrl-s3c24xx.c @@ -0,0 +1,651 @@ +/* + * S3C24XX specific support for Samsung pinctrl/gpiolib driver. + * + * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de> + * + * 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 file contains the SamsungS3C24XX specific information required by the + * Samsung pinctrl/gpiolib driver. It also includes the implementation of + * external gpio and wakeup interrupt support. + */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/irqdomain.h> +#include <linux/irq.h> +#include <linux/of_irq.h> +#include <linux/irqchip/chained_irq.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/err.h> + +#include "pinctrl-samsung.h" + +#define NUM_EINT 24 +#define NUM_EINT_IRQ 6 +#define EINT_MAX_PER_GROUP 8 + +#define EINTPEND_REG 0xa8 +#define EINTMASK_REG 0xa4 + +#define EINT_GROUP(i) ((int)((i) / EINT_MAX_PER_GROUP)) +#define EINT_REG(i) ((EINT_GROUP(i) * 4) + 0x88) +#define EINT_OFFS(i) ((i) % EINT_MAX_PER_GROUP * 4) + +#define EINT_LEVEL_LOW 0 +#define EINT_LEVEL_HIGH 1 +#define EINT_EDGE_FALLING 2 +#define EINT_EDGE_RISING 4 +#define EINT_EDGE_BOTH 6 +#define EINT_MASK 0xf + +static struct samsung_pin_bank_type bank_type_1bit = { + .fld_width = { 1, 1, }, + .reg_offset = { 0x00, 0x04, }, +}; + +static struct samsung_pin_bank_type bank_type_2bit = { + .fld_width = { 2, 1, 2, }, + .reg_offset = { 0x00, 0x04, 0x08, }, +}; + +#define PIN_BANK_A(pins, reg, id) \ + { \ + .type = &bank_type_1bit, \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .eint_type = EINT_TYPE_NONE, \ + .name = id \ + } + +#define PIN_BANK_2BIT(pins, reg, id) \ + { \ + .type = &bank_type_2bit, \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .eint_type = EINT_TYPE_NONE, \ + .name = id \ + } + +#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs, emask)\ + { \ + .type = &bank_type_2bit, \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .eint_type = EINT_TYPE_WKUP, \ + .eint_func = 2, \ + .eint_mask = emask, \ + .eint_offset = eoffs, \ + .name = id \ + } + +/** + * struct s3c24xx_eint_data: EINT common data + * @drvdata: pin controller driver data + * @domains: IRQ domains of particular EINT interrupts + * @parents: mapped parent irqs in the main interrupt controller + */ +struct s3c24xx_eint_data { + struct samsung_pinctrl_drv_data *drvdata; + struct irq_domain *domains[NUM_EINT]; + int parents[NUM_EINT_IRQ]; +}; + +/** + * struct s3c24xx_eint_domain_data: per irq-domain data + * @bank: pin bank related to the domain + * @eint_data: common data + * eint0_3_parent_only: live eints 0-3 only in the main intc + */ +struct s3c24xx_eint_domain_data { + struct samsung_pin_bank *bank; + struct s3c24xx_eint_data *eint_data; + bool eint0_3_parent_only; +}; + +static int s3c24xx_eint_get_trigger(unsigned int type) +{ + switch (type) { + case IRQ_TYPE_EDGE_RISING: + return EINT_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_FALLING: + return EINT_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: + return EINT_EDGE_BOTH; + break; + case IRQ_TYPE_LEVEL_HIGH: + return EINT_LEVEL_HIGH; + break; + case IRQ_TYPE_LEVEL_LOW: + return EINT_LEVEL_LOW; + break; + default: + return -EINVAL; + } +} + +static void s3c24xx_eint_set_handler(unsigned int irq, unsigned int type) +{ + /* Edge- and level-triggered interrupts need different handlers */ + if (type & IRQ_TYPE_EDGE_BOTH) + __irq_set_handler_locked(irq, handle_edge_irq); + else + __irq_set_handler_locked(irq, handle_level_irq); +} + +static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d, + struct samsung_pin_bank *bank, int pin) +{ + struct samsung_pin_bank_type *bank_type = bank->type; + unsigned long flags; + void __iomem *reg; + u8 shift; + u32 mask; + u32 val; + + /* Make sure that pin is configured as interrupt */ + reg = d->virt_base + bank->pctl_offset; + shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; + mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; + + spin_lock_irqsave(&bank->slock, flags); + + val = readl(reg); + val &= ~(mask << shift); + val |= bank->eint_func << shift; + writel(val, reg); + + spin_unlock_irqrestore(&bank->slock, flags); +} + +static int s3c24xx_eint_type(struct irq_data *data, unsigned int type) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct samsung_pinctrl_drv_data *d = bank->drvdata; + int index = bank->eint_offset + data->hwirq; + void __iomem *reg; + int trigger; + u8 shift; + u32 val; + + trigger = s3c24xx_eint_get_trigger(type); + if (trigger < 0) { + dev_err(d->dev, "unsupported external interrupt type\n"); + return -EINVAL; + } + + s3c24xx_eint_set_handler(data->irq, type); + + /* Set up interrupt trigger */ + reg = d->virt_base + EINT_REG(index); + shift = EINT_OFFS(index); + + val = readl(reg); + val &= ~(EINT_MASK << shift); + val |= trigger << shift; + writel(val, reg); + + s3c24xx_eint_set_function(d, bank, data->hwirq); + + return 0; +} + +/* Handling of EINTs 0-3 on all except S3C2412 and S3C2413 */ + +static void s3c2410_eint0_3_ack(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data; + struct s3c24xx_eint_data *eint_data = ddata->eint_data; + int parent_irq = eint_data->parents[data->hwirq]; + struct irq_chip *parent_chip = irq_get_chip(parent_irq); + + parent_chip->irq_ack(irq_get_irq_data(parent_irq)); +} + +static void s3c2410_eint0_3_mask(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data; + struct s3c24xx_eint_data *eint_data = ddata->eint_data; + int parent_irq = eint_data->parents[data->hwirq]; + struct irq_chip *parent_chip = irq_get_chip(parent_irq); + + parent_chip->irq_mask(irq_get_irq_data(parent_irq)); +} + +static void s3c2410_eint0_3_unmask(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data; + struct s3c24xx_eint_data *eint_data = ddata->eint_data; + int parent_irq = eint_data->parents[data->hwirq]; + struct irq_chip *parent_chip = irq_get_chip(parent_irq); + + parent_chip->irq_unmask(irq_get_irq_data(parent_irq)); +} + +static struct irq_chip s3c2410_eint0_3_chip = { + .name = "s3c2410-eint0_3", + .irq_ack = s3c2410_eint0_3_ack, + .irq_mask = s3c2410_eint0_3_mask, + .irq_unmask = s3c2410_eint0_3_unmask, + .irq_set_type = s3c24xx_eint_type, +}; + +static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc) +{ + struct irq_data *data = irq_desc_get_irq_data(desc); + struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq); + unsigned int virq; + + /* the first 4 eints have a simple 1 to 1 mapping */ + virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq); + /* Something must be really wrong if an unmapped EINT is unmasked */ + BUG_ON(!virq); + + generic_handle_irq(virq); +} + +/* Handling of EINTs 0-3 on S3C2412 and S3C2413 */ + +static void s3c2412_eint0_3_ack(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct samsung_pinctrl_drv_data *d = bank->drvdata; + + unsigned long bitval = 1UL << data->hwirq; + writel(bitval, d->virt_base + EINTPEND_REG); +} + +static void s3c2412_eint0_3_mask(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct samsung_pinctrl_drv_data *d = bank->drvdata; + unsigned long mask; + + mask = readl(d->virt_base + EINTMASK_REG); + mask |= (1UL << data->hwirq); + writel(mask, d->virt_base + EINTMASK_REG); +} + +static void s3c2412_eint0_3_unmask(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct samsung_pinctrl_drv_data *d = bank->drvdata; + unsigned long mask; + + mask = readl(d->virt_base + EINTMASK_REG); + mask &= ~(1UL << data->hwirq); + writel(mask, d->virt_base + EINTMASK_REG); +} + +static struct irq_chip s3c2412_eint0_3_chip = { + .name = "s3c2412-eint0_3", + .irq_ack = s3c2412_eint0_3_ack, + .irq_mask = s3c2412_eint0_3_mask, + .irq_unmask = s3c2412_eint0_3_unmask, + .irq_set_type = s3c24xx_eint_type, +}; + +static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc) +{ + struct irq_chip *chip = irq_get_chip(irq); + struct irq_data *data = irq_desc_get_irq_data(desc); + struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq); + unsigned int virq; + + chained_irq_enter(chip, desc); + + /* the first 4 eints have a simple 1 to 1 mapping */ + virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq); + /* Something must be really wrong if an unmapped EINT is unmasked */ + BUG_ON(!virq); + + generic_handle_irq(virq); + + chained_irq_exit(chip, desc); +} + +/* Handling of all other eints */ + +static void s3c24xx_eint_ack(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct samsung_pinctrl_drv_data *d = bank->drvdata; + unsigned char index = bank->eint_offset + data->hwirq; + + writel(1UL << index, d->virt_base + EINTPEND_REG); +} + +static void s3c24xx_eint_mask(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct samsung_pinctrl_drv_data *d = bank->drvdata; + unsigned char index = bank->eint_offset + data->hwirq; + unsigned long mask; + + mask = readl(d->virt_base + EINTMASK_REG); + mask |= (1UL << index); + writel(mask, d->virt_base + EINTMASK_REG); +} + +static void s3c24xx_eint_unmask(struct irq_data *data) +{ + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); + struct samsung_pinctrl_drv_data *d = bank->drvdata; + unsigned char index = bank->eint_offset + data->hwirq; + unsigned long mask; + + mask = readl(d->virt_base + EINTMASK_REG); + mask &= ~(1UL << index); + writel(mask, d->virt_base + EINTMASK_REG); +} + +static struct irq_chip s3c24xx_eint_chip = { + .name = "s3c-eint", + .irq_ack = s3c24xx_eint_ack, + .irq_mask = s3c24xx_eint_mask, + .irq_unmask = s3c24xx_eint_unmask, + .irq_set_type = s3c24xx_eint_type, +}; + +static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc, + u32 offset, u32 range) +{ + struct irq_chip *chip = irq_get_chip(irq); + struct s3c24xx_eint_data *data = irq_get_handler_data(irq); + struct samsung_pinctrl_drv_data *d = data->drvdata; + unsigned int pend, mask; + + chained_irq_enter(chip, desc); + + pend = readl(d->virt_base + EINTPEND_REG); + mask = readl(d->virt_base + EINTMASK_REG); + + pend &= ~mask; + pend &= range; + + while (pend) { + unsigned int virq; + + irq = __ffs(pend); + pend &= ~(1 << irq); + virq = irq_linear_revmap(data->domains[irq], irq - offset); + /* Something is really wrong if an unmapped EINT is unmasked */ + BUG_ON(!virq); + + generic_handle_irq(virq); + } + + chained_irq_exit(chip, desc); +} + +static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc) +{ + s3c24xx_demux_eint(irq, desc, 0, 0xf0); +} + +static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc) +{ + s3c24xx_demux_eint(irq, desc, 8, 0xffff00); +} + +static irq_flow_handler_t s3c2410_eint_handlers[NUM_EINT_IRQ] = { + s3c2410_demux_eint0_3, + s3c2410_demux_eint0_3, + s3c2410_demux_eint0_3, + s3c2410_demux_eint0_3, + s3c24xx_demux_eint4_7, + s3c24xx_demux_eint8_23, +}; + +static irq_flow_handler_t s3c2412_eint_handlers[NUM_EINT_IRQ] = { + s3c2412_demux_eint0_3, + s3c2412_demux_eint0_3, + s3c2412_demux_eint0_3, + s3c2412_demux_eint0_3, + s3c24xx_demux_eint4_7, + s3c24xx_demux_eint8_23, +}; + +static int s3c24xx_gpf_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct s3c24xx_eint_domain_data *ddata = h->host_data; + struct samsung_pin_bank *bank = ddata->bank; + + if (!(bank->eint_mask & (1 << (bank->eint_offset + hw)))) + return -EINVAL; + + if (hw <= 3) { + if (ddata->eint0_3_parent_only) + irq_set_chip_and_handler(virq, &s3c2410_eint0_3_chip, + handle_edge_irq); + else + irq_set_chip_and_handler(virq, &s3c2412_eint0_3_chip, + handle_edge_irq); + } else { + irq_set_chip_and_handler(virq, &s3c24xx_eint_chip, + handle_edge_irq); + } + irq_set_chip_data(virq, bank); + set_irq_flags(virq, IRQF_VALID); + return 0; +} + +static const struct irq_domain_ops s3c24xx_gpf_irq_ops = { + .map = s3c24xx_gpf_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + +static int s3c24xx_gpg_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct s3c24xx_eint_domain_data *ddata = h->host_data; + struct samsung_pin_bank *bank = ddata->bank; + + if (!(bank->eint_mask & (1 << (bank->eint_offset + hw)))) + return -EINVAL; + + irq_set_chip_and_handler(virq, &s3c24xx_eint_chip, handle_edge_irq); + irq_set_chip_data(virq, bank); + set_irq_flags(virq, IRQF_VALID); + return 0; +} + +static const struct irq_domain_ops s3c24xx_gpg_irq_ops = { + .map = s3c24xx_gpg_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + +static const struct of_device_id s3c24xx_eint_irq_ids[] = { + { .compatible = "samsung,s3c2410-wakeup-eint", .data = (void *)1 }, + { .compatible = "samsung,s3c2412-wakeup-eint", .data = (void *)0 }, + { } +}; + +static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d) +{ + struct device *dev = d->dev; + const struct of_device_id *match; + struct device_node *eint_np = NULL; + struct device_node *np; + struct samsung_pin_bank *bank; + struct s3c24xx_eint_data *eint_data; + const struct irq_domain_ops *ops; + unsigned int i; + bool eint0_3_parent_only; + irq_flow_handler_t *handlers; + + for_each_child_of_node(dev->of_node, np) { + match = of_match_node(s3c24xx_eint_irq_ids, np); + if (match) { + eint_np = np; + eint0_3_parent_only = (bool)match->data; + break; + } + } + if (!eint_np) + return -ENODEV; + + eint_data = devm_kzalloc(dev, sizeof(*eint_data), GFP_KERNEL); + if (!eint_data) + return -ENOMEM; + + eint_data->drvdata = d; + + handlers = eint0_3_parent_only ? s3c2410_eint_handlers + : s3c2412_eint_handlers; + for (i = 0; i < NUM_EINT_IRQ; ++i) { + unsigned int irq; + + irq = irq_of_parse_and_map(eint_np, i); + if (!irq) { + dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i); + return -ENXIO; + } + + eint_data->parents[i] = irq; + irq_set_chained_handler(irq, handlers[i]); + irq_set_handler_data(irq, eint_data); + } + + bank = d->ctrl->pin_banks; + for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { + struct s3c24xx_eint_domain_data *ddata; + unsigned int mask; + unsigned int irq; + unsigned int pin; + + if (bank->eint_type != EINT_TYPE_WKUP) + continue; + + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + ddata->bank = bank; + ddata->eint_data = eint_data; + ddata->eint0_3_parent_only = eint0_3_parent_only; + + ops = (bank->eint_offset == 0) ? &s3c24xx_gpf_irq_ops + : &s3c24xx_gpg_irq_ops; + + bank->irq_domain = irq_domain_add_linear(bank->of_node, + bank->nr_pins, ops, ddata); + if (!bank->irq_domain) { + dev_err(dev, "wkup irq domain add failed\n"); + return -ENXIO; + } + + irq = bank->eint_offset; + mask = bank->eint_mask; + for (pin = 0; mask; ++pin, mask >>= 1) { + if (irq > NUM_EINT) + break; + if (!(mask & 1)) + continue; + eint_data->domains[irq] = bank->irq_domain; + ++irq; + } + } + + return 0; +} + +static struct samsung_pin_bank s3c2412_pin_banks[] = { + PIN_BANK_A(23, 0x000, "gpa"), + PIN_BANK_2BIT(11, 0x010, "gpb"), + PIN_BANK_2BIT(16, 0x020, "gpc"), + PIN_BANK_2BIT(16, 0x030, "gpd"), + PIN_BANK_2BIT(16, 0x040, "gpe"), + PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff), + PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00), + PIN_BANK_2BIT(11, 0x070, "gph"), + PIN_BANK_2BIT(13, 0x080, "gpj"), +}; + +struct samsung_pin_ctrl s3c2412_pin_ctrl[] = { + { + .pin_banks = s3c2412_pin_banks, + .nr_banks = ARRAY_SIZE(s3c2412_pin_banks), + .eint_wkup_init = s3c24xx_eint_init, + .label = "S3C2412-GPIO", + }, +}; + +static struct samsung_pin_bank s3c2416_pin_banks[] = { + PIN_BANK_A(27, 0x000, "gpa"), + PIN_BANK_2BIT(11, 0x010, "gpb"), + PIN_BANK_2BIT(16, 0x020, "gpc"), + PIN_BANK_2BIT(16, 0x030, "gpd"), + PIN_BANK_2BIT(16, 0x040, "gpe"), + PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff), + PIN_BANK_2BIT_EINTW(8, 0x060, "gpg", 8, 0xff00), + PIN_BANK_2BIT(15, 0x070, "gph"), + PIN_BANK_2BIT(16, 0x0e0, "gpk"), + PIN_BANK_2BIT(14, 0x0f0, "gpl"), + PIN_BANK_2BIT(2, 0x100, "gpm"), +}; + +struct samsung_pin_ctrl s3c2416_pin_ctrl[] = { + { + .pin_banks = s3c2416_pin_banks, + .nr_banks = ARRAY_SIZE(s3c2416_pin_banks), + .eint_wkup_init = s3c24xx_eint_init, + .label = "S3C2416-GPIO", + }, +}; + +static struct samsung_pin_bank s3c2440_pin_banks[] = { + PIN_BANK_A(25, 0x000, "gpa"), + PIN_BANK_2BIT(11, 0x010, "gpb"), + PIN_BANK_2BIT(16, 0x020, "gpc"), + PIN_BANK_2BIT(16, 0x030, "gpd"), + PIN_BANK_2BIT(16, 0x040, "gpe"), + PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff), + PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00), + PIN_BANK_2BIT(11, 0x070, "gph"), + PIN_BANK_2BIT(13, 0x0d0, "gpj"), +}; + +struct samsung_pin_ctrl s3c2440_pin_ctrl[] = { + { + .pin_banks = s3c2440_pin_banks, + .nr_banks = ARRAY_SIZE(s3c2440_pin_banks), + .eint_wkup_init = s3c24xx_eint_init, + .label = "S3C2440-GPIO", + }, +}; + +static struct samsung_pin_bank s3c2450_pin_banks[] = { + PIN_BANK_A(28, 0x000, "gpa"), + PIN_BANK_2BIT(11, 0x010, "gpb"), + PIN_BANK_2BIT(16, 0x020, "gpc"), + PIN_BANK_2BIT(16, 0x030, "gpd"), + PIN_BANK_2BIT(16, 0x040, "gpe"), + PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff), + PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00), + PIN_BANK_2BIT(15, 0x070, "gph"), + PIN_BANK_2BIT(16, 0x0d0, "gpj"), + PIN_BANK_2BIT(16, 0x0e0, "gpk"), + PIN_BANK_2BIT(15, 0x0f0, "gpl"), + PIN_BANK_2BIT(2, 0x100, "gpm"), +}; + +struct samsung_pin_ctrl s3c2450_pin_ctrl[] = { + { + .pin_banks = s3c2450_pin_banks, + .nr_banks = ARRAY_SIZE(s3c2450_pin_banks), + .eint_wkup_init = s3c24xx_eint_init, + .label = "S3C2450-GPIO", + }, +}; diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 63ac22e8967..e67ff1b8042 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -1118,6 +1118,16 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { { .compatible = "samsung,s3c64xx-pinctrl", .data = s3c64xx_pin_ctrl }, #endif +#ifdef CONFIG_PINCTRL_S3C24XX + { .compatible = "samsung,s3c2412-pinctrl", + .data = s3c2412_pin_ctrl }, + { .compatible = "samsung,s3c2416-pinctrl", + .data = s3c2416_pin_ctrl }, + { .compatible = "samsung,s3c2440-pinctrl", + .data = s3c2440_pin_ctrl }, + { .compatible = "samsung,s3c2450-pinctrl", + .data = s3c2450_pin_ctrl }, +#endif {}, }; MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index 26d3519240c..79fcc2076c0 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -255,5 +255,9 @@ extern struct samsung_pin_ctrl exynos4210_pin_ctrl[]; extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[]; extern struct samsung_pin_ctrl exynos5250_pin_ctrl[]; extern struct samsung_pin_ctrl s3c64xx_pin_ctrl[]; +extern struct samsung_pin_ctrl s3c2412_pin_ctrl[]; +extern struct samsung_pin_ctrl s3c2416_pin_ctrl[]; +extern struct samsung_pin_ctrl s3c2440_pin_ctrl[]; +extern struct samsung_pin_ctrl s3c2450_pin_ctrl[]; #endif /* __PINCTRL_SAMSUNG_H */ diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c index bbff5596e92..82bf6aba007 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c @@ -1488,6 +1488,66 @@ IRQC_PINS_MUX(326, 54); IRQC_PINS_MUX(327, 55); IRQC_PINS_MUX(328, 56); IRQC_PINS_MUX(329, 57); +/* - MMCIF0 ----------------------------------------------------------------- */ +static const unsigned int mmc0_data1_pins[] = { + /* D[0] */ + 164, +}; +static const unsigned int mmc0_data1_mux[] = { + MMCD0_0_MARK, +}; +static const unsigned int mmc0_data4_pins[] = { + /* D[0:3] */ + 164, 165, 166, 167, +}; +static const unsigned int mmc0_data4_mux[] = { + MMCD0_0_MARK, MMCD0_1_MARK, MMCD0_2_MARK, MMCD0_3_MARK, +}; +static const unsigned int mmc0_data8_pins[] = { + /* D[0:7] */ + 164, 165, 166, 167, 168, 169, 170, 171, +}; +static const unsigned int mmc0_data8_mux[] = { + MMCD0_0_MARK, MMCD0_1_MARK, MMCD0_2_MARK, MMCD0_3_MARK, + MMCD0_4_MARK, MMCD0_5_MARK, MMCD0_6_MARK, MMCD0_7_MARK, +}; +static const unsigned int mmc0_ctrl_pins[] = { + /* CMD, CLK */ + 172, 173, +}; +static const unsigned int mmc0_ctrl_mux[] = { + MMCCMD0_MARK, MMCCLK0_MARK, +}; +/* - MMCIF1 ----------------------------------------------------------------- */ +static const unsigned int mmc1_data1_pins[] = { + /* D[0] */ + 199, +}; +static const unsigned int mmc1_data1_mux[] = { + MMCD1_0_MARK, +}; +static const unsigned int mmc1_data4_pins[] = { + /* D[0:3] */ + 199, 198, 197, 196, +}; +static const unsigned int mmc1_data4_mux[] = { + MMCD1_0_MARK, MMCD1_1_MARK, MMCD1_2_MARK, MMCD1_3_MARK, +}; +static const unsigned int mmc1_data8_pins[] = { + /* D[0:7] */ + 199, 198, 197, 196, 195, 194, 193, 192, +}; +static const unsigned int mmc1_data8_mux[] = { + MMCD1_0_MARK, MMCD1_1_MARK, MMCD1_2_MARK, MMCD1_3_MARK, + MMCD1_4_MARK, MMCD1_5_MARK, MMCD1_6_MARK, MMCD1_7_MARK, +}; +static const unsigned int mmc1_ctrl_pins[] = { + /* CMD, CLK */ + 200, 203, +}; +static const unsigned int mmc1_ctrl_mux[] = { + MMCCMD1_MARK, MMCCLK1_MARK, +}; /* - SCIFA0 ----------------------------------------------------------------- */ static const unsigned int scifa0_data_pins[] = { /* SCIFA0_RXD, SCIFA0_TXD */ @@ -1683,6 +1743,86 @@ static const unsigned int scifb3_ctrl_b_pins[] = { static const unsigned int scifb3_ctrl_b_mux[] = { SCIFB3_RTS_38_MARK, SCIFB3_CTS_39_MARK, }; +/* - SDHI0 ------------------------------------------------------------------ */ +static const unsigned int sdhi0_data1_pins[] = { + /* D0 */ + 302, +}; +static const unsigned int sdhi0_data1_mux[] = { + SDHID0_0_MARK, +}; +static const unsigned int sdhi0_data4_pins[] = { + /* D[0:3] */ + 302, 303, 304, 305, +}; +static const unsigned int sdhi0_data4_mux[] = { + SDHID0_0_MARK, SDHID0_1_MARK, SDHID0_2_MARK, SDHID0_3_MARK, +}; +static const unsigned int sdhi0_ctrl_pins[] = { + /* CLK, CMD */ + 308, 306, +}; +static const unsigned int sdhi0_ctrl_mux[] = { + SDHICLK0_MARK, SDHICMD0_MARK, +}; +static const unsigned int sdhi0_cd_pins[] = { + /* CD */ + 301, +}; +static const unsigned int sdhi0_cd_mux[] = { + SDHICD0_MARK, +}; +static const unsigned int sdhi0_wp_pins[] = { + /* WP */ + 307, +}; +static const unsigned int sdhi0_wp_mux[] = { + SDHIWP0_MARK, +}; +/* - SDHI1 ------------------------------------------------------------------ */ +static const unsigned int sdhi1_data1_pins[] = { + /* D0 */ + 289, +}; +static const unsigned int sdhi1_data1_mux[] = { + SDHID1_0_MARK, +}; +static const unsigned int sdhi1_data4_pins[] = { + /* D[0:3] */ + 289, 290, 291, 292, +}; +static const unsigned int sdhi1_data4_mux[] = { + SDHID1_0_MARK, SDHID1_1_MARK, SDHID1_2_MARK, SDHID1_3_MARK, +}; +static const unsigned int sdhi1_ctrl_pins[] = { + /* CLK, CMD */ + 293, 294, +}; +static const unsigned int sdhi1_ctrl_mux[] = { + SDHICLK1_MARK, SDHICMD1_MARK, +}; +/* - SDHI2 ------------------------------------------------------------------ */ +static const unsigned int sdhi2_data1_pins[] = { + /* D0 */ + 295, +}; +static const unsigned int sdhi2_data1_mux[] = { + SDHID2_0_MARK, +}; +static const unsigned int sdhi2_data4_pins[] = { + /* D[0:3] */ + 295, 296, 297, 298, +}; +static const unsigned int sdhi2_data4_mux[] = { + SDHID2_0_MARK, SDHID2_1_MARK, SDHID2_2_MARK, SDHID2_3_MARK, +}; +static const unsigned int sdhi2_ctrl_pins[] = { + /* CLK, CMD */ + 299, 300, +}; +static const unsigned int sdhi2_ctrl_mux[] = { + SDHICLK2_MARK, SDHICMD2_MARK, +}; static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(irqc_irq0), @@ -1743,6 +1883,14 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(irqc_irq55), SH_PFC_PIN_GROUP(irqc_irq56), SH_PFC_PIN_GROUP(irqc_irq57), + SH_PFC_PIN_GROUP(mmc0_data1), + SH_PFC_PIN_GROUP(mmc0_data4), + SH_PFC_PIN_GROUP(mmc0_data8), + SH_PFC_PIN_GROUP(mmc0_ctrl), + SH_PFC_PIN_GROUP(mmc1_data1), + SH_PFC_PIN_GROUP(mmc1_data4), + SH_PFC_PIN_GROUP(mmc1_data8), + SH_PFC_PIN_GROUP(mmc1_ctrl), SH_PFC_PIN_GROUP(scifa0_data), SH_PFC_PIN_GROUP(scifa0_clk), SH_PFC_PIN_GROUP(scifa0_ctrl), @@ -1770,6 +1918,17 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(scifb3_data_b), SH_PFC_PIN_GROUP(scifb3_clk_b), SH_PFC_PIN_GROUP(scifb3_ctrl_b), + SH_PFC_PIN_GROUP(sdhi0_data1), + SH_PFC_PIN_GROUP(sdhi0_data4), + SH_PFC_PIN_GROUP(sdhi0_ctrl), + SH_PFC_PIN_GROUP(sdhi0_cd), + SH_PFC_PIN_GROUP(sdhi0_wp), + SH_PFC_PIN_GROUP(sdhi1_data1), + SH_PFC_PIN_GROUP(sdhi1_data4), + SH_PFC_PIN_GROUP(sdhi1_ctrl), + SH_PFC_PIN_GROUP(sdhi2_data1), + SH_PFC_PIN_GROUP(sdhi2_data4), + SH_PFC_PIN_GROUP(sdhi2_ctrl), }; static const char * const irqc_groups[] = { @@ -1833,6 +1992,20 @@ static const char * const irqc_groups[] = { "irqc_irq57", }; +static const char * const mmc0_groups[] = { + "mmc0_data1", + "mmc0_data4", + "mmc0_data8", + "mmc0_ctrl", +}; + +static const char * const mmc1_groups[] = { + "mmc1_data1", + "mmc1_data4", + "mmc1_data8", + "mmc1_ctrl", +}; + static const char * const scifa0_groups[] = { "scifa0_data", "scifa0_clk", @@ -1878,14 +2051,39 @@ static const char * const scifb3_groups[] = { "scifb3_ctrl_b", }; +static const char * const sdhi0_groups[] = { + "sdhi0_data1", + "sdhi0_data4", + "sdhi0_ctrl", + "sdhi0_cd", + "sdhi0_wp", +}; + +static const char * const sdhi1_groups[] = { + "sdhi1_data1", + "sdhi1_data4", + "sdhi1_ctrl", +}; + +static const char * const sdhi2_groups[] = { + "sdhi2_data1", + "sdhi2_data4", + "sdhi2_ctrl", +}; + static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(irqc), + SH_PFC_FUNCTION(mmc0), + SH_PFC_FUNCTION(mmc1), SH_PFC_FUNCTION(scifa0), SH_PFC_FUNCTION(scifa1), SH_PFC_FUNCTION(scifb0), SH_PFC_FUNCTION(scifb1), SH_PFC_FUNCTION(scifb2), SH_PFC_FUNCTION(scifb3), + SH_PFC_FUNCTION(sdhi0), + SH_PFC_FUNCTION(sdhi1), + SH_PFC_FUNCTION(sdhi2), }; #undef PORTCR diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c index 1dcbabcd7b3..f9039102bb4 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c @@ -1447,11 +1447,11 @@ MMC_PFC_PINS(mmc_ctrl, RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6)); MMC_PFC_CTRL(mmc_ctrl, MMC_CLK, MMC_CMD); MMC_PFC_PINS(mmc_data1, RCAR_GP_PIN(1, 7)); MMC_PFC_DAT1(mmc_data1, MMC_D0); -MMC_PFC_PINS(mmc_data4, RCAR_GP_PIN(1, 7), RCAR_GP_PIN(2, 8), +MMC_PFC_PINS(mmc_data4, RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 8), RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 6)); MMC_PFC_DAT4(mmc_data4, MMC_D0, MMC_D1, MMC_D2, MMC_D3); -MMC_PFC_PINS(mmc_data8, RCAR_GP_PIN(1, 7), RCAR_GP_PIN(2, 8), +MMC_PFC_PINS(mmc_data8, RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 8), RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 6), RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 0), RCAR_GP_PIN(0, 30), RCAR_GP_PIN(0, 31)); diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 85d77a417c0..14f3ec267e1 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -1979,6 +1979,141 @@ static const unsigned int scif1_clk_e_pins[] = { static const unsigned int scif1_clk_e_mux[] = { SCK1_E_MARK, }; +/* - HSCIF0 ----------------------------------------------------------------- */ +static const unsigned int hscif0_data_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 9), +}; +static const unsigned int hscif0_data_mux[] = { + HRX0_MARK, HTX0_MARK, +}; +static const unsigned int hscif0_clk_pins[] = { + /* SCK */ + RCAR_GP_PIN(5, 7), +}; +static const unsigned int hscif0_clk_mux[] = { + HSCK0_MARK, +}; +static const unsigned int hscif0_ctrl_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 10), +}; +static const unsigned int hscif0_ctrl_mux[] = { + HRTS0_N_MARK, HCTS0_N_MARK, +}; +static const unsigned int hscif0_data_b_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 12), +}; +static const unsigned int hscif0_data_b_mux[] = { + HRX0_B_MARK, HTX0_B_MARK, +}; +static const unsigned int hscif0_ctrl_b_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(1, 29), RCAR_GP_PIN(1, 28), +}; +static const unsigned int hscif0_ctrl_b_mux[] = { + HRTS0_N_B_MARK, HCTS0_N_B_MARK, +}; +static const unsigned int hscif0_data_c_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 16), +}; +static const unsigned int hscif0_data_c_mux[] = { + HRX0_C_MARK, HTX0_C_MARK, +}; +static const unsigned int hscif0_ctrl_c_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 7), +}; +static const unsigned int hscif0_ctrl_c_mux[] = { + HRTS0_N_C_MARK, HCTS0_N_C_MARK, +}; +static const unsigned int hscif0_data_d_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 21), +}; +static const unsigned int hscif0_data_d_mux[] = { + HRX0_D_MARK, HTX0_D_MARK, +}; +static const unsigned int hscif0_ctrl_d_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(3, 23), RCAR_GP_PIN(3, 22), +}; +static const unsigned int hscif0_ctrl_d_mux[] = { + HRTS0_N_D_MARK, HCTS0_N_D_MARK, +}; +static const unsigned int hscif0_data_e_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(2, 21), RCAR_GP_PIN(2, 22), +}; +static const unsigned int hscif0_data_e_mux[] = { + HRX0_E_MARK, HTX0_E_MARK, +}; +static const unsigned int hscif0_ctrl_e_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(2, 24), RCAR_GP_PIN(2, 23), +}; +static const unsigned int hscif0_ctrl_e_mux[] = { + HRTS0_N_E_MARK, HCTS0_N_E_MARK, +}; +static const unsigned int hscif0_data_f_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 25), +}; +static const unsigned int hscif0_data_f_mux[] = { + HRX0_F_MARK, HTX0_F_MARK, +}; +static const unsigned int hscif0_ctrl_f_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(2, 26), RCAR_GP_PIN(2, 24), +}; +static const unsigned int hscif0_ctrl_f_mux[] = { + HRTS0_N_F_MARK, HCTS0_N_F_MARK, +}; +/* - HSCIF1 ----------------------------------------------------------------- */ +static const unsigned int hscif1_data_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 29), +}; +static const unsigned int hscif1_data_mux[] = { + HRX1_MARK, HTX1_MARK, +}; +static const unsigned int hscif1_clk_pins[] = { + /* SCK */ + RCAR_GP_PIN(4, 27), +}; +static const unsigned int hscif1_clk_mux[] = { + HSCK1_MARK, +}; +static const unsigned int hscif1_ctrl_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(4, 31), RCAR_GP_PIN(4, 30), +}; +static const unsigned int hscif1_ctrl_mux[] = { + HRTS1_N_MARK, HCTS1_N_MARK, +}; +static const unsigned int hscif1_data_b_pins[] = { + /* RX, TX */ + RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 18), +}; +static const unsigned int hscif1_data_b_mux[] = { + HRX1_B_MARK, HTX1_B_MARK, +}; +static const unsigned int hscif1_clk_b_pins[] = { + /* SCK */ + RCAR_GP_PIN(1, 28), +}; +static const unsigned int hscif1_clk_b_mux[] = { + HSCK1_B_MARK, +}; +static const unsigned int hscif1_ctrl_b_pins[] = { + /* RTS, CTS */ + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13), +}; +static const unsigned int hscif1_ctrl_b_mux[] = { + HRTS1_N_B_MARK, HCTS1_N_B_MARK, +}; /* - SCIFA0 ----------------------------------------------------------------- */ static const unsigned int scifa0_data_pins[] = { /* RXD, TXD */ @@ -2371,8 +2506,7 @@ static const unsigned int tpu0_to3_pins[] = { static const unsigned int tpu0_to3_mux[] = { TPU0TO3_MARK, }; - -/* - MMCIF ------------------------------------------------------------------ */ +/* - MMCIF0 ----------------------------------------------------------------- */ static const unsigned int mmc0_data1_pins[] = { /* D[0] */ RCAR_GP_PIN(3, 18), @@ -2406,7 +2540,7 @@ static const unsigned int mmc0_ctrl_pins[] = { static const unsigned int mmc0_ctrl_mux[] = { MMC0_CLK_MARK, MMC0_CMD_MARK, }; - +/* - MMCIF1 ----------------------------------------------------------------- */ static const unsigned int mmc1_data1_pins[] = { /* D[0] */ RCAR_GP_PIN(3, 26), @@ -2427,7 +2561,7 @@ static const unsigned int mmc1_data8_pins[] = { RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 27), RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 30), RCAR_GP_PIN(3, 31), - RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14), + RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), }; static const unsigned int mmc1_data8_mux[] = { MMC1_D0_MARK, MMC1_D1_MARK, MMC1_D2_MARK, MMC1_D3_MARK, @@ -2440,8 +2574,7 @@ static const unsigned int mmc1_ctrl_pins[] = { static const unsigned int mmc1_ctrl_mux[] = { MMC1_CLK_MARK, MMC1_CMD_MARK, }; - -/* - SDHI ------------------------------------------------------------------- */ +/* - SDHI0 ------------------------------------------------------------------ */ static const unsigned int sdhi0_data1_pins[] = { /* D0 */ RCAR_GP_PIN(3, 2), @@ -2477,7 +2610,7 @@ static const unsigned int sdhi0_wp_pins[] = { static const unsigned int sdhi0_wp_mux[] = { SD0_WP_MARK, }; - +/* - SDHI1 ------------------------------------------------------------------ */ static const unsigned int sdhi1_data1_pins[] = { /* D0 */ RCAR_GP_PIN(3, 10), @@ -2513,7 +2646,7 @@ static const unsigned int sdhi1_wp_pins[] = { static const unsigned int sdhi1_wp_mux[] = { SD1_WP_MARK, }; - +/* - SDHI2 ------------------------------------------------------------------ */ static const unsigned int sdhi2_data1_pins[] = { /* D0 */ RCAR_GP_PIN(3, 18), @@ -2549,7 +2682,7 @@ static const unsigned int sdhi2_wp_pins[] = { static const unsigned int sdhi2_wp_mux[] = { SD2_WP_MARK, }; - +/* - SDHI3 ------------------------------------------------------------------ */ static const unsigned int sdhi3_data1_pins[] = { /* D0 */ RCAR_GP_PIN(3, 26), @@ -2591,10 +2724,37 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(eth_magic), SH_PFC_PIN_GROUP(eth_mdio), SH_PFC_PIN_GROUP(eth_rmii), + SH_PFC_PIN_GROUP(hscif0_data), + SH_PFC_PIN_GROUP(hscif0_clk), + SH_PFC_PIN_GROUP(hscif0_ctrl), + SH_PFC_PIN_GROUP(hscif0_data_b), + SH_PFC_PIN_GROUP(hscif0_ctrl_b), + SH_PFC_PIN_GROUP(hscif0_data_c), + SH_PFC_PIN_GROUP(hscif0_ctrl_c), + SH_PFC_PIN_GROUP(hscif0_data_d), + SH_PFC_PIN_GROUP(hscif0_ctrl_d), + SH_PFC_PIN_GROUP(hscif0_data_e), + SH_PFC_PIN_GROUP(hscif0_ctrl_e), + SH_PFC_PIN_GROUP(hscif0_data_f), + SH_PFC_PIN_GROUP(hscif0_ctrl_f), + SH_PFC_PIN_GROUP(hscif1_data), + SH_PFC_PIN_GROUP(hscif1_clk), + SH_PFC_PIN_GROUP(hscif1_ctrl), + SH_PFC_PIN_GROUP(hscif1_data_b), + SH_PFC_PIN_GROUP(hscif1_clk_b), + SH_PFC_PIN_GROUP(hscif1_ctrl_b), SH_PFC_PIN_GROUP(intc_irq0), SH_PFC_PIN_GROUP(intc_irq1), SH_PFC_PIN_GROUP(intc_irq2), SH_PFC_PIN_GROUP(intc_irq3), + SH_PFC_PIN_GROUP(mmc0_data1), + SH_PFC_PIN_GROUP(mmc0_data4), + SH_PFC_PIN_GROUP(mmc0_data8), + SH_PFC_PIN_GROUP(mmc0_ctrl), + SH_PFC_PIN_GROUP(mmc1_data1), + SH_PFC_PIN_GROUP(mmc1_data4), + SH_PFC_PIN_GROUP(mmc1_data8), + SH_PFC_PIN_GROUP(mmc1_ctrl), SH_PFC_PIN_GROUP(scif0_data), SH_PFC_PIN_GROUP(scif0_clk), SH_PFC_PIN_GROUP(scif0_ctrl), @@ -2659,18 +2819,6 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(scifb2_clk_b), SH_PFC_PIN_GROUP(scifb2_ctrl_b), SH_PFC_PIN_GROUP(scifb2_data_c), - SH_PFC_PIN_GROUP(tpu0_to0), - SH_PFC_PIN_GROUP(tpu0_to1), - SH_PFC_PIN_GROUP(tpu0_to2), - SH_PFC_PIN_GROUP(tpu0_to3), - SH_PFC_PIN_GROUP(mmc0_data1), - SH_PFC_PIN_GROUP(mmc0_data4), - SH_PFC_PIN_GROUP(mmc0_data8), - SH_PFC_PIN_GROUP(mmc0_ctrl), - SH_PFC_PIN_GROUP(mmc1_data1), - SH_PFC_PIN_GROUP(mmc1_data4), - SH_PFC_PIN_GROUP(mmc1_data8), - SH_PFC_PIN_GROUP(mmc1_ctrl), SH_PFC_PIN_GROUP(sdhi0_data1), SH_PFC_PIN_GROUP(sdhi0_data4), SH_PFC_PIN_GROUP(sdhi0_ctrl), @@ -2691,6 +2839,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi3_ctrl), SH_PFC_PIN_GROUP(sdhi3_cd), SH_PFC_PIN_GROUP(sdhi3_wp), + SH_PFC_PIN_GROUP(tpu0_to0), + SH_PFC_PIN_GROUP(tpu0_to1), + SH_PFC_PIN_GROUP(tpu0_to2), + SH_PFC_PIN_GROUP(tpu0_to3), }; static const char * const eth_groups[] = { @@ -2726,6 +2878,31 @@ static const char * const scif1_groups[] = { "scif1_clk_e", }; +static const char * const hscif0_groups[] = { + "hscif0_data", + "hscif0_clk", + "hscif0_ctrl", + "hscif0_data_b", + "hscif0_ctrl_b", + "hscif0_data_c", + "hscif0_ctrl_c", + "hscif0_data_d", + "hscif0_ctrl_d", + "hscif0_data_e", + "hscif0_ctrl_e", + "hscif0_data_f", + "hscif0_ctrl_f", +}; + +static const char * const hscif1_groups[] = { + "hscif1_data", + "hscif1_clk", + "hscif1_ctrl", + "hscif1_data_b", + "hscif1_clk_b", + "hscif1_ctrl_b", +}; + static const char * const scifa0_groups[] = { "scifa0_data", "scifa0_clk", @@ -2850,7 +3027,11 @@ static const char * const sdhi3_groups[] = { static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(eth), + SH_PFC_FUNCTION(hscif0), + SH_PFC_FUNCTION(hscif1), SH_PFC_FUNCTION(intc), + SH_PFC_FUNCTION(mmc0), + SH_PFC_FUNCTION(mmc1), SH_PFC_FUNCTION(scif0), SH_PFC_FUNCTION(scif1), SH_PFC_FUNCTION(scifa0), @@ -2859,13 +3040,11 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(scifb0), SH_PFC_FUNCTION(scifb1), SH_PFC_FUNCTION(scifb2), - SH_PFC_FUNCTION(tpu0), - SH_PFC_FUNCTION(mmc0), - SH_PFC_FUNCTION(mmc1), SH_PFC_FUNCTION(sdhi0), SH_PFC_FUNCTION(sdhi1), SH_PFC_FUNCTION(sdhi2), SH_PFC_FUNCTION(sdhi3), + SH_PFC_FUNCTION(tpu0), }; static struct pinmux_cfg_reg pinmux_config_regs[] = { diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index d4d377c40ec..ce1743d0b67 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -14,8 +14,9 @@ config OMAP_REMOTEPROC depends on HAS_DMA depends on ARCH_OMAP4 || SOC_OMAP5 depends on OMAP_IOMMU - depends on OMAP_MBOX_FWK select REMOTEPROC + select MAILBOX + select OMAP2PLUS_MBOX select RPMSG help Say y here to support OMAP's remote processors (dual M3 diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 0e396c155b3..51689721ea7 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -27,8 +27,8 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/remoteproc.h> +#include <linux/omap-mailbox.h> -#include <plat/mailbox.h> #include <linux/platform_data/remoteproc-omap.h> #include "omap_remoteproc.h" diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig index 60848f198b4..165b918b817 100644 --- a/drivers/staging/tidspbridge/Kconfig +++ b/drivers/staging/tidspbridge/Kconfig @@ -5,7 +5,8 @@ menuconfig TIDSPBRIDGE tristate "DSP Bridge driver" depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM - select OMAP_MBOX_FWK + select MAILBOX + select OMAP2PLUS_MBOX help DSP/BIOS Bridge is designed for platforms that contain a GPP and one or more attached DSPs. The GPP is considered the master or diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h index 7f3a1db3161..d1441db469f 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h +++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h @@ -41,7 +41,7 @@ #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/clk.h> -#include <plat/mailbox.h> +#include <linux/omap-mailbox.h> #include <linux/pagemap.h> #include <asm/cacheflush.h> #include <linux/dma-mapping.h> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 01b8229fa86..62f6802f6e0 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -155,7 +155,7 @@ config USB_LPC32XX config USB_ATMEL_USBA tristate "Atmel USBA" - depends on AVR32 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 + depends on AVR32 || ARCH_AT91 help USBA is the integrated high-speed USB Device controller on the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel. diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 5a5128a226f..1d9722203ca 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -22,15 +22,13 @@ #include <linux/usb/atmel_usba_udc.h> #include <linux/delay.h> #include <linux/platform_data/atmel.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #include <asm/gpio.h> #include "atmel_usba_udc.h" - -static struct usba_udc the_udc; -static struct usba_ep *usba_ep; - #ifdef CONFIG_USB_GADGET_DEBUG_FS #include <linux/debugfs.h> #include <linux/uaccess.h> @@ -1014,16 +1012,13 @@ static void nop_release(struct device *dev) } -static struct usba_udc the_udc = { - .gadget = { - .ops = &usba_udc_ops, - .ep_list = LIST_HEAD_INIT(the_udc.gadget.ep_list), - .max_speed = USB_SPEED_HIGH, - .name = "atmel_usba_udc", - .dev = { - .init_name = "gadget", - .release = nop_release, - }, +struct usb_gadget usba_gadget_template = { + .ops = &usba_udc_ops, + .max_speed = USB_SPEED_HIGH, + .name = "atmel_usba_udc", + .dev = { + .init_name = "gadget", + .release = nop_release, }, }; @@ -1147,7 +1142,7 @@ static int do_test_mode(struct usba_udc *udc) * Test_SE0_NAK: Force high-speed mode and set up ep0 * for Bulk IN transfers */ - ep = &usba_ep[0]; + ep = &udc->usba_ep[0]; usba_writel(udc, TST, USBA_BF(SPEED_CFG, USBA_SPEED_CFG_FORCE_HIGH)); usba_ep_writel(ep, CFG, @@ -1165,7 +1160,7 @@ static int do_test_mode(struct usba_udc *udc) break; case 0x0400: /* Test_Packet */ - ep = &usba_ep[0]; + ep = &udc->usba_ep[0]; usba_ep_writel(ep, CFG, USBA_BF(EPT_SIZE, USBA_EPT_SIZE_64) | USBA_EPT_DIR_IN @@ -1668,7 +1663,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) for (i = 1; i < USBA_NR_ENDPOINTS; i++) if (dma_status & (1 << i)) - usba_dma_irq(udc, &usba_ep[i]); + usba_dma_irq(udc, &udc->usba_ep[i]); } ep_status = USBA_BFEXT(EPT_INT, status); @@ -1677,10 +1672,10 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) for (i = 0; i < USBA_NR_ENDPOINTS; i++) if (ep_status & (1 << i)) { - if (ep_is_control(&usba_ep[i])) - usba_control_irq(udc, &usba_ep[i]); + if (ep_is_control(&udc->usba_ep[i])) + usba_control_irq(udc, &udc->usba_ep[i]); else - usba_ep_irq(udc, &usba_ep[i]); + usba_ep_irq(udc, &udc->usba_ep[i]); } } @@ -1705,7 +1700,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) DBG(DBG_BUS, "%s bus reset detected\n", usb_speed_string(udc->gadget.speed)); - ep0 = &usba_ep[0]; + ep0 = &udc->usba_ep[0]; ep0->ep.desc = &usba_ep0_desc; ep0->state = WAIT_FOR_SETUP; usba_ep_writel(ep0, CFG, @@ -1835,17 +1830,158 @@ static int atmel_usba_stop(struct usb_gadget *gadget, return 0; } -static int __init usba_udc_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, + struct usba_udc *udc) +{ + u32 val; + const char *name; + enum of_gpio_flags flags; + struct device_node *np = pdev->dev.of_node; + struct device_node *pp; + int i, ret; + struct usba_ep *eps, *ep; + + udc->num_ep = 0; + + udc->vbus_pin = of_get_named_gpio_flags(np, "atmel,vbus-gpio", 0, + &flags); + udc->vbus_pin_inverted = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0; + + pp = NULL; + while ((pp = of_get_next_child(np, pp))) + udc->num_ep++; + + eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep, + GFP_KERNEL); + if (!eps) + return ERR_PTR(-ENOMEM); + + udc->gadget.ep0 = &eps[0].ep; + + INIT_LIST_HEAD(&eps[0].ep.ep_list); + + pp = NULL; + i = 0; + while ((pp = of_get_next_child(np, pp))) { + ep = &eps[i]; + + ret = of_property_read_u32(pp, "reg", &val); + if (ret) { + dev_err(&pdev->dev, "of_probe: reg error(%d)\n", ret); + goto err; + } + ep->index = val; + + ret = of_property_read_u32(pp, "atmel,fifo-size", &val); + if (ret) { + dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret); + goto err; + } + ep->fifo_size = val; + + ret = of_property_read_u32(pp, "atmel,nb-banks", &val); + if (ret) { + dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret); + goto err; + } + ep->nr_banks = val; + + ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); + ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); + + ret = of_property_read_string(pp, "name", &name); + ep->ep.name = name; + + ep->ep_regs = udc->regs + USBA_EPT_BASE(i); + ep->dma_regs = udc->regs + USBA_DMA_BASE(i); + ep->fifo = udc->fifo + USBA_FIFO_BASE(i); + ep->ep.ops = &usba_ep_ops; + ep->ep.maxpacket = ep->fifo_size; + ep->udc = udc; + INIT_LIST_HEAD(&ep->queue); + + if (i) + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + + i++; + } + + return eps; +err: + return ERR_PTR(ret); +} +#else +static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, + struct usba_udc *udc) +{ + return ERR_PTR(-ENOSYS); +} +#endif + +static struct usba_ep * usba_udc_pdata(struct platform_device *pdev, + struct usba_udc *udc) { struct usba_platform_data *pdata = pdev->dev.platform_data; + struct usba_ep *eps; + int i; + + if (!pdata) + return ERR_PTR(-ENXIO); + + eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * pdata->num_ep, + GFP_KERNEL); + if (!eps) + return ERR_PTR(-ENOMEM); + + udc->gadget.ep0 = &eps[0].ep; + + udc->vbus_pin = pdata->vbus_pin; + udc->vbus_pin_inverted = pdata->vbus_pin_inverted; + udc->num_ep = pdata->num_ep; + + INIT_LIST_HEAD(&eps[0].ep.ep_list); + + for (i = 0; i < pdata->num_ep; i++) { + struct usba_ep *ep = &eps[i]; + + ep->ep_regs = udc->regs + USBA_EPT_BASE(i); + ep->dma_regs = udc->regs + USBA_DMA_BASE(i); + ep->fifo = udc->fifo + USBA_FIFO_BASE(i); + ep->ep.ops = &usba_ep_ops; + ep->ep.name = pdata->ep[i].name; + ep->fifo_size = ep->ep.maxpacket = pdata->ep[i].fifo_size; + ep->udc = udc; + INIT_LIST_HEAD(&ep->queue); + ep->nr_banks = pdata->ep[i].nr_banks; + ep->index = pdata->ep[i].index; + ep->can_dma = pdata->ep[i].can_dma; + ep->can_isoc = pdata->ep[i].can_isoc; + + if (i) + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + } + + return eps; +} + +static int __init usba_udc_probe(struct platform_device *pdev) +{ struct resource *regs, *fifo; struct clk *pclk, *hclk; - struct usba_udc *udc = &the_udc; + struct usba_udc *udc; int irq, ret, i; + udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL); + if (!udc) + return -ENOMEM; + + udc->gadget = usba_gadget_template; + INIT_LIST_HEAD(&udc->gadget.ep_list); + regs = platform_get_resource(pdev, IORESOURCE_MEM, CTRL_IOMEM_ID); fifo = platform_get_resource(pdev, IORESOURCE_MEM, FIFO_IOMEM_ID); - if (!regs || !fifo || !pdata) + if (!regs || !fifo) return -ENXIO; irq = platform_get_irq(pdev, 0); @@ -1891,46 +2027,14 @@ static int __init usba_udc_probe(struct platform_device *pdev) usba_writel(udc, CTRL, USBA_DISABLE_MASK); clk_disable(pclk); - usba_ep = kzalloc(sizeof(struct usba_ep) * pdata->num_ep, - GFP_KERNEL); - if (!usba_ep) - goto err_alloc_ep; - - the_udc.gadget.ep0 = &usba_ep[0].ep; - - INIT_LIST_HEAD(&usba_ep[0].ep.ep_list); - usba_ep[0].ep_regs = udc->regs + USBA_EPT_BASE(0); - usba_ep[0].dma_regs = udc->regs + USBA_DMA_BASE(0); - usba_ep[0].fifo = udc->fifo + USBA_FIFO_BASE(0); - usba_ep[0].ep.ops = &usba_ep_ops; - usba_ep[0].ep.name = pdata->ep[0].name; - usba_ep[0].ep.maxpacket = pdata->ep[0].fifo_size; - usba_ep[0].udc = &the_udc; - INIT_LIST_HEAD(&usba_ep[0].queue); - usba_ep[0].fifo_size = pdata->ep[0].fifo_size; - usba_ep[0].nr_banks = pdata->ep[0].nr_banks; - usba_ep[0].index = pdata->ep[0].index; - usba_ep[0].can_dma = pdata->ep[0].can_dma; - usba_ep[0].can_isoc = pdata->ep[0].can_isoc; - - for (i = 1; i < pdata->num_ep; i++) { - struct usba_ep *ep = &usba_ep[i]; - - ep->ep_regs = udc->regs + USBA_EPT_BASE(i); - ep->dma_regs = udc->regs + USBA_DMA_BASE(i); - ep->fifo = udc->fifo + USBA_FIFO_BASE(i); - ep->ep.ops = &usba_ep_ops; - ep->ep.name = pdata->ep[i].name; - ep->ep.maxpacket = pdata->ep[i].fifo_size; - ep->udc = &the_udc; - INIT_LIST_HEAD(&ep->queue); - ep->fifo_size = pdata->ep[i].fifo_size; - ep->nr_banks = pdata->ep[i].nr_banks; - ep->index = pdata->ep[i].index; - ep->can_dma = pdata->ep[i].can_dma; - ep->can_isoc = pdata->ep[i].can_isoc; + if (pdev->dev.of_node) + udc->usba_ep = atmel_udc_of_init(pdev, udc); + else + udc->usba_ep = usba_udc_pdata(pdev, udc); - list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + if (IS_ERR(udc->usba_ep)) { + ret = PTR_ERR(udc->usba_ep); + goto err_alloc_ep; } ret = request_irq(irq, usba_udc_irq, 0, "atmel_usba_udc", udc); @@ -1941,16 +2045,12 @@ static int __init usba_udc_probe(struct platform_device *pdev) } udc->irq = irq; - if (gpio_is_valid(pdata->vbus_pin)) { - if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) { - udc->vbus_pin = pdata->vbus_pin; - udc->vbus_pin_inverted = pdata->vbus_pin_inverted; - + if (gpio_is_valid(udc->vbus_pin)) { + if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) { ret = request_irq(gpio_to_irq(udc->vbus_pin), usba_vbus_irq, 0, "atmel_usba_udc", udc); if (ret) { - gpio_free(udc->vbus_pin); udc->vbus_pin = -ENODEV; dev_warn(&udc->pdev->dev, "failed to request vbus irq; " @@ -1969,20 +2069,17 @@ static int __init usba_udc_probe(struct platform_device *pdev) goto err_add_udc; usba_init_debugfs(udc); - for (i = 1; i < pdata->num_ep; i++) - usba_ep_init_debugfs(udc, &usba_ep[i]); + for (i = 1; i < udc->num_ep; i++) + usba_ep_init_debugfs(udc, &udc->usba_ep[i]); return 0; err_add_udc: - if (gpio_is_valid(pdata->vbus_pin)) { + if (gpio_is_valid(udc->vbus_pin)) free_irq(gpio_to_irq(udc->vbus_pin), udc); - gpio_free(udc->vbus_pin); - } free_irq(irq, udc); err_request_irq: - kfree(usba_ep); err_alloc_ep: iounmap(udc->fifo); err_map_fifo: @@ -1999,23 +2096,20 @@ static int __exit usba_udc_remove(struct platform_device *pdev) { struct usba_udc *udc; int i; - struct usba_platform_data *pdata = pdev->dev.platform_data; udc = platform_get_drvdata(pdev); usb_del_gadget_udc(&udc->gadget); - for (i = 1; i < pdata->num_ep; i++) - usba_ep_cleanup_debugfs(&usba_ep[i]); + for (i = 1; i < udc->num_ep; i++) + usba_ep_cleanup_debugfs(&udc->usba_ep[i]); usba_cleanup_debugfs(udc); if (gpio_is_valid(udc->vbus_pin)) { free_irq(gpio_to_irq(udc->vbus_pin), udc); - gpio_free(udc->vbus_pin); } free_irq(udc->irq, udc); - kfree(usba_ep); iounmap(udc->fifo); iounmap(udc->regs); clk_put(udc->hclk); @@ -2024,11 +2118,21 @@ static int __exit usba_udc_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id atmel_udc_dt_ids[] = { + { .compatible = "atmel,at91sam9rl-udc" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids); +#endif + static struct platform_driver udc_driver = { .remove = __exit_p(usba_udc_remove), .driver = { .name = "atmel_usba_udc", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_udc_dt_ids), }, }; diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h index d65a61851d3..2922db50bef 100644 --- a/drivers/usb/gadget/atmel_usba_udc.h +++ b/drivers/usb/gadget/atmel_usba_udc.h @@ -317,8 +317,10 @@ struct usba_udc { int irq; int vbus_pin; int vbus_pin_inverted; + int num_ep; struct clk *pclk; struct clk *hclk; + struct usba_ep *usba_ep; u16 devstatus; diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 028ff4d07dc..fce71b60593 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -25,11 +25,19 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/usb/musb-ux500.h> #include "musb_core.h" +static struct musb_hdrc_config ux500_musb_hdrc_config = { + .multipoint = true, + .dyn_fifo = true, + .num_eps = 16, + .ram_bits = 16, +}; + struct ux500_glue { struct device *dev; struct platform_device *musb; @@ -187,15 +195,58 @@ static const struct musb_platform_ops ux500_ops = { .set_vbus = ux500_musb_set_vbus, }; +static struct musb_hdrc_platform_data * +ux500_of_probe(struct platform_device *pdev, struct device_node *np) +{ + struct musb_hdrc_platform_data *pdata; + const char *mode; + int strlen; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + mode = of_get_property(np, "dr_mode", &strlen); + if (!mode) { + dev_err(&pdev->dev, "No 'dr_mode' property found\n"); + return NULL; + } + + if (strlen > 0) { + if (!strcmp(mode, "host")) + pdata->mode = MUSB_HOST; + if (!strcmp(mode, "otg")) + pdata->mode = MUSB_OTG; + if (!strcmp(mode, "peripheral")) + pdata->mode = MUSB_PERIPHERAL; + } + + return pdata; +} + static int ux500_probe(struct platform_device *pdev) { struct resource musb_resources[2]; struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; struct platform_device *musb; struct ux500_glue *glue; struct clk *clk; int ret = -ENOMEM; + if (!pdata) { + if (np) { + pdata = ux500_of_probe(pdev, np); + if (!pdata) + goto err0; + + pdev->dev.platform_data = pdata; + } else { + dev_err(&pdev->dev, "no pdata or device tree found\n"); + goto err0; + } + } + glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(&pdev->dev, "failed to allocate glue context\n"); @@ -222,14 +273,16 @@ static int ux500_probe(struct platform_device *pdev) } musb->dev.parent = &pdev->dev; - musb->dev.dma_mask = pdev->dev.dma_mask; + musb->dev.dma_mask = &pdev->dev.coherent_dma_mask; musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; + musb->dev.of_node = pdev->dev.of_node; glue->dev = &pdev->dev; glue->musb = musb; glue->clk = clk; pdata->platform_ops = &ux500_ops; + pdata->config = &ux500_musb_hdrc_config; platform_set_drvdata(pdev, glue); @@ -334,12 +387,18 @@ static const struct dev_pm_ops ux500_pm_ops = { #define DEV_PM_OPS NULL #endif +static const struct of_device_id ux500_match[] = { + { .compatible = "stericsson,db8500-musb", }, + {} +}; + static struct platform_driver ux500_driver = { .probe = ux500_probe, .remove = ux500_remove, .driver = { .name = "musb-ux500", .pm = DEV_PM_OPS, + .of_match_table = ux500_match, }, }; diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 63e7c8a6b12..bfb7a65d83c 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -34,6 +34,11 @@ #include <linux/platform_data/usb-musb-ux500.h> #include "musb_core.h" +static const char *iep_chan_names[] = { "iep_1_9", "iep_2_10", "iep_3_11", "iep_4_12", + "iep_5_13", "iep_6_14", "iep_7_15", "iep_8" }; +static const char *oep_chan_names[] = { "oep_1_9", "oep_2_10", "oep_3_11", "oep_4_12", + "oep_5_13", "oep_6_14", "oep_7_15", "oep_8" }; + struct ux500_dma_channel { struct dma_channel channel; struct ux500_dma_controller *controller; @@ -48,10 +53,8 @@ struct ux500_dma_channel { struct ux500_dma_controller { struct dma_controller controller; - struct ux500_dma_channel rx_channel[UX500_MUSB_DMA_NUM_RX_CHANNELS]; - struct ux500_dma_channel tx_channel[UX500_MUSB_DMA_NUM_TX_CHANNELS]; - u32 num_rx_channels; - u32 num_tx_channels; + struct ux500_dma_channel rx_channel[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS]; + struct ux500_dma_channel tx_channel[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS]; void *private_data; dma_addr_t phy_base; }; @@ -143,19 +146,15 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c, struct ux500_dma_channel *ux500_channel = NULL; struct musb *musb = controller->private_data; u8 ch_num = hw_ep->epnum - 1; - u32 max_ch; - /* Max 8 DMA channels (0 - 7). Each DMA channel can only be allocated + /* 8 DMA channels (0 - 7). Each DMA channel can only be allocated * to specified hw_ep. For example DMA channel 0 can only be allocated * to hw_ep 1 and 9. */ if (ch_num > 7) ch_num -= 8; - max_ch = is_tx ? controller->num_tx_channels : - controller->num_rx_channels; - - if (ch_num >= max_ch) + if (ch_num >= UX500_MUSB_DMA_NUM_RX_TX_CHANNELS) return NULL; ux500_channel = is_tx ? &(controller->tx_channel[ch_num]) : @@ -263,7 +262,7 @@ static int ux500_dma_controller_stop(struct dma_controller *c) struct dma_channel *channel; u8 ch_num; - for (ch_num = 0; ch_num < controller->num_rx_channels; ch_num++) { + for (ch_num = 0; ch_num < UX500_MUSB_DMA_NUM_RX_TX_CHANNELS; ch_num++) { channel = &controller->rx_channel[ch_num].channel; ux500_channel = channel->private_data; @@ -273,7 +272,7 @@ static int ux500_dma_controller_stop(struct dma_controller *c) dma_release_channel(ux500_channel->dma_chan); } - for (ch_num = 0; ch_num < controller->num_tx_channels; ch_num++) { + for (ch_num = 0; ch_num < UX500_MUSB_DMA_NUM_RX_TX_CHANNELS; ch_num++) { channel = &controller->tx_channel[ch_num].channel; ux500_channel = channel->private_data; @@ -294,34 +293,36 @@ static int ux500_dma_controller_start(struct dma_controller *c) struct musb *musb = controller->private_data; struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; - struct ux500_musb_board_data *data = plat->board_data; + struct ux500_musb_board_data *data; struct dma_channel *dma_channel = NULL; + char **chan_names; u32 ch_num; u8 dir; u8 is_tx = 0; void **param_array; struct ux500_dma_channel *channel_array; - u32 ch_count; dma_cap_mask_t mask; - if ((data->num_rx_channels > UX500_MUSB_DMA_NUM_RX_CHANNELS) || - (data->num_tx_channels > UX500_MUSB_DMA_NUM_TX_CHANNELS)) + if (!plat) { + dev_err(musb->controller, "No platform data\n"); return -EINVAL; + } - controller->num_rx_channels = data->num_rx_channels; - controller->num_tx_channels = data->num_tx_channels; + data = plat->board_data; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); /* Prepare the loop for RX channels */ channel_array = controller->rx_channel; - ch_count = data->num_rx_channels; - param_array = data->dma_rx_param_array; + param_array = data ? data->dma_rx_param_array : NULL; + chan_names = (char **)iep_chan_names; for (dir = 0; dir < 2; dir++) { - for (ch_num = 0; ch_num < ch_count; ch_num++) { + for (ch_num = 0; + ch_num < UX500_MUSB_DMA_NUM_RX_TX_CHANNELS; + ch_num++) { ux500_channel = &channel_array[ch_num]; ux500_channel->controller = controller; ux500_channel->ch_num = ch_num; @@ -332,9 +333,15 @@ static int ux500_dma_controller_start(struct dma_controller *c) dma_channel->status = MUSB_DMA_STATUS_FREE; dma_channel->max_len = SZ_16M; - ux500_channel->dma_chan = dma_request_channel(mask, - data->dma_filter, - param_array[ch_num]); + ux500_channel->dma_chan = + dma_request_slave_channel(dev, chan_names[ch_num]); + + if (!ux500_channel->dma_chan) + ux500_channel->dma_chan = + dma_request_channel(mask, + data->dma_filter, + param_array[ch_num]); + if (!ux500_channel->dma_chan) { ERR("Dma pipe allocation error dir=%d ch=%d\n", dir, ch_num); @@ -349,8 +356,8 @@ static int ux500_dma_controller_start(struct dma_controller *c) /* Prepare the loop for TX channels */ channel_array = controller->tx_channel; - ch_count = data->num_tx_channels; - param_array = data->dma_tx_param_array; + param_array = data ? data->dma_tx_param_array : NULL; + chan_names = (char **)oep_chan_names; is_tx = 1; } diff --git a/include/dt-bindings/clk/exynos-audss-clk.h b/include/dt-bindings/clk/exynos-audss-clk.h new file mode 100644 index 00000000000..8279f427c60 --- /dev/null +++ b/include/dt-bindings/clk/exynos-audss-clk.h @@ -0,0 +1,25 @@ +/* + * This header provides constants for Samsung audio subsystem + * clock controller. + * + * The constants defined in this header are being used in dts + * and exynos audss driver. + */ + +#ifndef _DT_BINDINGS_CLK_EXYNOS_AUDSS_H +#define _DT_BINDINGS_CLK_EXYNOS_AUDSS_H + +#define EXYNOS_MOUT_AUDSS 0 +#define EXYNOS_MOUT_I2S 1 +#define EXYNOS_DOUT_SRP 2 +#define EXYNOS_DOUT_AUD_BUS 3 +#define EXYNOS_DOUT_I2S 4 +#define EXYNOS_SRP_CLK 5 +#define EXYNOS_I2S_BUS 6 +#define EXYNOS_SCLK_I2S 7 +#define EXYNOS_PCM_BUS 8 +#define EXYNOS_SCLK_PCM 9 + +#define EXYNOS_AUDSS_MAX_CLKS 10 + +#endif diff --git a/include/linux/omap-mailbox.h b/include/linux/omap-mailbox.h new file mode 100644 index 00000000000..f8322d9cd23 --- /dev/null +++ b/include/linux/omap-mailbox.h @@ -0,0 +1,29 @@ +/* + * omap-mailbox: interprocessor communication module for OMAP + * + * 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 OMAP_MAILBOX_H +#define OMAP_MAILBOX_H + +typedef u32 mbox_msg_t; +struct omap_mbox; + +typedef int __bitwise omap_mbox_irq_t; +#define IRQ_TX ((__force omap_mbox_irq_t) 1) +#define IRQ_RX ((__force omap_mbox_irq_t) 2) + +int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); + +struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb); +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb); + +void omap_mbox_save_ctx(struct omap_mbox *mbox); +void omap_mbox_restore_ctx(struct omap_mbox *mbox); +void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq); +void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq); + +#endif /* OMAP_MAILBOX_H */ diff --git a/include/linux/platform_data/dma-ste-dma40.h b/include/linux/platform_data/dma-ste-dma40.h index 4b781014b0a..1bb9b185225 100644 --- a/include/linux/platform_data/dma-ste-dma40.h +++ b/include/linux/platform_data/dma-ste-dma40.h @@ -70,23 +70,8 @@ enum stedma40_flow_ctrl { STEDMA40_FLOW_CTRL, }; -enum stedma40_periph_data_width { - STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT, - STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT, - STEDMA40_WORD_WIDTH = STEDMA40_ESIZE_32_BIT, - STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT -}; - -enum stedma40_xfer_dir { - STEDMA40_MEM_TO_MEM = 1, - STEDMA40_MEM_TO_PERIPH, - STEDMA40_PERIPH_TO_MEM, - STEDMA40_PERIPH_TO_PERIPH -}; - - /** - * struct stedma40_chan_cfg - dst/src channel configuration + * struct stedma40_half_channel_info - dst/src channel configuration * * @big_endian: true if the src/dst should be read as big endian * @data_width: Data width of the src/dst hardware @@ -95,7 +80,7 @@ enum stedma40_xfer_dir { */ struct stedma40_half_channel_info { bool big_endian; - enum stedma40_periph_data_width data_width; + enum dma_slave_buswidth data_width; int psize; enum stedma40_flow_ctrl flow_ctrl; }; @@ -109,8 +94,7 @@ struct stedma40_half_channel_info { * version 3+, i.e DB8500v2+ * @mode: channel mode: physical, logical, or operation * @mode_opt: options for the chosen channel mode - * @src_dev_type: Src device type - * @dst_dev_type: Dst device type + * @dev_type: src/dst device type (driver uses dir to figure out which) * @src_info: Parameters for dst half channel * @dst_info: Parameters for dst half channel * @use_fixed_channel: if true, use physical channel specified by phy_channel @@ -121,13 +105,12 @@ struct stedma40_half_channel_info { * */ struct stedma40_chan_cfg { - enum stedma40_xfer_dir dir; + enum dma_transfer_direction dir; bool high_priority; bool realtime; enum stedma40_mode mode; enum stedma40_mode_opt mode_opt; - int src_dev_type; - int dst_dev_type; + int dev_type; struct stedma40_half_channel_info src_info; struct stedma40_half_channel_info dst_info; @@ -138,13 +121,8 @@ struct stedma40_chan_cfg { /** * struct stedma40_platform_data - Configuration struct for the dma device. * - * @dev_len: length of dev_tx and dev_rx * @dev_tx: mapping between destination event line and io address * @dev_rx: mapping between source event line and io address - * @memcpy: list of memcpy event lines - * @memcpy_len: length of memcpy - * @memcpy_conf_phy: default configuration of physical channel memcpy - * @memcpy_conf_log: default configuration of logical channel memcpy * @disabled_channels: A vector, ending with -1, that marks physical channels * that are for different reasons not available for the driver. * @soft_lli_chans: A vector, that marks physical channels will use LLI by SW @@ -154,22 +132,17 @@ struct stedma40_chan_cfg { * @num_of_soft_lli_chans: The number of channels that needs to be configured * to use SoftLLI. * @use_esram_lcla: flag for mapping the lcla into esram region + * @num_of_memcpy_chans: The number of channels reserved for memcpy. * @num_of_phy_chans: The number of physical channels implemented in HW. * 0 means reading the number of channels from DMA HW but this is only valid * for 'multiple of 4' channels, like 8. */ struct stedma40_platform_data { - u32 dev_len; - const dma_addr_t *dev_tx; - const dma_addr_t *dev_rx; - int *memcpy; - u32 memcpy_len; - struct stedma40_chan_cfg *memcpy_conf_phy; - struct stedma40_chan_cfg *memcpy_conf_log; int disabled_channels[STEDMA40_MAX_PHYS]; int *soft_lli_chans; int num_of_soft_lli_chans; bool use_esram_lcla; + int num_of_memcpy_chans; int num_of_phy_chans; }; diff --git a/include/linux/platform_data/mailbox-omap.h b/include/linux/platform_data/mailbox-omap.h new file mode 100644 index 00000000000..4631dbb4255 --- /dev/null +++ b/include/linux/platform_data/mailbox-omap.h @@ -0,0 +1,58 @@ +/* + * mailbox-omap.h + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * 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. + * + * 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. + */ + +#ifndef _PLAT_MAILBOX_H +#define _PLAT_MAILBOX_H + +/* Interrupt register configuration types */ +#define MBOX_INTR_CFG_TYPE1 (0) +#define MBOX_INTR_CFG_TYPE2 (1) + +/** + * struct omap_mbox_dev_info - OMAP mailbox device attribute info + * @name: name of the mailbox device + * @tx_id: mailbox queue id used for transmitting messages + * @rx_id: mailbox queue id on which messages are received + * @irq_id: irq identifier number to use from the hwmod data + * @usr_id: mailbox user id for identifying the interrupt into + * the MPU interrupt controller. + */ +struct omap_mbox_dev_info { + const char *name; + u32 tx_id; + u32 rx_id; + u32 irq_id; + u32 usr_id; +}; + +/** + * struct omap_mbox_pdata - OMAP mailbox platform data + * @intr_type: type of interrupt configuration registers used + while programming mailbox queue interrupts + * @num_users: number of users (processor devices) that the mailbox + * h/w block can interrupt + * @num_fifos: number of h/w fifos within the mailbox h/w block + * @info_cnt: number of mailbox devices for the platform + * @info: array of mailbox device attributes + */ +struct omap_mbox_pdata { + u32 intr_type; + u32 num_users; + u32 num_fifos; + u32 info_cnt; + struct omap_mbox_dev_info *info; +}; + +#endif /* _PLAT_MAILBOX_H */ diff --git a/include/linux/platform_data/usb-musb-ux500.h b/include/linux/platform_data/usb-musb-ux500.h index 4c1cc50a595..dd9c83ac7de 100644 --- a/include/linux/platform_data/usb-musb-ux500.h +++ b/include/linux/platform_data/usb-musb-ux500.h @@ -9,14 +9,11 @@ #include <linux/dmaengine.h> -#define UX500_MUSB_DMA_NUM_RX_CHANNELS 8 -#define UX500_MUSB_DMA_NUM_TX_CHANNELS 8 +#define UX500_MUSB_DMA_NUM_RX_TX_CHANNELS 8 struct ux500_musb_board_data { void **dma_rx_param_array; void **dma_tx_param_array; - u32 num_rx_channels; - u32 num_tx_channels; bool (*dma_filter)(struct dma_chan *chan, void *filter_param); }; diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index b6e5ae27729..31f9bbc7452 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -76,20 +76,20 @@ static struct dma_chan *ux500_pcm_request_chan(struct snd_soc_pcm_runtime *rtd, dma_params = snd_soc_dai_get_dma_data(dai, substream); dma_cfg = dma_params->dma_cfg; - mem_data_width = STEDMA40_HALFWORD_WIDTH; + mem_data_width = DMA_SLAVE_BUSWIDTH_2_BYTES; switch (dma_params->data_size) { case 32: - per_data_width = STEDMA40_WORD_WIDTH; + per_data_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break; case 16: - per_data_width = STEDMA40_HALFWORD_WIDTH; + per_data_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case 8: - per_data_width = STEDMA40_BYTE_WIDTH; + per_data_width = DMA_SLAVE_BUSWIDTH_1_BYTE; break; default: - per_data_width = STEDMA40_WORD_WIDTH; + per_data_width = DMA_SLAVE_BUSWIDTH_4_BYTES; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |