diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 14:33:21 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 14:33:21 -0700 |
commit | 0bf6a210a43f7118d858806200127e421649fc4e (patch) | |
tree | 9a17d88ebd1b9bc693fba7f39c12123dec96e930 | |
parent | ee1a8d402e7e204d57fb108aa40003b6d1633036 (diff) | |
parent | 5c913a9a9772f4b434aaea7328836419287b5d1c (diff) | |
download | op-kernel-dev-0bf6a210a43f7118d858806200127e421649fc4e.zip op-kernel-dev-0bf6a210a43f7118d858806200127e421649fc4e.tar.gz |
Merge tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver specific changes from Arnd Bergmann:
"These changes are all driver specific and cross over between arm-soc
contents and some other subsystem, in these cases cpufreq, crypto,
dma, pinctrl, mailbox and usb, and the subsystem owners agreed to have
these changes merged through arm-soc.
As we proceed to untangle the dependencies between platform code and
driver code, the amount of changes in this category is fortunately
shrinking, for 3.11 we have 16 branches here and 101 non-merge
changesets, the majority of which are for the stedma40 dma engine
driver used in the ux500 platform. Cleaning up that code touches
multiple subsystems, but gets rid of the dependency in the end.
The mailbox code moved out from mach-omap2 to drivers/mailbox is an
intermediate step and is still omap specific at the moment. Patches
exist to generalize the subsystem and add other drivers with the same
API, but those did not make it for 3.11."
* tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (101 commits)
crypto: ux500: use dmaengine_submit API
crypto: ux500: use dmaengine_prep_slave_sg API
crypto: ux500: use dmaengine_device_control API
crypto: ux500/crypt: add missing __iomem qualifiers
crypto: ux500/hash: add missing static qualifiers
crypto: ux500/hash: use readl on iomem addresses
dmaengine: ste_dma40: Declare memcpy config as static
ARM: ux500: Remove mop500_snowball_ethernet_clock_enable()
ARM: ux500: Correct the EN_3v3 regulator's on/off GPIO
ARM: ux500: Provide a AB8500 GPIO Device Tree node
gpio: rcar: fix gpio_rcar_of_table
gpio-rcar: Remove #ifdef CONFIG_OF around OF-specific sections
gpio-rcar: Reference core gpio documentation in the DT bindings
clk: exynos5250: Add enum entries for divider clock of i2s1 and i2s2
ARM: dts: Update Samsung I2S documentation
ARM: dts: add clock provider information for i2s controllers in Exynos5250
ARM: dts: add Exynos audio subsystem clock controller node
clk: samsung: register audio subsystem clocks using common clock framework
ARM: dts: use #include for all device trees for Samsung
pinctrl: s3c24xx: use correct header for chained_irq functions
...
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 4b87ea1..704be93 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 0000000..a120180 --- /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 0000000..bea5b73 --- /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 f1e5dfe..5375625 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 0000000..cb3dc7b --- /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 6a983c1..df338cb 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 e15cfc4..72e9cd1 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 3070046..025e66b 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 60bd215..55f51af 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 0000000..330d6ec --- /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 7a13c2c..49fdc43 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 a082f0b..a152945 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 bed40ee..3f94fe8 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 08609b8..382d8c7 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 91332b7..9c01b71 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 9a14484..94eebff 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 345cdb5..889cdad 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 d4f8067e..b7f358a 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 c0f60f4..6f34d7f 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 867d945..46c678e 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 ca73c42..7993641 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 a8ba195..ad316a1 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 270b389..e743e67 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 35cb2099d..01da194 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 c6db281..abc7272 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 1e21200..35a66de 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 05244f1..e79331d 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 54a35e6..964158c 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 f722a02..5b22508 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 ba88cfd..ede7727 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 bfcb907..ff7f5d8 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 c4a1c0a..e2249bc 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 ad1dd09..59594cf1 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 6809324..e6555bd 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 cab46ff..2d1d7dc 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 fb9dce5..49824be 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 9940f7b..d74edba 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 222d58c..3889b6c 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 8e8c605..ea5a27f 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 c33adea..fc20a61 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 403c211..aef96e4 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 d9c2719..662c7fd 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 6c4da12..1c7969e 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 5137cc8..d8b9d60 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 4ce999e..5b90834 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 fa99154..f7a3df2 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 0adb2b8..6d9252e 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 6de730b..7f54e5b 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 548ced4..548ced4 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 663436d..bd064c0 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 aba9e56..bfe443d 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 43be3e0..b3e61a3 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 78389de..df5d27a 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 49514b8..d6fab16 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 7669a49..12eee81 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 ddbdcda..516a6f5 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 a616419..0296ae5 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 2dfc72f..b7bd8d3 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 ce66eb9..f82bae2 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 3119941..0b01b68 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 95509d8..d7e1715 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 80c4a80..85517ab 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 b7c232e..1876810 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 0000000..9b1bbd5 --- /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 22d7699..6f767c5 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 54f3d11..77398f8 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 6e57543..a924408 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 315b923..6ad0b91 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 cfa0dd8..cfa0dd8 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 8bf0f3a..4645b48 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 72b2cc8..72b2cc8 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 9b7b428..9b7b428 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 3c0e78e..3c0e78e 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 3eafa90..43a0c8a 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 14cfd05..d1d6606 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 8c2777c..83d79b9 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 cd9351c..be6eb54 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 3b8f661..496ae6a 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 71bf4ec..5ab5880 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 7180e0d..27b818d 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 fdde8ef..1b47312 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 d173d56..6ec82f7 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 b22ca79..a1392f4 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 9545c9f..c8b5c13 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 543ad6a..e0facb3 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 efc8f20..9001b76 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 0b08026..eba380d 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 42377ef..d79a646 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 cc3921e..6cd38fc 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 a1c6dd3..901a388 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 9bdaeb8..f90b645 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 0000000..24446da --- /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 63ac22e..e67ff1b 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 26d3519..79fcc20 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 bbff559..82bf6ab 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 1dcbabc..f903910 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 85d77a4..14f3ec2 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 d4d377c..ce1743d 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 0e396c1..5168972 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 60848f1..165b918 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 7f3a1db..d1441db 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 01b8229..62f6802 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 5a5128a..1d97222 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 d65a618..2922db5 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 028ff4d..fce71b6 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 63e7c8a..bfb7a65 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 0000000..8279f42 --- /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 0000000..f8322d9 --- /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 4b78101..1bb9b18 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 0000000..4631dbb --- /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 4c1cc50..dd9c83a 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 b6e5ae2..31f9bbc 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) { |