summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.txt50
-rw-r--r--Documentation/devicetree/bindings/clock/vf610-clock.txt15
-rw-r--r--Documentation/devicetree/bindings/fb/fsl-dcu-fb.txt67
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-vf610.txt56
-rw-r--r--Documentation/devicetree/bindings/iio/adc/vf610-adc.txt15
-rw-r--r--Documentation/devicetree/bindings/mtd/fsl-nfc.txt25
-rw-r--r--Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt23
-rw-r--r--Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt2
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--arch/arm/boot/dts/Makefile6
-rw-r--r--arch/arm/boot/dts/imx27-apf27dev.dts21
-rw-r--r--arch/arm/boot/dts/imx27.dtsi2
-rw-r--r--arch/arm/boot/dts/imx51.dtsi12
-rw-r--r--arch/arm/boot/dts/imx53.dtsi27
-rw-r--r--arch/arm/boot/dts/imx6dl.dtsi8
-rw-r--r--arch/arm/boot/dts/imx6q-tbs2910.dts432
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw52xx.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw53xx.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw54xx.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi131
-rw-r--r--arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi97
-rw-r--r--arch/arm/boot/dts/imx6qdl-rex.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi12
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi14
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts4
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi6
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb.dts81
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi8
-rw-r--r--arch/arm/boot/dts/ls1021a-qds.dts240
-rw-r--r--arch/arm/boot/dts/ls1021a-twr.dts127
-rw-r--r--arch/arm/boot/dts/ls1021a.dtsi408
-rw-r--r--arch/arm/boot/dts/vf-colibri-dual-eth.dtsi166
-rw-r--r--arch/arm/boot/dts/vf-colibri-eval-v3.dtsi270
-rw-r--r--arch/arm/boot/dts/vf-colibri.dtsi300
-rw-r--r--arch/arm/boot/dts/vf500-colibri-dual-eth.dts17
-rw-r--r--arch/arm/boot/dts/vf500-colibri-eval-v3.dts21
-rw-r--r--arch/arm/boot/dts/vf500-colibri.dtsi66
-rw-r--r--arch/arm/boot/dts/vf500.dtsi210
-rw-r--r--arch/arm/boot/dts/vf610-colibri-dual-eth.dts17
-rw-r--r--arch/arm/boot/dts/vf610-colibri-eval-v3.dts33
-rw-r--r--arch/arm/boot/dts/vf610-colibri.dtsi100
-rw-r--r--arch/arm/boot/dts/vf610-cosmic.dts14
-rw-r--r--arch/arm/boot/dts/vf610-twr.dts166
-rw-r--r--arch/arm/boot/dts/vf610.dtsi486
-rw-r--r--arch/arm/boot/dts/vfxxx.dtsi522
-rw-r--r--arch/arm/configs/colibri_vf_defconfig243
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig12
-rw-r--r--arch/arm/mach-imx/Kconfig37
-rw-r--r--arch/arm/mach-imx/Makefile10
-rw-r--r--arch/arm/mach-imx/anatop.c34
-rw-r--r--arch/arm/mach-imx/clk-cpu.c107
-rw-r--r--arch/arm/mach-imx/clk-gate2.c7
-rw-r--r--arch/arm/mach-imx/clk-imx51-imx53.c14
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c2
-rw-r--r--arch/arm/mach-imx/clk-pllv3.c17
-rw-r--r--arch/arm/mach-imx/clk-vf610.c46
-rw-r--r--arch/arm/mach-imx/clk.h18
-rw-r--r--arch/arm/mach-imx/common.h17
-rw-r--r--arch/arm/mach-imx/gpc.c75
-rw-r--r--arch/arm/mach-imx/imx25-dt.c9
-rw-r--r--arch/arm/mach-imx/imx27-dt.c3
-rw-r--r--arch/arm/mach-imx/imx31-dt.c9
-rw-r--r--arch/arm/mach-imx/imx35-dt.c10
-rw-r--r--arch/arm/mach-imx/iomux-imx31.c8
-rw-r--r--arch/arm/mach-imx/iomux-mx3.h2
-rw-r--r--arch/arm/mach-imx/mach-imx50.c9
-rw-r--r--arch/arm/mach-imx/mach-imx51.c2
-rw-r--r--arch/arm/mach-imx/mach-imx53.c4
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c5
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c6
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c55
-rw-r--r--arch/arm/mach-imx/mach-ls1021a.c22
-rw-r--r--arch/arm/mach-imx/mach-vf610.c19
-rw-r--r--arch/arm/mach-imx/mmdc.c17
-rw-r--r--arch/arm/mach-imx/mscm-vf610.c215
-rw-r--r--arch/arm/mach-imx/mxc.h2
-rw-r--r--arch/arm/mach-imx/platsmp.c33
-rw-r--r--arch/arm/mach-imx/pm-imx6.c10
-rw-r--r--arch/arm/mach-imx/pm-vf610.c385
-rw-r--r--arch/arm/mach-imx/suspend-imx6.S14
-rw-r--r--arch/arm/mach-imx/system.c15
-rw-r--r--arch/arm/mach-imx/vf610_sema4.c314
-rw-r--r--drivers/dma/fsl-edma.c2
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-vf610.c295
-rw-r--r--drivers/iio/adc/vf610_adc.c140
-rw-r--r--drivers/input/touchscreen/Kconfig19
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/colibri-vf50-ts.c429
-rw-r--r--drivers/input/touchscreen/fusion_F0710A.c548
-rw-r--r--drivers/input/touchscreen/fusion_F0710A.h87
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c17
-rw-r--r--drivers/mtd/nand/Kconfig13
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/fsl_nfc.c847
-rw-r--r--drivers/net/ethernet/freescale/fec.h2
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c9
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c72
-rw-r--r--drivers/power/reset/Kconfig9
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/imx-snvs-poweroff.c66
-rw-r--r--drivers/power/reset/syscon-reboot.c2
-rw-r--r--drivers/rtc/rtc-snvs.c39
-rw-r--r--drivers/spi/Kconfig1
-rw-r--r--drivers/spi/spi-fsl-dspi.c314
-rw-r--r--drivers/tty/serial/fsl_lpuart.c133
-rw-r--r--drivers/usb/chipidea/bits.h10
-rw-r--r--drivers/usb/chipidea/ci.h53
-rw-r--r--drivers/usb/chipidea/core.c23
-rw-r--r--drivers/usb/chipidea/udc.c20
-rw-r--r--drivers/video/fbdev/Kconfig11
-rw-r--r--drivers/video/fbdev/Makefile1
-rw-r--r--drivers/video/fbdev/core/fbmem.c12
-rw-r--r--drivers/video/fbdev/fsl-dcu-fb.c1223
-rw-r--r--include/dt-bindings/clock/imx5-clock.h5
-rw-r--r--include/dt-bindings/clock/vf610-clock.h5
-rw-r--r--include/linux/input/fusion_F0710A.h20
-rw-r--r--include/linux/mfd/syscon/imx6q-iomuxc-gpr.h39
-rw-r--r--include/linux/vf610_mscm.h11
-rw-r--r--include/linux/vf610_sema4.h33
122 files changed, 9541 insertions, 1075 deletions
diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index e935d7d4ac43..c830b5b65882 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -74,3 +74,53 @@ Required root node properties:
i.MX6q generic board
Required root node properties:
- compatible = "fsl,imx6q";
+
+Freescale Vybrid Platform Device Tree Bindings
+----------------------------------------------
+
+For the Vybrid SoC familiy all variants with DDR controller are supported,
+which is the VF5xx and VF6xx series. Out of historical reasons, in most
+places the kernel uses vf610 to refer to the whole familiy.
+
+Required root node compatible property (one of them):
+ - compatible = "fsl,vf500";
+ - compatible = "fsl,vf510";
+ - compatible = "fsl,vf600";
+ - compatible = "fsl,vf610";
+
+Freescale LS1021A Platform Device Tree Bindings
+------------------------------------------------
+
+Required root node compatible properties:
+ - compatible = "fsl,ls1021a";
+
+Freescale LS1021A SoC-specific Device Tree Bindings
+-------------------------------------------
+
+Freescale SCFG
+ SCFG is the supplemental configuration unit, that provides SoC specific
+configuration and status registers for the chip. Such as getting PEX port
+status.
+ Required properties:
+ - compatible: should be "fsl,ls1021a-scfg"
+ - reg: should contain base address and length of SCFG memory-mapped registers
+
+Example:
+ scfg: scfg@1570000 {
+ compatible = "fsl,ls1021a-scfg";
+ reg = <0x0 0x1570000 0x0 0x10000>;
+ };
+
+Freescale DCFG
+ DCFG is the device configuration unit, that provides general purpose
+configuration and status for the device. Such as setting the secondary
+core start address and release the secondary core from holdoff and startup.
+ Required properties:
+ - compatible: should be "fsl,ls1021a-dcfg"
+ - reg : should contain base address and length of DCFG memory-mapped registers
+
+Example:
+ dcfg: dcfg@1ee0000 {
+ compatible = "fsl,ls1021a-dcfg";
+ reg = <0x0 0x1ee0000 0x0 0x10000>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/vf610-clock.txt b/Documentation/devicetree/bindings/clock/vf610-clock.txt
index c80863d344ac..63f9f1ac3439 100644
--- a/Documentation/devicetree/bindings/clock/vf610-clock.txt
+++ b/Documentation/devicetree/bindings/clock/vf610-clock.txt
@@ -5,6 +5,19 @@ Required properties:
- reg: Address and length of the register set
- #clock-cells: Should be <1>
+Optional properties:
+- clocks: list of clock identifiers which are external input clocks to the
+ given clock controller. Please refer the next section to find
+ the input clocks for a given controller.
+- clock-names: list of names of clocks which are exteral input clocks to the
+ given clock controller.
+
+Input clocks for top clock controller:
+ - sxosc (external crystal oscillator 32KHz, recommended)
+ - fxosc (external crystal oscillator 24MHz, recommended)
+ - audio_ext
+ - enet_ext
+
The clock consumer should specify the desired clock by having the clock
ID in its "clocks" phandle cell. See include/dt-bindings/clock/vf610-clock.h
for the full list of VF610 clock IDs.
@@ -15,6 +28,8 @@ clks: ccm@4006b000 {
compatible = "fsl,vf610-ccm";
reg = <0x4006b000 0x1000>;
#clock-cells = <1>;
+ clocks = <&sxosc>, <&fxosc>;
+ clock-names = "sxosc", "fxosc";
};
uart1: serial@40028000 {
diff --git a/Documentation/devicetree/bindings/fb/fsl-dcu-fb.txt b/Documentation/devicetree/bindings/fb/fsl-dcu-fb.txt
new file mode 100644
index 000000000000..d0d50dd724d1
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/fsl-dcu-fb.txt
@@ -0,0 +1,67 @@
+* Freescale Display Control Unit (DCU)
+
+Required properties:
+- compatible: Should be "fsl,vf610-dcu". Supported chips include
+ Vybrid VF610.
+- reg: Address and length of the register set for DCU.
+- interrupts: Should contain DCU interrupts.
+- clocks: From common clock binding: handle to DCU clock.
+- clock-names: From common clock binding: Shall be "dcu".
+- tcon-controller: The phandle of TCON controller.
+- display: The phandle to display node.
+
+For the DCU initialization, we read data from TCON node.
+Required properties for TCON:
+- compatible: Should be "fsl,vf610-tcon". Supported chips include
+ Vybrid VF610.
+- reg: Address and length of the register set for TCON.
+- clocks: From common clock binding: handle to TCON clock.
+- clock-names: From common clock binding: Shall be "tcon".
+
+* display node
+
+Required properties:
+- bits-per-pixel: <24> for RGB888.
+
+Required sub-node:
+- display-timings: Refer to binding doc display-timing.txt for details.
+
+Examples:
+
+dcu0: dcu@40058000 {
+ compatible = "fsl,vf610-dcu";
+ reg = <0x40058000 0x1200>;
+ interrupts = <0 30 0x04>;
+ clocks = <&clks VF610_CLK_DCU0>;
+ clock-names = "dcu";
+ tcon-controller = <&tcon0>;
+ display = <&display>;
+
+ display: display@0 {
+ bits-per-pixel = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: nl4827hc19 {
+ clock-frequency = <10870000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hfront-porch = <2>;
+ vback-porch = <1>;
+ vfront-porch = <1>;
+ hsync-len = <41>;
+ vsync-len = <2>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+ };
+};
+
+tcon0: tcon@4003d000 {
+ compatible = "fsl,vf610-tcon";
+ reg = <0x4003d000 0x1000>;
+ clocks = <&clks VF610_CLK_TCON0>;
+ clock-names = "tcon";
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-vf610.txt b/Documentation/devicetree/bindings/gpio/gpio-vf610.txt
new file mode 100644
index 000000000000..da84121b9da0
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-vf610.txt
@@ -0,0 +1,56 @@
+* Freescale VF610 PORT/GPIO module
+
+The Freescale PORT/GPIO modules are two adjacent modules providing GPIO
+functionality. Each pair serves 32 GPIOs. The VF610 has 5 instances of
+each, and each PORT module has its own interrupt.
+
+Required properties for GPIO node:
+- compatible : Should be "fsl,<soc>-gpio", currently "fsl,vf610-gpio"
+- reg : The first reg tuple represents the PORT module, the second tuple
+ the GPIO module.
+- interrupts : Should be the port interrupt shared by all 32 pins.
+- gpio-controller : Marks the device node as a gpio controller.
+- #gpio-cells : Should be two. The first cell is the pin number and
+ the second cell is used to specify the gpio polarity:
+ 0 = active high
+ 1 = active low
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells : Should be 2. The first cell is the GPIO number.
+ The second cell bits[3:0] is used to specify trigger type and level flags:
+ 1 = low-to-high edge triggered.
+ 2 = high-to-low edge triggered.
+ 4 = active high level-sensitive.
+ 8 = active low level-sensitive.
+
+Note: Each GPIO port should have an alias correctly numbered in "aliases"
+node.
+
+Examples:
+
+aliases {
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+};
+
+gpio1: gpio@40049000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x40049000 0x1000 0x400ff000 0x40>;
+ interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 0 32>;
+};
+
+gpio2: gpio@4004a000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x4004a000 0x1000 0x400ff040 0x40>;
+ interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 32 32>;
+};
+
diff --git a/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt b/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
index 1a4a43d5c9ea..05e88c229216 100644
--- a/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
@@ -11,6 +11,18 @@ Required properties:
- clock-names: Must contain "adc", matching entry in the clocks property.
- vref-supply: The regulator supply ADC reference voltage.
+Recommended properties:
+- fsl,adck-max-frequency: Maximum frequencies according to datasheets operating
+ requirements. Three values are required:
+ - Frequency in default mode (ADLPC=0, ADHSC=0)
+ - Frequency in high speed mode (ADLPC=0, ADHSC=1)
+ - Frequency in low power mode (ADLPC=1, ADHSC=0)
+
+Optional properties:
+- fsl,use-lpm: Use low power conversion mode, which usually lowers maximum
+ sample rate slightly.
+- fsl,use-hsc: Use high speed configuration for maximum sample rates.
+
Example:
adc0: adc@4003b000 {
compatible = "fsl,vf610-adc";
@@ -18,5 +30,8 @@ adc0: adc@4003b000 {
interrupts = <0 53 0x04>;
clocks = <&clks VF610_CLK_ADC0>;
clock-names = "adc";
+ fsl,adck-max-frequency = <30000000>, <40000000>,
+ <20000000>;
+ fsl,use-lpm;
vref-supply = <&reg_vcc_3v3_mcu>;
};
diff --git a/Documentation/devicetree/bindings/mtd/fsl-nfc.txt b/Documentation/devicetree/bindings/mtd/fsl-nfc.txt
new file mode 100644
index 000000000000..1d339b194108
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/fsl-nfc.txt
@@ -0,0 +1,25 @@
+* Freescale's NFC (nand flash controller)
+
+Required properties:
+- compatible : "fsl,XXX-nfc"
+- reg : Address range of the mtd chip
+- interrupts: Should contain the STMMAC interrupts
+- nand-bus-width: see nand.txt
+- nand-ecc-mode: see nand.txt
+- nand-on-flash-bbt: see nand.txt
+- clock-frequency : Optional clock rate to NFC in Hz
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+ representing partitions.
+
+Example:
+
+ nfc: nand@400e0000 {
+ compatible = "fsl,vf610-nfc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x400e0000 0x4000>;
+ interrupts = <0 83 0x04>;
+ clocks = <&clks VF610_CLK_NFC>;
+ clock-names = "nfc";
+ clock-frequency = <33000000>;
+ };
diff --git a/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
new file mode 100644
index 000000000000..dc7c9bad63ea
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
@@ -0,0 +1,23 @@
+i.mx6 Poweroff Driver
+
+SNVS_LPCR in SNVS module can power off the whole system by pull
+PMIC_ON_REQ low if PMIC_ON_REQ is connected with external PMIC.
+If you don't want to use PMIC_ON_REQ as power on/off control,
+please set status='disabled' to disable this driver.
+
+Required Properties:
+-compatible: "fsl,sec-v4.0-poweroff"
+-reg: Specifies the physical address of the SNVS_LPCR register
+
+Example:
+ snvs@020cc000 {
+ compatible = "fsl,sec-v4.0-mon", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x020cc000 0x4000>;
+ .....
+ snvs_poweroff: snvs-poweroff@38 {
+ compatible = "fsl,sec-v4.0-poweroff";
+ reg = <0x38 0x4>;
+ };
+ }
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index cbbe16ed3874..b50439f6cab6 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -15,6 +15,8 @@ Optional property:
- big-endian: If present the dspi device's registers are implemented
in big endian mode, otherwise in native mode(same with CPU), for more
detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
+- tcfq-mode: If present, the data transfer will be done at TCFQ interrupt.
+ By default, driver chooses EOQ interrupt if 'tcfq-mode' property was not set.
Example:
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a344ec2713a5..1489e5702a52 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -149,6 +149,7 @@ st STMicroelectronics
ste ST-Ericsson
stericsson ST-Ericsson
synology Synology, Inc.
+tbs TBS Technologies
thine THine Electronics, Inc.
ti Texas Instruments
tlm Trusted Logic Mobility
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 38c89cafa1ab..107bc76a75d4 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -240,6 +240,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx6q-sabrelite.dtb \
imx6q-sabresd.dtb \
imx6q-sbc6x.dtb \
+ imx6q-tbs2910.dtb \
imx6q-udoo.dtb \
imx6q-wandboard.dtb \
imx6q-wandboard-revb1.dtb \
@@ -250,7 +251,12 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx6q-tx6q-1110.dtb \
imx6sl-evk.dtb \
imx6sx-sdb.dtb \
+ ls1021a-qds.dtb \
+ ls1021a-twr.dtb \
+ vf500-colibri-eval-v3.dtb \
vf610-colibri-eval-v3.dtb \
+ vf500-colibri-dual-eth.dtb \
+ vf610-colibri-dual-eth.dtb \
vf610-cosmic.dtb \
vf610-twr.dtb
dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts
index da306c5dd678..bba3f41b89ef 100644
--- a/arch/arm/boot/dts/imx27-apf27dev.dts
+++ b/arch/arm/boot/dts/imx27-apf27dev.dts
@@ -59,6 +59,21 @@
linux,default-trigger = "heartbeat";
};
};
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_max5821: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "max5821-reg";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+ };
};
&cspi1 {
@@ -107,6 +122,12 @@
compatible = "dallas,ds1374";
reg = <0x68>;
};
+
+ max5821@38 {
+ compatible = "maxim,max5821";
+ reg = <0x38>;
+ vref-supply = <&reg_max5821>;
+ };
};
&i2c2 {
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 107d713e1cbe..4b063b68db44 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -464,7 +464,7 @@
};
coda: coda@10023000 {
- compatible = "fsl,imx27-vpu";
+ compatible = "fsl,imx27-vpu", "cnm,codadx6";
reg = <0x10023000 0x0200>;
interrupts = <53>;
clocks = <&clks IMX27_CLK_VPU_BAUD_GATE>,
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 92660e1fe1fc..c0116cffc513 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -214,7 +214,9 @@
compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
reg = <0x70014000 0x4000>;
interrupts = <30>;
- clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+ clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>,
+ <&clks IMX5_CLK_SSI2_ROOT_GATE>;
+ clock-names = "ipg", "baud";
dmas = <&sdma 24 1 0>,
<&sdma 25 1 0>;
dma-names = "rx", "tx";
@@ -504,7 +506,9 @@
compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
reg = <0x83fcc000 0x4000>;
interrupts = <29>;
- clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+ clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>,
+ <&clks IMX5_CLK_SSI1_ROOT_GATE>;
+ clock-names = "ipg", "baud";
dmas = <&sdma 28 0 0>,
<&sdma 29 0 0>;
dma-names = "rx", "tx";
@@ -560,7 +564,9 @@
compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
reg = <0x83fe8000 0x4000>;
interrupts = <96>;
- clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
+ clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>,
+ <&clks IMX5_CLK_SSI3_ROOT_GATE>;
+ clock-names = "ipg", "baud";
dmas = <&sdma 46 0 0>,
<&sdma 47 0 0>;
dma-names = "rx", "tx";
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index f91725b2e8ab..b96213ba0671 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -46,10 +46,21 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a8";
reg = <0x0>;
+ clocks = <&clks IMX5_CLK_ARM>;
+ clock-latency = <61036>;
+ voltage-tolerance = <5>;
+ operating-points = <
+ /* kHz */
+ 166666 850000
+ 400000 900000
+ 800000 1050000
+ 1000000 1200000
+ 1200000 1300000
+ >;
};
};
@@ -227,7 +238,9 @@
"fsl,imx21-ssi";
reg = <0x50014000 0x4000>;
interrupts = <30>;
- clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+ clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>,
+ <&clks IMX5_CLK_SSI2_ROOT_GATE>;
+ clock-names = "ipg", "baud";
dmas = <&sdma 24 1 0>,
<&sdma 25 1 0>;
dma-names = "rx", "tx";
@@ -675,7 +688,9 @@
"fsl,imx21-ssi";
reg = <0x63fcc000 0x4000>;
interrupts = <29>;
- clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+ clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>,
+ <&clks IMX5_CLK_SSI1_ROOT_GATE>;
+ clock-names = "ipg", "baud";
dmas = <&sdma 28 0 0>,
<&sdma 29 0 0>;
dma-names = "rx", "tx";
@@ -703,7 +718,9 @@
"fsl,imx21-ssi";
reg = <0x63fe8000 0x4000>;
interrupts = <96>;
- clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
+ clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>,
+ <&clks IMX5_CLK_SSI3_ROOT_GATE>;
+ clock-names = "ipg", "baud";
dmas = <&sdma 46 0 0>,
<&sdma 47 0 0>;
dma-names = "rx", "tx";
@@ -739,7 +756,7 @@
};
vpu: vpu@63ff4000 {
- compatible = "fsl,imx53-vpu";
+ compatible = "fsl,imx53-vpu", "cnm,coda7541";
reg = <0x63ff4000 0x1000>;
interrupts = <9>;
clocks = <&clks IMX5_CLK_VPU_REFERENCE_GATE>,
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index b453e0e28aee..1ac2fe732867 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -13,6 +13,10 @@
#include "imx6qdl.dtsi"
/ {
+ aliases {
+ i2c3 = &i2c4;
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -114,3 +118,7 @@
"di0_sel", "di1_sel",
"di0", "di1";
};
+
+&vpu {
+ compatible = "fsl,imx6dl-vpu", "cnm,coda960";
+};
diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts
new file mode 100644
index 000000000000..a43abfa21e33
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-tbs2910.dts
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2014 Soeren Moch <smoch@web.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this file; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "TBS2910 Matrix ARM mini PC";
+ compatible = "tbs,imx6q-tbs2910", "fsl,imx6q";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x10000000 0x80000000>;
+ };
+
+ fan {
+ compatible = "gpio-fan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_fan>;
+ gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>;
+ gpio-fan,speed-map = <0 0
+ 3000 1>;
+ };
+
+ ir_recv {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio3 18 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ir>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+
+ blue {
+ label = "blue_status_led";
+ gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ default-state = "keep";
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_2p5v: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ };
+
+ reg_3p3v: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ reg_5p0v: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "5P0V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+ };
+
+ sound-sgtl5000 {
+ audio-codec = <&sgtl5000>;
+ audio-routing =
+ "MIC_IN", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "Headphone Jack", "HP_OUT";
+ compatible = "fsl,imx-audio-sgtl5000";
+ model = "On-board Codec";
+ mux-ext-port = <3>;
+ mux-int-port = <1>;
+ ssi-controller = <&ssi1>;
+ };
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "On-board SPDIF";
+ spdif-controller = <&spdif>;
+ spdif-out;
+ };
+};
+
+&audmux {
+ status = "okay";
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&hdmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi>;
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ sgtl5000: sgtl5000@0a {
+ clocks = <&clks 201>;
+ compatible = "fsl,sgtl5000";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sgtl5000>;
+ reg = <0x0a>;
+ VDDA-supply = <&reg_2p5v>;
+ VDDIO-supply = <&reg_3p3v>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ rtc: ds1307@68 {
+ compatible = "dallas,ds1307";
+ reg = <0x68>;
+ };
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif>;
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_5p0v>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_5p0v>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&reg_3p3v>;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;
+ wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&reg_3p3v>;
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ bus-width = <8>;
+ non-removable;
+ no-1-8-v;
+ status = "okay";
+};
+
+&iomuxc {
+ imx6q-tbs2910 {
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x1b059
+ >;
+ };
+
+ pinctrl_hdmi: hdmigrp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_ir: irgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D18__GPIO3_IO18 0x17059
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x17059
+ >;
+ };
+
+ pinctrl_sgtl5000: sgtl5000grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ >;
+ };
+
+ pinctrl_spdif: spdifgrp {
+ fsl,pins = <MX6QDL_PAD_GPIO_19__SPDIF_OUT 0x13091
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x17059
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x17059
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
+ };
+ };
+
+ gpio_fan {
+ pinctrl_gpio_fan: gpiofangrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x130b1
+ >;
+ };
+ };
+
+ gpio_leds {
+ pinctrl_gpio_leds: gpioledsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x130b1
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index e9f3646d1760..85f72e6b5bad 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -308,3 +308,7 @@
};
};
};
+
+&vpu {
+ compatible = "fsl,imx6q-vpu", "cnm,coda960";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index d3c0bf5c84e3..b5756c21ea1d 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -282,7 +282,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
index cade1bdc97e9..86f03c1b147c 100644
--- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -287,7 +287,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
index cf13239a1619..4a8d97f47759 100644
--- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -376,12 +376,10 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
&ssi2 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
index 584721264121..585b4f6986c1 100644
--- a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
@@ -9,17 +9,103 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
/ {
chosen {
linux,stdout-path = &uart4;
};
+
+ regulators {
+ sound_1v8: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "i2s-audio-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ sound_3v3: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "i2s-audio-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+
+ tlv320_mclk: oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <19200000>;
+ clock-output-names = "tlv320-mclk";
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "OnboardTLV320AIC3007";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&dailink_master>;
+ simple-audio-card,frame-master = <&dailink_master>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Line", "Line In",
+ "Line", "Line Out",
+ "Speaker", "Speaker",
+ "Headphone", "Headphone Jack";
+ simple-audio-card,routing =
+ "Line Out", "LLOUT",
+ "Line Out", "RLOUT",
+ "Speaker", "SPOP",
+ "Speaker", "SPOM",
+ "Headphone Jack", "HPLOUT",
+ "Headphone Jack", "HPROUT",
+ "MIC3L", "Mic Jack",
+ "MIC3R", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "LINE1L", "Line In",
+ "LINE1R", "Line In";
+
+ simple-audio-card,cpu {
+ sound-dai = <&ssi2>;
+ };
+
+ dailink_master: simple-audio-card,codec {
+ sound-dai = <&codec>;
+ clocks = <&tlv320_mclk>;
+ };
+ };
+
};
-&fec {
+&audmux {
status = "okay";
+
+ ssi2 {
+ fsl,audmux-port = <1>;
+ fsl,port-config = <
+ (IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(4) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(4))
+ IMX_AUDMUX_V2_PDCR_RXDSEL(4)
+ >;
+ };
+
+ pins5 {
+ fsl,audmux-port = <4>;
+ fsl,port-config = <
+ 0x00000000
+ IMX_AUDMUX_V2_PDCR_RXDSEL(1)
+ >;
+ };
};
-&gpmi {
+&can1 {
+ status = "okay";
+};
+
+&fec {
status = "okay";
};
@@ -28,14 +114,18 @@
};
&i2c2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c2>;
- clock-frequency = <100000>;
status = "okay";
- tlv320@18 {
- compatible = "ti,tlv320aic3x";
+ codec: tlv320@18 {
+ compatible = "ti,tlv320aic3007";
+ #sound-dai-cells = <0>;
reg = <0x18>;
+ ai3x-micbias-vg = <2>;
+
+ AVDD-supply = <&sound_3v3>;
+ IOVDD-supply = <&sound_3v3>;
+ DRVDD-supply = <&sound_3v3>;
+ DVDD-supply = <&sound_1v8>;
};
stmpe@41 {
@@ -55,9 +145,14 @@
};
&i2c3 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c3>;
- clock-frequency = <100000>;
+ status = "okay";
+};
+
+&pcie {
+ status = "okay";
+};
+
+&ssi2 {
status = "okay";
};
@@ -84,19 +179,3 @@
&usdhc3 {
status = "okay";
};
-
-&iomuxc {
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
- >;
- };
-
- pinctrl_i2c3: i2c3grp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
- >;
- };
-};
diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
index 0e50bb0a6b94..19cc269a08d4 100644
--- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
@@ -58,6 +58,18 @@
};
};
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "disabled";
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "disabled";
+};
+
&ecspi3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi3>;
@@ -72,6 +84,22 @@
};
};
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ phy-supply = <&vdd_eth_io_reg>;
+ status = "disabled";
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ nand-on-flash-bbt;
+ status = "okay";
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
@@ -85,8 +113,8 @@
pmic@58 {
compatible = "dlg,da9063";
reg = <0x58>;
- interrupt-parent = <&gpio4>;
- interrupts = <17 0x8>; /* active-low GPIO4_17 */
+ interrupt-parent = <&gpio2>;
+ interrupts = <9 0x8>; /* active-low GPIO2_9 */
regulators {
vddcore_reg: bcore1 {
@@ -162,6 +190,18 @@
};
};
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ clock-frequency = <100000>;
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ clock-frequency = <100000>;
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
@@ -171,7 +211,7 @@
fsl,pins = <
MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
- MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */
+ MX6QDL_PAD_SD4_DAT1__GPIO2_IO09 0x80000000 /* PMIC interrupt */
MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* Green LED */
MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000 /* Red LED */
>;
@@ -206,6 +246,13 @@
>;
};
+ pinctrl_flexcan1: flexcan1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ >;
+ };
+
pinctrl_gpmi_nand: gpminandgrp {
fsl,pins = <
MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
@@ -235,6 +282,24 @@
>;
};
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_pcie: pciegrp {
+ fsl,pins = <MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000>;
+ };
+
pinctrl_uart3: uart3grp {
fsl,pins = <
MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
@@ -293,22 +358,22 @@
MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
>;
};
- };
-};
-&fec {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
- phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
- phy-supply = <&vdd_eth_io_reg>;
- status = "disabled";
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x130b0
+ MX6QDL_PAD_DISP0_DAT17__AUD5_TXD 0x110b0
+ MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x130b0
+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+ >;
+ };
+ };
};
-&gpmi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpmi_nand>;
- nand-on-flash-bbt;
+&pcie {
+ pinctrl-name = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio4 17 0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/imx6qdl-rex.dtsi
index df7bcf86c156..488a640796ac 100644
--- a/arch/arm/boot/dts/imx6qdl-rex.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-rex.dtsi
@@ -308,7 +308,6 @@
};
&ssi1 {
- fsl,mode = "i2s-slave";
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index baf2f00d519a..f1cd2147421d 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -107,10 +107,8 @@
"Headphone Jack", "HPOUTR",
"Ext Spk", "SPKOUTL",
"Ext Spk", "SPKOUTR",
- "MICBIAS", "AMIC",
- "IN3R", "MICBIAS",
- "DMIC", "MICBIAS",
- "DMICDAT", "DMIC";
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC";
mux-int-port = <2>;
mux-ext-port = <3>;
};
@@ -179,7 +177,7 @@
codec: wm8962@1a {
compatible = "wlf,wm8962";
reg = <0x1a>;
- clocks = <&clks 201>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
DCVDD-supply = <&reg_audio>;
DBVDD-supply = <&reg_audio>;
AVDD-supply = <&reg_audio>;
@@ -531,6 +529,10 @@
status = "okay";
};
+&snvs_poweroff {
+ status = "okay";
+};
+
&ssi2 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 9596ed5867e6..4fc03b7f1cee 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -333,9 +333,17 @@
};
vpu: vpu@02040000 {
+ compatible = "cnm,coda960";
reg = <0x02040000 0x3c000>;
interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>,
<0 12 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "bit", "jpeg";
+ clocks = <&clks IMX6QDL_CLK_VPU_AXI>,
+ <&clks IMX6QDL_CLK_MMDC_CH0_AXI>,
+ <&clks IMX6QDL_CLK_OCRAM>;
+ clock-names = "per", "ahb", "ocram";
+ resets = <&src 1>;
+ iram = <&ocram>;
};
aipstz@0207c000 { /* AIPSTZ1 */
@@ -657,6 +665,12 @@
interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
<0 20 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ snvs_poweroff: snvs-poweroff@38 {
+ compatible = "fsl,sec-v4.0-poweroff";
+ reg = <0x38 0x4>;
+ status = "disabled";
+ };
};
epit1: epit@020d0000 { /* EPIT1 */
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 898d14fd765f..fda4932faefd 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -580,6 +580,10 @@
status = "okay";
};
+&snvs_poweroff {
+ status = "okay";
+};
+
&ssi2 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index dfd83e6d8087..36ab8e054cee 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -574,6 +574,12 @@
interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
<0 20 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ snvs_poweroff: snvs-poweroff@38 {
+ compatible = "fsl,sec-v4.0-poweroff";
+ reg = <0x38 0x4>;
+ status = "disabled";
+ };
};
epit1: epit@020d0000 {
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index 82d6b34527b7..8c1febd7e3f2 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -105,6 +105,30 @@
gpio = <&gpio3 27 0>;
enable-active-high;
};
+
+ reg_peri_3v3: regulator@5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_peri_3v3>;
+ regulator-name = "peri_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ reg_enet_3v3: regulator@6 {
+ compatible = "regulator-fixed";
+ reg = <6>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_3v3>;
+ regulator-name = "enet_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
+ };
};
sound {
@@ -133,7 +157,30 @@
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1>;
+ phy-supply = <&reg_enet_3v3>;
phy-mode = "rgmii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ ethphy2: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy2>;
status = "okay";
};
@@ -304,6 +351,10 @@
status = "okay";
};
+&snvs_poweroff {
+ status = "okay";
+};
+
&ssi2 {
status = "okay";
};
@@ -394,6 +445,30 @@
MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x91
+ >;
+ };
+
+ pinctrl_enet_3v3: enet3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0x80000000
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
>;
};
@@ -452,6 +527,12 @@
>;
};
+ pinctrl_peri_3v3: peri3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x80000000
+ >;
+ };
+
pinctrl_pwm3: pwm3grp-1 {
fsl,pins = <
MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index f3e88c03b1e4..7a24fee1e7ae 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -671,6 +671,12 @@
reg = <0x34 0x58>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ snvs_poweroff: snvs-poweroff@38 {
+ compatible = "fsl,sec-v4.0-poweroff";
+ reg = <0x38 0x4>;
+ status = "disabled";
+ };
};
epit1: epit@020d0000 {
@@ -877,7 +883,7 @@
};
fec2: ethernet@021b4000 {
- compatible = "fsl,imx6sx-fec";
+ compatible = "fsl,imx6sx-fec", "fsl,imx6q-fec";
reg = <0x021b4000 0x4000>;
interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/ls1021a-qds.dts b/arch/arm/boot/dts/ls1021a-qds.dts
new file mode 100644
index 000000000000..9c5e16ba8c95
--- /dev/null
+++ b/arch/arm/boot/dts/ls1021a-qds.dts
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this file; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "ls1021a.dtsi"
+
+/ {
+ model = "LS1021A QDS Board";
+
+ aliases {
+ enet0_rgmii_phy = &rgmii_phy1;
+ enet1_rgmii_phy = &rgmii_phy2;
+ enet2_rgmii_phy = &rgmii_phy3;
+ enet0_sgmii_phy = &sgmii_phy1c;
+ enet1_sgmii_phy = &sgmii_phy1d;
+ };
+};
+
+&dspi0 {
+ bus-num = <0>;
+ status = "okay";
+
+ dspiflash: at45db021d@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at45db021d", "atmel,at45", "atmel,dataflash";
+ spi-max-frequency = <16000000>;
+ spi-cpol;
+ spi-cpha;
+ reg = <0>;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+
+ pca9547: mux@77 {
+ reg = <0x77>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+
+ ds3232: rtc@68 {
+ compatible = "dallas,ds3232";
+ reg = <0x68>;
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x2>;
+
+ ina220@40 {
+ compatible = "ti,ina220";
+ reg = <0x40>;
+ shunt-resistor = <1000>;
+ };
+
+ ina220@41 {
+ compatible = "ti,ina220";
+ reg = <0x41>;
+ shunt-resistor = <1000>;
+ };
+ };
+
+ i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x3>;
+
+ eeprom@56 {
+ compatible = "atmel,24c512";
+ reg = <0x56>;
+ };
+
+ eeprom@57 {
+ compatible = "atmel,24c512";
+ reg = <0x57>;
+ };
+
+ adt7461a@4c {
+ compatible = "adi,adt7461a";
+ reg = <0x4c>;
+ };
+ };
+ };
+};
+
+&ifc {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ /* NOR, NAND Flashes and FPGA on board */
+ ranges = <0x0 0x0 0x0 0x60000000 0x08000000
+ 0x2 0x0 0x0 0x7e800000 0x00010000
+ 0x3 0x0 0x0 0x7fb00000 0x00000100>;
+ status = "okay";
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x8000000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ fpga: board-control@3,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ reg = <0x3 0x0 0x0000100>;
+ bank-width = <1>;
+ device-width = <1>;
+ ranges = <0 3 0 0x100>;
+
+ mdio-mux-emi1 {
+ compatible = "mdio-mux-mmioreg";
+ mdio-parent-bus = <&mdio0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x54 1>; /* BRDCFG4 */
+ mux-mask = <0xe0>; /* EMI1[2:0] */
+
+ /* Onboard PHYs */
+ ls1021amdio0: mdio@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rgmii_phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+ };
+
+ ls1021amdio1: mdio@20 {
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rgmii_phy2: ethernet-phy@2 {
+ reg = <0x2>;
+ };
+ };
+
+ ls1021amdio2: mdio@40 {
+ reg = <0x40>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rgmii_phy3: ethernet-phy@3 {
+ reg = <0x3>;
+ };
+ };
+
+ ls1021amdio3: mdio@60 {
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ sgmii_phy1c: ethernet-phy@1c {
+ reg = <0x1c>;
+ };
+ };
+
+ ls1021amdio4: mdio@80 {
+ reg = <0x80>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ sgmii_phy1d: ethernet-phy@1d {
+ reg = <0x1d>;
+ };
+ };
+ };
+ };
+};
+
+&lpuart0 {
+ status = "okay";
+};
+
+&mdio0 {
+ tbi0: tbi-phy@8 {
+ reg = <0x8>;
+ device_type = "tbi-phy";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
new file mode 100644
index 000000000000..a2c591e2d918
--- /dev/null
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this file; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "ls1021a.dtsi"
+
+/ {
+ model = "LS1021A TWR Board";
+
+ aliases {
+ enet2_rgmii_phy = &rgmii_phy1;
+ enet0_sgmii_phy = &sgmii_phy2;
+ enet1_sgmii_phy = &sgmii_phy0;
+ };
+};
+
+&dspi1 {
+ bus-num = <0>;
+ status = "okay";
+
+ dspiflash: s25fl064k@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25fl064k";
+ spi-max-frequency = <16000000>;
+ spi-cpol;
+ spi-cpha;
+ reg = <0>;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&ifc {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ /* NOR Flash on board */
+ ranges = <0x0 0x0 0x0 0x60000000 0x08000000>;
+ status = "okay";
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x8000000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+};
+
+&lpuart0 {
+ status = "okay";
+};
+
+&mdio0 {
+ sgmii_phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+ rgmii_phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+ sgmii_phy2: ethernet-phy@2 {
+ reg = <0x2>;
+ };
+ tbi1: tbi-phy@1f {
+ reg = <0x1f>;
+ device_type = "tbi-phy";
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
new file mode 100644
index 000000000000..657da14cb4b5
--- /dev/null
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this file; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "skeleton64.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "fsl,ls1021a";
+ interrupt-parent = <&gic>;
+
+ aliases {
+ serial0 = &lpuart0;
+ serial1 = &lpuart1;
+ serial2 = &lpuart2;
+ serial3 = &lpuart3;
+ serial4 = &lpuart4;
+ serial5 = &lpuart5;
+ sysclk = &sysclk;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@f00 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0xf00>;
+ clocks = <&cluster1_clk>;
+ };
+
+ cpu@f01 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0xf01>;
+ clocks = <&cluster1_clk>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ device_type = "soc";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ gic: interrupt-controller@1400000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x0 0x1401000 0x0 0x1000>,
+ <0x0 0x1402000 0x0 0x1000>,
+ <0x0 0x1404000 0x0 0x2000>,
+ <0x0 0x1406000 0x0 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+
+ };
+
+ ifc: ifc@1530000 {
+ compatible = "fsl,ifc", "simple-bus";
+ reg = <0x0 0x1530000 0x0 0x10000>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ dcfg: dcfg@1ee0000 {
+ compatible = "fsl,ls1021a-dcfg", "syscon";
+ reg = <0x0 0x1ee0000 0x0 0x10000>;
+ big-endian;
+ };
+
+ esdhc: esdhc@1560000 {
+ compatible = "fsl,esdhc";
+ reg = <0x0 0x1560000 0x0 0x10000>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0>;
+ voltage-ranges = <1800 1800 3300 3300>;
+ sdhci,auto-cmd12;
+ big-endian;
+ bus-width = <4>;
+ status = "disabled";
+ };
+
+ scfg: scfg@1570000 {
+ compatible = "fsl,ls1021a-scfg", "syscon";
+ reg = <0x0 0x1570000 0x0 0x10000>;
+ };
+
+ clockgen: clocking@1ee1000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x1ee1000 0x10000>;
+
+ sysclk: sysclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "sysclk";
+ };
+
+ cga_pll1: pll@800 {
+ compatible = "fsl,qoriq-core-pll-2.0";
+ #clock-cells = <1>;
+ reg = <0x800 0x10>;
+ clocks = <&sysclk>;
+ clock-output-names = "cga-pll1", "cga-pll1-div2",
+ "cga-pll1-div4";
+ };
+
+ platform_clk: pll@c00 {
+ compatible = "fsl,qoriq-core-pll-2.0";
+ #clock-cells = <1>;
+ reg = <0xc00 0x10>;
+ clocks = <&sysclk>;
+ clock-output-names = "platform-clk", "platform-clk-div2";
+ };
+
+ cluster1_clk: clk0c0@0 {
+ compatible = "fsl,qoriq-core-mux-2.0";
+ #clock-cells = <0>;
+ reg = <0x0 0x10>;
+ clock-names = "pll1cga", "pll1cga-div2", "pll1cga-div4";
+ clocks = <&cga_pll1 0>, <&cga_pll1 1>, <&cga_pll1 2>;
+ clock-output-names = "cluster1-clk";
+ };
+ };
+
+ dspi0: dspi@2100000 {
+ compatible = "fsl,vf610-dspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x2100000 0x0 0x10000>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dspi";
+ clocks = <&platform_clk 1>;
+ spi-num-chipselects = <5>;
+ big-endian;
+ status = "disabled";
+ };
+
+ dspi1: dspi@2110000 {
+ compatible = "fsl,vf610-dspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x2110000 0x0 0x10000>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "dspi";
+ clocks = <&platform_clk 1>;
+ spi-num-chipselects = <5>;
+ big-endian;
+ status = "disabled";
+ };
+
+ i2c0: i2c@2180000 {
+ compatible = "fsl,vf610-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x2180000 0x0 0x10000>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "i2c";
+ clocks = <&platform_clk 1>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@2190000 {
+ compatible = "fsl,vf610-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x2190000 0x0 0x10000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "i2c";
+ clocks = <&platform_clk 1>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@21a0000 {
+ compatible = "fsl,vf610-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x21a0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "i2c";
+ clocks = <&platform_clk 1>;
+ status = "disabled";
+ };
+
+ uart0: serial@21c0500 {
+ compatible = "fsl,16550-FIFO64", "ns16550a";
+ reg = <0x0 0x21c0500 0x0 0x100>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0>;
+ fifo-size = <15>;
+ status = "disabled";
+ };
+
+ uart1: serial@21c0600 {
+ compatible = "fsl,16550-FIFO64", "ns16550a";
+ reg = <0x0 0x21c0600 0x0 0x100>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0>;
+ fifo-size = <15>;
+ status = "disabled";
+ };
+
+ uart2: serial@21d0500 {
+ compatible = "fsl,16550-FIFO64", "ns16550a";
+ reg = <0x0 0x21d0500 0x0 0x100>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0>;
+ fifo-size = <15>;
+ status = "disabled";
+ };
+
+ uart3: serial@21d0600 {
+ compatible = "fsl,16550-FIFO64", "ns16550a";
+ reg = <0x0 0x21d0600 0x0 0x100>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <0>;
+ fifo-size = <15>;
+ status = "disabled";
+ };
+
+ lpuart0: serial@2950000 {
+ compatible = "fsl,ls1021a-lpuart";
+ reg = <0x0 0x2950000 0x0 0x1000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&sysclk>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart1: serial@2960000 {
+ compatible = "fsl,ls1021a-lpuart";
+ reg = <0x0 0x2960000 0x0 0x1000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart2: serial@2970000 {
+ compatible = "fsl,ls1021a-lpuart";
+ reg = <0x0 0x2970000 0x0 0x1000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart3: serial@2980000 {
+ compatible = "fsl,ls1021a-lpuart";
+ reg = <0x0 0x2980000 0x0 0x1000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart4: serial@2990000 {
+ compatible = "fsl,ls1021a-lpuart";
+ reg = <0x0 0x2990000 0x0 0x1000>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ lpuart5: serial@29a0000 {
+ compatible = "fsl,ls1021a-lpuart";
+ reg = <0x0 0x29a0000 0x0 0x1000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ wdog0: watchdog@2ad0000 {
+ compatible = "fsl,imx21-wdt";
+ reg = <0x0 0x2ad0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "wdog-en";
+ big-endian;
+ };
+
+ sai1: sai@2b50000 {
+ compatible = "fsl,vf610-sai";
+ reg = <0x0 0x2b50000 0x0 0x10000>;
+ interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "sai";
+ dma-names = "tx", "rx";
+ dmas = <&edma0 1 47>,
+ <&edma0 1 46>;
+ big-endian;
+ status = "disabled";
+ };
+
+ sai2: sai@2b60000 {
+ compatible = "fsl,vf610-sai";
+ reg = <0x0 0x2b60000 0x0 0x10000>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&platform_clk 1>;
+ clock-names = "sai";
+ dma-names = "tx", "rx";
+ dmas = <&edma0 1 45>,
+ <&edma0 1 44>;
+ big-endian;
+ status = "disabled";
+ };
+
+ edma0: edma@2c00000 {
+ #dma-cells = <2>;
+ compatible = "fsl,vf610-edma";
+ reg = <0x0 0x2c00000 0x0 0x10000>,
+ <0x0 0x2c10000 0x0 0x10000>,
+ <0x0 0x2c20000 0x0 0x10000>;
+ interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "edma-tx", "edma-err";
+ dma-channels = <32>;
+ big-endian;
+ clock-names = "dmamux0", "dmamux1";
+ clocks = <&platform_clk 1>,
+ <&platform_clk 1>;
+ };
+
+ mdio0: mdio@2d24000 {
+ compatible = "gianfar";
+ device_type = "mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0 0x2d24000 0x0 0x4000>;
+ };
+
+ usb@8600000 {
+ compatible = "fsl-usb2-dr-v2.5", "fsl-usb2-dr";
+ reg = <0x0 0x8600000 0x0 0x1000>;
+ interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+ dr_mode = "host";
+ phy_type = "ulpi";
+ };
+
+ usb3@3100000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0x3100000 0x0 0x10000>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ dr_mode = "host";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/vf-colibri-dual-eth.dtsi b/arch/arm/boot/dts/vf-colibri-dual-eth.dtsi
new file mode 100644
index 000000000000..f73814c00519
--- /dev/null
+++ b/arch/arm/boot/dts/vf-colibri-dual-eth.dtsi
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * 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.
+ */
+
+/ {
+ chosen {
+ bootargs = "console=ttyLP0,115200";
+ };
+
+ aliases {
+ ethernet0 = &fec0;
+ ethernet1 = &fec1;
+ };
+};
+
+&edma0 {
+ status = "okay";
+};
+
+&fec0 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec0>;
+ status = "okay";
+};
+
+&fec1 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ status = "okay";
+};
+
+&nfc {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+ clock-frequency = <33000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nfc_1>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart0>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&iomuxc {
+ vf610-colibri {
+ pinctrl_fec0: fec0grp {
+ fsl,pins = <
+ VF610_PAD_PTA9__RMII_CLKOUT 0x30d2
+ VF610_PAD_PTC0__ENET_RMII0_MDC 0x30d2
+ VF610_PAD_PTC1__ENET_RMII0_MDIO 0x30d3
+ VF610_PAD_PTC2__ENET_RMII0_CRS 0x30d1
+ VF610_PAD_PTC3__ENET_RMII0_RXD1 0x30d1
+ VF610_PAD_PTC4__ENET_RMII0_RXD0 0x30d1
+ VF610_PAD_PTC5__ENET_RMII0_RXER 0x30d1
+ VF610_PAD_PTC6__ENET_RMII0_TXD1 0x30d2
+ VF610_PAD_PTC7__ENET_RMII0_TXD0 0x30d2
+ VF610_PAD_PTC8__ENET_RMII0_TXEN 0x30d2
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ VF610_PAD_PTC9__ENET_RMII1_MDC 0x30d2
+ VF610_PAD_PTC10__ENET_RMII1_MDIO 0x30d3
+ VF610_PAD_PTC11__ENET_RMII1_CRS 0x30d1
+ VF610_PAD_PTC12__ENET_RMII_RXD1 0x30d1
+ VF610_PAD_PTC13__ENET_RMII1_RXD0 0x30d1
+ VF610_PAD_PTC14__ENET_RMII1_RXER 0x30d1
+ VF610_PAD_PTC15__ENET_RMII1_TXD1 0x30d2
+ VF610_PAD_PTC16__ENET_RMII1_TXD0 0x30d2
+ VF610_PAD_PTC17__ENET_RMII1_TXEN 0x30d2
+ >;
+ };
+
+ pinctrl_nfc_1: nfcgrp_1 {
+ fsl,pins = <
+ VF610_PAD_PTD23__NF_IO7 0x28df
+ VF610_PAD_PTD22__NF_IO6 0x28df
+ VF610_PAD_PTD21__NF_IO5 0x28df
+ VF610_PAD_PTD20__NF_IO4 0x28df
+ VF610_PAD_PTD19__NF_IO3 0x28df
+ VF610_PAD_PTD18__NF_IO2 0x28df
+ VF610_PAD_PTD17__NF_IO1 0x28df
+ VF610_PAD_PTD16__NF_IO0 0x28df
+ VF610_PAD_PTB24__NF_WE_B 0x28c2
+ VF610_PAD_PTB25__NF_CE0_B 0x28c2
+ VF610_PAD_PTB27__NF_RE_B 0x28c2
+ VF610_PAD_PTC26__NF_RB_B 0x283d
+ VF610_PAD_PTC27__NF_ALE 0x28c2
+ VF610_PAD_PTC28__NF_CLE 0x28c2
+ >;
+ };
+
+ pinctrl_uart0: uart0grp {
+ fsl,pins = <
+ VF610_PAD_PTB10__UART0_TX 0x21a2
+ VF610_PAD_PTB11__UART0_RX 0x21a1
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ VF610_PAD_PTB4__UART1_TX 0x21a2
+ VF610_PAD_PTB5__UART1_RX 0x21a1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ VF610_PAD_PTD0__UART2_TX 0x21a2
+ VF610_PAD_PTD1__UART2_RX 0x21a1
+ VF610_PAD_PTD2__UART2_RTS 0x21a2
+ VF610_PAD_PTD3__UART2_CTS 0x21a1
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ VF610_PAD_PTA20__UART3_TX 0x21a2
+ VF610_PAD_PTA21__UART3_RX 0x21a1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ VF610_PAD_PTA28__UART4_TX 0x21a2
+ VF610_PAD_PTA29__UART4_RX 0x21a1
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
new file mode 100644
index 000000000000..1f43dbeea1bb
--- /dev/null
+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <dt-bindings/input/input.h>
+
+/ {
+ chosen {
+ bootargs = "console=ttyLP0,115200";
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <0 36 49 66 87 112 145 179 217 255>;
+ default-brightness-level = <5>;
+ status = "okay";
+ };
+
+ bl_on {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_bl_on>;
+ compatible = "gpio-backlight";
+ gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+ default-on;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sys_5v0_reg: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ /* USBH_PEN */
+ usbh_vbus_reg: regulator@1 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1_reg>;
+ reg = <1>;
+ regulator-name = "usbh_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_LOW>;
+ vin-supply = <&sys_5v0_reg>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiokeys>;
+
+ power {
+ label = "Wake-Up";
+ gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ linux,code = <KEY_WAKEUP>;
+ debounce-interval = <10>;
+ gpio-key,wakeup;
+ };
+ };
+};
+
+&dcu0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dcu0_1>;
+ display = <&display>;
+ status = "okay";
+
+ display: display@0 {
+ bits-per-pixel = <16>;
+
+ display-timings {
+ native-mode = <&timing_vga>;
+ /* Standard VGA timing */
+ timing_vga: 640x480 {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ hsync-len = <96>;
+ vsync-len = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* WVGA Timing, e.g. EDT ET070080DH6 */
+ timing_wvga: 800x480 {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* WVGA Timing, TouchRevolution Fusion 7" */
+ timing_wvga2: 800x480pixclkact {
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <216>;
+ hfront-porch = <40>;
+ vback-porch = <35>;
+ vfront-porch = <10>;
+ hsync-len = <128>;
+ vsync-len = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <1>;
+ };
+ /* Standard SVGA timing */
+ timing_svga: 800x600 {
+ clock-frequency = <40000000>;
+ hactive = <800>;
+ vactive = <600>;
+ hback-porch = <88>;
+ hfront-porch = <40>;
+ vback-porch = <23>;
+ vfront-porch = <1>;
+ hsync-len = <128>;
+ vsync-len = <4>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ pixelclk-active = <0>;
+ };
+ /* TouchRevolution Fusion 10"/CLAA101NC05 10.1 inch */
+ timing_wsvga: 1024x600 {
+ clock-frequency = <48000000>;
+ hactive = <1024>;
+ vactive = <600>;
+ hback-porch = <104>;
+ hfront-porch = <43>;
+ vback-porch = <24>;
+ vfront-porch = <20>;
+ hsync-len = <5>;
+ vsync-len = <5>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ /* Standard XGA timing */
+ timing_xga: 1024x768 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <160>;
+ hfront-porch = <24>;
+ vback-porch = <29>;
+ vfront-porch = <3>;
+ hsync-len = <136>;
+ vsync-len = <6>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&dspi1 {
+ status = "okay";
+
+ spidev1: dspi@1 {
+ compatible = "spidev";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&esdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_esdhc1>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&fec1 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ /* TouchRevolution Fusion 7 and 10 multi-touch controller */
+ touch: touchrevf0710a@10 {
+ compatible = "touchrevolution,fusion-f0710a";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiotouch>;
+ reg = <0x10>;
+ gpios = <&gpio0 30 GPIO_ACTIVE_HIGH /* SO-DIMM 28, Pen down interrupt */
+ &gpio0 23 GPIO_ACTIVE_LOW /* SO-DIMM 30, Reset interrupt */
+ >;
+ status = "disabled";
+ };
+
+ /* M41T0M6 real time clock on carrier board */
+ rtc: m41t0m6@68 {
+ compatible = "st,m41t00";
+ reg = <0x68>;
+ };
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&tcon0 {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&usbh_vbus_reg>;
+};
+
+&iomuxc {
+ vf610-colibri {
+ pinctrl_gpiokeys: gpiokeys {
+ fsl,pins = <
+ VF610_PAD_PTB19__GPIO_41 0x219d
+ >;
+ };
+
+ pinctrl_gpiotouch: touchgpios {
+ fsl,pins = <
+ VF610_PAD_PTB8__GPIO_30 0x6f
+ VF610_PAD_PTB1__GPIO_23 0x4f
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi
new file mode 100644
index 000000000000..d10a2b46caf1
--- /dev/null
+++ b/arch/arm/boot/dts/vf-colibri.dtsi
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * 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.
+ */
+
+&adc0 {
+ status = "okay";
+};
+
+&adc1 {
+ status = "okay";
+};
+
+&dspi1 {
+ bus-num = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dspi1>;
+};
+
+&edma0 {
+ status = "okay";
+};
+
+&esdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_esdhc1>;
+ bus-width = <4>;
+ cd-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+};
+
+&fec1 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c0>;
+};
+
+&nfc {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+ clock-frequency = <33000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nfc_1>;
+ status = "okay";
+};
+
+&pwm0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0>;
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart0>;
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+};
+
+&usbdev0 {
+ disable-over-current;
+ status = "okay";
+};
+
+&usbh1 {
+ disable-over-current;
+ status = "okay";
+};
+
+&usbmisc0 {
+ status = "okay";
+};
+
+&usbmisc1 {
+ status = "okay";
+};
+
+&usbphy0 {
+ status = "okay";
+};
+
+&usbphy1 {
+ status = "okay";
+};
+
+&iomuxc {
+ vf610-colibri {
+ pinctrl_gpio_bl_on: gpio_bl_on {
+ fsl,pins = <
+ VF610_PAD_PTC0__GPIO_45 0x22ed
+ >;
+ };
+
+ pinctrl_additionalgpio: additionalgpios {
+ fsl,pins = <
+ VF610_PAD_PTA17__GPIO_7 0x22ed
+ VF610_PAD_PTA20__GPIO_10 0x22ed
+ VF610_PAD_PTA21__GPIO_11 0x22ed
+ VF610_PAD_PTA30__GPIO_20 0x22ed
+ VF610_PAD_PTA31__GPIO_21 0x22ed
+ VF610_PAD_PTB6__GPIO_28 0x22ed
+ VF610_PAD_PTB7__GPIO_29 0x22ed
+ VF610_PAD_PTB12__GPIO_34 0x22ed
+ VF610_PAD_PTB13__GPIO_35 0x22ed
+ VF610_PAD_PTB16__GPIO_38 0x22ed
+ VF610_PAD_PTB17__GPIO_39 0x22ed
+ VF610_PAD_PTB18__GPIO_40 0x22ed
+ VF610_PAD_PTB21__GPIO_43 0x22ed
+ VF610_PAD_PTB22__GPIO_44 0x22ed
+ VF610_PAD_PTC1__GPIO_46 0x22ed
+ VF610_PAD_PTC2__GPIO_47 0x22ed
+ VF610_PAD_PTC3__GPIO_48 0x22ed
+ VF610_PAD_PTC4__GPIO_49 0x22ed
+ VF610_PAD_PTC5__GPIO_50 0x22ed
+ VF610_PAD_PTC6__GPIO_51 0x22ed
+ VF610_PAD_PTC7__GPIO_52 0x22ed
+ VF610_PAD_PTC8__GPIO_53 0x22ed
+ VF610_PAD_PTD31__GPIO_63 0x22ed
+ VF610_PAD_PTD30__GPIO_64 0x22ed
+ VF610_PAD_PTD29__GPIO_65 0x22ed
+ VF610_PAD_PTD28__GPIO_66 0x22ed
+ VF610_PAD_PTD27__GPIO_67 0x22ed
+ VF610_PAD_PTD26__GPIO_68 0x22ed
+ VF610_PAD_PTD25__GPIO_69 0x22ed
+ VF610_PAD_PTD24__GPIO_70 0x22ed
+ VF610_PAD_PTD9__GPIO_88 0x22ed
+ VF610_PAD_PTD10__GPIO_89 0x22ed
+ VF610_PAD_PTD11__GPIO_90 0x22ed
+ VF610_PAD_PTD12__GPIO_91 0x22ed
+ VF610_PAD_PTD13__GPIO_92 0x22ed
+ VF610_PAD_PTB23__GPIO_93 0x22ed
+ VF610_PAD_PTB26__GPIO_96 0x22ed
+ VF610_PAD_PTB28__GPIO_98 0x22ed
+ VF610_PAD_PTC29__GPIO_102 0x22ed
+ VF610_PAD_PTC30__GPIO_103 0x22ed
+ VF610_PAD_PTA7__GPIO_134 0x22ed
+ >;
+ };
+
+ pinctrl_dcu0_1: dcu0grp_1 {
+ fsl,pins = <
+ VF610_PAD_PTE0__DCU0_HSYNC 0x1902
+ VF610_PAD_PTE1__DCU0_VSYNC 0x1902
+ VF610_PAD_PTE2__DCU0_PCLK 0x1902
+ VF610_PAD_PTE4__DCU0_DE 0x1902
+ VF610_PAD_PTE5__DCU0_R0 0x1902
+ VF610_PAD_PTE6__DCU0_R1 0x1902
+ VF610_PAD_PTE7__DCU0_R2 0x1902
+ VF610_PAD_PTE8__DCU0_R3 0x1902
+ VF610_PAD_PTE9__DCU0_R4 0x1902
+ VF610_PAD_PTE10__DCU0_R5 0x1902
+ VF610_PAD_PTE11__DCU0_R6 0x1902
+ VF610_PAD_PTE12__DCU0_R7 0x1902
+ VF610_PAD_PTE13__DCU0_G0 0x1902
+ VF610_PAD_PTE14__DCU0_G1 0x1902
+ VF610_PAD_PTE15__DCU0_G2 0x1902
+ VF610_PAD_PTE16__DCU0_G3 0x1902
+ VF610_PAD_PTE17__DCU0_G4 0x1902
+ VF610_PAD_PTE18__DCU0_G5 0x1902
+ VF610_PAD_PTE19__DCU0_G6 0x1902
+ VF610_PAD_PTE20__DCU0_G7 0x1902
+ VF610_PAD_PTE21__DCU0_B0 0x1902
+ VF610_PAD_PTE22__DCU0_B1 0x1902
+ VF610_PAD_PTE23__DCU0_B2 0x1902
+ VF610_PAD_PTE24__DCU0_B3 0x1902
+ VF610_PAD_PTE25__DCU0_B4 0x1902
+ VF610_PAD_PTE26__DCU0_B5 0x1902
+ VF610_PAD_PTE27__DCU0_B6 0x1902
+ VF610_PAD_PTE28__DCU0_B7 0x1902
+ >;
+ };
+
+ pinctrl_dspi1: dspi1grp {
+ fsl,pins = <
+ VF610_PAD_PTD5__DSPI1_CS0 0x33e2
+ VF610_PAD_PTD6__DSPI1_SIN 0x33e1
+ VF610_PAD_PTD7__DSPI1_SOUT 0x33e2
+ VF610_PAD_PTD8__DSPI1_SCK 0x33e2
+ >;
+ };
+
+ pinctrl_esdhc1: esdhc1grp {
+ fsl,pins = <
+ VF610_PAD_PTA24__ESDHC1_CLK 0x31ef
+ VF610_PAD_PTA25__ESDHC1_CMD 0x31ef
+ VF610_PAD_PTA26__ESDHC1_DAT0 0x31ef
+ VF610_PAD_PTA27__ESDHC1_DAT1 0x31ef
+ VF610_PAD_PTA28__ESDHC1_DATA2 0x31ef
+ VF610_PAD_PTA29__ESDHC1_DAT3 0x31ef
+ VF610_PAD_PTB20__GPIO_42 0x219d
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ VF610_PAD_PTA6__RMII_CLKOUT 0x30d2
+ VF610_PAD_PTC9__ENET_RMII1_MDC 0x30d2
+ VF610_PAD_PTC10__ENET_RMII1_MDIO 0x30d3
+ VF610_PAD_PTC11__ENET_RMII1_CRS 0x30d1
+ VF610_PAD_PTC12__ENET_RMII_RXD1 0x30d1
+ VF610_PAD_PTC13__ENET_RMII1_RXD0 0x30d1
+ VF610_PAD_PTC14__ENET_RMII1_RXER 0x30d1
+ VF610_PAD_PTC15__ENET_RMII1_TXD1 0x30d2
+ VF610_PAD_PTC16__ENET_RMII1_TXD0 0x30d2
+ VF610_PAD_PTC17__ENET_RMII1_TXEN 0x30d2
+ >;
+ };
+
+ pinctrl_i2c0: i2c0grp {
+ fsl,pins = <
+ VF610_PAD_PTB14__I2C0_SCL 0x37ff
+ VF610_PAD_PTB15__I2C0_SDA 0x37ff
+ >;
+ };
+
+ pinctrl_nfc_1: nfcgrp_1 {
+ fsl,pins = <
+ VF610_PAD_PTD23__NF_IO7 0x28df
+ VF610_PAD_PTD22__NF_IO6 0x28df
+ VF610_PAD_PTD21__NF_IO5 0x28df
+ VF610_PAD_PTD20__NF_IO4 0x28df
+ VF610_PAD_PTD19__NF_IO3 0x28df
+ VF610_PAD_PTD18__NF_IO2 0x28df
+ VF610_PAD_PTD17__NF_IO1 0x28df
+ VF610_PAD_PTD16__NF_IO0 0x28df
+ VF610_PAD_PTB24__NF_WE_B 0x28c2
+ VF610_PAD_PTB25__NF_CE0_B 0x28c2
+ VF610_PAD_PTB27__NF_RE_B 0x28c2
+ VF610_PAD_PTC26__NF_RB_B 0x283d
+ VF610_PAD_PTC27__NF_ALE 0x28c2
+ VF610_PAD_PTC28__NF_CLE 0x28c2
+ >;
+ };
+
+ pinctrl_pwm0: pwm0grp {
+ fsl,pins = <
+ VF610_PAD_PTB0__FTM0_CH0 0x1182
+ VF610_PAD_PTB1__FTM0_CH1 0x1182
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ VF610_PAD_PTB8__FTM1_CH0 0x1182
+ VF610_PAD_PTB9__FTM1_CH1 0x1182
+ >;
+ };
+
+ pinctrl_uart0: uart0grp {
+ fsl,pins = <
+ VF610_PAD_PTB10__UART0_TX 0x21a2
+ VF610_PAD_PTB11__UART0_RX 0x21a1
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ VF610_PAD_PTB4__UART1_TX 0x21a2
+ VF610_PAD_PTB5__UART1_RX 0x21a1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ VF610_PAD_PTD0__UART2_TX 0x21a2
+ VF610_PAD_PTD1__UART2_RX 0x21a1
+ VF610_PAD_PTD2__UART2_RTS 0x21a2
+ VF610_PAD_PTD3__UART2_CTS 0x21a1
+ >;
+ };
+
+ pinctrl_usbh1_reg: gpio_usb_vbus {
+ fsl,pins = <
+ VF610_PAD_PTD4__GPIO_83 0x22ed
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/vf500-colibri-dual-eth.dts b/arch/arm/boot/dts/vf500-colibri-dual-eth.dts
new file mode 100644
index 000000000000..24990e241e0e
--- /dev/null
+++ b/arch/arm/boot/dts/vf500-colibri-dual-eth.dts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "vf500-colibri.dtsi"
+#include "vf-colibri-dual-eth.dtsi"
+
+/ {
+ model = "Toradex Colibri VF50 on Dual Ethernet Board";
+ compatible = "toradex,vf500-colibri_vf50-on-dual-eth-board", "toradex,vf500-colibri_vf50", "fsl,vf500";
+};
diff --git a/arch/arm/boot/dts/vf500-colibri-eval-v3.dts b/arch/arm/boot/dts/vf500-colibri-eval-v3.dts
new file mode 100644
index 000000000000..c5efb576570c
--- /dev/null
+++ b/arch/arm/boot/dts/vf500-colibri-eval-v3.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "vf500-colibri.dtsi"
+#include "vf-colibri-eval-v3.dtsi"
+
+/ {
+ model = "Toradex Colibri VF50 on Colibri Evaluation Board";
+ compatible = "toradex,vf500-colibri_vf50-on-eval", "toradex,vf500-colibri_vf50", "fsl,vf500";
+};
+
+&touchctrl {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/vf500-colibri.dtsi b/arch/arm/boot/dts/vf500-colibri.dtsi
new file mode 100644
index 000000000000..87e478afa40c
--- /dev/null
+++ b/arch/arm/boot/dts/vf500-colibri.dtsi
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "vf500.dtsi"
+#include "vf-colibri.dtsi"
+
+/ {
+ model = "Toradex Colibri VF50 COM";
+ compatible = "toradex,vf610-colibri_vf50", "fsl,vf500";
+
+ memory {
+ reg = <0x80000000 0x8000000>;
+ };
+
+ touchctrl: vf50_touchctrl {
+ compatible = "toradex,vf50-touchctrl";
+ io-channels = <&adc1 0>,<&adc0 0>,
+ <&adc0 1>, <&adc1 2>;
+ vf,gpio-xp = <13>;
+ vf,gpio-xm = <93>;
+ vf,gpio-yp = <12>;
+ vf,gpio-ym = <4>;
+ vf,gpio-pen-detect = <8>;
+ vf,gpio-pen-pullup = <9>;
+ pinctrl-names = "idle","default","gpios";
+ pinctrl-0 = <&pinctrl_touchctrl_idle>;
+ pinctrl-1 = <&pinctrl_touchctrl_default>;
+ pinctrl-2 = <&pinctrl_touchctrl_gpios>;
+ status = "disabled";
+ };
+};
+
+&iomuxc {
+ vf610-colibri {
+ pinctrl_touchctrl_idle: touchctrl_idle {
+ fsl,pins = <
+ VF610_PAD_PTA18__GPIO_8 0x206d
+ VF610_PAD_PTA19__GPIO_9 0x206d
+ >;
+ };
+
+ pinctrl_touchctrl_default: touchctrl_default {
+ fsl,pins = <
+ VF610_PAD_PTA18__ADC0_SE0 0x2060
+ VF610_PAD_PTA19__ADC0_SE1 0x2060
+ VF610_PAD_PTA16__ADC1_SE0 0x2060
+ VF610_PAD_PTB2__ADC1_SE2 0x2060
+ >;
+ };
+
+ pinctrl_touchctrl_gpios: touchctrl_gpios {
+ fsl,pins = <
+ VF610_PAD_PTA23__GPIO_13 0x22ed
+ VF610_PAD_PTB23__GPIO_93 0x22ed
+ VF610_PAD_PTA22__GPIO_12 0x22ed
+ VF610_PAD_PTA11__GPIO_4 0x22ed
+ >;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi
new file mode 100644
index 000000000000..d7e3771b70ed
--- /dev/null
+++ b/arch/arm/boot/dts/vf500.dtsi
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "skeleton.dtsi"
+#include "vfxxx.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ a5_cpu: cpu@0 {
+ compatible = "arm,cortex-a5";
+ device_type = "cpu";
+ reg = <0x0>;
+ };
+ };
+
+ soc {
+ interrupt-parent = <&intc>;
+
+ aips-bus@40000000 {
+
+ intc: interrupt-controller@40002000 {
+ compatible = "arm,cortex-a9-gic";
+ arm,routable-irqs = <144>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x40003000 0x1000>,
+ <0x40002100 0x100>;
+ };
+
+ global_timer: timer@40002200 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0x40002200 0x20>;
+ interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks VF610_CLK_PLATFORM_BUS>;
+ };
+ };
+ };
+};
+
+&adc0 {
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&adc1 {
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&can0 {
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&can1 {
+ interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&dcu0 {
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&dspi0 {
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&dspi1 {
+ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&edma0 {
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "edma-tx", "edma-err";
+};
+
+&edma1 {
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "edma-tx", "edma-err";
+};
+
+&esdhc1 {
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&fec0 {
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&fec1 {
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&ftm {
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio0 {
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio1 {
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio2 {
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio3 {
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio4 {
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&i2c0 {
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mscm {
+
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "int0", "int1", "int2", "int3";
+};
+
+&nfc {
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&pit {
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&qspi0 {
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sai2 {
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&sema4 {
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&snvsrtc {
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&src {
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&uart0 {
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&uart1 {
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&uart2 {
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&uart3 {
+ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&uart4 {
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&uart5 {
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usbdev0 {
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usbh1 {
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usbphy0 {
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usbphy1 {
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&wdoga5 {
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/vf610-colibri-dual-eth.dts b/arch/arm/boot/dts/vf610-colibri-dual-eth.dts
new file mode 100644
index 000000000000..a2eff553956c
--- /dev/null
+++ b/arch/arm/boot/dts/vf610-colibri-dual-eth.dts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "vf610-colibri.dtsi"
+#include "vf-colibri-dual-eth.dtsi"
+
+/ {
+ model = "Toradex Colibri VF61 on Dual Ethernet Board";
+ compatible = "toradex,vf610-colibri_vf61-on-dual-eth-board", "toradex,vf610-colibri_vf61", "fsl,vf610";
+};
diff --git a/arch/arm/boot/dts/vf610-colibri-eval-v3.dts b/arch/arm/boot/dts/vf610-colibri-eval-v3.dts
index 7fb306679341..10ebe99e2751 100644
--- a/arch/arm/boot/dts/vf610-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/vf610-colibri-eval-v3.dts
@@ -9,38 +9,9 @@
/dts-v1/;
#include "vf610-colibri.dtsi"
+#include "vf-colibri-eval-v3.dtsi"
/ {
model = "Toradex Colibri VF61 on Colibri Evaluation Board";
compatible = "toradex,vf610-colibri_vf61-on-eval", "toradex,vf610-colibri_vf61", "fsl,vf610";
-
- chosen {
- bootargs = "console=ttyLP0,115200";
- };
-};
-
-&esdhc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_esdhc1>;
- bus-width = <4>;
- status = "okay";
-};
-
-&fec1 {
- phy-mode = "rmii";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_fec1>;
- status = "okay";
-};
-
-&uart0 {
- status = "okay";
-};
-
-&uart1 {
- status = "okay";
-};
-
-&uart2 {
- status = "okay";
-};
+}; \ No newline at end of file
diff --git a/arch/arm/boot/dts/vf610-colibri.dtsi b/arch/arm/boot/dts/vf610-colibri.dtsi
index 0cd83434b073..19fe045b8334 100644
--- a/arch/arm/boot/dts/vf610-colibri.dtsi
+++ b/arch/arm/boot/dts/vf610-colibri.dtsi
@@ -8,6 +8,7 @@
*/
#include "vf610.dtsi"
+#include "vf-colibri.dtsi"
/ {
model = "Toradex Colibri VF61 COM";
@@ -16,108 +17,9 @@
memory {
reg = <0x80000000 0x10000000>;
};
-
- clocks {
- enet_ext {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <50000000>;
- };
- };
-
-};
-
-&esdhc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_esdhc1>;
- bus-width = <4>;
-};
-
-&fec1 {
- phy-mode = "rmii";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_fec1>;
};
&L2 {
arm,data-latency = <2 1 2>;
arm,tag-latency = <3 2 3>;
};
-
-&uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart0>;
-};
-
-&uart1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart1>;
-};
-
-&uart2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart2>;
-};
-
-&usbdev0 {
- disable-over-current;
- status = "okay";
-};
-
-&usbh1 {
- disable-over-current;
- status = "okay";
-};
-
-&iomuxc {
- vf610-colibri {
- pinctrl_esdhc1: esdhc1grp {
- fsl,pins = <
- VF610_PAD_PTA24__ESDHC1_CLK 0x31ef
- VF610_PAD_PTA25__ESDHC1_CMD 0x31ef
- VF610_PAD_PTA26__ESDHC1_DAT0 0x31ef
- VF610_PAD_PTA27__ESDHC1_DAT1 0x31ef
- VF610_PAD_PTA28__ESDHC1_DATA2 0x31ef
- VF610_PAD_PTA29__ESDHC1_DAT3 0x31ef
- VF610_PAD_PTB20__GPIO_42 0x219d
- >;
- };
-
- pinctrl_fec1: fec1grp {
- fsl,pins = <
- VF610_PAD_PTC9__ENET_RMII1_MDC 0x30d2
- VF610_PAD_PTC10__ENET_RMII1_MDIO 0x30d3
- VF610_PAD_PTC11__ENET_RMII1_CRS 0x30d1
- VF610_PAD_PTC12__ENET_RMII_RXD1 0x30d1
- VF610_PAD_PTC13__ENET_RMII1_RXD0 0x30d1
- VF610_PAD_PTC14__ENET_RMII1_RXER 0x30d1
- VF610_PAD_PTC15__ENET_RMII1_TXD1 0x30d2
- VF610_PAD_PTC16__ENET_RMII1_TXD0 0x30d2
- VF610_PAD_PTC17__ENET_RMII1_TXEN 0x30d2
- >;
- };
-
- pinctrl_uart0: uart0grp {
- fsl,pins = <
- VF610_PAD_PTB10__UART0_TX 0x21a2
- VF610_PAD_PTB11__UART0_RX 0x21a1
- >;
- };
-
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- VF610_PAD_PTB4__UART1_TX 0x21a2
- VF610_PAD_PTB5__UART1_RX 0x21a1
- >;
- };
-
- pinctrl_uart2: uart2grp {
- fsl,pins = <
- VF610_PAD_PTD0__UART2_TX 0x21a2
- VF610_PAD_PTD1__UART2_RX 0x21a1
- VF610_PAD_PTD2__UART2_RTS 0x21a2
- VF610_PAD_PTD3__UART2_CTS 0x21a1
- >;
- };
- };
-};
diff --git a/arch/arm/boot/dts/vf610-cosmic.dts b/arch/arm/boot/dts/vf610-cosmic.dts
index de1b453c2932..fd8758b639f5 100644
--- a/arch/arm/boot/dts/vf610-cosmic.dts
+++ b/arch/arm/boot/dts/vf610-cosmic.dts
@@ -23,14 +23,16 @@
reg = <0x80000000 0x10000000>;
};
- clocks {
- enet_ext {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <50000000>;
- };
+ enet_ext: enet_ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
};
+};
+&clks {
+ clocks = <&sxosc>, <&fxosc>, <&enet_ext>;
+ clock-names = "sxosc", "fxosc", "enet_ext";
};
&esdhc1 {
diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 189b6975fe7d..9abffed22681 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -22,18 +22,16 @@
reg = <0x80000000 0x8000000>;
};
- clocks {
- audio_ext {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <24576000>;
- };
+ audio_ext: mclk_osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24576000>;
+ };
- enet_ext {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <50000000>;
- };
+ enet_ext: eth_osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
};
regulators {
@@ -95,6 +93,11 @@
status = "okay";
};
+&clks {
+ clocks = <&sxosc>, <&fxosc>, <&enet_ext>, <&audio_ext>;
+ clock-names = "sxosc", "fxosc", "enet_ext", "audio_ext";
+};
+
&dspi0 {
bus-num = <0>;
pinctrl-names = "default";
@@ -112,22 +115,70 @@
};
};
+&edma0 {
+ status = "okay";
+};
+
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
bus-width = <4>;
+ cd-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>;
status = "okay";
};
+&dcu0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dcu0_1>;
+ display = <&display>;
+ status = "okay";
+
+ display: display@0 {
+ bits-per-pixel = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: nl4827hc19 {
+ clock-frequency = <10870000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hfront-porch = <2>;
+ vback-porch = <1>;
+ vfront-porch = <1>;
+ hsync-len = <41>;
+ vsync-len = <2>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+ };
+};
+
&fec0 {
phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec0>;
status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
};
&fec1 {
phy-mode = "rmii";
+ phy-handle = <&ethphy1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec1>;
status = "okay";
@@ -157,6 +208,39 @@
>;
};
+ pinctrl_dcu0_1: dcu0grp_1 {
+ fsl,pins = <
+ VF610_PAD_PTE0__DCU0_HSYNC 0x42
+ VF610_PAD_PTE1__DCU0_VSYNC 0x42
+ VF610_PAD_PTE2__DCU0_PCLK 0x42
+ VF610_PAD_PTE4__DCU0_DE 0x42
+ VF610_PAD_PTE5__DCU0_R0 0x42
+ VF610_PAD_PTE6__DCU0_R1 0x42
+ VF610_PAD_PTE7__DCU0_R2 0x42
+ VF610_PAD_PTE8__DCU0_R3 0x42
+ VF610_PAD_PTE9__DCU0_R4 0x42
+ VF610_PAD_PTE10__DCU0_R5 0x42
+ VF610_PAD_PTE11__DCU0_R6 0x42
+ VF610_PAD_PTE12__DCU0_R7 0x42
+ VF610_PAD_PTE13__DCU0_G0 0x42
+ VF610_PAD_PTE14__DCU0_G1 0x42
+ VF610_PAD_PTE15__DCU0_G2 0x42
+ VF610_PAD_PTE16__DCU0_G3 0x42
+ VF610_PAD_PTE17__DCU0_G4 0x42
+ VF610_PAD_PTE18__DCU0_G5 0x42
+ VF610_PAD_PTE19__DCU0_G6 0x42
+ VF610_PAD_PTE20__DCU0_G7 0x42
+ VF610_PAD_PTE21__DCU0_B0 0x42
+ VF610_PAD_PTE22__DCU0_B1 0x42
+ VF610_PAD_PTE23__DCU0_B2 0x42
+ VF610_PAD_PTE24__DCU0_B3 0x42
+ VF610_PAD_PTE25__DCU0_B4 0x42
+ VF610_PAD_PTE26__DCU0_B5 0x42
+ VF610_PAD_PTE27__DCU0_B6 0x42
+ VF610_PAD_PTE28__DCU0_B7 0x42
+ >;
+ };
+
pinctrl_dspi0: dspi0grp {
fsl,pins = <
VF610_PAD_PTB19__DSPI0_CS0 0x1182
@@ -264,6 +348,50 @@
status = "okay";
};
+&iomuxc {
+ vf610-twr {
+ pinctrl_nfc_1: nfcgrp_1 {
+ fsl,pins = <
+ VF610_PAD_PTD31__NF_IO15 0x28df
+ VF610_PAD_PTD30__NF_IO14 0x28df
+ VF610_PAD_PTD29__NF_IO13 0x28df
+ VF610_PAD_PTD28__NF_IO12 0x28df
+ VF610_PAD_PTD27__NF_IO11 0x28df
+ VF610_PAD_PTD26__NF_IO10 0x28df
+ VF610_PAD_PTD25__NF_IO9 0x28df
+ VF610_PAD_PTD24__NF_IO8 0x28df
+ VF610_PAD_PTD23__NF_IO7 0x28df
+ VF610_PAD_PTD22__NF_IO6 0x28df
+ VF610_PAD_PTD21__NF_IO5 0x28df
+ VF610_PAD_PTD20__NF_IO4 0x28df
+ VF610_PAD_PTD19__NF_IO3 0x28df
+ VF610_PAD_PTD18__NF_IO2 0x28df
+ VF610_PAD_PTD17__NF_IO1 0x28df
+ VF610_PAD_PTD16__NF_IO0 0x28df
+ VF610_PAD_PTB24__NF_WE_B 0x28c2
+ VF610_PAD_PTB25__NF_CE0_B 0x28c2
+ VF610_PAD_PTB27__NF_RE_B 0x28c2
+ VF610_PAD_PTC26__NF_RB_B 0x283d
+ VF610_PAD_PTC27__NF_ALE 0x28c2
+ VF610_PAD_PTC28__NF_CLE 0x28c2
+ >;
+ };
+ };
+};
+
+&nfc {
+ nand-bus-width = <16>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+ clock-frequency = <33000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nfc_1>;
+};
+
+&tcon0 {
+ status = "okay";
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
@@ -285,3 +413,19 @@
disable-over-current;
status = "okay";
};
+
+&usbmisc0 {
+ status = "okay";
+};
+
+&usbmisc1 {
+ status = "okay";
+};
+
+&usbphy0 {
+ status = "okay";
+};
+
+&usbphy1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 4d2ec32de96f..5f8eb1bd782b 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -7,481 +7,19 @@
* (at your option) any later version.
*/
-#include "skeleton.dtsi"
-#include "vf610-pinfunc.h"
-#include <dt-bindings/clock/vf610-clock.h>
-#include <dt-bindings/interrupt-controller/irq.h>
+#include "vf500.dtsi"
-/ {
- aliases {
- can0 = &can0;
- can1 = &can1;
- serial0 = &uart0;
- serial1 = &uart1;
- serial2 = &uart2;
- serial3 = &uart3;
- serial4 = &uart4;
- serial5 = &uart5;
- gpio0 = &gpio1;
- gpio1 = &gpio2;
- gpio2 = &gpio3;
- gpio3 = &gpio4;
- gpio4 = &gpio5;
- usbphy0 = &usbphy0;
- usbphy1 = &usbphy1;
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu@0 {
- compatible = "arm,cortex-a5";
- device_type = "cpu";
- reg = <0x0>;
- next-level-cache = <&L2>;
- };
- };
-
- clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
- sxosc {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- };
-
- fxosc {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <24000000>;
- };
- };
-
- soc {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "simple-bus";
- interrupt-parent = <&intc>;
- ranges;
-
- aips0: aips-bus@40000000 {
- compatible = "fsl,aips-bus", "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- interrupt-parent = <&intc>;
- reg = <0x40000000 0x70000>;
- ranges;
-
- intc: interrupt-controller@40002000 {
- compatible = "arm,cortex-a9-gic";
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0x40003000 0x1000>,
- <0x40002100 0x100>;
- };
-
- L2: l2-cache@40006000 {
- compatible = "arm,pl310-cache";
- reg = <0x40006000 0x1000>;
- cache-unified;
- cache-level = <2>;
- arm,data-latency = <1 1 1>;
- arm,tag-latency = <2 2 2>;
- };
-
- edma0: dma-controller@40018000 {
- #dma-cells = <2>;
- compatible = "fsl,vf610-edma";
- reg = <0x40018000 0x2000>,
- <0x40024000 0x1000>,
- <0x40025000 0x1000>;
- interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
- <0 9 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "edma-tx", "edma-err";
- dma-channels = <32>;
- clock-names = "dmamux0", "dmamux1";
- clocks = <&clks VF610_CLK_DMAMUX0>,
- <&clks VF610_CLK_DMAMUX1>;
- };
-
- can0: flexcan@40020000 {
- compatible = "fsl,vf610-flexcan";
- reg = <0x40020000 0x4000>;
- interrupts = <0 58 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_FLEXCAN0>,
- <&clks VF610_CLK_FLEXCAN0>;
- clock-names = "ipg", "per";
- status = "disabled";
- };
-
- uart0: serial@40027000 {
- compatible = "fsl,vf610-lpuart";
- reg = <0x40027000 0x1000>;
- interrupts = <0 61 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_UART0>;
- clock-names = "ipg";
- dmas = <&edma0 0 2>,
- <&edma0 0 3>;
- dma-names = "rx","tx";
- status = "disabled";
- };
-
- uart1: serial@40028000 {
- compatible = "fsl,vf610-lpuart";
- reg = <0x40028000 0x1000>;
- interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_UART1>;
- clock-names = "ipg";
- dmas = <&edma0 0 4>,
- <&edma0 0 5>;
- dma-names = "rx","tx";
- status = "disabled";
- };
-
- uart2: serial@40029000 {
- compatible = "fsl,vf610-lpuart";
- reg = <0x40029000 0x1000>;
- interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_UART2>;
- clock-names = "ipg";
- dmas = <&edma0 0 6>,
- <&edma0 0 7>;
- dma-names = "rx","tx";
- status = "disabled";
- };
-
- uart3: serial@4002a000 {
- compatible = "fsl,vf610-lpuart";
- reg = <0x4002a000 0x1000>;
- interrupts = <0 64 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_UART3>;
- clock-names = "ipg";
- dmas = <&edma0 0 8>,
- <&edma0 0 9>;
- dma-names = "rx","tx";
- status = "disabled";
- };
-
- dspi0: dspi0@4002c000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,vf610-dspi";
- reg = <0x4002c000 0x1000>;
- interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_DSPI0>;
- clock-names = "dspi";
- spi-num-chipselects = <5>;
- status = "disabled";
- };
-
- sai2: sai@40031000 {
- compatible = "fsl,vf610-sai";
- reg = <0x40031000 0x1000>;
- interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_SAI2>;
- clock-names = "sai";
- dma-names = "tx", "rx";
- dmas = <&edma0 0 21>,
- <&edma0 0 20>;
- status = "disabled";
- };
-
- pit: pit@40037000 {
- compatible = "fsl,vf610-pit";
- reg = <0x40037000 0x1000>;
- interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_PIT>;
- clock-names = "pit";
- };
-
- pwm0: pwm@40038000 {
- compatible = "fsl,vf610-ftm-pwm";
- #pwm-cells = <3>;
- reg = <0x40038000 0x1000>;
- clock-names = "ftm_sys", "ftm_ext",
- "ftm_fix", "ftm_cnt_clk_en";
- clocks = <&clks VF610_CLK_FTM0>,
- <&clks VF610_CLK_FTM0_EXT_SEL>,
- <&clks VF610_CLK_FTM0_FIX_SEL>,
- <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
- status = "disabled";
- };
-
- adc0: adc@4003b000 {
- compatible = "fsl,vf610-adc";
- reg = <0x4003b000 0x1000>;
- interrupts = <0 53 0x04>;
- clocks = <&clks VF610_CLK_ADC0>;
- clock-names = "adc";
- status = "disabled";
- };
-
- wdog@4003e000 {
- compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
- reg = <0x4003e000 0x1000>;
- clocks = <&clks VF610_CLK_WDT>;
- clock-names = "wdog";
- };
-
- qspi0: quadspi@40044000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,vf610-qspi";
- reg = <0x40044000 0x1000>;
- interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_QSPI0_EN>,
- <&clks VF610_CLK_QSPI0>;
- clock-names = "qspi_en", "qspi";
- status = "disabled";
- };
-
- iomuxc: iomuxc@40048000 {
- compatible = "fsl,vf610-iomuxc";
- reg = <0x40048000 0x1000>;
- #gpio-range-cells = <3>;
- };
-
- gpio1: gpio@40049000 {
- compatible = "fsl,vf610-gpio";
- reg = <0x40049000 0x1000 0x400ff000 0x40>;
- interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-ranges = <&iomuxc 0 0 32>;
- };
-
- gpio2: gpio@4004a000 {
- compatible = "fsl,vf610-gpio";
- reg = <0x4004a000 0x1000 0x400ff040 0x40>;
- interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-ranges = <&iomuxc 0 32 32>;
- };
-
- gpio3: gpio@4004b000 {
- compatible = "fsl,vf610-gpio";
- reg = <0x4004b000 0x1000 0x400ff080 0x40>;
- interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-ranges = <&iomuxc 0 64 32>;
- };
-
- gpio4: gpio@4004c000 {
- compatible = "fsl,vf610-gpio";
- reg = <0x4004c000 0x1000 0x400ff0c0 0x40>;
- interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-ranges = <&iomuxc 0 96 32>;
- };
-
- gpio5: gpio@4004d000 {
- compatible = "fsl,vf610-gpio";
- reg = <0x4004d000 0x1000 0x400ff100 0x40>;
- interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-ranges = <&iomuxc 0 128 7>;
- };
-
- anatop: anatop@40050000 {
- compatible = "fsl,vf610-anatop", "syscon";
- reg = <0x40050000 0x400>;
- };
-
- usbphy0: usbphy@40050800 {
- compatible = "fsl,vf610-usbphy";
- reg = <0x40050800 0x400>;
- interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_USBPHY0>;
- fsl,anatop = <&anatop>;
- };
-
- usbphy1: usbphy@40050c00 {
- compatible = "fsl,vf610-usbphy";
- reg = <0x40050c00 0x400>;
- interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_USBPHY1>;
- fsl,anatop = <&anatop>;
- };
-
- i2c0: i2c@40066000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,vf610-i2c";
- reg = <0x40066000 0x1000>;
- interrupts =<0 71 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_I2C0>;
- clock-names = "ipg";
- dmas = <&edma0 0 50>,
- <&edma0 0 51>;
- dma-names = "rx","tx";
- status = "disabled";
- };
-
- clks: ccm@4006b000 {
- compatible = "fsl,vf610-ccm";
- reg = <0x4006b000 0x1000>;
- #clock-cells = <1>;
- };
-
- usbdev0: usb@40034000 {
- compatible = "fsl,vf610-usb", "fsl,imx27-usb";
- reg = <0x40034000 0x800>;
- interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_USBC0>;
- fsl,usbphy = <&usbphy0>;
- fsl,usbmisc = <&usbmisc0 0>;
- dr_mode = "peripheral";
- status = "disabled";
- };
-
- usbmisc0: usb@40034800 {
- #index-cells = <1>;
- compatible = "fsl,vf610-usbmisc";
- reg = <0x40034800 0x200>;
- clocks = <&clks VF610_CLK_USBC0>;
- };
- };
-
- aips1: aips-bus@40080000 {
- compatible = "fsl,aips-bus", "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x40080000 0x80000>;
- ranges;
-
- edma1: dma-controller@40098000 {
- #dma-cells = <2>;
- compatible = "fsl,vf610-edma";
- reg = <0x40098000 0x2000>,
- <0x400a1000 0x1000>,
- <0x400a2000 0x1000>;
- interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>,
- <0 11 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "edma-tx", "edma-err";
- dma-channels = <32>;
- clock-names = "dmamux0", "dmamux1";
- clocks = <&clks VF610_CLK_DMAMUX2>,
- <&clks VF610_CLK_DMAMUX3>;
- };
-
- uart4: serial@400a9000 {
- compatible = "fsl,vf610-lpuart";
- reg = <0x400a9000 0x1000>;
- interrupts = <0 65 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_UART4>;
- clock-names = "ipg";
- status = "disabled";
- };
-
- uart5: serial@400aa000 {
- compatible = "fsl,vf610-lpuart";
- reg = <0x400aa000 0x1000>;
- interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_UART5>;
- clock-names = "ipg";
- status = "disabled";
- };
-
- adc1: adc@400bb000 {
- compatible = "fsl,vf610-adc";
- reg = <0x400bb000 0x1000>;
- interrupts = <0 54 0x04>;
- clocks = <&clks VF610_CLK_ADC1>;
- clock-names = "adc";
- status = "disabled";
- };
-
- esdhc1: esdhc@400b2000 {
- compatible = "fsl,imx53-esdhc";
- reg = <0x400b2000 0x1000>;
- interrupts = <0 28 0x04>;
- clocks = <&clks VF610_CLK_IPG_BUS>,
- <&clks VF610_CLK_PLATFORM_BUS>,
- <&clks VF610_CLK_ESDHC1>;
- clock-names = "ipg", "ahb", "per";
- status = "disabled";
- };
-
- usbh1: usb@400b4000 {
- compatible = "fsl,vf610-usb", "fsl,imx27-usb";
- reg = <0x400b4000 0x800>;
- interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_USBC1>;
- fsl,usbphy = <&usbphy1>;
- fsl,usbmisc = <&usbmisc1 0>;
- dr_mode = "host";
- status = "disabled";
- };
-
- usbmisc1: usb@400b4800 {
- #index-cells = <1>;
- compatible = "fsl,vf610-usbmisc";
- reg = <0x400b4800 0x200>;
- clocks = <&clks VF610_CLK_USBC1>;
- };
-
- ftm: ftm@400b8000 {
- compatible = "fsl,ftm-timer";
- reg = <0x400b8000 0x1000 0x400b9000 0x1000>;
- interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "ftm-evt", "ftm-src",
- "ftm-evt-counter-en", "ftm-src-counter-en";
- clocks = <&clks VF610_CLK_FTM2>,
- <&clks VF610_CLK_FTM3>,
- <&clks VF610_CLK_FTM2_EXT_FIX_EN>,
- <&clks VF610_CLK_FTM3_EXT_FIX_EN>;
- status = "disabled";
- };
-
- fec0: ethernet@400d0000 {
- compatible = "fsl,mvf600-fec";
- reg = <0x400d0000 0x1000>;
- interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_ENET0>,
- <&clks VF610_CLK_ENET0>,
- <&clks VF610_CLK_ENET>;
- clock-names = "ipg", "ahb", "ptp";
- status = "disabled";
- };
-
- fec1: ethernet@400d1000 {
- compatible = "fsl,mvf600-fec";
- reg = <0x400d1000 0x1000>;
- interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_ENET1>,
- <&clks VF610_CLK_ENET1>,
- <&clks VF610_CLK_ENET>;
- clock-names = "ipg", "ahb", "ptp";
- status = "disabled";
- };
-
- can1: flexcan@400d4000 {
- compatible = "fsl,vf610-flexcan";
- reg = <0x400d4000 0x4000>;
- interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks VF610_CLK_FLEXCAN1>,
- <&clks VF610_CLK_FLEXCAN1>;
- clock-names = "ipg", "per";
- status = "disabled";
- };
+&a5_cpu {
+ next-level-cache = <&L2>;
+};
- };
+&aips0 {
+ L2: l2-cache@40006000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x40006000 0x1000>;
+ cache-unified;
+ cache-level = <2>;
+ arm,data-latency = <1 1 1>;
+ arm,tag-latency = <2 2 2>;
};
};
diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
new file mode 100644
index 000000000000..dfed92bd7bad
--- /dev/null
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "vf610-pinfunc.h"
+#include <dt-bindings/clock/vf610-clock.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ aliases {
+ can0 = &can0;
+ can1 = &can1;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ serial5 = &uart5;
+ gpio0 = &gpio0;
+ gpio1 = &gpio1;
+ gpio2 = &gpio2;
+ gpio3 = &gpio3;
+ gpio4 = &gpio4;
+ usbphy0 = &usbphy0;
+ usbphy1 = &usbphy1;
+ };
+
+ fxosc: fxosc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ };
+
+ sxosc: sxosc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ reboot: syscon-reboot {
+ compatible = "syscon-reboot";
+ regmap = <&src>;
+ offset = <0x0>;
+ mask = <0x1000>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ aips0: aips-bus@40000000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ mscm: mscm@40001000 {
+ compatible = "fsl,vf610-mscm";
+ reg = <0x40001000 0x1000>;
+ };
+
+ edma0: dma-controller@40018000 {
+ #dma-cells = <2>;
+ compatible = "fsl,vf610-edma";
+ reg = <0x40018000 0x2000>,
+ <0x40024000 0x1000>,
+ <0x40025000 0x1000>;
+ dma-channels = <32>;
+ clock-names = "dmamux0", "dmamux1";
+ clocks = <&clks VF610_CLK_DMAMUX0>,
+ <&clks VF610_CLK_DMAMUX1>;
+ status = "disabled";
+ };
+
+ sema4: semaphore-controller@4001d000 {
+ compatible = "fsl,vf610-sema4";
+ reg = <0x4001d000 0x1000>;
+ };
+
+ can0: flexcan@40020000 {
+ compatible = "fsl,vf610-flexcan";
+ reg = <0x40020000 0x4000>;
+ clocks = <&clks VF610_CLK_FLEXCAN0>,
+ <&clks VF610_CLK_FLEXCAN0>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ uart0: serial@40027000 {
+ compatible = "fsl,vf610-lpuart";
+ reg = <0x40027000 0x1000>;
+ clocks = <&clks VF610_CLK_UART0>;
+ clock-names = "ipg";
+ dmas = <&edma0 0 2>,
+ <&edma0 0 3>;
+ dma-names = "rx","tx";
+ status = "disabled";
+ };
+
+ uart1: serial@40028000 {
+ compatible = "fsl,vf610-lpuart";
+ reg = <0x40028000 0x1000>;
+ clocks = <&clks VF610_CLK_UART1>;
+ clock-names = "ipg";
+ dmas = <&edma0 0 4>,
+ <&edma0 0 5>;
+ dma-names = "rx","tx";
+ status = "disabled";
+ };
+
+ uart2: serial@40029000 {
+ compatible = "fsl,vf610-lpuart";
+ reg = <0x40029000 0x1000>;
+ clocks = <&clks VF610_CLK_UART2>;
+ clock-names = "ipg";
+ dmas = <&edma0 0 6>,
+ <&edma0 0 7>;
+ dma-names = "rx","tx";
+ status = "disabled";
+ };
+
+ uart3: serial@4002a000 {
+ compatible = "fsl,vf610-lpuart";
+ reg = <0x4002a000 0x1000>;
+ clocks = <&clks VF610_CLK_UART3>;
+ clock-names = "ipg";
+ dmas = <&edma0 0 8>,
+ <&edma0 0 9>;
+ dma-names = "rx","tx";
+ status = "disabled";
+ };
+
+ dspi0: dspi0@4002c000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,vf610-dspi";
+ reg = <0x4002c000 0x1000>;
+ clocks = <&clks VF610_CLK_DSPI0>;
+ clock-names = "dspi";
+ spi-num-chipselects = <5>;
+ status = "disabled";
+ };
+
+ dspi1: dspi1@4002d000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,vf610-dspi";
+ reg = <0x4002d000 0x1000>;
+ clocks = <&clks VF610_CLK_DSPI1>;
+ clock-names = "dspi";
+ spi-num-chipselects = <5>;
+ status = "disabled";
+ };
+
+ sai2: sai@40031000 {
+ compatible = "fsl,vf610-sai";
+ reg = <0x40031000 0x1000>;
+ clocks = <&clks VF610_CLK_SAI2>;
+ clock-names = "sai";
+ dma-names = "tx", "rx";
+ dmas = <&edma0 0 21>,
+ <&edma0 0 20>;
+ status = "disabled";
+ };
+
+ pit: pit@40037000 {
+ compatible = "fsl,vf610-pit";
+ reg = <0x40037000 0x1000>;
+ clocks = <&clks VF610_CLK_PIT>;
+ clock-names = "pit";
+ };
+
+ pwm0: pwm@40038000 {
+ compatible = "fsl,vf610-ftm-pwm";
+ #pwm-cells = <3>;
+ reg = <0x40038000 0x1000>;
+ clock-names = "ftm_sys", "ftm_ext",
+ "ftm_fix", "ftm_cnt_clk_en";
+ clocks = <&clks VF610_CLK_FTM0>,
+ <&clks VF610_CLK_FTM0_EXT_SEL>,
+ <&clks VF610_CLK_FTM0_FIX_SEL>,
+ <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
+ status = "disabled";
+ };
+
+ pwm1: pwm@40039000 {
+ compatible = "fsl,vf610-ftm-pwm";
+ #pwm-cells = <3>;
+ reg = <0x40039000 0x1000>;
+ clock-names = "ftm_sys", "ftm_ext",
+ "ftm_fix", "ftm_cnt_clk_en";
+ clocks = <&clks VF610_CLK_FTM1>,
+ <&clks VF610_CLK_FTM1_EXT_SEL>,
+ <&clks VF610_CLK_FTM1_FIX_SEL>,
+ <&clks VF610_CLK_FTM1_EXT_FIX_EN>;
+ status = "disabled";
+ };
+
+ adc0: adc@4003b000 {
+ compatible = "fsl,vf610-adc";
+ reg = <0x4003b000 0x1000>;
+ clocks = <&clks VF610_CLK_ADC0>;
+ clock-names = "adc";
+ status = "disabled";
+ fsl,adck-max-frequency = <30000000>, <40000000>,
+ <20000000>;
+ fsl,use-lpm;
+ #io-channel-cells = <1>;
+ };
+
+ tcon0: tcon@4003d000 {
+ compatible = "fsl,vf610-tcon";
+ reg = <0x4003d000 0x1000>;
+ clocks = <&clks VF610_CLK_TCON0>;
+ clock-names = "tcon";
+ status = "disabled";
+ };
+
+ wdoga5: wdog@4003e000 {
+ compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
+ reg = <0x4003e000 0x1000>;
+ clocks = <&clks VF610_CLK_WDT>;
+ clock-names = "wdog";
+ status = "disabled";
+ };
+
+ qspi0: quadspi@40044000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,vf610-qspi";
+ reg = <0x40044000 0x1000>;
+ clocks = <&clks VF610_CLK_QSPI0_EN>,
+ <&clks VF610_CLK_QSPI0>;
+ clock-names = "qspi_en", "qspi";
+ status = "disabled";
+ };
+
+ iomuxc: iomuxc@40048000 {
+ compatible = "fsl,vf610-iomuxc";
+ reg = <0x40048000 0x1000>;
+ #gpio-range-cells = <3>;
+ };
+
+ gpio0: gpio@40049000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x40049000 0x1000 0x400ff000 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 0 32>;
+ };
+
+ gpio1: gpio@4004a000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x4004a000 0x1000 0x400ff040 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 32 32>;
+ };
+
+ gpio2: gpio@4004b000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x4004b000 0x1000 0x400ff080 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 64 32>;
+ };
+
+ gpio3: gpio@4004c000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x4004c000 0x1000 0x400ff0c0 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 96 32>;
+ };
+
+ gpio4: gpio@4004d000 {
+ compatible = "fsl,vf610-gpio";
+ reg = <0x4004d000 0x1000 0x400ff100 0x40>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&iomuxc 0 128 7>;
+ };
+
+ anatop: anatop@40050000 {
+ compatible = "fsl,vf610-anatop", "syscon";
+ reg = <0x40050000 0x400>;
+ };
+
+ usbphy0: usbphy@40050800 {
+ compatible = "fsl,vf610-usbphy";
+ reg = <0x40050800 0x400>;
+ clocks = <&clks VF610_CLK_USBPHY0>;
+ fsl,anatop = <&anatop>;
+ status = "disabled";
+ };
+
+ usbphy1: usbphy@40050c00 {
+ compatible = "fsl,vf610-usbphy";
+ reg = <0x40050c00 0x400>;
+ clocks = <&clks VF610_CLK_USBPHY1>;
+ fsl,anatop = <&anatop>;
+ status = "disabled";
+ };
+
+ dcu0: dcu@40058000 {
+ compatible = "fsl,vf610-dcu";
+ reg = <0x40058000 0x1200>;
+ clocks = <&clks VF610_CLK_DCU0>;
+ clock-names = "dcu";
+ tcon-controller = <&tcon0>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@40066000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,vf610-i2c";
+ reg = <0x40066000 0x1000>;
+ clocks = <&clks VF610_CLK_I2C0>;
+ clock-names = "ipg";
+ dmas = <&edma0 0 50>,
+ <&edma0 0 51>;
+ dma-names = "rx","tx";
+ status = "disabled";
+ };
+
+ clks: ccm@4006b000 {
+ compatible = "fsl,vf610-ccm";
+ reg = <0x4006b000 0x1000>;
+ clocks = <&sxosc>, <&fxosc>;
+ clock-names = "sxosc", "fxosc";
+ #clock-cells = <1>;
+ };
+
+ usbdev0: usb@40034000 {
+ compatible = "fsl,vf610-usb", "fsl,imx27-usb";
+ reg = <0x40034000 0x800>;
+ clocks = <&clks VF610_CLK_USBC0>;
+ fsl,usbphy = <&usbphy0>;
+ fsl,usbmisc = <&usbmisc0 0>;
+ dr_mode = "peripheral";
+ status = "disabled";
+ };
+
+ usbmisc0: usb@40034800 {
+ #index-cells = <1>;
+ compatible = "fsl,vf610-usbmisc";
+ reg = <0x40034800 0x200>;
+ clocks = <&clks VF610_CLK_USBC0>;
+ status = "disabled";
+ };
+
+ gpc: gpc@4006c000 {
+ compatible = "fsl,vf610-gpc";
+ reg = <0x4006c000 0x1000>;
+ };
+
+ src: src@4006e000 {
+ compatible = "fsl,vf610-src", "syscon";
+ reg = <0x4006e000 0x1000>;
+ };
+ };
+
+ aips1: aips-bus@40080000 {
+ compatible = "fsl,aips-bus", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ edma1: dma-controller@40098000 {
+ #dma-cells = <2>;
+ compatible = "fsl,vf610-edma";
+ reg = <0x40098000 0x2000>,
+ <0x400a1000 0x1000>,
+ <0x400a2000 0x1000>;
+ dma-channels = <32>;
+ clock-names = "dmamux0", "dmamux1";
+ clocks = <&clks VF610_CLK_DMAMUX2>,
+ <&clks VF610_CLK_DMAMUX3>;
+ status = "disabled";
+ };
+
+ snvs0: snvs@400a7000 {
+ compatible = "fsl,sec-v4.0-mon", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x400a7000 0x2000>;
+
+ snvsrtc: snvs-rtc-lp@34 {
+ compatible = "fsl,sec-v4.0-mon-rtc-lp";
+ reg = <0x34 0x58>;
+ clocks = <&clks VF610_CLK_SNVS>;
+ clock-names = "snvs-rtc";
+ };
+ };
+
+ uart4: serial@400a9000 {
+ compatible = "fsl,vf610-lpuart";
+ reg = <0x400a9000 0x1000>;
+ clocks = <&clks VF610_CLK_UART4>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ uart5: serial@400aa000 {
+ compatible = "fsl,vf610-lpuart";
+ reg = <0x400aa000 0x1000>;
+ clocks = <&clks VF610_CLK_UART5>;
+ clock-names = "ipg";
+ status = "disabled";
+ };
+
+ adc1: adc@400bb000 {
+ compatible = "fsl,vf610-adc";
+ reg = <0x400bb000 0x1000>;
+ clocks = <&clks VF610_CLK_ADC1>;
+ clock-names = "adc";
+ status = "disabled";
+ fsl,adck-max-frequency = <30000000>, <40000000>,
+ <20000000>;
+ fsl,use-lpm;
+ #io-channel-cells = <1>;
+ };
+
+ esdhc1: esdhc@400b2000 {
+ compatible = "fsl,imx53-esdhc";
+ reg = <0x400b2000 0x1000>;
+ clocks = <&clks VF610_CLK_IPG_BUS>,
+ <&clks VF610_CLK_PLATFORM_BUS>,
+ <&clks VF610_CLK_ESDHC1>;
+ clock-names = "ipg", "ahb", "per";
+ status = "disabled";
+ };
+
+ usbh1: usb@400b4000 {
+ compatible = "fsl,vf610-usb", "fsl,imx27-usb";
+ reg = <0x400b4000 0x800>;
+ clocks = <&clks VF610_CLK_USBC1>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+ dr_mode = "host";
+ status = "disabled";
+ };
+
+ usbmisc1: usb@400b4800 {
+ #index-cells = <1>;
+ compatible = "fsl,vf610-usbmisc";
+ reg = <0x400b4800 0x200>;
+ clocks = <&clks VF610_CLK_USBC1>;
+ status = "disabled";
+ };
+
+ ftm: ftm@400b8000 {
+ compatible = "fsl,ftm-timer";
+ reg = <0x400b8000 0x1000 0x400b9000 0x1000>;
+ clock-names = "ftm-evt", "ftm-src",
+ "ftm-evt-counter-en", "ftm-src-counter-en";
+ clocks = <&clks VF610_CLK_FTM2>,
+ <&clks VF610_CLK_FTM3>,
+ <&clks VF610_CLK_FTM2_EXT_FIX_EN>,
+ <&clks VF610_CLK_FTM3_EXT_FIX_EN>;
+ status = "disabled";
+ };
+
+ fec0: ethernet@400d0000 {
+ compatible = "fsl,mvf600-fec";
+ reg = <0x400d0000 0x1000>;
+ clocks = <&clks VF610_CLK_ENET0>,
+ <&clks VF610_CLK_ENET0>,
+ <&clks VF610_CLK_ENET>;
+ clock-names = "ipg", "ahb", "ptp";
+ status = "disabled";
+ };
+
+ fec1: ethernet@400d1000 {
+ compatible = "fsl,mvf600-fec";
+ reg = <0x400d1000 0x1000>;
+ clocks = <&clks VF610_CLK_ENET1>,
+ <&clks VF610_CLK_ENET1>,
+ <&clks VF610_CLK_ENET>;
+ clock-names = "ipg", "ahb", "ptp";
+ status = "disabled";
+ };
+
+ can1: flexcan@400d4000 {
+ compatible = "fsl,vf610-flexcan";
+ reg = <0x400d4000 0x4000>;
+ clocks = <&clks VF610_CLK_FLEXCAN1>,
+ <&clks VF610_CLK_FLEXCAN1>;
+ clock-names = "ipg", "per";
+ status = "disabled";
+ };
+
+ nfc: nand@400e0000 {
+ compatible = "fsl,vf610-nfc";
+ reg = <0x400e0000 0x4000>;
+ clocks = <&clks VF610_CLK_NFC>;
+ clock-names = "nfc";
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm/configs/colibri_vf_defconfig b/arch/arm/configs/colibri_vf_defconfig
new file mode 100644
index 000000000000..c6c9056ac959
--- /dev/null
+++ b/arch/arm/configs/colibri_vf_defconfig
@@ -0,0 +1,243 @@
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_GZIP is not set
+CONFIG_RD_LZO=y
+CONFIG_RD_LZ4=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_VF610=y
+CONFIG_SWP_EMULATE=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+CONFIG_CMA=y
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_GOV_LADDER is not set
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_CAN=y
+CONFIG_CAN_FLEXCAN=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_DMA_CMA=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSL_NFC=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MICREL_PHY=y
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_EGALAX=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_FSL_DSPI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_STMPE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+# CONFIG_RC_MAP is not set
+# CONFIG_RC_DECODERS is not set
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_FB=y
+CONFIG_FB_FSL_DCU=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_GPIO=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_SERIAL=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
+CONFIG_USB_ETH=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+# CONFIG_MX3_IPU is not set
+CONFIG_FSL_EDMA=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_IIO=y
+CONFIG_IIO_TRIGGER=y
+CONFIG_VF610_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_FSL_FTM=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_OVERLAY_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 6790f1b3f3a1..e92807572517 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -163,7 +163,14 @@ CONFIG_SPI_IMX=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_MC9S08DZ60=y
CONFIG_GPIO_STMPE=y
-# CONFIG_HWMON is not set
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_IMX=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_IMX2_WDT=y
CONFIG_MFD_DA9052_I2C=y
@@ -192,7 +199,6 @@ CONFIG_SOC_CAMERA_OV2640=y
CONFIG_IMX_IPUV3_CORE=y
CONFIG_DRM=y
CONFIG_DRM_PANEL_SIMPLE=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_L4F00242T03=y
CONFIG_LCD_PLATFORM=y
@@ -211,6 +217,7 @@ CONFIG_SND_SOC_IMX_WM8962=y
CONFIG_SND_SOC_IMX_SGTL5000=y
CONFIG_SND_SOC_IMX_SPDIF=y
CONFIG_SND_SOC_IMX_MC13783=y
+CONFIG_SND_SOC_TLV320AIC3X=y
CONFIG_SND_SIMPLE_CARD=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
@@ -239,6 +246,7 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_ISL1208=y
CONFIG_RTC_DRV_PCF8563=y
CONFIG_RTC_DRV_MC13XXX=y
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 11b2957f792b..286c7ffd1006 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -58,6 +58,9 @@ config HAVE_IMX_SRC
def_bool y if SMP
select ARCH_HAS_RESET_CONTROLLER
+config HAVE_VF610_MSCM
+ bool
+
config IMX_HAVE_IOMUX_V1
bool
@@ -631,14 +634,46 @@ config SOC_IMX6SX
config SOC_VF610
bool "Vybrid Family VF610 support"
+ select HAVE_VF610_MSCM
select ARM_GIC
select PINCTRL_VF610
- select VF_PIT_TIMER
+ select HAVE_IMX_GPC
select PL310_ERRATA_769419 if CACHE_L2X0
+ select HAVE_NAND_FSL_NFC
help
This enable support for Freescale Vybrid VF610 processor.
+choice
+ prompt "Clocksource for scheduler clock"
+ depends on SOC_VF610
+ default VF_USE_ARM_GLOBAL_TIMER
+
+ config VF_USE_ARM_GLOBAL_TIMER
+ bool "Use ARM Global Timer"
+ select ARM_GLOBAL_TIMER
+ select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+ help
+ Use the ARM Global Timer as clocksource
+
+ config VF_USE_PIT_TIMER
+ bool "Use PIT timer"
+ select VF_PIT_TIMER
+ help
+ Use SoC Periodic Interrupt Timer (PIT) as clocksource
+
+endchoice
+
+config SOC_LS1021A
+ bool "Freescale LS1021A support"
+ select ARM_GIC
+ select HAVE_ARM_ARCH_TIMER
+ select PCI_DOMAINS if PCI
+ select ZONE_DMA if ARM_LPAE
+
+ help
+ This enable support for Freescale LS1021A processor.
+
endif
source "arch/arm/mach-imx/devices/Kconfig"
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 6e4fcd8339cd..777d1ca2cbf6 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
imx5-pm-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
clk-pfd.o clk-busy.o clk.o \
@@ -89,7 +89,7 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
-ifdef CONFIG_SOC_IMX6
+ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
@@ -103,11 +103,15 @@ AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
endif
obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
+obj-$(CONFIG_SOC_VF610) += pm-vf610.o
obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
-obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
+obj-$(CONFIG_HAVE_VF610_MSCM) += mscm-vf610.o
+obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o vf610_sema4.o
+
+obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o
obj-y += devices/
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
index 8259a625a920..7f262fe4ba77 100644
--- a/arch/arm/mach-imx/anatop.c
+++ b/arch/arm/mach-imx/anatop.c
@@ -30,8 +30,11 @@
#define ANADIG_DIGPROG_IMX6SL 0x280
#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
+#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x8
#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000
#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000
+/* Below MISC0_DISCON_HIGH_SNVS is only for i.MX6SL */
+#define BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS 0x2000
#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000
#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000
@@ -56,16 +59,43 @@ static void imx_anatop_enable_fet_odrive(bool enable)
BM_ANADIG_REG_CORE_FET_ODRIVE);
}
+static inline void imx_anatop_enable_2p5_pulldown(bool enable)
+{
+ regmap_write(anatop, ANADIG_REG_2P5 + (enable ? REG_SET : REG_CLR),
+ BM_ANADIG_REG_2P5_ENABLE_PULLDOWN);
+}
+
+static inline void imx_anatop_disconnect_high_snvs(bool enable)
+{
+ regmap_write(anatop, ANADIG_ANA_MISC0 + (enable ? REG_SET : REG_CLR),
+ BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS);
+}
+
void imx_anatop_pre_suspend(void)
{
- imx_anatop_enable_weak2p5(true);
+ if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+ imx_anatop_enable_2p5_pulldown(true);
+ else
+ imx_anatop_enable_weak2p5(true);
+
imx_anatop_enable_fet_odrive(true);
+
+ if (cpu_is_imx6sl())
+ imx_anatop_disconnect_high_snvs(true);
}
void imx_anatop_post_resume(void)
{
+ if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+ imx_anatop_enable_2p5_pulldown(false);
+ else
+ imx_anatop_enable_weak2p5(false);
+
imx_anatop_enable_fet_odrive(false);
- imx_anatop_enable_weak2p5(false);
+
+ if (cpu_is_imx6sl())
+ imx_anatop_disconnect_high_snvs(false);
+
}
static void imx_anatop_usb_chrg_detect_disable(void)
diff --git a/arch/arm/mach-imx/clk-cpu.c b/arch/arm/mach-imx/clk-cpu.c
new file mode 100644
index 000000000000..aa1c345e2a19
--- /dev/null
+++ b/arch/arm/mach-imx/clk-cpu.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
+ *
+ * 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.
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+
+struct clk_cpu {
+ struct clk_hw hw;
+ struct clk *div;
+ struct clk *mux;
+ struct clk *pll;
+ struct clk *step;
+};
+
+static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw)
+{
+ return container_of(hw, struct clk_cpu, hw);
+}
+
+static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_cpu *cpu = to_clk_cpu(hw);
+
+ return clk_get_rate(cpu->div);
+}
+
+static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_cpu *cpu = to_clk_cpu(hw);
+
+ return clk_round_rate(cpu->pll, rate);
+}
+
+static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_cpu *cpu = to_clk_cpu(hw);
+ int ret;
+
+ /* switch to PLL bypass clock */
+ ret = clk_set_parent(cpu->mux, cpu->step);
+ if (ret)
+ return ret;
+
+ /* reprogram PLL */
+ ret = clk_set_rate(cpu->pll, rate);
+ if (ret) {
+ clk_set_parent(cpu->mux, cpu->pll);
+ return ret;
+ }
+ /* switch back to PLL clock */
+ clk_set_parent(cpu->mux, cpu->pll);
+
+ /* Ensure the divider is what we expect */
+ clk_set_rate(cpu->div, rate);
+
+ return 0;
+}
+
+static const struct clk_ops clk_cpu_ops = {
+ .recalc_rate = clk_cpu_recalc_rate,
+ .round_rate = clk_cpu_round_rate,
+ .set_rate = clk_cpu_set_rate,
+};
+
+struct clk *imx_clk_cpu(const char *name, const char *parent_name,
+ struct clk *div, struct clk *mux, struct clk *pll,
+ struct clk *step)
+{
+ struct clk_cpu *cpu;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ cpu = kzalloc(sizeof(*cpu), GFP_KERNEL);
+ if (!cpu)
+ return ERR_PTR(-ENOMEM);
+
+ cpu->div = div;
+ cpu->mux = mux;
+ cpu->pll = pll;
+ cpu->step = step;
+
+ init.name = name;
+ init.ops = &clk_cpu_ops;
+ init.flags = 0;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ cpu->hw.init = &init;
+
+ clk = clk_register(NULL, &cpu->hw);
+ if (IS_ERR(clk))
+ kfree(cpu);
+
+ return clk;
+}
diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
index 5a75cdc81891..4145325ebddc 100644
--- a/arch/arm/mach-imx/clk-gate2.c
+++ b/arch/arm/mach-imx/clk-gate2.c
@@ -31,6 +31,7 @@ struct clk_gate2 {
struct clk_hw hw;
void __iomem *reg;
u8 bit_idx;
+ u8 cgr_val;
u8 flags;
spinlock_t *lock;
unsigned int *share_count;
@@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_hw *hw)
goto out;
reg = readl(gate->reg);
- reg |= 3 << gate->bit_idx;
+ reg &= ~(3 << gate->bit_idx);
+ reg |= gate->cgr_val << gate->bit_idx;
writel(reg, gate->reg);
out:
@@ -110,7 +112,7 @@ static struct clk_ops clk_gate2_ops = {
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
- void __iomem *reg, u8 bit_idx,
+ void __iomem *reg, u8 bit_idx, u8 cgr_val,
u8 clk_gate2_flags, spinlock_t *lock,
unsigned int *share_count)
{
@@ -125,6 +127,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
/* struct clk_gate2 assignments */
gate->reg = reg;
gate->bit_idx = bit_idx;
+ gate->cgr_val = cgr_val;
gate->flags = clk_gate2_flags;
gate->lock = lock;
gate->share_count = share_count;
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 72d65214223e..0f7e536147cb 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -125,6 +125,8 @@ static const char *mx53_spdif_xtal_sel[] = { "osc", "ckih", "ckih2", "pll4_sw",
static const char *spdif_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "spdif_xtal_sel", };
static const char *spdif0_com_sel[] = { "spdif0_podf", "ssi1_root_gate", };
static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", };
+static const char *step_sels[] = { "lp_apm", };
+static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
static struct clk *clk[IMX5_CLK_END];
static struct clk_onecell_data clk_data;
@@ -193,7 +195,9 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
clk[IMX5_CLK_USB_PHY_PODF] = imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
clk[IMX5_CLK_USB_PHY_SEL] = imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
- clk[IMX5_CLK_CPU_PODF] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
+ clk[IMX5_CLK_STEP_SEL] = imx_clk_mux("step_sel", MXC_CCM_CCSR, 7, 2, step_sels, ARRAY_SIZE(step_sels));
+ clk[IMX5_CLK_CPU_PODF_SEL] = imx_clk_mux("cpu_podf_sel", MXC_CCM_CCSR, 2, 1, cpu_podf_sels, ARRAY_SIZE(cpu_podf_sels));
+ clk[IMX5_CLK_CPU_PODF] = imx_clk_divider("cpu_podf", "cpu_podf_sel", MXC_CCM_CACRR, 0, 3);
clk[IMX5_CLK_DI_PRED] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
clk[IMX5_CLK_IIM_GATE] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
clk[IMX5_CLK_UART1_IPG_GATE] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
@@ -537,6 +541,11 @@ static void __init mx53_clocks_init(struct device_node *np)
clk[IMX5_CLK_CKO2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
clk[IMX5_CLK_SPDIF_XTAL_SEL] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel));
+ clk[IMX5_CLK_ARM] = imx_clk_cpu("arm", "cpu_podf",
+ clk[IMX5_CLK_CPU_PODF],
+ clk[IMX5_CLK_CPU_PODF_SEL],
+ clk[IMX5_CLK_PLL1_SW],
+ clk[IMX5_CLK_STEP_SEL]);
imx_check_clocks(clk, ARRAY_SIZE(clk));
@@ -551,6 +560,9 @@ static void __init mx53_clocks_init(struct device_node *np)
/* move can bus clk to 24MHz */
clk_set_parent(clk[IMX5_CLK_CAN_SEL], clk[IMX5_CLK_LP_APM]);
+ /* make sure step clock is running from 24MHz */
+ clk_set_parent(clk[IMX5_CLK_STEP_SEL], clk[IMX5_CLK_LP_APM]);
+
clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
imx_print_silicon_rev("i.MX53", mx53_revision());
clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 2daef619d053..5951660d1bd2 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -144,7 +144,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
post_div_table[1].div = 1;
post_div_table[2].div = 1;
video_div_table[1].div = 1;
- video_div_table[3].div = 1;
+ video_div_table[2].div = 1;
}
clk[IMX6QDL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
index 57de74da0acf..641ebc508920 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -31,6 +31,7 @@
* @base: base address of PLL registers
* @powerup_set: set POWER bit to power up the PLL
* @div_mask: mask of divider bits
+ * @div_shift: shift of divider bits
*
* IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3
* is actually a multiplier, and always sits at bit 0.
@@ -40,6 +41,7 @@ struct clk_pllv3 {
void __iomem *base;
bool powerup_set;
u32 div_mask;
+ u32 div_shift;
};
#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
@@ -69,7 +71,6 @@ static int clk_pllv3_prepare(struct clk_hw *hw)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val;
- int ret;
val = readl_relaxed(pll->base);
if (pll->powerup_set)
@@ -78,11 +79,7 @@ static int clk_pllv3_prepare(struct clk_hw *hw)
val &= ~BM_PLL_POWER;
writel_relaxed(val, pll->base);
- ret = clk_pllv3_wait_lock(pll);
- if (ret)
- return ret;
-
- return 0;
+ return clk_pllv3_wait_lock(pll);
}
static void clk_pllv3_unprepare(struct clk_hw *hw)
@@ -102,7 +99,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pllv3 *pll = to_clk_pllv3(hw);
- u32 div = readl_relaxed(pll->base) & pll->div_mask;
+ u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask;
return (div == 1) ? parent_rate * 22 : parent_rate * 20;
}
@@ -130,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
val = readl_relaxed(pll->base);
- val &= ~pll->div_mask;
- val |= div;
+ val &= ~(pll->div_mask << pll->div_shift);
+ val |= (div << pll->div_shift);
writel_relaxed(val, pll->base);
return clk_pllv3_wait_lock(pll);
@@ -300,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
case IMX_PLLV3_SYS:
ops = &clk_pllv3_sys_ops;
break;
+ case IMX_PLLV3_USB_VF610:
+ pll->div_shift = 1;
case IMX_PLLV3_USB:
ops = &clk_pllv3_ops;
pll->powerup_set = true;
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
index 409637254594..9fc721acf39d 100644
--- a/arch/arm/mach-imx/clk-vf610.c
+++ b/arch/arm/mach-imx/clk-vf610.c
@@ -13,6 +13,7 @@
#include <dt-bindings/clock/vf610-clock.h>
#include "clk.h"
+#include "common.h"
#define CCM_CCR (ccm_base + 0x00)
#define CCM_CSR (ccm_base + 0x04)
@@ -118,6 +119,18 @@ static struct clk_onecell_data clk_data;
static unsigned int const clks_init_on[] __initconst = {
VF610_CLK_SYS_BUS,
VF610_CLK_DDR_SEL,
+ VF610_CLK_DDRMC,
+};
+
+static struct clk * __init vf610_get_fixed_clock(
+ struct device_node *ccm_node, const char *name)
+{
+ struct clk *clk = of_clk_get_by_name(ccm_node, name);
+
+ /* Backward compatibility if device tree is missing clks assignments */
+ if (IS_ERR(clk))
+ clk = imx_obtain_fixed_clock(name, 0);
+ return clk;
};
static void __init vf610_clocks_init(struct device_node *ccm_node)
@@ -130,13 +143,13 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_SIRC_32K] = imx_clk_fixed("sirc_32k", 32000);
clk[VF610_CLK_FIRC] = imx_clk_fixed("firc", 24000000);
- clk[VF610_CLK_SXOSC] = imx_obtain_fixed_clock("sxosc", 0);
- clk[VF610_CLK_FXOSC] = imx_obtain_fixed_clock("fxosc", 0);
- clk[VF610_CLK_AUDIO_EXT] = imx_obtain_fixed_clock("audio_ext", 0);
- clk[VF610_CLK_ENET_EXT] = imx_obtain_fixed_clock("enet_ext", 0);
+ clk[VF610_CLK_SXOSC] = vf610_get_fixed_clock(ccm_node, "sxosc");
+ clk[VF610_CLK_FXOSC] = vf610_get_fixed_clock(ccm_node, "fxosc");
+ clk[VF610_CLK_AUDIO_EXT] = vf610_get_fixed_clock(ccm_node, "audio_ext");
+ clk[VF610_CLK_ENET_EXT] = vf610_get_fixed_clock(ccm_node, "enet_ext");
/* Clock source from external clock via LVDs PAD */
- clk[VF610_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0);
+ clk[VF610_CLK_ANACLK1] = vf610_get_fixed_clock(ccm_node, "anaclk1");
clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half", "fxosc", 1, 2);
@@ -148,6 +161,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
ccm_base = of_iomap(np, 0);
BUG_ON(!ccm_base);
+ vf610_pm_set_ccm_base(ccm_base);
+
clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel", CCM_CCSR, 4, 1, slow_sels, ARRAY_SIZE(slow_sels));
clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel", CCM_CCSR, 5, 1, fast_sels, ARRAY_SIZE(fast_sels));
@@ -161,11 +176,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
- clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1);
+ clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2);
clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f);
- clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1);
+ clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2);
clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
@@ -221,6 +236,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock);
clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1);
+ clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2);
+
clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6);
clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6);
@@ -252,10 +269,12 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(7));
- clk[VF610_CLK_UART0] = imx_clk_gate2("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7));
- clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8));
- clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9));
- clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10));
+ clk[VF610_CLK_UART0] = imx_clk_gate2_cgr("uart0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(7), 0x2);
+ clk[VF610_CLK_UART1] = imx_clk_gate2_cgr("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8), 0x2);
+ clk[VF610_CLK_UART2] = imx_clk_gate2_cgr("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9), 0x2);
+ clk[VF610_CLK_UART3] = imx_clk_gate2_cgr("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10), 0x2);
+ clk[VF610_CLK_UART4] = imx_clk_gate2_cgr("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9), 0x2);
+ clk[VF610_CLK_UART5] = imx_clk_gate2_cgr("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10), 0x2);
clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6));
clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7));
@@ -311,6 +330,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3);
clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8));
+ clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13));
+
clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4);
clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30);
clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en", CCM_CSCDR2, 24, 4);
@@ -368,6 +389,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(5));
clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
+ clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
imx_check_clocks(clk, ARRAY_SIZE(clk));
@@ -386,6 +408,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk_set_parent(clk[VF610_CLK_SAI2_SEL], clk[VF610_CLK_AUDIO_EXT]);
clk_set_parent(clk[VF610_CLK_SAI3_SEL], clk[VF610_CLK_AUDIO_EXT]);
+ clk_set_parent(clk[VF610_CLK_DCU0_SEL], clk[VF610_CLK_PLL1_PFD2]);
+
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clk[clks_init_on[i]]);
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 4cdf8b6a74e8..8aec27129ec7 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -20,6 +20,7 @@ enum imx_pllv3_type {
IMX_PLLV3_GENERIC,
IMX_PLLV3_SYS,
IMX_PLLV3_USB,
+ IMX_PLLV3_USB_VF610,
IMX_PLLV3_AV,
IMX_PLLV3_ENET,
};
@@ -29,7 +30,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
struct clk *clk_register_gate2(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
- void __iomem *reg, u8 bit_idx,
+ void __iomem *reg, u8 bit_idx, u8 cgr_val,
u8 clk_gate_flags, spinlock_t *lock,
unsigned int *share_count);
@@ -43,7 +44,7 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
- shift, 0, &imx_ccm_lock, NULL);
+ shift, 0x3, 0, &imx_ccm_lock, NULL);
}
static inline struct clk *imx_clk_gate2_shared(const char *name,
@@ -51,7 +52,14 @@ static inline struct clk *imx_clk_gate2_shared(const char *name,
unsigned int *share_count)
{
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
- shift, 0, &imx_ccm_lock, share_count);
+ shift, 0x3, 0, &imx_ccm_lock, share_count);
+}
+
+static inline struct clk *imx_clk_gate2_cgr(const char *name,
+ const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
+{
+ return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+ shift, cgr_val, 0, &imx_ccm_lock, NULL);
}
struct clk *imx_clk_pfd(const char *name, const char *parent_name,
@@ -131,4 +139,8 @@ static inline struct clk *imx_clk_fixed_factor(const char *name,
CLK_SET_RATE_PARENT, mult, div);
}
+struct clk *imx_clk_cpu(const char *name, const char *parent_name,
+ struct clk *div, struct clk *mux, struct clk *pll,
+ struct clk *step);
+
#endif
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 1dabf435c592..58b59643f868 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -61,7 +61,6 @@ struct platform_device *mxc_register_gpio(char *name, int id,
void mxc_set_cpu_type(unsigned int type);
void mxc_restart(enum reboot_mode, const char *);
void mxc_arch_reset_init(void __iomem *);
-void mxc_arch_reset_init_dt(void);
int mx51_revision(void);
int mx53_revision(void);
void imx_set_aips(void __iomem *);
@@ -80,6 +79,13 @@ enum mxc_cpu_pwr_mode {
STOP_POWER_OFF, /* STOP + SRPG */
};
+enum vf610_cpu_pwr_mode {
+ VF610_RUN,
+ VF610_LP_RUN,
+ VF610_STOP,
+ VF610_LP_STOP,
+};
+
enum mx3_cpu_pwr_mode {
MX3_RUN,
MX3_WAIT,
@@ -103,7 +109,9 @@ static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
#endif
void imx_src_init(void);
-void imx_gpc_init(void);
+void imx6_gpc_init(void);
+void vf610_gpc_init(void);
+void vf610_mscm_init(void);
void imx_gpc_pre_suspend(bool arm_power_off);
void imx_gpc_post_resume(void);
void imx_gpc_mask_all(void);
@@ -116,6 +124,7 @@ void imx_anatop_post_resume(void);
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
void imx6q_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
+int imx_mmdc_get_ddr_type(void);
void imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);
@@ -123,6 +132,7 @@ int imx_cpu_kill(unsigned int cpu);
#ifdef CONFIG_SUSPEND
void v7_cpu_resume(void);
void imx6_suspend(void __iomem *ocram_vbase);
+void vf610_suspend(void);
#else
static inline void v7_cpu_resume(void) {}
static inline void imx6_suspend(void __iomem *ocram_vbase) {}
@@ -133,6 +143,8 @@ void imx6dl_pm_init(void);
void imx6sl_pm_init(void);
void imx6sx_pm_init(void);
void imx6q_pm_set_ccm_base(void __iomem *base);
+void vf610_pm_init(void);
+void vf610_pm_set_ccm_base(void __iomem *base);
#ifdef CONFIG_PM
void imx51_pm_init(void);
@@ -157,5 +169,6 @@ static inline void imx_init_l2cache(void) {}
#endif
extern struct smp_operations imx_smp_ops;
+extern struct smp_operations ls1021a_smp_ops;
#endif
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 82ea74e68482..017f40a8d04a 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -18,52 +18,54 @@
#include <linux/irqchip/arm-gic.h>
#include "common.h"
-#define GPC_IMR1 0x008
+#define IMX6_GPC_IMR1 0x008
+#define VF610_GPC_IMR1 0x044
#define GPC_PGC_CPU_PDN 0x2a0
#define IMR_NUM 4
static void __iomem *gpc_base;
+static void __iomem *gpc_imr_base;
+static bool has_cpu_pdn;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
void imx_gpc_pre_suspend(bool arm_power_off)
{
- void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
/* Tell GPC to power off ARM core when suspend */
- if (arm_power_off)
+ if (arm_power_off && has_cpu_pdn)
writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
for (i = 0; i < IMR_NUM; i++) {
- gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
- writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
+ gpc_saved_imrs[i] = readl_relaxed(gpc_imr_base + i * 4);
+ writel_relaxed(~gpc_wake_irqs[i], gpc_imr_base + i * 4);
}
}
void imx_gpc_post_resume(void)
{
- void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
/* Keep ARM core powered on for other low-power modes */
- writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+ if (has_cpu_pdn)
+ writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
for (i = 0; i < IMR_NUM; i++)
- writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+ writel_relaxed(gpc_saved_imrs[i], gpc_imr_base + i * 4);
}
static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
{
- unsigned int idx = d->irq / 32 - 1;
+ unsigned int idx = d->hwirq / 32 - 1;
u32 mask;
/* Sanity check for SPI irq */
- if (d->irq < 32)
+ if (d->hwirq < 32)
return -EINVAL;
- mask = 1 << d->irq % 32;
+ mask = 1 << d->hwirq % 32;
gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
gpc_wake_irqs[idx] & ~mask;
@@ -72,23 +74,21 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
void imx_gpc_mask_all(void)
{
- void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
for (i = 0; i < IMR_NUM; i++) {
- gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
- writel_relaxed(~0, reg_imr1 + i * 4);
+ gpc_saved_imrs[i] = readl_relaxed(gpc_imr_base + i * 4);
+ writel_relaxed(~0, gpc_imr_base + i * 4);
}
}
void imx_gpc_restore_all(void)
{
- void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
for (i = 0; i < IMR_NUM; i++)
- writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+ writel_relaxed(gpc_saved_imrs[i], gpc_imr_base + i * 4);
}
void imx_gpc_irq_unmask(struct irq_data *d)
@@ -97,12 +97,12 @@ void imx_gpc_irq_unmask(struct irq_data *d)
u32 val;
/* Sanity check for SPI irq */
- if (d->irq < 32)
+ if (d->hwirq < 32)
return;
- reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+ reg = gpc_imr_base + (d->hwirq / 32 - 1) * 4;
val = readl_relaxed(reg);
- val &= ~(1 << d->irq % 32);
+ val &= ~(1 << d->hwirq % 32);
writel_relaxed(val, reg);
}
@@ -112,30 +112,51 @@ void imx_gpc_irq_mask(struct irq_data *d)
u32 val;
/* Sanity check for SPI irq */
- if (d->irq < 32)
+ if (d->hwirq < 32)
return;
- reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+ reg = gpc_imr_base + (d->hwirq / 32 - 1) * 4;
val = readl_relaxed(reg);
- val |= 1 << (d->irq % 32);
+ val |= 1 << (d->hwirq % 32);
writel_relaxed(val, reg);
}
-void __init imx_gpc_init(void)
+static void __init imx_gpc_init(void)
{
- struct device_node *np;
int i;
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
- gpc_base = of_iomap(np, 0);
WARN_ON(!gpc_base);
/* Initially mask all interrupts */
for (i = 0; i < IMR_NUM; i++)
- writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
+ writel_relaxed(~0, gpc_imr_base + i * 4);
/* Register GPC as the secondary interrupt controller behind GIC */
gic_arch_extn.irq_mask = imx_gpc_irq_mask;
gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
}
+
+void __init imx6_gpc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+ gpc_base = of_iomap(np, 0);
+ gpc_imr_base = gpc_base + IMX6_GPC_IMR1;
+ has_cpu_pdn = true;
+
+ imx_gpc_init();
+}
+
+void __init vf610_gpc_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,vf610-gpc");
+ gpc_base = of_iomap(np, 0);
+ gpc_imr_base = gpc_base + VF610_GPC_IMR1;
+ has_cpu_pdn = false;
+
+ imx_gpc_init();
+}
diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c
index cf8032bae277..25defbdb06c4 100644
--- a/arch/arm/mach-imx/imx25-dt.c
+++ b/arch/arm/mach-imx/imx25-dt.c
@@ -17,13 +17,6 @@
#include "common.h"
#include "mx25.h"
-static void __init imx25_dt_init(void)
-{
- mxc_arch_reset_init_dt();
-
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
static const char * const imx25_dt_board_compat[] __initconst = {
"fsl,imx25",
NULL
@@ -33,7 +26,5 @@ DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
.map_io = mx25_map_io,
.init_early = imx25_init_early,
.init_irq = mx25_init_irq,
- .init_machine = imx25_dt_init,
.dt_compat = imx25_dt_board_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index dc8f1a6f45f2..bd42d1bd10af 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -22,8 +22,6 @@ static void __init imx27_dt_init(void)
{
struct platform_device_info devinfo = { .name = "cpufreq-dt", };
- mxc_arch_reset_init_dt();
-
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
platform_device_register_full(&devinfo);
@@ -40,5 +38,4 @@ DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)")
.init_irq = mx27_init_irq,
.init_machine = imx27_dt_init,
.dt_compat = imx27_dt_board_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c
index 418dbc82adc4..32100222a017 100644
--- a/arch/arm/mach-imx/imx31-dt.c
+++ b/arch/arm/mach-imx/imx31-dt.c
@@ -18,13 +18,6 @@
#include "common.h"
#include "mx31.h"
-static void __init imx31_dt_init(void)
-{
- mxc_arch_reset_init_dt();
-
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
static const char * const imx31_dt_board_compat[] __initconst = {
"fsl,imx31",
NULL
@@ -40,7 +33,5 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)")
.init_early = imx31_init_early,
.init_irq = mx31_init_irq,
.init_time = imx31_dt_timer_init,
- .init_machine = imx31_dt_init,
.dt_compat = imx31_dt_board_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/imx35-dt.c b/arch/arm/mach-imx/imx35-dt.c
index 584fbe105579..e9396037235d 100644
--- a/arch/arm/mach-imx/imx35-dt.c
+++ b/arch/arm/mach-imx/imx35-dt.c
@@ -20,14 +20,6 @@
#include "common.h"
#include "mx35.h"
-static void __init imx35_dt_init(void)
-{
- mxc_arch_reset_init_dt();
-
- of_platform_populate(NULL, of_default_bus_match_table,
- NULL, NULL);
-}
-
static void __init imx35_irq_init(void)
{
imx_init_l2cache();
@@ -43,7 +35,5 @@ DT_MACHINE_START(IMX35_DT, "Freescale i.MX35 (Device Tree Support)")
.map_io = mx35_map_io,
.init_early = imx35_init_early,
.init_irq = imx35_irq_init,
- .init_machine = imx35_dt_init,
.dt_compat = imx35_dt_board_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/iomux-imx31.c b/arch/arm/mach-imx/iomux-imx31.c
index 1657fe64cd0f..d6a30753ca7c 100644
--- a/arch/arm/mach-imx/iomux-imx31.c
+++ b/arch/arm/mach-imx/iomux-imx31.c
@@ -44,9 +44,11 @@ static unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
/*
* set the mode for a IOMUX pin.
*/
-int mxc_iomux_mode(unsigned int pin_mode)
+void mxc_iomux_mode(unsigned int pin_mode)
{
- u32 field, l, mode, ret = 0;
+ u32 field;
+ u32 l;
+ u32 mode;
void __iomem *reg;
reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK);
@@ -61,8 +63,6 @@ int mxc_iomux_mode(unsigned int pin_mode)
__raw_writel(l, reg);
spin_unlock(&gpio_mux_lock);
-
- return ret;
}
/*
diff --git a/arch/arm/mach-imx/iomux-mx3.h b/arch/arm/mach-imx/iomux-mx3.h
index f79f78a1c0ed..0a5adba61e0b 100644
--- a/arch/arm/mach-imx/iomux-mx3.h
+++ b/arch/arm/mach-imx/iomux-mx3.h
@@ -144,7 +144,7 @@ void mxc_iomux_set_gpr(enum iomux_gp_func, bool en);
* It is called by the setup functions and should not be called directly anymore.
* It is here visible for backward compatibility
*/
-int mxc_iomux_mode(unsigned int pin_mode);
+void mxc_iomux_mode(unsigned int pin_mode);
#define IOMUX_PADNUM_MASK 0x1ff
#define IOMUX_GPIONUM_SHIFT 9
diff --git a/arch/arm/mach-imx/mach-imx50.c b/arch/arm/mach-imx/mach-imx50.c
index b1e56a94a382..ecf58b9e974b 100644
--- a/arch/arm/mach-imx/mach-imx50.c
+++ b/arch/arm/mach-imx/mach-imx50.c
@@ -16,13 +16,6 @@
#include "common.h"
-static void __init imx50_dt_init(void)
-{
- mxc_arch_reset_init_dt();
-
- of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
static const char * const imx50_dt_board_compat[] __initconst = {
"fsl,imx50",
NULL
@@ -30,7 +23,5 @@ static const char * const imx50_dt_board_compat[] __initconst = {
DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
.init_irq = tzic_init_irq,
- .init_machine = imx50_dt_init,
.dt_compat = imx50_dt_board_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx51.c b/arch/arm/mach-imx/mach-imx51.c
index 2c5fcaf8675b..b015129e4045 100644
--- a/arch/arm/mach-imx/mach-imx51.c
+++ b/arch/arm/mach-imx/mach-imx51.c
@@ -53,7 +53,6 @@ static void __init imx51_dt_init(void)
{
struct platform_device_info devinfo = { .name = "cpufreq-dt", };
- mxc_arch_reset_init_dt();
imx51_ipu_mipi_setup();
imx_src_init();
@@ -78,5 +77,4 @@ DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
.init_machine = imx51_dt_init,
.init_late = imx51_init_late,
.dt_compat = imx51_dt_board_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
index 03dd6ea13acc..86316a979297 100644
--- a/arch/arm/mach-imx/mach-imx53.c
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -30,7 +30,6 @@ static void __init imx53_init_early(void)
static void __init imx53_dt_init(void)
{
- mxc_arch_reset_init_dt();
imx_src_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -41,6 +40,8 @@ static void __init imx53_dt_init(void)
static void __init imx53_init_late(void)
{
imx53_pm_init();
+
+ platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
}
static const char * const imx53_dt_board_compat[] __initconst = {
@@ -54,5 +55,4 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
.init_machine = imx53_dt_init,
.init_late = imx53_init_late,
.dt_compat = imx53_dt_board_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index d51c6e99a2e9..070031067955 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -268,8 +268,6 @@ static void __init imx6q_init_machine(void)
imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
imx_get_soc_revision());
- mxc_arch_reset_init_dt();
-
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
@@ -392,7 +390,7 @@ static void __init imx6q_init_irq(void)
imx_init_revision_from_anatop();
imx_init_l2cache();
imx_src_init();
- imx_gpc_init();
+ imx6_gpc_init();
irqchip_init();
}
@@ -409,5 +407,4 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
.init_machine = imx6q_init_machine,
.init_late = imx6q_init_late,
.dt_compat = imx6q_dt_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index ed263a21d928..f0b4c60c7d69 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -48,8 +48,6 @@ static void __init imx6sl_init_machine(void)
{
struct device *parent;
- mxc_arch_reset_init_dt();
-
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
@@ -66,7 +64,7 @@ static void __init imx6sl_init_irq(void)
imx_init_revision_from_anatop();
imx_init_l2cache();
imx_src_init();
- imx_gpc_init();
+ imx6_gpc_init();
irqchip_init();
}
@@ -76,10 +74,8 @@ static const char * const imx6sl_dt_compat[] __initconst = {
};
DT_MACHINE_START(IMX6SL, "Freescale i.MX6 SoloLite (Device Tree)")
- .map_io = debug_ll_io_init,
.init_irq = imx6sl_init_irq,
.init_machine = imx6sl_init_machine,
.init_late = imx6sl_init_late,
.dt_compat = imx6sl_dt_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 3de3b7369aef..7a96c6577234 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -8,24 +8,73 @@
#include <linux/irqchip.h>
#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include "common.h"
#include "cpuidle.h"
+static int ar8031_phy_fixup(struct phy_device *dev)
+{
+ u16 val;
+
+ /* Set RGMII IO voltage to 1.8V */
+ phy_write(dev, 0x1d, 0x1f);
+ phy_write(dev, 0x1e, 0x8);
+
+ /* introduce tx clock delay */
+ phy_write(dev, 0x1d, 0x5);
+ val = phy_read(dev, 0x1e);
+ val |= 0x0100;
+ phy_write(dev, 0x1e, val);
+
+ return 0;
+}
+
+#define PHY_ID_AR8031 0x004dd074
+static void __init imx6sx_enet_phy_init(void)
+{
+ if (IS_BUILTIN(CONFIG_PHYLIB))
+ phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
+ ar8031_phy_fixup);
+}
+
+static void __init imx6sx_enet_clk_sel(void)
+{
+ struct regmap *gpr;
+
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
+ if (!IS_ERR(gpr)) {
+ regmap_update_bits(gpr, IOMUXC_GPR1,
+ IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0);
+ regmap_update_bits(gpr, IOMUXC_GPR1,
+ IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0);
+ } else {
+ pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
+ }
+}
+
+static inline void imx6sx_enet_init(void)
+{
+ imx6sx_enet_phy_init();
+ imx6sx_enet_clk_sel();
+}
+
static void __init imx6sx_init_machine(void)
{
struct device *parent;
- mxc_arch_reset_init_dt();
-
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+ imx6sx_enet_init();
imx_anatop_init();
imx6sx_pm_init();
}
@@ -53,10 +102,8 @@ static const char * const imx6sx_dt_compat[] __initconst = {
};
DT_MACHINE_START(IMX6SX, "Freescale i.MX6 SoloX (Device Tree)")
- .map_io = debug_ll_io_init,
.init_irq = imx6sx_init_irq,
.init_machine = imx6sx_init_machine,
.dt_compat = imx6sx_dt_compat,
.init_late = imx6sx_init_late,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
new file mode 100644
index 000000000000..b89c858ebfd6
--- /dev/null
+++ b/arch/arm/mach-imx/mach-ls1021a.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static const char * const ls1021a_dt_compat[] __initconst = {
+ "fsl,ls1021a",
+ NULL,
+};
+
+DT_MACHINE_START(LS1021A, "Freescale LS1021A")
+ .smp = smp_ops(ls1021a_smp_ops),
+ .dt_compat = ls1021a_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c
index ee7e57b752a7..f9335384c6aa 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -11,24 +11,33 @@
#include <linux/irqchip.h>
#include <asm/mach/arch.h>
#include <asm/hardware/cache-l2x0.h>
-
#include "common.h"
+static void __init vf610_init_irq(void)
+{
+ vf610_gpc_init();
+ vf610_mscm_init();
+ irqchip_init();
+}
+
static void __init vf610_init_machine(void)
{
- mxc_arch_reset_init_dt();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ vf610_pm_init();
}
static const char * const vf610_dt_compat[] __initconst = {
+ "fsl,vf500",
+ "fsl,vf510",
+ "fsl,vf600",
"fsl,vf610",
NULL,
};
-DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)")
+DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF5xx/VF6xx (Device Tree)")
.l2c_aux_val = 0,
.l2c_aux_mask = ~0,
- .init_machine = vf610_init_machine,
+ .init_irq = vf610_init_irq,
+ .init_machine = vf610_init_machine,
.dt_compat = vf610_dt_compat,
- .restart = mxc_restart,
MACHINE_END
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index 7a9686ad994c..3729d90cfa46 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -21,6 +21,12 @@
#define BP_MMDC_MAPSR_PSD 0
#define BP_MMDC_MAPSR_PSS 4
+#define MMDC_MDMISC 0x18
+#define BM_MMDC_MDMISC_DDR_TYPE 0x18
+#define BP_MMDC_MDMISC_DDR_TYPE 0x3
+
+static int ddr_type;
+
static int imx_mmdc_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -31,6 +37,12 @@ static int imx_mmdc_probe(struct platform_device *pdev)
mmdc_base = of_iomap(np, 0);
WARN_ON(!mmdc_base);
+ reg = mmdc_base + MMDC_MDMISC;
+ /* Get ddr type */
+ val = readl_relaxed(reg);
+ ddr_type = (val & BM_MMDC_MDMISC_DDR_TYPE) >>
+ BP_MMDC_MDMISC_DDR_TYPE;
+
reg = mmdc_base + MMDC_MAPSR;
/* Enable automatic power saving */
@@ -51,6 +63,11 @@ static int imx_mmdc_probe(struct platform_device *pdev)
return 0;
}
+int imx_mmdc_get_ddr_type(void)
+{
+ return ddr_type;
+}
+
static struct of_device_id imx_mmdc_dt_ids[] = {
{ .compatible = "fsl,imx6q-mmdc", },
{ /* sentinel */ }
diff --git a/arch/arm/mach-imx/mscm-vf610.c b/arch/arm/mach-imx/mscm-vf610.c
new file mode 100644
index 000000000000..e36a7936b57e
--- /dev/null
+++ b/arch/arm/mach-imx/mscm-vf610.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2014 Stefan Agner
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpu_pm.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqchip/arm-gic.h>
+#include "common.h"
+
+#define MSCM_CPxNUM 0x4
+
+#define MSCM_IRCP0IR 0x800
+#define MSCM_IRCP1IR 0x804
+#define MSCM_IRCPnIR(n) ((n) * 0x4 + MSCM_IRCP0IR)
+#define MSCM_IRCPnIR_INT(n) (0x1 << (n))
+#define MSCM_IRCPGIR 0x820
+
+#define MSCM_INTID_MASK 0x3
+#define MSCM_INTID(n) ((n) & MSCM_INTID_MASK)
+#define MSCM_CPUTL(n) (((n) == 0 ? 1 : 2) << 16)
+
+#define MSCM_IRSPRC(n) (0x880 + 2 * (n))
+#define MSCM_IRSPRC_CPEN_MASK 0x3
+
+#define MSCM_IRSPRC_NUM 112
+
+#define MSCM_CPU2CPU_NUM 4
+
+#define MSCM_IRQ_OFFSET 32
+
+static void __iomem *mscm_base;
+struct device_node *mscm_node;
+static u16 mscm_saved_irsprc[MSCM_IRSPRC_NUM];
+static u16 cpu_id;
+
+struct mscm_cpu2cpu_irq_data {
+ int intid;
+ int irq;
+ irq_handler_t handler;
+ void *priv;
+};
+
+static struct mscm_cpu2cpu_irq_data cpu2cpu_irq_data[MSCM_CPU2CPU_NUM];
+
+static int vf610_mscm_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ int i;
+
+ /* Only the primary (boot CPU) should do suspend/resume */
+ if (cpu_id > 0)
+ return NOTIFY_OK;
+
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ for (i = 0; i < MSCM_IRSPRC_NUM; i++)
+ mscm_saved_irsprc[i] =
+ readw_relaxed(mscm_base + MSCM_IRSPRC(i));
+ break;
+ case CPU_CLUSTER_PM_ENTER_FAILED:
+ case CPU_CLUSTER_PM_EXIT:
+ for (i = 0; i < MSCM_IRSPRC_NUM; i++)
+ writew_relaxed(mscm_saved_irsprc[i],
+ mscm_base + MSCM_IRSPRC(i));
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block mscm_notifier_block = {
+ .notifier_call = vf610_mscm_notifier,
+};
+
+static int vf610_mscm_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ u16 irsprc;
+
+ /* Do not handle non Interrupt Router IRQs */
+ if (hw < MSCM_IRQ_OFFSET)
+ return 0;
+
+ hw -= MSCM_IRQ_OFFSET;
+ irsprc = readw_relaxed(mscm_base + MSCM_IRSPRC(hw));
+ irsprc &= MSCM_IRSPRC_CPEN_MASK;
+
+ /* Warn if interrupt is enabled on another CPU */
+ WARN_ON(irsprc & ~(0x1 << cpu_id));
+
+ writew_relaxed(0x1 << cpu_id, mscm_base + MSCM_IRSPRC(hw));
+
+ return 0;
+}
+
+static void vf610_mscm_domain_unmap(struct irq_domain *d, unsigned int irq)
+{
+ irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
+ u16 irsprc;
+
+ /* Do not handle non Interrupt Router IRQs */
+ if (hw < MSCM_IRQ_OFFSET)
+ return;
+
+ hw -= MSCM_IRQ_OFFSET;
+ irsprc = readw_relaxed(mscm_base + MSCM_IRSPRC(hw));
+ irsprc &= MSCM_IRSPRC_CPEN_MASK;
+
+ writew_relaxed(0x1 << cpu_id, mscm_base + MSCM_IRSPRC(hw));
+}
+
+static int vf610_mscm_domain_xlate(struct irq_domain *d,
+ struct device_node *controller,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ *out_hwirq += 16;
+ return 0;
+}
+static const struct irq_domain_ops routable_irq_domain_ops = {
+ .map = vf610_mscm_domain_map,
+ .unmap = vf610_mscm_domain_unmap,
+ .xlate = vf610_mscm_domain_xlate,
+};
+
+static irqreturn_t mscm_cpu2cpu_irq_handler(int irq, void *dev_id)
+{
+ irqreturn_t ret;
+ struct mscm_cpu2cpu_irq_data *data = dev_id;
+
+
+ ret = data->handler(data->intid, data->priv);
+ if (ret == IRQ_HANDLED)
+ writel(MSCM_IRCPnIR_INT(data->intid), mscm_base + MSCM_IRCPnIR(cpu_id));
+
+ return ret;
+}
+
+int mscm_request_cpu2cpu_irq(unsigned int intid, irq_handler_t handler,
+ const char *name, void *priv)
+{
+ int irq;
+ struct mscm_cpu2cpu_irq_data *data;
+
+
+ if (intid >= MSCM_CPU2CPU_NUM)
+ return -EINVAL;
+
+ irq = of_irq_get(mscm_node, intid);
+ if (irq < 0)
+ return irq;
+
+ data = &cpu2cpu_irq_data[intid];
+ data->intid = intid;
+ data->irq = irq;
+ data->handler = handler;
+ data->priv = priv;
+
+ return request_irq(irq, mscm_cpu2cpu_irq_handler, 0, name, data);
+}
+EXPORT_SYMBOL(mscm_request_cpu2cpu_irq);
+
+void mscm_free_cpu2cpu_irq(unsigned int intid, void *priv)
+{
+ struct mscm_cpu2cpu_irq_data *data;
+
+ if (intid >= MSCM_CPU2CPU_NUM)
+ return;
+
+ data = &cpu2cpu_irq_data[intid];
+
+ if (data->irq < 0)
+ return;
+
+ free_irq(data->irq, data);
+}
+EXPORT_SYMBOL(mscm_free_cpu2cpu_irq);
+
+void mscm_trigger_cpu2cpu_irq(unsigned int intid, int cpuid)
+{
+ writel(MSCM_INTID(intid) | MSCM_CPUTL(cpuid), mscm_base + MSCM_IRCPGIR);
+}
+EXPORT_SYMBOL(mscm_trigger_cpu2cpu_irq);
+
+void __init vf610_mscm_init(void)
+{
+ mscm_node = of_find_compatible_node(NULL, NULL, "fsl,vf610-mscm");
+ mscm_base = of_iomap(mscm_node, 0);
+
+ if (!mscm_base) {
+ WARN_ON(1);
+ return;
+ }
+
+ cpu_id = readl_relaxed(mscm_base + MSCM_CPxNUM);
+
+ /* Register MSCM as interrupt router */
+ register_routable_domain_ops(&routable_irq_domain_ops);
+
+ cpu_pm_register_notifier(&mscm_notifier_block);
+}
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index 17a41ca65acf..4c1343df2ba4 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -55,6 +55,8 @@
#define IMX_CHIP_REVISION_3_3 0x33
#define IMX_CHIP_REVISION_UNKNOWN 0xff
+#define IMX_DDR_TYPE_LPDDR2 1
+
#ifndef __ASSEMBLY__
extern unsigned int __mxc_cpu_type;
#endif
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 771bd25c1025..7f270015fe58 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -11,7 +11,10 @@
*/
#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
#include <linux/smp.h>
+
#include <asm/cacheflush.h>
#include <asm/page.h>
#include <asm/smp_scu.h>
@@ -94,3 +97,33 @@ struct smp_operations imx_smp_ops __initdata = {
.cpu_kill = imx_cpu_kill,
#endif
};
+
+#define DCFG_CCSR_SCRATCHRW1 0x200
+
+static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ return 0;
+}
+
+static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *np;
+ void __iomem *dcfg_base;
+ unsigned long paddr;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg");
+ dcfg_base = of_iomap(np, 0);
+ BUG_ON(!dcfg_base);
+
+ paddr = virt_to_phys(secondary_startup);
+ writel_relaxed(cpu_to_be32(paddr), dcfg_base + DCFG_CCSR_SCRATCHRW1);
+
+ iounmap(dcfg_base);
+}
+
+struct smp_operations ls1021a_smp_ops __initdata = {
+ .smp_prepare_cpus = ls1021a_smp_prepare_cpus,
+ .smp_boot_secondary = ls1021a_boot_secondary,
+};
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 5c3af8f993d0..c653dd4c9103 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -88,7 +88,7 @@ struct imx6_pm_base {
};
struct imx6_pm_socdata {
- u32 cpu_type;
+ u32 ddr_type;
const char *mmdc_compat;
const char *src_compat;
const char *iomuxc_compat;
@@ -138,7 +138,6 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = {
};
static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
- .cpu_type = MXC_CPU_IMX6Q,
.mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6q-iomuxc",
@@ -148,7 +147,6 @@ static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
};
static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
- .cpu_type = MXC_CPU_IMX6DL,
.mmdc_compat = "fsl,imx6q-mmdc",
.src_compat = "fsl,imx6q-src",
.iomuxc_compat = "fsl,imx6dl-iomuxc",
@@ -158,7 +156,6 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
};
static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
- .cpu_type = MXC_CPU_IMX6SL,
.mmdc_compat = "fsl,imx6sl-mmdc",
.src_compat = "fsl,imx6sl-src",
.iomuxc_compat = "fsl,imx6sl-iomuxc",
@@ -168,7 +165,6 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
};
static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
- .cpu_type = MXC_CPU_IMX6SX,
.mmdc_compat = "fsl,imx6sx-mmdc",
.src_compat = "fsl,imx6sx-src",
.iomuxc_compat = "fsl,imx6sx-iomuxc",
@@ -187,7 +183,7 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
struct imx6_cpu_pm_info {
phys_addr_t pbase; /* The physical address of pm_info. */
phys_addr_t resume_addr; /* The physical resume address for asm code */
- u32 cpu_type;
+ u32 ddr_type;
u32 pm_info_size; /* Size of pm_info. */
struct imx6_pm_base mmdc_base;
struct imx6_pm_base src_base;
@@ -522,7 +518,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
goto pl310_cache_map_failed;
}
- pm_info->cpu_type = socdata->cpu_type;
+ pm_info->ddr_type = imx_mmdc_get_ddr_type();
pm_info->mmdc_io_num = socdata->mmdc_io_num;
mmdc_offset_array = socdata->mmdc_io_offset;
diff --git a/arch/arm/mach-imx/pm-vf610.c b/arch/arm/mach-imx/pm-vf610.c
new file mode 100644
index 000000000000..205c874d3660
--- /dev/null
+++ b/arch/arm/mach-imx/pm-vf610.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2014 Toradex AG
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/genalloc.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/tlb.h>
+
+#include "common.h"
+
+#define CCR 0x0
+#define BM_CCR_FIRC_EN (0x1 << 16)
+#define BM_CCR_FXOSC_EN (0x1 << 12)
+
+#define CCSR 0x8
+#define BM_CCSR_DDRC_CLK_SEL (0x1 << 6)
+#define BM_CCSR_FAST_CLK_SEL (0x1 << 5)
+#define BM_CCSR_SLOW_CLK_SEL (0x1 << 4)
+#define BM_CCSR_SYS_CLK_SEL_MASK (0x7 << 0)
+
+#define CLPCR 0x2c
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
+#define BM_CLPCR_SBYOS (0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
+#define BM_CLPCR_ANADIG_STOP_MODE (0x1 << 8)
+#define BM_CLPCR_FXOSC_BYPSEN (0x1 << 10)
+#define BM_CLPCR_FXOSC_PWRDWN (0x1 << 11)
+#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
+#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 24)
+#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 25)
+
+#define CGPR 0x64
+#define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17)
+
+#define GPC_PGCR 0x0
+#define BM_PGCR_DS_STOP (0x1 << 7)
+#define BM_PGCR_DS_LPSTOP (0x1 << 6)
+#define BM_PGCR_WB_STOP (0x1 << 4)
+#define BM_PGCR_HP_OFF (0x1 << 3)
+
+#define GPC_LPMR 0x40
+#define BM_LPMR_RUN 0x0
+#define BM_LPMR_STOP 0x2
+
+#define ANATOP_PLL1_CTRL 0x270
+#define ANATOP_PLL2_CTRL 0x30
+#define ANATOP_PLL2_PFD 0x100
+#define ANATOP_PLL3_CTRL 0x10
+#define ANATOP_PLL4_CTRL 0x70
+#define ANATOP_PLL5_CTRL 0xe0
+#define ANATOP_PLL6_CTRL 0xa0
+#define ANATOP_PLL7_CTRL 0x10
+#define BM_PLL_POWERDOWN (0x1 << 12)
+#define BM_PLL_ENABLE (0x1 << 13)
+#define BM_PLL_BYPASS (0x1 << 16)
+#define BM_PLL_LOCK (0x1 << 31)
+#define BM_PLL_PFD2_CLKGATE (0x1 << 15)
+
+#define VF610_SUSPEND_OCRAM_SIZE 0x4000
+
+#define VF_UART0_BASE_ADDR 0x40027000
+#define VF_UART1_BASE_ADDR 0x40028000
+#define VF_UART2_BASE_ADDR 0x40029000
+#define VF_UART3_BASE_ADDR 0x4002a000
+#define VF_UART_BASE_ADDR(n) VF_UART##n##_BASE_ADDR
+#define VF_UART_BASE(n) VF_UART_BASE_ADDR(n)
+#define VF_UART_PHYSICAL_BASE VF_UART_BASE(CONFIG_DEBUG_VF_UART_PORT)
+
+static void __iomem *ccm_base;
+static struct vf610_cpu_pm_info *pm_info;
+
+/*
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ * .
+ * .
+ * .
+ * ^
+ * ^
+ * ^
+ * vf610_suspend code
+ * PM_INFO structure(vf610_cpu_pm_info)
+ * ======================== low address =======================
+ */
+
+struct vf610_pm_base {
+ phys_addr_t pbase;
+ void __iomem *vbase;
+};
+
+struct vf610_pm_socdata {
+ const char *src_compat;
+ const char *gpc_compat;
+ const char *anatop_compat;
+};
+
+static const struct vf610_pm_socdata vf610_pm_data __initconst = {
+ .src_compat = "fsl,vf610-src",
+ .gpc_compat = "fsl,vf610-gpc",
+ .anatop_compat = "fsl,vf610-anatop",
+};
+
+/*
+ * This structure is for passing necessary data for low level ocram
+ * suspend code(arch/arm/mach-imx/suspend-vf610.S), if this struct
+ * definition is changed, the offset definition in
+ * arch/arm/mach-imx/suspend-vf610.S must be also changed accordingly,
+ * otherwise, the suspend to ocram function will be broken!
+ */
+struct vf610_cpu_pm_info {
+ phys_addr_t pbase; /* The physical address of pm_info. */
+ phys_addr_t resume_addr; /* The physical resume address for asm code */
+ u32 cpu_type; /* Currently not used, leave it for alignment */
+ u32 pm_info_size; /* Size of pm_info. */
+ struct vf610_pm_base anatop_base;
+ struct vf610_pm_base src_base;
+ struct vf610_pm_base ccm_base;
+ struct vf610_pm_base gpc_base;
+ struct vf610_pm_base l2_base;
+ u32 ccm_ccsr;
+} __aligned(8);
+
+#ifdef DEBUG
+static void uart_reinit(unsigned long int rate, unsigned long int baud)
+{
+ void __iomem *membase = ioremap(VF_UART_PHYSICAL_BASE, 0x1000);
+ u8 tmp;
+ u16 sbr, brfa;
+
+ /* UART_C2 */
+ __raw_writeb(0, membase + 0x3);
+
+ sbr = (u16) (rate / (baud * 16));
+ brfa = (rate / baud) - (sbr * 16);
+
+ tmp = ((sbr & 0x1f00) >> 8);
+ __raw_writeb(tmp, membase + 0x0);
+ tmp = sbr & 0x00ff;
+ __raw_writeb(tmp, membase + 0x1);
+
+ /* UART_C4 */
+ __raw_writeb(brfa & 0xf, membase + 0xa);
+
+ /* UART_C2 */
+ __raw_writeb(0xac, membase + 0x3);
+
+ iounmap(membase);
+}
+#else
+static void uart_reinit(unsigned long int rate, unsigned long int baud) {}
+#endif
+
+static void vf610_set(void __iomem *pll_base, u32 mask)
+{
+ writel_relaxed(readl_relaxed(pll_base) | mask, pll_base);
+}
+
+static void vf610_clr(void __iomem *pll_base, u32 mask)
+{
+ writel_relaxed(readl_relaxed(pll_base) & ~mask, pll_base);
+}
+
+int vf610_set_lpm(enum vf610_cpu_pwr_mode mode)
+{
+ u32 ccr = readl_relaxed(ccm_base + CCR);
+ u32 ccsr = readl_relaxed(ccm_base + CCSR);
+ u32 cclpcr = readl_relaxed(ccm_base + CLPCR);
+ void __iomem *gpc_base = pm_info->gpc_base.vbase;
+ u32 gpc_pgcr = readl_relaxed(gpc_base + GPC_PGCR);
+ void __iomem *anatop = pm_info->anatop_base.vbase;
+
+ switch (mode) {
+ case VF610_STOP:
+ cclpcr &= ~BM_CLPCR_ANADIG_STOP_MODE;
+ cclpcr |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
+ cclpcr &= ~BM_CLPCR_SBYOS;
+ writel_relaxed(cclpcr, ccm_base + CLPCR);
+
+ gpc_pgcr |= BM_PGCR_DS_STOP;
+ gpc_pgcr |= BM_PGCR_HP_OFF;
+ writel_relaxed(gpc_pgcr, gpc_base + GPC_PGCR);
+
+ writel_relaxed(BM_LPMR_STOP, gpc_base + GPC_LPMR);
+ /* fall-through */
+ case VF610_LP_RUN:
+ /* Store clock settings */
+ pm_info->ccm_ccsr = ccsr;
+
+ ccr |= BM_CCR_FIRC_EN;
+ writel_relaxed(ccr, ccm_base + CCR);
+
+ /* Enable PLL2 for DDR clock */
+ vf610_set(anatop + ANATOP_PLL2_CTRL, BM_PLL_ENABLE);
+ vf610_clr(anatop + ANATOP_PLL2_CTRL, BM_PLL_POWERDOWN);
+ vf610_clr(anatop + ANATOP_PLL2_CTRL, BM_PLL_BYPASS);
+ while (!(readl(anatop + ANATOP_PLL2_CTRL) & BM_PLL_LOCK));
+ vf610_clr(anatop + ANATOP_PLL2_PFD, BM_PLL_PFD2_CLKGATE);
+
+ /* Switch internal OSC's */
+ ccsr &= ~BM_CCSR_FAST_CLK_SEL;
+ ccsr &= ~BM_CCSR_SLOW_CLK_SEL;
+
+ /* Select PLL2 as DDR clock */
+ ccsr &= ~BM_CCSR_DDRC_CLK_SEL;
+ writel_relaxed(ccsr, ccm_base + CCSR);
+
+ ccsr &= ~BM_CCSR_SYS_CLK_SEL_MASK;
+ writel_relaxed(ccsr, ccm_base + CCSR);
+ uart_reinit(4000000UL, 115200);
+
+ vf610_set(anatop + ANATOP_PLL1_CTRL, BM_PLL_BYPASS);
+ vf610_clr(anatop + ANATOP_PLL3_CTRL, BM_PLL_ENABLE);
+ vf610_clr(anatop + ANATOP_PLL5_CTRL, BM_PLL_ENABLE);
+ vf610_clr(anatop + ANATOP_PLL7_CTRL, BM_PLL_ENABLE);
+ break;
+ case VF610_RUN:
+ vf610_clr(anatop + ANATOP_PLL1_CTRL, BM_PLL_BYPASS);
+ vf610_set(anatop + ANATOP_PLL3_CTRL, BM_PLL_ENABLE);
+ vf610_set(anatop + ANATOP_PLL5_CTRL, BM_PLL_ENABLE);
+ vf610_set(anatop + ANATOP_PLL7_CTRL, BM_PLL_ENABLE);
+
+ /* Restore clock settings */
+ writel_relaxed(pm_info->ccm_ccsr, ccm_base + CCSR);
+
+ /* Disable PLL2 if not needed */
+ if (pm_info->ccm_ccsr & BM_CCSR_DDRC_CLK_SEL)
+ vf610_set(anatop + ANATOP_PLL2_CTRL, BM_PLL_POWERDOWN);
+
+ uart_reinit(83368421UL, 115200);
+
+ writel_relaxed(BM_LPMR_RUN, gpc_base + GPC_LPMR);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vf610_pm_enter(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ vf610_set_lpm(VF610_STOP);
+ imx_gpc_pre_suspend(false);
+
+ /* zzZZZzzz */
+ cpu_do_idle();
+
+ imx_gpc_post_resume();
+ vf610_set_lpm(VF610_RUN);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vf610_pm_valid(suspend_state_t state)
+{
+ return state == PM_SUSPEND_STANDBY;
+}
+
+static const struct platform_suspend_ops vf610_pm_ops = {
+ .enter = vf610_pm_enter,
+ .valid = vf610_pm_valid,
+};
+
+void __init vf610_pm_set_ccm_base(void __iomem *base)
+{
+ ccm_base = base;
+}
+
+static int __init imx_pm_get_base(struct vf610_pm_base *base,
+ const char *compat)
+{
+ struct device_node *node;
+ struct resource res;
+ int ret = 0;
+
+ node = of_find_compatible_node(NULL, NULL, compat);
+ if (!node) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret)
+ goto put_node;
+
+ base->pbase = res.start;
+ base->vbase = ioremap(res.start, resource_size(&res));
+
+ if (!base->vbase)
+ ret = -ENOMEM;
+
+put_node:
+ of_node_put(node);
+out:
+ return ret;
+}
+
+static int __init vf610_suspend_init(const struct vf610_pm_socdata *socdata)
+{
+ int ret = 0;
+
+ suspend_set_ops(&vf610_pm_ops);
+
+ if (!socdata) {
+ pr_warn("%s: invalid argument!\n", __func__);
+ return -EINVAL;
+ }
+
+ pm_info = kzalloc(sizeof(*pm_info), GFP_KERNEL);
+ pm_info->pm_info_size = sizeof(*pm_info);
+
+ /*
+ * ccm physical address is not used by asm code currently,
+ * so get ccm virtual address directly, as we already have
+ * it from ccm driver.
+ */
+ pm_info->ccm_base.vbase = ccm_base;
+
+ ret = imx_pm_get_base(&pm_info->anatop_base, socdata->anatop_compat);
+ if (ret) {
+ pr_warn("%s: failed to get anatop base %d!\n", __func__, ret);
+ goto free_memory;
+ }
+
+ ret = imx_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat);
+ if (ret) {
+ pr_warn("%s: failed to get gpc base %d!\n", __func__, ret);
+ goto gpc_map_failed;
+ }
+
+ return 0;
+
+gpc_map_failed:
+ iounmap(&pm_info->anatop_base.vbase);
+free_memory:
+ kfree(pm_info);
+
+ return ret;
+}
+
+void __init vf610_pm_init(void)
+{
+ int ret;
+
+ WARN_ON(!ccm_base);
+
+ if (IS_ENABLED(CONFIG_SUSPEND)) {
+ ret = vf610_suspend_init(&vf610_pm_data);
+ if (ret)
+ pr_warn("%s: No DDR LPM support with suspend %d!\n",
+ __func__, ret);
+ }
+}
+
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
index ca4ea2daf25b..b99987b023fa 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -45,7 +45,7 @@
*/
#define PM_INFO_PBASE_OFFSET 0x0
#define PM_INFO_RESUME_ADDR_OFFSET 0x4
-#define PM_INFO_CPU_TYPE_OFFSET 0x8
+#define PM_INFO_DDR_TYPE_OFFSET 0x8
#define PM_INFO_PM_INFO_SIZE_OFFSET 0xC
#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10
#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14
@@ -110,7 +110,7 @@
ldreq r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
ldrne r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
- cmp r3, #MXC_CPU_IMX6SL
+ cmp r3, #IMX_DDR_TYPE_LPDDR2
bne 4f
/* reset read FIFO, RST_RD_FIFO */
@@ -151,7 +151,7 @@
ENTRY(imx6_suspend)
ldr r1, [r0, #PM_INFO_PBASE_OFFSET]
ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
- ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
+ ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
ldr r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
/*
@@ -209,8 +209,8 @@ poll_dvfs_set:
ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET
add r8, r8, r0
- /* i.MX6SL's last 3 IOs need special setting */
- cmp r3, #MXC_CPU_IMX6SL
+ /* LPDDR2's last 3 IOs need special setting */
+ cmp r3, #IMX_DDR_TYPE_LPDDR2
subeq r7, r7, #0x3
set_mmdc_io_lpm:
ldr r9, [r8], #0x8
@@ -218,7 +218,7 @@ set_mmdc_io_lpm:
subs r7, r7, #0x1
bne set_mmdc_io_lpm
- cmp r3, #MXC_CPU_IMX6SL
+ cmp r3, #IMX_DDR_TYPE_LPDDR2
bne set_mmdc_io_lpm_done
ldr r6, =0x1000
ldr r9, [r8], #0x8
@@ -324,7 +324,7 @@ resume:
str r7, [r11, #MX6Q_SRC_GPR1]
str r7, [r11, #MX6Q_SRC_GPR2]
- ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
+ ldr r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
mov r5, #0x1
resume_mmdc
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c
index d14c33fd6b03..51c35013b673 100644
--- a/arch/arm/mach-imx/system.c
+++ b/arch/arm/mach-imx/system.c
@@ -89,21 +89,6 @@ void __init mxc_arch_reset_init(void __iomem *base)
clk_prepare(wdog_clk);
}
-void __init mxc_arch_reset_init_dt(void)
-{
- struct device_node *np;
-
- np = of_find_compatible_node(NULL, NULL, "fsl,imx21-wdt");
- wdog_base = of_iomap(np, 0);
- WARN_ON(!wdog_base);
-
- wdog_clk = of_clk_get(np, 0);
- if (IS_ERR(wdog_clk))
- pr_warn("%s: failed to get wdog clock\n", __func__);
- else
- clk_prepare(wdog_clk);
-}
-
#ifdef CONFIG_CACHE_L2X0
void __init imx_init_l2cache(void)
{
diff --git a/arch/arm/mach-imx/vf610_sema4.c b/arch/arm/mach-imx/vf610_sema4.c
new file mode 100644
index 000000000000..9b4d7a74a8ab
--- /dev/null
+++ b/arch/arm/mach-imx/vf610_sema4.c
@@ -0,0 +1,314 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+
+#include <linux/mm.h>
+#include <linux/version.h>
+#include <linux/kdev_t.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include "hardware.h"
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <linux/debugfs.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include <linux/vf610_sema4.h>
+// ************************************ Local Data *************************************************
+
+#define NUM_GATES 16
+#define MASK_FROM_GATE(gate_num) ((u32)(1 << (NUM_GATES*2 - 1 - idx[gate_num])))
+
+#define THIS_CORE (0)
+#define LOCK_VALUE (THIS_CORE + 1)
+
+#define SEMA4_CP0INE (0x40)
+#define SEMA4_CP0NTF (0x80)
+
+static MVF_SEMA4* gates[NUM_GATES];
+static void __iomem *sema4_base;
+
+// account for the way the bits are set / returned in CP0INE and CP0NTF
+static const int idx[16] = {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12};
+
+// debugfs
+#define DEBUGFS_DIR "mvf_sema4"
+static struct dentry *debugfs_dir;
+
+// ************************************ Interrupt handler *************************************************
+
+static irqreturn_t sema4_irq_handler(int irq, void *dev_id)
+{
+ int gate_num;
+
+ u32 cp0ntf = readl(sema4_base + SEMA4_CP0NTF);
+
+ for(gate_num=0; gate_num<NUM_GATES; gate_num++)
+ {
+ // interrupt from this gate?
+ if(cp0ntf & MASK_FROM_GATE(gate_num))
+ {
+ // grab the gate to stop the interrupts
+ writeb(LOCK_VALUE, sema4_base + gate_num);
+
+ // make sure there's a gate assigned
+ if(gates[gate_num])
+ {
+ //if(gates[gate_num]->use_interrupts) {
+ // wake up whoever was aiting
+ wake_up_interruptible(&(gates[gate_num]->wait_queue));
+ // bump stats
+ gates[gate_num]->interrupts++;
+ //}
+ }
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+// ************************************ Utility functions *************************************************
+
+int mvf_sema4_assign(int gate_num, MVF_SEMA4** sema4_p)
+{
+ u32 cp0ine;
+ unsigned long irq_flags;
+ char debugfs_gatedir_name[4];
+ struct dentry *debugfs_gate_dir;
+
+ if((gate_num < 0) || (gate_num >= NUM_GATES))
+ return -EINVAL;
+
+ if(gates[gate_num])
+ return -EBUSY;
+
+ *sema4_p = (MVF_SEMA4 *)kmalloc(sizeof(MVF_SEMA4), GFP_KERNEL);
+ if(*sema4_p == NULL)
+ return -ENOMEM;
+ memset(*sema4_p, 0, sizeof(MVF_SEMA4));
+
+ gates[gate_num] = *sema4_p;
+ (*sema4_p)->gate_num = gate_num;
+
+ init_waitqueue_head(&((*sema4_p)->wait_queue));
+ local_irq_save(irq_flags);
+ cp0ine = readl(sema4_base + SEMA4_CP0INE);
+ cp0ine |= MASK_FROM_GATE(gate_num);
+ writel(cp0ine, sema4_base + SEMA4_CP0INE);
+ local_irq_restore(irq_flags);
+
+ // debugfs
+ sprintf(debugfs_gatedir_name, "%d", gate_num);
+ debugfs_gate_dir = debugfs_create_dir(debugfs_gatedir_name, debugfs_dir);
+ debugfs_create_u32("attempts", S_IRUGO | S_IWUGO, debugfs_gate_dir, &(*sema4_p)->attempts);
+ debugfs_create_u32("interrupts", S_IRUGO | S_IWUGO, debugfs_gate_dir, &(*sema4_p)->interrupts);
+ debugfs_create_u32("failures", S_IRUGO | S_IWUGO, debugfs_gate_dir, &(*sema4_p)->failures);
+ debugfs_create_u64("total_latency_us", S_IRUGO | S_IWUGO, debugfs_gate_dir, &(*sema4_p)->total_latency_us);
+ debugfs_create_u32("worst_latency_us", S_IRUGO | S_IWUGO, debugfs_gate_dir, &(*sema4_p)->worst_latency_us);
+
+ return 0;
+}
+EXPORT_SYMBOL(mvf_sema4_assign);
+
+int mvf_sema4_deassign(MVF_SEMA4 *sema4)
+{
+ u32 cp0ine;
+ unsigned long irq_flags;
+
+ int gate_num;
+ if(!sema4)
+ return -EINVAL;
+ gate_num = sema4->gate_num;
+
+ local_irq_save(irq_flags);
+ cp0ine = readl(sema4_base + SEMA4_CP0INE);
+ cp0ine &= ~MASK_FROM_GATE(gate_num);
+ writel(cp0ine, sema4_base + SEMA4_CP0INE);
+ local_irq_restore(irq_flags);
+
+ kfree(sema4);
+ gates[gate_num] = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(mvf_sema4_deassign);
+
+static long delta_time(struct timeval *start) {
+
+ struct timeval now;
+ long now_us, start_us;
+
+ do_gettimeofday(&now);
+
+ now_us = (now.tv_sec * 1000000) + now.tv_usec;
+ start_us = (start->tv_sec * 1000000) + start->tv_usec;
+
+ return now_us > start_us ? now_us - start_us : 0;
+}
+
+static void add_latency_stat(MVF_SEMA4 *sema4) {
+
+ long latency = delta_time(&sema4->request_time);
+
+ sema4->total_latency_us += latency;
+ sema4->worst_latency_us = sema4->worst_latency_us < latency ? latency : sema4->worst_latency_us;
+}
+
+int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us, bool use_interrupts)
+{
+ int retval;
+ int gate_num;
+ if(!sema4)
+ return -EINVAL;
+ gate_num = sema4->gate_num;
+
+ // bump stats
+ gates[gate_num]->attempts++;
+ do_gettimeofday(&gates[gate_num]->request_time);
+
+ // try to grab it
+ writeb(LOCK_VALUE, sema4_base + gate_num);
+ if(readb(sema4_base + gate_num) == LOCK_VALUE) {
+ add_latency_stat(gates[gate_num]);
+ return 0;
+ }
+
+ // no timeout, fail
+ if(!timeout_us) {
+ gates[gate_num]->failures++;
+ return -EBUSY;
+ }
+
+ // spin lock?
+ if(!use_interrupts) {
+ while(readb(sema4_base + gate_num) != LOCK_VALUE) {
+
+ if((timeout_us != 0xffffffff) && (delta_time(&gates[gate_num]->request_time) > timeout_us)) {
+ gates[gate_num]->failures++;
+ return -EBUSY;
+ }
+
+ writeb(LOCK_VALUE, sema4_base + gate_num);
+ }
+ add_latency_stat(gates[gate_num]);
+ return 0;
+ }
+
+ // wait forever?
+ if(timeout_us == 0xffffffff)
+ {
+ if(wait_event_interruptible(sema4->wait_queue, (readb(sema4_base + gate_num) == LOCK_VALUE))) {
+ gates[gate_num]->failures++;
+ return -ERESTARTSYS;
+ }
+ }
+ else
+ {
+ // return: 0 = timeout, >0 = woke up with that many jiffies left, <0 = error
+ retval = wait_event_interruptible_timeout(sema4->wait_queue,
+ (readb(sema4_base + gate_num) == LOCK_VALUE),
+ usecs_to_jiffies(timeout_us));
+ if(retval == 0) {
+ gates[gate_num]->failures++;
+ return -ETIME;
+ }
+ else if(retval < 0) {
+ gates[gate_num]->failures++;
+ return retval;
+ }
+ }
+
+ add_latency_stat(gates[gate_num]);
+ return 0;
+}
+EXPORT_SYMBOL(mvf_sema4_lock);
+
+int mvf_sema4_unlock(MVF_SEMA4 *sema4)
+{
+ if(!sema4)
+ return -EINVAL;
+
+ // unlock it
+ writeb(0, sema4_base + sema4->gate_num);
+
+ return 0;
+}
+EXPORT_SYMBOL(mvf_sema4_unlock);
+
+// return 0 on success (meaning it is set to us)
+int mvf_sema4_test(MVF_SEMA4 *sema4)
+{
+ if(!sema4)
+ return -EINVAL;
+
+ return (readb(sema4_base + sema4->gate_num)) == LOCK_VALUE ? 0 : 1;
+}
+EXPORT_SYMBOL(mvf_sema4_test);
+
+static int vf610_sema4_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *iores;
+ int irq, ret, i;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sema4_base = devm_ioremap_resource(dev, iores);
+ if (IS_ERR(sema4_base))
+ return PTR_ERR(sema4_base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq specified\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, sema4_irq_handler, 0, "SEMA4", NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
+ return ret;
+ }
+
+ // clear the gates table
+ for (i = 0; i < NUM_GATES; i++)
+ gates[i] = NULL;
+
+ writel_relaxed(0, sema4_base + SEMA4_CP0INE);
+
+ // debugfs
+ debugfs_dir = debugfs_create_dir(DEBUGFS_DIR, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id vf610_sema4_dt_ids[] = {
+ { .compatible = "fsl,vf610-sema4" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver vf610_sema4_compat_driver = {
+ .driver = {
+ .name = "vf610-sema4",
+ .owner = THIS_MODULE,
+ .of_match_table = vf610_sema4_dt_ids,
+ },
+ .probe = vf610_sema4_probe,
+};
+
+static int __init vf610_sema4_compat_init(void)
+{
+ return platform_driver_register(&vf610_sema4_compat_driver);
+}
+device_initcall(vf610_sema4_compat_init);
+
+MODULE_DESCRIPTION("Freescale SEMA4 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 3c5711d5fe97..58c6fc7e902e 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -386,7 +386,7 @@ static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan,
&(edesc->tcd[i].vtcd->daddr));
len -= size;
- if (cur_addr > dma_addr && cur_addr < dma_addr + size) {
+ if (cur_addr >= dma_addr && cur_addr < dma_addr + size) {
len += dma_addr + size - cur_addr;
break;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 0959ca9b6b27..8586517a99a2 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -333,6 +333,13 @@ config GPIO_TZ1090_PDC
help
Say yes here to support Toumaz Xenif TZ1090 PDC GPIOs.
+config GPIO_VF610
+ def_bool y
+ depends on ARCH_MXC && SOC_VF610
+ select GPIOLIB_IRQCHIP
+ help
+ Say yes here to support Vybrid vf610 GPIOs.
+
config GPIO_XGENE
bool "APM X-Gene GPIO controller support"
depends on ARM64 && OF_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index e5d346cf3b6e..eb58b85c685d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_TZ1090) += gpio-tz1090.o
obj-$(CONFIG_GPIO_TZ1090_PDC) += gpio-tz1090-pdc.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
+obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
new file mode 100644
index 000000000000..4ee4cee832ec
--- /dev/null
+++ b/drivers/gpio/gpio-vf610.c
@@ -0,0 +1,295 @@
+/*
+ * vf610 GPIO support through PORT and GPIO module
+ *
+ * Copyright (c) 2014 Toradex AG.
+ *
+ * Author: Stefan Agner <stefan@agner.ch>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+
+#define VF610_GPIO_PER_PORT 32
+
+struct vf610_gpio_port {
+ struct gpio_chip gc;
+ void __iomem *base;
+ void __iomem *gpio_base;
+ u8 irqc[VF610_GPIO_PER_PORT];
+ int irq;
+};
+
+#define GPIO_PDOR 0x00
+#define GPIO_PSOR 0x04
+#define GPIO_PCOR 0x08
+#define GPIO_PTOR 0x0c
+#define GPIO_PDIR 0x10
+
+#define PORT_PCR(n) ((n) * 0x4)
+#define PORT_PCR_IRQC_OFFSET 16
+
+#define PORT_ISFR 0xa0
+#define PORT_DFER 0xc0
+#define PORT_DFCR 0xc4
+#define PORT_DFWR 0xc8
+
+#define PORT_INT_OFF 0x0
+#define PORT_INT_LOGIC_ZERO 0x8
+#define PORT_INT_RISING_EDGE 0x9
+#define PORT_INT_FALLING_EDGE 0xa
+#define PORT_INT_EITHER_EDGE 0xb
+#define PORT_INT_LOGIC_ONE 0xc
+
+static const struct of_device_id vf610_gpio_dt_ids[] = {
+ { .compatible = "fsl,vf610-gpio" },
+ { /* sentinel */ }
+};
+
+static inline void vf610_gpio_writel(u32 val, void __iomem *reg)
+{
+ writel_relaxed(val, reg);
+}
+
+static inline u32 vf610_gpio_readl(void __iomem *reg)
+{
+ return readl_relaxed(reg);
+}
+
+static int vf610_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void vf610_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
+static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct vf610_gpio_port *port =
+ container_of(gc, struct vf610_gpio_port, gc);
+
+ return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) & BIT(gpio));
+}
+
+static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct vf610_gpio_port *port =
+ container_of(gc, struct vf610_gpio_port, gc);
+ unsigned long mask = BIT(gpio);
+
+ if (val)
+ vf610_gpio_writel(mask, port->gpio_base + GPIO_PSOR);
+ else
+ vf610_gpio_writel(mask, port->gpio_base + GPIO_PCOR);
+}
+
+static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ return pinctrl_gpio_direction_input(chip->base + gpio);
+}
+
+static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
+ int value)
+{
+ vf610_gpio_set(chip, gpio, value);
+
+ return pinctrl_gpio_direction_output(chip->base + gpio);
+}
+
+static void vf610_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ struct vf610_gpio_port *port = irq_get_handler_data(irq);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ int pin;
+ unsigned long irq_isfr;
+
+ chained_irq_enter(chip, desc);
+
+ irq_isfr = vf610_gpio_readl(port->base + PORT_ISFR);
+
+ for_each_set_bit(pin, &irq_isfr, VF610_GPIO_PER_PORT) {
+ vf610_gpio_writel(BIT(pin), port->base + PORT_ISFR);
+
+ generic_handle_irq(irq_find_mapping(port->gc.irqdomain, pin));
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void vf610_gpio_irq_ack(struct irq_data *d)
+{
+ struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ int gpio = d->hwirq;
+
+ vf610_gpio_writel(BIT(gpio), port->base + PORT_ISFR);
+}
+
+static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
+{
+ struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u8 irqc;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ irqc = PORT_INT_RISING_EDGE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ irqc = PORT_INT_FALLING_EDGE;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ irqc = PORT_INT_EITHER_EDGE;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ irqc = PORT_INT_LOGIC_ZERO;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ irqc = PORT_INT_LOGIC_ONE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ port->irqc[d->hwirq] = irqc;
+
+ return 0;
+}
+
+static void vf610_gpio_irq_mask(struct irq_data *d)
+{
+ struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
+
+ vf610_gpio_writel(0, pcr_base);
+}
+
+static void vf610_gpio_irq_unmask(struct irq_data *d)
+{
+ struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+ void __iomem *pcr_base = port->base + PORT_PCR(d->hwirq);
+
+ vf610_gpio_writel(port->irqc[d->hwirq] << PORT_PCR_IRQC_OFFSET,
+ pcr_base);
+}
+
+static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable)
+{
+ struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+
+ if (enable)
+ enable_irq_wake(port->irq);
+ else
+ disable_irq_wake(port->irq);
+
+ return 0;
+}
+
+static struct irq_chip vf610_gpio_irq_chip = {
+ .name = "gpio-vf610",
+ .irq_ack = vf610_gpio_irq_ack,
+ .irq_mask = vf610_gpio_irq_mask,
+ .irq_unmask = vf610_gpio_irq_unmask,
+ .irq_set_type = vf610_gpio_irq_set_type,
+ .irq_set_wake = vf610_gpio_irq_set_wake,
+};
+
+static int vf610_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct vf610_gpio_port *port;
+ struct resource *iores;
+ struct gpio_chip *gc;
+ int ret;
+
+ port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ port->base = devm_ioremap_resource(dev, iores);
+ if (IS_ERR(port->base))
+ return PTR_ERR(port->base);
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ port->gpio_base = devm_ioremap_resource(dev, iores);
+ if (IS_ERR(port->gpio_base))
+ return PTR_ERR(port->gpio_base);
+
+ port->irq = platform_get_irq(pdev, 0);
+ if (port->irq < 0)
+ return port->irq;
+
+ gc = &port->gc;
+ gc->of_node = np;
+ gc->dev = dev;
+ gc->label = "vf610-gpio",
+ gc->ngpio = VF610_GPIO_PER_PORT,
+ gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT;
+
+ gc->request = vf610_gpio_request,
+ gc->free = vf610_gpio_free,
+ gc->direction_input = vf610_gpio_direction_input,
+ gc->get = vf610_gpio_get,
+ gc->direction_output = vf610_gpio_direction_output,
+ gc->set = vf610_gpio_set,
+
+ ret = gpiochip_add(gc);
+ if (ret < 0)
+ return ret;
+
+ /* Clear the interrupt status register for all GPIO's */
+ vf610_gpio_writel(~0, port->base + PORT_ISFR);
+
+ ret = gpiochip_irqchip_add(gc, &vf610_gpio_irq_chip, 0,
+ handle_simple_irq, IRQ_TYPE_NONE);
+ if (ret) {
+ dev_err(dev, "failed to add irqchip\n");
+ gpiochip_remove(gc);
+ return ret;
+ }
+ gpiochip_set_chained_irqchip(gc, &vf610_gpio_irq_chip, port->irq,
+ vf610_gpio_irq_handler);
+
+ return 0;
+}
+
+static struct platform_driver vf610_gpio_driver = {
+ .driver = {
+ .name = "gpio-vf610",
+ .owner = THIS_MODULE,
+ .of_match_table = vf610_gpio_dt_ids,
+ },
+ .probe = vf610_gpio_probe,
+};
+
+static int __init gpio_vf610_init(void)
+{
+ return platform_driver_register(&vf610_gpio_driver);
+}
+device_initcall(gpio_vf610_init);
+
+MODULE_AUTHOR("Stefan Agner <stefan@agner.ch>");
+MODULE_DESCRIPTION("Freescale VF610 GPIO");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 4a10ae97dbf2..deffcc6658a4 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -91,12 +91,13 @@
#define VF610_ADC_CAL 0x80
/* Other field define */
-#define VF610_ADC_ADCHC(x) ((x) & 0xF)
+#define VF610_ADC_ADCHC(x) ((x) & 0x1F)
#define VF610_ADC_AIEN (0x1 << 7)
#define VF610_ADC_CONV_DISABLE 0x1F
#define VF610_ADC_HS_COCO0 0x1
#define VF610_ADC_CALF 0x2
#define VF610_ADC_TIMEOUT msecs_to_jiffies(100)
+#define VF610_SAMPLE_FREQ_CNT 5
enum clk_sel {
VF610_ADCIOC_BUSCLK_SET,
@@ -127,6 +128,7 @@ struct vf610_adc_feature {
int res_mode;
bool lpm;
+ bool hsc;
bool calibration;
bool ovwren;
};
@@ -139,11 +141,18 @@ struct vf610_adc {
u32 vref_uv;
u32 value;
struct regulator *vref;
+ unsigned long max_clk_default;
+ unsigned long max_clk_high_speed;
+ unsigned long max_clk_low_power;
struct vf610_adc_feature adc_feature;
+ u32 sample_freq_avail[VF610_SAMPLE_FREQ_CNT];
+
struct completion completion;
};
+static const u32 vf610_hw_avgs[VF610_SAMPLE_FREQ_CNT] = { 1, 4, 8, 16, 32 };
+
#define VF610_ADC_CHAN(_idx, _chan_type) { \
.type = (_chan_type), \
.indexed = 1, \
@@ -153,6 +162,12 @@ struct vf610_adc {
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
}
+#define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \
+ .type = (_chan_type), \
+ .channel = (_idx), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+}
+
static const struct iio_chan_spec vf610_adc_iio_channels[] = {
VF610_ADC_CHAN(0, IIO_VOLTAGE),
VF610_ADC_CHAN(1, IIO_VOLTAGE),
@@ -170,38 +185,61 @@ static const struct iio_chan_spec vf610_adc_iio_channels[] = {
VF610_ADC_CHAN(13, IIO_VOLTAGE),
VF610_ADC_CHAN(14, IIO_VOLTAGE),
VF610_ADC_CHAN(15, IIO_VOLTAGE),
+ VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
/* sentinel */
};
-
-/*
- * ADC sample frequency, unit is ADCK cycles.
- * ADC clk source is ipg clock, which is the same as bus clock.
- *
- * ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
- * SFCAdder: fixed to 6 ADCK cycles
- * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
- * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
- * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
- *
- * By default, enable 12 bit resolution mode, clock source
- * set to ipg clock, So get below frequency group:
- */
-static const u32 vf610_sample_freq_avail[5] =
-{1941176, 559332, 286957, 145374, 73171};
-
-static inline void vf610_adc_cfg_init(struct vf610_adc *info)
+static inline void vf610_adc_cfg_init(struct vf610_adc *info,
+ struct device_node *node)
{
- /* set default Configuration for ADC controller */
- info->adc_feature.clk_sel = VF610_ADCIOC_BUSCLK_SET;
- info->adc_feature.vol_ref = VF610_ADCIOC_VR_VREF_SET;
+ struct vf610_adc_feature *adc_feature = &info->adc_feature;
+ unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
+ u32 max_adck_rate[3];
+ int divisor, i;
- info->adc_feature.calibration = true;
- info->adc_feature.ovwren = true;
+ /* set default Configuration for ADC controller */
+ adc_feature->clk_sel = VF610_ADCIOC_BUSCLK_SET;
+ adc_feature->vol_ref = VF610_ADCIOC_VR_VREF_SET;
+
+ adc_feature->calibration = true;
+ adc_feature->ovwren = true;
+
+ adc_feature->res_mode = 12;
+ adc_feature->sample_rate = 1;
+ adc_feature->lpm = of_property_read_bool(node, "fsl,use-lpm");
+ adc_feature->hsc = of_property_read_bool(node, "fsl,use-hsc");
+
+ /* fall-back value using a conservative divisor */
+ adc_feature->clk_div = 4;
+
+ if (!of_property_read_u32_array(node, "fsl,adck-max-frequency",
+ max_adck_rate, 3)) {
+ /* calculate clk divider which is within specification */
+ if (adc_feature->lpm)
+ divisor = ipg_rate / max_adck_rate[2];
+ else if (adc_feature->hsc)
+ divisor = ipg_rate / max_adck_rate[1];
+ else
+ divisor = ipg_rate / max_adck_rate[0];
+
+ adc_feature->clk_div = 1 << fls(divisor + 1);
+ }
- info->adc_feature.clk_div = 1;
- info->adc_feature.res_mode = 12;
- info->adc_feature.sample_rate = 1;
info->adc_feature.lpm = true;
+ /*
+ * Calculate ADC sample frequencies
+ * Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
+ * which is the same as bus clock.
+ *
+ * ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
+ * SFCAdder: fixed to 6 ADCK cycles
+ * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
+ * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
+ * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
+ */
+ adck_rate = ipg_rate / info->adc_feature.clk_div;
+ for (i = 0; i < VF610_SAMPLE_FREQ_CNT; i++)
+ info->sample_freq_avail[i] =
+ adck_rate / (6 + vf610_hw_avgs[i] * (25 + 3));
}
static void vf610_adc_cfg_post_set(struct vf610_adc *info)
@@ -428,10 +466,27 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1941176, 559332, 286957, 145374, 73171");
+static ssize_t vf610_show_samp_freq_avail(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct vf610_adc *info = iio_priv(dev_to_iio_dev(dev));
+ size_t len = 0;
+ int i;
+
+ for (i = 0; i < VF610_SAMPLE_FREQ_CNT; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "%u ", info->sample_freq_avail[i]);
+
+ /* replace trailing space by newline */
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(vf610_show_samp_freq_avail);
static struct attribute *vf610_attributes[] = {
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
NULL
};
@@ -451,6 +506,7 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
mutex_lock(&indio_dev->mlock);
reinit_completion(&info->completion);
@@ -468,7 +524,23 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
return ret;
}
- *val = info->value;
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ *val = info->value;
+ break;
+ case IIO_TEMP:
+ /*
+ * Calculate in degree Celsius times 1000
+ * Using sensor slope of 1.84 mV/°C and
+ * V at 25°C of 696 mV
+ */
+ *val = 25000 - ((int)info->value - 864) * 1000000 / 1840;
+ break;
+ default:
+ mutex_unlock(&indio_dev->mlock);
+ return -EINVAL;
+ }
+
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT;
@@ -478,7 +550,7 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
- *val = vf610_sample_freq_avail[info->adc_feature.sample_rate];
+ *val = info->sample_freq_avail[info->adc_feature.sample_rate];
*val2 = 0;
return IIO_VAL_INT;
@@ -501,9 +573,9 @@ static int vf610_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
for (i = 0;
- i < ARRAY_SIZE(vf610_sample_freq_avail);
+ i < ARRAY_SIZE(info->sample_freq_avail);
i++)
- if (val == vf610_sample_freq_avail[i]) {
+ if (val == info->sample_freq_avail[i]) {
info->adc_feature.sample_rate = i;
vf610_adc_sample_set(info);
return 0;
@@ -619,7 +691,7 @@ static int vf610_adc_probe(struct platform_device *pdev)
goto error_adc_clk_enable;
}
- vf610_adc_cfg_init(info);
+ vf610_adc_cfg_init(info, pdev->dev.of_node);
vf610_adc_hw_init(info);
ret = iio_device_register(indio_dev);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e1d8003d01f8..bcfa370227b2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -543,6 +543,13 @@ config TOUCHSCREEN_MIGOR
To compile this driver as a module, choose M here: the
module will be called migor_ts.
+config TOUCHSCREEN_FUSION_F0710A
+ tristate "TouchRevolution Fusion F0710A Touchscreens"
+ depends on I2C
+ help
+ Say Y here if you want to support the multi-touch input driver for
+ the TouchRevolution Fusion 7 and 10 panels.
+
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
@@ -962,4 +969,16 @@ config TOUCHSCREEN_ZFORCE
To compile this driver as a module, choose M here: the
module will be called zforce_ts.
+config TOUCHSCREEN_COLIBRI_VF50
+ tristate "Toradex Colibri on board touchscreen driver"
+ depends on IIO && VF610_ADC
+ help
+ Say Y here if you have a Colibri VF50 and plan to use
+ the on-board provided 4-wire touchscreen driver.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called colibri_vf50_ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 090e61cc9171..09594f917ea2 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -79,3 +79,5 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
+obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
+obj-$(CONFIG_TOUCHSCREEN_FUSION_F0710A) += fusion_F0710A.o
diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c
new file mode 100644
index 000000000000..64cf29db66a4
--- /dev/null
+++ b/drivers/input/touchscreen/colibri-vf50-ts.c
@@ -0,0 +1,429 @@
+/* Copyright 2014 Toradex AG
+ *
+ * Toradex Colibri VF50 Touchscreen driver
+ *
+ * Originally authored by Stefan Agner. Taken from the colibri_vf branch
+ * at git.toradex.com/cgit/linux-toradex.git from the driver of the same
+ * name and ported for mainline.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/of.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/types.h>
+#include <linux/pinctrl/consumer.h>
+
+#define DRIVER_NAME "colibri-vf50-ts"
+#define DRV_VERSION "1.0"
+
+#define VF_ADC_MAX ((1 << 12) - 1)
+
+#define COLI_TOUCH_MIN_DELAY_US 1000
+#define COLI_TOUCH_MAX_DELAY_US 2000
+
+static int min_pressure = 200;
+
+struct vf50_touch_device {
+ struct platform_device *pdev;
+ struct input_dev *ts_input;
+ struct workqueue_struct *ts_workqueue;
+ struct work_struct ts_work;
+ struct iio_channel *channels;
+ int pen_irq;
+ int gpio_xp;
+ int gpio_xm;
+ int gpio_yp;
+ int gpio_ym;
+ int gpio_pen_detect;
+ int gpio_pen_detect_pullup;
+ bool stop_touchscreen;
+};
+
+/*
+ * Enables given plates and measures touch parameters using ADC
+ */
+static int adc_ts_measure(struct iio_channel *channel, int plate_p, int plate_m)
+{
+ int i, value = 0, val = 0;
+ int ret;
+
+ gpio_set_value(plate_p, 0); /* Low active */
+ gpio_set_value(plate_m, 1); /* High active */
+
+ /* Use hrtimer sleep since msleep sleeps 10ms+ */
+ usleep_range(COLI_TOUCH_MIN_DELAY_US, COLI_TOUCH_MAX_DELAY_US);
+
+ for (i = 0; i < 5; i++) {
+ ret = iio_read_channel_raw(channel, &val);
+ if (ret < 0)
+ return -EINVAL;
+
+ value += val;
+ }
+
+ value /= 5;
+
+ gpio_set_value(plate_p, 1);
+ gpio_set_value(plate_m, 0);
+
+ return value;
+}
+
+/*
+ * Enable touch detection using falling edge detection on XM
+ */
+static void vf50_ts_enable_touch_detection(struct vf50_touch_device *vf50_ts)
+{
+ /* Enable plate YM (needs to be strong GND, high active) */
+ gpio_set_value(vf50_ts->gpio_ym, 1);
+
+ /* Let the platform mux to GPIO in order to enable Pull-Up on GPIO */
+ pinctrl_pm_select_idle_state(&vf50_ts->pdev->dev);
+}
+
+/*
+ * ADC touch screen sampling worker function
+ */
+static void vf50_ts_work(struct work_struct *ts_work)
+{
+ struct vf50_touch_device *vf50_ts = container_of(ts_work,
+ struct vf50_touch_device, ts_work);
+ struct device *dev = &vf50_ts->pdev->dev;
+ int val_x, val_y, val_z1, val_z2, val_p = 0;
+ bool discard_val_on_start = true;
+
+ while (!vf50_ts->stop_touchscreen) {
+ /* X-Direction */
+ val_x = adc_ts_measure(&vf50_ts->channels[0], vf50_ts->gpio_xp, vf50_ts->gpio_xm);
+ if (val_x < 0)
+ continue;
+
+ /* Y-Direction */
+ val_y = adc_ts_measure(&vf50_ts->channels[1], vf50_ts->gpio_yp, vf50_ts->gpio_ym);
+ if (val_y < 0)
+ continue;
+
+ /* Touch pressure
+ * Measure on XP/YM
+ */
+ val_z1 = adc_ts_measure(&vf50_ts->channels[2], vf50_ts->gpio_yp, vf50_ts->gpio_xm);
+ if (val_z1 < 0)
+ continue;
+ val_z2 = adc_ts_measure(&vf50_ts->channels[3], vf50_ts->gpio_yp, vf50_ts->gpio_xm);
+ if (val_z2 < 0)
+ continue;
+
+ /* According to datasheet of our touchscreen,
+ * resistance on X axis is 400~1200..
+ */
+ /* Validate signal (avoid calculation using noise) */
+ if (val_z1 > 64 && val_x > 64) {
+ /* Calculate resistance between the plates
+ * lower resistance means higher pressure */
+ int r_x = (1000 * val_x) / VF_ADC_MAX;
+ val_p = (r_x * val_z2) / val_z1 - r_x;
+ } else {
+ val_p = 2000;
+ }
+
+ val_p = 2000 - val_p;
+ dev_dbg(dev, "Measured values: x: %d, y: %d, z1: %d, z2: %d, "
+ "p: %d\n", val_x, val_y, val_z1, val_z2, val_p);
+
+ /*
+ * If touch pressure is too low, stop measuring and reenable
+ * touch detection
+ */
+
+ if (val_p < min_pressure || val_p > 2000)
+ break;
+
+ /*
+ * The pressure may not be enough for the first x and the second
+ * y measurement, but, the pressure is ok when the driver is then
+ * third and fourth measurement. To take care of this, we drop the
+ * first measurement always
+ */
+
+ if (discard_val_on_start) {
+ discard_val_on_start = false;
+ } else {
+ /* Report touch position and sleep for next measurement */
+ input_report_abs(vf50_ts->ts_input, ABS_X, VF_ADC_MAX - val_x);
+ input_report_abs(vf50_ts->ts_input, ABS_Y, VF_ADC_MAX - val_y);
+ input_report_abs(vf50_ts->ts_input, ABS_PRESSURE, val_p);
+ input_report_key(vf50_ts->ts_input, BTN_TOUCH, 1);
+ input_sync(vf50_ts->ts_input);
+ }
+
+ msleep(10);
+ }
+
+ /* Report no more touch, reenable touch detection */
+ input_report_abs(vf50_ts->ts_input, ABS_PRESSURE, 0);
+ input_report_key(vf50_ts->ts_input, BTN_TOUCH, 0);
+ input_sync(vf50_ts->ts_input);
+
+ /* Wait the pull-up to be stable on high */
+ vf50_ts_enable_touch_detection(vf50_ts);
+ msleep(10);
+
+ /* Reenable IRQ to detect touch */
+ enable_irq(vf50_ts->pen_irq);
+
+ dev_dbg(dev, "Reenabled touch detection interrupt\n");
+}
+
+static irqreturn_t vf50_tc_touched(int irq, void *dev_id)
+{
+ struct vf50_touch_device *vf50_ts = (struct vf50_touch_device *)dev_id;
+ struct device *dev = &vf50_ts->pdev->dev;
+
+ dev_dbg(dev, "Touch detected, start worker thread\n");
+
+ /* Stop IRQ */
+ disable_irq_nosync(irq);
+
+ /* Disable the touch detection plates */
+ gpio_set_value(vf50_ts->gpio_ym, 0);
+
+ /* Let the platform mux to GPIO in order to enable Pull-Up on GPIO */
+ pinctrl_pm_select_default_state(dev);
+
+ /* Start worker thread */
+ queue_work(vf50_ts->ts_workqueue, &vf50_ts->ts_work);
+
+ return IRQ_HANDLED;
+}
+
+static int vf50_ts_open(struct input_dev *dev_input)
+{
+ int ret;
+ struct vf50_touch_device *touchdev = input_get_drvdata(dev_input);
+ struct device *dev = &touchdev->pdev->dev;
+
+ dev_dbg(dev, "Input device %s opened, starting touch detection\n",
+ dev_input->name);
+
+ touchdev->stop_touchscreen = false;
+
+ /* Initialize GPIOs, leave FETs closed by default */
+ gpio_direction_output(touchdev->gpio_xp, 1); /* Low active */
+ gpio_direction_output(touchdev->gpio_xm, 0); /* High active */
+ gpio_direction_output(touchdev->gpio_yp, 1); /* Low active */
+ gpio_direction_output(touchdev->gpio_ym, 0); /* High active */
+
+ /* Mux detection before request IRQ, wait for pull-up to settle */
+ vf50_ts_enable_touch_detection(touchdev);
+ msleep(10);
+
+ touchdev->pen_irq = gpio_to_irq(touchdev->gpio_pen_detect);
+ if (touchdev->pen_irq < 0) {
+ dev_err(dev, "Unable to get IRQ for GPIO %d\n",
+ touchdev->gpio_pen_detect);
+ return touchdev->pen_irq;
+ }
+
+ ret = request_irq(touchdev->pen_irq, vf50_tc_touched, IRQF_TRIGGER_FALLING,
+ "touch detected", touchdev);
+ if (ret < 0) {
+ dev_err(dev, "Unable to request IRQ %d\n", touchdev->pen_irq);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void vf50_ts_close(struct input_dev *dev_input)
+{
+ struct vf50_touch_device *touchdev = input_get_drvdata(dev_input);
+ struct device *dev = &touchdev->pdev->dev;
+
+ free_irq(touchdev->pen_irq, touchdev);
+
+ touchdev->stop_touchscreen = true;
+
+ /* Wait until touchscreen thread finishes any possible remnants. */
+ cancel_work_sync(&touchdev->ts_work);
+
+ dev_dbg(dev, "Input device %s closed, disable touch detection\n",
+ dev_input->name);
+}
+
+static int vf50_ts_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct vf50_touch_device *touchdev;
+ struct input_dev *input;
+ struct iio_channel *channels;
+
+ if (!node) {
+ dev_err(dev, "Device does not have associated DT data\n");
+ return -EINVAL;
+ }
+
+ channels = iio_channel_get_all(dev);
+ if (IS_ERR(channels))
+ return PTR_ERR(channels);
+
+ touchdev = devm_kzalloc(dev, sizeof(*touchdev), GFP_KERNEL);
+ if (touchdev == NULL) {
+ ret = -ENOMEM;
+ goto error_release_channels;
+ }
+
+ input = devm_input_allocate_device(dev);
+ if (!input) {
+ dev_err(dev, "Failed to allocate TS input device\n");
+ ret = -ENOMEM;
+ goto error_release_channels;
+ }
+
+ platform_set_drvdata(pdev, touchdev);
+
+ touchdev->pdev = pdev;
+ touchdev->channels = channels;
+
+ input->name = DRIVER_NAME;
+ input->id.bustype = BUS_HOST;
+ input->dev.parent = dev;
+ input->open = vf50_ts_open;
+ input->close = vf50_ts_close;
+
+ _set_bit(EV_ABS, input->evbit);
+ _set_bit(EV_KEY, input->evbit);
+ _set_bit(BTN_TOUCH, input->keybit);
+ input_set_abs_params(input, ABS_X, 0, VF_ADC_MAX, 0, 0);
+ input_set_abs_params(input, ABS_Y, 0, VF_ADC_MAX, 0, 0);
+ input_set_abs_params(input, ABS_PRESSURE, 0, VF_ADC_MAX, 0, 0);
+
+ touchdev->ts_input = input;
+ input_set_drvdata(input, touchdev);
+ ret = input_register_device(input);
+ if (ret) {
+ dev_err(dev, "Failed to register input device\n");
+ goto error_release_channels;
+ }
+
+ ret = of_property_read_u32(node, "vf,gpio-xp", &touchdev->gpio_xp);
+ if (ret)
+ goto error_release_channels;
+
+ ret = of_property_read_u32(node, "vf,gpio-xm", &touchdev->gpio_xm);
+ if (ret)
+ goto error_release_channels;
+
+ ret = of_property_read_u32(node, "vf,gpio-yp", &touchdev->gpio_yp);
+ if (ret)
+ goto error_release_channels;
+
+ ret = of_property_read_u32(node, "vf,gpio-ym", &touchdev->gpio_ym);
+ if (ret)
+ goto error_release_channels;
+
+ ret = of_property_read_u32(node, "vf,gpio-pen-detect", &touchdev->gpio_pen_detect);
+ if (ret)
+ goto error_release_channels;
+
+ ret = of_property_read_u32(node, "vf,gpio-pen-pullup", &touchdev->gpio_pen_detect_pullup);
+ if (ret)
+ goto error_release_channels;
+
+ /* Request GPIO's for FET's and touch detection */
+ ret = devm_gpio_request(dev, touchdev->gpio_xp, "Touchscreen XP");
+ if (ret)
+ goto error_release_channels;
+
+ ret = devm_gpio_request(dev, touchdev->gpio_xm, "Touchscreen XM");
+ if (ret)
+ goto error_release_channels;
+
+ ret = devm_gpio_request(dev, touchdev->gpio_yp, "Touchscreen YP");
+ if (ret)
+ goto error_release_channels;
+
+ ret = devm_gpio_request(dev, touchdev->gpio_ym, "Touchscreen YM");
+ if (ret)
+ goto error_release_channels;
+
+ ret = devm_gpio_request(dev, touchdev->gpio_pen_detect, "Pen/Touch Detect");
+ if (ret)
+ goto error_release_channels;
+
+ ret = devm_gpio_request(dev, touchdev->gpio_pen_detect_pullup, "Pen/Touch Detect pull-up");
+ if (ret)
+ goto error_release_channels;
+
+ /* Create workqueue for ADC sampling and calculation */
+ INIT_WORK(&touchdev->ts_work, vf50_ts_work);
+ touchdev->ts_workqueue = create_singlethread_workqueue("vf50-ts-touch");
+
+ if (!touchdev->ts_workqueue) {
+ dev_err(dev, "Failed to create vf50-ts-touch workqueue");
+ goto error_release_channels;
+ }
+
+ dev_info(dev, "Attached colibri-vf50-ts driver successfully\n");
+
+ return 0;
+
+error_release_channels:
+ iio_channel_release_all(channels);
+ return ret;
+}
+
+static int vf50_ts_remove(struct platform_device *pdev)
+{
+ struct vf50_touch_device *touchdev = platform_get_drvdata(pdev);
+
+ input_unregister_device(touchdev->ts_input);
+ input_free_device(touchdev->ts_input);
+
+ destroy_workqueue(touchdev->ts_workqueue);
+ iio_channel_release_all(touchdev->channels);
+
+ return 0;
+}
+
+static const struct of_device_id vf50_touch_of_match[] = {
+ { .compatible = "toradex,vf50-touchctrl", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, vf50_touch_of_match);
+
+static struct platform_driver __refdata vf50_touch_driver = {
+ .driver = {
+ .name = "toradex,vf50_touchctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = vf50_touch_of_match,
+ },
+ .probe = vf50_ts_probe,
+ .remove = vf50_ts_remove,
+ .prevent_deferred_probe = false,
+};
+
+module_platform_driver(vf50_touch_driver);
+
+module_param(min_pressure, int, 0600);
+MODULE_PARM_DESC(min_pressure, "Minimum pressure for touch detection");
+MODULE_AUTHOR("Sanchayan Maity");
+MODULE_DESCRIPTION("Colibri VF50 Touchscreen driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/input/touchscreen/fusion_F0710A.c b/drivers/input/touchscreen/fusion_F0710A.c
new file mode 100644
index 000000000000..48b8808e367e
--- /dev/null
+++ b/drivers/input/touchscreen/fusion_F0710A.c
@@ -0,0 +1,548 @@
+/*
+ * "fusion_F0710A" touchscreen driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <linux/gpio.h>
+#include <linux/input/fusion_F0710A.h>
+#include <linux/slab.h>
+#include <linux/of_gpio.h>
+
+
+#include "fusion_F0710A.h"
+
+#define DRV_NAME "fusion_F0710A"
+
+
+static struct fusion_F0710A_data fusion_F0710A;
+
+static unsigned short normal_i2c[] = { fusion_F0710A_I2C_SLAVE_ADDR, I2C_CLIENT_END };
+
+//I2C_CLIENT_INSMOD;
+
+static int fusion_F0710A_write_u8(u8 addr, u8 data)
+{
+ return i2c_smbus_write_byte_data(fusion_F0710A.client, addr, data);
+}
+
+static int fusion_F0710A_read_u8(u8 addr)
+{
+ return i2c_smbus_read_byte_data(fusion_F0710A.client, addr);
+}
+
+static int fusion_F0710A_read_block(u8 addr, u8 len, u8 *data)
+{
+#if 0
+ /* When i2c_smbus_read_i2c_block_data() takes a block length parameter, we can do
+ * this. lm-sensors lists hints this has been fixed, but I can't tell whether it
+ * was or will be merged upstream. */
+
+ return i2c_smbus_read_i2c_block_data(&fusion_F0710A.client, addr, data);
+#else
+ u8 msgbuf0[1] = { addr };
+ u16 slave = fusion_F0710A.client->addr;
+ u16 flags = fusion_F0710A.client->flags;
+ struct i2c_msg msg[2] = { { slave, flags, 1, msgbuf0 },
+ { slave, flags | I2C_M_RD, len, data }
+ };
+
+ return i2c_transfer(fusion_F0710A.client->adapter, msg, ARRAY_SIZE(msg));
+#endif
+}
+
+
+static int fusion_F0710A_register_input(void)
+{
+ int ret;
+ struct input_dev *dev;
+
+ dev = fusion_F0710A.input = input_allocate_device();
+ if (dev == NULL)
+ return -ENOMEM;
+
+ dev->name = "fusion_F0710A";
+
+ set_bit(EV_KEY, dev->evbit);
+ set_bit(EV_ABS, dev->evbit);
+
+ input_set_abs_params(dev, ABS_MT_POSITION_X, 0, fusion_F0710A.info.xres-1, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, fusion_F0710A.info.yres-1, 0, 0);
+ input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(dev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
+
+ input_set_abs_params(dev, ABS_X, 0, fusion_F0710A.info.xres-1, 0, 0);
+ input_set_abs_params(dev, ABS_Y, 0, fusion_F0710A.info.yres-1, 0, 0);
+ input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
+
+ ret = input_register_device(dev);
+ if (ret < 0)
+ goto bail1;
+
+ return 0;
+
+bail1:
+ input_free_device(dev);
+ return ret;
+}
+
+#define WC_RETRY_COUNT 3
+static int fusion_F0710A_write_complete(void)
+{
+ int ret, i;
+
+ for(i=0; i<WC_RETRY_COUNT; i++)
+ {
+ ret = fusion_F0710A_write_u8(fusion_F0710A_SCAN_COMPLETE, 0);
+ if(ret == 0)
+ break;
+ else
+ dev_err(&fusion_F0710A.client->dev, "Write complete failed(%d): %d\n", i, ret);
+ }
+
+ return ret;
+}
+
+#define DATA_START fusion_F0710A_DATA_INFO
+#define DATA_END fusion_F0710A_SEC_TIDTS
+#define DATA_LEN (DATA_END - DATA_START + 1)
+#define DATA_OFF(x) ((x) - DATA_START)
+
+static int fusion_F0710A_read_sensor(void)
+{
+ int ret;
+ u8 data[DATA_LEN];
+
+#define DATA(x) (data[DATA_OFF(x)])
+ /* To ensure data coherency, read the sensor with a single transaction. */
+ ret = fusion_F0710A_read_block(DATA_START, DATA_LEN, data);
+ if (ret < 0) {
+ dev_err(&fusion_F0710A.client->dev,
+ "Read block failed: %d\n", ret);
+
+ return ret;
+ }
+
+ fusion_F0710A.f_num = DATA(fusion_F0710A_DATA_INFO)&0x03;
+
+ fusion_F0710A.y1 = DATA(fusion_F0710A_POS_X1_HI) << 8;
+ fusion_F0710A.y1 |= DATA(fusion_F0710A_POS_X1_LO);
+ fusion_F0710A.x1 = DATA(fusion_F0710A_POS_Y1_HI) << 8;
+ fusion_F0710A.x1 |= DATA(fusion_F0710A_POS_Y1_LO);
+ fusion_F0710A.z1 = DATA(fusion_F0710A_FIR_PRESS);
+ fusion_F0710A.tip1 = DATA(fusion_F0710A_FIR_TIDTS)&0x0f;
+ fusion_F0710A.tid1 = (DATA(fusion_F0710A_FIR_TIDTS)&0xf0)>>4;
+
+
+ fusion_F0710A.y2 = DATA(fusion_F0710A_POS_X2_HI) << 8;
+ fusion_F0710A.y2 |= DATA(fusion_F0710A_POS_X2_LO);
+ fusion_F0710A.x2 = DATA(fusion_F0710A_POS_Y2_HI) << 8;
+ fusion_F0710A.x2 |= DATA(fusion_F0710A_POS_Y2_LO);
+ fusion_F0710A.z2 = DATA(fusion_F0710A_SEC_PRESS);
+ fusion_F0710A.tip2 = DATA(fusion_F0710A_SEC_TIDTS)&0x0f;
+ fusion_F0710A.tid2 =(DATA(fusion_F0710A_SEC_TIDTS)&0xf0)>>4;
+#undef DATA
+
+ return 0;
+}
+
+#define val_cut_max(x, max, reverse) \
+do \
+{ \
+ if(x > max) \
+ x = max; \
+ if(reverse) \
+ x = (max) - (x); \
+} \
+while(0)
+
+static void fusion_F0710A_wq(struct work_struct *work)
+{
+ struct input_dev *dev = fusion_F0710A.input;
+ int save_points = 0;
+ int x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0;
+
+ if (fusion_F0710A_read_sensor() < 0)
+ goto restore_irq;
+
+#ifdef DEBUG
+ printk(KERN_DEBUG "tip1, tid1, x1, y1, z1 (%x,%x,%d,%d,%d); tip2, tid2, x2, y2, z2 (%x,%x,%d,%d,%d)\n",
+ fusion_F0710A.tip1, fusion_F0710A.tid1, fusion_F0710A.x1, fusion_F0710A.y1, fusion_F0710A.z1,
+ fusion_F0710A.tip2, fusion_F0710A.tid2, fusion_F0710A.x2, fusion_F0710A.y2, fusion_F0710A.z2);
+#endif /* DEBUG */
+
+ val_cut_max(fusion_F0710A.x1, fusion_F0710A.info.xres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.y1, fusion_F0710A.info.yres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.x2, fusion_F0710A.info.xres-1, fusion_F0710A.info.xy_reverse);
+ val_cut_max(fusion_F0710A.y2, fusion_F0710A.info.yres-1, fusion_F0710A.info.xy_reverse);
+
+ if(fusion_F0710A.tip1 == 1)
+ {
+ if(fusion_F0710A.tid1 == 1)
+ {
+ /* first point */
+ x1 = fusion_F0710A.x1;
+ y1 = fusion_F0710A.y1;
+ z1 = fusion_F0710A.z1;
+ save_points |= fusion_F0710A_SAVE_PT1;
+ }
+ else if(fusion_F0710A.tid1 == 2)
+ {
+ /* second point ABS_DISTANCE second point pressure, BTN_2 second point touch */
+ x2 = fusion_F0710A.x1;
+ y2 = fusion_F0710A.y1;
+ z2 = fusion_F0710A.z1;
+ save_points |= fusion_F0710A_SAVE_PT2;
+ }
+ }
+
+ if(fusion_F0710A.tip2 == 1)
+ {
+ if(fusion_F0710A.tid2 == 2)
+ {
+ /* second point ABS_DISTANCE second point pressure, BTN_2 second point touch */
+ x2 = fusion_F0710A.x2;
+ y2 = fusion_F0710A.y2;
+ z2 = fusion_F0710A.z2;
+ save_points |= fusion_F0710A_SAVE_PT2;
+ }
+ else if(fusion_F0710A.tid2 == 1)/* maybe this will never happen */
+ {
+ /* first point */
+ x1 = fusion_F0710A.x2;
+ y1 = fusion_F0710A.y2;
+ z1 = fusion_F0710A.z2;
+ save_points |= fusion_F0710A_SAVE_PT1;
+ }
+ }
+
+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z1);
+ input_report_abs(dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_report_abs(dev, ABS_MT_POSITION_X, x1);
+ input_report_abs(dev, ABS_MT_POSITION_Y, y1);
+ input_mt_sync(dev);
+ input_report_abs(dev, ABS_MT_TOUCH_MAJOR, z2);
+ input_report_abs(dev, ABS_MT_WIDTH_MAJOR, 2);
+ input_report_abs(dev, ABS_MT_POSITION_X, x2);
+ input_report_abs(dev, ABS_MT_POSITION_Y, y2);
+ input_mt_sync(dev);
+
+ input_report_abs(dev, ABS_X, x1);
+ input_report_abs(dev, ABS_Y, y1);
+ input_report_abs(dev, ABS_PRESSURE, z1);
+ input_report_key(dev, BTN_TOUCH, fusion_F0710A.tip1);
+
+ input_sync(dev);
+
+restore_irq:
+ enable_irq(fusion_F0710A.client->irq);
+
+ /* Clear fusion_F0710A interrupt */
+ fusion_F0710A_write_complete();
+}
+static DECLARE_WORK(fusion_F0710A_work, fusion_F0710A_wq);
+
+static irqreturn_t fusion_F0710A_interrupt(int irq, void *dev_id)
+{
+ disable_irq_nosync(fusion_F0710A.client->irq);
+
+ queue_work(fusion_F0710A.workq, &fusion_F0710A_work);
+
+ return IRQ_HANDLED;
+}
+
+const static u8* g_ver_product[4] = {
+ "10Z8", "70Z7", "43Z6", ""
+};
+
+static int of_fusion_F0710A_get_pins(struct device_node *np,
+ unsigned int *int_pin, unsigned int *reset_pin)
+{
+ if (of_gpio_count(np) < 2)
+ return -ENODEV;
+
+ *int_pin = of_get_gpio(np, 0);
+ *reset_pin = of_get_gpio(np, 1);
+
+ if (!gpio_is_valid(*int_pin) || !gpio_is_valid(*reset_pin)) {
+ pr_err("%s: invalid GPIO pins, int=%d/reset=%d\n",
+ np->full_name, *int_pin, *reset_pin);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int fusion_F0710A_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ struct device_node *np = i2c->dev.of_node;
+ struct fusion_f0710a_init_data *pdata = i2c->dev.platform_data;
+ int ret;
+ u8 ver_product, ver_id;
+ u32 version;
+
+ if (np != NULL) {
+ pdata = i2c->dev.platform_data =
+ devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+ if (pdata == NULL) {
+ dev_err(&i2c->dev, "No platform data for Fusion driver\n");
+ return -ENODEV;
+ }
+ /* the dtb did the pinmuxing for us */
+ pdata->pinmux_fusion_pins = NULL;
+ ret = of_fusion_F0710A_get_pins(i2c->dev.of_node,
+ &pdata->gpio_int, &pdata->gpio_reset);
+ if (ret)
+ return ret;
+ }
+ else if (pdata == NULL) {
+ dev_err(&i2c->dev, "No platform data for Fusion driver\n");
+ return -ENODEV;
+ }
+
+ /* Request pinmuxing, if necessary */
+ if (pdata->pinmux_fusion_pins != NULL) {
+ ret = pdata->pinmux_fusion_pins();
+ if (ret < 0) {
+ dev_err(&i2c->dev, "muxing GPIOs failed\n");
+ return -ENODEV;
+ }
+ }
+
+ if ((gpio_request(pdata->gpio_int, "Fusion pen down interrupt") == 0) &&
+ (gpio_direction_input(pdata->gpio_int) == 0)) {
+ gpio_export(pdata->gpio_int, 0);
+ } else {
+ dev_warn(&i2c->dev, "Could not obtain GPIO for Fusion pen down\n");
+ return -ENODEV;
+ }
+
+ if ((gpio_request(pdata->gpio_reset, "Fusion reset") == 0) &&
+ (gpio_direction_output(pdata->gpio_reset, 1) == 0)) {
+
+ /* Generate a 0 => 1 edge explicitly, and wait for startup... */
+ gpio_set_value(pdata->gpio_reset, 0);
+ msleep(10);
+ gpio_set_value(pdata->gpio_reset, 1);
+ /* Wait for startup (up to 125ms according to datasheet) */
+ msleep(125);
+
+ gpio_export(pdata->gpio_reset, 0);
+ } else {
+ dev_warn(&i2c->dev, "Could not obtain GPIO for Fusion reset\n");
+ ret = -ENODEV;
+ goto bail0;
+ }
+
+ /* Use Pen Down GPIO as sampling interrupt */
+ i2c->irq = gpio_to_irq(pdata->gpio_int);
+ irq_set_irq_type(i2c->irq, IRQ_TYPE_LEVEL_HIGH);
+
+ if(!i2c->irq)
+ {
+ dev_err(&i2c->dev, "fusion_F0710A irq < 0 \n");
+ ret = -ENOMEM;
+ goto bail1;
+ }
+
+ /* Attach the I2C client */
+ fusion_F0710A.client = i2c;
+ i2c_set_clientdata(i2c, &fusion_F0710A);
+
+ dev_info(&i2c->dev, "Touchscreen registered with bus id (%d) with slave address 0x%x\n",
+ i2c_adapter_id(fusion_F0710A.client->adapter), fusion_F0710A.client->addr);
+
+ /* Read out a lot of registers */
+ ret = fusion_F0710A_read_u8(fusion_F0710A_VIESION_INFO_LO);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "query failed: %d\n", ret);
+ goto bail1;
+ }
+ ver_product = (((u8)ret) & 0xc0) >> 6;
+ version = (10 + ((((u32)ret)&0x30) >> 4)) * 100000;
+ version += (((u32)ret)&0xf) * 1000;
+ /* Read out a lot of registers */
+ ret = fusion_F0710A_read_u8(fusion_F0710A_VIESION_INFO);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "query failed: %d\n", ret);
+ goto bail1;
+ }
+ ver_id = ((u8)(ret) & 0x6) >> 1;
+ version += ((((u32)ret) & 0xf8) >> 3) * 10;
+ version += (((u32)ret) & 0x1) + 1; /* 0 is build 1, 1 is build 2 */
+ dev_info(&i2c->dev, "version product %s(%d)\n", g_ver_product[ver_product] ,ver_product);
+ dev_info(&i2c->dev, "version id %s(%d)\n", ver_id ? "1.4" : "1.0", ver_id);
+ dev_info(&i2c->dev, "version series (%d)\n", version);
+
+ switch(ver_product)
+ {
+ case fusion_F0710A_VIESION_07: /* 7 inch */
+ fusion_F0710A.info.xres = fusion_F0710A07_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A07_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A07_REV;
+ break;
+ case fusion_F0710A_VIESION_43: /* 4.3 inch */
+ fusion_F0710A.info.xres = fusion_F0710A43_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A43_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A43_REV;
+ break;
+ default: /* fusion_F0710A_VIESION_10 10 inch */
+ fusion_F0710A.info.xres = fusion_F0710A10_XMAX;
+ fusion_F0710A.info.yres = fusion_F0710A10_YMAX;
+ fusion_F0710A.info.xy_reverse = fusion_F0710A10_REV;
+ break;
+ }
+
+ /* Register the input device. */
+ ret = fusion_F0710A_register_input();
+ if (ret < 0) {
+ dev_err(&i2c->dev, "can't register input: %d\n", ret);
+ goto bail1;
+ }
+
+ /* Create a worker thread */
+ fusion_F0710A.workq = create_singlethread_workqueue(DRV_NAME);
+ if (fusion_F0710A.workq == NULL) {
+ dev_err(&i2c->dev, "can't create work queue\n");
+ ret = -ENOMEM;
+ goto bail2;
+ }
+
+
+ /* Register for the interrupt and enable it. Our handler will
+ * start getting invoked after this call. */
+ ret = request_irq(i2c->irq, fusion_F0710A_interrupt, IRQF_TRIGGER_RISING,
+ i2c->name, &fusion_F0710A);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "can't get irq %d: %d\n", i2c->irq, ret);
+ goto bail3;
+ }
+ /* clear the irq first */
+ ret = fusion_F0710A_write_u8(fusion_F0710A_SCAN_COMPLETE, 0);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Clear irq failed: %d\n", ret);
+ goto bail4;
+ }
+
+ return 0;
+
+bail4:
+ free_irq(i2c->irq, &fusion_F0710A);
+
+bail3:
+ destroy_workqueue(fusion_F0710A.workq);
+ fusion_F0710A.workq = NULL;
+
+bail2:
+ input_unregister_device(fusion_F0710A.input);
+bail1:
+ gpio_free(pdata->gpio_reset);
+bail0:
+ gpio_free(pdata->gpio_int);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int fusion_F0710A_suspend(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ disable_irq(i2c->irq);
+ flush_workqueue(fusion_F0710A.workq);
+
+ return 0;
+}
+
+static int fusion_F0710A_resume(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ enable_irq(i2c->irq);
+
+ return 0;
+}
+#endif
+
+static int fusion_F0710A_remove(struct i2c_client *i2c)
+{
+ struct fusion_f0710a_init_data *pdata = i2c->dev.platform_data;
+
+ gpio_free(pdata->gpio_int);
+ gpio_free(pdata->gpio_reset);
+ destroy_workqueue(fusion_F0710A.workq);
+ free_irq(i2c->irq, &fusion_F0710A);
+ input_unregister_device(fusion_F0710A.input);
+ i2c_set_clientdata(i2c, NULL);
+
+ dev_info(&i2c->dev, "driver removed\n");
+
+ return 0;
+}
+
+static struct i2c_device_id fusion_F0710A_id[] = {
+ {"fusion_F0710A", 0},
+ {},
+};
+
+
+static const struct of_device_id fusion_F0710A_dt_ids[] = {
+ {
+ .compatible = "touchrevolution,fusion-f0710a",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, fusion_F0710A_dt_ids);
+
+static const struct dev_pm_ops fusion_F0710A_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(fusion_F0710A_suspend, fusion_F0710A_resume)
+};
+
+static struct i2c_driver fusion_F0710A_i2c_drv = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .pm = &fusion_F0710A_pm_ops,
+ .of_match_table = fusion_F0710A_dt_ids,
+ },
+ .probe = fusion_F0710A_probe,
+ .remove = fusion_F0710A_remove,
+ .id_table = fusion_F0710A_id,
+ .address_list = normal_i2c,
+};
+
+static int __init fusion_F0710A_init( void )
+{
+ int ret;
+
+ memset(&fusion_F0710A, 0, sizeof(fusion_F0710A));
+
+ /* Probe for fusion_F0710A on I2C. */
+ ret = i2c_add_driver(&fusion_F0710A_i2c_drv);
+ if (ret < 0) {
+ printk(KERN_WARNING DRV_NAME " can't add i2c driver: %d\n", ret);
+ }
+
+ return ret;
+}
+
+static void __exit fusion_F0710A_exit( void )
+{
+ i2c_del_driver(&fusion_F0710A_i2c_drv);
+}
+module_init(fusion_F0710A_init);
+module_exit(fusion_F0710A_exit);
+
+MODULE_DESCRIPTION("fusion_F0710A Touchscreen Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/fusion_F0710A.h b/drivers/input/touchscreen/fusion_F0710A.h
new file mode 100644
index 000000000000..85f8210345a9
--- /dev/null
+++ b/drivers/input/touchscreen/fusion_F0710A.h
@@ -0,0 +1,87 @@
+/*
+ * "fusion_F0710A" touchscreen driver
+ *
+ * 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.
+ */
+
+/* I2C slave address */
+#define fusion_F0710A_I2C_SLAVE_ADDR 0x10
+
+/* I2C registers */
+#define fusion_F0710A_DATA_INFO 0x00
+
+/* First Point*/
+#define fusion_F0710A_POS_X1_HI 0x01 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_X1_LO 0x02 /* 16-bit register, LSB */
+#define fusion_F0710A_POS_Y1_HI 0x03 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_Y1_LO 0x04 /* 16-bit register, LSB */
+#define fusion_F0710A_FIR_PRESS 0X05
+#define fusion_F0710A_FIR_TIDTS 0X06
+
+/* Second Point */
+#define fusion_F0710A_POS_X2_HI 0x07 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_X2_LO 0x08 /* 16-bit register, LSB */
+#define fusion_F0710A_POS_Y2_HI 0x09 /* 16-bit register, MSB */
+#define fusion_F0710A_POS_Y2_LO 0x0A /* 16-bit register, LSB */
+#define fusion_F0710A_SEC_PRESS 0x0B
+#define fusion_F0710A_SEC_TIDTS 0x0C
+
+#define fusion_F0710A_VIESION_INFO_LO 0X0E
+#define fusion_F0710A_VIESION_INFO 0X0F
+
+#define fusion_F0710A_RESET 0x10
+#define fusion_F0710A_SCAN_COMPLETE 0x11
+
+
+#define fusion_F0710A_VIESION_10 0
+#define fusion_F0710A_VIESION_07 1
+#define fusion_F0710A_VIESION_43 2
+
+/* fusion_F0710A 10 inch panel */
+#define fusion_F0710A10_XMAX 2275
+#define fusion_F0710A10_YMAX 1275
+#define fusion_F0710A10_REV 1
+
+/* fusion_F0710A 7 inch panel */
+#define fusion_F0710A07_XMAX 1500
+#define fusion_F0710A07_YMAX 900
+#define fusion_F0710A07_REV 0
+
+/* fusion_F0710A 4.3 inch panel */
+#define fusion_F0710A43_XMAX 900
+#define fusion_F0710A43_YMAX 500
+#define fusion_F0710A43_REV 0
+
+#define fusion_F0710A_SAVE_PT1 0x1
+#define fusion_F0710A_SAVE_PT2 0x2
+
+
+
+/* fusion_F0710A touch screen information */
+struct fusion_F0710A_info {
+ int xres; /* x resolution */
+ int yres; /* y resolution */
+ int xy_reverse; /* if need reverse in the x,y value x=xres-1-x, y=yres-1-y*/
+};
+
+struct fusion_F0710A_data {
+ struct fusion_F0710A_info info;
+ struct i2c_client *client;
+ struct workqueue_struct *workq;
+ struct input_dev *input;
+ u16 x1;
+ u16 y1;
+ u8 z1;
+ u8 tip1;
+ u8 tid1;
+ u16 x2;
+ u16 y2;
+ u8 z2;
+ u8 tip2;
+ u8 tid2;
+ u8 f_num;
+ u8 save_points;
+};
+
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index c5b01d6bb85d..0bc864ef914e 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -31,6 +31,7 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/pm_runtime.h>
#ifdef CONFIG_PPC
#include <asm/machdep.h>
#endif
@@ -237,17 +238,29 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister);
#ifdef CONFIG_PM
int sdhci_pltfm_suspend(struct device *dev)
{
+ int ret;
struct sdhci_host *host = dev_get_drvdata(dev);
- return sdhci_suspend_host(host);
+ pm_runtime_get_sync(dev);
+ ret = sdhci_suspend_host(host);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);
int sdhci_pltfm_resume(struct device *dev)
{
+ int ret;
struct sdhci_host *host = dev_get_drvdata(dev);
- return sdhci_resume_host(host);
+ pm_runtime_get_sync(dev);
+ ret = sdhci_resume_host(host);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index dd10646982ae..9d2fbcbc83ef 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -453,6 +453,19 @@ config MTD_NAND_MPC5121_NFC
This enables the driver for the NAND flash controller on the
MPC5121 SoC.
+config HAVE_NAND_FSL_NFC
+ bool
+
+config MTD_NAND_FSL_NFC
+ tristate "Support for Freescale NFC"
+ depends on HAVE_NAND_FSL_NFC
+ help
+ Enables support for NAND Flash controller on some Freescale
+ processors like the MPC5125, VF610, MCF54418, and Kinetis K70.
+ The driver supports a maximum 2k page size. With 2k pages and
+ 64 bytes or more of OOB, hardware ECC with 24bit correction is
+ supported. Only MTD_OF (device tree) can enable the hardware ECC.
+
config MTD_NAND_MXC
tristate "MXC NAND support"
depends on ARCH_MXC
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 9c847e469ca7..d06181980b0c 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
obj-$(CONFIG_MTD_NAND_FSL_IFC) += fsl_ifc_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_NFC) += fsl_nfc.o
obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o
obj-$(CONFIG_MTD_NAND_SLC_LPC32XX) += lpc32xx_slc.o
obj-$(CONFIG_MTD_NAND_MLC_LPC32XX) += lpc32xx_mlc.o
diff --git a/drivers/mtd/nand/fsl_nfc.c b/drivers/mtd/nand/fsl_nfc.c
new file mode 100644
index 000000000000..bfc7b7b7190a
--- /dev/null
+++ b/drivers/mtd/nand/fsl_nfc.c
@@ -0,0 +1,847 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * Description: MPC5125, VF610, MCF54418 and Kinetis K70 Nand driver.
+ * Jason ported to M54418TWR and MVFA5.
+ * Authors: Shaohui Xie <b21989@freescale.com>
+ * Jason Jin <Jason.jin@freescale.com>
+ *
+ * Based on original driver mpc5121_nfc.c.
+ *
+ * This 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.
+ *
+ * Limitations:
+ * - Untested on MPC5125 and M54418.
+ * - DMA not used.
+ * - 2K pages or less.
+ * - Only 2K page w. 64+OOB and hardware ECC.
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_mtd.h>
+
+#define DRV_NAME "fsl_nfc"
+
+/* Register Offsets */
+#define NFC_FLASH_CMD1 0x3F00
+#define NFC_FLASH_CMD2 0x3F04
+#define NFC_COL_ADDR 0x3F08
+#define NFC_ROW_ADDR 0x3F0c
+#define NFC_ROW_ADDR_INC 0x3F14
+#define NFC_FLASH_STATUS1 0x3F18
+#define NFC_FLASH_STATUS2 0x3F1c
+#define NFC_CACHE_SWAP 0x3F28
+#define NFC_SECTOR_SIZE 0x3F2c
+#define NFC_FLASH_CONFIG 0x3F30
+#define NFC_IRQ_STATUS 0x3F38
+
+/* Addresses for NFC MAIN RAM BUFFER areas */
+#define NFC_MAIN_AREA(n) ((n) * 0x1000)
+
+#define PAGE_2K 0x0800
+#define OOB_64 0x0040
+
+/* NFC_CMD2[CODE] values. See section:
+ - 31.4.7 Flash Command Code Description, Vybrid manual
+ - 23.8.6 Flash Command Sequencer, MPC5125 manual
+
+ Briefly these are bitmasks of controller cycles.
+*/
+#define READ_PAGE_CMD_CODE 0x7EE0
+#define PROGRAM_PAGE_CMD_CODE 0x7FC0
+#define ERASE_CMD_CODE 0x4EC0
+#define READ_ID_CMD_CODE 0x4804
+#define RESET_CMD_CODE 0x4040
+#define STATUS_READ_CMD_CODE 0x4068
+
+/* NFC ECC mode define */
+#define ECC_BYPASS 0
+#define ECC_45_BYTE 6
+
+/*** Register Mask and bit definitions */
+
+/* NFC_FLASH_CMD1 Field */
+#define CMD_BYTE2_MASK 0xFF000000
+#define CMD_BYTE2_SHIFT 24
+
+/* NFC_FLASH_CM2 Field */
+#define CMD_BYTE1_MASK 0xFF000000
+#define CMD_BYTE1_SHIFT 24
+#define CMD_CODE_MASK 0x00FFFF00
+#define CMD_CODE_SHIFT 8
+#define BUFNO_MASK 0x00000006
+#define BUFNO_SHIFT 1
+#define START_BIT (1<<0)
+
+/* NFC_COL_ADDR Field */
+#define COL_ADDR_MASK 0x0000FFFF
+#define COL_ADDR_SHIFT 0
+
+/* NFC_ROW_ADDR Field */
+#define ROW_ADDR_MASK 0x00FFFFFF
+#define ROW_ADDR_SHIFT 0
+#define ROW_ADDR_CHIP_SEL_RB_MASK 0xF0000000
+#define ROW_ADDR_CHIP_SEL_RB_SHIFT 28
+#define ROW_ADDR_CHIP_SEL_MASK 0x0F000000
+#define ROW_ADDR_CHIP_SEL_SHIFT 24
+
+/* NFC_FLASH_STATUS2 Field */
+#define STATUS_BYTE1_MASK 0x000000FF
+
+/* NFC_FLASH_CONFIG Field */
+#define CONFIG_ECC_SRAM_ADDR_MASK 0x7FC00000
+#define CONFIG_ECC_SRAM_ADDR_SHIFT 22
+#define CONFIG_ECC_SRAM_REQ_BIT (1<<21)
+#define CONFIG_DMA_REQ_BIT (1<<20)
+#define CONFIG_ECC_MODE_MASK 0x000E0000
+#define CONFIG_ECC_MODE_SHIFT 17
+#define CONFIG_FAST_FLASH_BIT (1<<16)
+#define CONFIG_16BIT (1<<7)
+#define CONFIG_BOOT_MODE_BIT (1<<6)
+#define CONFIG_ADDR_AUTO_INCR_BIT (1<<5)
+#define CONFIG_BUFNO_AUTO_INCR_BIT (1<<4)
+#define CONFIG_PAGE_CNT_MASK 0xF
+#define CONFIG_PAGE_CNT_SHIFT 0
+
+/* NFC_IRQ_STATUS Field */
+#define IDLE_IRQ_BIT (1<<29)
+#define IDLE_EN_BIT (1<<20)
+#define CMD_DONE_CLEAR_BIT (1<<18)
+#define IDLE_CLEAR_BIT (1<<17)
+
+#define NFC_TIMEOUT (HZ)
+
+/* ECC status placed at end of buffers. */
+#define ECC_SRAM_ADDR ((PAGE_2K+256-8) >> 3)
+#define ECC_STATUS_MASK 0x80
+#define ECC_ERR_COUNT 0x3F
+
+struct nfc_config {
+ int hardware_ecc;
+ int width;
+ int flash_bbt;
+ u32 clkrate;
+};
+
+struct fsl_nfc {
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ struct device *dev;
+ void __iomem *regs;
+ wait_queue_head_t irq_waitq;
+ uint column;
+ int spareonly;
+ int page;
+ /* Status and ID are in alternate locations. */
+ int alt_buf;
+#define ALT_BUF_ID 1
+#define ALT_BUF_STAT 2
+ struct clk *clk;
+
+ struct nfc_config *cfg;
+};
+#define mtd_to_nfc(_mtd) container_of(_mtd, struct fsl_nfc, mtd)
+
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+ NAND_BBT_2BIT | NAND_BBT_VERSION,
+ .offs = 11,
+ .len = 4,
+ .veroffs = 15,
+ .maxblocks = 4,
+ .pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+ NAND_BBT_2BIT | NAND_BBT_VERSION,
+ .offs = 11,
+ .len = 4,
+ .veroffs = 15,
+ .maxblocks = 4,
+ .pattern = mirror_pattern,
+};
+
+static struct nand_ecclayout nfc_ecc45 = {
+ .eccbytes = 45,
+ .eccpos = {19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63},
+ .oobfree = {
+ {.offset = 8,
+ .length = 11} }
+};
+
+static u32 nfc_read(struct mtd_info *mtd, uint reg)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+ if (reg == NFC_FLASH_STATUS1 ||
+ reg == NFC_FLASH_STATUS2 ||
+ reg == NFC_IRQ_STATUS)
+ return __raw_readl(nfc->regs + reg);
+ /* Gang read/writes together for most registers. */
+ else
+ return *(u32 *)(nfc->regs + reg);
+}
+
+static void nfc_write(struct mtd_info *mtd, uint reg, u32 val)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+
+ if (reg == NFC_FLASH_STATUS1 ||
+ reg == NFC_FLASH_STATUS2 ||
+ reg == NFC_IRQ_STATUS)
+ __raw_writel(val, nfc->regs + reg);
+ /* Gang read/writes together for most registers. */
+ else
+ *(u32 *)(nfc->regs + reg) = val;
+}
+
+static void nfc_set(struct mtd_info *mtd, uint reg, u32 bits)
+{
+ nfc_write(mtd, reg, nfc_read(mtd, reg) | bits);
+}
+
+static void nfc_clear(struct mtd_info *mtd, uint reg, u32 bits)
+{
+ nfc_write(mtd, reg, nfc_read(mtd, reg) & ~bits);
+}
+
+static void nfc_set_field(struct mtd_info *mtd, u32 reg,
+ u32 mask, u32 shift, u32 val)
+{
+ nfc_write(mtd, reg, (nfc_read(mtd, reg) & (~mask)) | val << shift);
+}
+
+/* Clear flags for upcoming command */
+static void nfc_clear_status(struct mtd_info *mtd)
+{
+ nfc_set(mtd, NFC_IRQ_STATUS, CMD_DONE_CLEAR_BIT);
+ nfc_set(mtd, NFC_IRQ_STATUS, IDLE_CLEAR_BIT);
+}
+
+/* Wait for complete operation */
+static void nfc_done(struct mtd_info *mtd)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+ int rv;
+
+ nfc_set(mtd, NFC_IRQ_STATUS, IDLE_EN_BIT);
+ /* CMD2 is almost non-volatile, START_BIT is not */
+ barrier();
+ nfc_set(mtd, NFC_FLASH_CMD2, START_BIT);
+ barrier();
+
+ if (!(nfc_read(mtd, NFC_IRQ_STATUS) & IDLE_IRQ_BIT)) {
+ rv = wait_event_timeout(nfc->irq_waitq,
+ (nfc_read(mtd, NFC_IRQ_STATUS) & IDLE_IRQ_BIT),
+ NFC_TIMEOUT);
+ if (!rv)
+ dev_warn(nfc->dev, "Timeout while waiting for BUSY.\n");
+ }
+ nfc_clear_status(mtd);
+}
+
+static u8 nfc_get_id(struct mtd_info *mtd, int col)
+{
+ u32 flash_id;
+
+ if (col < 4) {
+ flash_id = nfc_read(mtd, NFC_FLASH_STATUS1);
+ return (flash_id >> (3-col)*8) & 0xff;
+ } else {
+ flash_id = nfc_read(mtd, NFC_FLASH_STATUS2);
+ return flash_id >> 24;
+ }
+}
+
+static u8 nfc_get_status(struct mtd_info *mtd)
+{
+ return nfc_read(mtd, NFC_FLASH_STATUS2) & STATUS_BYTE1_MASK;
+}
+
+/* Single command */
+static void nfc_send_command(struct mtd_info *mtd, u32 cmd_byte1,
+ u32 cmd_code)
+{
+ nfc_clear_status(mtd);
+
+ nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_BYTE1_MASK,
+ CMD_BYTE1_SHIFT, cmd_byte1);
+
+ nfc_clear(mtd, NFC_FLASH_CMD2, BUFNO_MASK);
+
+ nfc_set_field(mtd, NFC_FLASH_CMD2, CMD_CODE_MASK,
+ CMD_CODE_SHIFT, cmd_code);
+}
+
+/* Two commands */
+static void nfc_send_commands(struct mtd_info *mtd, u32 cmd_byte1,
+ u32 cmd_byte2, u32 cmd_code)
+{
+ nfc_send_command(mtd, cmd_byte1, cmd_code);
+
+ nfc_set_field(mtd, NFC_FLASH_CMD1, CMD_BYTE2_MASK,
+ CMD_BYTE2_SHIFT, cmd_byte2);
+}
+
+static irqreturn_t nfc_irq(int irq, void *data)
+{
+ struct mtd_info *mtd = data;
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+
+ nfc_clear(mtd, NFC_IRQ_STATUS, IDLE_EN_BIT);
+ wake_up(&nfc->irq_waitq);
+
+ return IRQ_HANDLED;
+}
+
+static void nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
+{
+ if (column != -1) {
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+ if (nfc->chip.options | NAND_BUSWIDTH_16)
+ column = column/2;
+ nfc_set_field(mtd, NFC_COL_ADDR, COL_ADDR_MASK,
+ COL_ADDR_SHIFT, column);
+ }
+ if (page != -1)
+ nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
+ ROW_ADDR_SHIFT, page);
+}
+
+/* Send command to NAND chip */
+static void nfc_command(struct mtd_info *mtd, unsigned command,
+ int column, int page)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+
+ nfc->column = max(column, 0);
+ nfc->spareonly = 0;
+ nfc->alt_buf = 0;
+
+ switch (command) {
+ case NAND_CMD_PAGEPROG:
+ nfc->page = -1;
+ nfc_send_commands(mtd, NAND_CMD_SEQIN,
+ command, PROGRAM_PAGE_CMD_CODE);
+ nfc_addr_cycle(mtd, column, page);
+ break;
+
+ case NAND_CMD_RESET:
+ nfc_send_command(mtd, command, RESET_CMD_CODE);
+ break;
+ /*
+ * NFC does not support sub-page reads and writes,
+ * so emulate them using full page transfers.
+ */
+ case NAND_CMD_READOOB:
+ nfc->spareonly = 1;
+ case NAND_CMD_SEQIN: /* Pre-read for partial writes. */
+ case NAND_CMD_READ0:
+ column = 0;
+ /* Already read? */
+ if (nfc->page == page)
+ return;
+ nfc->page = page;
+ nfc_send_commands(mtd, NAND_CMD_READ0,
+ NAND_CMD_READSTART, READ_PAGE_CMD_CODE);
+ nfc_addr_cycle(mtd, column, page);
+ break;
+
+ case NAND_CMD_ERASE1:
+ if (nfc->page == page)
+ nfc->page = -1;
+ nfc_send_commands(mtd, command,
+ NAND_CMD_ERASE2, ERASE_CMD_CODE);
+ nfc_addr_cycle(mtd, column, page);
+ break;
+
+ case NAND_CMD_READID:
+ nfc->alt_buf = ALT_BUF_ID;
+ nfc_send_command(mtd, command, READ_ID_CMD_CODE);
+ break;
+
+ case NAND_CMD_STATUS:
+ nfc->alt_buf = ALT_BUF_STAT;
+ nfc_send_command(mtd, command, STATUS_READ_CMD_CODE);
+ break;
+ default:
+ return;
+ }
+
+ nfc_done(mtd);
+}
+
+static void nfc_read_spare(struct mtd_info *mtd, void *buf, int len)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+
+ len = min(mtd->oobsize, (uint)len);
+ if (len > 0)
+ memcpy(buf, nfc->regs + mtd->writesize, len);
+}
+
+/* Read data from NFC buffers */
+static void nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+ uint c = nfc->column;
+ uint l;
+
+ /* Handle main area */
+ if (!nfc->spareonly) {
+
+ l = min((uint)len, mtd->writesize - c);
+ nfc->column += l;
+
+ if (!nfc->alt_buf)
+ memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, l);
+ else
+ if (nfc->alt_buf & ALT_BUF_ID)
+ *buf = nfc_get_id(mtd, c);
+ else
+ *buf = nfc_get_status(mtd);
+ buf += l;
+ len -= l;
+ }
+
+ /* Handle spare area access */
+ if (len) {
+ nfc->column += len;
+ nfc_read_spare(mtd, buf, len);
+ }
+}
+
+/* Write data to NFC buffers */
+static void nfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+ uint c = nfc->column;
+ uint l;
+
+ l = min((uint)len, mtd->writesize + mtd->oobsize - c);
+ nfc->column += l;
+
+ memcpy(nfc->regs + NFC_MAIN_AREA(0) + c, buf, l);
+}
+
+/* Read byte from NFC buffers */
+static u8 nfc_read_byte(struct mtd_info *mtd)
+{
+ u8 tmp;
+ nfc_read_buf(mtd, &tmp, sizeof(tmp));
+ return tmp;
+}
+
+/* Read word from NFC buffers */
+static u16 nfc_read_word(struct mtd_info *mtd)
+{
+ u16 tmp;
+ nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp));
+ return tmp;
+}
+
+/* If not provided, upper layers apply a fixed delay. */
+static int nfc_dev_ready(struct mtd_info *mtd)
+{
+ /* NFC handles R/B internally; always ready. */
+ return 1;
+}
+
+/* Vybrid only. MPC5125 has full RB and four CS. Assume boot loader
+ * has set this register for now.
+ */
+static void
+nfc_select_chip(struct mtd_info *mtd, int chip)
+{
+#ifdef CONFIG_SOC_VF610
+ nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_CHIP_SEL_RB_MASK,
+ ROW_ADDR_CHIP_SEL_RB_SHIFT, 1);
+
+ if (chip == 0)
+ nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_CHIP_SEL_MASK,
+ ROW_ADDR_CHIP_SEL_SHIFT, 1);
+ else if (chip == 1)
+ nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_CHIP_SEL_MASK,
+ ROW_ADDR_CHIP_SEL_SHIFT, 2);
+ else
+ nfc_clear(mtd, NFC_ROW_ADDR, ROW_ADDR_CHIP_SEL_MASK);
+#endif
+}
+
+/* Count the number of 0's in buff upto max_bits */
+static int count_written_bits(uint8_t *buff, int size, int max_bits)
+{
+ int k, written_bits = 0;
+
+ for (k = 0; k < size; k++) {
+ written_bits += hweight8(~buff[k]);
+ if (written_bits > max_bits)
+ break;
+ }
+
+ return written_bits;
+}
+
+static int nfc_correct_data(struct mtd_info *mtd, u_char *dat,
+ u_char *read_ecc, u_char *calc_ecc)
+{
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+ u32 ecc_status;
+ u8 ecc_count;
+ int flip;
+
+ /* Errata: ECC status is stored at NFC_CFG[ECCADD] +4 for
+ little-endian and +7 for big-endian SOC. Access as 32 bits
+ and use low byte.
+ */
+ ecc_status = __raw_readl(nfc->regs + ECC_SRAM_ADDR * 8 + 4);
+ ecc_count = ecc_status & ECC_ERR_COUNT;
+ if (!(ecc_status & ECC_STATUS_MASK))
+ return ecc_count;
+
+ /* If 'ecc_count' zero or less then buffer is all 0xff or erased. */
+ flip = count_written_bits(dat, nfc->chip.ecc.size, ecc_count);
+
+ /* ECC failed. */
+ if (flip > ecc_count && flip > (nfc->chip.ecc.strength / 2))
+ return -1;
+
+ /* Erased page. */
+ memset(dat, 0xff, nfc->chip.ecc.size);
+ return 0;
+}
+
+static int nfc_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+ u_char *ecc_code)
+{
+ return 0;
+}
+
+static void nfc_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+}
+
+#ifdef CONFIG_OF_MTD
+static struct of_device_id nfc_dt_ids[] = {
+ { .compatible = "fsl,vf610-nfc" },
+ { .compatible = "fsl,mpc5125-nfc" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, nfc_dt_ids);
+
+static int __init nfc_probe_dt(struct device *dev, struct nfc_config *cfg)
+{
+ struct device_node *np = dev->of_node;
+ int buswidth;
+ u32 clkrate;
+
+ if (!np)
+ return 1;
+
+ if (of_get_nand_ecc_mode(np) >= NAND_ECC_HW)
+ cfg->hardware_ecc = 1;
+
+ cfg->flash_bbt = of_get_nand_on_flash_bbt(np);
+
+ if (!of_property_read_u32(np, "clock-frequency", &clkrate))
+ cfg->clkrate = clkrate;
+
+ buswidth = of_get_nand_bus_width(np);
+ if (buswidth < 0)
+ return buswidth;
+
+ cfg->width = buswidth;
+
+ return 0;
+}
+#else
+static int __init nfc_probe_dt(struct device *dev, struct nfc_config *cfg)
+{
+ return 0;
+}
+#endif
+
+static int nfc_init_controller(struct mtd_info *mtd, struct nfc_config *cfg, int page_sz)
+{
+ if (cfg->width == 16)
+ nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
+ else
+ nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
+
+ /* Set configuration register. */
+ nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_ADDR_AUTO_INCR_BIT);
+ nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_BUFNO_AUTO_INCR_BIT);
+ nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_BOOT_MODE_BIT);
+ nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_DMA_REQ_BIT);
+ nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_FAST_FLASH_BIT);
+
+ /* PAGE_CNT = 1 */
+ nfc_set_field(mtd, NFC_FLASH_CONFIG, CONFIG_PAGE_CNT_MASK,
+ CONFIG_PAGE_CNT_SHIFT, 1);
+
+ /* Set ECC_STATUS offset */
+ nfc_set_field(mtd, NFC_FLASH_CONFIG,
+ CONFIG_ECC_SRAM_ADDR_MASK,
+ CONFIG_ECC_SRAM_ADDR_SHIFT, ECC_SRAM_ADDR);
+
+ nfc_write(mtd, NFC_SECTOR_SIZE, page_sz);
+
+ if (cfg->hardware_ecc) {
+ /* set ECC mode to 45 bytes OOB with 24 bits correction */
+ nfc_set_field(mtd, NFC_FLASH_CONFIG,
+ CONFIG_ECC_MODE_MASK,
+ CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE);
+
+ /* Enable ECC_STATUS */
+ nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_ECC_SRAM_REQ_BIT);
+ }
+
+ return 0;
+}
+
+static int nfc_probe(struct platform_device *pdev)
+{
+ struct fsl_nfc *nfc;
+ struct resource *res;
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+ struct nfc_config *cfg;
+ int err = 0;
+ int page_sz;
+ int irq;
+
+ nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL);
+ if (!nfc)
+ return -ENOMEM;
+
+ nfc->cfg = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL);
+ if (!nfc->cfg)
+ return -ENOMEM;
+ cfg = nfc->cfg;
+
+ nfc->dev = &pdev->dev;
+ nfc->page = -1;
+ mtd = &nfc->mtd;
+ chip = &nfc->chip;
+
+ mtd->priv = chip;
+ mtd->owner = THIS_MODULE;
+ mtd->dev.parent = nfc->dev;
+ mtd->name = DRV_NAME;
+
+ err = nfc_probe_dt(nfc->dev, cfg);
+ if (err)
+ return -ENODEV;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ nfc->regs = devm_ioremap_resource(nfc->dev, res);
+ if (IS_ERR(nfc->regs))
+ return PTR_ERR(nfc->regs);
+
+ nfc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(nfc->clk))
+ return PTR_ERR(nfc->clk);
+
+ if (cfg->clkrate && clk_set_rate(nfc->clk, cfg->clkrate)) {
+ dev_err(nfc->dev, "Clock rate not set.");
+ return -EINVAL;
+ }
+
+ err = clk_prepare_enable(nfc->clk);
+ if (err) {
+ dev_err(nfc->dev, "Unable to enable clock!\n");
+ return err;
+ }
+
+ if (cfg->width == 16)
+ chip->options |= NAND_BUSWIDTH_16;
+ else
+ chip->options &= ~NAND_BUSWIDTH_16;
+
+ chip->dev_ready = nfc_dev_ready;
+ chip->cmdfunc = nfc_command;
+ chip->read_byte = nfc_read_byte;
+ chip->read_word = nfc_read_word;
+ chip->read_buf = nfc_read_buf;
+ chip->write_buf = nfc_write_buf;
+ chip->select_chip = nfc_select_chip;
+
+ /* Bad block options. */
+ if (cfg->flash_bbt)
+ chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_CREATE;
+
+ chip->bbt_td = &bbt_main_descr;
+ chip->bbt_md = &bbt_mirror_descr;
+
+ init_waitqueue_head(&nfc->irq_waitq);
+
+ err = devm_request_irq(nfc->dev, irq, nfc_irq, 0, DRV_NAME, mtd);
+ if (err) {
+ dev_err(nfc->dev, "Error requesting IRQ!\n");
+ goto error;
+ }
+
+ page_sz = PAGE_2K + OOB_64;
+ page_sz += cfg->width == 16 ? 1 : 0;
+
+ nfc_init_controller(mtd, cfg, page_sz);
+
+ /* Always use software ECC for flash ID. */
+ nfc_set_field(mtd, NFC_FLASH_CONFIG,
+ CONFIG_ECC_MODE_MASK,
+ CONFIG_ECC_MODE_SHIFT, ECC_BYPASS);
+
+ /* first scan to find the device and get the page size */
+ if (nand_scan_ident(mtd, 1, NULL)) {
+ err = -ENXIO;
+ goto error;
+ }
+
+ chip->ecc.mode = NAND_ECC_SOFT; /* default */
+
+ page_sz = mtd->writesize + mtd->oobsize;
+
+ /* Single buffer only, max 256 OOB minus ECC status */
+ if (page_sz > PAGE_2K + 256 - 8) {
+ dev_err(nfc->dev, "Unsupported flash size\n");
+ err = -ENXIO;
+ goto error;
+ }
+ page_sz += cfg->width == 16 ? 1 : 0;
+ nfc_write(mtd, NFC_SECTOR_SIZE, page_sz);
+
+ if (cfg->hardware_ecc) {
+ if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
+ dev_err(nfc->dev, "Unsupported flash with hwecc\n");
+ err = -ENXIO;
+ goto error;
+ }
+
+ chip->ecc.layout = &nfc_ecc45;
+
+ /* propagate ecc.layout to mtd_info */
+ mtd->ecclayout = chip->ecc.layout;
+ chip->ecc.calculate = nfc_calculate_ecc;
+ chip->ecc.hwctl = nfc_enable_hwecc;
+ chip->ecc.correct = nfc_correct_data;
+ chip->ecc.mode = NAND_ECC_HW;
+
+ chip->ecc.bytes = 45;
+ chip->ecc.size = PAGE_2K;
+ chip->ecc.strength = 24;
+
+ /* set ECC mode to 45 bytes OOB with 24 bits correction */
+ nfc_set_field(mtd, NFC_FLASH_CONFIG,
+ CONFIG_ECC_MODE_MASK,
+ CONFIG_ECC_MODE_SHIFT, ECC_45_BYTE);
+ }
+
+ /* second phase scan */
+ if (nand_scan_tail(mtd)) {
+ err = -ENXIO;
+ goto error;
+ }
+
+ /* Register device in MTD */
+ mtd_device_parse_register(mtd, NULL,
+ &(struct mtd_part_parser_data){
+ .of_node = pdev->dev.of_node,
+ },
+ NULL, 0);
+
+ platform_set_drvdata(pdev, mtd);
+
+ return 0;
+
+error:
+ clk_disable_unprepare(nfc->clk);
+ return err;
+}
+
+
+
+static int nfc_remove(struct platform_device *pdev)
+{
+ struct mtd_info *mtd = platform_get_drvdata(pdev);
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+
+ nand_release(mtd);
+ clk_disable_unprepare(nfc->clk);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int nfc_suspend(struct device *dev)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+
+ clk_disable_unprepare(nfc->clk);
+ return 0;
+}
+
+static int nfc_resume(struct device *dev)
+{
+ struct mtd_info *mtd = dev_get_drvdata(dev);
+ struct fsl_nfc *nfc = mtd_to_nfc(mtd);
+ int page_sz;
+
+ pinctrl_pm_select_default_state(dev);
+ if (nfc->cfg->clkrate && clk_set_rate(nfc->clk, nfc->cfg->clkrate)) {
+ dev_err(nfc->dev, "Clock rate not set.");
+ return -EINVAL;
+ }
+
+ clk_prepare_enable(nfc->clk);
+
+ page_sz = mtd->writesize + mtd->oobsize;
+ page_sz += nfc->cfg->width == 16 ? 1 : 0;
+
+ nfc_init_controller(mtd, nfc->cfg, page_sz);
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(nfc_pm_ops, nfc_suspend, nfc_resume);
+
+static struct platform_driver nfc_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = nfc_dt_ids,
+ .pm = &nfc_pm_ops,
+ },
+ .probe = nfc_probe,
+ .remove = nfc_remove,
+};
+
+module_platform_driver(nfc_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("FSL NFC MTD driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 9af296a1ca99..35a8e20d544b 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -416,6 +416,8 @@ struct bufdesc_ex {
* (40ns * 6).
*/
#define FEC_QUIRK_BUG_CAPTURE (1 << 10)
+/* Controller has only one MDIO bus */
+#define FEC_QUIRK_SINGLE_MDIO (1 << 11)
struct fec_enet_priv_tx_q {
int index;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 3dca494797bd..f1bf1788d554 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -91,7 +91,8 @@ static struct platform_device_id fec_devtype[] = {
.driver_data = 0,
}, {
.name = "imx28-fec",
- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
+ .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
+ FEC_QUIRK_SINGLE_MDIO,
}, {
.name = "imx6q-fec",
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
@@ -1961,7 +1962,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
int err = -ENXIO, i;
/*
- * The dual fec interfaces are not equivalent with enet-mac.
+ * The i.MX28 dual fec interfaces are not equal.
* Here are the differences:
*
* - fec0 supports MII & RMII modes while fec1 only supports RMII
@@ -1976,7 +1977,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
* mdio interface in board design, and need to be configured by
* fec0 mii_bus.
*/
- if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) {
+ if ((id_entry->driver_data & FEC_QUIRK_SINGLE_MDIO) && fep->dev_id > 0) {
/* fec1 uses fec0 mii_bus */
if (mii_cnt && fec0_mii_bus) {
fep->mii_bus = fec0_mii_bus;
@@ -2039,7 +2040,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
mii_cnt++;
/* save fec0 mii_bus */
- if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
+ if (id_entry->driver_data & FEC_QUIRK_SINGLE_MDIO)
fec0_mii_bus = fep->mii_bus;
return 0;
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index f2446769247f..52f2b9404fe0 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -294,11 +294,83 @@ static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
return 0;
}
+static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg;
+ struct imx_pin_group *grp;
+ struct imx_pin *imx_pin;
+ unsigned int pin, group;
+ u32 reg;
+
+ /* Currently implementation only for shared mux/conf register */
+ if (!(info->flags & SHARE_MUX_CONF_REG))
+ return -EINVAL;
+
+ pin_reg = &info->pin_regs[offset];
+ if (pin_reg->mux_reg == -1)
+ return -EINVAL;
+
+ /* Find the pinctrl config with GPIO mux mode for the requested pin */
+ for (group = 0; group < info->ngroups; group++) {
+ grp = &info->groups[group];
+ for (pin = 0; pin < grp->npins; pin++) {
+ imx_pin = &grp->pins[pin];
+ if (imx_pin->pin == offset && !imx_pin->mux_mode)
+ goto mux_pin;
+ }
+ }
+
+ return -EINVAL;
+
+mux_pin:
+ reg = readl(ipctl->base + pin_reg->mux_reg);
+ reg &= ~(0x7 << 20);
+ reg |= imx_pin->config;
+ writel(reg, ipctl->base + pin_reg->mux_reg);
+
+ return 0;
+}
+
+static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+ struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct imx_pin_reg *pin_reg;
+ u32 reg;
+
+ /*
+ * Only Vybrid has the input/output buffer enable flags (IBE/OBE)
+ * They are part of the shared mux/conf register.
+ */
+ if (!(info->flags & SHARE_MUX_CONF_REG))
+ return -EINVAL;
+
+ pin_reg = &info->pin_regs[offset];
+ if (pin_reg->mux_reg == -1)
+ return -EINVAL;
+
+ /* IBE always enabled allows us to read the value "on the wire" */
+ reg = readl(ipctl->base + pin_reg->mux_reg);
+ if (input)
+ reg &= ~0x2;
+ else
+ reg |= 0x2;
+ writel(reg, ipctl->base + pin_reg->mux_reg);
+
+ return 0;
+}
+
static const struct pinmux_ops imx_pmx_ops = {
.get_functions_count = imx_pmx_get_funcs_count,
.get_function_name = imx_pmx_get_func_name,
.get_function_groups = imx_pmx_get_groups,
.set_mux = imx_pmx_set,
+ .gpio_request_enable = imx_pmx_gpio_request_enable,
+ .gpio_set_direction = imx_pmx_gpio_set_direction,
};
static int imx_pinconf_get(struct pinctrl_dev *pctldev,
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index f65ff49bb275..028e76504519 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -71,6 +71,15 @@ config POWER_RESET_HISI
help
Reboot support for Hisilicon boards.
+config POWER_RESET_IMX
+ bool "IMX6 power-off driver"
+ depends on POWER_RESET && SOC_IMX6
+ help
+ This driver support power off external PMIC by PMIC_ON_REQ on i.mx6
+ boards.If you want to use other pin to control external power,please
+ say N here or disable in dts to make sure pm_power_off never be
+ overwrote wrongly by this driver.
+
config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
depends on ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 76ce1c59469b..1d4804d6b323 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
+obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
diff --git a/drivers/power/reset/imx-snvs-poweroff.c b/drivers/power/reset/imx-snvs-poweroff.c
new file mode 100644
index 000000000000..ad6ce5020ea7
--- /dev/null
+++ b/drivers/power/reset/imx-snvs-poweroff.c
@@ -0,0 +1,66 @@
+/* Power off driver for i.mx6
+ * Copyright (c) 2014, FREESCALE CORPORATION. All rights reserved.
+ *
+ * based on msm-poweroff.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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 <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+static void __iomem *snvs_base;
+
+static void do_imx_poweroff(void)
+{
+ u32 value = readl(snvs_base);
+
+ /* set TOP and DP_EN bit */
+ writel(value | 0x60, snvs_base);
+}
+
+static int imx_poweroff_probe(struct platform_device *pdev)
+{
+ snvs_base = of_iomap(pdev->dev.of_node, 0);
+ if (!snvs_base) {
+ dev_err(&pdev->dev, "failed to get memory\n");
+ return -ENODEV;
+ }
+
+ pm_power_off = do_imx_poweroff;
+ return 0;
+}
+
+static const struct of_device_id of_imx_poweroff_match[] = {
+ { .compatible = "fsl,sec-v4.0-poweroff", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_imx_poweroff_match);
+
+static struct platform_driver imx_poweroff_driver = {
+ .probe = imx_poweroff_probe,
+ .driver = {
+ .name = "imx-snvs-poweroff",
+ .of_match_table = of_match_ptr(of_imx_poweroff_match),
+ },
+};
+
+static int __init imx_poweroff_init(void)
+{
+ return platform_driver_register(&imx_poweroff_driver);
+}
+device_initcall(imx_poweroff_init);
diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c
index 815b901822cf..c4049f45663f 100644
--- a/drivers/power/reset/syscon-reboot.c
+++ b/drivers/power/reset/syscon-reboot.c
@@ -68,7 +68,7 @@ static int syscon_reboot_probe(struct platform_device *pdev)
return -EINVAL;
ctx->restart_handler.notifier_call = syscon_restart_handle;
- ctx->restart_handler.priority = 128;
+ ctx->restart_handler.priority = 192;
err = register_restart_handler(&ctx->restart_handler);
if (err)
dev_err(dev, "can't register restart notifier (err=%d)\n", err);
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index fa384fe28988..2cd8ffe5c698 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -17,6 +17,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
+#include <linux/clk.h>
/* These register offsets are relative to LP (Low Power) range */
#define SNVS_LPCR 0x04
@@ -39,6 +40,7 @@ struct snvs_rtc_data {
void __iomem *ioaddr;
int irq;
spinlock_t lock;
+ struct clk *clk;
};
static u32 rtc_read_lp_counter(void __iomem *ioaddr)
@@ -260,6 +262,18 @@ static int snvs_rtc_probe(struct platform_device *pdev)
if (data->irq < 0)
return data->irq;
+ data->clk = devm_clk_get(&pdev->dev, "snvs-rtc");
+ if (IS_ERR(data->clk)) {
+ data->clk = NULL;
+ } else {
+ ret = clk_prepare_enable(data->clk);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Could not prepare or enable the snvs clock\n");
+ return ret;
+ }
+ }
+
platform_set_drvdata(pdev, data);
spin_lock_init(&data->lock);
@@ -280,7 +294,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "failed to request irq %d: %d\n",
data->irq, ret);
- return ret;
+ goto error_rtc_device_register;
}
data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
@@ -288,10 +302,16 @@ static int snvs_rtc_probe(struct platform_device *pdev)
if (IS_ERR(data->rtc)) {
ret = PTR_ERR(data->rtc);
dev_err(&pdev->dev, "failed to register rtc: %d\n", ret);
- return ret;
+ goto error_rtc_device_register;
}
return 0;
+
+error_rtc_device_register:
+ if (data->clk)
+ clk_disable_unprepare(data->clk);
+
+ return ret;
}
#ifdef CONFIG_PM_SLEEP
@@ -302,21 +322,34 @@ static int snvs_rtc_suspend(struct device *dev)
if (device_may_wakeup(dev))
enable_irq_wake(data->irq);
+ if (data->clk)
+ clk_disable_unprepare(data->clk);
+
return 0;
}
static int snvs_rtc_resume(struct device *dev)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
+ int ret;
if (device_may_wakeup(dev))
disable_irq_wake(data->irq);
+ if (data->clk) {
+ ret = clk_prepare_enable(data->clk);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
#endif
-static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume);
+static const struct dev_pm_ops snvs_rtc_pm_ops = {
+ .suspend_noirq = snvs_rtc_suspend,
+ .resume_noirq = snvs_rtc_resume,
+};
static const struct of_device_id snvs_dt_ids[] = {
{ .compatible = "fsl,sec-v4.0-mon-rtc-lp", },
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 84e7c9e6ccef..23d97362ac97 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -285,7 +285,6 @@ config SPI_FSL_SPI
config SPI_FSL_DSPI
tristate "Freescale DSPI controller"
- select SPI_BITBANG
select REGMAP_MMIO
depends on SOC_VF610 || COMPILE_TEST
help
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 831ceb4a91f6..440c1646b7e3 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -63,9 +63,11 @@
#define SPI_CTAR0_SLAVE 0x0c
#define SPI_SR 0x2c
+#define SPI_SR_TCFQF 0x80000000
#define SPI_SR_EOQF 0x10000000
#define SPI_RSER 0x30
+#define SPI_RSER_TCFQE 0x80000000
#define SPI_RSER_EOQFE 0x10000000
#define SPI_PUSHR 0x34
@@ -105,8 +107,14 @@ struct chip_data {
u16 void_write_data;
};
+enum dspi_trans_mode {
+ DSPI_EOQ_MODE = 0,
+ DSPI_TCFQ_MODE,
+ DSPI_DMA_MODE, /*TODO*/
+};
+
struct fsl_dspi {
- struct spi_bitbang bitbang;
+ struct spi_master *master;
struct platform_device *pdev;
struct regmap *regmap;
@@ -114,6 +122,7 @@ struct fsl_dspi {
struct clk *clk;
struct spi_transfer *cur_transfer;
+ struct spi_message *cur_msg;
struct chip_data *cur_chip;
size_t len;
void *tx;
@@ -123,6 +132,8 @@ struct fsl_dspi {
char dataflags;
u8 cs;
u16 void_write_data;
+ u32 cs_change;
+ enum dspi_trans_mode trans_mode;
wait_queue_head_t waitq;
u32 waitflags;
@@ -165,12 +176,68 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
*br = ARRAY_SIZE(brs) - 1;
}
-static int dspi_transfer_write(struct fsl_dspi *dspi)
+static u32 dspi_data_to_pushr(struct fsl_dspi *dspi, int tx_word)
+{
+ u16 d16;
+ u8 d8;
+
+ if (tx_word) {
+ if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
+ d16 = *(u16 *)dspi->tx;
+ dspi->tx += 2;
+ } else {
+ d16 = dspi->void_write_data;
+ }
+
+ dspi->len -= 2;
+
+ return SPI_PUSHR_TXDATA(d16) |
+ SPI_PUSHR_PCS(dspi->cs) |
+ SPI_PUSHR_CTAS(dspi->cs) |
+ SPI_PUSHR_CONT;
+ } else {
+ if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
+
+ d8 = *(u8 *)dspi->tx;
+ dspi->tx++;
+ } else {
+ d8 = (u8)dspi->void_write_data;
+ }
+
+ dspi->len--;
+
+ return SPI_PUSHR_TXDATA(d8) |
+ SPI_PUSHR_PCS(dspi->cs) |
+ SPI_PUSHR_CTAS(dspi->cs) |
+ SPI_PUSHR_CONT;
+ }
+}
+
+static void dspi_data_from_popr(struct fsl_dspi *dspi, int rx_word)
+{
+ u16 d;
+ unsigned int val;
+
+ if (rx_word) {
+ regmap_read(dspi->regmap, SPI_POPR, &val);
+ d = SPI_POPR_RXDATA(val);
+
+ if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
+ *(u16 *)dspi->rx = d;
+ dspi->rx += 2;
+ } else {
+ regmap_read(dspi->regmap, SPI_POPR, &val);
+ d = SPI_POPR_RXDATA(val);
+ if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
+ *(u8 *)dspi->rx = d;
+ dspi->rx++;
+ }
+}
+
+static int dspi_eoq_write(struct fsl_dspi *dspi)
{
int tx_count = 0;
int tx_word;
- u16 d16;
- u8 d8;
u32 dspi_pushr = 0;
int first = 1;
@@ -188,43 +255,13 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
}
while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) {
- if (tx_word) {
- if (dspi->len == 1)
- break;
-
- if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
- d16 = *(u16 *)dspi->tx;
- dspi->tx += 2;
- } else {
- d16 = dspi->void_write_data;
- }
-
- dspi_pushr = SPI_PUSHR_TXDATA(d16) |
- SPI_PUSHR_PCS(dspi->cs) |
- SPI_PUSHR_CTAS(dspi->cs) |
- SPI_PUSHR_CONT;
-
- dspi->len -= 2;
- } else {
- if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) {
-
- d8 = *(u8 *)dspi->tx;
- dspi->tx++;
- } else {
- d8 = (u8)dspi->void_write_data;
- }
-
- dspi_pushr = SPI_PUSHR_TXDATA(d8) |
- SPI_PUSHR_PCS(dspi->cs) |
- SPI_PUSHR_CTAS(dspi->cs) |
- SPI_PUSHR_CONT;
-
- dspi->len--;
- }
+ dspi_pushr = dspi_data_to_pushr(dspi, tx_word);
if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) {
/* last transfer in the transfer */
dspi_pushr |= SPI_PUSHR_EOQ;
+ if ((dspi->cs_change) && (!dspi->len))
+ dspi_pushr &= ~SPI_PUSHR_CONT;
} else if (tx_word && (dspi->len == 1))
dspi_pushr |= SPI_PUSHR_EOQ;
@@ -241,99 +278,117 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
return tx_count * (tx_word + 1);
}
-static int dspi_transfer_read(struct fsl_dspi *dspi)
+static int dspi_eoq_read(struct fsl_dspi *dspi)
{
int rx_count = 0;
int rx_word = is_double_byte_mode(dspi);
- u16 d;
+
while ((dspi->rx < dspi->rx_end)
&& (rx_count < DSPI_FIFO_SIZE)) {
- if (rx_word) {
- unsigned int val;
-
- if ((dspi->rx_end - dspi->rx) == 1)
- break;
-
- regmap_read(dspi->regmap, SPI_POPR, &val);
- d = SPI_POPR_RXDATA(val);
-
- if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
- *(u16 *)dspi->rx = d;
- dspi->rx += 2;
-
- } else {
- unsigned int val;
-
- regmap_read(dspi->regmap, SPI_POPR, &val);
- d = SPI_POPR_RXDATA(val);
- if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
- *(u8 *)dspi->rx = d;
- dspi->rx++;
- }
+ dspi_data_from_popr(dspi, rx_word);
rx_count++;
}
return rx_count;
}
-static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t)
+static int dspi_tcfq_write(struct fsl_dspi *dspi)
{
- struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
- dspi->cur_transfer = t;
- dspi->cur_chip = spi_get_ctldata(spi);
- dspi->cs = spi->chip_select;
- dspi->void_write_data = dspi->cur_chip->void_write_data;
+ int tx_word;
+ u32 dspi_pushr = 0;
- dspi->dataflags = 0;
- dspi->tx = (void *)t->tx_buf;
- dspi->tx_end = dspi->tx + t->len;
- dspi->rx = t->rx_buf;
- dspi->rx_end = dspi->rx + t->len;
- dspi->len = t->len;
+ tx_word = is_double_byte_mode(dspi);
- if (!dspi->rx)
- dspi->dataflags |= TRAN_STATE_RX_VOID;
+ if (tx_word && (dspi->len == 1)) {
+ dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
+ regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
+ SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
+ tx_word = 0;
+ }
- if (!dspi->tx)
- dspi->dataflags |= TRAN_STATE_TX_VOID;
+ dspi_pushr = dspi_data_to_pushr(dspi, tx_word);
- regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val);
- regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val);
- regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
+ if ((dspi->cs_change) && (!dspi->len))
+ dspi_pushr &= ~SPI_PUSHR_CONT;
- if (t->speed_hz)
- regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
- dspi->cur_chip->ctar_val);
+ regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
- dspi_transfer_write(dspi);
+ return tx_word + 1;
+}
- if (wait_event_interruptible(dspi->waitq, dspi->waitflags))
- dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n");
- dspi->waitflags = 0;
+static void dspi_tcfq_read(struct fsl_dspi *dspi)
+{
+ int rx_word = is_double_byte_mode(dspi);
- return t->len - dspi->len;
+ dspi_data_from_popr(dspi, rx_word);
}
-static void dspi_chipselect(struct spi_device *spi, int value)
+static int dspi_transfer_one_message(struct spi_master *master,
+ struct spi_message *message)
{
- struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
- unsigned int pushr;
+ struct fsl_dspi *dspi = spi_master_get_devdata(master);
+ struct spi_device *spi = message->spi;
+ struct spi_transfer *transfer;
+ int status = 0;
+ message->actual_length = 0;
+
+ list_for_each_entry(transfer, &message->transfers, transfer_list) {
+ dspi->cur_transfer = transfer;
+ dspi->cur_msg = message;
+ dspi->cur_chip = spi_get_ctldata(spi);
+ dspi->cs = spi->chip_select;
+ if (dspi->cur_transfer->transfer_list.next
+ == &dspi->cur_msg->transfers)
+ transfer->cs_change = 1;
+ dspi->cs_change = transfer->cs_change;
+ dspi->void_write_data = dspi->cur_chip->void_write_data;
+
+ dspi->dataflags = 0;
+ dspi->tx = (void *)transfer->tx_buf;
+ dspi->tx_end = dspi->tx + transfer->len;
+ dspi->rx = transfer->rx_buf;
+ dspi->rx_end = dspi->rx + transfer->len;
+ dspi->len = transfer->len;
+
+ if (!dspi->rx)
+ dspi->dataflags |= TRAN_STATE_RX_VOID;
+
+ if (!dspi->tx)
+ dspi->dataflags |= TRAN_STATE_TX_VOID;
+
+ regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val);
+ regmap_update_bits(dspi->regmap, SPI_MCR,
+ SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF,
+ SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
+ regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
+ dspi->cur_chip->ctar_val);
+ if (transfer->speed_hz)
+ regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
+ dspi->cur_chip->ctar_val);
+
+ if (dspi->trans_mode == DSPI_EOQ_MODE) {
+ regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
+ message->actual_length += dspi_eoq_write(dspi);
+ } else if (dspi->trans_mode == DSPI_TCFQ_MODE) {
+ regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE);
+ message->actual_length += dspi_tcfq_write(dspi);
+ }
- regmap_read(dspi->regmap, SPI_PUSHR, &pushr);
+ if (wait_event_interruptible(dspi->waitq, dspi->waitflags))
+ dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n");
+ dspi->waitflags = 0;
- switch (value) {
- case BITBANG_CS_ACTIVE:
- pushr |= SPI_PUSHR_CONT;
- break;
- case BITBANG_CS_INACTIVE:
- pushr &= ~SPI_PUSHR_CONT;
- break;
+ if (transfer->delay_usecs)
+ udelay(transfer->delay_usecs);
}
- regmap_write(dspi->regmap, SPI_PUSHR, pushr);
+ message->status = status;
+ spi_finalize_current_message(master);
+
+ return status;
}
-static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+static int dspi_setup(struct spi_device *spi)
{
struct chip_data *chip;
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
@@ -342,8 +397,7 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
if (chip == NULL) {
- chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data),
- GFP_KERNEL);
+ chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
if (!chip)
return -ENOMEM;
}
@@ -374,33 +428,42 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
return 0;
}
-static int dspi_setup(struct spi_device *spi)
+static void dspi_cleanup(struct spi_device *spi)
{
- if (!spi->max_speed_hz)
- return -EINVAL;
+ struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+
+ dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n",
+ spi->master->bus_num, spi->chip_select);
- return dspi_setup_transfer(spi, NULL);
+ kfree(chip);
}
static irqreturn_t dspi_interrupt(int irq, void *dev_id)
{
struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
- regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);
+ struct spi_message *msg = dspi->cur_msg;
- dspi_transfer_read(dspi);
+ if (dspi->trans_mode == DSPI_EOQ_MODE) {
+ regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);
+ dspi_eoq_read(dspi);
+ } else if (dspi->trans_mode == DSPI_TCFQ_MODE) {
+ regmap_write(dspi->regmap, SPI_SR, SPI_SR_TCFQF);
+ dspi_tcfq_read(dspi);
+ }
if (!dspi->len) {
if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
- SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16));
+ SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16));
dspi->waitflags = 1;
wake_up_interruptible(&dspi->waitq);
} else {
- dspi_transfer_write(dspi);
-
- return IRQ_HANDLED;
+ if (dspi->trans_mode == DSPI_EOQ_MODE)
+ msg->actual_length += dspi_eoq_write(dspi);
+ else if (dspi->trans_mode == DSPI_TCFQ_MODE)
+ msg->actual_length += dspi_tcfq_write(dspi);
}
return IRQ_HANDLED;
@@ -460,17 +523,22 @@ static int dspi_probe(struct platform_device *pdev)
dspi = spi_master_get_devdata(master);
dspi->pdev = pdev;
- dspi->bitbang.master = master;
- dspi->bitbang.chipselect = dspi_chipselect;
- dspi->bitbang.setup_transfer = dspi_setup_transfer;
- dspi->bitbang.txrx_bufs = dspi_txrx_transfer;
- dspi->bitbang.master->setup = dspi_setup;
- dspi->bitbang.master->dev.of_node = pdev->dev.of_node;
+ dspi->master = master;
+ dspi->trans_mode = DSPI_EOQ_MODE;
+ master->transfer = NULL;
+ master->setup = dspi_setup;
+ master->transfer_one_message = dspi_transfer_one_message;
+ master->dev.of_node = pdev->dev.of_node;
+
+ master->cleanup = dspi_cleanup;
master->mode_bits = SPI_CPOL | SPI_CPHA;
master->bits_per_word_mask = SPI_BPW_MASK(4) | SPI_BPW_MASK(8) |
SPI_BPW_MASK(16);
+ if (of_property_read_bool(np, "tcfq-mode"))
+ dspi->trans_mode = DSPI_TCFQ_MODE;
+
ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num);
if (ret < 0) {
dev_err(&pdev->dev, "can't get spi-num-chipselects\n");
@@ -493,7 +561,7 @@ static int dspi_probe(struct platform_device *pdev)
}
dspi_regmap_config.lock_arg = dspi;
- dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base,
+ dspi->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&dspi_regmap_config);
if (IS_ERR(dspi->regmap)) {
dev_err(&pdev->dev, "failed to init regmap: %ld\n",
@@ -526,7 +594,7 @@ static int dspi_probe(struct platform_device *pdev)
init_waitqueue_head(&dspi->waitq);
platform_set_drvdata(pdev, master);
- ret = spi_bitbang_start(&dspi->bitbang);
+ ret = spi_register_master(master);
if (ret != 0) {
dev_err(&pdev->dev, "Problem registering DSPI master\n");
goto out_clk_put;
@@ -548,9 +616,9 @@ static int dspi_remove(struct platform_device *pdev)
struct fsl_dspi *dspi = spi_master_get_devdata(master);
/* Disconnect from the SPI framework */
- spi_bitbang_stop(&dspi->bitbang);
clk_disable_unprepare(dspi->clk);
- spi_master_put(dspi->bitbang.master);
+ spi_unregister_master(dspi->master);
+ spi_master_put(dspi->master);
return 0;
}
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 6dd53af546a3..ef69452c1fbc 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -237,7 +237,8 @@ struct lpuart_port {
unsigned int rxfifo_size;
bool lpuart32;
- bool lpuart_dma_use;
+ bool lpuart_dma_tx_use;
+ bool lpuart_dma_rx_use;
struct dma_chan *dma_tx_chan;
struct dma_chan *dma_rx_chan;
struct dma_async_tx_descriptor *dma_tx_desc;
@@ -454,6 +455,15 @@ static int lpuart_dma_rx(struct lpuart_port *sport)
return 0;
}
+static void lpuart_flush_buffer(struct uart_port *port)
+{
+ struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
+ if (sport->lpuart_dma_tx_use) {
+ dmaengine_terminate_all(sport->dma_tx_chan);
+ sport->dma_tx_in_progress = 0;
+ }
+}
+
static void lpuart_dma_rx_complete(void *arg)
{
struct lpuart_port *sport = arg;
@@ -461,6 +471,7 @@ static void lpuart_dma_rx_complete(void *arg)
unsigned long flags;
async_tx_ack(sport->dma_rx_desc);
+ mod_timer(&sport->lpuart_timer, jiffies + sport->dma_rx_timeout);
spin_lock_irqsave(&sport->port.lock, flags);
@@ -506,9 +517,6 @@ static inline void lpuart_prepare_rx(struct lpuart_port *sport)
spin_lock_irqsave(&sport->port.lock, flags);
- init_timer(&sport->lpuart_timer);
- sport->lpuart_timer.function = lpuart_timer_func;
- sport->lpuart_timer.data = (unsigned long)sport;
sport->lpuart_timer.expires = jiffies + sport->dma_rx_timeout;
add_timer(&sport->lpuart_timer);
@@ -571,7 +579,7 @@ static void lpuart_start_tx(struct uart_port *port)
temp = readb(port->membase + UARTCR2);
writeb(temp | UARTCR2_TIE, port->membase + UARTCR2);
- if (sport->lpuart_dma_use) {
+ if (sport->lpuart_dma_tx_use) {
if (!uart_circ_empty(xmit) && !sport->dma_tx_in_progress)
lpuart_prepare_tx(sport);
} else {
@@ -758,19 +766,19 @@ out:
static irqreturn_t lpuart_int(int irq, void *dev_id)
{
struct lpuart_port *sport = dev_id;
- unsigned char sts;
+ unsigned char sts, crdma;
sts = readb(sport->port.membase + UARTSR1);
+ crdma = readb(sport->port.membase + UARTCR5);
- if (sts & UARTSR1_RDRF) {
- if (sport->lpuart_dma_use)
+ if (sts & UARTSR1_RDRF && !(crdma & UARTCR5_RDMAS)) {
+ if (sport->lpuart_dma_rx_use)
lpuart_prepare_rx(sport);
else
lpuart_rxint(irq, dev_id);
}
- if (sts & UARTSR1_TDRE &&
- !(readb(sport->port.membase + UARTCR5) & UARTCR5_TDMAS)) {
- if (sport->lpuart_dma_use)
+ if (sts & UARTSR1_TDRE && !(crdma & UARTCR5_TDMAS)) {
+ if (sport->lpuart_dma_tx_use)
lpuart_pio_tx(sport);
else
lpuart_txint(irq, dev_id);
@@ -913,6 +921,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
sport->port.membase + UARTPFIFO);
+ /* explicitly clear RDRF */
+ readb(sport->port.membase + UARTSR1);
+
/* flush Tx and Rx FIFO */
writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
sport->port.membase + UARTCFIFO);
@@ -953,26 +964,17 @@ static int lpuart_dma_tx_request(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
- struct dma_chan *tx_chan;
struct dma_slave_config dma_tx_sconfig;
dma_addr_t dma_bus;
unsigned char *dma_buf;
int ret;
- tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
-
- if (!tx_chan) {
- dev_err(sport->port.dev, "Dma tx channel request failed!\n");
- return -ENODEV;
- }
-
- dma_bus = dma_map_single(tx_chan->device->dev,
+ dma_bus = dma_map_single(sport->dma_tx_chan->device->dev,
sport->port.state->xmit.buf,
UART_XMIT_SIZE, DMA_TO_DEVICE);
- if (dma_mapping_error(tx_chan->device->dev, dma_bus)) {
+ if (dma_mapping_error(sport->dma_tx_chan->device->dev, dma_bus)) {
dev_err(sport->port.dev, "dma_map_single tx failed\n");
- dma_release_channel(tx_chan);
return -ENOMEM;
}
@@ -981,16 +983,14 @@ static int lpuart_dma_tx_request(struct uart_port *port)
dma_tx_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_tx_sconfig.dst_maxburst = sport->txfifo_size;
dma_tx_sconfig.direction = DMA_MEM_TO_DEV;
- ret = dmaengine_slave_config(tx_chan, &dma_tx_sconfig);
+ ret = dmaengine_slave_config(sport->dma_tx_chan, &dma_tx_sconfig);
if (ret < 0) {
dev_err(sport->port.dev,
"Dma slave config failed, err = %d\n", ret);
- dma_release_channel(tx_chan);
return ret;
}
- sport->dma_tx_chan = tx_chan;
sport->dma_tx_buf_virt = dma_buf;
sport->dma_tx_buf_bus = dma_bus;
sport->dma_tx_in_progress = 0;
@@ -1002,34 +1002,24 @@ static int lpuart_dma_rx_request(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
- struct dma_chan *rx_chan;
struct dma_slave_config dma_rx_sconfig;
dma_addr_t dma_bus;
unsigned char *dma_buf;
int ret;
- rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
-
- if (!rx_chan) {
- dev_err(sport->port.dev, "Dma rx channel request failed!\n");
- return -ENODEV;
- }
-
dma_buf = devm_kzalloc(sport->port.dev,
FSL_UART_RX_DMA_BUFFER_SIZE, GFP_KERNEL);
if (!dma_buf) {
dev_err(sport->port.dev, "Dma rx alloc failed\n");
- dma_release_channel(rx_chan);
return -ENOMEM;
}
- dma_bus = dma_map_single(rx_chan->device->dev, dma_buf,
+ dma_bus = dma_map_single(sport->dma_rx_chan->device->dev, dma_buf,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(rx_chan->device->dev, dma_bus)) {
+ if (dma_mapping_error(sport->dma_rx_chan->device->dev, dma_bus)) {
dev_err(sport->port.dev, "dma_map_single rx failed\n");
- dma_release_channel(rx_chan);
return -ENOMEM;
}
@@ -1037,16 +1027,14 @@ static int lpuart_dma_rx_request(struct uart_port *port)
dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma_rx_sconfig.src_maxburst = 1;
dma_rx_sconfig.direction = DMA_DEV_TO_MEM;
- ret = dmaengine_slave_config(rx_chan, &dma_rx_sconfig);
+ ret = dmaengine_slave_config(sport->dma_rx_chan, &dma_rx_sconfig);
if (ret < 0) {
dev_err(sport->port.dev,
"Dma slave config failed, err = %d\n", ret);
- dma_release_channel(rx_chan);
return ret;
}
- sport->dma_rx_chan = rx_chan;
sport->dma_rx_buf_virt = dma_buf;
sport->dma_rx_buf_bus = dma_bus;
sport->dma_rx_in_progress = 0;
@@ -1058,31 +1046,24 @@ static void lpuart_dma_tx_free(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
- struct dma_chan *dma_chan;
dma_unmap_single(sport->port.dev, sport->dma_tx_buf_bus,
UART_XMIT_SIZE, DMA_TO_DEVICE);
- dma_chan = sport->dma_tx_chan;
- sport->dma_tx_chan = NULL;
+
sport->dma_tx_buf_bus = 0;
sport->dma_tx_buf_virt = NULL;
- dma_release_channel(dma_chan);
}
static void lpuart_dma_rx_free(struct uart_port *port)
{
struct lpuart_port *sport = container_of(port,
struct lpuart_port, port);
- struct dma_chan *dma_chan;
dma_unmap_single(sport->port.dev, sport->dma_rx_buf_bus,
FSL_UART_RX_DMA_BUFFER_SIZE, DMA_FROM_DEVICE);
- dma_chan = sport->dma_rx_chan;
- sport->dma_rx_chan = NULL;
sport->dma_rx_buf_bus = 0;
sport->dma_rx_buf_virt = NULL;
- dma_release_channel(dma_chan);
}
static int lpuart_startup(struct uart_port *port)
@@ -1098,17 +1079,25 @@ static int lpuart_startup(struct uart_port *port)
sport->txfifo_size = 0x1 << (((temp >> UARTPFIFO_TXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK) + 1);
+ sport->port.fifosize = sport->txfifo_size;
+
sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) &
UARTPFIFO_FIFOSIZE_MASK) + 1);
- /* Whether use dma support by dma request results */
- if (lpuart_dma_tx_request(port) || lpuart_dma_rx_request(port)) {
- sport->lpuart_dma_use = false;
- } else {
- sport->lpuart_dma_use = true;
+ if (sport->dma_rx_chan && !lpuart_dma_rx_request(port)) {
+ sport->lpuart_dma_rx_use = true;
+ setup_timer(&sport->lpuart_timer, lpuart_timer_func,
+ (unsigned long)sport);
+ } else
+ sport->lpuart_dma_rx_use = false;
+
+
+ if (sport->dma_tx_chan && !lpuart_dma_tx_request(port)) {
+ sport->lpuart_dma_tx_use = true;
temp = readb(port->membase + UARTCR5);
writeb(temp | UARTCR5_TDMAS, port->membase + UARTCR5);
- }
+ } else
+ sport->lpuart_dma_tx_use = false;
ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
DRIVER_NAME, sport);
@@ -1179,10 +1168,13 @@ static void lpuart_shutdown(struct uart_port *port)
devm_free_irq(port->dev, port->irq, sport);
- if (sport->lpuart_dma_use) {
- lpuart_dma_tx_free(port);
- lpuart_dma_rx_free(port);
+ if (sport->lpuart_dma_rx_use) {
+ lpuart_dma_rx_free(&sport->port);
+ del_timer_sync(&sport->lpuart_timer);
}
+
+ if (sport->lpuart_dma_tx_use)
+ lpuart_dma_tx_free(&sport->port);
}
static void lpuart32_shutdown(struct uart_port *port)
@@ -1304,7 +1296,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
/* update the per-port timeout */
uart_update_timeout(port, termios->c_cflag, baud);
- if (sport->lpuart_dma_use) {
+ if (sport->lpuart_dma_rx_use) {
/* Calculate delay for 1.5 DMA buffers */
sport->dma_rx_timeout = (sport->port.timeout - HZ / 50) *
FSL_UART_RX_DMA_BUFFER_SIZE * 3 /
@@ -1517,6 +1509,7 @@ static struct uart_ops lpuart_pops = {
.release_port = lpuart_release_port,
.config_port = lpuart_config_port,
.verify_port = lpuart_verify_port,
+ .flush_buffer = lpuart_flush_buffer,
};
static struct uart_ops lpuart32_pops = {
@@ -1535,6 +1528,7 @@ static struct uart_ops lpuart32_pops = {
.release_port = lpuart_release_port,
.config_port = lpuart_config_port,
.verify_port = lpuart_verify_port,
+ .flush_buffer = lpuart_flush_buffer,
};
static struct lpuart_port *lpuart_ports[UART_NR];
@@ -1835,6 +1829,16 @@ static int lpuart_probe(struct platform_device *pdev)
return ret;
}
+ sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
+ if (!sport->dma_tx_chan)
+ dev_info(sport->port.dev, "DMA tx channel request failed, "
+ "operating without tx DMA\n");
+
+ sport->dma_rx_chan = dma_request_slave_channel(sport->port.dev, "rx");
+ if (!sport->dma_rx_chan)
+ dev_info(sport->port.dev, "DMA rx channel request failed, "
+ "operating without rx DMA\n");
+
return 0;
}
@@ -1846,6 +1850,12 @@ static int lpuart_remove(struct platform_device *pdev)
clk_disable_unprepare(sport->clk);
+ if (sport->dma_tx_chan)
+ dma_release_channel(sport->dma_tx_chan);
+
+ if (sport->dma_rx_chan)
+ dma_release_channel(sport->dma_rx_chan);
+
return 0;
}
@@ -1855,6 +1865,8 @@ static int lpuart_suspend(struct device *dev)
struct lpuart_port *sport = dev_get_drvdata(dev);
uart_suspend_port(&lpuart_reg, &sport->port);
+ if (sport->port.suspended && !sport->port.irq_wake)
+ clk_disable_unprepare(sport->clk);
return 0;
}
@@ -1863,6 +1875,11 @@ static int lpuart_resume(struct device *dev)
{
struct lpuart_port *sport = dev_get_drvdata(dev);
+ if (sport->port.suspended && !sport->port.irq_wake)
+ clk_prepare_enable(sport->clk);
+
+ /* Reinitialize FIFO's to flush characters parsed at wrong baud rate */
+ lpuart_setup_watermark(sport);
uart_resume_port(&lpuart_reg, &sport->port);
return 0;
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index ca57e3dcd3d5..e935ccce7c78 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -15,6 +15,16 @@
#include <linux/usb/ehci_def.h>
+/*
+ * ID
+ * For 1.x revision, bit24 - bit31 are reserved
+ * For 2.x revision, bit25 - bit28 are 0x2
+ */
+#define TAG (0x1F << 16)
+#define REVISION (0xF << 21)
+#define VERSION (0xF << 25)
+#define CIVERSION (0x7 << 29)
+
/* HCCPARAMS */
#define HCCPARAMS_LEN BIT(17)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index ea40626e0246..94db6365e647 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -29,6 +29,15 @@
/******************************************************************************
* REGISTERS
*****************************************************************************/
+/* Identification Registers */
+#define ID_ID 0x0
+#define ID_HWGENERAL 0x4
+#define ID_HWHOST 0x8
+#define ID_HWDEVICE 0xc
+#define ID_HWTXBUF 0x10
+#define ID_HWRXBUF 0x14
+#define ID_SBUSCFG 0x90
+
/* register indices */
enum ci_hw_regs {
CAP_CAPLENGTH,
@@ -97,6 +106,18 @@ enum ci_role {
CI_ROLE_END,
};
+enum CI_REVISION {
+ CI_REVISION_1X = 10, /* Revision 1.x */
+ CI_REVISION_20 = 20, /* Revision 2.0 */
+ CI_REVISION_21, /* Revision 2.1 */
+ CI_REVISION_22, /* Revision 2.2 */
+ CI_REVISION_23, /* Revision 2.3 */
+ CI_REVISION_24, /* Revision 2.4 */
+ CI_REVISION_25, /* Revision 2.5 */
+ CI_REVISION_25_PLUS, /* Revision above than 2.5 */
+ CI_REVISION_UNKNOWN = 99, /* Unknown Revision */
+};
+
/**
* struct ci_role_driver - host/gadget role driver
* @start: start this role
@@ -168,6 +189,7 @@ struct hw_bank {
* @b_sess_valid_event: indicates there is a vbus event, and handled
* at ci_otg_work
* @imx28_write_fix: Freescale imx28 needs swp instruction for writing
+ * @rev: The revision number for controller
*/
struct ci_hdrc {
struct device *dev;
@@ -207,6 +229,7 @@ struct ci_hdrc {
bool id_event;
bool b_sess_valid_event;
bool imx28_write_fix;
+ enum CI_REVISION rev;
};
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
@@ -244,6 +267,36 @@ static inline void ci_role_stop(struct ci_hdrc *ci)
}
/**
+ * hw_read_id_reg: reads from a identification register
+ * @ci: the controller
+ * @offset: offset from the beginning of identification registers region
+ * @mask: bitfield mask
+ *
+ * This function returns register contents
+ */
+static inline u32 hw_read_id_reg(struct ci_hdrc *ci, u32 offset, u32 mask)
+{
+ return ioread32(ci->hw_bank.abs + offset) & mask;
+}
+
+/**
+ * hw_write_id_reg: writes to a identification register
+ * @ci: the controller
+ * @offset: offset from the beginning of identification registers region
+ * @mask: bitfield mask
+ * @data: new value
+ */
+static inline void hw_write_id_reg(struct ci_hdrc *ci, u32 offset,
+ u32 mask, u32 data)
+{
+ if (~mask)
+ data = (ioread32(ci->hw_bank.abs + offset) & ~mask)
+ | (data & mask);
+
+ iowrite32(data, ci->hw_bank.abs + offset);
+}
+
+/**
* hw_read: reads from a hw register
* @ci: the controller
* @reg: register index
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 9bdc6bd73432..33a8c4a82494 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -136,6 +136,22 @@ static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
return 0;
}
+static enum CI_REVISION ci_get_revision(struct ci_hdrc *ci)
+{
+ int ver = hw_read_id_reg(ci, ID_ID, VERSION) >> __ffs(VERSION);
+ enum CI_REVISION rev = CI_REVISION_UNKNOWN;
+
+ if (ver == 0x2) {
+ int rev_reg = hw_read_id_reg
+ (ci, ID_ID, REVISION) >> __ffs(REVISION);
+ rev = rev_reg + CI_REVISION_20;
+ } else if (ver == 0x0) {
+ rev = CI_REVISION_1X;
+ }
+
+ return rev;
+}
+
/**
* hw_read_intr_enable: returns interrupt enable register
*
@@ -245,8 +261,11 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
/* Clear all interrupts status bits*/
hw_write(ci, OP_USBSTS, 0xffffffff, 0xffffffff);
- dev_dbg(ci->dev, "ChipIdea HDRC found, lpm: %d; cap: %p op: %p\n",
- ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op);
+ ci->rev = ci_get_revision(ci);
+
+ dev_dbg(ci->dev,
+ "ChipIdea HDRC found, revision: %d, lpm: %d; cap: %p op: %p\n",
+ ci->rev, ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op);
/* setup lock mode ? */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 0444d3f8971a..551ab37a949b 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -522,6 +522,20 @@ static void free_pending_td(struct ci_hw_ep *hwep)
kfree(pending);
}
+static int reprime_dtd(struct ci_hdrc *ci, struct ci_hw_ep *hwep,
+ struct td_node *node)
+{
+ hwep->qh.ptr->td.next = node->dma;
+ hwep->qh.ptr->td.token &=
+ cpu_to_le32(~(TD_STATUS_HALTED | TD_STATUS_ACTIVE));
+
+ /* Synchronize before ep prime */
+ wmb();
+
+ return hw_ep_prime(ci, hwep->num, hwep->dir,
+ hwep->type == USB_ENDPOINT_XFER_CONTROL);
+}
+
/**
* _hardware_dequeue: handles a request at hardware level
* @gadget: gadget
@@ -535,6 +549,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
struct td_node *node, *tmpnode;
unsigned remaining_length;
unsigned actual = hwreq->req.length;
+ struct ci_hdrc *ci = hwep->ci;
if (hwreq->req.status != -EALREADY)
return -EINVAL;
@@ -544,6 +559,11 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) {
tmptoken = le32_to_cpu(node->ptr->token);
if ((TD_STATUS_ACTIVE & tmptoken) != 0) {
+ int n = hw_ep_bit(hwep->num, hwep->dir);
+
+ if (ci->rev == CI_REVISION_24)
+ if (!hw_read(ci, OP_ENDPTSTAT, BIT(n)))
+ reprime_dtd(ci, hwep, node);
hwreq->req.status = -EALREADY;
return -EBUSY;
}
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index c7bf606a8706..2458cb1a9bb2 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1976,6 +1976,17 @@ config FB_FSL_DIU
---help---
Framebuffer driver for the Freescale SoC DIU
+config FB_FSL_DCU
+ tristate "Freescale DCU framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+ ---help---
+ Framebuffer driver for the Freescale SoC DCU
+
config FB_W100
tristate "W100 frame buffer support"
depends on FB && ARCH_PXA
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 1979afffccfe..471695d7b051 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_FB_IMX) += imxfb.o
obj-$(CONFIG_FB_S3C) += s3c-fb.o
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
+obj-$(CONFIG_FB_FSL_DCU) += fsl-dcu-fb.o
obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
obj-$(CONFIG_FB_PS3) += ps3fb.o
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 0705d8883ede..75aa2f30f6c9 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1681,6 +1681,10 @@ static int do_register_framebuffer(struct fb_info *fb_info)
return -ENODEV;
}
+ /* FIXME: unlock registration mutex before registration
+ * notification is sent, in order to avoid deadlock.
+ */
+ mutex_unlock(&registration_lock);
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
unlock_fb_info(fb_info);
console_unlock();
@@ -1775,7 +1779,13 @@ register_framebuffer(struct fb_info *fb_info)
mutex_lock(&registration_lock);
ret = do_register_framebuffer(fb_info);
- mutex_unlock(&registration_lock);
+ if (ret != 0)
+ /*
+ * FIXME: mutex is unlocked only if ret == 0.
+ * This is the second part of the workaround
+ * that prevents deadlocking.
+ */
+ mutex_unlock(&registration_lock);
return ret;
}
diff --git a/drivers/video/fbdev/fsl-dcu-fb.c b/drivers/video/fbdev/fsl-dcu-fb.c
new file mode 100644
index 000000000000..4bcab0f136a2
--- /dev/null
+++ b/drivers/video/fbdev/fsl-dcu-fb.c
@@ -0,0 +1,1223 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU framebuffer device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+#include <linux/pm_runtime.h>
+#include <linux/console.h>
+
+#define DRIVER_NAME "fsl-dcu-fb"
+
+#define DCU_DCU_MODE 0x0010
+#define DCU_MODE_BLEND_ITER(x) ((x) << 20)
+#define DCU_MODE_RASTER_EN (1 << 14)
+#define DCU_MODE_DCU_MODE(x) (x)
+#define DCU_MODE_DCU_MODE_MASK 0x03
+#define DCU_MODE_OFF 0
+#define DCU_MODE_NORMAL 1
+#define DCU_MODE_TEST 2
+#define DCU_MODE_COLORBAR 3
+
+#define DCU_BGND 0x0014
+#define DCU_BGND_R(x) ((x) << 16)
+#define DCU_BGND_G(x) ((x) << 8)
+#define DCU_BGND_B(x) (x)
+
+#define DCU_DISP_SIZE 0x0018
+#define DCU_DISP_SIZE_DELTA_Y(x) ((x) << 16)
+#define DCU_DISP_SIZE_DELTA_X(x) (x)
+
+#define DCU_HSYN_PARA 0x001c
+#define DCU_HSYN_PARA_BP(x) ((x) << 22)
+#define DCU_HSYN_PARA_PW(x) ((x) << 11)
+#define DCU_HSYN_PARA_FP(x) (x)
+
+#define DCU_VSYN_PARA 0x0020
+#define DCU_VSYN_PARA_BP(x) ((x) << 22)
+#define DCU_VSYN_PARA_PW(x) ((x) << 11)
+#define DCU_VSYN_PARA_FP(x) (x)
+
+#define DCU_SYN_POL 0x0024
+#define DCU_SYN_POL_INV_PXCK_FALL (1 << 6)
+#define DCU_SYN_POL_NEG_REMAIN (1 << 5)
+#define DCU_SYN_POL_INV_VS_LOW (1 << 1)
+#define DCU_SYN_POL_INV_HS_LOW (1)
+
+#define DCU_THRESHOLD 0x0028
+#define DCU_THRESHOLD_LS_BF_VS(x) ((x) << 16)
+#define DCU_THRESHOLD_OUT_BUF_HIGH(x) ((x) << 8)
+#define DCU_THRESHOLD_OUT_BUF_LOW(x) (x)
+
+#define DCU_INT_STATUS 0x002C
+#define DCU_INT_STATUS_UNDRUN (1 << 1)
+
+#define DCU_INT_MASK 0x0030
+#define DCU_INT_MASK_UNDRUN (1 << 1)
+
+#define DCU_DIV_RATIO 0x0054
+
+#define DCU_UPDATE_MODE 0x00cc
+#define DCU_UPDATE_MODE_MODE (1 << 31)
+#define DCU_UPDATE_MODE_READREG (1 << 30)
+
+#define DCU_CTRLDESCLN_1(x) (0x200 + (x) * 0x40)
+#define DCU_CTRLDESCLN_1_HEIGHT(x) ((x) << 16)
+#define DCU_CTRLDESCLN_1_WIDTH(x) (x)
+
+#define DCU_CTRLDESCLN_2(x) (0x204 + (x) * 0x40)
+#define DCU_CTRLDESCLN_2_POSY(x) ((x) << 16)
+#define DCU_CTRLDESCLN_2_POSX(x) (x)
+
+#define DCU_CTRLDESCLN_3(x) (0x208 + (x) * 0x40)
+
+#define DCU_CTRLDESCLN_4(x) (0x20c + (x) * 0x40)
+#define DCU_CTRLDESCLN_4_EN (1 << 31)
+#define DCU_CTRLDESCLN_4_TILE_EN (1 << 30)
+#define DCU_CTRLDESCLN_4_DATA_SEL_CLUT (1 << 29)
+#define DCU_CTRLDESCLN_4_SAFETY_EN (1 << 28)
+#define DCU_CTRLDESCLN_4_TRANS(x) ((x) << 20)
+#define DCU_CTRLDESCLN_4_BPP(x) ((x) << 16)
+#define DCU_CTRLDESCLN_4_RLE_EN (1 << 15)
+#define DCU_CTRLDESCLN_4_LUOFFS(x) ((x) << 4)
+#define DCU_CTRLDESCLN_4_BB_ON (1 << 2)
+#define DCU_CTRLDESCLN_4_AB(x) (x)
+
+#define DCU_CTRLDESCLN_5(x) (0x210 + (x) * 0x40)
+#define DCU_CTRLDESCLN_5_CKMAX_R(x) ((x) << 16)
+#define DCU_CTRLDESCLN_5_CKMAX_G(x) ((x) << 8)
+#define DCU_CTRLDESCLN_5_CKMAX_B(x) (x)
+
+#define DCU_CTRLDESCLN_6(x) (0x214 + (x) * 0x40)
+#define DCU_CTRLDESCLN_6_CKMIN_R(x) ((x) << 16)
+#define DCU_CTRLDESCLN_6_CKMIN_G(x) ((x) << 8)
+#define DCU_CTRLDESCLN_6_CKMIN_B(x) (x)
+
+#define DCU_CTRLDESCLN_7(x) (0x218 + (x) * 0x40)
+#define DCU_CTRLDESCLN_7_TILE_VER(x) ((x) << 16)
+#define DCU_CTRLDESCLN_7_TILE_HOR(x) (x)
+
+#define DCU_CTRLDESCLN_8(x) (0x21c + (x) * 0x40)
+#define DCU_CTRLDESCLN_8_FG_FCOLOR(x) (x)
+
+#define DCU_CTRLDESCLN_9(x) (0x220 + (x) * 0x40)
+#define DCU_CTRLDESCLN_9_BG_BCOLOR(x) (x)
+
+#define DCU_TOTAL_LAYER_NUM 64
+#define DCU_LAYER_NUM_MAX 6
+
+#define BPP_16_RGB565 4
+#define BPP_24_RGB888 5
+#define BPP_32_ARGB8888 6
+
+#define TCON_CTRL1 0x0000
+#define TCON_BYPASS_ENABLE (1 << 29)
+
+#define MFB_SET_ALPHA _IOW('M', 0, __u8)
+#define MFB_GET_ALPHA _IOR('M', 0, __u8)
+#define MFB_SET_LAYER _IOW('M', 4, struct layer_display_offset)
+#define MFB_GET_LAYER _IOR('M', 4, struct layer_display_offset)
+
+struct dcu_fb_data {
+ struct fb_info *fsl_dcu_info[DCU_LAYER_NUM_MAX];
+ struct device *dev;
+ void __iomem *reg_base;
+ unsigned int irq;
+ struct clk *clk;
+ struct fb_videomode *mode_db;
+ int modecnt;
+ struct fb_videomode native_mode;
+ u32 bits_per_pixel;
+ bool pixclockpol;
+};
+
+struct layer_display_offset {
+ int x_layer_d;
+ int y_layer_d;
+};
+
+struct mfb_info {
+ int index;
+ char *id;
+ unsigned long pseudo_palette[16];
+ unsigned char alpha;
+ unsigned char blend;
+ unsigned int count;
+ int x_layer_d; /* layer display x offset to physical screen */
+ int y_layer_d; /* layer display y offset to physical screen */
+ struct dcu_fb_data *parent;
+};
+
+enum mfb_index {
+ LAYER0 = 0,
+ LAYER1,
+ LAYER2,
+ LAYER3,
+ LAYER4,
+ LAYER5,
+};
+
+static struct mfb_info mfb_template[] = {
+ {
+ .index = LAYER0,
+ .id = "Layer0",
+ .alpha = 0xff,
+ .blend = 0,
+ .count = 0,
+ .x_layer_d = 0,
+ .y_layer_d = 0,
+ },
+ {
+ .index = LAYER1,
+ .id = "Layer1",
+ .alpha = 0xff,
+ .blend = 0,
+ .count = 0,
+ .x_layer_d = 50,
+ .y_layer_d = 50,
+ },
+ {
+ .index = LAYER2,
+ .id = "Layer2",
+ .alpha = 0xff,
+ .blend = 0,
+ .count = 0,
+ .x_layer_d = 100,
+ .y_layer_d = 100,
+ },
+ {
+ .index = LAYER3,
+ .id = "Layer3",
+ .alpha = 0xff,
+ .blend = 0,
+ .count = 0,
+ .x_layer_d = 150,
+ .y_layer_d = 150,
+ },
+ {
+ .index = LAYER4,
+ .id = "Layer4",
+ .alpha = 0xff,
+ .blend = 0,
+ .count = 0,
+ .x_layer_d = 200,
+ .y_layer_d = 200,
+ },
+ {
+ .index = LAYER5,
+ .id = "Layer5",
+ .alpha = 0xff,
+ .blend = 0,
+ .count = 0,
+ .x_layer_d = 250,
+ .y_layer_d = 250,
+ },
+};
+
+static int enable_panel(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ unsigned int bpp;
+
+ writel(DCU_CTRLDESCLN_1_HEIGHT(var->yres) |
+ DCU_CTRLDESCLN_1_WIDTH(var->xres),
+ dcufb->reg_base + DCU_CTRLDESCLN_1(mfbi->index));
+ writel(DCU_CTRLDESCLN_2_POSY(mfbi->y_layer_d) |
+ DCU_CTRLDESCLN_2_POSX(mfbi->x_layer_d),
+ dcufb->reg_base + DCU_CTRLDESCLN_2(mfbi->index));
+
+ writel(info->fix.smem_start,
+ dcufb->reg_base + DCU_CTRLDESCLN_3(mfbi->index));
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ bpp = BPP_16_RGB565;
+ break;
+ case 24:
+ bpp = BPP_24_RGB888;
+ break;
+ case 32:
+ bpp = BPP_32_ARGB8888;
+ break;
+ default:
+ dev_err(dcufb->dev, "unsupported color depth: %u\n",
+ var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ writel(DCU_CTRLDESCLN_4_EN |
+ DCU_CTRLDESCLN_4_TRANS(mfbi->alpha) |
+ DCU_CTRLDESCLN_4_BPP(bpp) |
+ DCU_CTRLDESCLN_4_AB(mfbi->blend),
+ dcufb->reg_base + DCU_CTRLDESCLN_4(mfbi->index));
+
+ writel(DCU_CTRLDESCLN_5_CKMAX_R(0xff) |
+ DCU_CTRLDESCLN_5_CKMAX_G(0xff) |
+ DCU_CTRLDESCLN_5_CKMAX_B(0xff),
+ dcufb->reg_base + DCU_CTRLDESCLN_5(mfbi->index));
+ writel(DCU_CTRLDESCLN_6_CKMIN_R(0) |
+ DCU_CTRLDESCLN_6_CKMIN_G(0) |
+ DCU_CTRLDESCLN_6_CKMIN_B(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_6(mfbi->index));
+
+ writel(DCU_CTRLDESCLN_7_TILE_VER(0) | DCU_CTRLDESCLN_7_TILE_HOR(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_7(mfbi->index));
+
+ writel(DCU_CTRLDESCLN_8_FG_FCOLOR(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_8(mfbi->index));
+ writel(DCU_CTRLDESCLN_9_BG_BCOLOR(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_9(mfbi->index));
+
+ writel(DCU_UPDATE_MODE_READREG, dcufb->reg_base + DCU_UPDATE_MODE);
+ return 0;
+}
+
+static int disable_panel(struct fb_info *info)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+
+ writel(DCU_CTRLDESCLN_1_HEIGHT(0) |
+ DCU_CTRLDESCLN_1_WIDTH(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_1(mfbi->index));
+ writel(DCU_CTRLDESCLN_2_POSY(0) | DCU_CTRLDESCLN_2_POSX(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_2(mfbi->index));
+
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_3(mfbi->index));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_4(mfbi->index));
+
+ writel(DCU_CTRLDESCLN_5_CKMAX_R(0) |
+ DCU_CTRLDESCLN_5_CKMAX_G(0) |
+ DCU_CTRLDESCLN_5_CKMAX_B(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_5(mfbi->index));
+ writel(DCU_CTRLDESCLN_6_CKMIN_R(0) |
+ DCU_CTRLDESCLN_6_CKMIN_G(0) |
+ DCU_CTRLDESCLN_6_CKMIN_B(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_6(mfbi->index));
+
+ writel(DCU_CTRLDESCLN_7_TILE_VER(0) | DCU_CTRLDESCLN_7_TILE_HOR(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_7(mfbi->index));
+
+ writel(DCU_CTRLDESCLN_8_FG_FCOLOR(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_8(mfbi->index));
+ writel(DCU_CTRLDESCLN_9_BG_BCOLOR(0),
+ dcufb->reg_base + DCU_CTRLDESCLN_9(mfbi->index));
+
+ writel(DCU_UPDATE_MODE_READREG, dcufb->reg_base + DCU_UPDATE_MODE);
+ return 0;
+}
+
+static void enable_controller(struct fb_info *info)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ unsigned int dcu_mode;
+
+ dcu_mode = readl(dcufb->reg_base + DCU_DCU_MODE);
+ writel(dcu_mode | DCU_MODE_DCU_MODE(DCU_MODE_NORMAL),
+ dcufb->reg_base + DCU_DCU_MODE);
+}
+
+static void disable_controller(struct fb_info *info)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+
+ writel(DCU_MODE_DCU_MODE(DCU_MODE_OFF),
+ dcufb->reg_base + DCU_DCU_MODE);
+}
+
+static int fsl_dcu_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+
+ if (var->xoffset + info->var.xres > info->var.xres_virtual)
+ var->xoffset = info->var.xres_virtual - info->var.xres;
+
+ if (var->yoffset + info->var.yres > info->var.yres_virtual)
+ var->yoffset = info->var.yres_virtual - info->var.yres;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ var->red.length = 5;
+ var->red.offset = 11;
+ var->red.msb_right = 0;
+
+ var->green.length = 6;
+ var->green.offset = 5;
+ var->green.msb_right = 0;
+
+ var->blue.length = 5;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 24:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 32:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 8;
+ var->transp.offset = 24;
+ var->transp.msb_right = 0;
+ break;
+ default:
+ dev_err(dcufb->dev, "unsupported color depth: %u\n",
+ var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fsl_dcu_calc_div(struct fb_info *info)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ unsigned long long div;
+ div = (unsigned long long)(clk_get_rate(dcufb->clk) / 1000);
+ div *= info->var.pixclock;
+ do_div(div, 1000000000);
+
+ return div;
+}
+
+static void update_controller(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ unsigned int div, pol = 0;
+
+ div = fsl_dcu_calc_div(info);
+ writel((div - 1), dcufb->reg_base + DCU_DIV_RATIO);
+
+ writel(DCU_DISP_SIZE_DELTA_Y(var->yres) |
+ DCU_DISP_SIZE_DELTA_X(var->xres / 16),
+ dcufb->reg_base + DCU_DISP_SIZE);
+
+ /* Horizontal and vertical sync parameters */
+ writel(DCU_HSYN_PARA_BP(var->left_margin) |
+ DCU_HSYN_PARA_PW(var->hsync_len) |
+ DCU_HSYN_PARA_FP(var->right_margin),
+ dcufb->reg_base + DCU_HSYN_PARA);
+
+ writel(DCU_VSYN_PARA_BP(var->upper_margin) |
+ DCU_VSYN_PARA_PW(var->vsync_len) |
+ DCU_VSYN_PARA_FP(var->lower_margin),
+ dcufb->reg_base + DCU_VSYN_PARA);
+
+ /*
+ * pixclockpol = 0 => display samples data on falling edge => 0
+ * pixclockpol = 1 => display samples data on rising edge => 1 (default)
+ */
+ if (dcufb->pixclockpol)
+ pol |= DCU_SYN_POL_INV_PXCK_FALL;
+
+ /* hsync:0 => active low => HS_LOW */
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+ pol |= DCU_SYN_POL_INV_HS_LOW;
+
+ /* vsync:0 => active low => VS_LOW */
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+ pol |= DCU_SYN_POL_INV_VS_LOW;
+
+ writel(pol, dcufb->reg_base + DCU_SYN_POL);
+
+ writel(DCU_BGND_R(0) | DCU_BGND_G(0) | DCU_BGND_B(0),
+ dcufb->reg_base + DCU_BGND);
+
+ writel(DCU_MODE_BLEND_ITER(DCU_LAYER_NUM_MAX) | DCU_MODE_RASTER_EN,
+ dcufb->reg_base + DCU_DCU_MODE);
+
+ writel(DCU_THRESHOLD_LS_BF_VS(0x3) | DCU_THRESHOLD_OUT_BUF_HIGH(0x78) |
+ DCU_THRESHOLD_OUT_BUF_LOW(0), dcufb->reg_base + DCU_THRESHOLD);
+}
+
+static int map_video_memory(struct fb_info *info)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ u32 smem_len = info->fix.line_length * info->var.yres_virtual;
+
+ info->fix.smem_len = smem_len;
+
+ info->screen_base = dma_alloc_writecombine(info->device,
+ info->fix.smem_len, (dma_addr_t *)&info->fix.smem_start,
+ GFP_KERNEL);
+ if (!info->screen_base) {
+ dev_err(dcufb->dev, "unable to allocate fb memory\n");
+ return -ENOMEM;
+ }
+
+ memset(info->screen_base, 0, info->fix.smem_len);
+
+ return 0;
+}
+
+static void unmap_video_memory(struct fb_info *info)
+{
+ if (!info->screen_base)
+ return;
+
+ dma_free_writecombine(info->device, info->fix.smem_len,
+ info->screen_base, info->fix.smem_start);
+
+ info->screen_base = NULL;
+ info->fix.smem_start = 0;
+ info->fix.smem_len = 0;
+}
+
+static int fsl_dcu_set_layer(struct fb_info *info)
+{
+ struct mfb_info *mfbi = info->par;
+ struct fb_var_screeninfo *var = &info->var;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ int pixel_offset;
+ unsigned long addr;
+
+ pixel_offset = (var->yoffset * var->xres_virtual) + var->xoffset;
+ addr = info->fix.smem_start +
+ (pixel_offset * (var->bits_per_pixel >> 3));
+
+ writel(addr, dcufb->reg_base + DCU_CTRLDESCLN_3(mfbi->index));
+ writel(DCU_UPDATE_MODE_READREG, dcufb->reg_base + DCU_UPDATE_MODE);
+
+ return 0;
+}
+
+static int fsl_dcu_set_par(struct fb_info *info)
+{
+ unsigned long len;
+ struct fb_var_screeninfo *var = &info->var;
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+
+ len = info->var.yres_virtual * info->fix.line_length;
+ if (len != info->fix.smem_len) {
+ if (info->fix.smem_start)
+ unmap_video_memory(info);
+
+ if (map_video_memory(info)) {
+ dev_err(dcufb->dev, "unable to allocate fb memory\n");
+ return -ENOMEM;
+ }
+ }
+
+ /* Only layer 0 could update LCD controller */
+ if (mfbi->index == LAYER0) {
+ update_controller(info);
+ enable_controller(info);
+ }
+
+ enable_panel(info);
+ return 0;
+}
+
+static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
+{
+ return ((val<<width) + 0x7FFF - val) >> 16;
+}
+
+static int fsl_dcu_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp, struct fb_info *info)
+{
+ unsigned int val;
+ int ret = -EINVAL;
+
+ /*
+ * If greyscale is true, then we convert the RGB value
+ * to greyscale no matter what visual we are using.
+ */
+ if (info->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green +
+ 7471 * blue) >> 16;
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ /*
+ * 16-bit True Colour. We encode the RGB value
+ * according to the RGB bitfield information.
+ */
+ if (regno < 16) {
+ u32 *pal = info->pseudo_palette;
+
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
+
+ val = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ pal[regno] = val;
+ ret = 0;
+ }
+ break;
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ break;
+ }
+
+ return ret;
+}
+
+static int fsl_dcu_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ if ((info->var.xoffset == var->xoffset) &&
+ (info->var.yoffset == var->yoffset))
+ return 0;
+
+ if ((var->xoffset + info->var.xres) > info->var.xres_virtual
+ || (var->yoffset + info->var.yres) > info->var.yres_virtual)
+ return -EINVAL;
+
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+
+ if (var->vmode & FB_VMODE_YWRAP)
+ info->var.vmode |= FB_VMODE_YWRAP;
+ else
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+
+ fsl_dcu_set_layer(info);
+
+ return 0;
+}
+
+static int fsl_dcu_blank(int blank_mode, struct fb_info *info)
+{
+ switch (blank_mode) {
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ disable_panel(info);
+ break;
+ case FB_BLANK_POWERDOWN:
+ disable_controller(info);
+ break;
+ case FB_BLANK_UNBLANK:
+ enable_panel(info);
+ break;
+ }
+
+ return 0;
+}
+
+static int fsl_dcu_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ struct layer_display_offset layer_d;
+ void __user *buf = (void __user *)arg;
+ unsigned char alpha;
+
+ switch (cmd) {
+ case MFB_SET_LAYER:
+ if (copy_from_user(&layer_d, buf, sizeof(layer_d)))
+ return -EFAULT;
+ mfbi->x_layer_d = layer_d.x_layer_d;
+ mfbi->y_layer_d = layer_d.y_layer_d;
+ fsl_dcu_set_par(info);
+ break;
+ case MFB_GET_LAYER:
+ layer_d.x_layer_d = mfbi->x_layer_d;
+ layer_d.y_layer_d = mfbi->y_layer_d;
+ if (copy_to_user(buf, &layer_d, sizeof(layer_d)))
+ return -EFAULT;
+ break;
+ case MFB_GET_ALPHA:
+ alpha = mfbi->alpha;
+ if (copy_to_user(buf, &alpha, sizeof(alpha)))
+ return -EFAULT;
+ break;
+ case MFB_SET_ALPHA:
+ if (copy_from_user(&alpha, buf, sizeof(alpha)))
+ return -EFAULT;
+ mfbi->blend = 1;
+ mfbi->alpha = alpha;
+ fsl_dcu_set_par(info);
+ break;
+ default:
+ dev_err(dcufb->dev, "unknown ioctl command (0x%08X)\n", cmd);
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+static void reset_layers(struct dcu_fb_data *dcufb)
+{
+ int i;
+
+ for (i = 1; i < DCU_TOTAL_LAYER_NUM; i++) {
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_1(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_2(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_3(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_4(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_5(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_6(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_7(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_8(i));
+ writel(0, dcufb->reg_base + DCU_CTRLDESCLN_9(i));
+ }
+ writel(DCU_UPDATE_MODE_READREG, dcufb->reg_base + DCU_UPDATE_MODE);
+}
+
+static int fsl_dcu_open(struct fb_info *info, int user)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ u32 int_mask = readl(dcufb->reg_base + DCU_INT_MASK);
+ int ret = 0;
+
+ mfbi->index = info->node;
+
+ mfbi->count++;
+ if (mfbi->count == 1) {
+ fsl_dcu_check_var(&info->var, info);
+ ret = fsl_dcu_set_par(info);
+ if (ret < 0)
+ mfbi->count--;
+ else
+ writel(int_mask & ~DCU_INT_MASK_UNDRUN,
+ dcufb->reg_base + DCU_INT_MASK);
+ }
+
+ return ret;
+}
+
+static int fsl_dcu_release(struct fb_info *info, int user)
+{
+ struct mfb_info *mfbi = info->par;
+ int ret = 0;
+
+ mfbi->count--;
+ if (mfbi->count == 0)
+ ret = disable_panel(info);
+
+ return ret;
+}
+
+static struct fb_ops fsl_dcu_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = fsl_dcu_check_var,
+ .fb_set_par = fsl_dcu_set_par,
+ .fb_setcolreg = fsl_dcu_setcolreg,
+ .fb_blank = fsl_dcu_blank,
+ .fb_pan_display = fsl_dcu_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_ioctl = fsl_dcu_ioctl,
+ .fb_open = fsl_dcu_open,
+ .fb_release = fsl_dcu_release,
+};
+
+static int fsl_dcu_init_modelist(struct dcu_fb_data *dcufb)
+{
+ struct device_node *np = dcufb->dev->of_node;
+ struct device_node *display_np;
+ struct display_timings *timings;
+ int i;
+ int ret = 0;
+
+ display_np = of_parse_phandle(np, "display", 0);
+ if (!display_np) {
+ dev_err(dcufb->dev, "failed to find display phandle\n");
+ return -ENOENT;
+ }
+
+ ret = of_property_read_u32(display_np, "bits-per-pixel",
+ &dcufb->bits_per_pixel);
+ if (ret < 0) {
+ dev_err(dcufb->dev, "failed to get property bits-per-pixel\n");
+ goto put_display_node;
+ }
+
+ timings = of_get_display_timings(display_np);
+ if (!timings) {
+ dev_err(dcufb->dev, "failed to get display timings\n");
+ ret = -ENOENT;
+ goto put_display_node;
+ }
+
+ dcufb->mode_db = devm_kzalloc(dcufb->dev, sizeof(struct fb_videomode) *
+ timings->num_timings, GFP_KERNEL);
+ if (!dcufb->mode_db) {
+ ret = -ENOMEM;
+ goto put_display_node;
+ }
+
+ for (i = 0; i < timings->num_timings; i++) {
+ struct videomode vm;
+
+ ret = videomode_from_timings(timings, &vm, i);
+ if (ret < 0)
+ goto free_dcu_mode_db;
+
+ ret = fb_videomode_from_videomode(&vm, &dcufb->mode_db[i]);
+ if (ret < 0)
+ goto free_dcu_mode_db;
+
+ if (i == timings->native_mode) {
+ fb_videomode_from_videomode(&vm, &dcufb->native_mode);
+
+ /*
+ * Kernel pixelclk settings are controller centric
+ * whereas DCU is display centric:
+ * PIXDATA_NEGEDGE (drive data on falling edge)
+ * => pixclockpol (display samples data on rising edge)
+ */
+ dcufb->pixclockpol = timings->timings[i]->flags &
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+ }
+
+ dcufb->modecnt++;
+ }
+
+ of_node_put(display_np);
+ return 0;
+
+free_dcu_mode_db:
+ kfree(dcufb->mode_db);
+ dcufb->mode_db = NULL;
+put_display_node:
+ of_node_put(display_np);
+ return ret;
+}
+
+static int parse_opt(struct dcu_fb_data *dcufb, char *this_opt, u32 *sync)
+{
+ if (!strncmp(this_opt, "hsync:", 6)) {
+ if (simple_strtoul(this_opt+6, NULL, 0))
+ *sync |= FB_SYNC_HOR_HIGH_ACT;
+ } else if (!strncmp(this_opt, "vsync:", 6)) {
+ if (simple_strtoul(this_opt+6, NULL, 0))
+ *sync |= FB_SYNC_VERT_HIGH_ACT;
+ } else if (!strncmp(this_opt, "pixclockpol:", 12))
+ dcufb->pixclockpol = !!simple_strtoul(this_opt+12, NULL, 0);
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int fsl_dcu_parse_options(struct dcu_fb_data *dcufb,
+ struct fb_info *info, char *option)
+{
+ char *this_opt;
+ int ret = 0;
+ u32 sync = 0;
+
+ while ((this_opt = strsep(&option, ",")) != NULL) {
+ /* Parse driver specific arguments */
+ if (parse_opt(dcufb, this_opt, &sync) == 0)
+ continue;
+
+ /* No valid driver specific argument, has to be mode */
+ ret = fb_find_mode(&info->var, info, this_opt, dcufb->mode_db,
+ dcufb->modecnt, &dcufb->native_mode,
+ dcufb->bits_per_pixel);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Overwrite from command line */
+ info->var.sync = sync;
+ return 0;
+}
+
+static int install_framebuffer(struct fb_info *info, char *option)
+{
+ struct mfb_info *mfbi = info->par;
+ struct dcu_fb_data *dcufb = mfbi->parent;
+ struct fb_videomode *mode = &dcufb->native_mode;
+ int ret;
+
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->fbops = &fsl_dcu_ops;
+ info->flags = FBINFO_FLAG_DEFAULT;
+ info->pseudo_palette = &mfbi->pseudo_palette;
+
+ fb_alloc_cmap(&info->cmap, 16, 0);
+
+ INIT_LIST_HEAD(&info->modelist);
+ fb_add_videomode(mode, &info->modelist);
+ fb_videomode_to_var(&info->var, mode);
+ info->var.bits_per_pixel = dcufb->bits_per_pixel;
+
+ /* Parse DCU option for every layer... */
+ ret = fsl_dcu_parse_options(dcufb, info, option);
+ if (ret < 0)
+ return ret;
+
+ fsl_dcu_check_var(&info->var, info);
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ dev_err(dcufb->dev, "failed to register framebuffer device\n");
+ return ret;
+ }
+
+ printk(KERN_INFO "fb%d: fb device registered successfully.\n",
+ info->node);
+ return 0;
+}
+
+static void uninstall_framebuffer(struct fb_info *info)
+{
+ unregister_framebuffer(info);
+ unmap_video_memory(info);
+
+ if (&info->cmap)
+ fb_dealloc_cmap(&info->cmap);
+}
+
+static irqreturn_t fsl_dcu_irq(int irq, void *dev_id)
+{
+ struct dcu_fb_data *dcufb = dev_id;
+ unsigned int status = readl(dcufb->reg_base + DCU_INT_STATUS);
+ u32 dcu_mode;
+
+ if (status & DCU_INT_STATUS_UNDRUN) {
+ dcu_mode = readl(dcufb->reg_base + DCU_DCU_MODE);
+ dcu_mode &= ~DCU_MODE_DCU_MODE_MASK;
+ writel(dcu_mode | DCU_MODE_DCU_MODE(DCU_MODE_OFF),
+ dcufb->reg_base + DCU_DCU_MODE);
+ udelay(1);
+ writel(dcu_mode | DCU_MODE_DCU_MODE(DCU_MODE_NORMAL),
+ dcufb->reg_base + DCU_DCU_MODE);
+ }
+
+ writel(status, dcufb->reg_base + DCU_INT_STATUS);
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int fsl_dcu_runtime_suspend(struct device *dev)
+{
+ struct dcu_fb_data *dcufb = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(dcufb->clk);
+
+ return 0;
+}
+
+static int fsl_dcu_runtime_resume(struct device *dev)
+{
+ struct dcu_fb_data *dcufb = dev_get_drvdata(dev);
+
+ clk_prepare_enable(dcufb->clk);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int fsl_dcu_suspend(struct device *dev)
+{
+ struct dcu_fb_data *dcufb = dev_get_drvdata(dev);
+ struct fb_info *fbi = dcufb->fsl_dcu_info[0];
+
+ console_lock();
+ fb_set_suspend(fbi, 1);
+ console_unlock();
+
+ disable_panel(fbi);
+
+ disable_controller(dcufb->fsl_dcu_info[0]);
+ clk_disable_unprepare(dcufb->clk);
+
+ return 0;
+}
+
+static int fsl_dcu_resume(struct device *dev)
+{
+ struct dcu_fb_data *dcufb = dev_get_drvdata(dev);
+ struct fb_info *fbi = dcufb->fsl_dcu_info[0];
+
+ clk_prepare_enable(dcufb->clk);
+ enable_controller(dcufb->fsl_dcu_info[0]);
+
+ console_lock();
+ fb_set_suspend(fbi, 0);
+ console_unlock();
+
+ fsl_dcu_set_par(fbi);
+
+ return 0;
+}
+#endif
+
+static int bypass_tcon(struct device_node *np)
+{
+ struct device_node *tcon_np;
+ struct platform_device *tcon_pdev;
+ struct clk *tcon_clk;
+ struct resource *res;
+ void __iomem *tcon_reg;
+
+ tcon_np = of_parse_phandle(np, "tcon-controller", 0);
+ if (!tcon_np)
+ return -EINVAL;
+
+ tcon_pdev = of_find_device_by_node(tcon_np);
+ if (!tcon_pdev)
+ return -EINVAL;
+
+ tcon_clk = devm_clk_get(&tcon_pdev->dev, "tcon");
+ if (IS_ERR(tcon_clk))
+ return PTR_ERR(tcon_clk);
+ clk_prepare_enable(tcon_clk);
+
+ res = platform_get_resource(tcon_pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ tcon_reg = devm_ioremap_resource(&tcon_pdev->dev, res);
+ if (IS_ERR(tcon_reg))
+ return PTR_ERR(tcon_reg);
+
+ writel(TCON_BYPASS_ENABLE, tcon_reg + TCON_CTRL1);
+ clk_disable_unprepare(tcon_clk);
+ return 0;
+}
+
+static int fsl_dcu_probe(struct platform_device *pdev)
+{
+ struct dcu_fb_data *dcufb;
+ struct mfb_info *mfbi;
+ struct resource *res;
+ int ret = 0;
+ int i;
+ char *option = NULL;
+
+ fb_get_options("dcufb", &option);
+
+ if (option != NULL) {
+ dev_info(&pdev->dev, "using cmd options: %s\n", option);
+ if (!strcmp(option, "off"))
+ return -ENODEV;
+ }
+
+ dcufb = devm_kzalloc(&pdev->dev,
+ sizeof(struct dcu_fb_data), GFP_KERNEL);
+ if (!dcufb)
+ return -ENOMEM;
+
+ dcufb->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, dcufb);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "could not get memory IO resource\n");
+ return -ENODEV;
+ }
+
+ dcufb->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(dcufb->reg_base)) {
+ dev_err(&pdev->dev, "could not ioremap resource\n");
+ return PTR_ERR(dcufb->reg_base);
+ }
+
+ dcufb->irq = platform_get_irq(pdev, 0);
+ if (!dcufb->irq) {
+ dev_err(&pdev->dev, "could not get irq\n");
+ return -EINVAL;
+ }
+
+ ret = devm_request_irq(&pdev->dev, dcufb->irq, fsl_dcu_irq,
+ 0, DRIVER_NAME, dcufb);
+ if (ret) {
+ dev_err(&pdev->dev, "could not request irq\n");
+ goto failed_ioremap;
+ }
+
+ /* Put TCON in bypass mode, so the input signals from DCU are passed
+ * through TCON unchanged */
+ ret = bypass_tcon(pdev->dev.of_node);
+ if (ret) {
+ dev_err(&pdev->dev, "could not bypass TCON\n");
+ goto failed_bypasstcon;
+ }
+
+ dcufb->clk = devm_clk_get(&pdev->dev, "dcu");
+ if (IS_ERR(dcufb->clk)) {
+ ret = PTR_ERR(dcufb->clk);
+ dev_err(&pdev->dev, "could not get clock\n");
+ goto failed_getclock;
+ }
+ clk_prepare_enable(dcufb->clk);
+
+ pm_runtime_enable(dcufb->dev);
+ pm_runtime_get_sync(dcufb->dev);
+
+ ret = fsl_dcu_init_modelist(dcufb);
+ if (ret)
+ goto failed_alloc_framebuffer;
+
+ reset_layers(dcufb);
+
+ for (i = 0; i < ARRAY_SIZE(dcufb->fsl_dcu_info); i++) {
+ dcufb->fsl_dcu_info[i] =
+ framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
+ if (!dcufb->fsl_dcu_info[i]) {
+ ret = -ENOMEM;
+ goto failed_alloc_framebuffer;
+ }
+
+ dcufb->fsl_dcu_info[i]->fix.smem_start = 0;
+
+ mfbi = dcufb->fsl_dcu_info[i]->par;
+ memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
+ mfbi->parent = dcufb;
+
+ ret = install_framebuffer(dcufb->fsl_dcu_info[i], option);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "could not register framebuffer %d\n", i);
+ goto failed_register_framebuffer;
+ }
+ }
+
+ if (option != NULL) {
+ ret = fsl_dcu_parse_options(dcufb, dcufb->fsl_dcu_info[0],
+ option);
+ if (ret < 0)
+ goto failed_alloc_framebuffer;
+ }
+
+ return 0;
+
+failed_register_framebuffer:
+ for (i = 0; i < ARRAY_SIZE(dcufb->fsl_dcu_info); i++) {
+ if (dcufb->fsl_dcu_info[i])
+ framebuffer_release(dcufb->fsl_dcu_info[i]);
+ }
+failed_alloc_framebuffer:
+ pm_runtime_put_sync(dcufb->dev);
+ pm_runtime_disable(dcufb->dev);
+failed_getclock:
+failed_bypasstcon:
+ free_irq(dcufb->irq, dcufb);
+failed_ioremap:
+ return ret;
+}
+
+static int fsl_dcu_remove(struct platform_device *pdev)
+{
+ struct dcu_fb_data *dcufb = dev_get_drvdata(&pdev->dev);
+ int i;
+
+ pm_runtime_get_sync(dcufb->dev);
+
+ disable_controller(dcufb->fsl_dcu_info[0]);
+
+ clk_disable_unprepare(dcufb->clk);
+ free_irq(dcufb->irq, dcufb);
+
+ for (i = 0; i < ARRAY_SIZE(dcufb->fsl_dcu_info); i++) {
+ uninstall_framebuffer(dcufb->fsl_dcu_info[i]);
+ framebuffer_release(dcufb->fsl_dcu_info[i]);
+ }
+
+ pm_runtime_put_sync(dcufb->dev);
+ pm_runtime_disable(dcufb->dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops fsl_dcu_pm_ops = {
+ SET_RUNTIME_PM_OPS(fsl_dcu_runtime_suspend,
+ fsl_dcu_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_suspend, fsl_dcu_resume)
+};
+
+static struct of_device_id fsl_dcu_dt_ids[] = {
+ {
+ .compatible = "fsl,vf610-dcu",
+ },
+ {}
+};
+
+static struct platform_driver fsl_dcu_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_dcu_dt_ids,
+ .pm = &fsl_dcu_pm_ops,
+ },
+ .probe = fsl_dcu_probe,
+ .remove = fsl_dcu_remove,
+};
+
+module_platform_driver(fsl_dcu_driver);
+
+MODULE_AUTHOR("Alison Wang");
+MODULE_DESCRIPTION("Freescale DCU framebuffer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/dt-bindings/clock/imx5-clock.h b/include/dt-bindings/clock/imx5-clock.h
index 5f2667ecd98e..f4b7478e23c8 100644
--- a/include/dt-bindings/clock/imx5-clock.h
+++ b/include/dt-bindings/clock/imx5-clock.h
@@ -198,6 +198,9 @@
#define IMX5_CLK_OCRAM 186
#define IMX5_CLK_SAHARA_IPG_GATE 187
#define IMX5_CLK_SATA_REF 188
-#define IMX5_CLK_END 189
+#define IMX5_CLK_STEP_SEL 189
+#define IMX5_CLK_CPU_PODF_SEL 190
+#define IMX5_CLK_ARM 191
+#define IMX5_CLK_END 192
#endif /* __DT_BINDINGS_CLOCK_IMX5_H */
diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h
index 801c0ac50c47..0b1a100007ad 100644
--- a/include/dt-bindings/clock/vf610-clock.h
+++ b/include/dt-bindings/clock/vf610-clock.h
@@ -192,6 +192,9 @@
#define VF610_PLL5_BYPASS 179
#define VF610_PLL6_BYPASS 180
#define VF610_PLL7_BYPASS 181
-#define VF610_CLK_END 182
+#define VF610_CLK_SNVS 182
+#define VF610_CLK_TCON0 183
+#define VF610_CLK_DDRMC 184
+#define VF610_CLK_END 185
#endif /* __DT_BINDINGS_CLOCK_VF610_H */
diff --git a/include/linux/input/fusion_F0710A.h b/include/linux/input/fusion_F0710A.h
new file mode 100644
index 000000000000..7d152cbdd06e
--- /dev/null
+++ b/include/linux/input/fusion_F0710A.h
@@ -0,0 +1,20 @@
+/* linux/input/fusion_F0710A.h
+ *
+ * Platform data for Fusion F0710A driver
+ *
+ * Copyright (c) 2013 Toradex AG (stefan.agner@toradex.ch)
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#ifndef __LINUX_I2C_FUSION_F0710A_H
+#define __LINUX_I2C_FUSION_F0710A_H
+
+/* Board specific touch screen initial values */
+struct fusion_f0710a_init_data {
+ int (*pinmux_fusion_pins)(void);
+ int gpio_int;
+ int gpio_reset;
+};
+
+#endif /* __LINUX_I2C_FUSION_F0710A_H */
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
index ff44374a1a4e..c877cad61a13 100644
--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -395,4 +395,43 @@
#define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK (0x3 << 17)
#define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK (0x1 << 14)
+/* For imx6sx iomux gpr register field define */
+#define IMX6SX_GPR1_VDEC_SW_RST_MASK (0x1 << 20)
+#define IMX6SX_GPR1_VDEC_SW_RST_RESET (0x1 << 20)
+#define IMX6SX_GPR1_VDEC_SW_RST_RELEASE (0x0 << 20)
+#define IMX6SX_GPR1_VADC_SW_RST_MASK (0x1 << 19)
+#define IMX6SX_GPR1_VADC_SW_RST_RESET (0x1 << 19)
+#define IMX6SX_GPR1_VADC_SW_RST_RELEASE (0x0 << 19)
+#define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK (0x3 << 13)
+#define IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK (0x3 << 17)
+#define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_EXT (0x3 << 13)
+
+#define IMX6SX_GPR4_FEC_ENET1_STOP_REQ (0x1 << 3)
+#define IMX6SX_GPR4_FEC_ENET2_STOP_REQ (0x1 << 4)
+
+#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_MASK (0x1 << 3)
+#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF1 (0x0 << 3)
+#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF2 (0x1 << 3)
+
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_MASK (0x3 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_EXT_PIN (0x0 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_CVD (0x1 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_VDAC_TO_CSI (0x2 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_GND (0x3 << 27)
+#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_MASK (0x1 << 26)
+#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_ENABLE (0x1 << 26)
+#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_DISABLE (0x0 << 26)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_MASK (0x3 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_EXT_PIN (0x0 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_CVD (0x1 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_VDAC_TO_CSI (0x2 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_GND (0x3 << 4)
+
+#define IMX6SX_GPR5_DISP_MUX_DCIC2_LCDIF2 (0x0 << 2)
+#define IMX6SX_GPR5_DISP_MUX_DCIC2_LVDS (0x1 << 2)
+#define IMX6SX_GPR5_DISP_MUX_DCIC2_MASK (0x1 << 2)
+#define IMX6SX_GPR5_DISP_MUX_DCIC1_LCDIF1 (0x0 << 1)
+#define IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS (0x1 << 1)
+#define IMX6SX_GPR5_DISP_MUX_DCIC1_MASK (0x1 << 1)
+
#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
diff --git a/include/linux/vf610_mscm.h b/include/linux/vf610_mscm.h
new file mode 100644
index 000000000000..881fbd772a95
--- /dev/null
+++ b/include/linux/vf610_mscm.h
@@ -0,0 +1,11 @@
+#ifndef __VF610_MSCM__
+#define __VF610_MSCM__
+
+#include <linux/interrupt.h>
+
+int mscm_request_cpu2cpu_irq(unsigned int intid, irq_handler_t handler,
+ const char *name, void *priv);
+void mscm_free_cpu2cpu_irq(unsigned int intid, void *priv);
+void mscm_trigger_cpu2cpu_irq(unsigned int intid, int cpuid);
+
+#endif /* __VF610_MSCM__ */
diff --git a/include/linux/vf610_sema4.h b/include/linux/vf610_sema4.h
new file mode 100644
index 000000000000..d0587aaf370b
--- /dev/null
+++ b/include/linux/vf610_sema4.h
@@ -0,0 +1,33 @@
+#ifndef __MVF_SEMA4__
+#define __MVF_SEMA4__
+
+#define MVF_SHMEM_SEMAPHORE_NUMBER (1)
+#define MVF_PRINTF_SEMAPHORE_NUMBER (2)
+#define MVF_I2C_SEMAPHORE_NUMBER (3)
+#define MVF_RESERVED1_SEMAPHORE_NUMBER (4)
+#define MVF_RESERVED2_SEMAPHORE_NUMBER (5)
+
+#ifdef __KERNEL__
+
+#include <linux/sched.h>
+
+typedef struct mvf_sema4_handle_struct {
+ int gate_num;
+ wait_queue_head_t wait_queue;
+ // stats
+ u32 attempts;
+ u32 interrupts;
+ u32 failures;
+ struct timeval request_time;
+ u64 total_latency_us;
+ u32 worst_latency_us;
+} MVF_SEMA4;
+
+int mvf_sema4_assign(int gate_num, MVF_SEMA4** sema4_p);
+int mvf_sema4_deassign(MVF_SEMA4 *sema4);
+int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us, bool use_interrupts);
+int mvf_sema4_unlock(MVF_SEMA4 *sema4);
+int mvf_sema4_test(MVF_SEMA4 *sema4);
+
+#endif /* __KERNEL__ */
+#endif /* __MVF_SEMA4__ */