summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKe Qinghua <qinghua.ke@freescale.com>2014-07-01 11:28:51 +0800
committerKe Qinghua <qinghua.ke@freescale.com>2014-07-01 11:47:26 +0800
commitd5800fcb9c0a07366c920414326ecb61d362b7b1 (patch)
tree686d7f7c5291fae49b48dbc95355e06d0c42d945
parentffa6a894db981abaed4e023cb2b198cc22e68f0f (diff)
parent58ad81506e01e6a9625bc096595113f1f6bbe521 (diff)
Merge remote-tracking branch 'remotes/fsl-linux-sdk/imx_3.10.31_1.1.0_beta' into imx_3.10.y_android
Conflicts: arch/arm/boot/dts/imx6qdl-sabreauto.dtsi arch/arm/boot/dts/imx6qdl-sabresd.dtsi drivers/hwmon/Makefile drivers/hwmon/mma8x5x.c drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c drivers/usb/chipidea/otg_fsm.c drivers/usb/chipidea/udc.c drivers/usb/gadget/udc-core.c drivers/usb/phy/Kconfig drivers/usb/phy/Makefile
-rw-r--r--Documentation/devicetree/bindings/clock/imx6q-clock.txt3
-rw-r--r--Documentation/usb/chipidea.txt9
-rw-r--r--Makefile2
-rw-r--r--arch/arm/boot/dts/imx6dl.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabreauto.dtsi16
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi17
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts3
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6sx-19x19-arm2.dts13
-rw-r--r--arch/arm/boot/dts/imx6sx-sdb.dts23
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi20
-rw-r--r--arch/arm/configs/imx_v7_android_defconfig49
-rw-r--r--arch/arm/mach-imx/busfreq-imx6.c18
-rw-r--r--arch/arm/mach-imx/busfreq_ddr3.c3
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c89
-rw-r--r--arch/arm/mach-imx/clk-imx6sl.c10
-rw-r--r--arch/arm/mach-imx/clk-imx6sx.c18
-rw-r--r--arch/arm/mach-imx/clk-pllv3.c2
-rw-r--r--arch/arm/mach-imx/clk.h10
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6.S15
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6sx.S155
-rw-r--r--arch/arm/mach-imx/gpc.c74
-rw-r--r--drivers/char/imx_mcc/Kconfig8
-rw-r--r--drivers/char/imx_mcc/Makefile1
-rw-r--r--drivers/char/imx_mcc/imx_mcc_tty.c253
-rw-r--r--drivers/clk/clk-mux.c2
-rw-r--r--drivers/clk/clk.c13
-rw-r--r--drivers/cpufreq/cpufreq-imx6.c6
-rw-r--r--drivers/dma/pxp/pxp_dma_v2.c110
-rw-r--r--drivers/hwmon/Kconfig6
-rw-r--r--drivers/hwmon/Makefile4
-rw-r--r--drivers/hwmon/mma8x5x.c441
-rw-r--r--drivers/media/platform/mxc/capture/csi_v4l2_capture.c215
-rw-r--r--drivers/media/platform/mxc/capture/fsl_csi.c173
-rw-r--r--drivers/media/platform/mxc/capture/fsl_csi.h85
-rw-r--r--drivers/media/platform/mxc/capture/mxc_v4l2_capture.h5
-rw-r--r--drivers/media/platform/mxc/capture/mxc_vadc.c2
-rw-r--r--drivers/net/can/m_can.c295
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c5
-rw-r--r--drivers/tty/hvc/hvc_console.c2
-rw-r--r--drivers/tty/n_gsm.c11
-rw-r--r--drivers/tty/tty_io.c23
-rw-r--r--drivers/usb/chipidea/ci.h18
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c10
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.h1
-rw-r--r--drivers/usb/chipidea/core.c107
-rw-r--r--drivers/usb/chipidea/host.c61
-rw-r--r--drivers/usb/chipidea/host.h6
-rw-r--r--drivers/usb/chipidea/otg.c77
-rw-r--r--drivers/usb/chipidea/otg.h1
-rw-r--r--drivers/usb/chipidea/otg_fsm.c92
-rw-r--r--drivers/usb/chipidea/otg_fsm.h8
-rw-r--r--drivers/usb/chipidea/udc.c47
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c31
-rw-r--r--drivers/usb/common/usb-otg-fsm.c63
-rw-r--r--drivers/usb/gadget/udc-core.c1
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c36
-rw-r--r--drivers/video/mxsfb.c13
-rw-r--r--include/dt-bindings/clock/imx6sx-clock.h3
-rw-r--r--include/linux/clk-provider.h6
-rw-r--r--include/linux/usb/gadget.h1
-rw-r--r--include/linux/usb/otg-fsm.h12
-rw-r--r--sound/soc/fsl/fsl_spdif.c9
64 files changed, 2038 insertions, 786 deletions
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
index 622e5ac90d28..845cc69bc9b7 100644
--- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -45,8 +45,6 @@ clocks and IDs.
gpu3d_shader_sel 30
ipu1_sel 31
ipu2_sel 32
- ldb_di0_sel 33
- ldb_di1_sel 34
ipu1_di0_pre_sel 35
ipu1_di1_pre_sel 36
ipu2_di0_pre_sel 37
@@ -240,6 +238,7 @@ clocks and IDs.
asrc_mem 227
esai_ipg 228
esai_mem 229
+ axi_alt_sel 230
Examples:
diff --git a/Documentation/usb/chipidea.txt b/Documentation/usb/chipidea.txt
index 995c8bca40e2..b2b93b401710 100644
--- a/Documentation/usb/chipidea.txt
+++ b/Documentation/usb/chipidea.txt
@@ -26,14 +26,13 @@ cat /sys/kernel/debug/ci_hdrc.0/registers
On B-device:
echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
- if HNP polling is not supported, also need:
- On A-device:
- echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
-
B-device should take host role and enumrate A-device.
4) A-device switch back to host.
- On B-device:
+ On A-device:
+ echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
+
+ or, on B-device:
echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
A-device should switch back to host and enumrate B-device.
diff --git a/Makefile b/Makefile
index 56b93edbbe4e..30714282fbc5 100644
--- a/Makefile
+++ b/Makefile
@@ -1023,7 +1023,7 @@ MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \
Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
signing_key.priv signing_key.x509 x509.genkey \
extra_certificates signing_key.x509.keyid \
- signing_key.x509.signer
+ signing_key.x509.signer include/linux/version.h
# clean - Delete most, but leave enough to build external modules
#
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index e2bedf6d8917..511a1544a60d 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -56,9 +56,9 @@
busfreq { /* BUSFREQ */
compatible = "fsl,imx6_busfreq";
clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>,
- <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>, <&clks 22> , <&clks 8>;
+ <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>, <&clks 230>, <&clks 22> , <&clks 8>;
clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph",
- "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "axi_sel", "pll3_pfd1_540m";
+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "axi_alt_sel", "axi_sel", "pll3_pfd1_540m";
interrupts = <0 107 0x04>, <0 112 0x4>;
interrupt-names = "irq_busfreq_0", "irq_busfreq_1";
fsl,max_ddr_freq = <400000000>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 5e2c044a2a16..fd5d0b31e1c4 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -12,7 +12,6 @@
/ {
aliases {
- mmc0 = &usdhc3;
mxcfb0 = &mxcfb1;
mxcfb1 = &mxcfb2;
mxcfb2 = &mxcfb3;
@@ -492,12 +491,13 @@
#gpio-cells = <2>;
};
- mma8x5x@1c {
- compatible = "fsl,mma8x5x";
+ mma8451@1c {
+ compatible = "fsl,mma8451";
reg = <0x1c>;
position = <7>;
interrupt-parent = <&gpio6>;
- interrupts = <31 1>;
+ interrupts = <31 8>;
+ interrupt-route = <1>;
};
mag3110@0e {
@@ -743,17 +743,17 @@
};
};
&caam_sm {
- status = "disable";
+ status = "disabled";
};
&irq_sec_vio {
- status = "disable";
+ status = "disabled";
};
&caam_snvs {
- status = "disable";
+ status = "disabled";
};
&crypto {
- status = "disable";
+ status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 79ce6b266153..1a9ab935c0cf 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -12,8 +12,6 @@
/ {
aliases {
- mmc0 = &usdhc4;
- mmc1 = &usdhc3;
mxcfb0 = &mxcfb1;
mxcfb1 = &mxcfb2;
mxcfb2 = &mxcfb3;
@@ -378,14 +376,15 @@
mclk_source = <0>;
};
- mma8x5x@1c {
- compatible = "fsl,mma8x5x";
+ mma8451@1c {
+ compatible = "fsl,mma8451";
reg = <0x1c>;
position = <0>;
vdd-supply = <&reg_sensor>;
vddio-supply = <&reg_sensor>;
interrupt-parent = <&gpio1>;
- interrupts = <18 1>;
+ interrupts = <18 8>;
+ interrupt-route = <1>;
};
};
@@ -674,17 +673,17 @@
};
&caam_sm {
- status = "disable";
+ status = "disabled";
};
&irq_sec_vio {
- status = "disable";
+ status = "disabled";
};
&caam_snvs {
- status = "disable";
+ status = "disabled";
};
&crypto {
- status = "disable";
+ status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index a0f0b7300a2c..cecc6c298c06 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -23,6 +23,10 @@
gpio5 = &gpio6;
gpio6 = &gpio7;
ipu0 = &ipu1;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ mmc3 = &usdhc4;
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index ea28a4645e60..bf67dae099da 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -14,9 +14,6 @@
/ {
model = "Freescale i.MX6 SoloLite EVK Board(PFUZE100)";
compatible = "fsl,imx6sl-evk", "fsl,imx6sl";
- aliases {
- mmc0 = &usdhc2;
- };
};
&i2c1 {
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index c5f6bae9a5f3..c4068b507773 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -13,6 +13,10 @@
/ {
aliases {
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ mmc3 = &usdhc4;
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
diff --git a/arch/arm/boot/dts/imx6sx-19x19-arm2.dts b/arch/arm/boot/dts/imx6sx-19x19-arm2.dts
index 2d2687ad4d3a..131f330decfe 100644
--- a/arch/arm/boot/dts/imx6sx-19x19-arm2.dts
+++ b/arch/arm/boot/dts/imx6sx-19x19-arm2.dts
@@ -23,6 +23,13 @@
csi1_v4l2_cap {
compatible = "fsl,imx6sx-csi-v4l2", "fsl,imx6sl-csi-v4l2";
+ csi_id = <0>;
+ status = "okay";
+ };
+
+ csi2_v4l2_cap {
+ compatible = "fsl,imx6sx-csi-v4l2", "fsl,imx6sl-csi-v4l2";
+ csi_id = <1>;
status = "okay";
};
@@ -99,6 +106,10 @@
status = "okay";
};
+&csi2 {
+ status = "okay";
+};
+
&fec1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_enet1_1>;
@@ -492,6 +503,6 @@
&vadc {
vadc_in = <0>;
- csi_id = <0>;
+ csi_id = <1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index 9c58768aafa8..bd152a26aa8d 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -15,9 +15,6 @@
model = "Freescale i.MX6 SoloX SDB Board";
compatible = "fsl,imx6sx-sdb", "fsl,imx6sx";
- aliases {
- mmc0 = &usdhc4;
- };
pwm-backlight {
compatible = "pwm-backlight";
@@ -141,8 +138,17 @@
hp-det-gpios = <&gpio1 17 1>;
};
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif",
+ "fsl,imx6sx-sdb-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-out;
+ };
+
csi1_v4l2_cap {
compatible = "fsl,imx6sx-csi-v4l2", "fsl,imx6sl-csi-v4l2";
+ csi_id = <0>;
status = "okay";
};
@@ -384,6 +390,9 @@
compatible = "fsl,mma8451";
reg = <0x1c>;
position = <1>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <2 8>;
+ interrupt-route = <2>;
};
};
@@ -455,6 +464,12 @@
status = "disabled";
};
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif_2>;
+ status = "okay";
+};
+
&ssi2 {
status = "okay";
};
@@ -634,6 +649,6 @@
&vadc {
vadc_in = <0>;
- csi_id = <0>;
+ csi_id = <1>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 2549b361c706..ab915d2e17e6 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -26,6 +26,12 @@
gpio6 = &gpio7;
lcdif0 = &lcdif1;
lcdif1 = &lcdif2;
+ csi0 = &csi1;
+ csi1 = &csi2;
+ mmc0 = &usdhc1;
+ mmc1 = &usdhc2;
+ mmc2 = &usdhc3;
+ mmc3 = &usdhc4;
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
@@ -553,8 +559,12 @@
compatible = "fsl,imx6q-gpc";
reg = <0x020dc000 0x4000>;
interrupts = <0 89 0x04>;
- clocks = <&clks IMX6SX_CLK_GPU>, <&clks IMX6SX_CLK_IPG>;
- clock-names = "gpu3d_core", "ipg";
+ clocks = <&clks IMX6SX_CLK_GPU>, <&clks IMX6SX_CLK_IPG>,
+ <&clks IMX6SX_CLK_PXP_AXI>, <&clks IMX6SX_CLK_DISPLAY_AXI>,
+ <&clks IMX6SX_CLK_LCDIF1_PIX>, <&clks IMX6SX_CLK_LCDIF_APB>,
+ <&clks IMX6SX_CLK_LCDIF2_PIX>, <&clks IMX6SX_CLK_CSI>;
+ clock-names = "gpu3d_core", "ipg", "pxp_axi", "disp_axi", "lcdif1_pix",
+ "lcdif_axi", "lcdif2_pix", "csi_mclk";
pu-supply = <&pu_dummy>;
pcie-supply = <&reg_pcie>;
fsl,mf-mix-wakeup-irq = <0x7c00000 0x3d00 0x0 0x400200>;
@@ -1569,6 +1579,12 @@
MX6SX_PAD_ENET2_COL__SPDIF_IN 0x1b0b0
>;
};
+
+ pinctrl_spdif_2: spdifgrp-2 {
+ fsl,pins = <
+ MX6SX_PAD_SD4_DATA4__SPDIF_OUT 0x1b0b0
+ >;
+ };
};
uart1 {
diff --git a/arch/arm/configs/imx_v7_android_defconfig b/arch/arm/configs/imx_v7_android_defconfig
index cb2fef6bdbe3..2a35f1b5671d 100644
--- a/arch/arm/configs/imx_v7_android_defconfig
+++ b/arch/arm/configs/imx_v7_android_defconfig
@@ -96,7 +96,7 @@ CONFIG_RCU_FANOUT_LEAF=16
# CONFIG_RCU_BOOST is not set
# CONFIG_RCU_NOCB_CPU is not set
CONFIG_IKCONFIG=y
-# CONFIG_IKCONFIG_PROC is not set
+CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
@@ -933,6 +933,7 @@ CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_XPS=y
# CONFIG_NETPRIO_CGROUP is not set
+CONFIG_LLC2=y
CONFIG_BQL=y
# CONFIG_BPF_JIT is not set
@@ -958,10 +959,7 @@ CONFIG_CAN_CALC_BITTIMING=y
# CONFIG_CAN_MCP251X is not set
CONFIG_HAVE_CAN_FLEXCAN=y
CONFIG_CAN_FLEXCAN=y
-# CONFIG_CAN_GRCAN is not set
-# CONFIG_CAN_SJA1000 is not set
-# CONFIG_CAN_C_CAN is not set
-# CONFIG_CAN_CC770 is not set
+CONFIG_CAN_M_CAN=y
#
# CAN USB interfaces
@@ -1682,6 +1680,7 @@ CONFIG_INPUT_ISL29023=y
#
CONFIG_SERIO=y
CONFIG_SERIO_SERPORT=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_SERIO_ALTERA_PS2 is not set
@@ -1740,7 +1739,7 @@ CONFIG_HW_RANDOM=y
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_DCC_TTY is not set
-# CONFIG_MXS_VIIM is not set
+CONFIG_MXS_VIIM=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_COMPAT is not set
@@ -2858,7 +2857,7 @@ CONFIG_USB_SERIAL_OPTION=y
# CONFIG_USB_HSIC_USB3503 is not set
CONFIG_USB_PHY=y
CONFIG_USB_OTG_WAKELOCK=y
-# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_NOP_USB_XCEIV=y
# CONFIG_OMAP_CONTROL_USB is not set
# CONFIG_OMAP_USB3 is not set
# CONFIG_SAMSUNG_USBPHY is not set
@@ -2891,14 +2890,14 @@ CONFIG_USB_FSL_USB2=y
CONFIG_USB_LIBCOMPOSITE=y
CONFIG_USB_F_ACM=y
CONFIG_USB_U_SERIAL=y
-# CONFIG_USB_ZERO is not set
+CONFIG_USB_ZERO=y
# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_G_NCM is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_G_NCM=y
# CONFIG_USB_GADGETFS is not set
# CONFIG_USB_FUNCTIONFS is not set
-# CONFIG_USB_MASS_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
+CONFIG_USB_MASS_STORAGE=y
+CONFIG_USB_G_SERIAL=y
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
CONFIG_USB_G_ANDROID=y
@@ -3608,7 +3607,7 @@ CONFIG_CRYPTO_CTS=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LRW=y
# CONFIG_CRYPTO_PCBC is not set
-# CONFIG_CRYPTO_XTS is not set
+CONFIG_CRYPTO_XTS=y
#
# Hash modes
@@ -3624,19 +3623,19 @@ CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_CRC32C=y
# CONFIG_CRYPTO_CRC32 is not set
CONFIG_CRYPTO_GHASH=y
-# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=y
+CONFIG_CRYPTO_RMD160=y
+CONFIG_CRYPTO_RMD256=y
+CONFIG_CRYPTO_RMD320=y
CONFIG_CRYPTO_SHA1=y
# CONFIG_CRYPTO_SHA1_ARM is not set
CONFIG_CRYPTO_SHA256=y
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
#
# Ciphers
@@ -3645,8 +3644,8 @@ CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_AES_ARM is not set
# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_ARC4=y
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_CAMELLIA=y
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
CONFIG_CRYPTO_DES=y
@@ -3656,7 +3655,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_TWOFISH is not set
+CONFIG_CRYPTO_TWOFISH=y
#
# Compression
diff --git a/arch/arm/mach-imx/busfreq-imx6.c b/arch/arm/mach-imx/busfreq-imx6.c
index e67bdbc21a83..d4529ab490ea 100644
--- a/arch/arm/mach-imx/busfreq-imx6.c
+++ b/arch/arm/mach-imx/busfreq-imx6.c
@@ -108,6 +108,7 @@ static struct clk *periph2_pre_clk;
static struct clk *periph2_clk2_sel;
static struct clk *periph2_clk2;
static struct clk *step_clk;
+static struct clk *axi_alt_sel_clk;
static struct clk *axi_sel_clk;
static struct clk *pll3_pfd1_540m;
@@ -356,8 +357,7 @@ int reduce_bus_freq(void)
else if (cpu_is_imx6sx())
enter_lpm_imx6sx();
else {
- if (cpu_is_imx6dl() && (clk_get_parent(axi_sel_clk)
- != periph_clk))
+ if (cpu_is_imx6dl())
/* Set axi to periph_clk */
clk_set_parent(axi_sel_clk, periph_clk);
@@ -515,10 +515,11 @@ int set_high_bus_freq(int high_bus_freq)
dev_warn(busfreq_dev,
"%s: %d: clk set parent fail!\n",
__func__, __LINE__);
- if (cpu_is_imx6dl() && (clk_get_parent(axi_sel_clk)
- != pll3_pfd1_540m))
+ if (cpu_is_imx6dl()) {
/* Set axi to pll3_pfd1_540m */
- clk_set_parent(axi_sel_clk, pll3_pfd1_540m);
+ clk_set_parent(axi_alt_sel_clk, pll3_pfd1_540m);
+ clk_set_parent(axi_sel_clk, axi_alt_sel_clk);
+ }
clk_disable_unprepare(pll2_400);
} else {
update_ddr_freq_imx6q(ddr_med_rate);
@@ -921,6 +922,13 @@ static int busfreq_probe(struct platform_device *pdev)
}
if (cpu_is_imx6dl()) {
+ axi_alt_sel_clk = devm_clk_get(&pdev->dev, "axi_alt_sel");
+ if (IS_ERR(axi_alt_sel_clk)) {
+ dev_err(busfreq_dev, "%s: failed to get axi_alt_sel_clk\n",
+ __func__);
+ return PTR_ERR(axi_alt_sel_clk);
+ }
+
axi_sel_clk = devm_clk_get(&pdev->dev, "axi_sel");
if (IS_ERR(axi_sel_clk)) {
dev_err(busfreq_dev, "%s: failed to get axi_sel_clk\n",
diff --git a/arch/arm/mach-imx/busfreq_ddr3.c b/arch/arm/mach-imx/busfreq_ddr3.c
index 6854f78d3f47..f959c3c1ae08 100644
--- a/arch/arm/mach-imx/busfreq_ddr3.c
+++ b/arch/arm/mach-imx/busfreq_ddr3.c
@@ -105,7 +105,8 @@ unsigned long ddr3_dll_mx6sx[][2] = {
{0x10, 0x0},
{0x30, 0x0},
{0x1C, 0x04008032},
- {0x1C, 0x00068031},
+ {0x1C, 0x00008033},
+ {0x1C, 0x00048031},
{0x1C, 0x05208030},
{0x1C, 0x04008040},
{0x818, 0x0},
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 78e616286e1e..4497e29fb602 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -33,17 +33,18 @@ static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy",
static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", };
static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
-static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = { "periph", "axi_alt_sel", };
static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
static const char *gpu_axi_sels[] = { "axi", "ahb", };
static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
-static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
-static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll3_pfd0_720m", };
-static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
+static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi_podf", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
+static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi_podf", "pll3_usb_otg", "pll2_pfd1_594m", "pll3_pfd0_720m", };
+static const char *ipu_sels[] = { "mmdc_ch0_axi_podf", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
static const char *ldb_di_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
-static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi_podf", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
@@ -61,7 +62,7 @@ static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5
"dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
"ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio_div", };
static const char *cko2_sels[] = {
- "mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
+ "mmdc_ch0_axi_podf", "mmdc_ch1_axi", "usdhc4", "usdhc1",
"gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi",
"usdhc3", "dummy", "arm", "ipu1",
"ipu2", "vdo_axi", "osc", "gpu2d_core",
@@ -116,7 +117,8 @@ enum mx6q_clks {
ldb_di0_div_7, ldb_di1_div_7, ldb_di0_div_sel, ldb_di1_div_sel,
pll4_audio_div, lvds1_sel, lvds1_in, lvds1_out, caam_mem, caam_aclk,
caam_ipg, epit1, epit2, tzasc2, pll4_sel, lvds2_sel, lvds2_in, lvds2_out,
- anaclk1, anaclk2, spdif1, asrc_ipg, asrc_mem, esai_ipg, esai_mem, clk_max
+ anaclk1, anaclk2, spdif1, asrc_ipg, asrc_mem, esai_ipg, esai_mem,
+ axi_alt_sel, clk_max
};
static struct clk *clk[clk_max];
@@ -148,7 +150,36 @@ static struct clk_div_table video_div_table[] = {
{ }
};
-static void init_ldb_clks(enum mx6q_clks new_parent)
+/*
+ * Kernel parameter 'ldb_di_clk_sel' is used to select parent of ldb_di_clk,
+ * among the following clocks.
+ * 'pll5_video_div'
+ * 'pll2_pfd0_352m'
+ * 'pll2_pfd2_396m'
+ * 'mmdc_ch1_axi'
+ * 'pll3_usb_otg'
+ * Example format: ldb_di_clk_sel=pll5_video_div
+ * If the kernel parameter is absent or invalid, pll2_pfd0_352m will be
+ * selected by default.
+ */
+static int ldb_di_sel = 1;
+
+static int __init get_ldb_di_parent(char *p)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ldb_di_sels); i++) {
+ if (strcmp(p, ldb_di_sels[i]) == 0) {
+ ldb_di_sel = i;
+ break;
+ }
+ }
+
+ return 0;
+}
+early_param("ldb_di_clk_sel", get_ldb_di_parent);
+
+static void init_ldb_clks(void)
{
u32 reg;
@@ -222,8 +253,10 @@ static void init_ldb_clks(enum mx6q_clks new_parent)
/*
* Perform the LDB parent clock switch.
*/
- clk_set_parent(clk[ldb_di0_sel], clk[new_parent]);
- clk_set_parent(clk[ldb_di1_sel], clk[new_parent]);
+ reg = readl_relaxed(ccm_base + 0x2c);
+ reg &= ~((7 << 9) | (7 << 12));
+ reg |= ((ldb_di_sel << 9) | (ldb_di_sel << 12));
+ writel_relaxed(reg, ccm_base + 0x2c);
/*
* Unbypass pll3_sw_clk.
@@ -346,10 +379,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[gpt_3m] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
clk[video_27m] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20);
- clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
- clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+ clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+ clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
np = ccm_node;
ccm_base = base = of_iomap(np, 0);
@@ -363,7 +396,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[periph2_pre] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
clk[periph_clk2_sel] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
clk[periph2_clk2_sel] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
- clk[axi_sel] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels));
+ clk[axi_alt_sel] = imx_clk_mux("axi_alt_sel", base + 0x14, 7, 1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+ clk[axi_sel] = imx_clk_mux("axi_sel", base + 0x14, 6, 1, axi_sels, ARRAY_SIZE(axi_sels));
clk[esai_sel] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[spdif1_sel] = imx_clk_mux("spdif1_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[spdif_sel] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
@@ -374,8 +408,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
clk[ipu1_sel] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
clk[ldb_di0_div_sel] = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT);
clk[ldb_di1_div_sel] = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT);
clk[ipu1_di0_pre_sel] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
@@ -426,10 +458,10 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[gpu3d_shader] = imx_clk_divider("gpu3d_shader", "gpu3d_shader_sel", base + 0x18, 29, 3);
clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3);
clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3);
- clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
- clk[ldb_di0_div_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7);
- clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
- clk[ldb_di1_div_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7);
+ clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", ldb_di_sels[ldb_di_sel], 2, 7);
+ clk[ldb_di0_div_7] = imx_clk_fixed_factor("ldb_di0_div_7", ldb_di_sels[ldb_di_sel], 1, 7);
+ clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", ldb_di_sels[ldb_di_sel], 2, 7);
+ clk[ldb_di1_div_7] = imx_clk_fixed_factor("ldb_di1_div_7", ldb_di_sels[ldb_di_sel], 1, 7);
clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3);
clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3);
clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3);
@@ -525,8 +557,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[mlb] = imx_clk_gate2("mlb", "gpu2d_core_podf", base + 0x74, 18);
else
clk[mlb] = imx_clk_gate2("mlb", "axi", base + 0x74, 18);
- clk[mmdc_ch0_axi] = imx_clk_gate2("mmdc_ch0_axi", "mmdc_ch0_axi_podf", base + 0x74, 20);
- clk[mmdc_ch1_axi] = imx_clk_gate2("mmdc_ch1_axi", "mmdc_ch1_axi_podf", base + 0x74, 22);
clk[ocram] = imx_clk_gate2("ocram", "ahb", base + 0x74, 28);
clk[openvg_axi] = imx_clk_gate2("openvg_axi", "axi", base + 0x74, 30);
clk[pcie_axi] = imx_clk_gate2("pcie_axi", "pcie_axi_sel", base + 0x78, 0);
@@ -563,6 +593,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[cko1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7);
clk[cko2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24);
+ /*
+ * These two clocks (mmdc_ch0_axi and mmdc_ch1_axi) were incorrectly
+ * implemented as gate at the beginning. To fix them with the minimized
+ * impact, let's point them to their dividers.
+ */
+ clk[mmdc_ch0_axi] = clk[mmdc_ch0_axi_podf];
+ clk[mmdc_ch1_axi] = clk[mmdc_ch1_axi_podf];
+
for (i = 0; i < ARRAY_SIZE(clk); i++)
if (IS_ERR(clk[i]))
pr_err("i.MX6q clk %d: register failed with %ld\n",
@@ -657,7 +695,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
}
/* ipu clock initialization */
- init_ldb_clks(pll2_pfd0_352m);
+ init_ldb_clks();
clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
@@ -669,7 +707,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
if (cpu_is_imx6dl()) {
clk_set_rate(clk[pll3_pfd1_540m], 540000000);
clk_set_parent(clk[ipu1_sel], clk[pll3_pfd1_540m]);
- clk_set_parent(clk[axi_sel], clk[pll3_pfd1_540m]);
+ clk_set_parent(clk[axi_alt_sel], clk[pll3_pfd1_540m]);
+ clk_set_parent(clk[axi_sel], clk[axi_alt_sel]);
/* set epdc/pxp axi clock to 200Mhz */
clk_set_parent(clk[ipu2_sel], clk[pll2_pfd2_396m]);
clk_set_rate(clk[ipu2], 200000000);
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index c9eb48a09159..c99b51148035 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -42,7 +42,7 @@ static bool uart_from_osc;
static const char const *step_sels[] = { "osc", "pll2_pfd2", };
static const char const *pll1_sw_sels[] = { "pll1_sys", "step", };
static const char const *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", };
-static const char const *ocram_sels[] = { "periph", "ocram_alt_sels", };
+static const char const *ocram_sels[] = { "periph", "ocram_alt_sel", };
static const char const *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", };
static const char const *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", };
static const char const *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", };
@@ -202,10 +202,10 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
/* dev name parent_name flags reg shift width div: flags, div_table lock */
- clks[IMX6SL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clks[IMX6SL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
- clks[IMX6SL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
- clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+ clks[IMX6SL_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clks[IMX6SL_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+ clks[IMX6SL_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clks[IMX6SL_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
clks[IMX6SL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0, base + 0xe0, 0, 2, 0, clk_enet_ref_table, &imx_ccm_lock);
/* name parent_name reg idx */
diff --git a/arch/arm/mach-imx/clk-imx6sx.c b/arch/arm/mach-imx/clk-imx6sx.c
index 0844e5ce2f32..5987850f0550 100644
--- a/arch/arm/mach-imx/clk-imx6sx.c
+++ b/arch/arm/mach-imx/clk-imx6sx.c
@@ -36,7 +36,8 @@ static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", };
static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
-static const char *ocram_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
+static const char *ocram_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *ocram_sels[] = { "periph", "ocram_alt_sel", };
static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
static const char *gpu_axi_sels[] = { "pll2_pfd2_396m", "pll3_pfd0_720m", "pll3_pfd1_540m", "pll2_bus", };
static const char *gpu_core_sels[] = { "pll3_pfd1_540m", "pll3_pfd0_720m", "pll2_bus", "pll2_pfd2_396m", };
@@ -205,13 +206,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
clks[IMX6SX_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio",
- CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
clks[IMX6SX_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div",
- CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 15, 1, 0, &imx_ccm_lock);
clks[IMX6SX_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video",
- CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
clks[IMX6SX_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div",
- CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
/* name reg shift width parent_names num_parents */
clks[IMX6SX_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
@@ -224,7 +225,8 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
/* name reg shift width parent_names num_parents */
clks[IMX6SX_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
clks[IMX6SX_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
- clks[IMX6SX_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 2, ocram_sels, ARRAY_SIZE(ocram_sels));
+ clks[IMX6SX_CLK_OCRAM_ALT_SEL] = imx_clk_mux("ocram_alt_sel", base + 0x14, 7, 1, ocram_alt_sels, ARRAY_SIZE(ocram_alt_sels));
+ clks[IMX6SX_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 1, ocram_sels, ARRAY_SIZE(ocram_sels));
clks[IMX6SX_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
clks[IMX6SX_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
clks[IMX6SX_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
@@ -240,13 +242,13 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
clks[IMX6SX_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
clks[IMX6SX_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels));
- clks[IMX6SX_CLK_QSPI1_SEL] = imx_clk_mux_flags_reparent("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SX_CLK_QSPI1_SEL] = imx_clk_mux_flags("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
clks[IMX6SX_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
clks[IMX6SX_CLK_VID_SEL] = imx_clk_mux("vid_sel", base + 0x20, 21, 3, vid_sels, ARRAY_SIZE(vid_sels));
clks[IMX6SX_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SX_CLK_CAN_SEL] = imx_clk_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels));
clks[IMX6SX_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
- clks[IMX6SX_CLK_QSPI2_SEL] = imx_clk_mux_flags_reparent("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
+ clks[IMX6SX_CLK_QSPI2_SEL] = imx_clk_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
clks[IMX6SX_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SX_CLK_AUDIO_SEL] = imx_clk_mux("audio_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
clks[IMX6SX_CLK_ENET_PRE_SEL] = imx_clk_mux("enet_pre_sel", base + 0x34, 15, 3, enet_pre_sels, ARRAY_SIZE(enet_pre_sels));
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
index b73756eec5b7..bd257ae0bc2b 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -439,7 +439,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
init.name = name;
init.ops = ops;
- init.flags = 0;
+ init.flags = CLK_SET_RATE_GATE;
init.parent_names = &parent_name;
init.num_parents = 1;
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 319a9660e4c2..0f9076909517 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -110,16 +110,6 @@ static inline struct clk *imx_clk_mux_flags(const char *name,
int num_parents, unsigned long flags)
{
return clk_register_mux(NULL, name, parents, num_parents,
- flags | CLK_SET_RATE_NO_REPARENT, reg, shift, width, 0,
- &imx_ccm_lock);
-}
-
-/* we can use this helper to register the clock which needs the re-parent. */
-static inline struct clk *imx_clk_mux_flags_reparent(const char *name,
- void __iomem *reg, u8 shift, u8 width, const char **parents,
- int num_parents, unsigned long flags)
-{
- return clk_register_mux(NULL, name, parents, num_parents,
flags, reg, shift, width, 0,
&imx_ccm_lock);
}
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6.S b/arch/arm/mach-imx/ddr3_freq_imx6.S
index 25406d45ccb8..8137f513c787 100644
--- a/arch/arm/mach-imx/ddr3_freq_imx6.S
+++ b/arch/arm/mach-imx/ddr3_freq_imx6.S
@@ -623,11 +623,6 @@ update_iomux:
orr r0, r0, #(0x1 << 29)
str r0, [r5, r2]
- /* MMDC0_MAPSR adopt power down enable. */
- ldr r0, [r5, #MMDC0_MAPSR]
- bic r0, r0, #0x01
- str r0, [r5, #MMDC0_MAPSR]
-
/* frc_msr + mu bypass */
ldr r0, =0x00000060
str r0, [r5, #MMDC0_MPMUR0]
@@ -867,11 +862,6 @@ cont15:
cmp r1, #0
bgt delay15
- /* MMDC0_MAPSR adopt power down enable. */
- ldr r0, [r5, #MMDC0_MAPSR]
- bic r0, r0, #0x01
- str r0, [r5, #MMDC0_MAPSR]
-
/* enable MMDC power down timer. */
ldr r0, [r5, #MMDC0_MDPDC]
orr r0, r0, #(0x55 << 8)
@@ -920,6 +910,11 @@ poll_conreq_clear_2:
done:
+ /* MMDC0_MAPSR adopt power down enable. */
+ ldr r0, [r5, #MMDC0_MAPSR]
+ bic r0, r0, #0x01
+ str r0, [r5, #MMDC0_MAPSR]
+
#ifdef CONFIG_CACHE_L2X0
/* Enable L2. */
ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6sx.S b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
index c63bf570100d..d0f692c39e64 100644
--- a/arch/arm/mach-imx/ddr3_freq_imx6sx.S
+++ b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
@@ -59,7 +59,8 @@
add r9, r9, #4
cmp r9, #16
bne 2b
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt 1b
.endm
@@ -78,33 +79,7 @@
/* check whether periph2_clk is already from top path */
ldr r8, [r5, #CCM_CBCDR]
ands r8, #(1 << 26)
- bne skip_periph2_clk2_switch_400m
-
- /* change periph2_clk2 to be sourced from pll3_clk. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(1 << 20)
- str r8, [r5, #CCM_CBCMR]
-
- /* make sure periph2_clk2 freq not exceed 400MHz */
- ldr r8, [r5, #CCM_CBCDR]
- bic r8, r8, #0x7
- orr r8, r8, #0x1
- str r8, [r5, #CCM_CBCDR]
-
- /* now switch periph2_clk to pll3_main_clk. */
- ldr r8, [r5, #CCM_CBCDR]
- orr r8, r8, #(1 << 26)
- str r8, [r5, #CCM_CBCDR]
-
- wait_for_ccm_handshake
-
-skip_periph2_clk2_switch_400m:
-
- /* now switch pre_periph2_clk to PFD_400MHz. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(0x3 << 21)
- orr r8, r8, #(0x1 << 21)
- str r8, [r5, #CCM_CBCMR]
+ beq skip_periph2_clk2_switch_400m
/* now switch periph2_clk back. */
ldr r8, [r5, #CCM_CBCDR]
@@ -113,6 +88,13 @@ skip_periph2_clk2_switch_400m:
wait_for_ccm_handshake
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_400m:
+
/* fabric_mmdc_podf to 0 */
ldr r8, [r5, #CCM_CBCDR]
bic r8, r8, #(0x7 << 3)
@@ -127,32 +109,7 @@ skip_periph2_clk2_switch_400m:
/* check whether periph2_clk is already from top path */
ldr r8, [r5, #CCM_CBCDR]
ands r8, #(1 << 26)
- bne skip_periph2_clk2_switch_50m
-
- /* change periph2_clk2 to be sourced from pll3_clk. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(1 << 20)
- str r8, [r5, #CCM_CBCMR]
-
- ldr r8, [r5, #CCM_CBCDR]
- bic r8, r8, #0x7
- orr r8, r8, #0x1
- str r8, [r5, #CCM_CBCDR]
-
- /* now switch periph2_clk to pll3_main_clk. */
- ldr r8, [r5, #CCM_CBCDR]
- orr r8, r8, #(1 << 26)
- str r8, [r5, #CCM_CBCDR]
-
- wait_for_ccm_handshake
-
-skip_periph2_clk2_switch_50m:
-
- /* now switch pre_periph2_clk to PFD_400MHz. */
- ldr r8, [r5, #CCM_CBCMR]
- bic r8, r8, #(0x3 << 21)
- orr r8, r8, #(0x1 << 21)
- str r8, [r5, #CCM_CBCMR]
+ beq skip_periph2_clk2_switch_50m
/* now switch periph2_clk back. */
ldr r8, [r5, #CCM_CBCDR]
@@ -161,6 +118,13 @@ skip_periph2_clk2_switch_50m:
wait_for_ccm_handshake
+ /*
+ * on i.MX6SX, pre_periph2_clk will be always from
+ * pll2_pfd2, so no need to set pre_periph2_clk
+ * parent, just set the mmdc divider directly.
+ */
+skip_periph2_clk2_switch_50m:
+
/* fabric_mmdc_podf to 7 so that mmdc is 400 / 8 = 50MHz */
ldr r8, [r5, #CCM_CBCDR]
orr r8, r8, #(0x7 << 3)
@@ -227,22 +191,24 @@ imx6sx_ddr3_freq_change_start:
* and 2-4G is translated by TTBR1.
*/
+ ldr r6, =iram_tlb_phys_addr
+ ldr r7, [r6]
+
/* Disable Branch Prediction, Z bit in SCTLR. */
- mrc p15, 0, r7, c1, c0, 0
- bic r7, r7, #0x800
- mcr p15, 0, r7, c1, c0, 0
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x800
+ mcr p15, 0, r6, c1, c0, 0
/* Flush the Branch Target Address Cache (BTAC) */
ldr r6, =0x0
mcr p15, 0, r6, c7, c1, 6
- ldr r6, =iram_tlb_phys_addr
- ldr r6, [r6]
dsb
isb
/* Store the IRAM table in TTBR1 */
- mcr p15, 0, r6, c2, c0, 1
+ mcr p15, 0, r7, c2, c0, 1
+
/* Read TTBCR and set PD0=1, N = 1 */
mrc p15, 0, r6, c2, c0, 2
orr r6, r6, #0x11
@@ -259,9 +225,9 @@ imx6sx_ddr3_freq_change_start:
isb
/* Disable L1 data cache. */
- mrc p15, 0, r7, c1, c0, 0
- bic r7, r7, #0x4
- mcr p15, 0, r7, c1, c0, 0
+ mrc p15, 0, r6, c1, c0, 0
+ bic r6, r6, #0x4
+ mcr p15, 0, r6, c1, c0, 0
ldr r4, =IMX_IO_P2V(MX6Q_MMDC_P0_BASE_ADDR)
ldr r5, =IMX_IO_P2V(MX6Q_CCM_BASE_ADDR)
@@ -309,20 +275,6 @@ wait_for_l2_to_idle:
ldr r8, =4
do_delay
- /* set CON_REG */
- ldr r8, =0x8000
- str r8, [r4, #MMDC0_MDSCR]
-poll_conreq_set_1:
- ldr r8, [r4, #MMDC0_MDSCR]
- and r8, r8, #(0x4 << 12)
- cmp r8, #(0x4 << 12)
- bne poll_conreq_set_1
-
- ldr r8, =0x00008010
- str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x00008018
- str r8, [r4, #MMDC0_MDSCR]
-
/*
* if requested frequency is greater than
* 300MHz go to DLL on mode.
@@ -400,10 +352,10 @@ poll_dvfs_clear_1:
ldr r8, =0x00018039
str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x08208030
+ ldr r8, =0x04208030
str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x08208038
+ ldr r8, =0x04208038
str r8, [r4, #MMDC0_MDSCR]
ldr r8, =0x00088032
@@ -441,7 +393,8 @@ update_iomux:
orr r11, r11, #0x28
str r11, [r6, r10]
add r3, r3, #8
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt update_iomux
/* ODT disabled. */
@@ -453,16 +406,11 @@ update_iomux:
orr r8, r8, #(1 << 29)
str r8, [r4, #MMDC0_MPDGCTRL0]
- /* MMDC0_MAPSR adopt power down enable. */
- ldr r8, [r4, #MMDC0_MAPSR]
- bic r8, r8, #0x1
- str r8, [r4, #MMDC0_MAPSR]
-
/* frc_msr + mu bypass */
- ldr r8, =0x00000060
+ ldr r8, =0x00000160
str r8, [r4, #MMDC0_MPMUR0]
- ldr r8, =0x00000460
+ ldr r8, =0x00000560
str r8, [r4, #MMDC0_MPMUR0]
ldr r8, =0x00000c60
@@ -490,10 +438,6 @@ dll_on_mode:
orr r8, r8, #(1 << 21)
str r8, [r4, #MMDC0_MAPSR]
- /* de-assert CON_REQ. */
- mov r8, #0x0
- str r8, [r4, #MMDC0_MDSCR]
-
/* poll DVFS ack. */
poll_dvfs_set_2:
ldr r8, [r4, #MMDC0_MAPSR]
@@ -546,7 +490,8 @@ update_iomux1:
ldr r11, [r3, #0x4]
str r11, [r6, r10]
add r3, r3, #8
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt update_iomux1
/* config MMDC timings to 400MHz. */
@@ -579,10 +524,10 @@ update_iomux1:
do_delay
/* reset dll. */
- ldr r8, =0x09208030
+ ldr r8, =0x05208030
str r8, [r4, #MMDC0_MDSCR]
- ldr r8, =0x09208038
+ ldr r8, =0x05208038
str r8, [r4, #MMDC0_MDSCR]
/* delay for while. */
@@ -632,11 +577,6 @@ update_iomux1:
ldr r8, =40
do_delay
- /* MMDC0_MAPSR adopt power down enable. */
- ldr r8, [r4, #MMDC0_MAPSR]
- bic r8, r8, #0x01
- str r8, [r4, #MMDC0_MAPSR]
-
/* enable MMDC power down timer. */
ldr r8, [r4, #MMDC0_MDPDC]
orr r8, r8, #(0x55 << 8)
@@ -660,7 +600,8 @@ update_calib:
ldr r11, [r1, #0x4]
str r11, [r4, r10]
add r1, r1, #8
- subs r8, r8, #1
+ sub r8, r8, #1
+ cmp r8, #0
bgt update_calib
/* perform a force measurement. */
@@ -681,10 +622,11 @@ poll_conreq_clear_2:
beq poll_conreq_clear_2
done:
- /* Enable L1 data cache. */
- mrc p15, 0, r7, c1, c0, 0
- orr r7, r7, #0x4
- mcr p15, 0, r7, c1, c0, 0
+
+ /* MMDC0_MAPSR adopt power down enable. */
+ ldr r8, [r4, #MMDC0_MAPSR]
+ bic r8, r8, #0x01
+ str r8, [r4, #MMDC0_MAPSR]
#ifdef CONFIG_CACHE_L2X0
/* Enable L2. */
@@ -693,6 +635,11 @@ done:
str r7, [r8, #0x100]
#endif
+ /* Enable L1 data cache. */
+ mrc p15, 0, r7, c1, c0, 0
+ orr r7, r7, #0x4
+ mcr p15, 0, r7, c1, c0, 0
+
/* Restore the TTBCR */
dsb
isb
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 07fac4b13bdd..9a0d6b4e87ce 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -63,6 +63,7 @@ static u32 gpc_saved_imrs[IMR_NUM];
static struct clk *gpu3d_clk, *gpu3d_shader_clk, *gpu2d_clk, *gpu2d_axi_clk;
static struct clk *lcd_axi_clk, *lcd_pix_clk, *epdc_axi_clk, *epdc_pix_clk;
static struct clk *pxp_axi_clk;
+static struct clk *disp_axi_clk, *lcdif_axi_clk, *lcdif1_pix_clk, *lcdif2_pix_clk, *csi_mclk;
static struct clk *openvg_axi_clk, *vpu_clk, *ipg_clk;
static struct device *gpc_dev;
static struct regulator *pu_reg;
@@ -80,25 +81,43 @@ static int pu_dummy_enable;
static void imx_disp_clk(bool enable)
{
- if (enable) {
- clk_prepare_enable(lcd_axi_clk);
- clk_prepare_enable(lcd_pix_clk);
- clk_prepare_enable(epdc_axi_clk);
- clk_prepare_enable(epdc_pix_clk);
- clk_prepare_enable(pxp_axi_clk);
- } else {
- clk_disable_unprepare(lcd_axi_clk);
- clk_disable_unprepare(lcd_pix_clk);
- clk_disable_unprepare(epdc_axi_clk);
- clk_disable_unprepare(epdc_pix_clk);
- clk_disable_unprepare(pxp_axi_clk);
+ if (cpu_is_imx6sl()) {
+ if (enable) {
+ clk_prepare_enable(lcd_axi_clk);
+ clk_prepare_enable(lcd_pix_clk);
+ clk_prepare_enable(epdc_axi_clk);
+ clk_prepare_enable(epdc_pix_clk);
+ clk_prepare_enable(pxp_axi_clk);
+ } else {
+ clk_disable_unprepare(lcd_axi_clk);
+ clk_disable_unprepare(lcd_pix_clk);
+ clk_disable_unprepare(epdc_axi_clk);
+ clk_disable_unprepare(epdc_pix_clk);
+ clk_disable_unprepare(pxp_axi_clk);
+ }
+ } else if (cpu_is_imx6sx()) {
+ if (enable) {
+ clk_prepare_enable(lcdif_axi_clk);
+ clk_prepare_enable(lcdif1_pix_clk);
+ clk_prepare_enable(lcdif2_pix_clk);
+ clk_prepare_enable(pxp_axi_clk);
+ clk_prepare_enable(csi_mclk);
+ clk_prepare_enable(disp_axi_clk);
+ } else {
+ clk_disable_unprepare(lcdif_axi_clk);
+ clk_disable_unprepare(lcdif1_pix_clk);
+ clk_disable_unprepare(lcdif2_pix_clk);
+ clk_disable_unprepare(pxp_axi_clk);
+ clk_disable_unprepare(csi_mclk);
+ clk_disable_unprepare(disp_axi_clk);
+ }
}
}
static void imx_gpc_dispmix_on(void)
{
- if (cpu_is_imx6sl() &&
- imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) {
+ if ((cpu_is_imx6sl() &&
+ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) {
imx_disp_clk(true);
writel_relaxed(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
@@ -113,8 +132,8 @@ static void imx_gpc_dispmix_on(void)
static void imx_gpc_dispmix_off(void)
{
- if (cpu_is_imx6sl() &&
- imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) {
+ if ((cpu_is_imx6sl() &&
+ imx_get_soc_revision() >= IMX_CHIP_REVISION_1_2) || cpu_is_imx6sx()) {
imx_disp_clk(true);
writel_relaxed(0xFFFFFFFF,
@@ -138,9 +157,17 @@ static void imx_gpc_mf_mix_off(void)
if ((gpc_wake_irqs[i] & gpc_mf_irqs[i]) != 0)
return;
- pr_info("Turn off M/F mix!\n");
- /* turn off mega/fast mix */
- writel_relaxed(0x1, gpc_base + GPC_PGC_MF_PDN);
+ /*
+ * As some drivers are not ready for this
+ * Mega/Fast mix off feature, so just skip the
+ * setting of turning off M/F mix, if anyone
+ * want to enable this feature, just add below
+ * two lines back.
+ *
+ * pr_info("Turn off M/F mix!\n");
+ * writel_relaxed(0x1, gpc_base + GPC_PGC_MF_PDN);
+ *
+ */
}
void imx_gpc_pre_suspend(bool arm_power_off)
@@ -585,7 +612,14 @@ static int imx_gpc_probe(struct platform_device *pdev)
} else if (cpu_is_imx6sx()) {
gpu3d_clk = devm_clk_get(gpc_dev, "gpu3d_core");
ipg_clk = devm_clk_get(gpc_dev, "ipg");
- if (IS_ERR(gpu3d_clk) || IS_ERR(ipg_clk)) {
+ pxp_axi_clk = devm_clk_get(gpc_dev, "pxp_axi");
+ disp_axi_clk = devm_clk_get(gpc_dev, "disp_axi");
+ lcdif1_pix_clk = devm_clk_get(gpc_dev, "lcdif1_pix");
+ lcdif_axi_clk = devm_clk_get(gpc_dev, "lcdif_axi");
+ lcdif2_pix_clk = devm_clk_get(gpc_dev, "lcdif2_pix");
+ csi_mclk = devm_clk_get(gpc_dev, "csi_mclk");
+ if (IS_ERR(gpu3d_clk) || IS_ERR(ipg_clk) || IS_ERR(pxp_axi_clk) || IS_ERR(disp_axi_clk) ||
+ IS_ERR(lcdif1_pix_clk) || IS_ERR(lcdif_axi_clk) || IS_ERR(lcdif2_pix_clk) || IS_ERR(csi_mclk)) {
dev_err(gpc_dev, "failed to get clk!\n");
return -ENOENT;
}
diff --git a/drivers/char/imx_mcc/Kconfig b/drivers/char/imx_mcc/Kconfig
index d60cf66cd8fd..9625efa2df7f 100644
--- a/drivers/char/imx_mcc/Kconfig
+++ b/drivers/char/imx_mcc/Kconfig
@@ -13,3 +13,11 @@ config IMX_MCC_DEMO
depends on SOC_IMX6SX && IMX_SEMA4
help
Support for IMX MCC DEMO, most people should say N here.
+
+config IMX_MCC_TTY
+ bool "imx pty for mcc interface"
+ depends on SOC_IMX6SX && IMX_SEMA4
+ help
+ This enables a pty node for imx6sx mcc interface.
+
+#end imx mcc
diff --git a/drivers/char/imx_mcc/Makefile b/drivers/char/imx_mcc/Makefile
index a0d60f341d07..f5bda928e23c 100644
--- a/drivers/char/imx_mcc/Makefile
+++ b/drivers/char/imx_mcc/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_IMX_SEMA4) += imx_sema4.o
obj-$(CONFIG_IMX_MCC_DEMO) += imx_mcc_demo.o
+obj-$(CONFIG_IMX_MCC_TTY) += imx_mcc_tty.o
diff --git a/drivers/char/imx_mcc/imx_mcc_tty.c b/drivers/char/imx_mcc/imx_mcc_tty.c
new file mode 100644
index 000000000000..843b5fcbd010
--- /dev/null
+++ b/drivers/char/imx_mcc/imx_mcc_tty.c
@@ -0,0 +1,253 @@
+/*
+ * imx_mcc_tty.c - pty demo driver used to test imx mcc
+ * posix pty interface.
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ */
+
+/*
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/mcc_common.h>
+#include <linux/mcc_api.h>
+
+/**
+ * struct mcctty_port - Wrapper struct for imx mcc pty port.
+ * @port: TTY port data
+ * @rx_lock: Lock for rx_buf.
+ * @rx_buf: Read buffer
+ */
+struct mcctty_port {
+ struct delayed_work read;
+ struct tty_port port;
+ spinlock_t rx_lock;
+ char *rx_buf;
+};
+
+static struct mcctty_port mcc_tty_port;
+
+enum {
+ MCC_NODE_A9 = 0,
+ MCC_NODE_M4 = 0,
+
+ MCC_A9_PORT = 1,
+ MCC_M4_PORT = 2,
+};
+
+/* mcc tty/pingpong demo */
+static MCC_ENDPOINT mcc_endpoint_a9_pingpong = {0, MCC_NODE_A9, MCC_A9_PORT};
+static MCC_ENDPOINT mcc_endpoint_m4_pingpong = {1, MCC_NODE_M4, MCC_M4_PORT};
+struct mcc_pp_msg {
+ unsigned int data;
+};
+
+static void mcctty_delay_work(struct work_struct *work)
+{
+ struct mcctty_port *cport = &mcc_tty_port;
+ int ret, space;
+ unsigned char *cbuf;
+ struct mcc_pp_msg pp_msg;
+ MCC_MEM_SIZE num_of_received_bytes;
+ MCC_INFO_STRUCT mcc_info;
+
+ /* start mcc tty recv here */
+ ret = mcc_initialize(MCC_NODE_A9);
+ if (ret)
+ pr_err("failed to initialize mcc.\n");
+
+ ret = mcc_get_info(MCC_NODE_A9, &mcc_info);
+ if (ret)
+ pr_err("failed to get mcc info.\n");
+ pr_info("\nA9 mcc prepares run, MCC version is %s\n",
+ mcc_info.version_string);
+
+ pr_info("imx mcc tty/pingpong demo begin.\n");
+ ret = mcc_create_endpoint(&mcc_endpoint_a9_pingpong,
+ MCC_A9_PORT);
+ if (ret)
+ pr_err("failed to create a9 mcc ep.\n");
+
+ while (1) {
+ ret = mcc_recv_copy(&mcc_endpoint_a9_pingpong, &pp_msg,
+ sizeof(struct mcc_pp_msg),
+ &num_of_received_bytes, 0xffffffff);
+
+ if (MCC_SUCCESS != ret) {
+ pr_err("A9 Main task receive error: %d\n", ret);
+ } else {
+ /* flush the recv-ed data to tty node */
+ spin_lock_bh(&cport->rx_lock);
+ space = tty_prepare_flip_string(&cport->port, &cbuf,
+ num_of_received_bytes);
+ if ((space <= 0) || (cport->rx_buf == NULL))
+ goto pp_unlock;
+
+ memcpy(cport->rx_buf, &pp_msg.data,
+ num_of_received_bytes);
+ memcpy(cbuf, cport->rx_buf, space);
+ tty_flip_buffer_push(&cport->port);
+pp_unlock:
+ spin_unlock_bh(&cport->rx_lock);
+ }
+ }
+}
+
+static struct tty_port_operations mcctty_port_ops = { };
+
+static int mcctty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+ return tty_port_install(&mcc_tty_port.port, driver, tty);
+}
+
+static int mcctty_open(struct tty_struct *tty, struct file *filp)
+{
+ return tty_port_open(tty->port, tty, filp);
+}
+
+static void mcctty_close(struct tty_struct *tty, struct file *filp)
+{
+ return tty_port_close(tty->port, tty, filp);
+}
+
+static int mcctty_write(struct tty_struct *tty, const unsigned char *buf,
+ int total)
+{
+ int i, ret = 0;
+ struct mcc_pp_msg pp_msg;
+
+ if (NULL == buf)
+ return 0;
+
+ for (i = 0; i < total; i++) {
+ pp_msg.data = (unsigned int)buf[i];
+
+ /*
+ * wait until the remote endpoint is created by
+ * the other core
+ */
+ ret = mcc_send(&mcc_endpoint_m4_pingpong, &pp_msg,
+ sizeof(struct mcc_pp_msg),
+ 0xffffffff);
+
+ while (MCC_ERR_ENDPOINT == ret) {
+ pr_err("\n send err ret %d, re-send\n", ret);
+ ret = mcc_send(&mcc_endpoint_m4_pingpong, &pp_msg,
+ sizeof(struct mcc_pp_msg),
+ 0xffffffff);
+ msleep(5000);
+ }
+ }
+
+ return total;
+}
+
+static int mcctty_write_room(struct tty_struct *tty)
+{
+ int room;
+
+ /* report the space in the mcc buffer */
+ room = MCC_ATTR_BUFFER_SIZE_IN_BYTES;
+
+ return room;
+}
+
+static const struct tty_operations imxmcctty_ops = {
+ .install = mcctty_install,
+ .open = mcctty_open,
+ .close = mcctty_close,
+ .write = mcctty_write,
+ .write_room = mcctty_write_room,
+};
+
+static struct tty_driver *mcctty_driver;
+
+static int __init imxmcctty_init(void)
+{
+ int ret;
+ struct mcctty_port *cport = &mcc_tty_port;
+
+ mcctty_driver = tty_alloc_driver(1,
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_UNNUMBERED_NODE);
+ if (IS_ERR(mcctty_driver))
+ return PTR_ERR(mcctty_driver);
+
+ mcctty_driver->driver_name = "mcc_tty";
+ mcctty_driver->name = "ttyMCC";
+ mcctty_driver->major = TTYAUX_MAJOR;
+ mcctty_driver->minor_start = 3;
+ mcctty_driver->type = TTY_DRIVER_TYPE_PTY;
+ mcctty_driver->init_termios = tty_std_termios;
+ mcctty_driver->init_termios.c_cflag |= CLOCAL;
+
+ tty_set_operations(mcctty_driver, &imxmcctty_ops);
+
+ tty_port_init(&cport->port);
+ cport->port.ops = &mcctty_port_ops;
+ spin_lock_init(&cport->rx_lock);
+ spin_lock_init(&cport->tx_lock);
+
+ ret = tty_register_driver(mcctty_driver);
+ if (ret < 0) {
+ pr_err("Couldn't install mcc tty driver: err %d\n", ret);
+ goto error;
+ } else
+ pr_info("Install mcc tty driver!\n");
+
+ /* Allocate the buffer we use for reading data */
+ cport->rx_buf = kzalloc(MCC_ATTR_BUFFER_SIZE_IN_BYTES,
+ GFP_KERNEL);
+ if (!cport->rx_buf) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ INIT_DELAYED_WORK(&cport->read, mcctty_delay_work);
+ schedule_delayed_work(&cport->read, HZ/100);
+ return 0;
+
+error:
+ tty_unregister_driver(mcctty_driver);
+ put_tty_driver(mcctty_driver);
+ tty_port_destroy(&cport->port);
+ mcctty_driver = NULL;
+
+ return ret;
+}
+
+static void imxmcctty_exit(void)
+{
+ int ret = 0;
+ struct mcctty_port *cport = &mcc_tty_port;
+
+ /* stop reading, null the read buffer. */
+ kfree(cport->rx_buf);
+ cport->rx_buf = NULL;
+
+ /* destory the mcc tty endpoint here */
+ ret = mcc_destroy_endpoint(&mcc_endpoint_a9_pingpong);
+ if (ret)
+ pr_err("failed to destory a9 mcc ep.\n");
+ else
+ pr_info("destory a9 mcc ep.\n");
+
+ tty_unregister_driver(mcctty_driver);
+ tty_port_destroy(&cport->port);
+ put_tty_driver(mcctty_driver);
+}
+
+module_init(imxmcctty_init);
+module_exit(imxmcctty_exit);
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 0811633fcc4d..2718b1139948 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -143,7 +143,7 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
init.ops = &clk_mux_ro_ops;
else
init.ops = &clk_mux_ops;
- init.flags = flags | CLK_IS_BASIC;
+ init.flags = flags | CLK_IS_BASIC | CLK_IS_BASIC_MUX;
init.parent_names = parent_names;
init.num_parents = num_parents;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 02e75d4e0a77..91894db43c50 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1567,6 +1567,7 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent)
*/
int clk_set_parent(struct clk *clk, struct clk *parent)
{
+ struct clk *child;
int ret = 0;
u8 p_index = 0;
unsigned long p_rate = 0;
@@ -1593,6 +1594,18 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
goto out;
}
+ /* check two consecutive basic mux clocks */
+ if (clk->flags & CLK_IS_BASIC_MUX) {
+ hlist_for_each_entry(child, &clk->children, child_node) {
+ if (child->flags & CLK_IS_BASIC_MUX) {
+ pr_err("%s: failed to switch parent of %s due to child mux %s\n",
+ __func__, clk->name, child->name);
+ ret = -EBUSY;
+ goto out;
+ }
+ }
+ }
+
/* try finding the new parent index */
if (parent) {
p_index = clk_fetch_parent_index(clk, parent);
diff --git a/drivers/cpufreq/cpufreq-imx6.c b/drivers/cpufreq/cpufreq-imx6.c
index c49c8eff8e79..2e457e0c1215 100644
--- a/drivers/cpufreq/cpufreq-imx6.c
+++ b/drivers/cpufreq/cpufreq-imx6.c
@@ -405,6 +405,12 @@ static int imx6_cpufreq_probe(struct platform_device *pdev)
}
imx6_soc_opp[i].arm_freq = freq;
imx6_soc_opp[i].soc_volt = volt;
+#ifdef CONFIG_MX6_VPU_352M
+ if (imx6_soc_opp[i].arm_freq == 792000) {
+ pr_info("increase SOC/PU voltage for VPU352MHz\n");
+ imx6_soc_opp[i].soc_volt = 1250000;
+ }
+#endif
soc_opp_count++;
}
rcu_read_unlock();
diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c
index 2010c0171b5a..a310569c40e6 100644
--- a/drivers/dma/pxp/pxp_dma_v2.c
+++ b/drivers/dma/pxp/pxp_dma_v2.c
@@ -377,11 +377,8 @@ static void pxp_set_ctrl(struct pxps *pxp)
ctrl |= BM_PXP_CTRL_VFLIP;
if (proc_data->hflip)
ctrl |= BM_PXP_CTRL_HFLIP;
- if (proc_data->rotate) {
+ if (proc_data->rotate)
ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90);
- if (proc_data->rot_pos)
- ctrl |= BM_PXP_CTRL_ROT_POS;
- }
/* In default, the block size is set to 8x8
* But block size can be set to 16x16 due to
@@ -409,25 +406,20 @@ static void pxp_set_outbuf(struct pxps *pxp)
__raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF);
- if (proc_data->rotate == 90 || proc_data->rotate == 270) {
- if (proc_data->rot_pos == 1)
- __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.height - 1) |
- BF_PXP_OUT_LRC_Y(proc_data->drect.width - 1),
- pxp->base + HW_PXP_OUT_LRC);
- else
- __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.width - 1) |
- BF_PXP_OUT_LRC_Y(proc_data->drect.height - 1),
- pxp->base + HW_PXP_OUT_LRC);
- } else
- __raw_writel(BF_PXP_OUT_LRC_X(proc_data->drect.width - 1) |
- BF_PXP_OUT_LRC_Y(proc_data->drect.height - 1),
+ if (proc_data->rotate == 90 || proc_data->rotate == 270)
+ __raw_writel(BF_PXP_OUT_LRC_X(out_params->height - 1) |
+ BF_PXP_OUT_LRC_Y(out_params->width - 1),
+ pxp->base + HW_PXP_OUT_LRC);
+ else
+ __raw_writel(BF_PXP_OUT_LRC_X(out_params->width - 1) |
+ BF_PXP_OUT_LRC_Y(out_params->height - 1),
pxp->base + HW_PXP_OUT_LRC);
if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) {
__raw_writel(out_params->stride * 3,
pxp->base + HW_PXP_OUT_PITCH);
} else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 ||
- out_params->pixel_fmt == PXP_PIX_FMT_RGB32) {
+ out_params->pixel_fmt == PXP_PIX_FMT_RGB32) {
__raw_writel(out_params->stride << 2,
pxp->base + HW_PXP_OUT_PITCH);
} else if (out_params->pixel_fmt == PXP_PIX_FMT_RGB565) {
@@ -512,22 +504,9 @@ static void pxp_set_oln(int layer_no, struct pxps *pxp)
__raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC);
} else {
__raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC);
- if (pxp_conf->proc_data.rotate == 90 ||
- pxp_conf->proc_data.rotate == 270) {
- if (pxp_conf->proc_data.rot_pos == 1) {
- __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->height - 1) |
- BF_PXP_OUT_AS_LRC_Y(olparams_data->width - 1),
- pxp->base + HW_PXP_OUT_AS_LRC);
- } else {
- __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
- BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
- pxp->base + HW_PXP_OUT_AS_LRC);
- }
- } else {
- __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
+ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) |
BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1),
pxp->base + HW_PXP_OUT_AS_LRC);
- }
}
if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) |
@@ -589,12 +568,44 @@ static void pxp_set_s0param(struct pxps *pxp)
struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
struct pxp_layer_param *out_params = &pxp_conf->out_param;
- u32 s0param;
+ u32 s0param_ulc, s0param_lrc;
- if (proc_data->drect.left != 0 || proc_data->drect.top != 0) {
- out_params->paddr += (proc_data->drect.top * out_params->stride +
- proc_data->drect.left) * 2;
- proc_data->drect.left = proc_data->drect.top = 0;
+ /* contains the coordinate for the PS in the OUTPUT buffer. */
+ if ((pxp_conf->s0_param).width == 0 &&
+ (pxp_conf->s0_param).height == 0) {
+ __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC);
+ __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC);
+ } else {
+ switch (proc_data->rotate) {
+ case 0:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left);
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top);
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.width - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.height - 1);
+ break;
+ case 90:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_Y(out_params->width - (proc_data->drect.left + proc_data->drect.width));
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_X(proc_data->drect.top);
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.height - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.width - 1);
+ break;
+ case 180:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_X(out_params->width - (proc_data->drect.left + proc_data->drect.width));
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_Y(out_params->height - (proc_data->drect.top + proc_data->drect.height));
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.width - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.height - 1);
+ break;
+ case 270:
+ s0param_ulc = BF_PXP_OUT_PS_ULC_X(out_params->height - (proc_data->drect.top + proc_data->drect.height));
+ s0param_ulc |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.left);
+ s0param_lrc = BF_PXP_OUT_PS_LRC_X(((s0param_ulc & BM_PXP_OUT_PS_ULC_X) >> 16) + proc_data->drect.height - 1);
+ s0param_lrc |= BF_PXP_OUT_PS_LRC_Y((s0param_ulc & BM_PXP_OUT_PS_ULC_Y) + proc_data->drect.width - 1);
+ break;
+ default:
+ return;
+ }
+ __raw_writel(s0param_ulc, pxp->base + HW_PXP_OUT_PS_ULC);
+ __raw_writel(s0param_lrc, pxp->base + HW_PXP_OUT_PS_LRC);
}
/* Since user apps always pass the rotated drect
@@ -608,33 +619,6 @@ static void pxp_set_s0param(struct pxps *pxp)
proc_data->drect.width = proc_data->drect.height;
proc_data->drect.height = temp;
}
-
- /* contains the coordinate for the PS in the OUTPUT buffer. */
- if ((pxp_conf->s0_param).width == 0 &&
- (pxp_conf->s0_param).height == 0) {
- __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC);
- __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC);
- } else {
- s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left);
- s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top);
- __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC);
- /* In PXP, the two different rotation
- * position requires different settings
- * on OUT_PS_LRC register
- */
- if (proc_data->rot_pos == 1) {
- s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
- proc_data->drect.height - 1);
- s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
- proc_data->drect.width - 1);
- } else {
- s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left +
- proc_data->drect.width - 1);
- s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top +
- proc_data->drect.height - 1);
- }
- __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC);
- }
}
/* crop behavior is re-designed in h/w. */
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index cce31c3e5f76..d51103f5316a 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1582,4 +1582,10 @@ config SENSORS_MMA8X5X
If you say yes here you get support for the Freescale
MMA8451/MMA8452/MMA8453/MMA8652/MMA8653 sensors.
+config MXC_MMA8x5x
+ tristate "MMA8x5x device driver"
+ depends on I2C && SYSFS
+ default n
+ help
+ This configure is used by android sensor driver.
endif # HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 76d65717d6b2..4fcafff867c3 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -142,7 +142,9 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
obj-$(CONFIG_SENSORS_MAG3110) += mag3110.o
-obj-$(CONFIG_SENSORS_MMA8X5X) += mma8x5x.o
+obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o
+obj-$(CONFIG_MXC_MMA8x5x) += mma8x5x.o
+
obj-$(CONFIG_PMBUS) += pmbus/
ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
diff --git a/drivers/hwmon/mma8x5x.c b/drivers/hwmon/mma8x5x.c
index 4b13a2521f86..d77dc515043f 100644
--- a/drivers/hwmon/mma8x5x.c
+++ b/drivers/hwmon/mma8x5x.c
@@ -34,6 +34,7 @@
#include <linux/hwmon.h>
#include <linux/input.h>
#include <linux/miscdevice.h>
+#include <linux/regulator/consumer.h>
#define MMA8X5X_I2C_ADDR 0x1D
#define MMA8451_ID 0x1A
@@ -155,12 +156,14 @@ struct mma8x5x_data {
int position;
u8 chip_id;
int mode;
- int awaken; // is just awake from suspend
+ int awaken;
s64 period_rel;
int fifo_wakeup;
int fifo_timeout;
+ u32 int_pin;
};
-static struct mma8x5x_data * p_mma8x5x_data = NULL;
+
+static struct mma8x5x_data *p_mma8x5x_data;
/* Addresses scanned */
static const unsigned short normal_i2c[] = { 0x1c, 0x1d, I2C_CLIENT_END };
@@ -205,7 +208,8 @@ static int mma8x5x_data_convert(struct mma8x5x_data *pdata,
for (i = 0; i < 3; i++) {
data[i] = 0;
for (j = 0; j < 3; j++)
- data[i] += rawdata[j] * mma8x5x_position_setting[position][i][j];
+ data[i] += rawdata[j] *
+ mma8x5x_position_setting[position][i][j];
}
axis_data->x = data[0];
axis_data->y = data[1];
@@ -216,7 +220,8 @@ static int mma8x5x_check_id(int id)
{
int i = 0;
- for (i = 0; i < sizeof(mma8x5x_chip_id) / sizeof(mma8x5x_chip_id[0]); i++)
+ for (i = 0; i < sizeof(mma8x5x_chip_id) /
+ sizeof(mma8x5x_chip_id[0]); i++)
if (id == mma8x5x_chip_id[i])
return 1;
return 0;
@@ -226,7 +231,8 @@ static char *mma8x5x_id2name(u8 id)
return mma8x5x_names[(id >> 4) - 1];
}
-static int mma8x5x_i2c_read_fifo(struct i2c_client *client,u8 reg, char * buf, int len)
+static int mma8x5x_i2c_read_fifo(struct i2c_client *client,
+ u8 reg, char *buf, int len)
{
char send_buf[] = {reg};
struct i2c_msg msgs[] = {
@@ -251,42 +257,51 @@ static int mma8x5x_i2c_read_fifo(struct i2c_client *client,u8 reg, char * buf, i
}
/*period is ms, return the real period per event*/
-static s64 mma8x5x_odr_set(struct i2c_client * client, int period){
+static s64 mma8x5x_odr_set(struct i2c_client *client, int period)
+{
u8 odr;
u8 val;
s64 period_rel;
val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,val &(~0x01)); //standby
+ /*Standby*/
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val & (~0x01));
val &= ~(0x07 << 3);
- if(period >= 640){ /*1.56HZ*/
+ if (period >= 640) {
+ /*1.56HZ*/
odr = 0x7;
period_rel = 640 * NSEC_PER_MSEC;
- }
- else if(period >= 160){ /*6.25HZ*/
+ } else if (period >= 160) {
+ /*6.25HZ*/
odr = 0x06;
period_rel = 160 * NSEC_PER_MSEC;
- }
- else if(period >= 80){ /*12.5HZ*/
+ } else if (period >= 80) {
+ /*12.5HZ*/
odr = 0x05;
period_rel = 80 * NSEC_PER_MSEC;
- }else if(period >= 20){ /*50HZ*/
+ } else if (period >= 20) {
+ /*50HZ*/
odr = 0x04;
period_rel = 20 * NSEC_PER_MSEC;
- }else if(period >= 10){ /*100HZ*/
+ } else if (period >= 10) {
+ /*100HZ*/
odr = 0x03;
period_rel = 10 * NSEC_PER_MSEC;
- }else if(period >= 5){ /*200HZ*/
+ } else if (period >= 5) {
+ /*200HZ*/
odr = 0x02;
period_rel = 5 * NSEC_PER_MSEC;
- }else if((period * 2) >= 5){ /*400HZ*/
+ } else if ((period * 2) >= 5) {
+ /*400HZ*/
odr = 0x01;
period_rel = 2500 * NSEC_PER_USEC;
- }else{ /*800HZ*/
+ } else {
+ /*800HZ*/
odr = 0x00;
period_rel = 1250 * NSEC_PER_USEC;
}
val |= (odr << 3);
- i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,val); //standby
+ /*Standby*/
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val);
return period_rel;
}
static int mma8x5x_device_init(struct i2c_client *client)
@@ -335,66 +350,93 @@ static int mma8x5x_read_data(struct i2c_client *client,
data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
return 0;
}
-static int mma8x5x_fifo_interrupt(struct i2c_client *client,int enable)
+
+static int mma8x5x_fifo_interrupt(struct i2c_client *client, int enable)
{
- u8 val,sys_mode;
- sys_mode = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG1);
- i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,(sys_mode & (~0x01))); //standby
- val = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG4);
+ u8 val, sys_mode;
+ sys_mode = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ /*standby*/
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,
+ (sys_mode & (~0x01)));
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG4);
val &= ~(0x01 << 6);
- if(enable)
+ if (enable)
val |= (0x01 << 6);
- i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG4,val);
- i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,sys_mode);
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG4, val);
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, sys_mode);
return 0;
}
-static int mma8x5x_fifo_setting(struct mma8x5x_data *pdata,int time_out,int is_overwrite)
+
+static int mma8x5x_fifo_setting(struct mma8x5x_data *pdata,
+ int time_out, int is_overwrite)
{
- u8 val,sys_mode,pin_cfg;
+ u8 val, sys_mode, pin_cfg;
struct i2c_client *client = pdata->client;
- sys_mode = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG1);
- i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,(sys_mode & (~0x01))); //standby
- pin_cfg = i2c_smbus_read_byte_data(client,MMA8X5X_CTRL_REG5);
- val = i2c_smbus_read_byte_data(client,MMA8X5X_F_SETUP);
+ sys_mode = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+ /*standby*/
+ i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG1,
+ (sys_mode & (~0x01)));
+ pin_cfg = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG5);
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_F_SETUP);
val &= ~(0x03 << 6);
- if(time_out > 0){
- if(is_overwrite)
+ if (time_out > 0) {
+ if (is_overwrite)
val |= (0x01 << 6);
else
val |= (0x02 << 6);
}
- i2c_smbus_write_byte_data(client,MMA8X5X_F_SETUP,val);
- i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG5,pin_cfg |(0x01 << 6));//route to pin 1
- i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1,sys_mode);
- if(time_out > 0){
- pdata->period_rel = mma8x5x_odr_set(client,time_out/32); //fifo len is 32
+ i2c_smbus_write_byte_data(client, MMA8X5X_F_SETUP, val);
+ /*route to pin 1*/
+ if (pdata->int_pin == 1)
+ i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG5,
+ pin_cfg | (0x01 << 6));
+ /*route to pin 1*/
+ else
+ i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG5,
+ pin_cfg & ~(0x01 << 6));
+
+ i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, sys_mode);
+
+ if (time_out > 0) {
+ /*fifo len is 32*/
+ pdata->period_rel = mma8x5x_odr_set(client, time_out/32);
}
return 0;
}
-static int mma8x5x_read_fifo_data(struct mma8x5x_data *pdata){
- int count,cnt;
- u8 buf[256],val;
- int i,index;
+static int mma8x5x_read_fifo_data(struct mma8x5x_data *pdata)
+{
+ int count, cnt;
+ u8 buf[256], val;
+ int i, index;
struct i2c_client *client = pdata->client;
struct mma8x5x_fifo *pfifo = &pdata->fifo;
struct timespec ts;
- val = i2c_smbus_read_byte_data(client,MMA8X5X_STATUS);
- if(val & (0x01 << 7)) //fifo overflow
- {
+ val = i2c_smbus_read_byte_data(client, MMA8X5X_STATUS);
+ /*FIFO overflow*/
+ if (val & (0x01 << 7)) {
cnt = (val & 0x3f);
- count = mma8x5x_i2c_read_fifo(client,MMA8X5X_OUT_X_MSB,buf,MMA8X5X_BUF_SIZE * cnt);
- if(count > 0){
+ count = mma8x5x_i2c_read_fifo(client, MMA8X5X_OUT_X_MSB,
+ buf, MMA8X5X_BUF_SIZE * cnt);
+ if (count > 0) {
ktime_get_ts(&ts);
- for(i = 0; i < count/MMA8X5X_BUF_SIZE ;i++){
+ for (i = 0; i < count/MMA8X5X_BUF_SIZE ; i++) {
index = MMA8X5X_BUF_SIZE * i;
- pfifo->fifo_data[i].x = ((buf[index] << 8) & 0xff00) | buf[index + 1];
- pfifo->fifo_data[i].y = ((buf[index + 2] << 8) & 0xff00) | buf[index + 3];
- pfifo->fifo_data[i].z = ((buf[index + 4] << 8) & 0xff00) | buf[index + 5];
- mma8x5x_data_convert(pdata, &pfifo->fifo_data[i]);
+ pfifo->fifo_data[i].x =
+ ((buf[index] << 8) & 0xff00) | buf[index + 1];
+ pfifo->fifo_data[i].y =
+ ((buf[index + 2] << 8) & 0xff00) | buf[index + 3];
+ pfifo->fifo_data[i].z =
+ ((buf[index + 4] << 8) & 0xff00) | buf[index + 5];
+ mma8x5x_data_convert(pdata,
+ &pfifo->fifo_data[i]);
}
pfifo->period = pdata->period_rel;
pfifo->count = count / MMA8X5X_BUF_SIZE;
- pfifo->timestamp = ((s64)ts.tv_sec) * NSEC_PER_SEC + ts.tv_nsec;
+ pfifo->timestamp = ((s64)ts.tv_sec) * NSEC_PER_SEC
+ + ts.tv_nsec;
return 0;
}
}
@@ -406,7 +448,7 @@ static void mma8x5x_report_data(struct mma8x5x_data *pdata)
struct mma8x5x_data_axis data;
int ret;
ret = mma8x5x_read_data(pdata->client, &data);
- if(!ret){
+ if (!ret) {
mma8x5x_data_convert(pdata, &data);
input_report_abs(pdata->idev, ABS_X, data.x);
input_report_abs(pdata->idev, ABS_Y, data.y);
@@ -414,9 +456,10 @@ static void mma8x5x_report_data(struct mma8x5x_data *pdata)
input_sync(pdata->idev);
}
}
-static void mma8x5x_work(struct mma8x5x_data * pdata){
+static void mma8x5x_work(struct mma8x5x_data *pdata)
+{
int delay;
- if(pdata->active == MMA_ACTIVED){
+ if (pdata->active == MMA_ACTIVED) {
delay = msecs_to_jiffies(pdata->delay);
if (delay >= HZ)
delay = round_jiffies_relative(delay);
@@ -425,7 +468,9 @@ static void mma8x5x_work(struct mma8x5x_data * pdata){
}
static void mma8x5x_dev_poll(struct work_struct *work)
{
- struct mma8x5x_data *pdata = container_of(work, struct mma8x5x_data,work.work);
+ struct mma8x5x_data *pdata = container_of(work,
+ struct mma8x5x_data,
+ work.work);
mma8x5x_report_data(pdata);
mma8x5x_work(pdata);
}
@@ -434,24 +479,24 @@ static irqreturn_t mma8x5x_irq_handler(int irq, void *dev)
int ret;
u8 int_src;
struct mma8x5x_data *pdata = (struct mma8x5x_data *)dev;
- int_src = i2c_smbus_read_byte_data(pdata->client,MMA8X5X_INT_SOURCE);
- if(int_src & (0x01 << 6)){
+ int_src = i2c_smbus_read_byte_data(pdata->client, MMA8X5X_INT_SOURCE);
+ if (int_src & (0x01 << 6)) {
ret = mma8x5x_read_fifo_data(pdata);
- if(!ret){
+ if (!ret) {
atomic_set(&pdata->fifo_ready, 1);
wake_up(&pdata->fifo_wq);
}
- if(pdata->awaken) /*is just awken from suspend*/
- {
- mma8x5x_fifo_setting(pdata,pdata->fifo_timeout,0); //10s timeout
- mma8x5x_fifo_interrupt(pdata->client,1);
+ /*is just awken from suspend*/
+ if (pdata->awaken) {
+ /*10s timeout*/
+ mma8x5x_fifo_setting(pdata, pdata->fifo_timeout, 0);
+ mma8x5x_fifo_interrupt(pdata->client, 1);
pdata->awaken = 0;
}
}
return IRQ_HANDLED;
}
-
static ssize_t mma8x5x_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -480,34 +525,46 @@ static ssize_t mma8x5x_enable_store(struct device *dev,
unsigned long enable;
u8 val = 0;
- enable = simple_strtoul(buf, NULL, 10);
+ ret = strict_strtol(buf, 10, &enable);
+ if (ret) {
+ dev_err(dev, "string to long error\n");
+ return ret;
+ }
mutex_lock(&pdata->data_lock);
enable = (enable > 0) ? 1 : 0;
if (enable && pdata->active == MMA_STANDBY) {
val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client,MMA8X5X_CTRL_REG1, val | 0x01);
+ ret = i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG1,
+ val | 0x01);
if (!ret) {
pdata->active = MMA_ACTIVED;
- if(pdata->fifo_timeout <= 0) //continuous mode
+ /*continuous mode*/
+ if (pdata->fifo_timeout <= 0)
mma8x5x_work(pdata);
- else{ /*fifo mode*/
- mma8x5x_fifo_setting(pdata,pdata->fifo_timeout,0); //no overwirte fifo
- mma8x5x_fifo_interrupt(client,1);
+ else {
+ /*fifo mode*/
+ mma8x5x_fifo_setting(pdata,
+ pdata->fifo_timeout, 0);
+ mma8x5x_fifo_interrupt(client, 1);
}
- printk(KERN_INFO"mma enable setting active \n");
+ printk(KERN_INFO"mma enable setting active\n");
}
- } else if (enable == 0 && pdata->active == MMA_ACTIVED) {
+ } else if (enable == 0 && pdata->active == MMA_ACTIVED) {
val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val & 0xFE);
+ ret = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,
+ val & 0xFE);
if (!ret) {
pdata->active = MMA_STANDBY;
- if(pdata->fifo_timeout <= 0) //continuous mode
+ if (pdata->fifo_timeout <= 0)
+ /*continuous mode*/
cancel_delayed_work_sync(&pdata->work);
- else{ /*fifo mode*/
- mma8x5x_fifo_setting(pdata,0,0); //no overwirte fifo
- mma8x5x_fifo_interrupt(client,0);
+ else {
+ /*fifo mode*/
+ mma8x5x_fifo_setting(pdata, 0, 0);
+ mma8x5x_fifo_interrupt(client, 0);
}
- printk(KERN_INFO"mma enable setting inactive \n");
+ printk(KERN_INFO"mma enable setting inactive\n");
}
}
mutex_unlock(&pdata->data_lock);
@@ -530,14 +587,20 @@ static ssize_t mma8x5x_delay_store(struct device *dev,
const char *buf, size_t count)
{
struct mma8x5x_data *pdata = dev_get_drvdata(dev);
- struct i2c_client * client = pdata->client;
- int delay;
- delay = simple_strtoul(buf, NULL, 10);
+ struct i2c_client *client = pdata->client;
+ int ret;
+ long delay;
+ ret = strict_strtol(buf, 10, &delay);
+ if (ret) {
+ dev_err(dev, "string to long error\n");
+ return ret;
+ }
+
mutex_lock(&pdata->data_lock);
cancel_delayed_work_sync(&pdata->work);
- pdata->delay = delay;
- if(pdata->active == MMA_ACTIVED && pdata->fifo_timeout <= 0){
- mma8x5x_odr_set(client,delay);
+ pdata->delay = (int)delay;
+ if (pdata->active == MMA_ACTIVED && pdata->fifo_timeout <= 0) {
+ mma8x5x_odr_set(client, (int)delay);
mma8x5x_work(pdata);
}
mutex_unlock(&pdata->data_lock);
@@ -551,9 +614,12 @@ static ssize_t mma8x5x_fifo_show(struct device *dev,
struct mma8x5x_data *pdata = dev_get_drvdata(dev);
mutex_lock(&pdata->data_lock);
count = sprintf(&buf[count], "period poll :%d ms\n", pdata->delay);
- count += sprintf(&buf[count],"period fifo :%lld ns\n",pdata->period_rel);
- count += sprintf(&buf[count],"timeout :%d ms\n", pdata->fifo_timeout);
- count += sprintf(&buf[count],"interrupt wake up: %s\n", (pdata->fifo_wakeup ? "yes" : "no")); /*is the interrupt enable*/
+ count += sprintf(&buf[count], "period fifo :%lld ns\n",
+ pdata->period_rel);
+ count += sprintf(&buf[count], "timeout :%d ms\n", pdata->fifo_timeout);
+ /*is the interrupt enable*/
+ count += sprintf(&buf[count], "interrupt wake up: %s\n",
+ (pdata->fifo_wakeup ? "yes" : "no"));
mutex_unlock(&pdata->data_lock);
return count;
}
@@ -563,27 +629,30 @@ static ssize_t mma8x5x_fifo_store(struct device *dev,
const char *buf, size_t count)
{
struct mma8x5x_data *pdata = dev_get_drvdata(dev);
- struct i2c_client * client = pdata->client;
- int period,timeout,wakeup;
- sscanf(buf,"%d,%d,%d",&period,&timeout,&wakeup);
- printk("period %d ,timeout is %d, wake up is :%d\n",period,timeout,wakeup);
- if(timeout > 0){
+ struct i2c_client *client = pdata->client;
+ int period, timeout, wakeup;
+ sscanf(buf, "%d,%d,%d", &period, &timeout, &wakeup);
+ printk(KERN_INFO"period %d ,timeout is %d, wake up is :%d\n",
+ period, timeout, wakeup);
+ if (timeout > 0) {
mutex_lock(&pdata->data_lock);
cancel_delayed_work_sync(&pdata->work);
pdata->delay = period;
mutex_unlock(&pdata->data_lock);
- mma8x5x_fifo_setting(pdata,timeout,0); //no overwirte fifo
- mma8x5x_fifo_interrupt(client,1);
+ /*no overwirte fifo*/
+ mma8x5x_fifo_setting(pdata, timeout, 0);
+ mma8x5x_fifo_interrupt(client, 1);
pdata->fifo_timeout = timeout;
pdata->fifo_wakeup = wakeup;
- }else{
- mma8x5x_fifo_setting(pdata,timeout,0); //no overwirte fifo
- mma8x5x_fifo_interrupt(client,0);
+ } else {
+ /*no overwirte fifo*/
+ mma8x5x_fifo_setting(pdata, timeout, 0);
+ mma8x5x_fifo_interrupt(client, 0);
pdata->fifo_timeout = timeout;
pdata->fifo_wakeup = wakeup;
mutex_lock(&pdata->data_lock);
pdata->delay = period;
- if(pdata->active == MMA_ACTIVED)
+ if (pdata->active == MMA_ACTIVED)
mma8x5x_work(pdata);
mutex_unlock(&pdata->data_lock);
}
@@ -606,10 +675,15 @@ static ssize_t mma8x5x_position_store(struct device *dev,
const char *buf, size_t count)
{
struct mma8x5x_data *pdata = dev_get_drvdata(dev);
- int position;
- position = simple_strtoul(buf, NULL, 10);
+ int ret;
+ long position;
+ ret = strict_strtol(buf, 10, &position);
+ if (ret) {
+ dev_err(dev, "string to long error\n");
+ return ret;
+ }
mutex_lock(&pdata->data_lock);
- pdata->position = position;
+ pdata->position = (int)position;
mutex_unlock(&pdata->data_lock);
return count;
}
@@ -646,12 +720,13 @@ static int mma8x5x_detect(struct i2c_client *client,
chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
if (!mma8x5x_check_id(chip_id))
return -ENODEV;
- printk(KERN_INFO "check %s i2c address 0x%x \n",
+ printk(KERN_INFO"check %s i2c address 0x%x\n",
mma8x5x_id2name(chip_id), client->addr);
strlcpy(info->type, "mma8x5x", I2C_NAME_SIZE);
return 0;
}
-static int mma8x5x_open(struct inode *inode, struct file *file){
+static int mma8x5x_open(struct inode *inode, struct file *file)
+{
int err;
err = nonseekable_open(inode, file);
if (err)
@@ -659,27 +734,33 @@ static int mma8x5x_open(struct inode *inode, struct file *file){
file->private_data = p_mma8x5x_data;
return 0;
}
-static ssize_t mma8x5x_read(struct file *file, char __user *buf, size_t size, loff_t *ppos){
+static ssize_t mma8x5x_read(struct file *file,
+ char __user *buf,
+ size_t size, loff_t *ppos)
+{
struct mma8x5x_data *pdata = file->private_data;
int ret = 0;
if (!(file->f_flags & O_NONBLOCK)) {
- ret = wait_event_interruptible(pdata->fifo_wq, (atomic_read(&pdata->fifo_ready) != 0));
+ ret = wait_event_interruptible(pdata->fifo_wq,
+ (atomic_read(&pdata->fifo_ready) != 0));
if (ret)
return ret;
}
if (!atomic_read(&pdata->fifo_ready))
return -ENODEV;
- if(size < sizeof(struct mma8x5x_fifo)){
- printk(KERN_ERR "the buffer leght less than need\n");
+ if (size < sizeof(struct mma8x5x_fifo)) {
+ printk(KERN_ERR"the buffer leght less than need\n");
return -ENOMEM;
}
- if(!copy_to_user(buf,&pdata->fifo,sizeof(struct mma8x5x_fifo))){
- atomic_set(&pdata->fifo_ready,0);
+ if (!copy_to_user(buf, &pdata->fifo, sizeof(struct mma8x5x_fifo))) {
+ atomic_set(&pdata->fifo_ready, 0);
return size;
}
return -ENOMEM ;
}
-static unsigned int mma8x5x_poll(struct file * file, struct poll_table_struct * wait){
+static unsigned int mma8x5x_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
struct mma8x5x_data *pdata = file->private_data;
poll_wait(file, &pdata->fifo_wq, wait);
if (atomic_read(&pdata->fifo_ready))
@@ -707,8 +788,29 @@ static int mma8x5x_probe(struct i2c_client *client,
struct input_dev *idev;
struct mma8x5x_data *pdata;
struct i2c_adapter *adapter;
- struct device_node *of_node = client->dev.of_node;
- u32 pos = 0;
+ struct device_node *of_node = client->dev.of_node;
+ u32 pos = 0;
+ struct regulator *vdd, *vdd_io;
+ u32 irq_flag;
+ struct irq_data *irq_data;
+
+ vdd = devm_regulator_get(&client->dev, "vdd");
+ if (!IS_ERR(vdd)) {
+ result = regulator_enable(vdd);
+ if (result) {
+ dev_err(&client->dev, "vdd set voltage error\n");
+ return result;
+ }
+ }
+
+ vdd_io = devm_regulator_get(&client->dev, "vddio");
+ if (!IS_ERR(vdd_io)) {
+ result = regulator_enable(vdd_io);
+ if (result) {
+ dev_err(&client->dev, "vddio set voltage error\n");
+ return result;
+ }
+ }
adapter = to_i2c_adapter(client->dev.parent);
result = i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_BYTE |
@@ -716,7 +818,6 @@ static int mma8x5x_probe(struct i2c_client *client,
if (!result)
goto err_out;
- printk(KERN_ERR"%s here 7", __func__);
chip_id = i2c_smbus_read_byte_data(client, MMA8X5X_WHO_AM_I);
if (!mma8x5x_check_id(chip_id)) {
@@ -734,37 +835,30 @@ static int mma8x5x_probe(struct i2c_client *client,
goto err_out;
}
- printk(KERN_ERR"%s here 6", __func__);
/* Initialize the MMA8X5X chip */
- memset(pdata,0,sizeof(struct mma8x5x_data));
+ memset(pdata, 0, sizeof(struct mma8x5x_data));
pdata->client = client;
pdata->chip_id = chip_id;
pdata->mode = MODE_2G;
pdata->fifo_wakeup = 0;
pdata->fifo_timeout = 0;
- printk(KERN_ERR"%s here 0", __func__);
- result = of_property_read_u32(of_node, "position",&pos );
-
- printk(KERN_ERR"%s here result=%d pos=%d", __func__, result, pos);
- if (result)
- pos = 1;
+ result = of_property_read_u32(of_node, "position", &pos);
+ if (result)
+ pos = 1;
pdata->position = (int)pos;
p_mma8x5x_data = pdata;
mutex_init(&pdata->data_lock);
i2c_set_clientdata(client, pdata);
- printk(KERN_ERR"%s here 12", __func__);
mma8x5x_device_init(client);
- printk(KERN_ERR"%s here 13", __func__);
idev = input_allocate_device();
if (!idev) {
result = -ENOMEM;
dev_err(&client->dev, "alloc input device failed!\n");
goto err_alloc_input_device;
}
- printk(KERN_ERR"%s here 1", __func__);
idev->name = "FreescaleAccelerometer";
idev->uniq = mma8x5x_id2name(pdata->chip_id);
idev->id.bustype = BUS_I2C;
@@ -772,9 +866,8 @@ static int mma8x5x_probe(struct i2c_client *client,
input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
- dev_set_drvdata(&idev->dev,pdata);
- pdata->idev= idev ;
- printk(KERN_ERR"%s here 2", __func__);
+ dev_set_drvdata(&idev->dev, pdata);
+ pdata->idev = idev;
result = input_register_device(pdata->idev);
if (result) {
dev_err(&client->dev, "register input device failed!\n");
@@ -789,28 +882,53 @@ static int mma8x5x_probe(struct i2c_client *client,
goto err_create_sysfs;
}
init_waitqueue_head(&pdata->fifo_wq);
- if(client->irq){
- printk(KERN_ERR"%s here 3", __func__);
- result= request_threaded_irq(client->irq,NULL, mma8x5x_irq_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->dev.driver->name, pdata);
+
+ if (client->irq) {
+ irq_data = irq_get_irq_data(client->irq);
+ irq_flag = irqd_get_trigger_type(irq_data);
+ irq_flag |= IRQF_ONESHOT;
+ result = request_threaded_irq(client->irq, NULL,
+ mma8x5x_irq_handler,
+ irq_flag,
+ client->dev.driver->name,
+ pdata);
if (result < 0) {
- dev_err(&client->dev, "failed to register MMA8x5x irq %d!\n",
+ dev_err(&client->dev,
+ "failed to register MMA8x5x irq %d!\n",
client->irq);
goto err_register_irq;
- }else{
+ } else {
result = misc_register(&mma8x5x_dev);
if (result) {
- dev_err(&client->dev,"register fifo device error\n");
+ dev_err(&client->dev,
+ "register fifo device error\n");
goto err_reigster_dev;
}
}
+
+ result = of_property_read_u32(of_node,
+ "interrupt-route",
+ &pdata->int_pin);
+ if (result) {
+ result = -EINVAL;
+ dev_err(&client->dev,
+ "Can't find interrupt-pin value\n");
+ goto err_reigster_dev;
+
+ }
+ if (pdata->int_pin == 0 || pdata->int_pin > 2) {
+ result = -EINVAL;
+ dev_err(&client->dev,
+ "The interrupt-pin value is invalid\n");
+ goto err_reigster_dev;
+ }
}
printk(KERN_INFO"mma8x5x device driver probe successfully\n");
return 0;
err_reigster_dev:
- free_irq(client->irq,pdata);
+ free_irq(client->irq, pdata);
err_register_irq:
- sysfs_remove_group(&idev->dev.kobj,&mma8x5x_attr_group);
+ sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group);
err_create_sysfs:
input_unregister_device(pdata->idev);
err_register_input_device:
@@ -820,13 +938,14 @@ err_alloc_input_device:
err_out:
return result;
}
+
static int mma8x5x_remove(struct i2c_client *client)
{
struct mma8x5x_data *pdata = i2c_get_clientdata(client);
struct input_dev *idev = pdata->idev;
mma8x5x_device_stop(client);
if (pdata) {
- sysfs_remove_group(&idev->dev.kobj,&mma8x5x_attr_group);
+ sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group);
input_unregister_device(pdata->idev);
input_free_device(pdata->idev);
kfree(pdata);
@@ -839,17 +958,19 @@ static int mma8x5x_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct mma8x5x_data *pdata = i2c_get_clientdata(client);
- if(pdata->fifo_timeout <= 0){
+ if (pdata->fifo_timeout <= 0) {
if (pdata->active == MMA_ACTIVED)
mma8x5x_device_stop(client);
- }else{
- if (pdata->active == MMA_ACTIVED){
- if (pdata->fifo_wakeup){
- mma8x5x_fifo_setting(pdata,10000,0); //10s timeout , overwrite
- mma8x5x_fifo_interrupt(client,1);
- }else{
- mma8x5x_fifo_interrupt(client,0);
- mma8x5x_fifo_setting(pdata,10000,1); //10s timeout , overwrite
+ } else {
+ if (pdata->active == MMA_ACTIVED) {
+ if (pdata->fifo_wakeup) {
+ /*10s timeout , overwrite*/
+ mma8x5x_fifo_setting(pdata, 10000, 0);
+ mma8x5x_fifo_interrupt(client, 1);
+ } else {
+ mma8x5x_fifo_interrupt(client, 0);
+ /*10s timeout , overwrite*/
+ mma8x5x_fifo_setting(pdata, 10000, 1);
}
}
}
@@ -861,15 +982,18 @@ static int mma8x5x_resume(struct device *dev)
int val = 0;
struct i2c_client *client = to_i2c_client(dev);
struct mma8x5x_data *pdata = i2c_get_clientdata(client);
- if(pdata->fifo_timeout <= 0){
+ if (pdata->fifo_timeout <= 0) {
if (pdata->active == MMA_ACTIVED) {
- val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, val | 0x01);
+ val = i2c_smbus_read_byte_data(client,
+ MMA8X5X_CTRL_REG1);
+ i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG1, val | 0x01);
}
- }else{
+ } else {
if (pdata->active == MMA_ACTIVED) {
- mma8x5x_fifo_interrupt(client,1);
- pdata->awaken = 1; //awake from suspend
+ mma8x5x_fifo_interrupt(client, 1);
+ /*Awake from suspend*/
+ pdata->awaken = 1;
}
}
return 0;
@@ -878,9 +1002,14 @@ static int mma8x5x_resume(struct device *dev)
#endif
static const struct i2c_device_id mma8x5x_id[] = {
- { "mma8x5x", 0 },
- { }
+ {"mma8451", 0},
+ {"mma8452", 0},
+ {"mma8453", 0},
+ {"mma8652", 0},
+ {"mma8653", 0},
+ {}
};
+
MODULE_DEVICE_TABLE(i2c, mma8x5x_id);
static SIMPLE_DEV_PM_OPS(mma8x5x_pm_ops, mma8x5x_suspend, mma8x5x_resume);
diff --git a/drivers/media/platform/mxc/capture/csi_v4l2_capture.c b/drivers/media/platform/mxc/capture/csi_v4l2_capture.c
index 3da162860205..3f759b635f8b 100644
--- a/drivers/media/platform/mxc/capture/csi_v4l2_capture.c
+++ b/drivers/media/platform/mxc/capture/csi_v4l2_capture.c
@@ -48,8 +48,6 @@ static int req_buf_number;
static int csi_v4l2_master_attach(struct v4l2_int_device *slave);
static void csi_v4l2_master_detach(struct v4l2_int_device *slave);
static u8 camera_power(cam_data *cam, bool cameraOn);
-static struct v4l2_format cam_input_fmt;
-static bool bswapenable;
/*! Information about this driver. */
static struct v4l2_int_master csi_v4l2_master = {
@@ -57,15 +55,6 @@ static struct v4l2_int_master csi_v4l2_master = {
.detach = csi_v4l2_master_detach,
};
-static struct v4l2_int_device csi_v4l2_int_device = {
- .module = THIS_MODULE,
- .name = "csi_v4l2_cap",
- .type = v4l2_int_type_master,
- .u = {
- .master = &csi_v4l2_master,
- },
-};
-
static struct v4l2_queryctrl pxp_controls[] = {
{
.id = V4L2_CID_HFLIP,
@@ -307,11 +296,12 @@ static int pxp_process_update(cam_data *cam)
/*
* Configure PxP for processing of new v4l2 buf
*/
- pxp_conf->s0_param.pixel_fmt = v4l2_fmt_2_pxp_fmt(cam_input_fmt.fmt.pix.pixelformat);
+ pxp_conf->s0_param.pixel_fmt =
+ v4l2_fmt_2_pxp_fmt(cam->input_fmt.fmt.pix.pixelformat);
pxp_conf->s0_param.color_key = -1;
pxp_conf->s0_param.color_key_enable = false;
- pxp_conf->s0_param.width = cam_input_fmt.fmt.pix.width;
- pxp_conf->s0_param.height = cam_input_fmt.fmt.pix.height;
+ pxp_conf->s0_param.width = cam->input_fmt.fmt.pix.width;
+ pxp_conf->s0_param.height = cam->input_fmt.fmt.pix.height;
pxp_conf->ol_param[0].combine_enable = false;
@@ -462,12 +452,12 @@ next:
list_del(cam->ready_q.next);
list_add_tail(&ready_frame->queue, &cam->working_q);
- __raw_writel(ready_frame->paddress,
+ csi_write(cam->csi_soc, ready_frame->paddress,
cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 :
CSI_CSIDMASA_FB2);
ready_frame->csi_buf_num = cam->ping_pong_csi;
} else {
- __raw_writel(cam->dummy_frame.paddress,
+ csi_write(cam->csi_soc, cam->dummy_frame.paddress,
cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 :
CSI_CSIDMASA_FB2);
}
@@ -488,10 +478,10 @@ static int csi_cap_image(cam_data *cam)
{
unsigned int value;
- value = __raw_readl(CSI_CSICR3);
- __raw_writel(value | BIT_FRMCNT_RST, CSI_CSICR3);
- value = __raw_readl(CSI_CSISR);
- __raw_writel(value, CSI_CSISR);
+ value = csi_read(cam->csi_soc, CSI_CSICR3);
+ csi_write(cam->csi_soc, value | BIT_FRMCNT_RST, CSI_CSICR3);
+ value = csi_read(cam->csi_soc, CSI_CSISR);
+ csi_write(cam->csi_soc, value, CSI_CSISR);
return 0;
}
@@ -711,7 +701,7 @@ static int csi_streamon(cam_data *cam)
frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
list_del(cam->ready_q.next);
list_add_tail(&frame->queue, &cam->working_q);
- __raw_writel(frame->paddress, CSI_CSIDMASA_FB1);
+ csi_write(cam->csi_soc, frame->paddress, CSI_CSIDMASA_FB1);
frame->csi_buf_num = 1;
if (list_empty(&cam->ready_q)) {
@@ -723,7 +713,7 @@ static int csi_streamon(cam_data *cam)
frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue);
list_del(cam->ready_q.next);
list_add_tail(&frame->queue, &cam->working_q);
- __raw_writel(frame->paddress, CSI_CSIDMASA_FB2);
+ csi_write(cam->csi_soc, frame->paddress, CSI_CSIDMASA_FB2);
frame->csi_buf_num = 2;
spin_unlock_irqrestore(&cam->queue_int_lock, flags);
@@ -733,12 +723,13 @@ static int csi_streamon(cam_data *cam)
local_irq_save(flags);
for (timeout = 1000000; timeout > 0; timeout--) {
- if (__raw_readl(CSI_CSISR) & BIT_SOF_INT) {
- val = __raw_readl(CSI_CSICR3);
- __raw_writel(val | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
+ if (csi_read(cam->csi_soc, CSI_CSISR) & BIT_SOF_INT) {
+ val = csi_read(cam->csi_soc, CSI_CSICR3);
+ csi_write(cam->csi_soc, val | BIT_DMA_REFLASH_RFF,
+ CSI_CSICR3);
/* Wait DMA reflash done */
for (timeout2 = 1000000; timeout2 > 0; timeout2--) {
- if (__raw_readl(CSI_CSICR3) &
+ if (csi_read(cam->csi_soc, CSI_CSICR3) &
BIT_DMA_REFLASH_RFF)
cpu_relax();
else
@@ -750,9 +741,9 @@ static int csi_streamon(cam_data *cam)
return -ETIME;
}
- csi_dmareq_rff_enable();
- csi_enable_int(1);
- csi_enable(1);
+ csi_dmareq_rff_enable(cam->csi_soc);
+ csi_enable_int(cam, 1);
+ csi_enable(cam, 1);
break;
} else
cpu_relax();
@@ -781,21 +772,21 @@ static int csi_streamoff(cam_data *cam)
if (cam->capture_on == false)
return 0;
- csi_dmareq_rff_disable();
- csi_disable_int();
+ csi_dmareq_rff_disable(cam->csi_soc);
+ csi_disable_int(cam);
cam->capture_on = false;
/* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */
- __raw_writel(0, CSI_CSIDMASA_FB1);
- __raw_writel(0, CSI_CSIDMASA_FB2);
+ csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB1);
+ csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB2);
if (strcmp(csi_capture_inputs[cam->current_input].name,
"Vadc") == 0) {
- csi_buf_stride_set(0);
- csi_deinterlace_enable(false);
- csi_tvdec_enable(false);
+ csi_buf_stride_set(cam, 0);
+ csi_deinterlace_enable(cam, false);
+ csi_tvdec_enable(cam, false);
}
- csi_enable(0);
+ csi_enable(cam, 0);
csi_free_frames(cam);
csi_free_frame_buf(cam);
@@ -814,11 +805,13 @@ static int start_preview(cam_data *cam)
{
unsigned long fb_addr = (unsigned long)cam->v4l2_fb.base;
- __raw_writel(fb_addr, CSI_CSIDMASA_FB1);
- __raw_writel(fb_addr, CSI_CSIDMASA_FB2);
- __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
+ csi_write(cam->csi_soc, fb_addr, CSI_CSIDMASA_FB1);
+ csi_write(cam->csi_soc, fb_addr, CSI_CSIDMASA_FB2);
+ csi_write(cam->csi_soc,
+ csi_read(cam->csi_soc, CSI_CSICR3) | BIT_DMA_REFLASH_RFF,
+ CSI_CSICR3);
- csi_enable_int(0);
+ csi_enable_int(cam, 0);
return 0;
}
@@ -832,12 +825,14 @@ static int start_preview(cam_data *cam)
*/
static int stop_preview(cam_data *cam)
{
- csi_disable_int();
+ csi_disable_int(cam);
/* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */
- __raw_writel(0, CSI_CSIDMASA_FB1);
- __raw_writel(0, CSI_CSIDMASA_FB2);
- __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
+ csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB1);
+ csi_write(cam->csi_soc, 0, CSI_CSIDMASA_FB2);
+ csi_write(cam->csi_soc,
+ csi_read(cam->csi_soc, CSI_CSICR3) | BIT_DMA_REFLASH_RFF,
+ CSI_CSICR3);
return 0;
}
@@ -948,7 +943,8 @@ static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
}
/* disable swap function */
- csi_format_swap16(false);
+ csi_format_swap16(cam, false);
+ cam->bswapenable = false;
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_RGB565:
@@ -962,17 +958,17 @@ static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
case V4L2_PIX_FMT_UYVY:
size = f->fmt.pix.width * f->fmt.pix.height * 2;
bytesperline = f->fmt.pix.width * 2;
- if (cam_input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
- csi_format_swap16(true);
- bswapenable = true;
+ if (cam->input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
+ csi_format_swap16(cam, true);
+ cam->bswapenable = true;
}
break;
case V4L2_PIX_FMT_YUYV:
size = f->fmt.pix.width * f->fmt.pix.height * 2;
bytesperline = f->fmt.pix.width * 2;
- if (cam_input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) {
- csi_format_swap16(true);
- bswapenable = true;
+ if (cam->input_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) {
+ csi_format_swap16(cam, true);
+ cam->bswapenable = true;
}
break;
case V4L2_PIX_FMT_YUV420:
@@ -1000,8 +996,8 @@ static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f)
else
size = f->fmt.pix.sizeimage;
- if (cam_input_fmt.fmt.pix.sizeimage > f->fmt.pix.sizeimage)
- f->fmt.pix.sizeimage = cam_input_fmt.fmt.pix.sizeimage;
+ if (cam->input_fmt.fmt.pix.sizeimage > f->fmt.pix.sizeimage)
+ f->fmt.pix.sizeimage = cam->input_fmt.fmt.pix.sizeimage;
cam->v2f.fmt.pix = f->fmt.pix;
@@ -1084,32 +1080,36 @@ static int csi_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
}
vidioc_int_g_ifparm(cam->sensor, &ifparm);
- cam_input_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- vidioc_int_g_fmt_cap(cam->sensor, &cam_input_fmt);
+ cam->input_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ vidioc_int_g_fmt_cap(cam->sensor, &cam->input_fmt);
pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n",
- cam_input_fmt.fmt.pix.width, cam_input_fmt.fmt.pix.height);
+ cam->input_fmt.fmt.pix.width, cam->input_fmt.fmt.pix.height);
- f = &cam_input_fmt;
+ f = &cam->input_fmt;
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUV444:
size = f->fmt.pix.width * f->fmt.pix.height * 4;
- csi_set_32bit_imagpara(f->fmt.pix.width,
+ csi_set_32bit_imagpara(cam,
+ f->fmt.pix.width,
f->fmt.pix.height);
break;
case V4L2_PIX_FMT_UYVY:
size = f->fmt.pix.width * f->fmt.pix.height * 2;
- csi_set_16bit_imagpara(f->fmt.pix.width,
+ csi_set_16bit_imagpara(cam,
+ f->fmt.pix.width,
f->fmt.pix.height);
break;
case V4L2_PIX_FMT_YUYV:
size = f->fmt.pix.width * f->fmt.pix.height * 2;
- csi_set_16bit_imagpara(f->fmt.pix.width,
+ csi_set_16bit_imagpara(cam,
+ f->fmt.pix.width,
f->fmt.pix.height);
break;
case V4L2_PIX_FMT_YUV420:
size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2;
- csi_set_12bit_imagpara(f->fmt.pix.width,
+ csi_set_12bit_imagpara(cam,
+ f->fmt.pix.width,
f->fmt.pix.height);
break;
case V4L2_PIX_FMT_YUV422P:
@@ -1125,8 +1125,8 @@ static int csi_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm)
f->fmt.pix.sizeimage = size;
cam->crop_bounds.top = cam->crop_bounds.left = 0;
- cam->crop_bounds.width = cam_input_fmt.fmt.pix.width;
- cam->crop_bounds.height = cam_input_fmt.fmt.pix.height;
+ cam->crop_bounds.width = cam->input_fmt.fmt.pix.width;
+ cam->crop_bounds.height = cam->input_fmt.fmt.pix.height;
cam->crop_current.width = cam->crop_bounds.width;
cam->crop_current.height = cam->crop_bounds.height;
@@ -1201,9 +1201,9 @@ static int csi_v4l_s_std(cam_data *cam, v4l2_std_id e)
strcpy(cam->standard.name, video_fmts[video_index].name);
/* Enable csi PAL/NTSC deinterlace mode */
- csi_buf_stride_set(video_fmts[video_index].active_width);
- csi_deinterlace_mode(cam->standard.id);
- csi_deinterlace_enable(true);
+ csi_buf_stride_set(cam, video_fmts[video_index].active_width);
+ csi_deinterlace_mode(cam, cam->standard.id);
+ csi_deinterlace_enable(cam, true);
/* crop will overwrite */
cam->crop_bounds.width = video_fmts[video_index].active_width;
@@ -1231,7 +1231,7 @@ static int csi_v4l_g_std(cam_data *cam, v4l2_std_id *e)
{
struct v4l2_format tv_fmt;
- pr_debug("In csi_v4l2_g_std\n");
+ pr_debug("In csi_v4l2_g_std, cam->csi %d\n", cam->csi);
if (cam->device_type == 1) {
/* Use this function to get what the TV-In device detects the
@@ -1256,13 +1256,13 @@ static int csi_v4l_g_std(cam_data *cam, v4l2_std_id *e)
return 0;
}
-static void csi_input_select(int input_select)
+static void csi_input_select(cam_data *cam)
{
- if (strcmp(csi_capture_inputs[input_select].name, "Vadc") == 0)
+ if (strcmp(csi_capture_inputs[cam->current_input].name, "Vadc") == 0)
/* Enable csi tvdec */
- csi_tvdec_enable(true);
+ csi_tvdec_enable(cam, true);
else
- csi_tvdec_enable(false);
+ csi_tvdec_enable(cam, false);
}
/*!
@@ -1332,8 +1332,8 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
* If want to do preview on LCD, use PxP CSC to convert from UYVY
* to RGB565; but for encoding, usually we don't use RGB format.
*/
- if (cam->v2f.fmt.pix.pixelformat != cam_input_fmt.fmt.pix.pixelformat
- && !bswapenable) {
+ if (cam->v2f.fmt.pix.pixelformat != cam->input_fmt.fmt.pix.pixelformat
+ && !cam->bswapenable) {
sg_dma_address(&cam->sg[0]) = buf->m.offset;
/* last frame buffer as pxp output buffer */
sg_dma_address(&cam->sg[1]) =
@@ -1467,7 +1467,6 @@ static int csi_v4l_close(struct file *file)
file->private_data = NULL;
vidioc_int_s_power(cam->sensor, 0);
clk_disable_unprepare(sensor->sensor_clk);
- csi_clk_disable();
}
return err;
@@ -1510,19 +1509,23 @@ static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count,
return -ENOMEM;
}
cam->still_counter = 0;
- __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB2);
- __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB1);
- __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF,
- CSI_CSICR3);
- __raw_writel(__raw_readl(CSI_CSISR), CSI_CSISR);
- __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST,
- CSI_CSICR3);
- csi_enable_int(1);
- csi_enable(1);
+ csi_write(cam->csi_soc, cam->still_buf[0], CSI_CSIDMASA_FB2);
+ csi_write(cam->csi_soc, cam->still_buf[0], CSI_CSIDMASA_FB1);
+ csi_write(cam->csi_soc,
+ csi_read(cam->csi_soc, CSI_CSICR3) |
+ BIT_DMA_REFLASH_RFF,
+ CSI_CSICR3);
+ csi_write(cam->csi_soc, csi_read(cam->csi_soc, CSI_CSISR),
+ CSI_CSISR);
+ csi_write(cam->csi_soc,
+ csi_read(cam->csi_soc, CSI_CSICR3) | BIT_FRMCNT_RST,
+ CSI_CSICR3);
+ csi_enable_int(cam, 1);
+ csi_enable(cam, 1);
}
wait_event_interruptible(cam->still_queue, cam->still_counter);
- csi_disable_int();
+ csi_disable_int(cam);
err = copy_to_user(buf, cam->still_buf_vaddr,
cam->v2f.fmt.pix.sizeimage);
@@ -1965,7 +1968,7 @@ static long csi_v4l_do_ioctl(struct file *file,
cam->current_input = *index;
- csi_input_select(cam->current_input);
+ csi_input_select(cam);
break;
}
case VIDIOC_G_OUTPUT:
@@ -2066,11 +2069,20 @@ static struct video_device csi_v4l_template = {
*
* @return status 0 Success
*/
-static void init_camera_struct(cam_data *cam)
+static void init_camera_struct(cam_data *cam, struct platform_device *pdev)
{
struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data;
+ struct device_node *np = pdev->dev.of_node;
+ int ret = 0;
+ int csi_id;
pr_debug("In MVC: %s\n", __func__);
+ ret = of_property_read_u32(np, "csi_id", &csi_id);
+ if (ret) {
+ dev_err(&pdev->dev, "csi_id missing or invalid\n");
+ return;
+ }
+
proc_data->hflip = 0;
proc_data->vflip = 0;
proc_data->rotate = 0;
@@ -2082,6 +2094,9 @@ static void init_camera_struct(cam_data *cam)
sema_init(&cam->param_lock, 1);
sema_init(&cam->busy_lock, 1);
+ /* TODO sanity check */
+ cam->csi_soc = csi_get_soc(csi_id);
+
cam->video_dev = video_device_alloc();
if (cam->video_dev == NULL)
return;
@@ -2126,11 +2141,18 @@ static void init_camera_struct(cam_data *cam)
cam->crop_bounds.height = 480;
cam->crop_current = cam->crop_defrect = cam->crop_bounds;
+ cam->csi = csi_id;
cam->enc_callback = camera_callback;
csi_start_callback(cam);
init_waitqueue_head(&cam->power_queue);
spin_lock_init(&cam->queue_int_lock);
spin_lock_init(&cam->dqueue_int_lock);
+
+ cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL);
+ cam->self->module = THIS_MODULE;
+ sprintf(cam->self->name, "csi_v4l2_cap%d", cam->csi);
+ cam->self->type = v4l2_int_type_master;
+ cam->self->u.master = &csi_v4l2_master;
}
/*!
@@ -2172,14 +2194,13 @@ static int csi_v4l2_probe(struct platform_device *pdev)
err = -ENOMEM;
goto out;
}
- memset(&cam_input_fmt, 0, sizeof(cam_input_fmt));
- init_camera_struct(g_cam);
+ memset(&g_cam->input_fmt, 0, sizeof(g_cam->input_fmt));
+ init_camera_struct(g_cam, pdev);
platform_set_drvdata(pdev, (void *)g_cam);
/* Set up the v4l2 device and register it */
- csi_v4l2_int_device.priv = g_cam;
- /* This function contains a bug that won't let this be rmmod'd. */
- v4l2_int_device_register(&csi_v4l2_int_device);
+ g_cam->self->priv = g_cam;
+ v4l2_int_device_register(g_cam->self);
/* register v4l video device */
if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr)
@@ -2209,7 +2230,7 @@ static int csi_v4l2_remove(struct platform_device *pdev)
"-- setting ops to NULL\n");
} else {
pr_info("V4L2 freeing image input device\n");
- v4l2_int_device_unregister(&csi_v4l2_int_device);
+ v4l2_int_device_unregister(g_cam->self);
csi_stop_callback(g_cam);
video_unregister_device(g_cam->video_dev);
platform_set_drvdata(pdev, NULL);
@@ -2304,17 +2325,23 @@ static struct platform_driver csi_v4l2_driver = {
static int csi_v4l2_master_attach(struct v4l2_int_device *slave)
{
cam_data *cam = slave->u.slave->master->priv;
+ struct sensor_data *sdata = slave->priv;
struct v4l2_format cam_fmt;
pr_debug("In MVC: %s\n", __func__);
pr_debug(" slave.name = %s\n", slave->name);
pr_debug(" master.name = %s\n", slave->u.slave->master->name);
- cam->sensor = slave;
if (slave == NULL) {
pr_err("ERROR: v4l2 capture: slave parameter not valid.\n");
return -1;
}
+ if (sdata->csi != cam->csi) {
+ pr_debug("%s: csi doesn't match\n", __func__);
+ return -1;
+ }
+
+ cam->sensor = slave;
cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt);
diff --git a/drivers/media/platform/mxc/capture/fsl_csi.c b/drivers/media/platform/mxc/capture/fsl_csi.c
index 2839e9fa0d8e..602899d70ce0 100644
--- a/drivers/media/platform/mxc/capture/fsl_csi.c
+++ b/drivers/media/platform/mxc/capture/fsl_csi.c
@@ -33,9 +33,9 @@
#include "mxc_v4l2_capture.h"
#include "fsl_csi.h"
-void __iomem *csi_regbase;
-EXPORT_SYMBOL(csi_regbase);
-static int irq_nr;
+#define CSI_MAX_NUM 2
+struct csi_soc csi_array[CSI_MAX_NUM], *csi;
+
static csi_irq_callback_t g_callback;
static void *g_callback_data;
static struct clk *disp_axi_clk;
@@ -61,9 +61,10 @@ EXPORT_SYMBOL(csi_clk_disable);
static irqreturn_t csi_irq_handler(int irq, void *data)
{
cam_data *cam = (cam_data *) data;
- unsigned long status = __raw_readl(CSI_CSISR);
+ struct csi_soc *csi = &csi_array[cam->csi];
+ unsigned long status = __raw_readl(csi->regbase + CSI_CSISR);
- __raw_writel(status, CSI_CSISR);
+ __raw_writel(status, csi->regbase + CSI_CSISR);
if (status & BIT_HRESP_ERR_INT)
pr_warning("Hresponse error is detected.\n");
@@ -100,24 +101,25 @@ static irqreturn_t csi_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static void csihw_reset_frame_count(void)
+static void csihw_reset_frame_count(struct csi_soc *csi)
{
- __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST, CSI_CSICR3);
+ __raw_writel(__raw_readl(csi->regbase + CSI_CSICR3) | BIT_FRMCNT_RST,
+ csi->regbase + CSI_CSICR3);
}
-static void csihw_reset(void)
+static void csihw_reset(struct csi_soc *csi)
{
- csihw_reset_frame_count();
- __raw_writel(CSICR1_RESET_VAL, CSI_CSICR1);
- __raw_writel(CSICR2_RESET_VAL, CSI_CSICR2);
- __raw_writel(CSICR3_RESET_VAL, CSI_CSICR3);
+ csihw_reset_frame_count(csi);
+ __raw_writel(CSICR1_RESET_VAL, csi->regbase + CSI_CSICR1);
+ __raw_writel(CSICR2_RESET_VAL, csi->regbase + CSI_CSICR2);
+ __raw_writel(CSICR3_RESET_VAL, csi->regbase + CSI_CSICR3);
}
/*!
* csi_init_interface
* Init csi interface
*/
-void csi_init_interface(void)
+static void csi_init_interface(struct csi_soc *csi)
{
unsigned int val = 0;
unsigned int imag_para;
@@ -129,22 +131,22 @@ void csi_init_interface(void)
val |= BIT_FCC;
val |= 1 << SHIFT_MCLKDIV;
val |= BIT_MCLKEN;
- __raw_writel(val, CSI_CSICR1);
+ __raw_writel(val, csi->regbase + CSI_CSICR1);
imag_para = (640 << 16) | 960;
- __raw_writel(imag_para, CSI_CSIIMAG_PARA);
+ __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA);
val = 0x1010;
val |= BIT_DMA_REFLASH_RFF;
- __raw_writel(val, CSI_CSICR3);
+ __raw_writel(val, csi->regbase + CSI_CSICR3);
}
-EXPORT_SYMBOL(csi_init_interface);
-void csi_format_swap16(bool enable)
+void csi_format_swap16(cam_data *cam, bool enable)
{
+ struct csi_soc *csi = &csi_array[cam->csi];
unsigned int val;
- val = __raw_readl(CSI_CSICR1);
+ val = __raw_readl(csi->regbase + CSI_CSICR1);
if (enable) {
val |= BIT_PACK_DIR;
val |= BIT_SWAP16_EN;
@@ -153,7 +155,7 @@ void csi_format_swap16(bool enable)
val &= ~BIT_SWAP16_EN;
}
- __raw_writel(val, CSI_CSICR1);
+ __raw_writel(val, csi->regbase + CSI_CSICR1);
}
EXPORT_SYMBOL(csi_format_swap16);
@@ -172,7 +174,8 @@ void csi_start_callback(void *data)
{
cam_data *cam = (cam_data *) data;
- if (request_irq(irq_nr, csi_irq_handler, 0, "csi", cam) < 0)
+ if (request_irq(csi_array[cam->csi].irq_nr, csi_irq_handler, 0, "csi",
+ cam) < 0)
pr_debug("CSI error: irq request fail\n");
}
@@ -182,13 +185,14 @@ void csi_stop_callback(void *data)
{
cam_data *cam = (cam_data *) data;
- free_irq(irq_nr, cam);
+ free_irq(csi_array[cam->csi].irq_nr, cam);
}
EXPORT_SYMBOL(csi_stop_callback);
-void csi_enable_int(int arg)
+void csi_enable_int(cam_data *cam, int arg)
{
- unsigned long cr1 = __raw_readl(CSI_CSICR1);
+ struct csi_soc *csi = &csi_array[cam->csi];
+ unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1);
cr1 |= BIT_SOF_INTEN;
if (arg == 1) {
@@ -196,69 +200,76 @@ void csi_enable_int(int arg)
cr1 |= BIT_FB1_DMA_DONE_INTEN;
cr1 |= BIT_FB2_DMA_DONE_INTEN;
}
- __raw_writel(cr1, CSI_CSICR1);
+ __raw_writel(cr1, csi->regbase + CSI_CSICR1);
}
EXPORT_SYMBOL(csi_enable_int);
-void csi_disable_int(void)
+void csi_disable_int(cam_data *cam)
{
- unsigned long cr1 = __raw_readl(CSI_CSICR1);
+ struct csi_soc *csi = &csi_array[cam->csi];
+ unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1);
cr1 &= ~BIT_SOF_INTEN;
cr1 &= ~BIT_FB1_DMA_DONE_INTEN;
cr1 &= ~BIT_FB2_DMA_DONE_INTEN;
- __raw_writel(cr1, CSI_CSICR1);
+ __raw_writel(cr1, csi->regbase + CSI_CSICR1);
}
EXPORT_SYMBOL(csi_disable_int);
-void csi_enable(int arg)
+void csi_enable(cam_data *cam, int arg)
{
- unsigned long cr = __raw_readl(CSI_CSICR18);
+ struct csi_soc *csi = &csi_array[cam->csi];
+ unsigned long cr = __raw_readl(csi->regbase + CSI_CSICR18);
if (arg == 1)
cr |= BIT_CSI_ENABLE;
else
cr &= ~BIT_CSI_ENABLE;
- __raw_writel(cr, CSI_CSICR18);
+ __raw_writel(cr, csi->regbase + CSI_CSICR18);
}
EXPORT_SYMBOL(csi_enable);
-void csi_buf_stride_set(u32 stride)
+void csi_buf_stride_set(cam_data *cam, u32 stride)
{
- __raw_writel(stride, CSI_CSIFBUF_PARA);
+ struct csi_soc *csi = &csi_array[cam->csi];
+
+ __raw_writel(stride, csi->regbase + CSI_CSIFBUF_PARA);
}
EXPORT_SYMBOL(csi_buf_stride_set);
-void csi_deinterlace_enable(bool enable)
+void csi_deinterlace_enable(cam_data *cam, bool enable)
{
- unsigned long cr18 = __raw_readl(CSI_CSICR18);
+ struct csi_soc *csi = &csi_array[cam->csi];
+ unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18);
if (enable == true)
cr18 |= BIT_DEINTERLACE_EN;
else
cr18 &= ~BIT_DEINTERLACE_EN;
- __raw_writel(cr18, CSI_CSICR18);
+ __raw_writel(cr18, csi->regbase + CSI_CSICR18);
}
EXPORT_SYMBOL(csi_deinterlace_enable);
-void csi_deinterlace_mode(int mode)
+void csi_deinterlace_mode(cam_data *cam, int mode)
{
- unsigned long cr18 = __raw_readl(CSI_CSICR18);
+ struct csi_soc *csi = &csi_array[cam->csi];
+ unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18);
if (mode == V4L2_STD_NTSC)
cr18 |= BIT_NTSC_EN;
else
cr18 &= ~BIT_NTSC_EN;
- __raw_writel(cr18, CSI_CSICR18);
+ __raw_writel(cr18, csi->regbase + CSI_CSICR18);
}
EXPORT_SYMBOL(csi_deinterlace_mode);
-void csi_tvdec_enable(bool enable)
+void csi_tvdec_enable(cam_data *cam, bool enable)
{
- unsigned long cr18 = __raw_readl(CSI_CSICR18);
- unsigned long cr1 = __raw_readl(CSI_CSICR1);
+ struct csi_soc *csi = &csi_array[cam->csi];
+ unsigned long cr18 = __raw_readl(csi->regbase + CSI_CSICR18);
+ unsigned long cr1 = __raw_readl(csi->regbase + CSI_CSICR1);
if (enable == true) {
cr18 |= (BIT_TVDECODER_IN_EN | BIT_BASEADDR_SWITCH_EN);
@@ -270,71 +281,85 @@ void csi_tvdec_enable(bool enable)
cr1 |= BIT_SOF_POL | BIT_REDGE;
}
- __raw_writel(cr18, CSI_CSICR18);
- __raw_writel(cr1, CSI_CSICR1);
+ __raw_writel(cr18, csi->regbase + CSI_CSICR18);
+ __raw_writel(cr1, csi->regbase + CSI_CSICR1);
}
EXPORT_SYMBOL(csi_tvdec_enable);
-void csi_set_32bit_imagpara(int width, int height)
+void csi_set_32bit_imagpara(cam_data *cam, int width, int height)
{
+ struct csi_soc *csi = &csi_array[cam->csi];
int imag_para = 0;
- unsigned long cr3 = __raw_readl(CSI_CSICR3);
+ unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
imag_para = (width << 16) | height;
- __raw_writel(imag_para, CSI_CSIIMAG_PARA);
+ __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA);
/* reflash the embeded DMA controller */
- __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
+ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3);
}
EXPORT_SYMBOL(csi_set_32bit_imagpara);
-void csi_set_16bit_imagpara(int width, int height)
+void csi_set_16bit_imagpara(cam_data *cam, int width, int height)
{
+ struct csi_soc *csi = &csi_array[cam->csi];
int imag_para = 0;
- unsigned long cr3 = __raw_readl(CSI_CSICR3);
+ unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
imag_para = (width << 16) | (height * 2);
- __raw_writel(imag_para, CSI_CSIIMAG_PARA);
+ __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA);
/* reflash the embeded DMA controller */
- __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
+ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3);
}
EXPORT_SYMBOL(csi_set_16bit_imagpara);
-void csi_set_12bit_imagpara(int width, int height)
+void csi_set_12bit_imagpara(cam_data *cam, int width, int height)
{
+ struct csi_soc *csi = &csi_array[cam->csi];
int imag_para = 0;
- unsigned long cr3 = __raw_readl(CSI_CSICR3);
+ unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
imag_para = (width << 16) | (height * 3 / 2);
- __raw_writel(imag_para, CSI_CSIIMAG_PARA);
+ __raw_writel(imag_para, csi->regbase + CSI_CSIIMAG_PARA);
/* reflash the embeded DMA controller */
- __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3);
+ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, csi->regbase + CSI_CSICR3);
}
EXPORT_SYMBOL(csi_set_12bit_imagpara);
-void csi_dmareq_rff_enable(void)
+void csi_dmareq_rff_enable(struct csi_soc *csi)
{
- unsigned long cr3 = __raw_readl(CSI_CSICR3);
+ unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
cr3 |= BIT_DMA_REQ_EN_RFF;
cr3 |= BIT_HRESP_ERR_EN;
- __raw_writel(cr3, CSI_CSICR3);
+ __raw_writel(cr3, csi->regbase + CSI_CSICR3);
}
EXPORT_SYMBOL(csi_dmareq_rff_enable);
-void csi_dmareq_rff_disable(void)
+void csi_dmareq_rff_disable(struct csi_soc *csi)
{
- unsigned long cr3 = __raw_readl(CSI_CSICR3);
+ unsigned long cr3 = __raw_readl(csi->regbase + CSI_CSICR3);
cr3 &= ~BIT_DMA_REQ_EN_RFF;
cr3 &= ~BIT_HRESP_ERR_EN;
- __raw_writel(cr3, CSI_CSICR3);
+ __raw_writel(cr3, csi->regbase + CSI_CSICR3);
}
EXPORT_SYMBOL(csi_dmareq_rff_disable);
+struct csi_soc *csi_get_soc(int id)
+{
+ if (id >= CSI_MAX_NUM)
+ return ERR_PTR(-ENODEV);
+ else if (!csi_array[id].online)
+ return ERR_PTR(-ENODEV);
+ else
+ return &(csi_array[id]);
+}
+EXPORT_SYMBOL_GPL(csi_get_soc);
+
static const struct of_device_id fsl_csi_dt_ids[] = {
{ .compatible = "fsl,imx6sl-csi", },
{ /* sentinel */ }
@@ -345,6 +370,13 @@ static int csi_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *res;
+ int id;
+
+ id = of_alias_get_id(pdev->dev.of_node, "csi");
+ if (id < 0) {
+ dev_dbg(&pdev->dev, "can not get alias id\n");
+ return id;
+ }
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
@@ -352,7 +384,10 @@ static int csi_probe(struct platform_device *pdev)
ret = -ENODEV;
goto err;
}
- irq_nr = res->start;
+
+ csi = &csi_array[id];
+ csi->irq_nr = res->start;
+ csi->online = false;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
@@ -360,8 +395,8 @@ static int csi_probe(struct platform_device *pdev)
ret = -ENODEV;
goto err;
}
- csi_regbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!csi_regbase) {
+ csi->regbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!csi->regbase) {
dev_err(&pdev->dev, "ioremap failed with csi base\n");
ret = -ENOMEM;
goto err;
@@ -385,11 +420,11 @@ static int csi_probe(struct platform_device *pdev)
}
csi_clk_enable();
- csihw_reset();
- csi_init_interface();
- csi_dmareq_rff_disable();
- csi_clk_disable();
+ csihw_reset(csi);
+ csi_init_interface(csi);
+ csi_dmareq_rff_disable(csi);
+ csi->online = true;
err:
return ret;
}
diff --git a/drivers/media/platform/mxc/capture/fsl_csi.h b/drivers/media/platform/mxc/capture/fsl_csi.h
index 78b393ef9151..1bb15075473f 100644
--- a/drivers/media/platform/mxc/capture/fsl_csi.h
+++ b/drivers/media/platform/mxc/capture/fsl_csi.h
@@ -110,30 +110,24 @@
#define CSI_MCLK_I2C 8
#endif
-extern void __iomem *csi_regbase;
-#define CSI_CSICR1 (csi_regbase)
-#define CSI_CSICR2 (csi_regbase + 0x4)
-#define CSI_CSICR3 (csi_regbase + 0x8)
-#define CSI_STATFIFO (csi_regbase + 0xC)
-#define CSI_CSIRXFIFO (csi_regbase + 0x10)
-#define CSI_CSIRXCNT (csi_regbase + 0x14)
-#define CSI_CSISR (csi_regbase + 0x18)
-
-#define CSI_CSIDBG (csi_regbase + 0x1C)
-#define CSI_CSIDMASA_STATFIFO (csi_regbase + 0x20)
-#define CSI_CSIDMATS_STATFIFO (csi_regbase + 0x24)
-#define CSI_CSIDMASA_FB1 (csi_regbase + 0x28)
-#define CSI_CSIDMASA_FB2 (csi_regbase + 0x2C)
-#define CSI_CSIFBUF_PARA (csi_regbase + 0x30)
-#define CSI_CSIIMAG_PARA (csi_regbase + 0x34)
-
-#define CSI_CSICR18 (csi_regbase + 0x48)
-#define CSI_CSICR19 (csi_regbase + 0x4c)
-
-static inline void csi_clear_status(unsigned long status)
-{
- __raw_writel(status, CSI_CSISR);
-}
+#define CSI_CSICR1 0x0
+#define CSI_CSICR2 0x4
+#define CSI_CSICR3 0x8
+#define CSI_STATFIFO 0xC
+#define CSI_CSIRXFIFO 0x10
+#define CSI_CSIRXCNT 0x14
+#define CSI_CSISR 0x18
+
+#define CSI_CSIDBG 0x1C
+#define CSI_CSIDMASA_STATFIFO 0x20
+#define CSI_CSIDMATS_STATFIFO 0x24
+#define CSI_CSIDMASA_FB1 0x28
+#define CSI_CSIDMASA_FB2 0x2C
+#define CSI_CSIFBUF_PARA 0x30
+#define CSI_CSIIMAG_PARA 0x34
+
+#define CSI_CSICR18 0x48
+#define CSI_CSICR19 0x4c
struct csi_signal_cfg_t {
unsigned data_width:3;
@@ -193,24 +187,39 @@ struct csi_config_t {
unsigned int rxcnt;
};
+struct csi_soc {
+ bool online;
+ int irq_nr;
+ void __iomem *regbase;
+};
+
typedef void (*csi_irq_callback_t) (void *data, unsigned long status);
-void csi_init_interface(void);
-void csi_set_32bit_imagpara(int width, int height);
-void csi_set_16bit_imagpara(int width, int height);
-void csi_set_12bit_imagpara(int width, int height);
-void csi_format_swap16(bool enable);
+void csi_set_32bit_imagpara(cam_data *cam, int width, int height);
+void csi_set_16bit_imagpara(cam_data *cam, int width, int height);
+void csi_set_12bit_imagpara(cam_data *cam, int width, int height);
+void csi_format_swap16(cam_data *cam, bool enable);
int csi_read_mclk_flag(void);
void csi_start_callback(void *data);
void csi_stop_callback(void *data);
-void csi_enable_int(int arg);
-void csi_buf_stride_set(u32 stride);
-void csi_deinterlace_mode(int mode);
-void csi_deinterlace_enable(bool enable);
-void csi_tvdec_enable(bool enable);
-void csi_enable(int arg);
-void csi_disable_int(void);
+void csi_enable_int(cam_data *cam, int arg);
+void csi_buf_stride_set(cam_data *cam, u32 stride);
+void csi_deinterlace_mode(cam_data *cam, int mode);
+void csi_deinterlace_enable(cam_data *cam, bool enable);
+void csi_tvdec_enable(cam_data *cam, bool enable);
+void csi_enable(cam_data *cam, int arg);
+void csi_disable_int(cam_data *cam);
void csi_clk_enable(void);
void csi_clk_disable(void);
-void csi_dmareq_rff_enable(void);
-void csi_dmareq_rff_disable(void);
+void csi_dmareq_rff_enable(struct csi_soc *csi);
+void csi_dmareq_rff_disable(struct csi_soc *csi);
+static inline int csi_read(struct csi_soc *csi, unsigned int offset)
+{
+ return __raw_readl(csi->regbase + offset);
+}
+static inline void csi_write(struct csi_soc *csi, unsigned int value, unsigned int offset)
+{
+ __raw_writel(value, csi->regbase + offset);
+}
+
+struct csi_soc *csi_get_soc(int id);
diff --git a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
index 09a421f20f7e..b8ea5b9b2d27 100644
--- a/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
+++ b/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -157,6 +157,8 @@ typedef struct _cam_data {
/* v4l2 format */
struct v4l2_format v2f;
+ struct v4l2_format input_fmt; /* camera in */
+ bool bswapenable;
int rotation; /* for IPUv1 and IPUv3, this means encoder rotation */
int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */
struct v4l2_mxc_offset offset;
@@ -219,6 +221,7 @@ typedef struct _cam_data {
struct v4l2_int_device *self;
int sensor_index;
void *ipu;
+ void *csi_soc;
enum imx_v4l2_devtype devtype;
/* v4l2 buf elements related to PxP DMA */
diff --git a/drivers/media/platform/mxc/capture/mxc_vadc.c b/drivers/media/platform/mxc/capture/mxc_vadc.c
index bb114e1f9994..a5aa3f128268 100644
--- a/drivers/media/platform/mxc/capture/mxc_vadc.c
+++ b/drivers/media/platform/mxc/capture/mxc_vadc.c
@@ -885,6 +885,8 @@ static int vadc_probe(struct platform_device *pdev)
return ret;
}
+ vadc->sen.csi = csi_id;
+
/* remap GPR register */
vadc->gpr = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"gpr");
diff --git a/drivers/net/can/m_can.c b/drivers/net/can/m_can.c
index 4397cfe2ec31..ed6d86bfdd02 100644
--- a/drivers/net/can/m_can.c
+++ b/drivers/net/can/m_can.c
@@ -83,7 +83,23 @@ enum m_can_reg {
M_CAN_TXEFA = 0xf8,
};
+/* m_can lec values */
+enum m_can_lec_type {
+ LEC_NO_ERROR = 0,
+ LEC_STUFF_ERROR,
+ LEC_FORM_ERROR,
+ LEC_ACK_ERROR,
+ LEC_BIT1_ERROR,
+ LEC_BIT0_ERROR,
+ LEC_CRC_ERROR,
+ LEC_UNUSED,
+};
+/* Test Register (TEST) */
+#define TEST_LBCK BIT(4)
+
/* CC Control Register(CCCR) */
+#define CCCR_TEST BIT(7)
+#define CCCR_MON BIT(5)
#define CCCR_CCE BIT(1)
#define CCCR_INIT BIT(0)
@@ -97,6 +113,19 @@ enum m_can_reg {
#define BTR_SJW_SHIFT 0
#define BTR_SJW_MASK 0xf
+/* Error Counter Register(ECR) */
+#define ECR_RP BIT(15)
+#define ECR_REC_SHIFT 8
+#define ECR_REC_MASK (0x7f << ECR_REC_SHIFT)
+#define ECR_TEC_SHIFT 0
+#define ECR_TEC_MASK 0xff
+
+/* Protocol Status Register(PSR) */
+#define PSR_BO BIT(7)
+#define PSR_EW BIT(6)
+#define PSR_EP BIT(5)
+#define PSR_LEC_MASK 0x7
+
/* Interrupt Register(IR) */
#define IR_ALL_INT 0xffffffff
#define IR_STE BIT(31)
@@ -131,10 +160,11 @@ enum m_can_reg {
#define IR_RF0F BIT(2)
#define IR_RF0W BIT(1)
#define IR_RF0N BIT(0)
-#define IR_ERR_ALL (IR_STE | IR_FOE | IR_ACKE | IR_BE | IR_CRCE | \
- IR_WDI | IR_BO | IR_EW | IR_EP | IR_ELO | IR_BEU | \
- IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \
- IR_RF0L)
+#define IR_ERR_STATE (IR_BO | IR_EW | IR_EP)
+#define IR_ERR_BUS (IR_STE | IR_FOE | IR_ACKE | IR_BE | IR_CRCE | \
+ IR_WDI | IR_ELO | IR_BEU | IR_BEC | IR_TOO | IR_MRAF | \
+ IR_TSW | IR_TEFL | IR_RF1L | IR_RF0L)
+#define IR_ERR_ALL (IR_ERR_STATE | IR_ERR_BUS)
/* Rx FIFO 0/1 Configuration (RXF0C/RXF1C) */
#define RXFC_FWM_OFF 24
@@ -320,12 +350,175 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
return num_rx_pkts;
}
+static int m_can_handle_lost_msg(struct net_device *dev)
+{
+ struct net_device_stats *stats = &dev->stats;
+ struct sk_buff *skb;
+ struct can_frame *frame;
+
+ netdev_err(dev, "msg lost in rxf0\n");
+
+ skb = alloc_can_err_skb(dev, &frame);
+ if (unlikely(!skb))
+ return 0;
+
+ frame->can_id |= CAN_ERR_CRTL;
+ frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ stats->rx_errors++;
+ stats->rx_over_errors++;
+
+ netif_receive_skb(skb);
+
+ return 1;
+}
+
+static int m_can_handle_bus_err(struct net_device *dev,
+ enum m_can_lec_type lec_type)
+{
+ struct m_can_priv *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+
+ /* early exit if no lec update */
+ if (lec_type == LEC_UNUSED)
+ return 0;
+
+ /* propagate the error condition to the CAN stack */
+ skb = alloc_can_err_skb(dev, &cf);
+ if (unlikely(!skb))
+ return 0;
+
+ /*
+ * check for 'last error code' which tells us the
+ * type of the last error to occur on the CAN bus
+ */
+ priv->can.can_stats.bus_error++;
+ stats->rx_errors++;
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+
+ switch (lec_type) {
+ case LEC_STUFF_ERROR:
+ netdev_dbg(dev, "stuff error\n");
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ break;
+ case LEC_FORM_ERROR:
+ netdev_dbg(dev, "form error\n");
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ break;
+ case LEC_ACK_ERROR:
+ netdev_dbg(dev, "ack error\n");
+ cf->data[3] |= (CAN_ERR_PROT_LOC_ACK |
+ CAN_ERR_PROT_LOC_ACK_DEL);
+ break;
+ case LEC_BIT1_ERROR:
+ netdev_dbg(dev, "bit1 error\n");
+ cf->data[2] |= CAN_ERR_PROT_BIT1;
+ break;
+ case LEC_BIT0_ERROR:
+ netdev_dbg(dev, "bit0 error\n");
+ cf->data[2] |= CAN_ERR_PROT_BIT0;
+ break;
+ case LEC_CRC_ERROR:
+ netdev_dbg(dev, "CRC error\n");
+ cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+ CAN_ERR_PROT_LOC_CRC_DEL);
+ break;
+ default:
+ break;
+ }
+
+ netif_receive_skb(skb);
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+
+ return 1;
+}
+
+static int m_can_get_berr_counter(const struct net_device *dev,
+ struct can_berr_counter *bec)
+{
+ struct m_can_priv *priv = netdev_priv(dev);
+ unsigned int ecr;
+
+ ecr = m_can_read(priv, M_CAN_ECR);
+ bec->rxerr = (ecr & ECR_REC_MASK) >> ECR_REC_SHIFT;
+ bec->txerr = ecr & ECR_TEC_MASK;
+
+ return 0;
+}
+
+static int m_can_handle_state_change(struct net_device *dev,
+ enum can_state new_state)
+{
+ struct m_can_priv *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct can_berr_counter bec;
+ unsigned int ecr;
+
+ /* propagate the error condition to the CAN stack */
+ skb = alloc_can_err_skb(dev, &cf);
+ if (unlikely(!skb))
+ return 0;
+
+ m_can_get_berr_counter(dev, &bec);
+
+ switch (new_state) {
+ case CAN_STATE_ERROR_ACTIVE:
+ /* error warning state */
+ priv->can.can_stats.error_warning++;
+ priv->can.state = CAN_STATE_ERROR_WARNING;
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = (bec.txerr > bec.rxerr) ?
+ CAN_ERR_CRTL_TX_WARNING :
+ CAN_ERR_CRTL_RX_WARNING;
+ cf->data[6] = bec.txerr;
+ cf->data[7] = bec.rxerr;
+ break;
+ case CAN_STATE_ERROR_PASSIVE:
+ /* error passive state */
+ priv->can.can_stats.error_passive++;
+ priv->can.state = CAN_STATE_ERROR_PASSIVE;
+ cf->can_id |= CAN_ERR_CRTL;
+ ecr = m_can_read(priv, M_CAN_ECR);
+ if (ecr & ECR_RP)
+ cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+ if (bec.txerr > 127)
+ cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+ cf->data[6] = bec.txerr;
+ cf->data[7] = bec.rxerr;
+ break;
+ case CAN_STATE_BUS_OFF:
+ /* bus-off state */
+ priv->can.state = CAN_STATE_BUS_OFF;
+ cf->can_id |= CAN_ERR_BUSOFF;
+ /*
+ * disable all interrupts in bus-off mode to ensure that
+ * the CPU is not hogged down
+ */
+ m_can_enable_all_interrupts(priv, false);
+ can_bus_off(dev);
+ break;
+ default:
+ break;
+ }
+
+ netif_receive_skb(skb);
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+
+ return 1;
+}
+
static int m_can_poll(struct napi_struct *napi, int quota)
{
struct net_device *dev = napi->dev;
struct m_can_priv *priv = netdev_priv(dev);
u32 work_done = 0;
- u32 irqstatus;
+ u32 irqstatus, psr;
irqstatus = m_can_read(priv, M_CAN_IR);
if (irqstatus)
@@ -337,6 +530,48 @@ static int m_can_poll(struct napi_struct *napi, int quota)
if (!irqstatus)
goto end;
+ psr = m_can_read(priv, M_CAN_PSR);
+ if (irqstatus & IR_ERR_STATE) {
+ if ((psr & PSR_EW) &&
+ (priv->can.state != CAN_STATE_ERROR_WARNING)) {
+ netdev_dbg(dev, "entered error warning state\n");
+ work_done += m_can_handle_state_change(dev,
+ CAN_STATE_ERROR_WARNING);
+ }
+
+ if ((psr & PSR_EP) &&
+ (priv->can.state != CAN_STATE_ERROR_PASSIVE)) {
+ netdev_dbg(dev, "entered error warning state\n");
+ work_done += m_can_handle_state_change(dev,
+ CAN_STATE_ERROR_PASSIVE);
+ }
+
+ if ((psr & PSR_BO) &&
+ (priv->can.state != CAN_STATE_BUS_OFF)) {
+ netdev_dbg(dev, "entered error warning state\n");
+ work_done += m_can_handle_state_change(dev,
+ CAN_STATE_BUS_OFF);
+ }
+ }
+
+ if (irqstatus & IR_ERR_BUS) {
+ if (irqstatus & IR_RF0L)
+ work_done += m_can_handle_lost_msg(dev);
+
+ /* handle lec errors on the bus */
+ if (psr & LEC_UNUSED)
+ work_done += m_can_handle_bus_err(dev,
+ psr & LEC_UNUSED);
+
+ /* other unproccessed error interrupts */
+ if (irqstatus & IR_WDI)
+ netdev_err(dev, "Message RAM Watchdog event due to missing READY\n");
+ if (irqstatus & IR_TOO)
+ netdev_err(dev, "Timeout reached\n");
+ if (irqstatus & IR_MRAF)
+ netdev_err(dev, "Message RAM access failure occurred\n");
+ }
+
if (irqstatus & IR_RF0N)
/* handle events corresponding to receive message objects */
work_done += m_can_do_rx_poll(dev, (quota - work_done));
@@ -369,31 +604,18 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
if (ir & IR_ALL_INT)
m_can_write(priv, M_CAN_IR, ir);
- if (ir & IR_ERR_ALL) {
- netdev_dbg(dev, "bus error\n");
- /* TODO: handle bus error */
- }
-
- /* save irqstatus for later using */
- priv->irqstatus = ir;
-
/*
* schedule NAPI in case of
* - rx IRQ
- * - state change IRQ(TODO)
- * - bus error IRQ and bus error reporting (TODO)
+ * - state change IRQ
+ * - bus error IRQ and bus error reporting
*/
- if (ir & IR_RF0N) {
+ if ((ir & IR_RF0N) || (ir & IR_ERR_ALL)) {
+ priv->irqstatus = ir;
m_can_enable_all_interrupts(priv, false);
napi_schedule(&priv->napi);
}
- /* FIFO overflow */
- if (ir & IR_RF0L) {
- dev->stats.rx_over_errors++;
- dev->stats.rx_errors++;
- }
-
/* transmission complete interrupt */
if (ir & IR_TC) {
netdev_dbg(dev, "tx complete\n");
@@ -443,14 +665,13 @@ static int m_can_set_bittiming(struct net_device *dev)
* - configure rx fifo
* - accept non-matching frame into fifo 0
* - configure tx buffer
+ * - configure mode
* - setup bittiming
- * - TODO:
- * 1) other working modes support like monitor, loopback...
- * 2) lec error status report enable
*/
static void m_can_chip_config(struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
+ u32 cccr, test;
m_can_config_endisable(priv, true);
@@ -477,6 +698,22 @@ static void m_can_chip_config(struct net_device *dev)
m_can_write(priv, M_CAN_RXF1C, (priv->rxf1_elems << RXFC_FS_OFF) |
RXFC_FWM_1 | (priv->mram_off + priv->rxf1_off));
+ cccr = m_can_read(priv, M_CAN_CCCR);
+ cccr &= ~(CCCR_TEST | CCCR_MON);
+ test = m_can_read(priv, M_CAN_TEST);
+ test &= ~TEST_LBCK;
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ cccr |= CCCR_MON;
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+ cccr |= CCCR_TEST;
+ test |= TEST_LBCK;
+ }
+
+ m_can_write(priv, M_CAN_CCCR, cccr);
+ m_can_write(priv, M_CAN_TEST, test);
+
/* enable all interrupts */
m_can_write(priv, M_CAN_IR, IR_ALL_INT);
m_can_write(priv, M_CAN_IE, IR_ALL_INT);
@@ -515,14 +752,6 @@ static int m_can_set_mode(struct net_device *dev, enum can_mode mode)
return 0;
}
-static int m_can_get_berr_counter(const struct net_device *dev,
- struct can_berr_counter *bec)
-{
- /* TODO */
-
- return 0;
-}
-
static void free_m_can_dev(struct net_device *dev)
{
free_candev(dev);
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1c4f4d50d574..853b19f0e613 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1601,7 +1601,7 @@ fec_enet_interrupt(int irq, void *dev_id)
fep->work_ts = 0;
}
- if (fep->work_tx || fep->work_rx) {
+ if ((fep->work_tx || fep->work_rx) && fep->link) {
ret = IRQ_HANDLED;
/* Disable the RX interrupt */
@@ -2359,8 +2359,7 @@ fec_enet_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- if (!(fep->wol_flag & FEC_WOL_HAS_MAGIC_PACKET) &&
- wol->wolopts != 0)
+ if (!(fep->wol_flag & FEC_WOL_HAS_MAGIC_PACKET))
return -EINVAL;
if (wol->wolopts & ~WAKE_MAGIC)
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index eb255e807c06..ce028e159efe 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -186,7 +186,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
return hvc_driver;
}
-static int __init hvc_console_setup(struct console *co, char *options)
+static int hvc_console_setup(struct console *co, char *options)
{
if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
return -ENODEV;
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 642239015b46..3ee7217e25b2 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -1089,6 +1089,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
{
unsigned int addr = 0;
unsigned int modem = 0;
+ unsigned int brk = 0;
struct gsm_dlci *dlci;
int len = clen;
u8 *dp = data;
@@ -1115,6 +1116,16 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
if (len == 0)
return;
}
+ len--;
+ if (len > 0) {
+ while (gsm_read_ea(&brk, *dp++) == 0) {
+ len--;
+ if (len == 0)
+ return;
+ }
+ modem <<= 7;
+ modem |= (brk & 0x7f);
+ }
tty = tty_port_tty_get(&dlci->port);
gsm_process_modem(tty, dlci, modem, clen);
if (tty) {
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 59d26ef538d8..3723c0ebb316 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1267,12 +1267,13 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p)
*
* Locking: None
*/
-static void tty_line_name(struct tty_driver *driver, int index, char *p)
+static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p)
{
if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE)
- strcpy(p, driver->name);
+ return sprintf(p, "%s", driver->name);
else
- sprintf(p, "%s%d", driver->name, index + driver->name_base);
+ return sprintf(p, "%s%d", driver->name,
+ index + driver->name_base);
}
/**
@@ -3538,9 +3539,19 @@ static ssize_t show_cons_active(struct device *dev,
if (i >= ARRAY_SIZE(cs))
break;
}
- while (i--)
- count += sprintf(buf + count, "%s%d%c",
- cs[i]->name, cs[i]->index, i ? ' ':'\n');
+ while (i--) {
+ int index = cs[i]->index;
+ struct tty_driver *drv = cs[i]->device(cs[i], &index);
+
+ /* don't resolve tty0 as some programs depend on it */
+ if (drv && (cs[i]->index > 0 || drv->major != TTY_MAJOR))
+ count += tty_line_name(drv, index, buf + count);
+ else
+ count += sprintf(buf + count, "%s%d",
+ cs[i]->name, cs[i]->index);
+
+ count += sprintf(buf + count, "%c", i ? ' ':'\n');
+ }
console_unlock();
return count;
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index cbd333edbec0..8819bf14b2de 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -79,6 +79,10 @@ struct ci_role_driver {
int (*start)(struct ci_hdrc *);
void (*stop)(struct ci_hdrc *);
irqreturn_t (*irq)(struct ci_hdrc *);
+ /* Save before suspend */
+ void (*save)(struct ci_hdrc *);
+ /* Restore after power lost */
+ void (*restore)(struct ci_hdrc *);
const char *name;
};
@@ -154,6 +158,8 @@ struct ci_hdrc {
bool is_otg;
struct otg_fsm fsm;
struct ci_otg_fsm_timer_list *fsm_timer;
+ struct timer_list hnp_polling_timer;
+ bool hnp_polling_req;
struct work_struct work;
struct workqueue_struct *wq;
@@ -181,12 +187,24 @@ struct ci_hdrc {
struct dentry *debugfs;
bool id_event;
bool b_sess_valid_event;
+ bool vbus_glitch_check_event;
/* imx28 needs swp instruction for writing */
bool imx28_write_fix;
bool supports_runtime_pm;
bool in_lpm;
bool wakeup_int;
struct timer_list timer;
+ /* register save area for suspend&resume */
+ u32 pm_command;
+ u32 pm_status;
+ u32 pm_intr_enable;
+ u32 pm_frame_index;
+ u32 pm_segment;
+ u32 pm_frame_list;
+ u32 pm_async_next;
+ u32 pm_configured_flag;
+ u32 pm_portsc;
+ struct work_struct power_lost_work;
};
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 9a53efd1ad44..c0f6f902aaad 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -512,6 +512,16 @@ static int imx_controller_resume(struct device *dev)
data->in_lpm = false;
if (data->usbmisc_data) {
+ ret = imx_usbmisc_power_lost_check(data->usbmisc_data);
+ /* re-init if resume from power lost */
+ if (ret > 0) {
+ ret = imx_usbmisc_init(data->usbmisc_data);
+ if (ret) {
+ dev_err(dev, "usbmisc init failed, ret=%d\n",
+ ret);
+ goto clk_disable;
+ }
+ }
ret = imx_usbmisc_set_wakeup(data->usbmisc_data, false);
if (ret) {
dev_err(dev,
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h
index 3376c88c1ae6..a195a8961a0f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -34,5 +34,6 @@ int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool);
/* Call it before setting portsc.suspendM */
int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *);
int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *, bool);
+int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *);
#endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index f6b76604cf17..b6c57161985c 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -457,7 +457,7 @@ static irqreturn_t ci_irq(int irq, void *data)
* and disconnection events.
*/
if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) {
- ci->b_sess_valid_event = true;
+ ci->vbus_glitch_check_event = true;
hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
ci_otg_queue_work(ci);
return IRQ_HANDLED;
@@ -611,6 +611,52 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
}
}
+static enum ci_role ci_get_role(struct ci_hdrc *ci)
+{
+ if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
+ if (ci->is_otg) {
+ hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
+ return ci_otg_role(ci);
+ } else {
+ /*
+ * If the controller is not OTG capable, but support
+ * role switch, the defalt role is gadget, and the
+ * user can switch it through debugfs.
+ */
+ return CI_ROLE_GADGET;
+ }
+ } else {
+ return ci->roles[CI_ROLE_HOST]
+ ? CI_ROLE_HOST
+ : CI_ROLE_GADGET;
+ }
+}
+
+static void ci_start_new_role(struct ci_hdrc *ci)
+{
+ enum ci_role role = ci_get_role(ci);
+
+ if (ci->role != role)
+ ci_handle_id_switch(ci);
+
+ if (role == CI_ROLE_GADGET)
+ ci_handle_vbus_connected(ci);
+}
+
+static void ci_power_lost_work(struct work_struct *work)
+{
+ struct ci_hdrc *ci = container_of(work, struct ci_hdrc,
+ power_lost_work);
+
+ pm_runtime_get_sync(ci->dev);
+ if (ci_otg_is_fsm_mode(ci))
+ ci_hdrc_otg_fsm_restart(ci);
+ else
+ ci_start_new_role(ci);
+ pm_runtime_put_sync(ci->dev);
+ enable_irq(ci->irq);
+}
+
static int ci_hdrc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -715,24 +761,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
}
}
- if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
- if (ci->is_otg) {
- ci->role = ci_otg_role(ci);
- hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
- } else {
- /*
- * If the controller is not OTG capable, but support
- * role switch, the defalt role is gadget, and the
- * user can switch it through debugfs.
- */
- ci->role = CI_ROLE_GADGET;
- }
- } else {
- ci->role = ci->roles[CI_ROLE_HOST]
- ? CI_ROLE_HOST
- : CI_ROLE_GADGET;
- }
-
+ ci->role = ci_get_role(ci);
/* Notify vbus connected event if it is existed */
if (ci->role == CI_ROLE_GADGET)
ci_handle_vbus_connected(ci);
@@ -762,6 +791,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ci_otg_is_fsm_mode(ci))
ci_hdrc_otg_fsm_start(ci);
+ /* Init workqueue for controller power lost handling */
+ INIT_WORK(&ci->power_lost_work, ci_power_lost_work);
+
setup_timer(&ci->timer, delay_runtime_pm_put_timer,
(unsigned long)ci);
ret = dbg_create_files(ci);
@@ -838,6 +870,13 @@ static int ci_controller_suspend(struct device *dev)
if (ci->in_lpm)
return 0;
+ /*
+ * The registers for suspended host will not be updated
+ * during system suspend.
+ */
+ if (ci->roles[ci->role]->save)
+ ci->roles[ci->role]->save(ci);
+
if (ci_otg_is_fsm_mode(ci))
ci_otg_fsm_suspend_for_srp(ci);
@@ -881,11 +920,10 @@ static int ci_controller_resume(struct device *dev)
ci->wakeup_int = false;
enable_irq(ci->irq);
mod_timer(&ci->timer, jiffies + msecs_to_jiffies(2000));
+ if (ci_otg_is_fsm_mode(ci))
+ ci_otg_fsm_wakeup_by_srp(ci);
}
- if (ci_otg_is_fsm_mode(ci))
- ci_otg_fsm_wakeup_by_srp(ci);
-
return 0;
}
@@ -909,12 +947,35 @@ static int ci_resume(struct device *dev)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
int ret;
+ bool power_lost = false;
+ u32 sample_reg_val;
+
+ /* Check if controller resume from power lost */
+ sample_reg_val = hw_read(ci, OP_ENDPTLISTADDR, ~0);
+ if (sample_reg_val == 0)
+ power_lost = true;
+ else if (sample_reg_val == 0xFFFFFFFF)
+ /* Restore value 0 if it was set for power lost check */
+ hw_write(ci, OP_ENDPTLISTADDR, ~0, 0);
if (device_may_wakeup(dev))
disable_irq_wake(ci->irq);
ret = ci_controller_resume(dev);
- if (!ret && ci->supports_runtime_pm) {
+ if (ret)
+ return ret;
+
+ if (power_lost) {
+ /* re-init for phy */
+ usb_phy_shutdown(ci->transceiver);
+ ci_usb_phy_init(ci);
+ if (ci->roles[ci->role]->restore)
+ ci->roles[ci->role]->restore(ci);
+ disable_irq_nosync(ci->irq);
+ schedule_work(&ci->power_lost_work);
+ }
+
+ if (ci->supports_runtime_pm) {
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index db0a78576331..b14810a940f2 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -321,8 +321,67 @@ static void host_stop(struct ci_hdrc *ci)
if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci))
regulator_disable(ci->platdata->reg_vbus);
}
+ ci->hcd = NULL;
}
+bool ci_hdrc_host_has_device(struct ci_hdrc *ci)
+{
+ struct usb_device *roothub;
+ int i;
+
+ if ((ci->role == CI_ROLE_HOST) && ci->hcd) {
+ roothub = ci->hcd->self.root_hub;
+ for (i = 0; i < roothub->maxchild; ++i) {
+ if (usb_hub_find_child(roothub, (i + 1)))
+ return true;
+ }
+ }
+ return false;
+}
+
+void ci_hdrc_host_save_for_power_lost(struct ci_hdrc *ci)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(ci->hcd);
+
+ /* save EHCI registers */
+ ci->pm_command = ehci_readl(ehci, &ehci->regs->command);
+ ci->pm_command &= ~CMD_RUN;
+ ci->pm_status = ehci_readl(ehci, &ehci->regs->status);
+ ci->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable);
+ ci->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index);
+ ci->pm_segment = ehci_readl(ehci, &ehci->regs->segment);
+ ci->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list);
+ ci->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next);
+ ci->pm_configured_flag =
+ ehci_readl(ehci, &ehci->regs->configured_flag);
+ ci->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]);
+}
+
+void ci_hdrc_host_restore_from_power_lost(struct ci_hdrc *ci)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(ci->hcd);
+ unsigned long flags;
+ u32 tmp;
+
+ hw_device_reset(ci, USBMODE_CM_HC);
+
+ spin_lock_irqsave(&ehci->lock, flags);
+ /* restore EHCI registers */
+ ehci_writel(ehci, ci->pm_portsc, &ehci->regs->port_status[0]);
+ ehci_writel(ehci, ci->pm_command, &ehci->regs->command);
+ ehci_writel(ehci, ci->pm_intr_enable, &ehci->regs->intr_enable);
+ ehci_writel(ehci, ci->pm_frame_index, &ehci->regs->frame_index);
+ ehci_writel(ehci, ci->pm_segment, &ehci->regs->segment);
+ ehci_writel(ehci, ci->pm_frame_list, &ehci->regs->frame_list);
+ ehci_writel(ehci, ci->pm_async_next, &ehci->regs->async_next);
+ ehci_writel(ehci, ci->pm_configured_flag,
+ &ehci->regs->configured_flag);
+
+ tmp = ehci_readl(ehci, &ehci->regs->command);
+ tmp |= CMD_RUN;
+ ehci_writel(ehci, tmp, &ehci->regs->command);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+}
void ci_hdrc_host_destroy(struct ci_hdrc *ci)
{
@@ -344,6 +403,8 @@ int ci_hdrc_host_init(struct ci_hdrc *ci)
rdrv->start = host_start;
rdrv->stop = host_stop;
rdrv->irq = host_irq;
+ rdrv->save = ci_hdrc_host_save_for_power_lost;
+ rdrv->restore = ci_hdrc_host_restore_from_power_lost;
rdrv->name = "host";
ci->roles[CI_ROLE_HOST] = rdrv;
diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h
index 5707bf379bfb..0b01b635e6e4 100644
--- a/drivers/usb/chipidea/host.h
+++ b/drivers/usb/chipidea/host.h
@@ -5,6 +5,7 @@
int ci_hdrc_host_init(struct ci_hdrc *ci);
void ci_hdrc_host_destroy(struct ci_hdrc *ci);
+bool ci_hdrc_host_has_device(struct ci_hdrc *ci);
#else
@@ -18,6 +19,11 @@ static inline void ci_hdrc_host_destroy(struct ci_hdrc *ci)
}
+static inline bool ci_hdrc_host_has_device(struct ci_hdrc *ci)
+{
+ return false;
+}
+
#endif
#endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 70ac5c4028af..1e0389965b83 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -24,6 +24,7 @@
#include "bits.h"
#include "otg.h"
#include "otg_fsm.h"
+#include "host.h"
/**
* hw_read_otgsc returns otgsc register bits value.
@@ -57,6 +58,27 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
return role;
}
+#define CI_VBUS_CONNECT_TIMEOUT_MS 500
+static int ci_is_vbus_glitch(struct ci_hdrc *ci)
+{
+ /*
+ * Handling vbus glitch
+ *
+ * We only need to consider glitch for without usb connection,
+ * With usb connection, we consider it as real disconnection.
+ *
+ * If the vbus can't higher than AVV in timeout value, we think
+ * it is a vbus glitch
+ */
+ if (hw_wait_reg(ci, OP_OTGSC, OTGSC_AVV, OTGSC_AVV,
+ CI_VBUS_CONNECT_TIMEOUT_MS)) {
+ dev_warn(ci->dev, "there is a vbus glitch\n");
+ return 1;
+ }
+
+ return 0;
+}
+
void ci_handle_vbus_connected(struct ci_hdrc *ci)
{
u32 otgsc;
@@ -71,7 +93,7 @@ void ci_handle_vbus_connected(struct ci_hdrc *ci)
otgsc = hw_read(ci, OP_OTGSC, ~0);
- if (otgsc & OTGSC_BSV)
+ if ((otgsc & OTGSC_BSV) && !ci_is_vbus_glitch(ci))
usb_gadget_vbus_connect(&ci->gadget);
}
@@ -87,25 +109,18 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
}
#define CI_VBUS_STABLE_TIMEOUT_MS 5000
-static void ci_handle_id_switch(struct ci_hdrc *ci)
+void ci_handle_id_switch(struct ci_hdrc *ci)
{
enum ci_role role = ci_otg_role(ci);
- struct usb_device *roothub;
- int i;
if (role != ci->role) {
dev_dbg(ci->dev, "switching from %s to %s\n",
ci_role(ci)->name, ci->roles[role]->name);
- if ((ci->role == CI_ROLE_HOST) && ci->hcd) {
- roothub = ci->hcd->self.root_hub;
- for (i = 0; i < roothub->maxchild; ++i) {
- while (usb_hub_find_child(roothub, (i + 1))) {
- enable_irq(ci->irq);
- usleep_range(10000, 15000);
- disable_irq_nosync(ci->irq);
- }
- }
+ while (ci_hdrc_host_has_device(ci)) {
+ enable_irq(ci->irq);
+ usleep_range(10000, 15000);
+ disable_irq_nosync(ci->irq);
}
ci_role_stop(ci);
@@ -115,6 +130,33 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
ci_role_start(ci, role);
}
}
+
+static void ci_handle_vbus_glitch(struct ci_hdrc *ci)
+{
+ bool valid_vbus_change = false;
+
+ if (hw_read_otgsc(ci, OTGSC_BSV)) {
+ if (!ci_is_vbus_glitch(ci)) {
+ if (ci_otg_is_fsm_mode(ci)) {
+ ci->fsm.b_sess_vld = 1;
+ ci->fsm.b_ssend_srp = 0;
+ otg_del_timer(&ci->fsm, B_SSEND_SRP);
+ otg_del_timer(&ci->fsm, B_SRP_FAIL);
+ }
+ valid_vbus_change = true;
+ }
+ } else {
+ if (ci->vbus_active || (ci_otg_is_fsm_mode(ci) &&
+ ci->fsm.b_sess_vld))
+ valid_vbus_change = true;
+ }
+
+ if (valid_vbus_change) {
+ ci->b_sess_valid_event = true;
+ ci_otg_queue_work(ci);
+ }
+}
+
/**
* ci_otg_work - perform otg (vbus/id) event handle
* @work: work struct
@@ -123,6 +165,15 @@ static void ci_otg_work(struct work_struct *work)
{
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
+ if (ci->vbus_glitch_check_event) {
+ ci->vbus_glitch_check_event = false;
+ pm_runtime_get_sync(ci->dev);
+ ci_handle_vbus_glitch(ci);
+ pm_runtime_put_sync(ci->dev);
+ enable_irq(ci->irq);
+ return;
+ }
+
if (ci_otg_is_fsm_mode(ci) && !ci_otg_fsm_work(ci)) {
enable_irq(ci->irq);
return;
diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h
index 05ad33707b72..c42ac78d3035 100644
--- a/drivers/usb/chipidea/otg.h
+++ b/drivers/usb/chipidea/otg.h
@@ -17,6 +17,7 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci);
void ci_hdrc_otg_destroy(struct ci_hdrc *ci);
enum ci_role ci_otg_role(struct ci_hdrc *ci);
void ci_handle_vbus_change(struct ci_hdrc *ci);
+void ci_handle_id_switch(struct ci_hdrc *ci);
void ci_handle_vbus_connected(struct ci_hdrc *ci);
static inline void ci_otg_queue_work(struct ci_hdrc *ci)
{
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index fc9d865d0f25..6faab2a06053 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -29,6 +29,7 @@
#include "bits.h"
#include "otg.h"
#include "otg_fsm.h"
+#include "host.h"
static struct ci_otg_fsm_timer *otg_timer_initializer
(struct ci_hdrc *ci, void (*function)(void *, unsigned long),
@@ -82,6 +83,11 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr,
return count;
}
ci->fsm.a_bus_req = 1;
+ if (ci->transceiver->state == OTG_STATE_A_PERIPHERAL) {
+ ci->gadget.host_request_flag = 1;
+ mutex_unlock(&ci->fsm.lock);
+ return count;
+ }
}
ci_otg_queue_work(ci);
@@ -160,8 +166,14 @@ set_b_bus_req(struct device *dev, struct device_attribute *attr,
mutex_lock(&ci->fsm.lock);
if (buf[0] == '0')
ci->fsm.b_bus_req = 0;
- else if (buf[0] == '1')
+ else if (buf[0] == '1') {
ci->fsm.b_bus_req = 1;
+ if (ci->transceiver->state == OTG_STATE_B_PERIPHERAL) {
+ ci->gadget.host_request_flag = 1;
+ mutex_unlock(&ci->fsm.lock);
+ return count;
+ }
+ }
ci_otg_queue_work(ci);
mutex_unlock(&ci->fsm.lock);
@@ -369,6 +381,14 @@ static void b_data_pulse_end(void *ptr, unsigned long indicator)
ci_otg_queue_work(ci);
}
+static void hnp_polling_timer_work(unsigned long arg)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)arg;
+
+ ci->hnp_polling_req = true;
+ ci_otg_queue_work(ci);
+}
+
/* Initialize timers */
static int ci_otg_init_timers(struct ci_hdrc *ci)
{
@@ -439,9 +459,17 @@ static int ci_otg_init_timers(struct ci_hdrc *ci)
if (ci->fsm_timer->timer_list[B_SESS_VLD] == NULL)
return -ENOMEM;
+ setup_timer(&ci->hnp_polling_timer, hnp_polling_timer_work,
+ (unsigned long)ci);
return 0;
}
+static void ci_otg_add_hnp_polling_timer(struct ci_hdrc *ci)
+{
+ mod_timer(&ci->hnp_polling_timer,
+ jiffies + msecs_to_jiffies(T_HOST_REQ_POLL));
+}
+
/* -------------------------------------------------------------*/
/* Operations that will be called from OTG Finite State Machine */
/* -------------------------------------------------------------*/
@@ -449,8 +477,12 @@ static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
{
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
- if (t < NUM_OTG_FSM_TIMERS)
- ci_otg_add_timer(ci, t);
+ if (t < NUM_OTG_FSM_TIMERS) {
+ if (t == HNP_POLLING)
+ ci_otg_add_hnp_polling_timer(ci);
+ else
+ ci_otg_add_timer(ci, t);
+ }
return;
}
@@ -605,6 +637,14 @@ int ci_otg_fsm_work(struct ci_hdrc *ci)
}
pm_runtime_get_sync(ci->dev);
+ if (ci->hnp_polling_req) {
+ ci->hnp_polling_req = false;
+ if (otg_hnp_polling(&ci->fsm) != HOST_REQUEST_FLAG) {
+ pm_runtime_put_sync(ci->dev);
+ return 0;
+ }
+ }
+
if (otg_statemachine(&ci->fsm)) {
if (ci->transceiver->state == OTG_STATE_A_IDLE) {
/*
@@ -763,13 +803,8 @@ irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci)
}
} else if (otg_int_src & OTGSC_BSVIS) {
hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
- ci->b_sess_valid_event = true;
- if (otgsc & OTGSC_BSV) {
- fsm->b_sess_vld = 1;
- ci_otg_del_timer(ci, B_SSEND_SRP);
- ci_otg_del_timer(ci, B_SRP_FAIL);
- fsm->b_ssend_srp = 0;
- } else {
+ ci->vbus_glitch_check_event = true;
+ if (!(otgsc & OTGSC_BSV) && fsm->b_sess_vld) {
fsm->b_sess_vld = 0;
if (fsm->id)
ci_otg_add_timer(ci, B_SSEND_SRP);
@@ -863,4 +898,41 @@ int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
{
sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group);
+ del_timer_sync(&ci->hnp_polling_timer);
+}
+
+/* Restart OTG fsm if resume from power lost */
+void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci)
+{
+ struct otg_fsm *fsm = &ci->fsm;
+ int id_status = fsm->id;
+
+ /* Update fsm if power lost in peripheral state */
+ if (ci->transceiver->state == OTG_STATE_B_PERIPHERAL) {
+ fsm->b_sess_vld = 0;
+ otg_statemachine(fsm);
+ }
+
+ hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
+ hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE);
+
+ /* Update fsm variables for restart */
+ fsm->id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
+ if (fsm->id) {
+ fsm->b_ssend_srp =
+ hw_read_otgsc(ci, OTGSC_BSV) ? 0 : 1;
+ fsm->b_sess_vld =
+ hw_read_otgsc(ci, OTGSC_BSV) ? 1 : 0;
+ } else if (fsm->id != id_status) {
+ /* ID changes to be 0 */
+ fsm->a_bus_drop = 0;
+ fsm->a_bus_req = 1;
+ ci->id_event = true;
+ }
+
+ if (ci_hdrc_host_has_device(ci) &&
+ !hw_read(ci, OP_PORTSC, PORTSC_CCS))
+ fsm->b_conn = 0;
+
+ ci_otg_fsm_work(ci);
}
diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h
index 94c085f456a9..3399e901b419 100644
--- a/drivers/usb/chipidea/otg_fsm.h
+++ b/drivers/usb/chipidea/otg_fsm.h
@@ -64,6 +64,8 @@
#define TB_SESS_VLD (1000)
+#define T_HOST_REQ_POLL (1500) /* HNP polling interval 1s~2s */
+
enum ci_otg_fsm_timer_index {
/*
* CI specific timers, start from the end
@@ -96,6 +98,7 @@ int ci_otg_fsm_work(struct ci_hdrc *ci);
irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci);
void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci);
void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci);
+void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci);
#else
@@ -124,6 +127,11 @@ static inline void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
}
+static inline void ci_hdrc_otg_fsm_restart(struct ci_hdrc *ci)
+{
+
+}
+
#endif
#endif /* __DRIVERS_USB_CHIPIDEA_OTG_FSM_H */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index abe3da77f123..d84aefde1a79 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -827,7 +827,10 @@ __acquires(hwep->lock)
return -ENOMEM;
req->complete = isr_get_status_complete;
- req->length = 2;
+ if (setup->wIndex == OTG_STS_SELECTOR)
+ req->length = 1;
+ else
+ req->length = 2;
req->buf = kzalloc(req->length, gfp_flags);
if (req->buf == NULL) {
retval = -ENOMEM;
@@ -835,8 +838,16 @@ __acquires(hwep->lock)
}
if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
- /* Assume that device is bus powered for now. */
- *(u16 *)req->buf = ci->remote_wakeup << 1;
+ if ((setup->wIndex == OTG_STS_SELECTOR) &&
+ ci_otg_is_fsm_mode(ci)) {
+ if (ci->gadget.host_request_flag)
+ *(u8 *)req->buf = HOST_REQUEST_FLAG;
+ else
+ *(u8 *)req->buf = 0;
+ } else {
+ /* Assume that device is bus powered for now. */
+ *(u16 *)req->buf = ci->remote_wakeup << 1;
+ }
} else if ((setup->bRequestType & USB_RECIP_MASK) \
== USB_RECIP_ENDPOINT) {
dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
@@ -1044,8 +1055,9 @@ __acquires(ci->lock)
type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
type != (USB_DIR_IN|USB_RECIP_INTERFACE))
goto delegate;
- if (le16_to_cpu(req.wLength) != 2 ||
- le16_to_cpu(req.wValue) != 0)
+ if ((le16_to_cpu(req.wLength) != 2 &&
+ le16_to_cpu(req.wLength) != 1) ||
+ le16_to_cpu(req.wValue) != 0)
break;
err = isr_get_status_response(ci, &req);
break;
@@ -1925,6 +1937,29 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci)
hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS);
}
+static void udc_suspend_for_power_lost(struct ci_hdrc *ci)
+{
+ /*
+ * Set OP_ENDPTLISTADDR to be non-zero for
+ * checking if controller resume from power lost
+ * in non-host mode.
+ */
+ if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0)
+ hw_write(ci, OP_ENDPTLISTADDR, ~0, ~0);
+}
+
+/* Power lost with device mode */
+static void udc_resume_from_power_lost(struct ci_hdrc *ci)
+{
+ /* Force disconnect if power lost with vbus on */
+ if (ci->vbus_active)
+ usb_gadget_vbus_disconnect(&ci->gadget);
+
+ if (ci->is_otg)
+ hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
+ OTGSC_BSVIS | OTGSC_BSVIE);
+}
+
/**
* ci_hdrc_gadget_init - initialize device related bits
* ci: the controller
@@ -1945,6 +1980,8 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
rdrv->start = udc_id_switch_for_device;
rdrv->stop = udc_id_switch_for_host;
rdrv->irq = udc_irq;
+ rdrv->save = udc_suspend_for_power_lost;
+ rdrv->restore = udc_resume_from_power_lost;
rdrv->name = "gadget";
ci->roles[CI_ROLE_GADGET] = rdrv;
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index d263ae438d17..acda7a93a612 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -75,6 +75,8 @@ struct usbmisc_ops {
int (*hsic_set_connect)(struct imx_usbmisc_data *data);
/* It's called during suspend/resume */
int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled);
+ /* It's called when system resume from usb power lost */
+ int (*power_lost_check)(struct imx_usbmisc_data *data);
};
struct imx_usbmisc {
@@ -255,6 +257,24 @@ static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data)
return 0;
}
+static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ val = readl(usbmisc->base + data->index * 4);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ /*
+ * Here use a power on reset value to judge
+ * if the controller experienced a power lost
+ */
+ if (val == 0x30001000)
+ return 1;
+ else
+ return 0;
+}
+
static int usbmisc_imx6q_hsic_set_connect(struct imx_usbmisc_data *data)
{
unsigned long flags;
@@ -358,6 +378,7 @@ static const struct usbmisc_ops imx6sx_usbmisc_ops = {
.set_wakeup = usbmisc_imx6q_set_wakeup,
.hsic_set_connect = usbmisc_imx6q_hsic_set_connect,
.hsic_set_clk = usbmisc_imx6q_hsic_set_clk,
+ .power_lost_check = usbmisc_imx6sx_power_lost_check,
};
int imx_usbmisc_init(struct imx_usbmisc_data *data)
@@ -410,6 +431,16 @@ int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on)
}
EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk);
+int imx_usbmisc_power_lost_check(struct imx_usbmisc_data *data)
+{
+ if (!usbmisc)
+ return -ENODEV;
+ if (!usbmisc->ops->power_lost_check)
+ return 0;
+ return usbmisc->ops->power_lost_check(data);
+}
+EXPORT_SYMBOL_GPL(imx_usbmisc_power_lost_check);
+
static const struct of_device_id usbmisc_imx_dt_ids[] = {
{
.compatible = "fsl,imx25-usbmisc",
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index f51dc5e9a23b..76611f8c589f 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -84,6 +84,8 @@ void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
fsm->b_ase0_brst_tmout = 0;
break;
case OTG_STATE_B_HOST:
+ if (fsm->otg->gadget)
+ fsm->otg->gadget->host_request_flag = 0;
break;
case OTG_STATE_A_IDLE:
fsm->adp_prb = 0;
@@ -98,6 +100,8 @@ void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
break;
case OTG_STATE_A_HOST:
otg_del_timer(fsm, A_WAIT_ENUM);
+ if (fsm->otg->gadget)
+ fsm->otg->gadget->host_request_flag = 0;
break;
case OTG_STATE_A_SUSPEND:
otg_del_timer(fsm, A_AIDL_BDIS);
@@ -169,6 +173,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
otg_set_protocol(fsm, PROTO_HOST);
usb_bus_start_enum(fsm->otg->host,
fsm->otg->host->otg_port);
+ otg_add_timer(fsm, HNP_POLLING);
break;
case OTG_STATE_A_IDLE:
otg_drv_vbus(fsm, 0);
@@ -203,6 +208,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
*/
if (!fsm->a_bus_req || fsm->a_suspend_req_inf)
otg_add_timer(fsm, A_WAIT_ENUM);
+ otg_add_timer(fsm, HNP_POLLING);
break;
case OTG_STATE_A_SUSPEND:
otg_drv_vbus(fsm, 1);
@@ -364,3 +370,60 @@ int otg_statemachine(struct otg_fsm *fsm)
return state_changed;
}
EXPORT_SYMBOL_GPL(otg_statemachine);
+
+/*
+ * Called by host to poll peripheral if it wants to be host
+ * Return value:
+ * - host request flag(1) if the device wants to be host,
+ * - host request flag(0) if the device keeps peripheral role,
+ * - otherwise, error code.
+ */
+int otg_hnp_polling(struct otg_fsm *fsm)
+{
+ struct usb_device *udev;
+ u8 host_req_flag;
+ int retval;
+ enum usb_otg_state state = fsm->otg->phy->state;
+
+ if (state != OTG_STATE_A_HOST && state != OTG_STATE_B_HOST)
+ return -EINVAL;
+
+ udev = usb_hub_find_child(fsm->otg->host->root_hub, 1);
+ if (!udev) {
+ dev_err(fsm->otg->host->controller,
+ "no usb dev connected, can't start HNP polling\n");
+ return -ENODEV;
+ }
+
+ /* Get host request flag from connected USB device */
+ retval = usb_control_msg(udev,
+ usb_rcvctrlpipe(udev, 0),
+ USB_REQ_GET_STATUS,
+ USB_DIR_IN | USB_RECIP_DEVICE,
+ 0,
+ OTG_STS_SELECTOR,
+ &host_req_flag,
+ 1,
+ USB_CTRL_GET_TIMEOUT);
+ if (retval == 1) {
+ if (host_req_flag == HOST_REQUEST_FLAG) {
+ if (state == OTG_STATE_A_HOST)
+ fsm->a_bus_req = 0;
+ else if (state == OTG_STATE_B_HOST)
+ fsm->b_bus_req = 0;
+ retval = HOST_REQUEST_FLAG;
+ } else if (host_req_flag == 0) {
+ /* Continue polling */
+ otg_add_timer(fsm, HNP_POLLING);
+ retval = 0;
+ } else {
+ dev_err(&udev->dev, "host request flag is invalid\n");
+ retval = -EINVAL;
+ }
+ } else {
+ dev_err(&udev->dev, "Get one byte OTG status failed\n");
+ retval = -EIO;
+ }
+ return retval;
+}
+EXPORT_SYMBOL_GPL(otg_hnp_polling);
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 415c88a6ce0e..bf72adb2c906 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -114,7 +114,6 @@ void usb_gadget_set_state(struct usb_gadget *gadget,
enum usb_device_state state)
{
gadget->state = state;
- sysfs_notify(&gadget->dev.kobj, NULL, "state");
schedule_work(&gadget->work);
}
EXPORT_SYMBOL_GPL(usb_gadget_set_state);
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 305a3134bfa9..8555ef3c7d3b 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -40,6 +40,7 @@
#define BM_USBPHY_CTRL_SFTRST BIT(31)
#define BM_USBPHY_CTRL_CLKGATE BIT(30)
+#define BM_USBPHY_CTRL_OTG_ID_VALUE BIT(27)
#define BM_USBPHY_CTRL_ENAUTOSET_USBCLKS BIT(26)
#define BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE BIT(25)
#define BM_USBPHY_CTRL_ENVBUSCHG_WKUP BIT(23)
@@ -129,7 +130,8 @@ static const struct mxs_phy_data imx6sl_phy_data = {
};
static const struct mxs_phy_data imx6sx_phy_data = {
- .flags = MXS_PHY_HAS_ANATOP,
+ .flags = MXS_PHY_HAS_ANATOP |
+ MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
};
static const struct of_device_id mxs_phy_dt_ids[] = {
@@ -221,11 +223,6 @@ static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
return false;
}
-#ifdef CONFIG_USB_OTG_FSM
-static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
-{
-}
-#else
static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
{
void __iomem *base = mxs_phy->phy.io_priv;
@@ -258,6 +255,18 @@ static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
usleep_range(500, 1000);
}
+static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
+{
+ void __iomem *base = mxs_phy->phy.io_priv;
+ u32 phyctrl = readl(base + HW_USBPHY_CTRL);
+
+ if (IS_ENABLED(CONFIG_USB_OTG) &&
+ !(phyctrl & BM_USBPHY_CTRL_OTG_ID_VALUE))
+ return true;
+
+ return false;
+}
+
static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
{
bool vbus_is_on = false;
@@ -272,13 +281,12 @@ static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
- if (on && !vbus_is_on)
+ if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
__mxs_phy_disconnect_line(mxs_phy, true);
else
__mxs_phy_disconnect_line(mxs_phy, false);
}
-#endif
static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
{
@@ -308,7 +316,17 @@ static int mxs_phy_init(struct usb_phy *phy)
static void mxs_phy_shutdown(struct usb_phy *phy)
{
struct mxs_phy *mxs_phy = to_mxs_phy(phy);
-
+ u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
+ BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
+ BM_USBPHY_CTRL_ENIDCHG_WKUP |
+ BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
+ BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
+ BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
+ BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
+ BM_USBPHY_CTRL_ENAUTO_PWRON_PLL;
+
+ writel(value, phy->io_priv + HW_USBPHY_CTRL_CLR);
+ writel(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
writel(BM_USBPHY_CTRL_CLKGATE,
phy->io_priv + HW_USBPHY_CTRL_SET);
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 5e4a26056025..63b072385b82 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -419,6 +419,9 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres;
+ if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 16))
+ var->bits_per_pixel = 32;
+
switch (var->bits_per_pixel) {
case 16:
/* always expect RGB 565 */
@@ -434,11 +437,11 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var,
rgb = def_rgb666;
break;
case STMLCDIF_18BIT:
- if (pixfmt_is_equal(var, def_rgb888))
- rgb = def_rgb888;
- else
+ if (pixfmt_is_equal(var, def_rgb666))
/* 24 bit to 18 bit mapping */
rgb = def_rgb666;
+ else
+ rgb = def_rgb888;
break;
case STMLCDIF_24BIT:
/* real 24 bit */
@@ -664,9 +667,7 @@ static int mxsfb_set_par(struct fb_info *fb_info)
*/
break;
case STMLCDIF_18BIT:
- if (pixfmt_is_equal(&fb_info->var, def_rgb888))
- break;
- else
+ if (pixfmt_is_equal(&fb_info->var, def_rgb666))
/* 24 bit to 18 bit mapping */
ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
* each colour component
diff --git a/include/dt-bindings/clock/imx6sx-clock.h b/include/dt-bindings/clock/imx6sx-clock.h
index 421d8bb76f2f..0e3710cdd5f6 100644
--- a/include/dt-bindings/clock/imx6sx-clock.h
+++ b/include/dt-bindings/clock/imx6sx-clock.h
@@ -251,6 +251,7 @@
#define IMX6SX_CLK_SAI2_IPG 238
#define IMX6SX_CLK_ESAI_IPG 239
#define IMX6SX_CLK_ESAI_MEM 240
-#define IMX6SX_CLK_CLK_END 241
+#define IMX6SX_CLK_OCRAM_ALT_SEL 241
+#define IMX6SX_CLK_CLK_END 242
#endif /* __DT_BINDINGS_CLOCK_IMX6SX_H */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 4e9f36a15033..0c71babde4a7 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -28,6 +28,12 @@
#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */
#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
+/*
+ * Basic mux clk, can't switch parent while there is another basic mux clk
+ * being its child. Otherwise, a glitch might be propagated to downstream
+ * clocks through this child mux.
+ */
+#define CLK_IS_BASIC_MUX BIT(8)
struct clk_hw;
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 08c6877f7a2b..28e99a181b35 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -536,6 +536,7 @@ struct usb_gadget {
unsigned b_hnp_enable:1;
unsigned a_hnp_support:1;
unsigned a_alt_hnp_support:1;
+ unsigned host_request_flag:1;
const char *name;
struct device dev;
unsigned out_epnum;
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h
index b6ba1bfb86f2..d4bf33b1ad6f 100644
--- a/include/linux/usb/otg-fsm.h
+++ b/include/linux/usb/otg-fsm.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
+/* Copyright (C) 2007-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
@@ -40,6 +40,14 @@
#define PROTO_HOST (1)
#define PROTO_GADGET (2)
+#define OTG_STS_SELECTOR 0xF000 /* OTG status selector, according to
+ * OTG and EH 2.0 Charpter 6.2.3
+ * Table:6-4
+ */
+#define HOST_REQUEST_FLAG 1 /* Host request flag, according to
+ * OTG and EH 2.0 Charpter 6.2.3
+ * Table:6-5
+ */
enum otg_fsm_timer {
/* Standard OTG timers */
A_WAIT_VRISE,
@@ -53,6 +61,7 @@ enum otg_fsm_timer {
B_SE0_SRP,
B_SRP_FAIL,
A_WAIT_ENUM,
+ HNP_POLLING,
NUM_OTG_FSM_TIMERS,
};
@@ -239,6 +248,7 @@ static inline int otg_start_gadget(struct otg_fsm *fsm, int on)
return fsm->ops->start_gadget(fsm, on);
}
+int otg_hnp_polling(struct otg_fsm *fsm);
int otg_statemachine(struct otg_fsm *fsm);
#endif /* __LINUX_USB_OTG_FSM_H */
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 8df108966155..868ee2ca547e 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -987,6 +987,15 @@ static bool fsl_spdif_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case REG_SPDIF_SIS:
+ case REG_SPDIF_SRL:
+ case REG_SPDIF_SRR:
+ case REG_SPDIF_SRCSH:
+ case REG_SPDIF_SRCSL:
+ case REG_SPDIF_SRU:
+ case REG_SPDIF_SRQ:
+ case REG_SPDIF_STL:
+ case REG_SPDIF_STR:
+ case REG_SPDIF_SRFM:
return true;
default:
return false;