diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt new file mode 100644 index 000000000000..952e373178d2 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt @@ -0,0 +1,28 @@ +* Renesas CPG DIV6 Clock + +The CPG DIV6 clocks are variable factor clocks provided by the Clock Pulse +Generator (CPG). They clock input is divided by a configurable factor from 1 +to 64. + +Required Properties: + + - compatible: Must be one of the following + - "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks + - "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2) DIV6 clocks + - "renesas,cpg-div6-clock" for generic DIV6 clocks + - reg: Base address and length of the memory resource used by the DIV6 clock + - clocks: Reference to the parent clock + - #clock-cells: Must be 0 + - clock-output-names: The name of the clock as a free-form string + + +Example +------- + + sd2_clk: sd2_clk@e6150078 { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150078 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd2"; + }; diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt new file mode 100644 index 000000000000..a6a352c2771e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt @@ -0,0 +1,51 @@ +* Renesas CPG Module Stop (MSTP) Clocks + +The CPG can gate SoC device clocks. The gates are organized in groups of up to +32 gates. + +This device tree binding describes a single 32 gate clocks group per node. +Clocks are referenced by user nodes by the MSTP node phandle and the clock +index in the group, from 0 to 31. + +Required Properties: + + - compatible: Must be one of the following + - "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks + - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2) MSTP gate clocks + - "renesas,cpg-mstp-clock" for generic MSTP gate clocks + - reg: Base address and length of the I/O mapped registers used by the MSTP + clocks. The first register is the clock control register and is mandatory. + The second register is the clock status register and is optional when not + implemented in hardware. + - clocks: Reference to the parent clocks, one per output clock. The parents + must appear in the same order as the output clocks. + - #clock-cells: Must be 1 + - clock-output-names: The name of the clocks as free-form strings + - renesas,indices: Indices of the gate clocks into the group (0 to 31) + +The clocks, clock-output-names and renesas,indices properties contain one +entry per gate clock. The MSTP groups are sparsely populated. Unimplemented +gate clocks must not be declared. + + +Example +------- + + #include + + mstp3_clks: mstp3_clks@e615013c { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; + clocks = <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, <&sd2_clk>, + <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, + <&mmc0_clk>; + #clock-cells = <1>; + clock-output-names = + "tpu0", "mmcif1", "sdhi3", "sdhi2", + "sdhi1", "sdhi0", "mmcif0"; + renesas,clock-indices = < + R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3 + R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 + R8A7790_CLK_MMCIF0 + >; + }; diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt new file mode 100644 index 000000000000..7b41c2fe54db --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt @@ -0,0 +1,32 @@ +* Renesas R-Car Gen2 Clock Pulse Generator (CPG) + +The CPG generates core clocks for the R-Car Gen2 SoCs. It includes three PLLs +and several fixed ratio dividers. + +Required Properties: + + - compatible: Must be one of + - "renesas,r8a7790-cpg-clocks" for the r8a7790 CPG + - "renesas,r8a7791-cpg-clocks" for the r8a7791 CPG + - "renesas,rcar-gen2-cpg-clocks" for the generic R-Car Gen2 CPG + + - reg: Base address and length of the memory resource used by the CPG + + - clocks: Reference to the parent clock + - #clock-cells: Must be 1 + - clock-output-names: The names of the clocks. Supported clocks are "main", + "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1" and "z" + + +Example +------- + + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,r8a7790-cpg-clocks", + "renesas,rcar-gen2-cpg-clocks"; + reg = <0 0xe6150000 0 0x1000>; + clocks = <&extal_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0, "pll1", "pll3", + "lb", "qspi", "sdh", "sd0", "sd1", "z"; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx25-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx25-pinctrl.txt new file mode 100644 index 000000000000..fd653bde18d5 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx25-pinctrl.txt @@ -0,0 +1,23 @@ +* Freescale IMX25 IOMUX Controller + +Please refer to fsl,imx-pinctrl.txt in this directory for common binding part +and usage. + +CONFIG bits definition: +PAD_CTL_HYS (1 << 8) +PAD_CTL_PKE (1 << 7) +PAD_CTL_PUE (1 << 6) +PAD_CTL_PUS_100K_DOWN (0 << 4) +PAD_CTL_PUS_47K_UP (1 << 4) +PAD_CTL_PUS_100K_UP (2 << 4) +PAD_CTL_PUS_22K_UP (3 << 4) +PAD_CTL_ODE_CMOS (0 << 3) +PAD_CTL_ODE_OPENDRAIN (1 << 3) +PAD_CTL_DSE_NOMINAL (0 << 1) +PAD_CTL_DSE_HIGH (1 << 1) +PAD_CTL_DSE_MAX (2 << 1) +PAD_CTL_SRE_FAST (1 << 0) +PAD_CTL_SRE_SLOW (0 << 0) + +Refer to imx25-pinfunc.h in device tree source folder for all available +imx25 PIN_FUNC_ID. diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt index 353eca0efbf8..d1706ea82572 100644 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt @@ -52,12 +52,25 @@ Required properties for pin configuration node: CONFIG can be 0 or 1, meaning Pullup disable/enable. +The iomux controller has gpio child nodes which are embedded in the iomux +control registers. They have to be defined as child nodes of the iomux device +node. If gpio subnodes are defined "#address-cells", "#size-cells" and "ranges" +properties for the iomux device node are required. Example: iomuxc: iomuxc@10015000 { compatible = "fsl,imx27-iomuxc"; reg = <0x10015000 0x600>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio1: gpio@10015000 { + ... + }; + + ... uart { pinctrl_uart1: uart-1 { @@ -83,6 +96,15 @@ The above example using macros: iomuxc: iomuxc@10015000 { compatible = "fsl,imx27-iomuxc"; reg = <0x10015000 0x600>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio1: gpio@10015000 { + ... + }; + + ... uart { pinctrl_uart1: uart-1 { diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8x74-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8x74-pinctrl.txt new file mode 100644 index 000000000000..70ab78fe93c8 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8x74-pinctrl.txt @@ -0,0 +1,92 @@ +Qualcomm MSM8x74 TLMM block + +Required properties: +- compatible: "qcom,msm8x74-pinctrl" +- reg: Should be the base address and length of the TLMM block. +- interrupts: Should be the parent IRQ of the TLMM block. +- interrupt-controller: Marks the device node as an interrupt controller. +- #interrupt-cells: Should be two. +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells : Should be two. + The first cell is the gpio pin number and the + second cell is used for optional parameters. + +Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for +a general description of GPIO and interrupt bindings. + +Please refer to pinctrl-bindings.txt in this directory for details of the +common pinctrl bindings used by client devices, including the meaning of the +phrase "pin configuration node". + +Qualcomm's pin configuration nodes act as a container for an abitrary number of +subnodes. Each of these subnodes represents some desired configuration for a +pin, a group, or a list of pins or groups. This configuration can include the +mux function to select on those pin(s)/group(s), and various pin configuration +parameters, such as pull-up, drive strength, etc. + +The name of each subnode is not important; all subnodes should be enumerated +and processed purely based on their content. + +Each subnode only affects those parameters that are explicitly listed. In +other words, a subnode that lists a mux function but no pin configuration +parameters implies no information about any pin configuration parameters. +Similarly, a pin subnode that describes a pullup parameter implies no +information about e.g. the mux function. + + +The following generic properties as defined in pinctrl-bindings.txt are valid +to specify in a pin configuration subnode: + pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength. + +Non-empty subnodes must specify the 'pins' property. +Note that not all properties are valid for all pins. + + +Valid values for qcom,pins are: + gpio0-gpio145 + Supports mux, bias and drive-strength + + sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, sdc2_data + Supports bias and drive-strength + +Valid values for qcom,function are: + blsp_i2c2, blsp_i2c6, blsp_i2c11, blsp_spi1, blsp_uart2, blsp_uart8, slimbus + + (Note that this is not yet the complete list of functions) + + + +Example: + + msmgpio: pinctrl@fd510000 { + compatible = "qcom,msm8x74-pinctrl"; + reg = <0xfd510000 0x4000>; + + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <0 208 0>; + + pinctrl-names = "default"; + pinctrl-0 = <&uart2_default>; + + uart2_default: uart2_default { + mux { + qcom,pins = "gpio4", "gpio5"; + qcom,function = "blsp_uart2"; + }; + + tx { + qcom,pins = "gpio4"; + drive-strength = <4>; + bias-disable; + }; + + rx { + qcom,pins = "gpio5"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt index d5dac7b843a9..35d2e1f186f0 100644 --- a/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt @@ -26,6 +26,11 @@ Optional properties: - #gpio-range-cells: Mandatory when the PFC doesn't handle GPIO, forbidden otherwise. Should be 3. + - interrupts-extended: Specify the interrupts associated with external + IRQ pins. This property is mandatory when the PFC handles GPIOs and + forbidden otherwise. When specified, it must contain one interrupt per + external IRQ, sorted by external IRQ number. + The PFC node also acts as a container for pin configuration nodes. Please refer to pinctrl-bindings.txt in this directory for the definition of the term "pin configuration node" and for the common pinctrl bindings used by client devices. @@ -103,6 +108,15 @@ Example 1: SH73A0 (SH-Mobile AG5) pin controller node <0xe605801c 0x1c>; gpio-controller; #gpio-cells = <2>; + interrupts-extended = + <&irqpin0 0 0>, <&irqpin0 1 0>, <&irqpin0 2 0>, <&irqpin0 3 0>, + <&irqpin0 4 0>, <&irqpin0 5 0>, <&irqpin0 6 0>, <&irqpin0 7 0>, + <&irqpin1 0 0>, <&irqpin1 1 0>, <&irqpin1 2 0>, <&irqpin1 3 0>, + <&irqpin1 4 0>, <&irqpin1 5 0>, <&irqpin1 6 0>, <&irqpin1 7 0>, + <&irqpin2 0 0>, <&irqpin2 1 0>, <&irqpin2 2 0>, <&irqpin2 3 0>, + <&irqpin2 4 0>, <&irqpin2 5 0>, <&irqpin2 6 0>, <&irqpin2 7 0>, + <&irqpin3 0 0>, <&irqpin3 1 0>, <&irqpin3 2 0>, <&irqpin3 3 0>, + <&irqpin3 4 0>, <&irqpin3 5 0>, <&irqpin3 6 0>, <&irqpin3 7 0>; }; Example 2: A GPIO LED node that references a GPIO diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index e7d3444caed8..4f93eefb4c29 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -232,7 +232,6 @@ dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += emev2-kzm9d.dtb \ r8a7779-marzen.dtb \ r8a7779-marzen-reference.dtb \ r8a7791-koelsch.dtb \ - r8a7791-koelsch-reference.dtb \ r8a7790-lager.dtb \ r8a7790-lager-reference.dtb \ sh73a0-kzm9g.dtb \ diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi index 6b7ce89a68f7..62d0211bd192 100644 --- a/arch/arm/boot/dts/r8a73a4.dtsi +++ b/arch/arm/boot/dts/r8a73a4.dtsi @@ -288,6 +288,22 @@ reg = <0 0xe6050000 0 0x9000>; gpio-controller; #gpio-cells = <2>; + interrupts-extended = + <&irqc0 0 0>, <&irqc0 1 0>, <&irqc0 2 0>, <&irqc0 3 0>, + <&irqc0 4 0>, <&irqc0 5 0>, <&irqc0 6 0>, <&irqc0 7 0>, + <&irqc0 8 0>, <&irqc0 9 0>, <&irqc0 10 0>, <&irqc0 11 0>, + <&irqc0 12 0>, <&irqc0 13 0>, <&irqc0 14 0>, <&irqc0 15 0>, + <&irqc0 16 0>, <&irqc0 17 0>, <&irqc0 18 0>, <&irqc0 19 0>, + <&irqc0 20 0>, <&irqc0 21 0>, <&irqc0 22 0>, <&irqc0 23 0>, + <&irqc0 24 0>, <&irqc0 25 0>, <&irqc0 26 0>, <&irqc0 27 0>, + <&irqc0 28 0>, <&irqc0 29 0>, <&irqc0 30 0>, <&irqc0 31 0>, + <&irqc1 0 0>, <&irqc1 1 0>, <&irqc1 2 0>, <&irqc1 3 0>, + <&irqc1 4 0>, <&irqc1 5 0>, <&irqc1 6 0>, <&irqc1 7 0>, + <&irqc1 8 0>, <&irqc1 9 0>, <&irqc1 10 0>, <&irqc1 11 0>, + <&irqc1 12 0>, <&irqc1 13 0>, <&irqc1 14 0>, <&irqc1 15 0>, + <&irqc1 16 0>, <&irqc1 17 0>, <&irqc1 18 0>, <&irqc1 19 0>, + <&irqc1 20 0>, <&irqc1 21 0>, <&irqc1 22 0>, <&irqc1 23 0>, + <&irqc1 24 0>, <&irqc1 25 0>; }; sdhi0: sd@ee100000 { diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts index 6d6fd3dff2d3..95a849bf921f 100644 --- a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts @@ -63,6 +63,44 @@ enable-active-high; }; + reg_5p0v: regulator@3 { + compatible = "regulator-fixed"; + regulator-name = "fixed-5.0V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + gpio-keys { + compatible = "gpio-keys"; + + power-key { + gpios = <&pfc 99 GPIO_ACTIVE_LOW>; + linux,code = <116>; + label = "SW3"; + gpio-key,wakeup; + }; + + back-key { + gpios = <&pfc 100 GPIO_ACTIVE_LOW>; + linux,code = <158>; + label = "SW4"; + }; + + menu-key { + gpios = <&pfc 97 GPIO_ACTIVE_LOW>; + linux,code = <139>; + label = "SW5"; + }; + + home-key { + gpios = <&pfc 98 GPIO_ACTIVE_LOW>; + linux,code = <102>; + label = "SW6"; + }; + }; + leds { compatible = "gpio-leds"; led1 { @@ -86,6 +124,8 @@ default-brightness-level = <9>; pinctrl-0 = <&backlight_pins>; pinctrl-names = "default"; + power-supply = <®_5p0v>; + enable-gpios = <&pfc 61 GPIO_ACTIVE_HIGH>; }; sound { diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi index 2782f642acfc..8280884bfa59 100644 --- a/arch/arm/boot/dts/r8a7740.dtsi +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -155,6 +155,15 @@ <0xe605800c 0x20>; gpio-controller; #gpio-cells = <2>; + interrupts-extended = + <&irqpin0 0 0>, <&irqpin0 1 0>, <&irqpin0 2 0>, <&irqpin0 3 0>, + <&irqpin0 4 0>, <&irqpin0 5 0>, <&irqpin0 6 0>, <&irqpin0 7 0>, + <&irqpin1 0 0>, <&irqpin1 1 0>, <&irqpin1 2 0>, <&irqpin1 3 0>, + <&irqpin1 4 0>, <&irqpin1 5 0>, <&irqpin1 6 0>, <&irqpin1 7 0>, + <&irqpin2 0 0>, <&irqpin2 1 0>, <&irqpin2 2 0>, <&irqpin2 3 0>, + <&irqpin2 4 0>, <&irqpin2 5 0>, <&irqpin2 6 0>, <&irqpin2 7 0>, + <&irqpin3 0 0>, <&irqpin3 1 0>, <&irqpin3 2 0>, <&irqpin3 3 0>, + <&irqpin3 4 0>, <&irqpin3 5 0>, <&irqpin3 6 0>, <&irqpin3 7 0>; }; tpu: pwm@e6600000 { diff --git a/arch/arm/boot/dts/r8a7790-lager-reference.dts b/arch/arm/boot/dts/r8a7790-lager-reference.dts deleted file mode 100644 index dfedc0ea82e1..000000000000 --- a/arch/arm/boot/dts/r8a7790-lager-reference.dts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Device Tree Source for the Lager board - * - * Copyright (C) 2013 Renesas Solutions Corp. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -/dts-v1/; -#include "r8a7790.dtsi" -#include - -/ { - model = "Lager"; - compatible = "renesas,lager-reference", "renesas,r8a7790"; - - chosen { - bootargs = "console=ttySC6,115200 ignore_loglevel rw"; - }; - - memory@40000000 { - device_type = "memory"; - reg = <0 0x40000000 0 0x80000000>; - }; - - memory@180000000 { - device_type = "memory"; - reg = <1 0x80000000 0 0x80000000>; - }; - - lbsc { - #address-cells = <1>; - #size-cells = <1>; - }; - - leds { - compatible = "gpio-leds"; - led6 { - gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; - }; - led7 { - gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>; - }; - led8 { - gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>; - }; - }; - - fixedregulator3v3: fixedregulator@0 { - compatible = "regulator-fixed"; - regulator-name = "fixed-3.3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - regulator-always-on; - }; -}; - -&pfc { - pinctrl-0 = <&scif0_pins &scif1_pins>; - pinctrl-names = "default"; - - scif0_pins: serial0 { - renesas,groups = "scif0_data"; - renesas,function = "scif0"; - }; - - scif1_pins: serial1 { - renesas,groups = "scif1_data"; - renesas,function = "scif1"; - }; - - mmc1_pins: mmc1 { - renesas,groups = "mmc1_data8", "mmc1_ctrl"; - renesas,function = "mmc1"; - }; -}; - -&mmcif1 { - pinctrl-0 = <&mmc1_pins>; - pinctrl-names = "default"; - - vmmc-supply = <&fixedregulator3v3>; - bus-width = <8>; - non-removable; - status = "okay"; -}; diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 10e6a08164e5..57569cba1528 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -10,6 +10,7 @@ /dts-v1/; #include "r8a7790.dtsi" +#include / { model = "Lager"; @@ -33,4 +34,60 @@ #address-cells = <1>; #size-cells = <1>; }; + + leds { + compatible = "gpio-leds"; + led6 { + gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; + }; + led7 { + gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>; + }; + led8 { + gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>; + }; + }; + + fixedregulator3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&extal_clk { + clock-frequency = <20000000>; +}; + +&pfc { + pinctrl-0 = <&scif0_pins &scif1_pins>; + pinctrl-names = "default"; + + scif0_pins: serial0 { + renesas,groups = "scif0_data"; + renesas,function = "scif0"; + }; + + scif1_pins: serial1 { + renesas,groups = "scif1_data"; + renesas,function = "scif1"; + }; + + mmc1_pins: mmc1 { + renesas,groups = "mmc1_data8", "mmc1_ctrl"; + renesas,function = "mmc1"; + }; +}; + +&mmcif1 { + pinctrl-0 = <&mmc1_pins>; + pinctrl-names = "default"; + + vmmc-supply = <&fixedregulator3v3>; + bus-width = <8>; + non-removable; + status = "okay"; }; diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 0e4d5b57c48b..c5417dafca0d 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -8,6 +8,7 @@ * kind, whether express or implied. */ +#include #include #include @@ -196,6 +197,7 @@ reg = <0 0xe6508000 0 0x40>; interrupt-parent = <&gic>; interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_I2C0>; status = "disabled"; }; @@ -206,6 +208,7 @@ reg = <0 0xe6518000 0 0x40>; interrupt-parent = <&gic>; interrupts = <0 288 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_I2C1>; status = "disabled"; }; @@ -216,6 +219,7 @@ reg = <0 0xe6530000 0 0x40>; interrupt-parent = <&gic>; interrupts = <0 286 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_I2C2>; status = "disabled"; }; @@ -226,6 +230,7 @@ reg = <0 0xe6540000 0 0x40>; interrupt-parent = <&gic>; interrupts = <0 290 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_I2C3>; status = "disabled"; }; @@ -234,6 +239,7 @@ reg = <0 0xee200000 0 0x80>; interrupt-parent = <&gic>; interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>; reg-io-width = <4>; status = "disabled"; }; @@ -243,6 +249,7 @@ reg = <0 0xee220000 0 0x80>; interrupt-parent = <&gic>; interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_MMCIF1>; reg-io-width = <4>; status = "disabled"; }; @@ -257,6 +264,7 @@ reg = <0 0xee100000 0 0x100>; interrupt-parent = <&gic>; interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_SDHI0>; cap-sd-highspeed; status = "disabled"; }; @@ -266,6 +274,7 @@ reg = <0 0xee120000 0 0x100>; interrupt-parent = <&gic>; interrupts = <0 166 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_SDHI1>; cap-sd-highspeed; status = "disabled"; }; @@ -275,6 +284,7 @@ reg = <0 0xee140000 0 0x100>; interrupt-parent = <&gic>; interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_SDHI2>; cap-sd-highspeed; status = "disabled"; }; @@ -284,7 +294,357 @@ reg = <0 0xee160000 0 0x100>; interrupt-parent = <&gic>; interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks R8A7790_CLK_SDHI3>; cap-sd-highspeed; status = "disabled"; }; + + clocks { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* External root clock */ + extal_clk: extal_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overriden by the board. */ + clock-frequency = <0>; + clock-output-names = "extal"; + }; + + /* Special CPG clocks */ + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,r8a7790-cpg-clocks", + "renesas,rcar-gen2-cpg-clocks"; + reg = <0 0xe6150000 0 0x1000>; + clocks = <&extal_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0", "pll1", "pll3", + "lb", "qspi", "sdh", "sd0", "sd1", + "z"; + }; + + /* Variable factor clocks */ + sd2_clk: sd2_clk@e6150078 { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150078 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd2"; + }; + sd3_clk: sd3_clk@e615007c { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe615007c 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd3"; + }; + mmc0_clk: mmc0_clk@e6150240 { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150240 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mmc0"; + }; + mmc1_clk: mmc1_clk@e6150244 { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150244 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mmc1"; + }; + ssp_clk: ssp_clk@e6150248 { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150248 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "ssp"; + }; + ssprs_clk: ssprs_clk@e615024c { + compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe615024c 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "ssprs"; + }; + + /* Fixed factor clocks */ + pll1_div2_clk: pll1_div2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "pll1_div2"; + }; + z2_clk: z2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "z2"; + }; + zg_clk: zg_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <3>; + clock-mult = <1>; + clock-output-names = "zg"; + }; + zx_clk: zx_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <3>; + clock-mult = <1>; + clock-output-names = "zx"; + }; + zs_clk: zs_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <6>; + clock-mult = <1>; + clock-output-names = "zs"; + }; + hp_clk: hp_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <12>; + clock-mult = <1>; + clock-output-names = "hp"; + }; + i_clk: i_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "i"; + }; + b_clk: b_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <12>; + clock-mult = <1>; + clock-output-names = "b"; + }; + p_clk: p_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <24>; + clock-mult = <1>; + clock-output-names = "p"; + }; + cl_clk: cl_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <48>; + clock-mult = <1>; + clock-output-names = "cl"; + }; + m2_clk: m2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + clock-output-names = "m2"; + }; + imp_clk: imp_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clock-output-names = "imp"; + }; + rclk_clk: rclk_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <(48 * 1024)>; + clock-mult = <1>; + clock-output-names = "rclk"; + }; + oscclk_clk: oscclk_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <(12 * 1024)>; + clock-mult = <1>; + clock-output-names = "oscclk"; + }; + zb3_clk: zb3_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL3>; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clock-output-names = "zb3"; + }; + zb3d2_clk: zb3d2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL3>; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + clock-output-names = "zb3d2"; + }; + ddr_clk: ddr_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7790_CLK_PLL3>; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + clock-output-names = "ddr"; + }; + mp_clk: mp_clk { + compatible = "fixed-factor-clock"; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-div = <15>; + clock-mult = <1>; + clock-output-names = "mp"; + }; + cp_clk: cp_clk { + compatible = "fixed-factor-clock"; + clocks = <&extal_clk>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "cp"; + }; + + /* Gate clocks */ + mstp0_clks: mstp0_clks@e6150130 { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; + clocks = <&mp_clk>; + #clock-cells = <1>; + renesas,clock-indices = ; + clock-output-names = "msiof0"; + }; + mstp1_clks: mstp1_clks@e6150134 { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150134 0 4>, <0 0xe6150038 0 4>; + clocks = <&p_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>, + <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>, + <&zs_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7790_CLK_TMU1 R8A7790_CLK_TMU3 R8A7790_CLK_TMU2 + R8A7790_CLK_CMT0 R8A7790_CLK_TMU0 R8A7790_CLK_VSP1_DU1 + R8A7790_CLK_VSP1_DU0 R8A7790_CLK_VSP1_RT R8A7790_CLK_VSP1_SY + >; + clock-output-names = + "tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1", + "vsp1-du0", "vsp1-rt", "vsp1-sy"; + }; + mstp2_clks: mstp2_clks@e6150138 { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>; + clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, + <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7790_CLK_SCIFA2 R8A7790_CLK_SCIFA1 R8A7790_CLK_SCIFA0 + R8A7790_CLK_MSIOF2 R8A7790_CLK_SCIFB0 R8A7790_CLK_SCIFB1 + R8A7790_CLK_MSIOF1 R8A7790_CLK_MSIOF3 R8A7790_CLK_SCIFB2 + >; + clock-output-names = + "scifa2", "scifa1", "scifa0", "msiof2", "scifb0", + "scifb1", "msiof1", "msiof3", "scifb2"; + }; + mstp3_clks: mstp3_clks@e615013c { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; + clocks = <&cp_clk>, <&mmc1_clk>, <&sd3_clk>, <&sd2_clk>, + <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, + <&mmc0_clk>, <&rclk_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3 + R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 + R8A7790_CLK_MMCIF0 R8A7790_CLK_CMT1 + >; + clock-output-names = + "tpu0", "mmcif1", "sdhi3", "sdhi2", + "sdhi1", "sdhi0", "mmcif0", "cmt1"; + }; + mstp5_clks: mstp5_clks@e6150144 { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>; + clocks = <&extal_clk>, <&p_clk>; + #clock-cells = <1>; + renesas,clock-indices = ; + clock-output-names = "thermal", "pwm"; + }; + mstp7_clks: mstp7_clks@e615014c { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>; + clocks = <&mp_clk>, <&mp_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>, + <&p_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>, + <&zx_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7790_CLK_EHCI R8A7790_CLK_HSUSB R8A7790_CLK_HSCIF1 + R8A7790_CLK_HSCIF0 R8A7790_CLK_SCIF1 R8A7790_CLK_SCIF0 + R8A7790_CLK_DU2 R8A7790_CLK_DU1 R8A7790_CLK_DU0 + R8A7790_CLK_LVDS1 R8A7790_CLK_LVDS0 + >; + clock-output-names = + "ehci", "hsusb", "hscif1", "hscif0", "scif1", + "scif0", "du2", "du1", "du0", "lvds1", "lvds0"; + }; + mstp8_clks: mstp8_clks@e6150990 { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; + clocks = <&p_clk>; + #clock-cells = <1>; + renesas,clock-indices = ; + clock-output-names = "ether"; + }; + mstp9_clks: mstp9_clks@e6150994 { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; + clocks = <&p_clk>, <&p_clk>, <&cpg_clocks R8A7790_CLK_QSPI>, + <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7790_CLK_RCAN1 R8A7790_CLK_RCAN0 R8A7790_CLK_QSPI_MOD + R8A7790_CLK_I2C3 R8A7790_CLK_I2C2 R8A7790_CLK_I2C1 + R8A7790_CLK_I2C0 + >; + clock-output-names = + "rcan1", "rcan0", "qspi_mod", "i2c3", "i2c2", "i2c1", "i2c0"; + }; + mstp10_clks: mstp10_clks@e6150998 { + compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>; + clocks = <&p_clk>, <&mstp10_clks R8A7790_CLK_SSI>, + <&mstp10_clks R8A7790_CLK_SSI>, <&mstp10_clks R8A7790_CLK_SSI>, + <&mstp10_clks R8A7790_CLK_SSI>, <&mstp10_clks R8A7790_CLK_SSI>, + <&mstp10_clks R8A7790_CLK_SSI>, <&mstp10_clks R8A7790_CLK_SSI>, + <&mstp10_clks R8A7790_CLK_SSI>, <&mstp10_clks R8A7790_CLK_SSI>, + <&mstp10_clks R8A7790_CLK_SSI>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7790_CLK_SSI R8A7790_CLK_SSI9 R8A7790_CLK_SSI8 + R8A7790_CLK_SSI7 R8A7790_CLK_SSI6 R8A7790_CLK_SSI5 + R8A7790_CLK_SSI4 R8A7790_CLK_SSI3 R8A7790_CLK_SSI2 + R8A7790_CLK_SSI1 R8A7790_CLK_SSI0 + >; + clock-output-names = + "ssi", "ssi9", "ssi8", "ssi7", "ssi6", "ssi5", + "ssi4", "ssi3", "ssi2", "ssi1", "ssi0"; + }; + }; }; diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index c4e8b3a0cd13..fd556c3483e3 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -11,6 +11,7 @@ /dts-v1/; #include "r8a7791.dtsi" +#include / { model = "Koelsch"; @@ -29,4 +30,36 @@ #address-cells = <1>; #size-cells = <1>; }; + + leds { + compatible = "gpio-leds"; + led6 { + gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>; + }; + led7 { + gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>; + }; + led8 { + gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&extal_clk { + clock-frequency = <20000000>; +}; + +&pfc { + pinctrl-0 = <&scif0_pins &scif1_pins>; + pinctrl-names = "default"; + + scif0_pins: serial0 { + renesas,groups = "scif0_data_d"; + renesas,function = "scif0"; + }; + + scif1_pins: serial1 { + renesas,groups = "scif1_data_d"; + renesas,function = "scif1"; + }; }; diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index a349aff54c76..e92c1f7aedd0 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -9,6 +9,7 @@ * kind, whether express or implied. */ +#include #include #include @@ -183,4 +184,346 @@ reg = <0 0xe6060000 0 0x250>; #gpio-range-cells = <3>; }; + + clocks { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* External root clock */ + extal_clk: extal_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overriden by the board. */ + clock-frequency = <0>; + clock-output-names = "extal"; + }; + + /* Special CPG clocks */ + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,r8a7791-cpg-clocks", + "renesas,rcar-gen2-cpg-clocks"; + reg = <0 0xe6150000 0 0x1000>; + clocks = <&extal_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0", "pll1", "pll3", + "lb", "qspi", "sdh", "sd0", "z"; + }; + + /* Variable factor clocks */ + sd1_clk: sd2_clk@e6150078 { + compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150078 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd1"; + }; + sd2_clk: sd3_clk@e615007c { + compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe615007c 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd2"; + }; + mmc0_clk: mmc0_clk@e6150240 { + compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150240 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mmc0"; + }; + ssp_clk: ssp_clk@e6150248 { + compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150248 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "ssp"; + }; + ssprs_clk: ssprs_clk@e615024c { + compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe615024c 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "ssprs"; + }; + + /* Fixed factor clocks */ + pll1_div2_clk: pll1_div2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "pll1_div2"; + }; + zg_clk: zg_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <3>; + clock-mult = <1>; + clock-output-names = "zg"; + }; + zx_clk: zx_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <3>; + clock-mult = <1>; + clock-output-names = "zx"; + }; + zs_clk: zs_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <6>; + clock-mult = <1>; + clock-output-names = "zs"; + }; + hp_clk: hp_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <12>; + clock-mult = <1>; + clock-output-names = "hp"; + }; + i_clk: i_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "i"; + }; + b_clk: b_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <12>; + clock-mult = <1>; + clock-output-names = "b"; + }; + p_clk: p_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <24>; + clock-mult = <1>; + clock-output-names = "p"; + }; + cl_clk: cl_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <48>; + clock-mult = <1>; + clock-output-names = "cl"; + }; + m2_clk: m2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + clock-output-names = "m2"; + }; + imp_clk: imp_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clock-output-names = "imp"; + }; + rclk_clk: rclk_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <(48 * 1024)>; + clock-mult = <1>; + clock-output-names = "rclk"; + }; + oscclk_clk: oscclk_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <(12 * 1024)>; + clock-mult = <1>; + clock-output-names = "oscclk"; + }; + zb3_clk: zb3_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL3>; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clock-output-names = "zb3"; + }; + zb3d2_clk: zb3d2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL3>; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + clock-output-names = "zb3d2"; + }; + ddr_clk: ddr_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks R8A7791_CLK_PLL3>; + #clock-cells = <0>; + clock-div = <8>; + clock-mult = <1>; + clock-output-names = "ddr"; + }; + mp_clk: mp_clk { + compatible = "fixed-factor-clock"; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-div = <15>; + clock-mult = <1>; + clock-output-names = "mp"; + }; + cp_clk: cp_clk { + compatible = "fixed-factor-clock"; + clocks = <&extal_clk>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "cp"; + }; + + /* Gate clocks */ + mstp0_clks: mstp0_clks@e6150130 { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; + clocks = <&mp_clk>; + #clock-cells = <1>; + renesas,clock-indices = ; + clock-output-names = "msiof0"; + }; + mstp1_clks: mstp1_clks@e6150134 { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150134 0 4>, <0 0xe6150038 0 4>; + clocks = <&p_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>, + <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7791_CLK_TMU1 R8A7791_CLK_TMU3 R8A7791_CLK_TMU2 + R8A7791_CLK_CMT0 R8A7791_CLK_TMU0 R8A7791_CLK_VSP1_DU1 + R8A7791_CLK_VSP1_DU0 R8A7791_CLK_VSP1_SY + >; + clock-output-names = + "tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1", + "vsp1-du0", "vsp1-sy"; + }; + mstp2_clks: mstp2_clks@e6150138 { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>; + clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, + <&mp_clk>, <&mp_clk>, <&mp_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7791_CLK_SCIFA2 R8A7791_CLK_SCIFA1 R8A7791_CLK_SCIFA0 + R8A7791_CLK_MSIOF2 R8A7791_CLK_SCIFB0 R8A7791_CLK_SCIFB1 + R8A7791_CLK_MSIOF1 R8A7791_CLK_SCIFB2 + >; + clock-output-names = + "scifa2", "scifa1", "scifa0", "misof2", "scifb0", + "scifb1", "msiof1", "scifb2"; + }; + mstp3_clks: mstp3_clks@e615013c { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; + clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>, + <&cpg_clocks R8A7791_CLK_SD0>, <&mmc0_clk>, <&rclk_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1 + R8A7791_CLK_SDHI0 R8A7791_CLK_MMCIF0 R8A7791_CLK_CMT1 + >; + clock-output-names = + "tpu0", "sdhi2", "sdhi1", "sdhi0", "mmcif0", "cmt1"; + }; + mstp5_clks: mstp5_clks@e6150144 { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>; + clocks = <&extal_clk>, <&p_clk>; + #clock-cells = <1>; + renesas,clock-indices = ; + clock-output-names = "thermal", "pwm"; + }; + mstp7_clks: mstp7_clks@e615014c { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>; + clocks = <&mp_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>, + <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, + <&zx_clk>, <&zx_clk>, <&zx_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7791_CLK_HSUSB R8A7791_CLK_HSCIF2 R8A7791_CLK_SCIF5 + R8A7791_CLK_SCIF4 R8A7791_CLK_HSCIF1 R8A7791_CLK_HSCIF0 + R8A7791_CLK_SCIF3 R8A7791_CLK_SCIF2 R8A7791_CLK_SCIF1 + R8A7791_CLK_SCIF0 R8A7791_CLK_DU1 R8A7791_CLK_DU0 + R8A7791_CLK_LVDS0 + >; + clock-output-names = + "hsusb", "hscif2", "scif5", "scif4", "hscif1", "hscif0", + "scif3", "scif2", "scif1", "scif0", "du1", "du0", "lvds0"; + }; + mstp8_clks: mstp8_clks@e6150990 { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; + clocks = <&p_clk>; + #clock-cells = <1>; + renesas,clock-indices = ; + clock-output-names = "ether"; + }; + mstp9_clks: mstp9_clks@e6150994 { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; + clocks = <&p_clk>, <&p_clk>, <&cpg_clocks R8A7791_CLK_QSPI>, + <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, + <&p_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7791_CLK_RCAN1 R8A7791_CLK_RCAN0 R8A7791_CLK_QSPI_MOD + R8A7791_CLK_I2C4 R8A7791_CLK_I2C4 R8A7791_CLK_I2C3 + R8A7791_CLK_I2C2 R8A7791_CLK_I2C1 R8A7791_CLK_I2C0 + >; + clock-output-names = + "rcan1", "rcan0", "qspi_mod", "i2c5", "i2c4", "i2c3", + "i2c2", "i2c1", "i2c0"; + }; + mstp10_clks: mstp10_clks@e6150998 { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>; + clocks = <&p_clk>, <&mstp10_clks R8A7791_CLK_SSI>, + <&mstp10_clks R8A7791_CLK_SSI>, <&mstp10_clks R8A7791_CLK_SSI>, + <&mstp10_clks R8A7791_CLK_SSI>, <&mstp10_clks R8A7791_CLK_SSI>, + <&mstp10_clks R8A7791_CLK_SSI>, <&mstp10_clks R8A7791_CLK_SSI>, + <&mstp10_clks R8A7791_CLK_SSI>, <&mstp10_clks R8A7791_CLK_SSI>, + <&mstp10_clks R8A7791_CLK_SSI>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7791_CLK_SSI R8A7791_CLK_SSI9 R8A7791_CLK_SSI8 + R8A7791_CLK_SSI7 R8A7791_CLK_SSI6 R8A7791_CLK_SSI5 + R8A7791_CLK_SSI4 R8A7791_CLK_SSI3 R8A7791_CLK_SSI2 + R8A7791_CLK_SSI1 R8A7791_CLK_SSI0 + >; + clock-output-names = + "ssi", "ssi9", "ssi8", "ssi7", "ssi6", "ssi5", + "ssi4", "ssi3", "ssi2", "ssi1", "ssi0"; + }; + mstp11_clks: mstp11_clks@e615099c { + compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>; + clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>; + #clock-cells = <1>; + renesas,clock-indices = < + R8A7791_CLK_SCIFA3 R8A7791_CLK_SCIFA4 R8A7791_CLK_SCIFA5 + >; + clock-output-names = "scifa3", "scifa4", "scifa5"; + }; + }; }; diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index c460dd229b13..b7bd3b9a6753 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -242,6 +242,15 @@ <0xe605801c 0x1c>; gpio-controller; #gpio-cells = <2>; + interrupts-extended = + <&irqpin0 0 0>, <&irqpin0 1 0>, <&irqpin0 2 0>, <&irqpin0 3 0>, + <&irqpin0 4 0>, <&irqpin0 5 0>, <&irqpin0 6 0>, <&irqpin0 7 0>, + <&irqpin1 0 0>, <&irqpin1 1 0>, <&irqpin1 2 0>, <&irqpin1 3 0>, + <&irqpin1 4 0>, <&irqpin1 5 0>, <&irqpin1 6 0>, <&irqpin1 7 0>, + <&irqpin2 0 0>, <&irqpin2 1 0>, <&irqpin2 2 0>, <&irqpin2 3 0>, + <&irqpin2 4 0>, <&irqpin2 5 0>, <&irqpin2 6 0>, <&irqpin2 7 0>, + <&irqpin3 0 0>, <&irqpin3 1 0>, <&irqpin3 2 0>, <&irqpin3 3 0>, + <&irqpin3 4 0>, <&irqpin3 5 0>, <&irqpin3 6 0>, <&irqpin3 7 0>; }; sh_fsi2: sound@ec230000 { diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index aa9017bb750c..8c8889211f6d 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -12,6 +12,7 @@ config ARCH_SHMOBILE_MULTI select HAVE_SMP select ARM_GIC select MIGHT_HAVE_CACHE_L2X0 + select MIGHT_HAVE_PCI select NO_IOPORT select PINCTRL select ARCH_REQUIRE_GPIOLIB @@ -96,6 +97,7 @@ config ARCH_R8A7790 select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_GIC select CPU_V7 + select MIGHT_HAVE_PCI select SH_CLK_CPG select RENESAS_IRQC @@ -104,6 +106,7 @@ config ARCH_R8A7791 select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_GIC select CPU_V7 + select MIGHT_HAVE_PCI select SH_CLK_CPG select RENESAS_IRQC @@ -112,6 +115,7 @@ config ARCH_EMEV2 select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_GIC select CPU_V7 + select MIGHT_HAVE_PCI select USE_OF select AUTO_ZRELADDR @@ -239,6 +243,7 @@ config MACH_KOELSCH bool "Koelsch board" depends on ARCH_R8A7791 select USE_OF + select MICREL_PHY if SH_ETH config MACH_KZM9G bool "KZM-A9-GT board" diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c index 38611526fe9a..44b55ef8857e 100644 --- a/arch/arm/mach-shmobile/board-bockw.c +++ b/arch/arm/mach-shmobile/board-bockw.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-shmobile/clock-r7s72100.c b/arch/arm/mach-shmobile/clock-r7s72100.c index 7b457aed8253..0814a508fd61 100644 --- a/arch/arm/mach-shmobile/clock-r7s72100.c +++ b/arch/arm/mach-shmobile/clock-r7s72100.c @@ -181,7 +181,6 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]), CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]), CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]), - CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]), }; void __init r7s72100_clock_init(void) diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c index 312376d2cfd1..c5c60ecdec8f 100644 --- a/arch/arm/mach-shmobile/clock-r8a7790.c +++ b/arch/arm/mach-shmobile/clock-r8a7790.c @@ -292,9 +292,13 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]), CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]), CLKDEV_DEV_ID("e6508000.i2c", &mstp_clks[MSTP931]), + CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP931]), CLKDEV_DEV_ID("e6518000.i2c", &mstp_clks[MSTP930]), + CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP930]), CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP929]), + CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP929]), CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP928]), + CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP928]), CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]), CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]), CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c index ff2d60d55bd5..f5461262ee25 100644 --- a/arch/arm/mach-shmobile/clock-r8a7791.c +++ b/arch/arm/mach-shmobile/clock-r8a7791.c @@ -122,6 +122,7 @@ static struct clk *main_clks[] = { /* MSTP */ enum { + MSTP813, MSTP726, MSTP724, MSTP723, MSTP721, MSTP720, MSTP719, MSTP718, MSTP715, MSTP714, MSTP522, @@ -132,6 +133,7 @@ enum { }; static struct clk mstp_clks[MSTP_NR] = { + [MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */ [MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */ [MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */ [MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */ @@ -192,6 +194,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]), CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]), CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), + CLKDEV_DEV_ID("r8a7791-ether", &mstp_clks[MSTP813]), /* Ether */ }; #define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31) \ diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 30d88689a960..23edf8360c27 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -652,6 +652,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */ + CLKDEV_DEV_ID("ec230000.sound", &mstp_clks[MSTP328]), /* FSI */ CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */ diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h index b497f932d04f..f4076a50e970 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7778.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h @@ -20,13 +20,30 @@ #define __ASM_R8A7778_H__ #include -#include /* HPB-DMA slave IDs */ enum { HPBDMA_SLAVE_DUMMY, HPBDMA_SLAVE_SDHI0_TX, HPBDMA_SLAVE_SDHI0_RX, + HPBDMA_SLAVE_SSI0_TX, + HPBDMA_SLAVE_SSI0_RX, + HPBDMA_SLAVE_SSI1_TX, + HPBDMA_SLAVE_SSI1_RX, + HPBDMA_SLAVE_SSI2_TX, + HPBDMA_SLAVE_SSI2_RX, + HPBDMA_SLAVE_SSI3_TX, + HPBDMA_SLAVE_SSI3_RX, + HPBDMA_SLAVE_SSI4_TX, + HPBDMA_SLAVE_SSI4_RX, + HPBDMA_SLAVE_SSI5_TX, + HPBDMA_SLAVE_SSI5_RX, + HPBDMA_SLAVE_SSI6_TX, + HPBDMA_SLAVE_SSI6_RX, + HPBDMA_SLAVE_SSI7_TX, + HPBDMA_SLAVE_SSI7_RX, + HPBDMA_SLAVE_SSI8_TX, + HPBDMA_SLAVE_SSI8_RX, HPBDMA_SLAVE_HPBIF0_TX, HPBDMA_SLAVE_HPBIF0_RX, HPBDMA_SLAVE_HPBIF1_TX, @@ -45,6 +62,8 @@ enum { HPBDMA_SLAVE_HPBIF7_RX, HPBDMA_SLAVE_HPBIF8_TX, HPBDMA_SLAVE_HPBIF8_RX, + HPBDMA_SLAVE_USBFUNC_TX, + HPBDMA_SLAVE_USBFUNC_RX, }; extern void r8a7778_add_standard_devices(void); diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index 81701cfb6cc6..7ea6308e5da8 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c @@ -319,6 +319,29 @@ void __init r8a7778_add_dt_devices(void) #define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE BIT(1) /* SDHI0 */ #define HPB_DMAE_ASYNCMDR_ASMD21_MULTI 0 /* SDHI0 */ +#define HPBDMA_SSI(_id) \ +{ \ + .id = HPBDMA_SLAVE_SSI## _id ##_TX, \ + .addr = 0xffd91008 + (_id * 0x40), \ + .dcr = HPB_DMAE_DCR_CT | \ + HPB_DMAE_DCR_DIP | \ + HPB_DMAE_DCR_SPDS_32BIT | \ + HPB_DMAE_DCR_DMDL | \ + HPB_DMAE_DCR_DPDS_32BIT, \ + .port = _id + (_id << 8), \ + .dma_ch = (28 + _id), \ +}, { \ + .id = HPBDMA_SLAVE_SSI## _id ##_RX, \ + .addr = 0xffd9100c + (_id * 0x40), \ + .dcr = HPB_DMAE_DCR_CT | \ + HPB_DMAE_DCR_DIP | \ + HPB_DMAE_DCR_SMDL | \ + HPB_DMAE_DCR_SPDS_32BIT | \ + HPB_DMAE_DCR_DPDS_32BIT, \ + .port = _id + (_id << 8), \ + .dma_ch = (28 + _id), \ +} + #define HPBDMA_HPBIF(_id) \ { \ .id = HPBDMA_SLAVE_HPBIF## _id ##_TX, \ @@ -371,8 +394,34 @@ static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = { .port = 0x0D0C, .flags = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE, .dma_ch = 22, + }, { + .id = HPBDMA_SLAVE_USBFUNC_TX, /* for D0 */ + .addr = 0xffe60018, + .dcr = HPB_DMAE_DCR_SPDS_32BIT | + HPB_DMAE_DCR_DMDL | + HPB_DMAE_DCR_DPDS_32BIT, + .port = 0x0000, + .dma_ch = 14, + }, { + .id = HPBDMA_SLAVE_USBFUNC_RX, /* for D1 */ + .addr = 0xffe6001c, + .dcr = HPB_DMAE_DCR_SMDL | + HPB_DMAE_DCR_SPDS_32BIT | + HPB_DMAE_DCR_DPDS_32BIT, + .port = 0x0101, + .dma_ch = 15, }, + HPBDMA_SSI(0), + HPBDMA_SSI(1), + HPBDMA_SSI(2), + HPBDMA_SSI(3), + HPBDMA_SSI(4), + HPBDMA_SSI(5), + HPBDMA_SSI(6), + HPBDMA_SSI(7), + HPBDMA_SSI(8), + HPBDMA_HPBIF(0), HPBDMA_HPBIF(1), HPBDMA_HPBIF(2), @@ -385,24 +434,44 @@ static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = { }; static const struct hpb_dmae_channel hpb_dmae_channels[] = { + HPB_DMAE_CHANNEL(0x7c, HPBDMA_SLAVE_USBFUNC_TX), /* ch. 14 */ + HPB_DMAE_CHANNEL(0x7c, HPBDMA_SLAVE_USBFUNC_RX), /* ch. 15 */ HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */ HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI0_TX), /* ch. 28 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI0_RX), /* ch. 28 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_TX), /* ch. 28 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_RX), /* ch. 28 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI1_TX), /* ch. 29 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI1_RX), /* ch. 29 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_TX), /* ch. 29 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_RX), /* ch. 29 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI2_TX), /* ch. 30 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI2_RX), /* ch. 30 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_TX), /* ch. 30 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_RX), /* ch. 30 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI3_TX), /* ch. 31 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI3_RX), /* ch. 31 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_TX), /* ch. 31 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_RX), /* ch. 31 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI4_TX), /* ch. 32 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI4_RX), /* ch. 32 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_TX), /* ch. 32 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_RX), /* ch. 32 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI5_TX), /* ch. 33 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI5_RX), /* ch. 33 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_TX), /* ch. 33 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_RX), /* ch. 33 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI6_TX), /* ch. 34 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI6_RX), /* ch. 34 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_TX), /* ch. 34 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_RX), /* ch. 34 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI7_TX), /* ch. 35 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI7_RX), /* ch. 35 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_TX), /* ch. 35 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_RX), /* ch. 35 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI8_TX), /* ch. 36 */ + HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_SSI8_RX), /* ch. 36 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_TX), /* ch. 36 */ HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_RX), /* ch. 36 */ }; diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index 3543c3bacb75..8474818a7ae0 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -67,6 +67,27 @@ R8A7790_GPIO(5); &r8a7790_gpio##idx##_platform_data, \ sizeof(r8a7790_gpio##idx##_platform_data)) +static struct resource i2c_resources[] __initdata = { + /* I2C0 */ + DEFINE_RES_MEM(0xE6508000, 0x40), + DEFINE_RES_IRQ(gic_spi(287)), + /* I2C1 */ + DEFINE_RES_MEM(0xE6518000, 0x40), + DEFINE_RES_IRQ(gic_spi(288)), + /* I2C2 */ + DEFINE_RES_MEM(0xE6530000, 0x40), + DEFINE_RES_IRQ(gic_spi(286)), + /* I2C3 */ + DEFINE_RES_MEM(0xE6540000, 0x40), + DEFINE_RES_IRQ(gic_spi(290)), + +}; + +#define r8a7790_register_i2c(idx) \ + platform_device_register_simple( \ + "i2c-rcar", idx, \ + i2c_resources + (2 * idx), 2); \ + void __init r8a7790_pinmux_init(void) { r8a7790_register_pfc(); @@ -76,6 +97,10 @@ void __init r8a7790_pinmux_init(void) r8a7790_register_gpio(3); r8a7790_register_gpio(4); r8a7790_register_gpio(5); + r8a7790_register_i2c(0); + r8a7790_register_i2c(1); + r8a7790_register_i2c(2); + r8a7790_register_i2c(3); } #define SCIF_COMMON(scif_type, baseaddr, irq) \ diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 5734c24bf6c7..69ccc6c6fd33 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -44,8 +45,10 @@ u32 __init rcar_gen2_read_mode_pins(void) void __init rcar_gen2_timer_init(void) { -#ifdef CONFIG_ARM_ARCH_TIMER +#if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK) u32 mode = rcar_gen2_read_mode_pins(); +#endif +#ifdef CONFIG_ARM_ARCH_TIMER void __iomem *base; int extal_mhz = 0; u32 freq; @@ -78,14 +81,28 @@ void __init rcar_gen2_timer_init(void) /* Remap "armgcnt address map" space */ base = ioremap(0xe6080000, PAGE_SIZE); - /* Update registers with correct frequency */ - iowrite32(freq, base + CNTFID0); - asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq)); + /* + * Update the timer if it is either not running, or is not at the + * right frequency. The timer is only configurable in secure mode + * so this avoids an abort if the loader started the timer and + * entered the kernel in non-secure mode. + */ + + if ((ioread32(base + CNTCR) & 1) == 0 || + ioread32(base + CNTFID0) != freq) { + /* Update registers with correct frequency */ + iowrite32(freq, base + CNTFID0); + asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq)); + + /* make sure arch timer is started by setting bit 0 of CNTCR */ + iowrite32(1, base + CNTCR); + } - /* make sure arch timer is started by setting bit 0 of CNTCR */ - iowrite32(1, base + CNTCR); iounmap(base); #endif /* CONFIG_ARM_ARCH_TIMER */ +#ifdef CONFIG_COMMON_CLK + rcar_gen2_clocks_init(mode); +#endif clocksource_of_init(); } diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index ace7309c4369..a3b7c5dd3c16 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ obj-$(CONFIG_COMMON_CLK_AT91) += at91/ +obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ obj-$(CONFIG_X86) += x86/ diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile new file mode 100644 index 000000000000..706adc6ae70c --- /dev/null +++ b/drivers/clk/shmobile/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o +obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o +obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o +obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o + +# for emply built-in.o +obj-n := dummy diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c new file mode 100644 index 000000000000..aac4756ec52e --- /dev/null +++ b/drivers/clk/shmobile/clk-div6.c @@ -0,0 +1,185 @@ +/* + * r8a7790 Common Clock Framework support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * + * Contact: Laurent Pinchart + * + * 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; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CPG_DIV6_CKSTP BIT(8) +#define CPG_DIV6_DIV(d) ((d) & 0x3f) +#define CPG_DIV6_DIV_MASK 0x3f + +/** + * struct div6_clock - MSTP gating clock + * @hw: handle between common and hardware-specific interfaces + * @reg: IO-remapped register + * @div: divisor value (1-64) + */ +struct div6_clock { + struct clk_hw hw; + void __iomem *reg; + unsigned int div; +}; + +#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) + +static int cpg_div6_clock_enable(struct clk_hw *hw) +{ + struct div6_clock *clock = to_div6_clock(hw); + + clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg); + + return 0; +} + +static void cpg_div6_clock_disable(struct clk_hw *hw) +{ + struct div6_clock *clock = to_div6_clock(hw); + + /* DIV6 clocks require the divisor field to be non-zero when stopping + * the clock. + */ + clk_writel(CPG_DIV6_CKSTP | CPG_DIV6_DIV(CPG_DIV6_DIV_MASK), + clock->reg); +} + +static int cpg_div6_clock_is_enabled(struct clk_hw *hw) +{ + struct div6_clock *clock = to_div6_clock(hw); + + return !(clk_readl(clock->reg) & CPG_DIV6_CKSTP); +} + +static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct div6_clock *clock = to_div6_clock(hw); + unsigned int div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; + + return parent_rate / div; +} + +static unsigned int cpg_div6_clock_calc_div(unsigned long rate, + unsigned long parent_rate) +{ + unsigned int div; + + div = DIV_ROUND_CLOSEST(parent_rate, rate); + return clamp_t(unsigned int, div, 1, 64); +} + +static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate); + + return *parent_rate / div; +} + +static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct div6_clock *clock = to_div6_clock(hw); + unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate); + + clock->div = div; + + /* Only program the new divisor if the clock isn't stopped. */ + if (!(clk_readl(clock->reg) & CPG_DIV6_CKSTP)) + clk_writel(CPG_DIV6_DIV(clock->div - 1), clock->reg); + + return 0; +} + +static const struct clk_ops cpg_div6_clock_ops = { + .enable = cpg_div6_clock_enable, + .disable = cpg_div6_clock_disable, + .is_enabled = cpg_div6_clock_is_enabled, + .recalc_rate = cpg_div6_clock_recalc_rate, + .round_rate = cpg_div6_clock_round_rate, + .set_rate = cpg_div6_clock_set_rate, +}; + +static void __init cpg_div6_clock_init(struct device_node *np) +{ + struct clk_init_data init; + struct div6_clock *clock; + const char *parent_name; + const char *name; + struct clk *clk; + int ret; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) { + pr_err("%s: failed to allocate %s DIV6 clock\n", + __func__, np->name); + return; + } + + /* Remap the clock register and read the divisor. Disabling the + * clock overwrites the divisor, so we need to cache its value for the + * enable operation. + */ + clock->reg = of_iomap(np, 0); + if (clock->reg == NULL) { + pr_err("%s: failed to map %s DIV6 clock register\n", + __func__, np->name); + goto error; + } + + clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; + + /* Parse the DT properties. */ + ret = of_property_read_string(np, "clock-output-names", &name); + if (ret < 0) { + pr_err("%s: failed to get %s DIV6 clock output name\n", + __func__, np->name); + goto error; + } + + parent_name = of_clk_get_parent_name(np, 0); + if (parent_name == NULL) { + pr_err("%s: failed to get %s DIV6 clock parent name\n", + __func__, np->name); + goto error; + } + + /* Register the clock. */ + init.name = name; + init.ops = &cpg_div6_clock_ops; + init.flags = CLK_IS_BASIC; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->hw.init = &init; + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register %s DIV6 clock (%ld)\n", + __func__, np->name, PTR_ERR(clk)); + goto error; + } + + of_clk_add_provider(np, of_clk_src_simple_get, clk); + + return; + +error: + if (clock->reg) + iounmap(clock->reg); + kfree(clock); +} +CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init); diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c new file mode 100644 index 000000000000..e576b60de20e --- /dev/null +++ b/drivers/clk/shmobile/clk-mstp.c @@ -0,0 +1,229 @@ +/* + * R-Car MSTP clocks + * + * Copyright (C) 2013 Ideas On Board SPRL + * + * Contact: Laurent Pinchart + * + * 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; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include + +/* + * MSTP clocks. We can't use standard gate clocks as we need to poll on the + * status register when enabling the clock. + */ + +#define MSTP_MAX_CLOCKS 32 + +/** + * struct mstp_clock_group - MSTP gating clocks group + * + * @data: clocks in this group + * @smstpcr: module stop control register + * @mstpsr: module stop status register (optional) + * @lock: protects writes to SMSTPCR + */ +struct mstp_clock_group { + struct clk_onecell_data data; + void __iomem *smstpcr; + void __iomem *mstpsr; + spinlock_t lock; +}; + +/** + * struct mstp_clock - MSTP gating clock + * @hw: handle between common and hardware-specific interfaces + * @bit_index: control bit index + * @group: MSTP clocks group + */ +struct mstp_clock { + struct clk_hw hw; + u32 bit_index; + struct mstp_clock_group *group; +}; + +#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw) + +static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) +{ + struct mstp_clock *clock = to_mstp_clock(hw); + struct mstp_clock_group *group = clock->group; + u32 bitmask = BIT(clock->bit_index); + unsigned long flags; + unsigned int i; + u32 value; + + spin_lock_irqsave(&group->lock, flags); + + value = clk_readl(group->smstpcr); + if (enable) + value &= ~bitmask; + else + value |= bitmask; + clk_writel(value, group->smstpcr); + + spin_unlock_irqrestore(&group->lock, flags); + + if (!enable || !group->mstpsr) + return 0; + + for (i = 1000; i > 0; --i) { + if (!(clk_readl(group->mstpsr) & bitmask)) + break; + cpu_relax(); + } + + if (!i) { + pr_err("%s: failed to enable %p[%d]\n", __func__, + group->smstpcr, clock->bit_index); + return -ETIMEDOUT; + } + + return 0; +} + +static int cpg_mstp_clock_enable(struct clk_hw *hw) +{ + return cpg_mstp_clock_endisable(hw, true); +} + +static void cpg_mstp_clock_disable(struct clk_hw *hw) +{ + cpg_mstp_clock_endisable(hw, false); +} + +static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) +{ + struct mstp_clock *clock = to_mstp_clock(hw); + struct mstp_clock_group *group = clock->group; + u32 value; + + if (group->mstpsr) + value = clk_readl(group->mstpsr); + else + value = clk_readl(group->smstpcr); + + return !!(value & BIT(clock->bit_index)); +} + +static const struct clk_ops cpg_mstp_clock_ops = { + .enable = cpg_mstp_clock_enable, + .disable = cpg_mstp_clock_disable, + .is_enabled = cpg_mstp_clock_is_enabled, +}; + +static struct clk * __init +cpg_mstp_clock_register(const char *name, const char *parent_name, + unsigned int index, struct mstp_clock_group *group) +{ + struct clk_init_data init; + struct mstp_clock *clock; + struct clk *clk; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) { + pr_err("%s: failed to allocate MSTP clock.\n", __func__); + return ERR_PTR(-ENOMEM); + } + + init.name = name; + init.ops = &cpg_mstp_clock_ops; + init.flags = CLK_IS_BASIC; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->bit_index = index; + clock->group = group; + clock->hw.init = &init; + + clk = clk_register(NULL, &clock->hw); + + if (IS_ERR(clk)) + kfree(clock); + + return clk; +} + +static void __init cpg_mstp_clocks_init(struct device_node *np) +{ + struct mstp_clock_group *group; + struct clk **clks; + unsigned int i; + + group = kzalloc(sizeof(*group), GFP_KERNEL); + clks = kzalloc(MSTP_MAX_CLOCKS * sizeof(*clks), GFP_KERNEL); + if (group == NULL || clks == NULL) { + kfree(group); + kfree(clks); + pr_err("%s: failed to allocate group\n", __func__); + return; + } + + spin_lock_init(&group->lock); + group->data.clks = clks; + + group->smstpcr = of_iomap(np, 0); + group->mstpsr = of_iomap(np, 1); + + if (group->smstpcr == NULL) { + pr_err("%s: failed to remap SMSTPCR\n", __func__); + kfree(group); + kfree(clks); + return; + } + + for (i = 0; i < MSTP_MAX_CLOCKS; ++i) { + const char *parent_name; + const char *name; + u32 clkidx; + int ret; + + /* Skip clocks with no name. */ + ret = of_property_read_string_index(np, "clock-output-names", + i, &name); + if (ret < 0 || strlen(name) == 0) + continue; + + parent_name = of_clk_get_parent_name(np, i); + ret = of_property_read_u32_index(np, "renesas,clock-indices", i, + &clkidx); + if (parent_name == NULL || ret < 0) + break; + + if (clkidx >= MSTP_MAX_CLOCKS) { + pr_err("%s: invalid clock %s %s index %u)\n", + __func__, np->name, name, clkidx); + continue; + } + + clks[clkidx] = cpg_mstp_clock_register(name, parent_name, i, + group); + if (!IS_ERR(clks[clkidx])) { + group->data.clk_num = max(group->data.clk_num, clkidx); + /* + * Register a clkdev to let board code retrieve the + * clock by name and register aliases for non-DT + * devices. + * + * FIXME: Remove this when all devices that require a + * clock will be instantiated from DT. + */ + clk_register_clkdev(clks[clkidx], name, NULL); + } else { + pr_err("%s: failed to register %s %s clock (%ld)\n", + __func__, np->name, name, PTR_ERR(clks[clkidx])); + } + } + + of_clk_add_provider(np, of_clk_src_onecell_get, &group->data); +} +CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init); diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c new file mode 100644 index 000000000000..a59ec217a124 --- /dev/null +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -0,0 +1,298 @@ +/* + * rcar_gen2 Core CPG Clocks + * + * Copyright (C) 2013 Ideas On Board SPRL + * + * Contact: Laurent Pinchart + * + * 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; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct rcar_gen2_cpg { + struct clk_onecell_data data; + spinlock_t lock; + void __iomem *reg; +}; + +#define CPG_SDCKCR 0x00000074 +#define CPG_PLL0CR 0x000000d8 +#define CPG_FRQCRC 0x000000e0 +#define CPG_FRQCRC_ZFC_MASK (0x1f << 8) +#define CPG_FRQCRC_ZFC_SHIFT 8 + +/* ----------------------------------------------------------------------------- + * Z Clock + * + * Traits of this clock: + * prepare - clk_prepare only ensures that parents are prepared + * enable - clk_enable only ensures that parents are enabled + * rate - rate is adjustable. clk->rate = parent->rate * mult / 32 + * parent - fixed parent. No clk_set_parent support + */ + +struct cpg_z_clk { + struct clk_hw hw; + void __iomem *reg; +}; + +#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) + +static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cpg_z_clk *zclk = to_z_clk(hw); + unsigned int mult; + unsigned int val; + + val = (clk_readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) + >> CPG_FRQCRC_ZFC_SHIFT; + mult = 32 - val; + + return div_u64((u64)parent_rate * mult, 32); +} + +static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long prate = *parent_rate; + unsigned int mult; + + if (!prate) + prate = 1; + + mult = div_u64((u64)rate * 32, prate); + mult = clamp(mult, 1U, 32U); + + return *parent_rate / 32 * mult; +} + +static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cpg_z_clk *zclk = to_z_clk(hw); + unsigned int mult; + u32 val; + + mult = div_u64((u64)rate * 32, parent_rate); + mult = clamp(mult, 1U, 32U); + + val = clk_readl(zclk->reg); + val &= ~CPG_FRQCRC_ZFC_MASK; + val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT; + clk_writel(val, zclk->reg); + + return 0; +} + +static const struct clk_ops cpg_z_clk_ops = { + .recalc_rate = cpg_z_clk_recalc_rate, + .round_rate = cpg_z_clk_round_rate, + .set_rate = cpg_z_clk_set_rate, +}; + +static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg) +{ + static const char *parent_name = "pll0"; + struct clk_init_data init; + struct cpg_z_clk *zclk; + struct clk *clk; + + zclk = kzalloc(sizeof(*zclk), GFP_KERNEL); + if (!zclk) + return ERR_PTR(-ENOMEM); + + init.name = "z"; + init.ops = &cpg_z_clk_ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + + zclk->reg = cpg->reg + CPG_FRQCRC; + zclk->hw.init = &init; + + clk = clk_register(NULL, &zclk->hw); + if (IS_ERR(clk)) + kfree(zclk); + + return clk; +} + +/* ----------------------------------------------------------------------------- + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL3 + * 14 13 19 (MHz) *1 *1 + *--------------------------------------------------- + * 0 0 0 15 x 1 x172/2 x208/2 x106 + * 0 0 1 15 x 1 x172/2 x208/2 x88 + * 0 1 0 20 x 1 x130/2 x156/2 x80 + * 0 1 1 20 x 1 x130/2 x156/2 x66 + * 1 0 0 26 / 2 x200/2 x240/2 x122 + * 1 0 1 26 / 2 x200/2 x240/2 x102 + * 1 1 0 30 / 2 x172/2 x208/2 x106 + * 1 1 1 30 / 2 x172/2 x208/2 x88 + * + * *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2) + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ + (((md) & BIT(13)) >> 12) | \ + (((md) & BIT(19)) >> 19)) +struct cpg_pll_config { + unsigned int extal_div; + unsigned int pll1_mult; + unsigned int pll3_mult; +}; + +static const struct cpg_pll_config cpg_pll_configs[8] __initconst = { + { 1, 208, 106 }, { 1, 208, 88 }, { 1, 156, 80 }, { 1, 156, 66 }, + { 2, 240, 122 }, { 2, 240, 102 }, { 2, 208, 106 }, { 2, 208, 88 }, +}; + +/* SDHI divisors */ +static const struct clk_div_table cpg_sdh_div_table[] = { + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, + { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, + { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 }, +}; + +static const struct clk_div_table cpg_sd01_div_table[] = { + { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, + { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, +}; + +/* ----------------------------------------------------------------------------- + * Initialization + */ + +static u32 cpg_mode __initdata; + +static struct clk * __init +rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg, + const struct cpg_pll_config *config, + const char *name) +{ + const struct clk_div_table *table = NULL; + const char *parent_name = "main"; + unsigned int shift; + unsigned int mult = 1; + unsigned int div = 1; + + if (!strcmp(name, "main")) { + parent_name = of_clk_get_parent_name(np, 0); + div = config->extal_div; + } else if (!strcmp(name, "pll0")) { + /* PLL0 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + u32 value = clk_readl(cpg->reg + CPG_PLL0CR); + mult = ((value >> 24) & ((1 << 7) - 1)) + 1; + } else if (!strcmp(name, "pll1")) { + mult = config->pll1_mult / 2; + } else if (!strcmp(name, "pll3")) { + mult = config->pll3_mult; + } else if (!strcmp(name, "lb")) { + div = cpg_mode & BIT(18) ? 36 : 24; + } else if (!strcmp(name, "qspi")) { + div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) + ? 16 : 20; + } else if (!strcmp(name, "sdh")) { + table = cpg_sdh_div_table; + shift = 8; + } else if (!strcmp(name, "sd0")) { + table = cpg_sd01_div_table; + shift = 4; + } else if (!strcmp(name, "sd1")) { + table = cpg_sd01_div_table; + shift = 0; + } else if (!strcmp(name, "z")) { + return cpg_z_clk_register(cpg); + } else { + return ERR_PTR(-EINVAL); + } + + if (!table) + return clk_register_fixed_factor(NULL, name, parent_name, 0, + mult, div); + else + return clk_register_divider_table(NULL, name, parent_name, 0, + cpg->reg + CPG_SDCKCR, shift, + 4, 0, table, &cpg->lock); +} + +static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) +{ + const struct cpg_pll_config *config; + struct rcar_gen2_cpg *cpg; + struct clk **clks; + unsigned int i; + int num_clks; + + num_clks = of_property_count_strings(np, "clock-output-names"); + if (num_clks < 0) { + pr_err("%s: failed to count clocks\n", __func__); + return; + } + + cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); + clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); + if (cpg == NULL || clks == NULL) { + /* We're leaking memory on purpose, there's no point in cleaning + * up as the system won't boot anyway. + */ + pr_err("%s: failed to allocate cpg\n", __func__); + return; + } + + spin_lock_init(&cpg->lock); + + cpg->data.clks = clks; + cpg->data.clk_num = num_clks; + + cpg->reg = of_iomap(np, 0); + if (WARN_ON(cpg->reg == NULL)) + return; + + config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + + for (i = 0; i < num_clks; ++i) { + const char *name; + struct clk *clk; + + of_property_read_string_index(np, "clock-output-names", i, + &name); + + clk = rcar_gen2_cpg_register_clock(np, cpg, config, name); + if (IS_ERR(clk)) + pr_err("%s: failed to register %s %s clock (%ld)\n", + __func__, np->name, name, PTR_ERR(clk)); + else + cpg->data.clks[i] = clk; + } + + of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); +} +CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks", + rcar_gen2_cpg_clocks_init); + +void __init rcar_gen2_clocks_init(u32 mode) +{ + cpg_mode = mode; + + of_clk_init(NULL); +} diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 0965e9848b3d..940341a185d7 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -634,12 +634,18 @@ static int sh_cmt_clock_event_next(unsigned long delta, static void sh_cmt_clock_event_suspend(struct clock_event_device *ced) { - pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev); + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); + + pm_genpd_syscore_poweroff(&p->pdev->dev); + clk_unprepare(p->clk); } static void sh_cmt_clock_event_resume(struct clock_event_device *ced) { - pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev); + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); + + clk_prepare(p->clk); + pm_genpd_syscore_poweron(&p->pdev->dev); } static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, @@ -737,6 +743,10 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) goto err2; } + ret = clk_prepare(p->clk); + if (ret < 0) + goto err3; + if (res2 && (resource_size(res2) == 4)) { /* assume both CMSTR and CMCSR to be 32-bit */ p->read_control = sh_cmt_read32; @@ -773,19 +783,21 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) cfg->clocksource_rating); if (ret) { dev_err(&p->pdev->dev, "registration failed\n"); - goto err3; + goto err4; } p->cs_enabled = false; ret = setup_irq(irq, &p->irqaction); if (ret) { dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); - goto err3; + goto err4; } platform_set_drvdata(pdev, p); return 0; +err4: + clk_unprepare(p->clk); err3: clk_put(p->clk); err2: diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 33f9dc1f14fd..30fcb897eb99 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -116,15 +116,22 @@ config PINCTRL_IMX1_CORE config PINCTRL_IMX27 bool "IMX27 pinctrl driver" - depends on OF depends on SOC_IMX27 select PINCTRL_IMX1_CORE help Say Y here to enable the imx27 pinctrl driver + +config PINCTRL_IMX25 + bool "IMX25 pinctrl driver" + depends on OF + depends on SOC_IMX25 + select PINCTRL_IMX + help + Say Y here to enable the imx25 pinctrl driver + config PINCTRL_IMX35 bool "IMX35 pinctrl driver" - depends on OF depends on SOC_IMX35 select PINCTRL_IMX help @@ -132,7 +139,6 @@ config PINCTRL_IMX35 config PINCTRL_IMX50 bool "IMX50 pinctrl driver" - depends on OF depends on SOC_IMX50 select PINCTRL_IMX help @@ -140,7 +146,6 @@ config PINCTRL_IMX50 config PINCTRL_IMX51 bool "IMX51 pinctrl driver" - depends on OF depends on SOC_IMX51 select PINCTRL_IMX help @@ -148,7 +153,6 @@ config PINCTRL_IMX51 config PINCTRL_IMX53 bool "IMX53 pinctrl driver" - depends on OF depends on SOC_IMX53 select PINCTRL_IMX help @@ -156,7 +160,6 @@ config PINCTRL_IMX53 config PINCTRL_IMX6Q bool "IMX6Q/DL pinctrl driver" - depends on OF depends on SOC_IMX6Q select PINCTRL_IMX help @@ -164,7 +167,6 @@ config PINCTRL_IMX6Q config PINCTRL_IMX6SL bool "IMX6SL pinctrl driver" - depends on OF depends on SOC_IMX6SL select PINCTRL_IMX help @@ -172,7 +174,6 @@ config PINCTRL_IMX6SL config PINCTRL_VF610 bool "Freescale Vybrid VF610 pinctrl driver" - depends on OF depends on SOC_VF610 select PINCTRL_IMX help @@ -202,6 +203,17 @@ config PINCTRL_IMX28 bool select PINCTRL_MXS +config PINCTRL_MSM + bool + select PINMUX + select PINCONF + select GENERIC_PINCONF + +config PINCTRL_MSM8X74 + bool "Qualcomm 8x74 pin controller driver" + depends on OF && OF_IRQ + select PINCTRL_MSM + config PINCTRL_NOMADIK bool "Nomadik pin controller driver" depends on ARCH_U8500 || ARCH_NOMADIK diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 4f7be2921aa5..5d91e4b448d4 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -34,7 +34,10 @@ obj-$(CONFIG_PINCTRL_IMX6SL) += pinctrl-imx6sl.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o +obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o +obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o +obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index b8fcc38c0d11..4187fe58794d 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -28,12 +28,6 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev) { const struct pinconf_ops *ops = pctldev->desc->confops; - /* We must be able to read out pin status */ - if (!ops->pin_config_get && !ops->pin_config_group_get) { - dev_err(pctldev->dev, - "pinconf must be able to read out pin status\n"); - return -EINVAL; - } /* We have to be able to config the pins in SOME way */ if (!ops->pin_config_set && !ops->pin_config_group_set) { dev_err(pctldev->dev, @@ -67,9 +61,9 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, const struct pinconf_ops *ops = pctldev->desc->confops; if (!ops || !ops->pin_config_get) { - dev_err(pctldev->dev, "cannot get pin configuration, missing " + dev_dbg(pctldev->dev, "cannot get pin configuration, missing " "pin_config_get() function in driver\n"); - return -EINVAL; + return -ENOTSUPP; } return ops->pin_config_get(pctldev, pin, config); @@ -93,10 +87,10 @@ int pin_config_group_get(const char *dev_name, const char *pin_group, ops = pctldev->desc->confops; if (!ops || !ops->pin_config_group_get) { - dev_err(pctldev->dev, "cannot get configuration for pin " + dev_dbg(pctldev->dev, "cannot get configuration for pin " "group, missing group config get function in " "driver\n"); - ret = -EINVAL; + ret = -ENOTSUPP; goto unlock; } @@ -305,9 +299,6 @@ static int pinconf_pins_show(struct seq_file *s, void *what) const struct pinconf_ops *ops = pctldev->desc->confops; unsigned i, pin; - if (!ops || !ops->pin_config_get) - return 0; - seq_puts(s, "Pin config settings per pin\n"); seq_puts(s, "Format: pin (name): configs\n"); @@ -356,9 +347,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) unsigned ngroups = pctlops->get_groups_count(pctldev); unsigned selector = 0; - if (!ops || !ops->pin_config_group_get) - return 0; - seq_puts(s, "Pin config settings per pin group\n"); seq_puts(s, "Format: group (name): configs\n"); diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index a7549c4c83b4..b0b78f3468ae 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -118,7 +118,7 @@ struct at91_pin_group { }; /** - * struct at91_pinctrl_mux_ops - describes an At91 mux ops group + * struct at91_pinctrl_mux_ops - describes an AT91 mux ops group * on new IP with support for periph C and D the way to mux in * periph A and B has changed * So provide the right call back @@ -722,7 +722,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin; int div; - dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config); + *config = 0; + dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id); pio = pin_to_controller(info, pin_to_bank(pin_id)); pin = pin_id % MAX_NB_GPIO_PER_BANK; @@ -1396,7 +1397,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) chained_irq_enter(chip, desc); for (;;) { /* Reading ISR acks pending (edge triggered) GPIO interrupts. - * When there none are pending, we're finished unless we need + * When there are none pending, we're finished unless we need * to process multiple banks (like ID_PIOCDE on sam9263). */ isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR); @@ -1505,7 +1506,7 @@ static int at91_gpio_of_irq_setup(struct device_node *node, prev = gpio_chips[at91_gpio->pioc_idx - 1]; /* The top level handler handles one bank of GPIOs, except - * on some SoC it can handles up to three... + * on some SoC it can handle up to three... * We only set up the handler for the first of the list. */ if (prev && prev->next == at91_gpio) diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c index 2832576d8b12..5888066d80c2 100644 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ b/drivers/pinctrl/pinctrl-baytrail.c @@ -286,13 +286,19 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) spin_lock_irqsave(&vg->lock, flags); for (i = 0; i < vg->chip.ngpio; i++) { + const char *label; offs = vg->range->pins[i] * 16; conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); val = readl(vg->reg_base + offs + BYT_VAL_REG); + label = gpiochip_is_requested(chip, i); + if (!label) + label = "Unrequested"; + seq_printf(s, - " gpio-%-3d %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n", + " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n", i, + label, val & BYT_INPUT_EN ? " " : "in", val & BYT_OUTPUT_EN ? " " : "out", val & BYT_LEVEL ? "hi" : "lo", @@ -366,11 +372,33 @@ static void byt_irq_mask(struct irq_data *d) { } +static unsigned int byt_irq_startup(struct irq_data *d) +{ + struct byt_gpio *vg = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&vg->chip, irqd_to_hwirq(d))) + dev_err(vg->chip.dev, + "unable to lock HW IRQ %lu for IRQ\n", + irqd_to_hwirq(d)); + byt_irq_unmask(d); + return 0; +} + +static void byt_irq_shutdown(struct irq_data *d) +{ + struct byt_gpio *vg = irq_data_get_irq_chip_data(d); + + byt_irq_mask(d); + gpio_unlock_as_irq(&vg->chip, irqd_to_hwirq(d)); +} + static struct irq_chip byt_irqchip = { .name = "BYT-GPIO", .irq_mask = byt_irq_mask, .irq_unmask = byt_irq_unmask, .irq_set_type = byt_irq_type, + .irq_startup = byt_irq_startup, + .irq_shutdown = byt_irq_shutdown, }; static void byt_gpio_irq_init_hw(struct byt_gpio *vg) diff --git a/drivers/pinctrl/pinctrl-imx1-core.c b/drivers/pinctrl/pinctrl-imx1-core.c index f77914ac081a..17aecde1b51d 100644 --- a/drivers/pinctrl/pinctrl-imx1-core.c +++ b/drivers/pinctrl/pinctrl-imx1-core.c @@ -638,6 +638,13 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev, return -EINVAL; } + ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + if (ret) { + pinctrl_unregister(ipctl->pctl); + dev_err(&pdev->dev, "Failed to populate subdevices\n"); + return ret; + } + dev_info(&pdev->dev, "initialized IMX pinctrl driver\n"); return 0; diff --git a/drivers/pinctrl/pinctrl-imx25.c b/drivers/pinctrl/pinctrl-imx25.c new file mode 100644 index 000000000000..1aae1b61c4dc --- /dev/null +++ b/drivers/pinctrl/pinctrl-imx25.c @@ -0,0 +1,351 @@ +/* + * imx25 pinctrl driver. + * + * Copyright 2013 Eukréa Electromatique + * + * This driver was mostly copied from the imx51 pinctrl driver which has: + * + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * Copyright (C) 2012 Linaro, Inc. + * + * Author: Denis Carikli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pinctrl-imx.h" + +enum imx25_pads { + MX25_PAD_RESERVE0 = 1, + MX25_PAD_RESERVE1 = 2, + MX25_PAD_A10 = 3, + MX25_PAD_A13 = 4, + MX25_PAD_A14 = 5, + MX25_PAD_A15 = 6, + MX25_PAD_A16 = 7, + MX25_PAD_A17 = 8, + MX25_PAD_A18 = 9, + MX25_PAD_A19 = 10, + MX25_PAD_A20 = 11, + MX25_PAD_A21 = 12, + MX25_PAD_A22 = 13, + MX25_PAD_A23 = 14, + MX25_PAD_A24 = 15, + MX25_PAD_A25 = 16, + MX25_PAD_EB0 = 17, + MX25_PAD_EB1 = 18, + MX25_PAD_OE = 19, + MX25_PAD_CS0 = 20, + MX25_PAD_CS1 = 21, + MX25_PAD_CS4 = 22, + MX25_PAD_CS5 = 23, + MX25_PAD_NF_CE0 = 24, + MX25_PAD_ECB = 25, + MX25_PAD_LBA = 26, + MX25_PAD_BCLK = 27, + MX25_PAD_RW = 28, + MX25_PAD_NFWE_B = 29, + MX25_PAD_NFRE_B = 30, + MX25_PAD_NFALE = 31, + MX25_PAD_NFCLE = 32, + MX25_PAD_NFWP_B = 33, + MX25_PAD_NFRB = 34, + MX25_PAD_D15 = 35, + MX25_PAD_D14 = 36, + MX25_PAD_D13 = 37, + MX25_PAD_D12 = 38, + MX25_PAD_D11 = 39, + MX25_PAD_D10 = 40, + MX25_PAD_D9 = 41, + MX25_PAD_D8 = 42, + MX25_PAD_D7 = 43, + MX25_PAD_D6 = 44, + MX25_PAD_D5 = 45, + MX25_PAD_D4 = 46, + MX25_PAD_D3 = 47, + MX25_PAD_D2 = 48, + MX25_PAD_D1 = 49, + MX25_PAD_D0 = 50, + MX25_PAD_LD0 = 51, + MX25_PAD_LD1 = 52, + MX25_PAD_LD2 = 53, + MX25_PAD_LD3 = 54, + MX25_PAD_LD4 = 55, + MX25_PAD_LD5 = 56, + MX25_PAD_LD6 = 57, + MX25_PAD_LD7 = 58, + MX25_PAD_LD8 = 59, + MX25_PAD_LD9 = 60, + MX25_PAD_LD10 = 61, + MX25_PAD_LD11 = 62, + MX25_PAD_LD12 = 63, + MX25_PAD_LD13 = 64, + MX25_PAD_LD14 = 65, + MX25_PAD_LD15 = 66, + MX25_PAD_HSYNC = 67, + MX25_PAD_VSYNC = 68, + MX25_PAD_LSCLK = 69, + MX25_PAD_OE_ACD = 70, + MX25_PAD_CONTRAST = 71, + MX25_PAD_PWM = 72, + MX25_PAD_CSI_D2 = 73, + MX25_PAD_CSI_D3 = 74, + MX25_PAD_CSI_D4 = 75, + MX25_PAD_CSI_D5 = 76, + MX25_PAD_CSI_D6 = 77, + MX25_PAD_CSI_D7 = 78, + MX25_PAD_CSI_D8 = 79, + MX25_PAD_CSI_D9 = 80, + MX25_PAD_CSI_MCLK = 81, + MX25_PAD_CSI_VSYNC = 82, + MX25_PAD_CSI_HSYNC = 83, + MX25_PAD_CSI_PIXCLK = 84, + MX25_PAD_I2C1_CLK = 85, + MX25_PAD_I2C1_DAT = 86, + MX25_PAD_CSPI1_MOSI = 87, + MX25_PAD_CSPI1_MISO = 88, + MX25_PAD_CSPI1_SS0 = 89, + MX25_PAD_CSPI1_SS1 = 90, + MX25_PAD_CSPI1_SCLK = 91, + MX25_PAD_CSPI1_RDY = 92, + MX25_PAD_UART1_RXD = 93, + MX25_PAD_UART1_TXD = 94, + MX25_PAD_UART1_RTS = 95, + MX25_PAD_UART1_CTS = 96, + MX25_PAD_UART2_RXD = 97, + MX25_PAD_UART2_TXD = 98, + MX25_PAD_UART2_RTS = 99, + MX25_PAD_UART2_CTS = 100, + MX25_PAD_SD1_CMD = 101, + MX25_PAD_SD1_CLK = 102, + MX25_PAD_SD1_DATA0 = 103, + MX25_PAD_SD1_DATA1 = 104, + MX25_PAD_SD1_DATA2 = 105, + MX25_PAD_SD1_DATA3 = 106, + MX25_PAD_KPP_ROW0 = 107, + MX25_PAD_KPP_ROW1 = 108, + MX25_PAD_KPP_ROW2 = 109, + MX25_PAD_KPP_ROW3 = 110, + MX25_PAD_KPP_COL0 = 111, + MX25_PAD_KPP_COL1 = 112, + MX25_PAD_KPP_COL2 = 113, + MX25_PAD_KPP_COL3 = 114, + MX25_PAD_FEC_MDC = 115, + MX25_PAD_FEC_MDIO = 116, + MX25_PAD_FEC_TDATA0 = 117, + MX25_PAD_FEC_TDATA1 = 118, + MX25_PAD_FEC_TX_EN = 119, + MX25_PAD_FEC_RDATA0 = 120, + MX25_PAD_FEC_RDATA1 = 121, + MX25_PAD_FEC_RX_DV = 122, + MX25_PAD_FEC_TX_CLK = 123, + MX25_PAD_RTCK = 124, + MX25_PAD_DE_B = 125, + MX25_PAD_GPIO_A = 126, + MX25_PAD_GPIO_B = 127, + MX25_PAD_GPIO_C = 128, + MX25_PAD_GPIO_D = 129, + MX25_PAD_GPIO_E = 130, + MX25_PAD_GPIO_F = 131, + MX25_PAD_EXT_ARMCLK = 132, + MX25_PAD_UPLL_BYPCLK = 133, + MX25_PAD_VSTBY_REQ = 134, + MX25_PAD_VSTBY_ACK = 135, + MX25_PAD_POWER_FAIL = 136, + MX25_PAD_CLKO = 137, + MX25_PAD_BOOT_MODE0 = 138, + MX25_PAD_BOOT_MODE1 = 139, +}; + +/* Pad names for the pinmux subsystem */ +static const struct pinctrl_pin_desc imx25_pinctrl_pads[] = { + IMX_PINCTRL_PIN(MX25_PAD_RESERVE0), + IMX_PINCTRL_PIN(MX25_PAD_RESERVE1), + IMX_PINCTRL_PIN(MX25_PAD_A10), + IMX_PINCTRL_PIN(MX25_PAD_A13), + IMX_PINCTRL_PIN(MX25_PAD_A14), + IMX_PINCTRL_PIN(MX25_PAD_A15), + IMX_PINCTRL_PIN(MX25_PAD_A16), + IMX_PINCTRL_PIN(MX25_PAD_A17), + IMX_PINCTRL_PIN(MX25_PAD_A18), + IMX_PINCTRL_PIN(MX25_PAD_A19), + IMX_PINCTRL_PIN(MX25_PAD_A20), + IMX_PINCTRL_PIN(MX25_PAD_A21), + IMX_PINCTRL_PIN(MX25_PAD_A22), + IMX_PINCTRL_PIN(MX25_PAD_A23), + IMX_PINCTRL_PIN(MX25_PAD_A24), + IMX_PINCTRL_PIN(MX25_PAD_A25), + IMX_PINCTRL_PIN(MX25_PAD_EB0), + IMX_PINCTRL_PIN(MX25_PAD_EB1), + IMX_PINCTRL_PIN(MX25_PAD_OE), + IMX_PINCTRL_PIN(MX25_PAD_CS0), + IMX_PINCTRL_PIN(MX25_PAD_CS1), + IMX_PINCTRL_PIN(MX25_PAD_CS4), + IMX_PINCTRL_PIN(MX25_PAD_CS5), + IMX_PINCTRL_PIN(MX25_PAD_NF_CE0), + IMX_PINCTRL_PIN(MX25_PAD_ECB), + IMX_PINCTRL_PIN(MX25_PAD_LBA), + IMX_PINCTRL_PIN(MX25_PAD_BCLK), + IMX_PINCTRL_PIN(MX25_PAD_RW), + IMX_PINCTRL_PIN(MX25_PAD_NFWE_B), + IMX_PINCTRL_PIN(MX25_PAD_NFRE_B), + IMX_PINCTRL_PIN(MX25_PAD_NFALE), + IMX_PINCTRL_PIN(MX25_PAD_NFCLE), + IMX_PINCTRL_PIN(MX25_PAD_NFWP_B), + IMX_PINCTRL_PIN(MX25_PAD_NFRB), + IMX_PINCTRL_PIN(MX25_PAD_D15), + IMX_PINCTRL_PIN(MX25_PAD_D14), + IMX_PINCTRL_PIN(MX25_PAD_D13), + IMX_PINCTRL_PIN(MX25_PAD_D12), + IMX_PINCTRL_PIN(MX25_PAD_D11), + IMX_PINCTRL_PIN(MX25_PAD_D10), + IMX_PINCTRL_PIN(MX25_PAD_D9), + IMX_PINCTRL_PIN(MX25_PAD_D8), + IMX_PINCTRL_PIN(MX25_PAD_D7), + IMX_PINCTRL_PIN(MX25_PAD_D6), + IMX_PINCTRL_PIN(MX25_PAD_D5), + IMX_PINCTRL_PIN(MX25_PAD_D4), + IMX_PINCTRL_PIN(MX25_PAD_D3), + IMX_PINCTRL_PIN(MX25_PAD_D2), + IMX_PINCTRL_PIN(MX25_PAD_D1), + IMX_PINCTRL_PIN(MX25_PAD_D0), + IMX_PINCTRL_PIN(MX25_PAD_LD0), + IMX_PINCTRL_PIN(MX25_PAD_LD1), + IMX_PINCTRL_PIN(MX25_PAD_LD2), + IMX_PINCTRL_PIN(MX25_PAD_LD3), + IMX_PINCTRL_PIN(MX25_PAD_LD4), + IMX_PINCTRL_PIN(MX25_PAD_LD5), + IMX_PINCTRL_PIN(MX25_PAD_LD6), + IMX_PINCTRL_PIN(MX25_PAD_LD7), + IMX_PINCTRL_PIN(MX25_PAD_LD8), + IMX_PINCTRL_PIN(MX25_PAD_LD9), + IMX_PINCTRL_PIN(MX25_PAD_LD10), + IMX_PINCTRL_PIN(MX25_PAD_LD11), + IMX_PINCTRL_PIN(MX25_PAD_LD12), + IMX_PINCTRL_PIN(MX25_PAD_LD13), + IMX_PINCTRL_PIN(MX25_PAD_LD14), + IMX_PINCTRL_PIN(MX25_PAD_LD15), + IMX_PINCTRL_PIN(MX25_PAD_HSYNC), + IMX_PINCTRL_PIN(MX25_PAD_VSYNC), + IMX_PINCTRL_PIN(MX25_PAD_LSCLK), + IMX_PINCTRL_PIN(MX25_PAD_OE_ACD), + IMX_PINCTRL_PIN(MX25_PAD_CONTRAST), + IMX_PINCTRL_PIN(MX25_PAD_PWM), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D2), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D3), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D4), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D5), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D6), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D7), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D8), + IMX_PINCTRL_PIN(MX25_PAD_CSI_D9), + IMX_PINCTRL_PIN(MX25_PAD_CSI_MCLK), + IMX_PINCTRL_PIN(MX25_PAD_CSI_VSYNC), + IMX_PINCTRL_PIN(MX25_PAD_CSI_HSYNC), + IMX_PINCTRL_PIN(MX25_PAD_CSI_PIXCLK), + IMX_PINCTRL_PIN(MX25_PAD_I2C1_CLK), + IMX_PINCTRL_PIN(MX25_PAD_I2C1_DAT), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_MOSI), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_MISO), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_SS0), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_SS1), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_SCLK), + IMX_PINCTRL_PIN(MX25_PAD_CSPI1_RDY), + IMX_PINCTRL_PIN(MX25_PAD_UART1_RXD), + IMX_PINCTRL_PIN(MX25_PAD_UART1_TXD), + IMX_PINCTRL_PIN(MX25_PAD_UART1_RTS), + IMX_PINCTRL_PIN(MX25_PAD_UART1_CTS), + IMX_PINCTRL_PIN(MX25_PAD_UART2_RXD), + IMX_PINCTRL_PIN(MX25_PAD_UART2_TXD), + IMX_PINCTRL_PIN(MX25_PAD_UART2_RTS), + IMX_PINCTRL_PIN(MX25_PAD_UART2_CTS), + IMX_PINCTRL_PIN(MX25_PAD_SD1_CMD), + IMX_PINCTRL_PIN(MX25_PAD_SD1_CLK), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA0), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA1), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA2), + IMX_PINCTRL_PIN(MX25_PAD_SD1_DATA3), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW0), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW1), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW2), + IMX_PINCTRL_PIN(MX25_PAD_KPP_ROW3), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL0), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL1), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL2), + IMX_PINCTRL_PIN(MX25_PAD_KPP_COL3), + IMX_PINCTRL_PIN(MX25_PAD_FEC_MDC), + IMX_PINCTRL_PIN(MX25_PAD_FEC_MDIO), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TDATA0), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TDATA1), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TX_EN), + IMX_PINCTRL_PIN(MX25_PAD_FEC_RDATA0), + IMX_PINCTRL_PIN(MX25_PAD_FEC_RDATA1), + IMX_PINCTRL_PIN(MX25_PAD_FEC_RX_DV), + IMX_PINCTRL_PIN(MX25_PAD_FEC_TX_CLK), + IMX_PINCTRL_PIN(MX25_PAD_RTCK), + IMX_PINCTRL_PIN(MX25_PAD_DE_B), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_A), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_B), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_C), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_D), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_E), + IMX_PINCTRL_PIN(MX25_PAD_GPIO_F), + IMX_PINCTRL_PIN(MX25_PAD_EXT_ARMCLK), + IMX_PINCTRL_PIN(MX25_PAD_UPLL_BYPCLK), + IMX_PINCTRL_PIN(MX25_PAD_VSTBY_REQ), + IMX_PINCTRL_PIN(MX25_PAD_VSTBY_ACK), + IMX_PINCTRL_PIN(MX25_PAD_POWER_FAIL), + IMX_PINCTRL_PIN(MX25_PAD_CLKO), + IMX_PINCTRL_PIN(MX25_PAD_BOOT_MODE0), + IMX_PINCTRL_PIN(MX25_PAD_BOOT_MODE1), +}; + +static struct imx_pinctrl_soc_info imx25_pinctrl_info = { + .pins = imx25_pinctrl_pads, + .npins = ARRAY_SIZE(imx25_pinctrl_pads), +}; + +static struct of_device_id imx25_pinctrl_of_match[] = { + { .compatible = "fsl,imx25-iomuxc", }, + { /* sentinel */ } +}; + +static int imx25_pinctrl_probe(struct platform_device *pdev) +{ + return imx_pinctrl_probe(pdev, &imx25_pinctrl_info); +} + +static struct platform_driver imx25_pinctrl_driver = { + .driver = { + .name = "imx25-pinctrl", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(imx25_pinctrl_of_match), + }, + .probe = imx25_pinctrl_probe, + .remove = imx_pinctrl_remove, +}; + +static int __init imx25_pinctrl_init(void) +{ + return platform_driver_register(&imx25_pinctrl_driver); +} +arch_initcall(imx25_pinctrl_init); + +static void __exit imx25_pinctrl_exit(void) +{ + platform_driver_unregister(&imx25_pinctrl_driver); +} +module_exit(imx25_pinctrl_exit); +MODULE_AUTHOR("Denis Carikli "); +MODULE_DESCRIPTION("Freescale IMX25 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-msm.c b/drivers/pinctrl/pinctrl-msm.c new file mode 100644 index 000000000000..28b90aba708d --- /dev/null +++ b/drivers/pinctrl/pinctrl-msm.c @@ -0,0 +1,1028 @@ +/* + * Copyright (c) 2013, Sony Mobile Communications AB. + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-msm.h" +#include "pinctrl-utils.h" + +/** + * struct msm_pinctrl - state for a pinctrl-msm device + * @dev: device handle. + * @pctrl: pinctrl handle. + * @domain: irqdomain handle. + * @chip: gpiochip handle. + * @irq: parent irq for the TLMM irq_chip. + * @lock: Spinlock to protect register resources as well + * as msm_pinctrl data structures. + * @enabled_irqs: Bitmap of currently enabled irqs. + * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge + * detection. + * @wake_irqs: Bitmap of irqs with requested as wakeup source. + * @soc; Reference to soc_data of platform specific data. + * @regs: Base address for the TLMM register map. + */ +struct msm_pinctrl { + struct device *dev; + struct pinctrl_dev *pctrl; + struct irq_domain *domain; + struct gpio_chip chip; + unsigned irq; + + spinlock_t lock; + + unsigned long *enabled_irqs; + unsigned long *dual_edge_irqs; + unsigned long *wake_irqs; + + const struct msm_pinctrl_soc_data *soc; + void __iomem *regs; +}; + +static int msm_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->ngroups; +} + +static const char *msm_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->groups[group].name; +} + +static int msm_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + *pins = pctrl->soc->groups[group].pins; + *num_pins = pctrl->soc->groups[group].npins; + return 0; +} + +static struct pinctrl_ops msm_pinctrl_ops = { + .get_groups_count = msm_get_groups_count, + .get_group_name = msm_get_group_name, + .get_group_pins = msm_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_group, + .dt_free_map = pinctrl_utils_dt_free_map, +}; + +static int msm_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->nfunctions; +} + +static const char *msm_get_function_name(struct pinctrl_dev *pctldev, + unsigned function) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->soc->functions[function].name; +} + +static int msm_get_function_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pctrl->soc->functions[function].groups; + *num_groups = pctrl->soc->functions[function].ngroups; + return 0; +} + +static int msm_pinmux_enable(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct msm_pingroup *g; + unsigned long flags; + u32 val; + int i; + + g = &pctrl->soc->groups[group]; + + if (WARN_ON(g->mux_bit < 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { + if (g->funcs[i] == function) + break; + } + + if (WARN_ON(i == ARRAY_SIZE(g->funcs))) + return -EINVAL; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->ctl_reg); + val &= ~(0x7 << g->mux_bit); + val |= i << g->mux_bit; + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static void msm_pinmux_disable(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct msm_pingroup *g; + unsigned long flags; + u32 val; + + g = &pctrl->soc->groups[group]; + + if (WARN_ON(g->mux_bit < 0)) + return; + + spin_lock_irqsave(&pctrl->lock, flags); + + /* Clear the mux bits to select gpio mode */ + val = readl(pctrl->regs + g->ctl_reg); + val &= ~(0x7 << g->mux_bit); + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static struct pinmux_ops msm_pinmux_ops = { + .get_functions_count = msm_get_functions_count, + .get_function_name = msm_get_function_name, + .get_function_groups = msm_get_function_groups, + .enable = msm_pinmux_enable, + .disable = msm_pinmux_disable, +}; + +static int msm_config_reg(struct msm_pinctrl *pctrl, + const struct msm_pingroup *g, + unsigned param, + unsigned *reg, + unsigned *mask, + unsigned *bit) +{ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + *reg = g->ctl_reg; + *bit = g->pull_bit; + *mask = 3; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + *reg = g->ctl_reg; + *bit = g->pull_bit; + *mask = 3; + break; + case PIN_CONFIG_BIAS_PULL_UP: + *reg = g->ctl_reg; + *bit = g->pull_bit; + *mask = 3; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + *reg = g->ctl_reg; + *bit = g->drv_bit; + *mask = 7; + break; + default: + dev_err(pctrl->dev, "Invalid config param %04x\n", param); + return -ENOTSUPP; + } + + if (*reg < 0) { + dev_err(pctrl->dev, "Config param %04x not supported on group %s\n", + param, g->name); + return -ENOTSUPP; + } + + return 0; +} + +static int msm_config_get(struct pinctrl_dev *pctldev, + unsigned int pin, + unsigned long *config) +{ + dev_err(pctldev->dev, "pin_config_set op not supported\n"); + return -ENOTSUPP; +} + +static int msm_config_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned num_configs) +{ + dev_err(pctldev->dev, "pin_config_set op not supported\n"); + return -ENOTSUPP; +} + +#define MSM_NO_PULL 0 +#define MSM_PULL_DOWN 1 +#define MSM_PULL_UP 3 + +static const unsigned msm_regval_to_drive[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; +static const unsigned msm_drive_to_regval[] = { -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, 6, -1, 7 }; + +static int msm_config_group_get(struct pinctrl_dev *pctldev, + unsigned int group, + unsigned long *config) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + unsigned param = pinconf_to_config_param(*config); + unsigned mask; + unsigned arg; + unsigned bit; + unsigned reg; + int ret; + u32 val; + + g = &pctrl->soc->groups[group]; + + ret = msm_config_reg(pctrl, g, param, ®, &mask, &bit); + if (ret < 0) + return ret; + + val = readl(pctrl->regs + reg); + arg = (val >> bit) & mask; + + /* Convert register value to pinconf value */ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + arg = arg == MSM_NO_PULL; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + arg = arg == MSM_PULL_DOWN; + break; + case PIN_CONFIG_BIAS_PULL_UP: + arg = arg == MSM_PULL_UP; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = msm_regval_to_drive[arg]; + break; + default: + dev_err(pctrl->dev, "Unsupported config parameter: %x\n", + param); + return -EINVAL; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int msm_config_group_set(struct pinctrl_dev *pctldev, + unsigned group, + unsigned long *configs, + unsigned num_configs) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + unsigned long flags; + unsigned param; + unsigned mask; + unsigned arg; + unsigned bit; + unsigned reg; + int ret; + u32 val; + int i; + + g = &pctrl->soc->groups[group]; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + ret = msm_config_reg(pctrl, g, param, ®, &mask, &bit); + if (ret < 0) + return ret; + + /* Convert pinconf values to register values */ + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + arg = MSM_NO_PULL; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + arg = MSM_PULL_DOWN; + break; + case PIN_CONFIG_BIAS_PULL_UP: + arg = MSM_PULL_UP; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + /* Check for invalid values */ + if (arg > ARRAY_SIZE(msm_drive_to_regval)) + arg = -1; + else + arg = msm_drive_to_regval[arg]; + break; + default: + dev_err(pctrl->dev, "Unsupported config parameter: %x\n", + param); + return -EINVAL; + } + + /* Range-check user-supplied value */ + if (arg & ~mask) { + dev_err(pctrl->dev, "config %x: %x is invalid\n", param, arg); + return -EINVAL; + } + + spin_lock_irqsave(&pctrl->lock, flags); + val = readl(pctrl->regs + reg); + val &= ~(mask << bit); + val |= arg << bit; + writel(val, pctrl->regs + reg); + spin_unlock_irqrestore(&pctrl->lock, flags); + } + + return 0; +} + +static struct pinconf_ops msm_pinconf_ops = { + .pin_config_get = msm_config_get, + .pin_config_set = msm_config_set, + .pin_config_group_get = msm_config_group_get, + .pin_config_group_set = msm_config_group_set, +}; + +static struct pinctrl_desc msm_pinctrl_desc = { + .pctlops = &msm_pinctrl_ops, + .pmxops = &msm_pinmux_ops, + .confops = &msm_pinconf_ops, + .owner = THIS_MODULE, +}; + +static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned long flags; + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[offset]; + + if (WARN_ON(g->oe_bit < 0)) + return -EINVAL; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->ctl_reg); + val &= ~BIT(g->oe_bit); + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned long flags; + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[offset]; + + if (WARN_ON(g->oe_bit < 0)) + return -EINVAL; + + spin_lock_irqsave(&pctrl->lock, flags); + + writel(value ? BIT(g->out_bit) : 0, pctrl->regs + g->io_reg); + + val = readl(pctrl->regs + g->ctl_reg); + val |= BIT(g->oe_bit); + writel(val, pctrl->regs + g->ctl_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[offset]; + + val = readl(pctrl->regs + g->io_reg); + return !!(val & BIT(g->in_bit)); +} + +static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned long flags; + u32 val; + + if (WARN_ON(offset >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[offset]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->io_reg); + val |= BIT(g->out_bit); + writel(val, pctrl->regs + g->io_reg); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + + return irq_find_mapping(pctrl->domain, offset); +} + +static int msm_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + return pinctrl_request_gpio(gpio); +} + +static void msm_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + return pinctrl_free_gpio(gpio); +} + +#ifdef CONFIG_DEBUG_FS +#include + +static void msm_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, + struct gpio_chip *chip, + unsigned offset, + unsigned gpio) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = container_of(chip, struct msm_pinctrl, chip); + unsigned func; + int is_out; + int drive; + int pull; + u32 ctl_reg; + + const char *pulls[] = { + "no pull", + "pull down", + "keeper", + "pull up" + }; + + g = &pctrl->soc->groups[offset]; + ctl_reg = readl(pctrl->regs + g->ctl_reg); + + is_out = !!(ctl_reg & BIT(g->oe_bit)); + func = (ctl_reg >> g->mux_bit) & 7; + drive = (ctl_reg >> g->drv_bit) & 7; + pull = (ctl_reg >> g->pull_bit) & 3; + + seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func); + seq_printf(s, " %dmA", msm_regval_to_drive[drive]); + seq_printf(s, " %s", pulls[pull]); +} + +static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + unsigned gpio = chip->base; + unsigned i; + + for (i = 0; i < chip->ngpio; i++, gpio++) { + msm_gpio_dbg_show_one(s, NULL, chip, i, gpio); + seq_printf(s, "\n"); + } +} + +#else +#define msm_gpio_dbg_show NULL +#endif + +static struct gpio_chip msm_gpio_template = { + .direction_input = msm_gpio_direction_input, + .direction_output = msm_gpio_direction_output, + .get = msm_gpio_get, + .set = msm_gpio_set, + .to_irq = msm_gpio_to_irq, + .request = msm_gpio_request, + .free = msm_gpio_free, + .dbg_show = msm_gpio_dbg_show, +}; + +/* For dual-edge interrupts in software, since some hardware has no + * such support: + * + * At appropriate moments, this function may be called to flip the polarity + * settings of both-edge irq lines to try and catch the next edge. + * + * The attempt is considered successful if: + * - the status bit goes high, indicating that an edge was caught, or + * - the input value of the gpio doesn't change during the attempt. + * If the value changes twice during the process, that would cause the first + * test to fail but would force the second, as two opposite + * transitions would cause a detection no matter the polarity setting. + * + * The do-loop tries to sledge-hammer closed the timing hole between + * the initial value-read and the polarity-write - if the line value changes + * during that window, an interrupt is lost, the new polarity setting is + * incorrect, and the first success test will fail, causing a retry. + * + * Algorithm comes from Google's msmgpio driver. + */ +static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl, + const struct msm_pingroup *g, + struct irq_data *d) +{ + int loop_limit = 100; + unsigned val, val2, intstat; + unsigned pol; + + do { + val = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit); + + pol = readl(pctrl->regs + g->intr_cfg_reg); + pol ^= BIT(g->intr_polarity_bit); + writel(pol, pctrl->regs + g->intr_cfg_reg); + + val2 = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit); + intstat = readl(pctrl->regs + g->intr_status_reg); + if (intstat || (val == val2)) + return; + } while (loop_limit-- > 0); + dev_err(pctrl->dev, "dual-edge irq failed to stabilize, %#08x != %#08x\n", + val, val2); +} + +static void msm_gpio_irq_mask(struct irq_data *d) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->intr_cfg_reg); + val &= ~BIT(g->intr_enable_bit); + writel(val, pctrl->regs + g->intr_cfg_reg); + + clear_bit(d->hwirq, pctrl->enabled_irqs); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static void msm_gpio_irq_unmask(struct irq_data *d) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->intr_status_reg); + val &= ~BIT(g->intr_status_bit); + writel(val, pctrl->regs + g->intr_status_reg); + + val = readl(pctrl->regs + g->intr_cfg_reg); + val |= BIT(g->intr_enable_bit); + writel(val, pctrl->regs + g->intr_cfg_reg); + + set_bit(d->hwirq, pctrl->enabled_irqs); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +static void msm_gpio_irq_ack(struct irq_data *d) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + val = readl(pctrl->regs + g->intr_status_reg); + val &= ~BIT(g->intr_status_bit); + writel(val, pctrl->regs + g->intr_status_reg); + + if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) + msm_gpio_update_dual_edge_pos(pctrl, g, d); + + spin_unlock_irqrestore(&pctrl->lock, flags); +} + +#define INTR_TARGET_PROC_APPS 4 + +static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl; + unsigned long flags; + u32 val; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return -EINVAL; + + if (WARN_ON(d->hwirq >= pctrl->soc->ngroups)) + return -EINVAL; + + g = &pctrl->soc->groups[d->hwirq]; + + spin_lock_irqsave(&pctrl->lock, flags); + + /* + * For hw without possibility of detecting both edges + */ + if (g->intr_detection_width == 1 && type == IRQ_TYPE_EDGE_BOTH) + set_bit(d->hwirq, pctrl->dual_edge_irqs); + else + clear_bit(d->hwirq, pctrl->dual_edge_irqs); + + /* Route interrupts to application cpu */ + val = readl(pctrl->regs + g->intr_target_reg); + val &= ~(7 << g->intr_target_bit); + val |= INTR_TARGET_PROC_APPS << g->intr_target_bit; + writel(val, pctrl->regs + g->intr_target_reg); + + /* Update configuration for gpio. + * RAW_STATUS_EN is left on for all gpio irqs. Due to the + * internal circuitry of TLMM, toggling the RAW_STATUS + * could cause the INTR_STATUS to be set for EDGE interrupts. + */ + val = readl(pctrl->regs + g->intr_cfg_reg); + val |= BIT(g->intr_raw_status_bit); + if (g->intr_detection_width == 2) { + val &= ~(3 << g->intr_detection_bit); + val &= ~(1 << g->intr_polarity_bit); + switch (type) { + case IRQ_TYPE_EDGE_RISING: + val |= 1 << g->intr_detection_bit; + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_EDGE_FALLING: + val |= 2 << g->intr_detection_bit; + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_EDGE_BOTH: + val |= 3 << g->intr_detection_bit; + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_LEVEL_LOW: + break; + case IRQ_TYPE_LEVEL_HIGH: + val |= BIT(g->intr_polarity_bit); + break; + } + } else if (g->intr_detection_width == 1) { + val &= ~(1 << g->intr_detection_bit); + val &= ~(1 << g->intr_polarity_bit); + switch (type) { + case IRQ_TYPE_EDGE_RISING: + val |= BIT(g->intr_detection_bit); + val |= BIT(g->intr_polarity_bit); + break; + case IRQ_TYPE_EDGE_FALLING: + val |= BIT(g->intr_detection_bit); + break; + case IRQ_TYPE_EDGE_BOTH: + val |= BIT(g->intr_detection_bit); + break; + case IRQ_TYPE_LEVEL_LOW: + break; + case IRQ_TYPE_LEVEL_HIGH: + val |= BIT(g->intr_polarity_bit); + break; + } + } else { + BUG(); + } + writel(val, pctrl->regs + g->intr_cfg_reg); + + if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) + msm_gpio_update_dual_edge_pos(pctrl, g, d); + + spin_unlock_irqrestore(&pctrl->lock, flags); + + if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + __irq_set_handler_locked(d->irq, handle_level_irq); + else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + __irq_set_handler_locked(d->irq, handle_edge_irq); + + return 0; +} + +static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) +{ + struct msm_pinctrl *pctrl; + unsigned long flags; + unsigned ngpio; + + pctrl = irq_data_get_irq_chip_data(d); + if (!pctrl) + return -EINVAL; + + ngpio = pctrl->chip.ngpio; + + spin_lock_irqsave(&pctrl->lock, flags); + + if (on) { + if (bitmap_empty(pctrl->wake_irqs, ngpio)) + enable_irq_wake(pctrl->irq); + set_bit(d->hwirq, pctrl->wake_irqs); + } else { + clear_bit(d->hwirq, pctrl->wake_irqs); + if (bitmap_empty(pctrl->wake_irqs, ngpio)) + disable_irq_wake(pctrl->irq); + } + + spin_unlock_irqrestore(&pctrl->lock, flags); + + return 0; +} + +static unsigned int msm_gpio_irq_startup(struct irq_data *d) +{ + struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); + + if (gpio_lock_as_irq(&pctrl->chip, d->hwirq)) { + dev_err(pctrl->dev, "unable to lock HW IRQ %lu for IRQ\n", + d->hwirq); + } + msm_gpio_irq_unmask(d); + return 0; +} + +static void msm_gpio_irq_shutdown(struct irq_data *d) +{ + struct msm_pinctrl *pctrl = irq_data_get_irq_chip_data(d); + + msm_gpio_irq_mask(d); + gpio_unlock_as_irq(&pctrl->chip, d->hwirq); +} + +static struct irq_chip msm_gpio_irq_chip = { + .name = "msmgpio", + .irq_mask = msm_gpio_irq_mask, + .irq_unmask = msm_gpio_irq_unmask, + .irq_ack = msm_gpio_irq_ack, + .irq_set_type = msm_gpio_irq_set_type, + .irq_set_wake = msm_gpio_irq_set_wake, + .irq_startup = msm_gpio_irq_startup, + .irq_shutdown = msm_gpio_irq_shutdown, +}; + +static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + const struct msm_pingroup *g; + struct msm_pinctrl *pctrl = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_get_chip(irq); + int irq_pin; + int handled = 0; + u32 val; + int i; + + chained_irq_enter(chip, desc); + + /* + * Each pin have it's own IRQ status register, so use + * enabled_irq bitmap to limit the number of reads. + */ + for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) { + g = &pctrl->soc->groups[i]; + val = readl(pctrl->regs + g->intr_status_reg); + if (val & BIT(g->intr_status_bit)) { + irq_pin = irq_find_mapping(pctrl->domain, i); + generic_handle_irq(irq_pin); + handled++; + } + } + + /* No interrutps where flagged */ + if (handled == 0) + handle_bad_irq(irq, desc); + + chained_irq_exit(chip, desc); +} + +static int msm_gpio_init(struct msm_pinctrl *pctrl) +{ + struct gpio_chip *chip; + int irq; + int ret; + int i; + int r; + + chip = &pctrl->chip; + chip->base = 0; + chip->ngpio = pctrl->soc->ngpios; + chip->label = dev_name(pctrl->dev); + chip->dev = pctrl->dev; + chip->owner = THIS_MODULE; + chip->of_node = pctrl->dev->of_node; + + pctrl->enabled_irqs = devm_kzalloc(pctrl->dev, + sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), + GFP_KERNEL); + if (!pctrl->enabled_irqs) { + dev_err(pctrl->dev, "Failed to allocate enabled_irqs bitmap\n"); + return -ENOMEM; + } + + pctrl->dual_edge_irqs = devm_kzalloc(pctrl->dev, + sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), + GFP_KERNEL); + if (!pctrl->dual_edge_irqs) { + dev_err(pctrl->dev, "Failed to allocate dual_edge_irqs bitmap\n"); + return -ENOMEM; + } + + pctrl->wake_irqs = devm_kzalloc(pctrl->dev, + sizeof(unsigned long) * BITS_TO_LONGS(chip->ngpio), + GFP_KERNEL); + if (!pctrl->wake_irqs) { + dev_err(pctrl->dev, "Failed to allocate wake_irqs bitmap\n"); + return -ENOMEM; + } + + ret = gpiochip_add(&pctrl->chip); + if (ret) { + dev_err(pctrl->dev, "Failed register gpiochip\n"); + return ret; + } + + ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio); + if (ret) { + dev_err(pctrl->dev, "Failed to add pin range\n"); + return ret; + } + + pctrl->domain = irq_domain_add_linear(pctrl->dev->of_node, chip->ngpio, + &irq_domain_simple_ops, NULL); + if (!pctrl->domain) { + dev_err(pctrl->dev, "Failed to register irq domain\n"); + r = gpiochip_remove(&pctrl->chip); + return -ENOSYS; + } + + for (i = 0; i < chip->ngpio; i++) { + irq = irq_create_mapping(pctrl->domain, i); + irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, handle_edge_irq); + irq_set_chip_data(irq, pctrl); + } + + irq_set_handler_data(pctrl->irq, pctrl); + irq_set_chained_handler(pctrl->irq, msm_gpio_irq_handler); + + return 0; +} + +int msm_pinctrl_probe(struct platform_device *pdev, + const struct msm_pinctrl_soc_data *soc_data) +{ + struct msm_pinctrl *pctrl; + struct resource *res; + int ret; + + pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) { + dev_err(&pdev->dev, "Can't allocate msm_pinctrl\n"); + return -ENOMEM; + } + pctrl->dev = &pdev->dev; + pctrl->soc = soc_data; + pctrl->chip = msm_gpio_template; + + spin_lock_init(&pctrl->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pctrl->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pctrl->regs)) + return PTR_ERR(pctrl->regs); + + pctrl->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (pctrl->irq < 0) { + dev_err(&pdev->dev, "No interrupt defined for msmgpio\n"); + return pctrl->irq; + } + + msm_pinctrl_desc.name = dev_name(&pdev->dev); + msm_pinctrl_desc.pins = pctrl->soc->pins; + msm_pinctrl_desc.npins = pctrl->soc->npins; + pctrl->pctrl = pinctrl_register(&msm_pinctrl_desc, &pdev->dev, pctrl); + if (!pctrl->pctrl) { + dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); + return -ENODEV; + } + + ret = msm_gpio_init(pctrl); + if (ret) { + pinctrl_unregister(pctrl->pctrl); + return ret; + } + + platform_set_drvdata(pdev, pctrl); + + dev_dbg(&pdev->dev, "Probed Qualcomm pinctrl driver\n"); + + return 0; +} +EXPORT_SYMBOL(msm_pinctrl_probe); + +int msm_pinctrl_remove(struct platform_device *pdev) +{ + struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); + int ret; + + irq_set_chained_handler(pctrl->irq, NULL); + irq_domain_remove(pctrl->domain); + ret = gpiochip_remove(&pctrl->chip); + pinctrl_unregister(pctrl->pctrl); + + return 0; +} +EXPORT_SYMBOL(msm_pinctrl_remove); + diff --git a/drivers/pinctrl/pinctrl-msm.h b/drivers/pinctrl/pinctrl-msm.h new file mode 100644 index 000000000000..206e782e2daa --- /dev/null +++ b/drivers/pinctrl/pinctrl-msm.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2013, Sony Mobile Communications AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only 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 __PINCTRL_MSM_H__ +#define __PINCTRL_MSM_H__ + +#include +#include +#include +#include + +/** + * struct msm_function - a pinmux function + * @name: Name of the pinmux function. + * @groups: List of pingroups for this function. + * @ngroups: Number of entries in @groups. + */ +struct msm_function { + const char *name; + const char * const *groups; + unsigned ngroups; +}; + +/** + * struct msm_pingroup - Qualcomm pingroup definition + * @name: Name of the pingroup. + * @pins: A list of pins assigned to this pingroup. + * @npins: Number of entries in @pins. + * @funcs: A list of pinmux functions that can be selected for + * this group. The index of the selected function is used + * for programming the function selector. + * Entries should be indices into the groups list of the + * struct msm_pinctrl_soc_data. + * @ctl_reg: Offset of the register holding control bits for this group. + * @io_reg: Offset of the register holding input/output bits for this group. + * @intr_cfg_reg: Offset of the register holding interrupt configuration bits. + * @intr_status_reg: Offset of the register holding the status bits for this group. + * @intr_target_reg: Offset of the register specifying routing of the interrupts + * from this group. + * @mux_bit: Offset in @ctl_reg for the pinmux function selection. + * @pull_bit: Offset in @ctl_reg for the bias configuration. + * @drv_bit: Offset in @ctl_reg for the drive strength configuration. + * @oe_bit: Offset in @ctl_reg for controlling output enable. + * @in_bit: Offset in @io_reg for the input bit value. + * @out_bit: Offset in @io_reg for the output bit value. + * @intr_enable_bit: Offset in @intr_cfg_reg for enabling the interrupt for this group. + * @intr_status_bit: Offset in @intr_status_reg for reading and acking the interrupt + * status. + * @intr_target_bit: Offset in @intr_target_reg for configuring the interrupt routing. + * @intr_raw_status_bit: Offset in @intr_cfg_reg for the raw status bit. + * @intr_polarity_bit: Offset in @intr_cfg_reg for specifying polarity of the interrupt. + * @intr_detection_bit: Offset in @intr_cfg_reg for specifying interrupt type. + * @intr_detection_width: Number of bits used for specifying interrupt type, + * Should be 2 for SoCs that can detect both edges in hardware, + * otherwise 1. + */ +struct msm_pingroup { + const char *name; + const unsigned *pins; + unsigned npins; + + unsigned funcs[8]; + + s16 ctl_reg; + s16 io_reg; + s16 intr_cfg_reg; + s16 intr_status_reg; + s16 intr_target_reg; + + unsigned mux_bit:5; + + unsigned pull_bit:5; + unsigned drv_bit:5; + + unsigned oe_bit:5; + unsigned in_bit:5; + unsigned out_bit:5; + + unsigned intr_enable_bit:5; + unsigned intr_status_bit:5; + + unsigned intr_target_bit:5; + unsigned intr_raw_status_bit:5; + unsigned intr_polarity_bit:5; + unsigned intr_detection_bit:5; + unsigned intr_detection_width:5; +}; + +/** + * struct msm_pinctrl_soc_data - Qualcomm pin controller driver configuration + * @pins: An array describing all pins the pin controller affects. + * @npins: The number of entries in @pins. + * @functions: An array describing all mux functions the SoC supports. + * @nfunctions: The number of entries in @functions. + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The numbmer of entries in @groups. + * @ngpio: The number of pingroups the driver should expose as GPIOs. + */ +struct msm_pinctrl_soc_data { + const struct pinctrl_pin_desc *pins; + unsigned npins; + const struct msm_function *functions; + unsigned nfunctions; + const struct msm_pingroup *groups; + unsigned ngroups; + unsigned ngpios; +}; + +int msm_pinctrl_probe(struct platform_device *pdev, + const struct msm_pinctrl_soc_data *soc_data); +int msm_pinctrl_remove(struct platform_device *pdev); + +#endif diff --git a/drivers/pinctrl/pinctrl-msm8x74.c b/drivers/pinctrl/pinctrl-msm8x74.c new file mode 100644 index 000000000000..762552bc53b9 --- /dev/null +++ b/drivers/pinctrl/pinctrl-msm8x74.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2013, Sony Mobile Communications AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only 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. + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-msm.h" + +static const struct pinctrl_pin_desc msm8x74_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + + PINCTRL_PIN(146, "SDC1_CLK"), + PINCTRL_PIN(147, "SDC1_CMD"), + PINCTRL_PIN(148, "SDC1_DATA"), + PINCTRL_PIN(149, "SDC2_CLK"), + PINCTRL_PIN(150, "SDC2_CMD"), + PINCTRL_PIN(151, "SDC2_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); +DECLARE_MSM_GPIO_PINS(133); +DECLARE_MSM_GPIO_PINS(134); +DECLARE_MSM_GPIO_PINS(135); +DECLARE_MSM_GPIO_PINS(136); +DECLARE_MSM_GPIO_PINS(137); +DECLARE_MSM_GPIO_PINS(138); +DECLARE_MSM_GPIO_PINS(139); +DECLARE_MSM_GPIO_PINS(140); +DECLARE_MSM_GPIO_PINS(141); +DECLARE_MSM_GPIO_PINS(142); +DECLARE_MSM_GPIO_PINS(143); +DECLARE_MSM_GPIO_PINS(144); +DECLARE_MSM_GPIO_PINS(145); + +static const unsigned int sdc1_clk_pins[] = { 146 }; +static const unsigned int sdc1_cmd_pins[] = { 147 }; +static const unsigned int sdc1_data_pins[] = { 148 }; +static const unsigned int sdc2_clk_pins[] = { 149 }; +static const unsigned int sdc2_cmd_pins[] = { 150 }; +static const unsigned int sdc2_data_pins[] = { 151 }; + +#define FUNCTION(fname) \ + [MSM_MUX_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = ARRAY_SIZE(gpio##id##_pins), \ + .funcs = { \ + MSM_MUX_NA, /* gpio mode */ \ + MSM_MUX_##f1, \ + MSM_MUX_##f2, \ + MSM_MUX_##f3, \ + MSM_MUX_##f4, \ + MSM_MUX_##f5, \ + MSM_MUX_##f6, \ + MSM_MUX_##f7 \ + }, \ + .ctl_reg = 0x1000 + 0x10 * id , \ + .io_reg = 0x1004 + 0x10 * id, \ + .intr_cfg_reg = 0x1008 + 0x10 * id, \ + .intr_status_reg = 0x100c + 0x10 * id, \ + .intr_target_reg = 0x1008 + 0x10 * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } + +/* + * TODO: Add the rest of the possible functions and fill out + * the pingroup table below. + */ +enum msm8x74_functions { + MSM_MUX_blsp_i2c2, + MSM_MUX_blsp_i2c6, + MSM_MUX_blsp_i2c11, + MSM_MUX_blsp_spi1, + MSM_MUX_blsp_uart2, + MSM_MUX_blsp_uart8, + MSM_MUX_slimbus, + MSM_MUX_NA, +}; + +static const char * const blsp_i2c2_groups[] = { "gpio6", "gpio7" }; +static const char * const blsp_i2c6_groups[] = { "gpio29", "gpio30" }; +static const char * const blsp_i2c11_groups[] = { "gpio83", "gpio84" }; +static const char * const blsp_spi1_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3" }; +static const char * const blsp_uart2_groups[] = { "gpio4", "gpio5" }; +static const char * const blsp_uart8_groups[] = { "gpio45", "gpio46" }; +static const char * const slimbus_groups[] = { "gpio70", "gpio71" }; + +static const struct msm_function msm8x74_functions[] = { + FUNCTION(blsp_i2c2), + FUNCTION(blsp_i2c6), + FUNCTION(blsp_i2c11), + FUNCTION(blsp_spi1), + FUNCTION(blsp_uart2), + FUNCTION(blsp_uart8), + FUNCTION(slimbus), +}; + +static const struct msm_pingroup msm8x74_groups[] = { + PINGROUP(0, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(1, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(2, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(3, blsp_spi1, NA, NA, NA, NA, NA, NA), + PINGROUP(4, NA, blsp_uart2, NA, NA, NA, NA, NA), + PINGROUP(5, NA, blsp_uart2, NA, NA, NA, NA, NA), + PINGROUP(6, NA, NA, blsp_i2c2, NA, NA, NA, NA), + PINGROUP(7, NA, NA, blsp_i2c2, NA, NA, NA, NA), + PINGROUP(8, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(9, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(10, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(11, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(12, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(13, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(14, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(15, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(16, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(17, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(18, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(19, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(20, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(21, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(22, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(23, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(24, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(25, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(26, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(27, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(28, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(29, NA, NA, blsp_i2c6, NA, NA, NA, NA), + PINGROUP(30, NA, NA, blsp_i2c6, NA, NA, NA, NA), + PINGROUP(31, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(32, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(33, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(34, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(35, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(36, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(37, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(38, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(39, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(40, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(41, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(42, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(43, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(44, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(45, NA, blsp_uart8, NA, NA, NA, NA, NA), + PINGROUP(46, NA, blsp_uart8, NA, NA, NA, NA, NA), + PINGROUP(47, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(48, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(49, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(50, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(51, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(52, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(53, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(54, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(55, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(56, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(57, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(58, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(59, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(60, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(61, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(62, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(63, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(64, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(65, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(66, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(67, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(68, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(69, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(70, slimbus, NA, NA, NA, NA, NA, NA), + PINGROUP(71, slimbus, NA, NA, NA, NA, NA, NA), + PINGROUP(72, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(73, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(74, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(75, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(76, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(77, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(78, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(79, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(80, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(81, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(82, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(83, NA, NA, blsp_i2c11, NA, NA, NA, NA), + PINGROUP(84, NA, NA, blsp_i2c11, NA, NA, NA, NA), + PINGROUP(85, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(86, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(87, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(88, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(89, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(90, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(91, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(92, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(93, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(94, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(95, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(96, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(97, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(98, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(99, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(100, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(101, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(102, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(103, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(104, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(105, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(106, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(107, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(108, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(109, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(110, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(111, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(112, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(113, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(114, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(115, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(116, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(117, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(118, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(119, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(120, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(121, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(122, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(123, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(124, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(125, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(126, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(127, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(128, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(129, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(130, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(131, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(132, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(133, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(134, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(135, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(136, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(137, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(138, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(139, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(140, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(141, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(143, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(143, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(144, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(145, NA, NA, NA, NA, NA, NA, NA), + SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6), + SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3), + SDC_PINGROUP(sdc1_data, 0x2044, 9, 0), + SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6), + SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3), + SDC_PINGROUP(sdc2_data, 0x2048, 9, 0), +}; + +#define NUM_GPIO_PINGROUPS 146 + +static const struct msm_pinctrl_soc_data msm8x74_pinctrl = { + .pins = msm8x74_pins, + .npins = ARRAY_SIZE(msm8x74_pins), + .functions = msm8x74_functions, + .nfunctions = ARRAY_SIZE(msm8x74_functions), + .groups = msm8x74_groups, + .ngroups = ARRAY_SIZE(msm8x74_groups), + .ngpios = NUM_GPIO_PINGROUPS, +}; + +static int msm8x74_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &msm8x74_pinctrl); +} + +static struct of_device_id msm8x74_pinctrl_of_match[] = { + { .compatible = "qcom,msm8x74-pinctrl", }, + { }, +}; + +static struct platform_driver msm8x74_pinctrl_driver = { + .driver = { + .name = "msm8x74-pinctrl", + .owner = THIS_MODULE, + .of_match_table = msm8x74_pinctrl_of_match, + }, + .probe = msm8x74_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init msm8x74_pinctrl_init(void) +{ + return platform_driver_register(&msm8x74_pinctrl_driver); +} +arch_initcall(msm8x74_pinctrl_init); + +static void __exit msm8x74_pinctrl_exit(void) +{ + platform_driver_unregister(&msm8x74_pinctrl_driver); +} +module_exit(msm8x74_pinctrl_exit); + +MODULE_AUTHOR("Bjorn Andersson "); +MODULE_DESCRIPTION("Qualcomm MSM8x74 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, msm8x74_pinctrl_of_match); + diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 983662e846a4..6559e1436768 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1060,14 +1060,14 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, (mode < 0) ? "unknown" : modes[mode], pull ? "pull" : "none"); - if (label && !is_out) { - int irq = gpio_to_irq(gpio); + if (!is_out) { + int irq = gpio_to_irq(gpio); struct irq_desc *desc = irq_to_desc(irq); /* This races with request_irq(), set_irq_type(), * and set_irq_wake() ... but those are "rare". */ - if (irq >= 0 && desc->action) { + if (irq > 0 && desc && desc->action) { char *trigger; u32 bitmask = nmk_gpio_get_bitmask(gpio); diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index d77ece5217f0..b9b464d0578c 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -26,29 +26,67 @@ #include "core.h" -static int sh_pfc_ioremap(struct sh_pfc *pfc, struct platform_device *pdev) +static int sh_pfc_map_resources(struct sh_pfc *pfc, + struct platform_device *pdev) { + unsigned int num_windows = 0; + unsigned int num_irqs = 0; + struct sh_pfc_window *windows; + unsigned int *irqs = NULL; struct resource *res; - int k; + unsigned int i; - if (pdev->num_resources == 0) + /* Count the MEM and IRQ resources. */ + for (i = 0; i < pdev->num_resources; ++i) { + switch (resource_type(&pdev->resource[i])) { + case IORESOURCE_MEM: + num_windows++; + break; + + case IORESOURCE_IRQ: + num_irqs++; + break; + } + } + + if (num_windows == 0) return -EINVAL; - pfc->window = devm_kzalloc(pfc->dev, pdev->num_resources * - sizeof(*pfc->window), GFP_NOWAIT); - if (!pfc->window) + /* Allocate memory windows and IRQs arrays. */ + windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows), + GFP_KERNEL); + if (windows == NULL) return -ENOMEM; - pfc->num_windows = pdev->num_resources; + pfc->num_windows = num_windows; + pfc->windows = windows; - for (k = 0, res = pdev->resource; k < pdev->num_resources; k++, res++) { - WARN_ON(resource_type(res) != IORESOURCE_MEM); - pfc->window[k].phys = res->start; - pfc->window[k].size = resource_size(res); - pfc->window[k].virt = devm_ioremap_nocache(pfc->dev, res->start, - resource_size(res)); - if (!pfc->window[k].virt) + if (num_irqs) { + irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs), + GFP_KERNEL); + if (irqs == NULL) return -ENOMEM; + + pfc->num_irqs = num_irqs; + pfc->irqs = irqs; + } + + /* Fill them. */ + for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) { + switch (resource_type(res)) { + case IORESOURCE_MEM: + windows->phys = res->start; + windows->size = resource_size(res); + windows->virt = devm_ioremap_resource(pfc->dev, res); + if (IS_ERR(windows->virt)) + return -ENOMEM; + windows++; + break; + + case IORESOURCE_IRQ: + *irqs++ = res->start; + break; + } } return 0; @@ -62,7 +100,7 @@ static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, /* scan through physical windows and convert address */ for (i = 0; i < pfc->num_windows; i++) { - window = pfc->window + i; + window = pfc->windows + i; if (address < window->phys) continue; @@ -147,7 +185,7 @@ static void sh_pfc_config_reg_helper(struct sh_pfc *pfc, unsigned long *maskp, unsigned long *posp) { - int k; + unsigned int k; *mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg); @@ -196,7 +234,7 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id, { const struct pinmux_cfg_reg *config_reg; unsigned long r_width, f_width, curr_width, ncomb; - int k, m, n, pos, bit_pos; + unsigned int k, m, n, pos, bit_pos; k = 0; while (1) { @@ -238,7 +276,7 @@ static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos, u16 *enum_idp) { const u16 *data = pfc->info->gpio_data; - int k; + unsigned int k; if (pos) { *enum_idp = data[pos + 1]; @@ -481,7 +519,7 @@ static int sh_pfc_probe(struct platform_device *pdev) pfc->info = info; pfc->dev = &pdev->dev; - ret = sh_pfc_ioremap(pfc, pdev); + ret = sh_pfc_map_resources(pfc, pdev); if (unlikely(ret < 0)) return ret; diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index 11ea87268658..b7b0e6ccf305 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h @@ -37,7 +37,9 @@ struct sh_pfc { spinlock_t lock; unsigned int num_windows; - struct sh_pfc_window *window; + struct sh_pfc_window *windows; + unsigned int num_irqs; + unsigned int *irqs; struct sh_pfc_pin_range *ranges; unsigned int nr_ranges; diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c index 04bf52b64fb3..63480815e1af 100644 --- a/drivers/pinctrl/sh-pfc/gpio.c +++ b/drivers/pinctrl/sh-pfc/gpio.c @@ -204,18 +204,24 @@ static void gpio_pin_set(struct gpio_chip *gc, unsigned offset, int value) static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) { struct sh_pfc *pfc = gpio_to_pfc(gc); - int i, k; + unsigned int i, k; for (i = 0; i < pfc->info->gpio_irq_size; i++) { - unsigned short *gpios = pfc->info->gpio_irq[i].gpios; + short *gpios = pfc->info->gpio_irq[i].gpios; - for (k = 0; gpios[k]; k++) { + for (k = 0; gpios[k] >= 0; k++) { if (gpios[k] == offset) - return pfc->info->gpio_irq[i].irq; + goto found; } } return -ENOSYS; + +found: + if (pfc->num_irqs) + return pfc->irqs[i]; + else + return pfc->info->gpio_irq[i].irq; } static int gpio_pin_setup(struct sh_pfc_chip *chip) @@ -347,7 +353,7 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc) * GPIOs. */ for (i = 0; i < pfc->num_windows; ++i) { - struct sh_pfc_window *window = &pfc->window[i]; + struct sh_pfc_window *window = &pfc->windows[i]; if (pfc->info->data_regs[0].reg >= window->phys && pfc->info->data_regs[0].reg < window->phys + window->size) @@ -357,8 +363,14 @@ int sh_pfc_register_gpiochip(struct sh_pfc *pfc) if (i == pfc->num_windows) return 0; + /* If we have IRQ resources make sure their number is correct. */ + if (pfc->num_irqs && pfc->num_irqs != pfc->info->gpio_irq_size) { + dev_err(pfc->dev, "invalid number of IRQ resources\n"); + return -EINVAL; + } + /* Register the real GPIOs chip. */ - chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->window[i]); + chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]); if (IS_ERR(chip)) return PTR_ERR(chip); diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c index d25fd4ea0a1d..32dd478f28e3 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a73a4.c @@ -2061,17 +2061,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(sdhi2), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } - static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xe6050000), PORTCR(1, 0xe6050001), @@ -2691,7 +2680,7 @@ static unsigned int r8a73a4_pinmux_get_bias(struct sh_pfc *pfc, { void __iomem *addr; - addr = pfc->window->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; + addr = pfc->windows->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; switch (ioread8(addr) & PORTCR_PULMD_MASK) { case PORTCR_PULMD_UP: @@ -2710,7 +2699,7 @@ static void r8a73a4_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, void __iomem *addr; u32 value; - addr = pfc->window->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; + addr = pfc->windows->virt + r8a73a4_portcr_offsets[pin >> 5] + pin; value = ioread8(addr) & ~PORTCR_PULMD_MASK; switch (bias) { diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c index bc5eb453a45c..61e258577881 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c @@ -3234,17 +3234,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(tpu0), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } - static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xe6050000), /* PORT0CR */ PORTCR(1, 0xe6050001), /* PORT1CR */ @@ -3721,7 +3710,7 @@ static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin) &r8a7740_portcr_offsets[i]; if (pin <= group->end_pin) - return pfc->window->virt + group->offset + pin; + return pfc->windows->virt + group->offset + pin; } return NULL; diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index 72786fc93958..293a51a7434e 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c @@ -1739,6 +1739,56 @@ static struct sh_pfc_pin pinmux_pins[] = { SH_PFC_PIN_NAMED(ROW_GROUP_A('H'), 15, AH15), }; +/* - AUDIO CLOCK ------------------------------------------------------------ */ +static const unsigned int audio_clk_a_pins[] = { + /* CLK A */ + RCAR_GP_PIN(4, 25), +}; +static const unsigned int audio_clk_a_mux[] = { + AUDIO_CLKA_MARK, +}; +static const unsigned int audio_clk_b_pins[] = { + /* CLK B */ + RCAR_GP_PIN(4, 26), +}; +static const unsigned int audio_clk_b_mux[] = { + AUDIO_CLKB_MARK, +}; +static const unsigned int audio_clk_c_pins[] = { + /* CLK C */ + RCAR_GP_PIN(5, 27), +}; +static const unsigned int audio_clk_c_mux[] = { + AUDIO_CLKC_MARK, +}; +static const unsigned int audio_clkout_pins[] = { + /* CLK OUT */ + RCAR_GP_PIN(5, 16), +}; +static const unsigned int audio_clkout_mux[] = { + AUDIO_CLKOUT_MARK, +}; +static const unsigned int audio_clkout_b_pins[] = { + /* CLK OUT B */ + RCAR_GP_PIN(0, 23), +}; +static const unsigned int audio_clkout_b_mux[] = { + AUDIO_CLKOUT_B_MARK, +}; +static const unsigned int audio_clkout_c_pins[] = { + /* CLK OUT C */ + RCAR_GP_PIN(5, 27), +}; +static const unsigned int audio_clkout_c_mux[] = { + AUDIO_CLKOUT_C_MARK, +}; +static const unsigned int audio_clkout_d_pins[] = { + /* CLK OUT D */ + RCAR_GP_PIN(5, 20), +}; +static const unsigned int audio_clkout_d_mux[] = { + AUDIO_CLKOUT_D_MARK, +}; /* - DU RGB ----------------------------------------------------------------- */ static const unsigned int du_rgb666_pins[] = { /* R[7:2], G[7:2], B[7:2] */ @@ -2961,6 +3011,189 @@ static const unsigned int sdhi3_wp_pins[] = { static const unsigned int sdhi3_wp_mux[] = { SD3_WP_MARK, }; +/* - SSI -------------------------------------------------------------------- */ +static const unsigned int ssi0_data_pins[] = { + /* SDATA0 */ + RCAR_GP_PIN(4, 5), +}; +static const unsigned int ssi0_data_mux[] = { + SSI_SDATA0_MARK, +}; +static const unsigned int ssi0129_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 4), +}; +static const unsigned int ssi0129_ctrl_mux[] = { + SSI_SCK0129_MARK, SSI_WS0129_MARK, +}; +static const unsigned int ssi1_data_pins[] = { + /* SDATA1 */ + RCAR_GP_PIN(4, 6), +}; +static const unsigned int ssi1_data_mux[] = { + SSI_SDATA1_MARK, +}; +static const unsigned int ssi1_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 24), +}; +static const unsigned int ssi1_ctrl_mux[] = { + SSI_SCK1_MARK, SSI_WS1_MARK, +}; +static const unsigned int ssi2_data_pins[] = { + /* SDATA2 */ + RCAR_GP_PIN(4, 7), +}; +static const unsigned int ssi2_data_mux[] = { + SSI_SDATA2_MARK, +}; +static const unsigned int ssi2_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 17), +}; +static const unsigned int ssi2_ctrl_mux[] = { + SSI_SCK2_MARK, SSI_WS2_MARK, +}; +static const unsigned int ssi3_data_pins[] = { + /* SDATA3 */ + RCAR_GP_PIN(4, 10), +}; +static const unsigned int ssi3_data_mux[] = { + SSI_SDATA3_MARK +}; +static const unsigned int ssi34_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 8), RCAR_GP_PIN(4, 9), +}; +static const unsigned int ssi34_ctrl_mux[] = { + SSI_SCK34_MARK, SSI_WS34_MARK, +}; +static const unsigned int ssi4_data_pins[] = { + /* SDATA4 */ + RCAR_GP_PIN(4, 13), +}; +static const unsigned int ssi4_data_mux[] = { + SSI_SDATA4_MARK, +}; +static const unsigned int ssi4_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 12), +}; +static const unsigned int ssi4_ctrl_mux[] = { + SSI_SCK4_MARK, SSI_WS4_MARK, +}; +static const unsigned int ssi5_pins[] = { + /* SDATA5, SCK, WS */ + RCAR_GP_PIN(4, 16), RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 15), +}; +static const unsigned int ssi5_mux[] = { + SSI_SDATA5_MARK, SSI_SCK5_MARK, SSI_WS5_MARK, +}; +static const unsigned int ssi5_b_pins[] = { + /* SDATA5, SCK, WS */ + RCAR_GP_PIN(0, 26), RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), +}; +static const unsigned int ssi5_b_mux[] = { + SSI_SDATA5_B_MARK, SSI_SCK5_B_MARK, SSI_WS5_B_MARK +}; +static const unsigned int ssi5_c_pins[] = { + /* SDATA5, SCK, WS */ + RCAR_GP_PIN(4, 24), RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 12), +}; +static const unsigned int ssi5_c_mux[] = { + SSI_SDATA5_C_MARK, SSI_SCK5_C_MARK, SSI_WS5_C_MARK, +}; +static const unsigned int ssi6_pins[] = { + /* SDATA6, SCK, WS */ + RCAR_GP_PIN(4, 19), RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 18), +}; +static const unsigned int ssi6_mux[] = { + SSI_SDATA6_MARK, SSI_SCK6_MARK, SSI_WS6_MARK, +}; +static const unsigned int ssi6_b_pins[] = { + /* SDATA6, SCK, WS */ + RCAR_GP_PIN(1, 29), RCAR_GP_PIN(1, 25), RCAR_GP_PIN(1, 27), +}; +static const unsigned int ssi6_b_mux[] = { + SSI_SDATA6_B_MARK, SSI_SCK6_B_MARK, SSI_WS6_B_MARK, +}; +static const unsigned int ssi7_data_pins[] = { + /* SDATA7 */ + RCAR_GP_PIN(4, 22), +}; +static const unsigned int ssi7_data_mux[] = { + SSI_SDATA7_MARK, +}; +static const unsigned int ssi7_b_data_pins[] = { + /* SDATA7 */ + RCAR_GP_PIN(4, 22), +}; +static const unsigned int ssi7_b_data_mux[] = { + SSI_SDATA7_B_MARK, +}; +static const unsigned int ssi7_c_data_pins[] = { + /* SDATA7 */ + RCAR_GP_PIN(1, 26), +}; +static const unsigned int ssi7_c_data_mux[] = { + SSI_SDATA7_C_MARK, +}; +static const unsigned int ssi78_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(4, 20), RCAR_GP_PIN(4, 21), +}; +static const unsigned int ssi78_ctrl_mux[] = { + SSI_SCK78_MARK, SSI_WS78_MARK, +}; +static const unsigned int ssi78_b_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 24), +}; +static const unsigned int ssi78_b_ctrl_mux[] = { + SSI_SCK78_B_MARK, SSI_WS78_B_MARK, +}; +static const unsigned int ssi78_c_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 25), +}; +static const unsigned int ssi78_c_ctrl_mux[] = { + SSI_SCK78_C_MARK, SSI_WS78_C_MARK, +}; +static const unsigned int ssi8_data_pins[] = { + /* SDATA8 */ + RCAR_GP_PIN(4, 23), +}; +static const unsigned int ssi8_data_mux[] = { + SSI_SDATA8_MARK, +}; +static const unsigned int ssi8_b_data_pins[] = { + /* SDATA8 */ + RCAR_GP_PIN(4, 23), +}; +static const unsigned int ssi8_b_data_mux[] = { + SSI_SDATA8_B_MARK, +}; +static const unsigned int ssi8_c_data_pins[] = { + /* SDATA8 */ + RCAR_GP_PIN(1, 27), +}; +static const unsigned int ssi8_c_data_mux[] = { + SSI_SDATA8_C_MARK, +}; +static const unsigned int ssi9_data_pins[] = { + /* SDATA9 */ + RCAR_GP_PIN(4, 24), +}; +static const unsigned int ssi9_data_mux[] = { + SSI_SDATA9_MARK, +}; +static const unsigned int ssi9_ctrl_pins[] = { + /* SCK, WS */ + RCAR_GP_PIN(5, 10), RCAR_GP_PIN(5, 11), +}; +static const unsigned int ssi9_ctrl_mux[] = { + SSI_SCK9_MARK, SSI_WS9_MARK, +}; /* - TPU0 ------------------------------------------------------------------- */ static const unsigned int tpu0_to0_pins[] = { /* TO */ @@ -3014,59 +3247,110 @@ static const unsigned int usb2_pins[] = { static const unsigned int usb2_mux[] = { USB2_PWEN_MARK, USB2_OVC_MARK, }; + +union vin_data { + unsigned int data24[24]; + unsigned int data20[20]; + unsigned int data16[16]; + unsigned int data12[12]; + unsigned int data10[10]; + unsigned int data8[8]; + unsigned int data4[4]; +}; + +#define VIN_DATA_PIN_GROUP(n, s) \ + { \ + .name = #n#s, \ + .pins = n##_pins.data##s, \ + .mux = n##_mux.data##s, \ + .nr_pins = ARRAY_SIZE(n##_pins.data##s), \ + } + /* - VIN0 ------------------------------------------------------------------- */ -static const unsigned int vin0_data_g_pins[] = { - RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 10), - RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), +static const union vin_data vin0_data_pins = { + .data24 = { + /* B */ + RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), + RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4), + RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6), + RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), + /* G */ + RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), + RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), + /* R */ + RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), + RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), + RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), + RCAR_GP_PIN(0, 26), RCAR_GP_PIN(1, 11), + }, +}; +static const union vin_data vin0_data_mux = { + .data24 = { + /* B */ + VI0_DATA0_VI0_B0_MARK, VI0_DATA1_VI0_B1_MARK, + VI0_DATA2_VI0_B2_MARK, VI0_DATA3_VI0_B3_MARK, + VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, + VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK, + /* G */ + VI0_G0_MARK, VI0_G1_MARK, + VI0_G2_MARK, VI0_G3_MARK, + VI0_G4_MARK, VI0_G5_MARK, + VI0_G6_MARK, VI0_G7_MARK, + /* R */ + VI0_R0_MARK, VI0_R1_MARK, + VI0_R2_MARK, VI0_R3_MARK, + VI0_R4_MARK, VI0_R5_MARK, + VI0_R6_MARK, VI0_R7_MARK, + }, +}; +static const unsigned int vin0_data18_pins[] = { + /* B */ + RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4), + RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6), + RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), + /* G */ + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), -}; -static const unsigned int vin0_data_g_mux[] = { - VI0_G0_MARK, VI0_G1_MARK, VI0_G2_MARK, - VI0_G3_MARK, VI0_G4_MARK, VI0_G5_MARK, - VI0_G6_MARK, VI0_G7_MARK, -}; -static const unsigned int vin0_data_r_pins[] = { - RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 6), - RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), + /* R */ + RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), + RCAR_GP_PIN(0, 24), RCAR_GP_PIN(0, 25), RCAR_GP_PIN(0, 26), RCAR_GP_PIN(1, 11), }; -static const unsigned int vin0_data_r_mux[] = { - VI0_R0_MARK, VI0_R1_MARK, VI0_R2_MARK, - VI0_R3_MARK, VI0_R4_MARK, VI0_R5_MARK, +static const unsigned int vin0_data18_mux[] = { + /* B */ + VI0_DATA2_VI0_B2_MARK, VI0_DATA3_VI0_B3_MARK, + VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, + VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK, + /* G */ + VI0_G2_MARK, VI0_G3_MARK, + VI0_G4_MARK, VI0_G5_MARK, + VI0_G6_MARK, VI0_G7_MARK, + /* R */ + VI0_R2_MARK, VI0_R3_MARK, + VI0_R4_MARK, VI0_R5_MARK, VI0_R6_MARK, VI0_R7_MARK, }; -static const unsigned int vin0_data_b_pins[] = { - RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 3), - RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 6), - RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), +static const unsigned int vin0_sync_pins[] = { + RCAR_GP_PIN(0, 12), /* HSYNC */ + RCAR_GP_PIN(0, 13), /* VSYNC */ }; -static const unsigned int vin0_data_b_mux[] = { - VI0_DATA0_VI0_B0_MARK, VI0_DATA1_VI0_B1_MARK, VI0_DATA2_VI0_B2_MARK, - VI0_DATA3_VI0_B3_MARK, VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK, - VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK, -}; -static const unsigned int vin0_hsync_signal_pins[] = { - RCAR_GP_PIN(0, 12), -}; -static const unsigned int vin0_hsync_signal_mux[] = { +static const unsigned int vin0_sync_mux[] = { VI0_HSYNC_N_MARK, -}; -static const unsigned int vin0_vsync_signal_pins[] = { - RCAR_GP_PIN(0, 13), -}; -static const unsigned int vin0_vsync_signal_mux[] = { VI0_VSYNC_N_MARK, }; -static const unsigned int vin0_field_signal_pins[] = { +static const unsigned int vin0_field_pins[] = { RCAR_GP_PIN(0, 15), }; -static const unsigned int vin0_field_signal_mux[] = { +static const unsigned int vin0_field_mux[] = { VI0_FIELD_MARK, }; -static const unsigned int vin0_data_enable_pins[] = { +static const unsigned int vin0_clkenb_pins[] = { RCAR_GP_PIN(0, 14), }; -static const unsigned int vin0_data_enable_mux[] = { +static const unsigned int vin0_clkenb_mux[] = { VI0_CLKENB_MARK, }; static const unsigned int vin0_clk_pins[] = { @@ -3076,15 +3360,91 @@ static const unsigned int vin0_clk_mux[] = { VI0_CLK_MARK, }; /* - VIN1 ------------------------------------------------------------------- */ -static const unsigned int vin1_data_pins[] = { - RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 12), - RCAR_GP_PIN(2, 13), RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), - RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17), +static const union vin_data vin1_data_pins = { + .data24 = { + /* B */ + RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), + RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), + RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), + RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17), + /* G */ + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 15), + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 12), + RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(0, 27), RCAR_GP_PIN(0, 28), + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 4), + RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), + RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 8), + }, }; -static const unsigned int vin1_data_mux[] = { - VI1_DATA0_VI1_B0_MARK, VI1_DATA1_VI1_B1_MARK, VI1_DATA2_VI1_B2_MARK, - VI1_DATA3_VI1_B3_MARK, VI1_DATA4_VI1_B4_MARK, VI1_DATA5_VI1_B5_MARK, +static const union vin_data vin1_data_mux = { + .data24 = { + /* B */ + VI1_DATA0_VI1_B0_MARK, VI1_DATA1_VI1_B1_MARK, + VI1_DATA2_VI1_B2_MARK, VI1_DATA3_VI1_B3_MARK, + VI1_DATA4_VI1_B4_MARK, VI1_DATA5_VI1_B5_MARK, + VI1_DATA6_VI1_B6_MARK, VI1_DATA7_VI1_B7_MARK, + /* G */ + VI1_G0_MARK, VI1_G1_MARK, + VI1_G2_MARK, VI1_G3_MARK, + VI1_G4_MARK, VI1_G5_MARK, + VI1_G6_MARK, VI1_G7_MARK, + /* R */ + VI1_R0_MARK, VI1_R1_MARK, + VI1_R2_MARK, VI1_R3_MARK, + VI1_R4_MARK, VI1_R5_MARK, + VI1_R6_MARK, VI1_R7_MARK, + }, +}; +static const unsigned int vin1_data18_pins[] = { + /* B */ + RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), + RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), + RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 17), + /* G */ + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 12), + RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 4), + RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), + RCAR_GP_PIN(1, 10), RCAR_GP_PIN(1, 8), +}; +static const unsigned int vin1_data18_mux[] = { + /* B */ + VI1_DATA2_VI1_B2_MARK, VI1_DATA3_VI1_B3_MARK, + VI1_DATA4_VI1_B4_MARK, VI1_DATA5_VI1_B5_MARK, VI1_DATA6_VI1_B6_MARK, VI1_DATA7_VI1_B7_MARK, + /* G */ + VI1_G2_MARK, VI1_G3_MARK, + VI1_G4_MARK, VI1_G5_MARK, + VI1_G6_MARK, VI1_G7_MARK, + /* R */ + VI1_R2_MARK, VI1_R3_MARK, + VI1_R4_MARK, VI1_R5_MARK, + VI1_R6_MARK, VI1_R7_MARK, +}; +static const unsigned int vin1_sync_pins[] = { + RCAR_GP_PIN(1, 24), /* HSYNC */ + RCAR_GP_PIN(1, 25), /* VSYNC */ +}; +static const unsigned int vin1_sync_mux[] = { + VI1_HSYNC_N_MARK, + VI1_VSYNC_N_MARK, +}; +static const unsigned int vin1_field_pins[] = { + RCAR_GP_PIN(1, 13), +}; +static const unsigned int vin1_field_mux[] = { + VI1_FIELD_MARK, +}; +static const unsigned int vin1_clkenb_pins[] = { + RCAR_GP_PIN(1, 26), +}; +static const unsigned int vin1_clkenb_mux[] = { + VI1_CLKENB_MARK, }; static const unsigned int vin1_clk_pins[] = { RCAR_GP_PIN(2, 9), @@ -3092,8 +3452,147 @@ static const unsigned int vin1_clk_pins[] = { static const unsigned int vin1_clk_mux[] = { VI1_CLK_MARK, }; +/* - VIN2 ----------------------------------------------------------------- */ +static const union vin_data vin2_data_pins = { + .data24 = { + /* B */ + RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 9), + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13), + RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15), + /* G */ + RCAR_GP_PIN(0, 27), RCAR_GP_PIN(0, 28), + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 10), + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 5), + RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 13), + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 15), + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 24), + }, +}; +static const union vin_data vin2_data_mux = { + .data24 = { + /* B */ + VI2_DATA0_VI2_B0_MARK, VI2_DATA1_VI2_B1_MARK, + VI2_DATA2_VI2_B2_MARK, VI2_DATA3_VI2_B3_MARK, + VI2_DATA4_VI2_B4_MARK, VI2_DATA5_VI2_B5_MARK, + VI2_DATA6_VI2_B6_MARK, VI2_DATA7_VI2_B7_MARK, + /* G */ + VI2_G0_MARK, VI2_G1_MARK, + VI2_G2_MARK, VI2_G3_MARK, + VI2_G4_MARK, VI2_G5_MARK, + VI2_G6_MARK, VI2_G7_MARK, + /* R */ + VI2_R0_MARK, VI2_R1_MARK, + VI2_R2_MARK, VI2_R3_MARK, + VI2_R4_MARK, VI2_R5_MARK, + VI2_R6_MARK, VI2_R7_MARK, + }, +}; +static const unsigned int vin2_data18_pins[] = { + /* B */ + RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11), + RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 13), + RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15), + /* G */ + RCAR_GP_PIN(0, 29), RCAR_GP_PIN(1, 10), + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 5), + RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7), + /* R */ + RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 15), + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 20), + RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 24), +}; +static const unsigned int vin2_data18_mux[] = { + /* B */ + VI2_DATA2_VI2_B2_MARK, VI2_DATA3_VI2_B3_MARK, + VI2_DATA4_VI2_B4_MARK, VI2_DATA5_VI2_B5_MARK, + VI2_DATA6_VI2_B6_MARK, VI2_DATA7_VI2_B7_MARK, + /* G */ + VI2_G2_MARK, VI2_G3_MARK, + VI2_G4_MARK, VI2_G5_MARK, + VI2_G6_MARK, VI2_G7_MARK, + /* R */ + VI2_R2_MARK, VI2_R3_MARK, + VI2_R4_MARK, VI2_R5_MARK, + VI2_R6_MARK, VI2_R7_MARK, +}; +static const unsigned int vin2_sync_pins[] = { + RCAR_GP_PIN(1, 16), /* HSYNC */ + RCAR_GP_PIN(1, 21), /* VSYNC */ +}; +static const unsigned int vin2_sync_mux[] = { + VI2_HSYNC_N_MARK, + VI2_VSYNC_N_MARK, +}; +static const unsigned int vin2_field_pins[] = { + RCAR_GP_PIN(1, 9), +}; +static const unsigned int vin2_field_mux[] = { + VI2_FIELD_MARK, +}; +static const unsigned int vin2_clkenb_pins[] = { + RCAR_GP_PIN(1, 8), +}; +static const unsigned int vin2_clkenb_mux[] = { + VI2_CLKENB_MARK, +}; +static const unsigned int vin2_clk_pins[] = { + RCAR_GP_PIN(1, 11), +}; +static const unsigned int vin2_clk_mux[] = { + VI2_CLK_MARK, +}; +/* - VIN3 ----------------------------------------------------------------- */ +static const unsigned int vin3_data8_pins[] = { + RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), + RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), + RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), + RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), +}; +static const unsigned int vin3_data8_mux[] = { + VI3_DATA0_MARK, VI3_DATA1_MARK, + VI3_DATA2_MARK, VI3_DATA3_MARK, + VI3_DATA4_MARK, VI3_DATA5_MARK, + VI3_DATA6_MARK, VI3_DATA7_MARK, +}; +static const unsigned int vin3_sync_pins[] = { + RCAR_GP_PIN(1, 16), /* HSYNC */ + RCAR_GP_PIN(1, 17), /* VSYNC */ +}; +static const unsigned int vin3_sync_mux[] = { + VI3_HSYNC_N_MARK, + VI2_VSYNC_N_MARK, +}; +static const unsigned int vin3_field_pins[] = { + RCAR_GP_PIN(1, 15), +}; +static const unsigned int vin3_field_mux[] = { + VI3_FIELD_MARK, +}; +static const unsigned int vin3_clkenb_pins[] = { + RCAR_GP_PIN(1, 14), +}; +static const unsigned int vin3_clkenb_mux[] = { + VI3_CLKENB_MARK, +}; +static const unsigned int vin3_clk_pins[] = { + RCAR_GP_PIN(1, 23), +}; +static const unsigned int vin3_clk_mux[] = { + VI3_CLK_MARK, +}; static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(audio_clk_a), + SH_PFC_PIN_GROUP(audio_clk_b), + SH_PFC_PIN_GROUP(audio_clk_c), + SH_PFC_PIN_GROUP(audio_clkout), + SH_PFC_PIN_GROUP(audio_clkout_b), + SH_PFC_PIN_GROUP(audio_clkout_c), + SH_PFC_PIN_GROUP(audio_clkout_d), SH_PFC_PIN_GROUP(du_rgb666), SH_PFC_PIN_GROUP(du_rgb888), SH_PFC_PIN_GROUP(du_clk_out_0), @@ -3259,6 +3758,32 @@ 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(ssi0_data), + SH_PFC_PIN_GROUP(ssi0129_ctrl), + SH_PFC_PIN_GROUP(ssi1_data), + SH_PFC_PIN_GROUP(ssi1_ctrl), + SH_PFC_PIN_GROUP(ssi2_data), + SH_PFC_PIN_GROUP(ssi2_ctrl), + SH_PFC_PIN_GROUP(ssi3_data), + SH_PFC_PIN_GROUP(ssi34_ctrl), + SH_PFC_PIN_GROUP(ssi4_data), + SH_PFC_PIN_GROUP(ssi4_ctrl), + SH_PFC_PIN_GROUP(ssi5), + SH_PFC_PIN_GROUP(ssi5_b), + SH_PFC_PIN_GROUP(ssi5_c), + SH_PFC_PIN_GROUP(ssi6), + SH_PFC_PIN_GROUP(ssi6_b), + SH_PFC_PIN_GROUP(ssi7_data), + SH_PFC_PIN_GROUP(ssi7_b_data), + SH_PFC_PIN_GROUP(ssi7_c_data), + SH_PFC_PIN_GROUP(ssi78_ctrl), + SH_PFC_PIN_GROUP(ssi78_b_ctrl), + SH_PFC_PIN_GROUP(ssi78_c_ctrl), + SH_PFC_PIN_GROUP(ssi8_data), + SH_PFC_PIN_GROUP(ssi8_b_data), + SH_PFC_PIN_GROUP(ssi8_c_data), + SH_PFC_PIN_GROUP(ssi9_data), + SH_PFC_PIN_GROUP(ssi9_ctrl), SH_PFC_PIN_GROUP(tpu0_to0), SH_PFC_PIN_GROUP(tpu0_to1), SH_PFC_PIN_GROUP(tpu0_to2), @@ -3266,16 +3791,54 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(usb0), SH_PFC_PIN_GROUP(usb1), SH_PFC_PIN_GROUP(usb2), - SH_PFC_PIN_GROUP(vin0_data_g), - SH_PFC_PIN_GROUP(vin0_data_r), - SH_PFC_PIN_GROUP(vin0_data_b), - SH_PFC_PIN_GROUP(vin0_hsync_signal), - SH_PFC_PIN_GROUP(vin0_vsync_signal), - SH_PFC_PIN_GROUP(vin0_field_signal), - SH_PFC_PIN_GROUP(vin0_data_enable), + VIN_DATA_PIN_GROUP(vin0_data, 24), + VIN_DATA_PIN_GROUP(vin0_data, 20), + SH_PFC_PIN_GROUP(vin0_data18), + VIN_DATA_PIN_GROUP(vin0_data, 16), + VIN_DATA_PIN_GROUP(vin0_data, 12), + VIN_DATA_PIN_GROUP(vin0_data, 10), + VIN_DATA_PIN_GROUP(vin0_data, 8), + VIN_DATA_PIN_GROUP(vin0_data, 4), + SH_PFC_PIN_GROUP(vin0_sync), + SH_PFC_PIN_GROUP(vin0_field), + SH_PFC_PIN_GROUP(vin0_clkenb), SH_PFC_PIN_GROUP(vin0_clk), - SH_PFC_PIN_GROUP(vin1_data), + VIN_DATA_PIN_GROUP(vin1_data, 24), + VIN_DATA_PIN_GROUP(vin1_data, 20), + SH_PFC_PIN_GROUP(vin1_data18), + VIN_DATA_PIN_GROUP(vin1_data, 16), + VIN_DATA_PIN_GROUP(vin1_data, 12), + VIN_DATA_PIN_GROUP(vin1_data, 10), + VIN_DATA_PIN_GROUP(vin1_data, 8), + VIN_DATA_PIN_GROUP(vin1_data, 4), + SH_PFC_PIN_GROUP(vin1_sync), + SH_PFC_PIN_GROUP(vin1_field), + SH_PFC_PIN_GROUP(vin1_clkenb), SH_PFC_PIN_GROUP(vin1_clk), + VIN_DATA_PIN_GROUP(vin2_data, 24), + SH_PFC_PIN_GROUP(vin2_data18), + VIN_DATA_PIN_GROUP(vin2_data, 16), + VIN_DATA_PIN_GROUP(vin2_data, 8), + VIN_DATA_PIN_GROUP(vin2_data, 4), + SH_PFC_PIN_GROUP(vin2_sync), + SH_PFC_PIN_GROUP(vin2_field), + SH_PFC_PIN_GROUP(vin2_clkenb), + SH_PFC_PIN_GROUP(vin2_clk), + SH_PFC_PIN_GROUP(vin3_data8), + SH_PFC_PIN_GROUP(vin3_sync), + SH_PFC_PIN_GROUP(vin3_field), + SH_PFC_PIN_GROUP(vin3_clkenb), + SH_PFC_PIN_GROUP(vin3_clk), +}; + +static const char * const audio_clk_groups[] = { + "audio_clk_a", + "audio_clk_b", + "audio_clk_c", + "audio_clkout", + "audio_clkout_b", + "audio_clkout_c", + "audio_clkout_d", }; static const char * const du_groups[] = { @@ -3533,6 +4096,35 @@ static const char * const sdhi3_groups[] = { "sdhi3_wp", }; +static const char * const ssi_groups[] = { + "ssi0_data", + "ssi0129_ctrl", + "ssi1_data", + "ssi1_ctrl", + "ssi2_data", + "ssi2_ctrl", + "ssi3_data", + "ssi34_ctrl", + "ssi4_data", + "ssi4_ctrl", + "ssi5", + "ssi5_b", + "ssi5_c", + "ssi6", + "ssi6_b", + "ssi7_data", + "ssi7_b_data", + "ssi7_c_data", + "ssi78_ctrl", + "ssi78_b_ctrl", + "ssi78_c_ctrl", + "ssi8_data", + "ssi8_b_data", + "ssi8_c_data", + "ssi9_data", + "ssi9_ctrl", +}; + static const char * const tpu0_groups[] = { "tpu0_to0", "tpu0_to1", @@ -3553,22 +4145,57 @@ static const char * const usb2_groups[] = { }; static const char * const vin0_groups[] = { - "vin0_data_g", - "vin0_data_r", - "vin0_data_b", - "vin0_hsync_signal", - "vin0_vsync_signal", - "vin0_field_signal", - "vin0_data_enable", + "vin0_data24", + "vin0_data20", + "vin0_data18", + "vin0_data16", + "vin0_data12", + "vin0_data10", + "vin0_data8", + "vin0_data4", + "vin0_sync", + "vin0_field", + "vin0_clkenb", "vin0_clk", }; static const char * const vin1_groups[] = { - "vin1_data", + "vin1_data24", + "vin1_data20", + "vin1_data18", + "vin1_data16", + "vin1_data12", + "vin1_data10", + "vin1_data8", + "vin1_data4", + "vin1_sync", + "vin1_field", + "vin1_clkenb", "vin1_clk", }; +static const char * const vin2_groups[] = { + "vin2_data24", + "vin2_data18", + "vin2_data16", + "vin2_data8", + "vin2_data4", + "vin2_sync", + "vin2_field", + "vin2_clkenb", + "vin2_clk", +}; + +static const char * const vin3_groups[] = { + "vin3_data8", + "vin3_sync", + "vin3_field", + "vin3_clkenb", + "vin3_clk", +}; + static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(du), SH_PFC_FUNCTION(du0), SH_PFC_FUNCTION(du1), @@ -3599,12 +4226,15 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(sdhi1), SH_PFC_FUNCTION(sdhi2), SH_PFC_FUNCTION(sdhi3), + SH_PFC_FUNCTION(ssi), SH_PFC_FUNCTION(tpu0), SH_PFC_FUNCTION(usb0), SH_PFC_FUNCTION(usb1), SH_PFC_FUNCTION(usb2), SH_PFC_FUNCTION(vin0), SH_PFC_FUNCTION(vin1), + SH_PFC_FUNCTION(vin2), + SH_PFC_FUNCTION(vin3), }; static struct pinmux_cfg_reg pinmux_config_regs[] = { diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c index bf76a654c02f..ea02d37bab7c 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c @@ -1730,11 +1730,11 @@ static const unsigned int du_clk_out_1_pins[] = { static const unsigned int du_clk_out_1_mux[] = { DU1_DOTCLKOUT1_MARK }; -static const unsigned int du_sync_1_pins[] = { +static const unsigned int du_sync_pins[] = { /* EXVSYNC/VSYNC, EXHSYNC/HSYNC, EXDISP/EXODDF/EXCDE */ RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 27), }; -static const unsigned int du_sync_1_mux[] = { +static const unsigned int du_sync_mux[] = { DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK, DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK }; @@ -1742,6 +1742,9 @@ static const unsigned int du_cde_disp_pins[] = { /* CDE DISP */ RCAR_GP_PIN(3, 31), RCAR_GP_PIN(3, 30), }; +static const unsigned int du_cde_disp_mux[] = { + DU1_CDE_MARK, DU1_DISP_MARK +}; static const unsigned int du0_clk_in_pins[] = { /* CLKIN */ RCAR_GP_PIN(6, 31), @@ -1749,15 +1752,26 @@ static const unsigned int du0_clk_in_pins[] = { static const unsigned int du0_clk_in_mux[] = { DU0_DOTCLKIN_MARK }; -static const unsigned int du_cde_disp_mux[] = { - DU1_CDE_MARK, DU1_DISP_MARK -}; static const unsigned int du1_clk_in_pins[] = { /* CLKIN */ - RCAR_GP_PIN(7, 20), RCAR_GP_PIN(7, 19), RCAR_GP_PIN(3, 24), + RCAR_GP_PIN(3, 24), }; static const unsigned int du1_clk_in_mux[] = { - DU1_DOTCLKIN_C_MARK, DU1_DOTCLKIN_B_MARK, DU1_DOTCLKIN_MARK + DU1_DOTCLKIN_MARK +}; +static const unsigned int du1_clk_in_b_pins[] = { + /* CLKIN */ + RCAR_GP_PIN(7, 19), +}; +static const unsigned int du1_clk_in_b_mux[] = { + DU1_DOTCLKIN_B_MARK, +}; +static const unsigned int du1_clk_in_c_pins[] = { + /* CLKIN */ + RCAR_GP_PIN(7, 20), +}; +static const unsigned int du1_clk_in_c_mux[] = { + DU1_DOTCLKIN_C_MARK, }; /* - ETH -------------------------------------------------------------------- */ static const unsigned int eth_link_pins[] = { @@ -2670,10 +2684,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(du_rgb888), SH_PFC_PIN_GROUP(du_clk_out_0), SH_PFC_PIN_GROUP(du_clk_out_1), - SH_PFC_PIN_GROUP(du_sync_1), + SH_PFC_PIN_GROUP(du_sync), SH_PFC_PIN_GROUP(du_cde_disp), SH_PFC_PIN_GROUP(du0_clk_in), SH_PFC_PIN_GROUP(du1_clk_in), + SH_PFC_PIN_GROUP(du1_clk_in_b), + SH_PFC_PIN_GROUP(du1_clk_in_c), SH_PFC_PIN_GROUP(eth_link), SH_PFC_PIN_GROUP(eth_magic), SH_PFC_PIN_GROUP(eth_mdio), @@ -2805,7 +2821,7 @@ static const char * const du_groups[] = { "du_rgb888", "du_clk_out_0", "du_clk_out_1", - "du_sync_1", + "du_sync", "du_cde_disp", }; @@ -2815,6 +2831,8 @@ static const char * const du0_groups[] = { static const char * const du1_groups[] = { "du1_clk_in", + "du1_clk_in_b", + "du1_clk_in_c", }; static const char * const eth_groups[] = { @@ -2840,20 +2858,29 @@ static const char * const mmc_groups[] = { static const char * const msiof0_groups[] = { "msiof0_clk", - "msiof0_ctrl", - "msiof0_data", + "msiof0_sync", + "msiof0_ss1", + "msiof0_ss2", + "msiof0_rx", + "msiof0_tx", }; static const char * const msiof1_groups[] = { "msiof1_clk", - "msiof1_ctrl", - "msiof1_data", + "msiof1_sync", + "msiof1_ss1", + "msiof1_ss2", + "msiof1_rx", + "msiof1_tx", }; static const char * const msiof2_groups[] = { "msiof2_clk", - "msiof2_ctrl", - "msiof2_data", + "msiof2_sync", + "msiof2_ss1", + "msiof2_ss2", + "msiof2_rx", + "msiof2_tx", }; static const char * const scif0_groups[] = { diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7372.c b/drivers/pinctrl/sh-pfc/pfc-sh7372.c index cc097b693820..9f66a5025db0 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7372.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7372.c @@ -2118,17 +2118,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(usb1), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } - static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xE6051000), /* PORT0CR */ PORTCR(1, 0xE6051001), /* PORT1CR */ @@ -2585,7 +2574,7 @@ static void __iomem *sh7372_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin) &sh7372_portcr_offsets[i]; if (pin <= group->end_pin) - return pfc->window->virt + group->offset + pin; + return pfc->windows->virt + group->offset + pin; } return NULL; diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index 7e278a97e411..dc7c7fb33805 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c @@ -3138,16 +3138,6 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(usb), }; -#undef PORTCR -#define PORTCR(nr, reg) \ - { \ - PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ - PORT##nr##_FN0, PORT##nr##_FN1, \ - PORT##nr##_FN2, PORT##nr##_FN3, \ - PORT##nr##_FN4, PORT##nr##_FN5, \ - PORT##nr##_FN6, PORT##nr##_FN7 } \ - } static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(0, 0xe6050000), /* PORT0CR */ PORTCR(1, 0xe6050001), /* PORT1CR */ @@ -3661,38 +3651,38 @@ static const struct pinmux_data_reg pinmux_data_regs[] = { }; static const struct pinmux_irq pinmux_irqs[] = { - PINMUX_IRQ(irq_pin(19), 9), - PINMUX_IRQ(irq_pin(1), 10), PINMUX_IRQ(irq_pin(0), 11), + PINMUX_IRQ(irq_pin(1), 10), + PINMUX_IRQ(irq_pin(2), 149), + PINMUX_IRQ(irq_pin(3), 224), + PINMUX_IRQ(irq_pin(4), 159), + PINMUX_IRQ(irq_pin(5), 227), + PINMUX_IRQ(irq_pin(6), 147), + PINMUX_IRQ(irq_pin(7), 150), + PINMUX_IRQ(irq_pin(8), 223), + PINMUX_IRQ(irq_pin(9), 56, 308), + PINMUX_IRQ(irq_pin(10), 54), + PINMUX_IRQ(irq_pin(11), 238), + PINMUX_IRQ(irq_pin(12), 156), + PINMUX_IRQ(irq_pin(13), 239), + PINMUX_IRQ(irq_pin(14), 251), + PINMUX_IRQ(irq_pin(15), 0), + PINMUX_IRQ(irq_pin(16), 249), + PINMUX_IRQ(irq_pin(17), 234), PINMUX_IRQ(irq_pin(18), 13), + PINMUX_IRQ(irq_pin(19), 9), PINMUX_IRQ(irq_pin(20), 14), PINMUX_IRQ(irq_pin(21), 15), - PINMUX_IRQ(irq_pin(31), 26), - PINMUX_IRQ(irq_pin(30), 27), - PINMUX_IRQ(irq_pin(29), 28), PINMUX_IRQ(irq_pin(22), 40), PINMUX_IRQ(irq_pin(23), 53), - PINMUX_IRQ(irq_pin(10), 54), - PINMUX_IRQ(irq_pin(9), 56), + PINMUX_IRQ(irq_pin(24), 118), + PINMUX_IRQ(irq_pin(25), 164), PINMUX_IRQ(irq_pin(26), 115), PINMUX_IRQ(irq_pin(27), 116), PINMUX_IRQ(irq_pin(28), 117), - PINMUX_IRQ(irq_pin(24), 118), - PINMUX_IRQ(irq_pin(6), 147), - PINMUX_IRQ(irq_pin(2), 149), - PINMUX_IRQ(irq_pin(7), 150), - PINMUX_IRQ(irq_pin(12), 156), - PINMUX_IRQ(irq_pin(4), 159), - PINMUX_IRQ(irq_pin(25), 164), - PINMUX_IRQ(irq_pin(8), 223), - PINMUX_IRQ(irq_pin(3), 224), - PINMUX_IRQ(irq_pin(5), 227), - PINMUX_IRQ(irq_pin(17), 234), - PINMUX_IRQ(irq_pin(11), 238), - PINMUX_IRQ(irq_pin(13), 239), - PINMUX_IRQ(irq_pin(16), 249), - PINMUX_IRQ(irq_pin(14), 251), - PINMUX_IRQ(irq_pin(9), 308), + PINMUX_IRQ(irq_pin(29), 28), + PINMUX_IRQ(irq_pin(30), 27), + PINMUX_IRQ(irq_pin(31), 26), }; /* ----------------------------------------------------------------------------- @@ -3702,7 +3692,7 @@ static const struct pinmux_irq pinmux_irqs[] = { static void sh73a0_vccq_mc0_endisable(struct regulator_dev *reg, bool enable) { struct sh_pfc *pfc = reg->reg_data; - void __iomem *addr = pfc->window[1].virt + 4; + void __iomem *addr = pfc->windows[1].virt + 4; unsigned long flags; u32 value; @@ -3735,7 +3725,7 @@ static int sh73a0_vccq_mc0_disable(struct regulator_dev *reg) static int sh73a0_vccq_mc0_is_enabled(struct regulator_dev *reg) { struct sh_pfc *pfc = reg->reg_data; - void __iomem *addr = pfc->window[1].virt + 4; + void __iomem *addr = pfc->windows[1].virt + 4; unsigned long flags; u32 value; @@ -3794,7 +3784,7 @@ static const unsigned int sh73a0_portcr_offsets[] = { static unsigned int sh73a0_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin) { - void __iomem *addr = pfc->window->virt + void __iomem *addr = pfc->windows->virt + sh73a0_portcr_offsets[pin >> 5] + pin; u32 value = ioread8(addr) & PORTnCR_PULMD_MASK; @@ -3812,7 +3802,7 @@ static unsigned int sh73a0_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin) static void sh73a0_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, unsigned int bias) { - void __iomem *addr = pfc->window->virt + void __iomem *addr = pfc->windows->virt + sh73a0_portcr_offsets[pin >> 5] + pin; u32 value = ioread8(addr) & ~PORTnCR_PULMD_MASK; diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 11bd0d970a52..e17ccab54f2d 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -94,11 +94,11 @@ struct pinmux_data_reg { struct pinmux_irq { int irq; - unsigned short *gpios; + short *gpios; }; #define PINMUX_IRQ(irq_nr, ids...) \ - { .irq = irq_nr, .gpios = (unsigned short []) { ids, 0 } } \ + { .irq = irq_nr, .gpios = (short []) { ids, -1 } } struct pinmux_range { u16 begin; @@ -304,8 +304,7 @@ struct sh_pfc_soc_info { #define PORTCR(nr, reg) \ { \ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \ - _PCRH(PORT##nr##_IN, PORT##nr##_IN_PD, \ - PORT##nr##_IN_PU, PORT##nr##_OUT), \ + _PCRH(PORT##nr##_IN, 0, 0, PORT##nr##_OUT), \ PORT##nr##_FN0, PORT##nr##_FN1, \ PORT##nr##_FN2, PORT##nr##_FN3, \ PORT##nr##_FN4, PORT##nr##_FN5, \ diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 7d8103cd3e2e..1a3fc7a2e4db 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -421,9 +421,9 @@ static void sci_port_enable(struct sci_port *sci_port) pm_runtime_get_sync(sci_port->port.dev); - clk_enable(sci_port->iclk); + clk_prepare_enable(sci_port->iclk); sci_port->port.uartclk = clk_get_rate(sci_port->iclk); - clk_enable(sci_port->fclk); + clk_prepare_enable(sci_port->fclk); } static void sci_port_disable(struct sci_port *sci_port) @@ -431,8 +431,16 @@ static void sci_port_disable(struct sci_port *sci_port) if (!sci_port->port.dev) return; - clk_disable(sci_port->fclk); - clk_disable(sci_port->iclk); + /* Cancel the break timer to ensure that the timer handler will not try + * to access the hardware with clocks and power disabled. Reset the + * break flag to make the break debouncing state machine ready for the + * next break. + */ + del_timer_sync(&sci_port->break_timer); + sci_port->break_flag = 0; + + clk_disable_unprepare(sci_port->fclk); + clk_disable_unprepare(sci_port->iclk); pm_runtime_put_sync(sci_port->port.dev); } @@ -557,7 +565,7 @@ static inline int sci_rxd_in(struct uart_port *port) return 1; /* Cast for ARM damage */ - return !!__raw_readb((void __iomem *)s->cfg->port_reg); + return !!__raw_readb((void __iomem *)(uintptr_t)s->cfg->port_reg); } /* ********************************************************************** * @@ -733,8 +741,6 @@ static void sci_break_timer(unsigned long data) { struct sci_port *port = (struct sci_port *)data; - sci_port_enable(port); - if (sci_rxd_in(&port->port) == 0) { port->break_flag = 1; sci_schedule_break_timer(port); @@ -744,8 +750,6 @@ static void sci_break_timer(unsigned long data) sci_schedule_break_timer(port); } else port->break_flag = 0; - - sci_port_disable(port); } static int sci_handle_errors(struct uart_port *port) @@ -1309,7 +1313,7 @@ static int sci_dma_rx_push(struct sci_port *s, size_t count) } if (room < count) - dev_warn(port->dev, "Rx overrun: dropping %u bytes\n", + dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n", count - room); if (!room) return room; @@ -1442,7 +1446,7 @@ static void work_fn_rx(struct work_struct *work) int count; chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); - dev_dbg(port->dev, "Read %u bytes with cookie %d\n", + dev_dbg(port->dev, "Read %zu bytes with cookie %d\n", sh_desc->partial, sh_desc->cookie); spin_lock_irqsave(&port->lock, flags); @@ -1691,16 +1695,17 @@ static void sci_request_dma(struct uart_port *port) s->chan_tx = chan; sg_init_table(&s->sg_tx, 1); /* UART circular tx buffer is an aligned page. */ - BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK); + BUG_ON((uintptr_t)port->state->xmit.buf & ~PAGE_MASK); sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf), - UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK); + UART_XMIT_SIZE, + (uintptr_t)port->state->xmit.buf & ~PAGE_MASK); nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE); if (!nent) sci_tx_dma_release(s, false); else - dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__, - sg_dma_len(&s->sg_tx), - port->state->xmit.buf, sg_dma_address(&s->sg_tx)); + dev_dbg(port->dev, "%s: mapped %d@%p to %pad\n", __func__, + sg_dma_len(&s->sg_tx), port->state->xmit.buf, + &sg_dma_address(&s->sg_tx)); s->sg_len_tx = nent; @@ -1740,7 +1745,7 @@ static void sci_request_dma(struct uart_port *port) sg_init_table(sg, 1); sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, - (int)buf[i] & ~PAGE_MASK); + (uintptr_t)buf[i] & ~PAGE_MASK); sg_dma_address(sg) = dma[i]; } diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h new file mode 100644 index 000000000000..dbb262a3e7a6 --- /dev/null +++ b/include/dt-bindings/clock/r8a7790-clock.h @@ -0,0 +1,120 @@ +/* + * Copyright 2013 Ideas On Board SPRL + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __DT_BINDINGS_CLOCK_R8A7790_H__ +#define __DT_BINDINGS_CLOCK_R8A7790_H__ + +/* CPG */ +#define R8A7790_CLK_MAIN 0 +#define R8A7790_CLK_PLL0 1 +#define R8A7790_CLK_PLL1 2 +#define R8A7790_CLK_PLL3 3 +#define R8A7790_CLK_LB 4 +#define R8A7790_CLK_QSPI 5 +#define R8A7790_CLK_SDH 6 +#define R8A7790_CLK_SD0 7 +#define R8A7790_CLK_SD1 8 +#define R8A7790_CLK_Z 9 + +/* MSTP0 */ +#define R8A7790_CLK_MSIOF0 0 + +/* MSTP1 */ +#define R8A7790_CLK_TMU1 11 +#define R8A7790_CLK_TMU3 21 +#define R8A7790_CLK_TMU2 22 +#define R8A7790_CLK_CMT0 24 +#define R8A7790_CLK_TMU0 25 +#define R8A7790_CLK_VSP1_DU1 27 +#define R8A7790_CLK_VSP1_DU0 28 +#define R8A7790_CLK_VSP1_RT 30 +#define R8A7790_CLK_VSP1_SY 31 + +/* MSTP2 */ +#define R8A7790_CLK_SCIFA2 2 +#define R8A7790_CLK_SCIFA1 3 +#define R8A7790_CLK_SCIFA0 4 +#define R8A7790_CLK_MSIOF2 5 +#define R8A7790_CLK_SCIFB0 6 +#define R8A7790_CLK_SCIFB1 7 +#define R8A7790_CLK_MSIOF1 8 +#define R8A7790_CLK_MSIOF3 15 +#define R8A7790_CLK_SCIFB2 16 +#define R8A7790_CLK_SYS_DMAC0 18 +#define R8A7790_CLK_SYS_DMAC1 19 + +/* MSTP3 */ +#define R8A7790_CLK_TPU0 4 +#define R8A7790_CLK_MMCIF1 5 +#define R8A7790_CLK_SDHI3 11 +#define R8A7790_CLK_SDHI2 12 +#define R8A7790_CLK_SDHI1 13 +#define R8A7790_CLK_SDHI0 14 +#define R8A7790_CLK_MMCIF0 15 +#define R8A7790_CLK_SSUSB 28 +#define R8A7790_CLK_CMT1 29 +#define R8A7790_CLK_USBDMAC0 30 +#define R8A7790_CLK_USBDMAC1 31 + +/* MSTP5 */ +#define R8A7790_CLK_THERMAL 22 +#define R8A7790_CLK_PWM 23 + +/* MSTP7 */ +#define R8A7790_CLK_EHCI 3 +#define R8A7790_CLK_HSUSB 4 +#define R8A7790_CLK_HSCIF1 16 +#define R8A7790_CLK_HSCIF0 17 +#define R8A7790_CLK_SCIF1 20 +#define R8A7790_CLK_SCIF0 21 +#define R8A7790_CLK_DU2 22 +#define R8A7790_CLK_DU1 23 +#define R8A7790_CLK_DU0 24 +#define R8A7790_CLK_LVDS1 25 +#define R8A7790_CLK_LVDS0 26 + +/* MSTP8 */ +#define R8A7790_CLK_VIN3 8 +#define R8A7790_CLK_VIN2 9 +#define R8A7790_CLK_VIN1 10 +#define R8A7790_CLK_VIN0 11 +#define R8A7790_CLK_ETHER 13 +#define R8A7790_CLK_SATA1 14 +#define R8A7790_CLK_SATA0 15 + +/* MSTP9 */ +#define R8A7790_CLK_GPIO5 7 +#define R8A7790_CLK_GPIO4 8 +#define R8A7790_CLK_GPIO3 9 +#define R8A7790_CLK_GPIO2 10 +#define R8A7790_CLK_GPIO1 11 +#define R8A7790_CLK_GPIO0 12 +#define R8A7790_CLK_RCAN1 15 +#define R8A7790_CLK_RCAN0 16 +#define R8A7790_CLK_QSPI_MOD 17 +#define R8A7790_CLK_IICDVFS 26 +#define R8A7790_CLK_I2C3 28 +#define R8A7790_CLK_I2C2 29 +#define R8A7790_CLK_I2C1 30 +#define R8A7790_CLK_I2C0 31 + +/* MSTP10 */ +#define R8A7790_CLK_SSI 5 +#define R8A7790_CLK_SSI9 6 +#define R8A7790_CLK_SSI8 7 +#define R8A7790_CLK_SSI7 8 +#define R8A7790_CLK_SSI6 9 +#define R8A7790_CLK_SSI5 10 +#define R8A7790_CLK_SSI4 11 +#define R8A7790_CLK_SSI3 12 +#define R8A7790_CLK_SSI2 13 +#define R8A7790_CLK_SSI1 14 +#define R8A7790_CLK_SSI0 15 + +#endif /* __DT_BINDINGS_CLOCK_R8A7790_H__ */ diff --git a/include/dt-bindings/clock/r8a7791-clock.h b/include/dt-bindings/clock/r8a7791-clock.h new file mode 100644 index 000000000000..1c8f00d0d88b --- /dev/null +++ b/include/dt-bindings/clock/r8a7791-clock.h @@ -0,0 +1,124 @@ +/* + * Copyright 2013 Ideas On Board SPRL + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __DT_BINDINGS_CLOCK_R8A7791_H__ +#define __DT_BINDINGS_CLOCK_R8A7791_H__ + +/* CPG */ +#define R8A7791_CLK_MAIN 0 +#define R8A7791_CLK_PLL0 1 +#define R8A7791_CLK_PLL1 2 +#define R8A7791_CLK_PLL3 3 +#define R8A7791_CLK_LB 4 +#define R8A7791_CLK_QSPI 5 +#define R8A7791_CLK_SDH 6 +#define R8A7791_CLK_SD0 7 +#define R8A7791_CLK_Z 8 + +/* MSTP0 */ +#define R8A7791_CLK_MSIOF0 0 + +/* MSTP1 */ +#define R8A7791_CLK_TMU1 11 +#define R8A7791_CLK_TMU3 21 +#define R8A7791_CLK_TMU2 22 +#define R8A7791_CLK_CMT0 24 +#define R8A7791_CLK_TMU0 25 +#define R8A7791_CLK_VSP1_DU1 27 +#define R8A7791_CLK_VSP1_DU0 28 +#define R8A7791_CLK_VSP1_SY 31 + +/* MSTP2 */ +#define R8A7791_CLK_SCIFA2 2 +#define R8A7791_CLK_SCIFA1 3 +#define R8A7791_CLK_SCIFA0 4 +#define R8A7791_CLK_MSIOF2 5 +#define R8A7791_CLK_SCIFB0 6 +#define R8A7791_CLK_SCIFB1 7 +#define R8A7791_CLK_MSIOF1 8 +#define R8A7791_CLK_SCIFB2 16 +#define R8A7791_CLK_DMAC 18 + +/* MSTP3 */ +#define R8A7791_CLK_TPU0 4 +#define R8A7791_CLK_SDHI2 11 +#define R8A7791_CLK_SDHI1 12 +#define R8A7791_CLK_SDHI0 14 +#define R8A7791_CLK_MMCIF0 15 +#define R8A7791_CLK_SSUSB 28 +#define R8A7791_CLK_CMT1 29 +#define R8A7791_CLK_USBDMAC0 30 +#define R8A7791_CLK_USBDMAC1 31 + +/* MSTP5 */ +#define R8A7791_CLK_THERMAL 22 +#define R8A7791_CLK_PWM 23 + +/* MSTP7 */ +#define R8A7791_CLK_HSUSB 4 +#define R8A7791_CLK_HSCIF2 13 +#define R8A7791_CLK_SCIF5 14 +#define R8A7791_CLK_SCIF4 15 +#define R8A7791_CLK_HSCIF1 16 +#define R8A7791_CLK_HSCIF0 17 +#define R8A7791_CLK_SCIF3 18 +#define R8A7791_CLK_SCIF2 19 +#define R8A7791_CLK_SCIF1 20 +#define R8A7791_CLK_SCIF0 21 +#define R8A7791_CLK_DU1 23 +#define R8A7791_CLK_DU0 24 +#define R8A7791_CLK_LVDS0 26 + +/* MSTP8 */ +#define R8A7791_CLK_VIN2 9 +#define R8A7791_CLK_VIN1 10 +#define R8A7791_CLK_VIN0 11 +#define R8A7791_CLK_ETHER 13 +#define R8A7791_CLK_SATA1 14 +#define R8A7791_CLK_SATA0 15 + +/* MSTP9 */ +#define R8A7791_CLK_GPIO7 4 +#define R8A7791_CLK_GPIO6 5 +#define R8A7791_CLK_GPIO5 7 +#define R8A7791_CLK_GPIO4 8 +#define R8A7791_CLK_GPIO3 9 +#define R8A7791_CLK_GPIO2 10 +#define R8A7791_CLK_GPIO1 11 +#define R8A7791_CLK_GPIO0 12 +#define R8A7791_CLK_RCAN1 15 +#define R8A7791_CLK_RCAN0 16 +#define R8A7791_CLK_QSPI_MOD 17 +#define R8A7791_CLK_I2C5 25 +#define R8A7791_CLK_IICDVFS 26 +#define R8A7791_CLK_I2C4 27 +#define R8A7791_CLK_I2C3 28 +#define R8A7791_CLK_I2C2 29 +#define R8A7791_CLK_I2C1 30 +#define R8A7791_CLK_I2C0 31 + +/* MSTP10 */ +#define R8A7791_CLK_SSI 5 +#define R8A7791_CLK_SSI9 6 +#define R8A7791_CLK_SSI8 7 +#define R8A7791_CLK_SSI7 8 +#define R8A7791_CLK_SSI6 9 +#define R8A7791_CLK_SSI5 10 +#define R8A7791_CLK_SSI4 11 +#define R8A7791_CLK_SSI3 12 +#define R8A7791_CLK_SSI2 13 +#define R8A7791_CLK_SSI1 14 +#define R8A7791_CLK_SSI0 15 + +/* MSTP11 */ +#define R8A7791_CLK_SCIFA3 6 +#define R8A7791_CLK_SCIFA4 7 +#define R8A7791_CLK_SCIFA5 8 + +#endif /* __DT_BINDINGS_CLOCK_R8A7791_H__ */ diff --git a/include/linux/clk/shmobile.h b/include/linux/clk/shmobile.h new file mode 100644 index 000000000000..f9bf080a1123 --- /dev/null +++ b/include/linux/clk/shmobile.h @@ -0,0 +1,19 @@ +/* + * Copyright 2013 Ideas On Board SPRL + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __LINUX_CLK_SHMOBILE_H_ +#define __LINUX_CLK_SHMOBILE_H_ + +#include + +void rcar_gen2_clocks_init(u32 mode); + +#endif diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h index fb90ef5eb038..282309d7c4dc 100644 --- a/include/linux/pinctrl/pinconf-generic.h +++ b/include/linux/pinctrl/pinconf-generic.h @@ -82,8 +82,10 @@ * operation, if several modes of operation are supported these can be * passed in the argument on a custom form, else just use argument 1 * to indicate low power mode, argument 0 turns low power mode off. - * @PIN_CONFIG_OUTPUT: this will configure the pin in output, use argument - * 1 to indicate high level, argument 0 to indicate low level. + * @PIN_CONFIG_OUTPUT: this will configure the pin as an output. Use argument + * 1 to indicate high level, argument 0 to indicate low level. (Please + * see Documentation/pinctrl.txt, section "GPIO mode pitfalls" for a + * discussion around this parameter.) * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if * you need to pass in custom configurations to the pin controller, use * PIN_CONFIG_END+1 as the base offset.