Merge remote-tracking branch 'fsl-linux-sdk/imx_3.14.y' into imx_3.14.y_android
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 06d8181..715db92 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -160,6 +160,7 @@
imx6dl-sabreauto-ecspi.dtb \
imx6dl-sabreauto-gpmi-weim.dtb \
imx6dl-sabresd.dtb \
+ imx6dl-sabresd-btwifi.dtb \
imx6dl-sabresd-enetirq.dtb \
imx6dl-sabresd-ldo.dtb \
imx6dl-sabresd-pf200.dtb \
@@ -177,19 +178,20 @@
imx6qp-sabreauto-flexcan1.dtb \
imx6qp-sabreauto-gpmi-weim.dtb \
imx6qp-sabresd.dtb \
+ imx6qp-sabresd-btwifi.dtb \
imx6qp-sabresd-ldo.dtb \
- imx6qp-sabresd-uart.dtb \
+ imx6qp-sabresd-hdcp.dtb \
imx6q-sabrelite.dtb \
imx6q-sabresd.dtb \
- imx6q-sabresd-ldo.dtb \
+ imx6q-sabresd-btwifi.dtb \
imx6q-sabresd-enetirq.dtb \
- imx6q-sabresd-uart.dtb \
- imx6q-sabresd-hdcp.dtb \
imx6q-sabresd-ldo.dtb \
+ imx6q-sabresd-hdcp.dtb \
imx6q-sbc6x.dtb \
imx6q-udoo.dtb \
imx6q-wandboard.dtb \
imx6sl-evk.dtb \
+ imx6sl-evk-btwifi.dtb \
imx6sl-evk-csi.dtb \
imx6sl-evk-ldo.dtb \
imx6sl-evk-pf200.dtb \
@@ -211,6 +213,7 @@
imx6sx-19x19-arm2-lcdif1.dtb \
imx6sx-19x19-arm2-gpmi-weim.dtb \
imx6sx-sdb.dtb \
+ imx6sx-sdb-btwifi.dtb \
imx6sx-sdb-ldo.dtb \
imx6sx-sdb-mqs.dtb \
imx6sx-sdb-reva.dtb \
@@ -230,6 +233,7 @@
imx6ul-14x14-ddr3-arm2-spdif.dtb \
imx6ul-14x14-ddr3-arm2-wm8958.dtb \
imx6ul-14x14-evk.dtb \
+ imx6ul-14x14-evk-btwifi.dtb \
imx6ul-14x14-evk-csi.dtb \
imx6ul-9x9-evk.dtb \
imx6ul-9x9-evk-ldo.dtb \
diff --git a/arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts b/arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts
new file mode 100644
index 0000000..814c935
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sabresd-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2015 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6dl-sabresd.dts"
+#include "imx6qdl-sabresd-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6q-sabresd-btwifi.dts b/arch/arm/boot/dts/imx6q-sabresd-btwifi.dts
new file mode 100644
index 0000000..af65f3a
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sabresd-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2015 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6q-sabresd.dts"
+#include "imx6qdl-sabresd-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6q-sabresd-uart.dts b/arch/arm/boot/dts/imx6q-sabresd-uart.dts
deleted file mode 100644
index 6743731..0000000
--- a/arch/arm/boot/dts/imx6q-sabresd-uart.dts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "imx6q-sabresd.dts"
-
-/ {
- leds {
- compatible = "gpio-leds";
- status = "disabled";
- };
-};
-
-&uart5 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart5_1>;
- fsl,uart-has-rtscts;
- status = "okay";
- /* for DTE mode, add below change */
- /* fsl,dte-mode; */
- /* pinctrl-0 = <&pinctrl_uart5dte_1>; */
-};
-
-&ecspi1 {
- status = "disabled";
-};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi
new file mode 100644
index 0000000..d4c0569
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sabresd-btwifi.dtsi
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into SD2
+ * slot using Murata i.MX InterConnect Ver 2.0 Adapter & connecting Bluetooth
+ * UART & control signals via ribbon cable.
+ * This configuration supports both WLAN and Bluetooth.
+ * WL_REG_ON/BT_REG_ON/WL_HOST_WAKE are connected via ribbon cable (J13 connector
+ * on board).
+ * ==> Hardware modification is required. Refer to schematic.
+ */
+
+/ {
+ leds {
+ compatible = "gpio-leds";
+ status = "disabled";
+ };
+
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio4 7 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&ecspi1 {
+ status = "disabled";
+};
+
+&iomuxc {
+ imx6qdl-sabresd-murata-v2 {
+ /* add MUXing entry for SD2 4-bit interface and configure control pins */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x13069 /* WL_REG_ON */
+ >;
+ };
+ };
+};
+
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5_1>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+ /* for DTE mode, add below change */
+ /* fsl,dte-mode; */
+ /* pinctrl-0 = <&pinctrl_uart5dte_1>; */
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ wifi-host;
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts b/arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts
new file mode 100644
index 0000000..38d39ca
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2015 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6qp-sabresd.dts"
+#include "imx6qdl-sabresd-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts b/arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts
new file mode 100644
index 0000000..8dce5ca
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-sabresd-hdcp.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2015 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 "imx6qp-sabresd.dts"
+
+&hdmi_video {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+ fsl,hdcp;
+};
+
+&i2c2 {
+ status = "disable";
+};
diff --git a/arch/arm/boot/dts/imx6qp-sabresd-uart.dts b/arch/arm/boot/dts/imx6qp-sabresd-uart.dts
deleted file mode 100644
index d855aae..0000000
--- a/arch/arm/boot/dts/imx6qp-sabresd-uart.dts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "imx6qp-sabresd.dts"
-
-/ {
- leds {
- compatible = "gpio-leds";
- status = "disabled";
- };
-};
-
-&ecspi1 {
- status = "disabled";
-};
-
-&uart5 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart5_1>;
- fsl,uart-has-rtscts;
- status = "okay";
- /* for DTE mode, add below change */
- /* fsl,dte-mode; */
- /* pinctrl-0 = <&pinctrl_uart5dte_1>; */
-};
diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts
index 0fb94e5..a4f066c 100644
--- a/arch/arm/boot/dts/imx6qp-sabresd.dts
+++ b/arch/arm/boot/dts/imx6qp-sabresd.dts
@@ -102,3 +102,7 @@
memory-region = <&memory>;
status = "okay";
};
+
+&sata {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6sl-evk-btwifi.dts b/arch/arm/boot/dts/imx6sl-evk-btwifi.dts
new file mode 100644
index 0000000..86924c7
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-evk-btwifi.dts
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into SD1
+ * slot using Murata i.MX InterConnect Ver 1.0 Adapter AND wiring in control
+ * signals with SD Card Extender on SD3 slot.
+ * Bluetooth UART connect via SD1 EMMC/MMC Plus pinout.
+ * WL_REG_ON/BT_REG_ON/WL_HOST_WAKE are connected from SD Card Extender on SD3
+ * slot.
+ */
+#include "imx6sl-evk.dts"
+
+/ {
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio5 16 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&iomuxc {
+ imx6sl-evk-murata-v1_sdext {
+ /* Only MUX SD1_DAT0..3 lines so UART4 can be MUXed on higher data lines. */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ MX6SL_PAD_SD3_DAT2__GPIO5_IO16 0x13069 /* WL_REG_ON */
+ >;
+ };
+
+ pinctrl_usdhc3_1: usdhc3grp-1 {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ >;
+ };
+ };
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v;
+ wifi-host;
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3_1>;
+ bus-width = <1>;
+ no-1-8-v;
+};
diff --git a/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
new file mode 100644
index 0000000..575ed3c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into SD3
+ * slot using Murata i.MX InterConnect Ver 1.0 Adapter AND SD Card Extender on
+ * SD2 slot. Bluetooth UART connects via SD3 EMMC/MMC Plus pinout.
+ * WL_REG_ON/BT_REG_ON/WL_HOST_WAKE connect via SD Card Extender.
+ */
+
+#include "imx6sx-sdb.dts"
+
+/ {
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio6 10 0>;
+ startup-delay-us = <100>;
+ regulator-always-on;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&iomuxc {
+ imx6sx-sdb-murata-v1_sdext {
+ pinctrl_bt: btgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_DATA3__GPIO6_IO_11 0x13069 /* BT_REG_ON */
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_DATA4__UART3_RX 0x1b0b1
+ MX6SX_PAD_SD3_DATA5__UART3_TX 0x1b0b1
+ MX6SX_PAD_SD3_DATA7__UART3_CTS_B 0x1b0b1
+ MX6SX_PAD_SD3_DATA6__UART3_RTS_B 0x1b0b1
+ >;
+ };
+
+ /* change MUXing on SD2 slot for control signals. */
+ pinctrl_usdhc2_1: usdhc2grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ >;
+ };
+
+ /* Murata change SD3 to 4-bit SDIO only; use upper 4-bits for UART. */
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17069
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10071
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17069
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17069
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17069
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17069
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
+ /* Murata Module control signals */
+ MX6SX_PAD_SD2_DATA2__GPIO6_IO_10 0x13069 /* WL_REG_ON */
+ >;
+ };
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3
+ &pinctrl_bt>;
+ fsl,uart-has-rtscts;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2_1>;
+ bus-width = <1>;
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi>;
+ bus-width = <4>;
+ no-1-8-v; /* force 3.3V VIO */
+ wifi-host; /* pull in card detect mechanism for BCMDHD driver */
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts
new file mode 100644
index 0000000..97a21dc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into Slot
+ * SD1 and using Murata i.MX InterConnect Ver 2.0 Adapter. Bluetooth UART &
+ * control signals are connected via ribbon cable (J1701 connector).
+ */
+
+#include "imx6ul-14x14-evk.dts"
+
+/ {
+ regulators {
+ wlreg_on: fixedregulator@100 {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "wlreg_on";
+ gpio = <&gpio5 1 0>;
+ startup-delay-us = <100>;
+ enable-active-high;
+ };
+ };
+
+ bcmdhd_wlan_0: bcmdhd_wlan@0 {
+ compatible = "android,bcmdhd_wlan";
+ wlreg_on-supply = <&wlreg_on>;
+ };
+};
+
+&iomuxc {
+ imx6ul-evk-murata-v2 {
+ pinctrl_wifi: wifigrp {
+ fsl,pins = <
+ MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x03029
+ >;
+ };
+ };
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_wifi>;
+ no-1-8-v;
+ wifi-host; /* add hook for SD card detect mechanism for BCMDHD driver */
+};
diff --git a/arch/arm/configs/imx_v7_mfg_defconfig b/arch/arm/configs/imx_v7_mfg_defconfig
index 3093eec..2a88710 100644
--- a/arch/arm/configs/imx_v7_mfg_defconfig
+++ b/arch/arm/configs/imx_v7_mfg_defconfig
@@ -302,6 +302,7 @@
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
index 9770a5f..a5e0412 100644
--- a/arch/arm/mach-imx/anatop.c
+++ b/arch/arm/mach-imx/anatop.c
@@ -45,6 +45,8 @@
#define BM_ANADIG_REG_CORE_REG2 (0x1f << 18)
#define BP_ANADIG_REG_CORE_REG2 (18)
#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000
+#define BM_ANADIG_ANA_MISC0_V2_STOP_MODE_CONFIG 0x800
+#define BM_ANADIG_ANA_MISC0_V3_STOP_MODE_CONFIG 0xc00
#define BM_ANADIG_ANA_MISC2_REG1_STEP_TIME (0x3 << 26)
#define BP_ANADIG_ANA_MISC2_REG1_STEP_TIME (26)
/* Below MISC0_DISCON_HIGH_SNVS is only for i.MX6SL */
@@ -61,14 +63,20 @@
static void imx_anatop_enable_weak2p5(bool enable)
{
- u32 reg, val;
+ u32 reg, val, mask;
regmap_read(anatop, ANADIG_ANA_MISC0, &val);
+ if (cpu_is_imx6sx() || cpu_is_imx6ul())
+ mask = BM_ANADIG_ANA_MISC0_V3_STOP_MODE_CONFIG;
+ else if (cpu_is_imx6sl())
+ mask = BM_ANADIG_ANA_MISC0_V2_STOP_MODE_CONFIG;
+ else
+ mask = BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG;
+
/* can only be enabled when stop_mode_config is clear. */
reg = ANADIG_REG_2P5;
- reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ?
- REG_SET : REG_CLR;
+ reg += (enable && (val & mask) == 0) ? REG_SET : REG_CLR;
regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG);
}
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index ada6f20..e64384e 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -812,6 +812,9 @@
imx_clk_set_parent(clk[IMX6QDL_CLK_IPU2_SEL], clk[IMX6QDL_CLK_MMDC_CH0_AXI]);
}
+ imx_clk_set_parent(clk[IMX6QDL_CLK_AXI_ALT_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
+ imx_clk_set_parent(clk[IMX6QDL_CLK_AXI_SEL], clk[IMX6QDL_CLK_AXI_ALT_SEL]);
+
/*
* The gpmi needs 100MHz frequency in the EDO/Sync mode,
* We can not get the 100MHz from the pll2_pfd0_352m.
@@ -868,8 +871,8 @@
if (IS_ENABLED(CONFIG_PCI_IMX6))
imx_clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF]);
- /* set eim_slow to 132Mhz */
- imx_clk_set_rate(clk[IMX6QDL_CLK_EIM_SLOW], 132000000);
+ /* set eim_slow to 135Mhz */
+ imx_clk_set_rate(clk[IMX6QDL_CLK_EIM_SLOW], 135000000);
/*
* Enable clocks only after both parent and rate are all initialized
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 8a2cd5c..69422dc 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -648,7 +648,7 @@
* which is present on mx6q, and not on mx53,
* we should use sg_tablesize = 1 for reliable operation
*/
- if (imxpriv->type == AHCI_IMX6Q) {
+ if (imxpriv->type == AHCI_IMX6Q || imxpriv->type == AHCI_IMX6QP) {
dma_addr_t dma;
ahci_platform_sht.sg_tablesize = 1;
diff --git a/drivers/cpufreq/imx7-cpufreq.c b/drivers/cpufreq/imx7-cpufreq.c
index 28d4cdd..a620cf0 100644
--- a/drivers/cpufreq/imx7-cpufreq.c
+++ b/drivers/cpufreq/imx7-cpufreq.c
@@ -181,7 +181,7 @@
pll_arm = devm_clk_get(cpu_dev, "pll_arm");
pll_sys_main = devm_clk_get(cpu_dev, "pll_sys_main");
- if (IS_ERR(arm_clk) | IS_ERR(arm_src) | IS_ERR(pll_arm) |
+ if (IS_ERR(arm_clk) || IS_ERR(arm_src) || IS_ERR(pll_arm) ||
IS_ERR(pll_sys_main)) {
dev_err(cpu_dev, "failed to get clocks\n");
ret = -ENOENT;
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index be1c36e..d89381c 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -353,6 +353,7 @@
struct gen_pool *iram_pool;
u32 spba_start_addr;
u32 spba_end_addr;
+ bool suspend_off;
};
static struct sdma_driver_data sdma_imx31 = {
@@ -984,7 +985,7 @@
/*
* restore back context since context may loss if mega/fast OFF
*/
- if (!readl_relaxed(sdma->regs + SDMA_H_C0PTR)) {
+ if (sdma->suspend_off) {
if (sdma_load_context(sdmac)) {
dev_err(sdmac->sdma->dev, "context load failed.\n");
return -EINVAL;
@@ -2175,6 +2176,8 @@
struct sdma_engine *sdma = platform_get_drvdata(pdev);
int i;
+ sdma->suspend_off = false;
+
/* Do nothing if not i.MX6SX or i.MX7D*/
if (sdma->drvdata != &sdma_imx6sx && sdma->drvdata != &sdma_imx7d)
return 0;
@@ -2219,6 +2222,9 @@
clk_disable(sdma->clk_ahb);
return 0;
}
+
+ sdma->suspend_off = true;
+
/* restore regs and load firmware */
for (i = 0; i < MXC_SDMA_SAVED_REG_NUM; i++) {
/*
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index a33eb04..e6fab94 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -672,7 +672,6 @@
static const struct dev_pm_ops wm8994_pm_ops = {
SET_RUNTIME_PM_OPS(wm8994_suspend, wm8994_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume)
};
static struct i2c_driver wm8994_i2c_driver = {
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 9fa6ec4..5e8d55f 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -22,12 +22,16 @@
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
+#include <linux/debugfs.h>
#include "gpmi-nand.h"
#include "gpmi-regs.h"
#include "bch-regs.h"
+/* export the bch geometry to dbgfs */
+static struct debugfs_blob_wrapper dbg_bch_geo;
+
static struct timing_threshod timing_default_threshold = {
.max_data_setup_cycles = (BM_GPMI_TIMING0_DATA_SETUP >>
BP_GPMI_TIMING0_DATA_SETUP),
@@ -229,7 +233,8 @@
"ECC Strength : %u\n"
"Page Size in Bytes : %u\n"
"Metadata Size in Bytes : %u\n"
- "ECC Chunk Size in Bytes: %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
"ECC Chunk Count : %u\n"
"Payload Size in Bytes : %u\n"
"Auxiliary Size in Bytes: %u\n"
@@ -240,7 +245,8 @@
geo->ecc_strength,
geo->page_size,
geo->metadata_size,
- geo->ecc_chunk_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
geo->ecc_chunk_count,
geo->payload_size,
geo->auxiliary_size,
@@ -255,23 +261,40 @@
struct resources *r = &this->resources;
struct bch_geometry *bch_geo = &this->bch_geometry;
unsigned int block_count;
- unsigned int block_size;
+ unsigned int block0_size;
+ unsigned int blockn_size;
unsigned int metadata_size;
unsigned int ecc_strength;
unsigned int page_size;
unsigned int gf_len;
int ret;
+ struct dentry *dbg_root;
if (common_nfc_set_geometry(this))
return !0;
block_count = bch_geo->ecc_chunk_count - 1;
- block_size = bch_geo->ecc_chunk_size;
+ block0_size = bch_geo->ecc_chunk0_size;
+ blockn_size = bch_geo->ecc_chunkn_size;
metadata_size = bch_geo->metadata_size;
ecc_strength = bch_geo->ecc_strength >> 1;
page_size = bch_geo->page_size;
gf_len = bch_geo->gf_len;
+ dbg_root = debugfs_create_dir("gpmi-nand", NULL);
+ if (!dbg_root) {
+ dev_err(this->dev, "failed to create debug directory\n");
+ return -EINVAL;
+ }
+
+ dbg_bch_geo.data = (void *)bch_geo;
+ dbg_bch_geo.size = sizeof(struct bch_geometry);
+ if (!debugfs_create_blob("bch_geometry", S_IRUGO,
+ dbg_root, &dbg_bch_geo)) {
+ dev_err(this->dev, "failed to create debug bch geometry\n");
+ return -EINVAL;
+ }
+
ret = pm_runtime_get_sync(this->dev);
if (ret < 0) {
dev_err(this->dev, "Failed to enable clock\n");
@@ -295,18 +318,18 @@
| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block0_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT0);
writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(blockn_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT1);
- /* Set erase threshold to gf/2 for mx6ul, mx6qp and mx7 */
+ /* Set erase threshold to ecc strength for mx6ul, mx6qp and mx7 */
if (GPMI_IS_MX6QP(this) || GPMI_IS_MX7(this) || GPMI_IS_MX6UL(this))
- writel(BF_BCH_MODE_ERASE_THRESHOLD(gf_len/2),
+ writel(BF_BCH_MODE_ERASE_THRESHOLD(ecc_strength),
r->bch_regs + HW_BCH_MODE);
/* Set *all* chip selects to use layout 0. */
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 21f3c55..7a0ac23 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -152,6 +152,36 @@
return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
}
+static inline bool bbm_in_data_chunk(struct gpmi_nand_data *this,
+ unsigned int *chunk_num)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->mtd;
+ unsigned int i, j;
+
+ if (geo->ecc_chunk0_size != geo->ecc_chunk0_size) {
+ dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
+ return false;
+ }
+
+ i = (mtd->writesize * 8 - geo->metadata_size * 8) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8);
+
+ j = (mtd->writesize * 8 - geo->metadata_size * 8) -
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) * i;
+
+ if (j < geo->ecc_chunkn_size * 8) {
+ *chunk_num = i+1;
+ dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
+ geo->ecc_strength, *chunk_num);
+ return true;
+ }
+
+ return false;
+}
+
/*
* If we can get the ECC information from the nand chip, we do not
* need to calculate them ourselves.
@@ -182,15 +212,14 @@
chip->ecc_strength_ds, chip->ecc_step_ds);
return -EINVAL;
}
- geo->ecc_chunk_size = chip->ecc_step_ds;
+ geo->ecc_chunk0_size = chip->ecc_step_ds;
+ geo->ecc_chunkn_size = chip->ecc_step_ds;
geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
if (!gpmi_check_ecc(this))
return -EINVAL;
- /* set the ecc strength to the maximum ecc controller can support */
- geo->ecc_strength = this->devdata->bch_max_ecc_strength;
/* Keep the C >= O */
- if (geo->ecc_chunk_size < mtd->oobsize) {
+ if (geo->ecc_chunkn_size < mtd->oobsize) {
dev_err(this->dev,
"unsupported nand chip. ecc size: %d, oob size : %d\n",
chip->ecc_step_ds, mtd->oobsize);
@@ -200,7 +229,7 @@
/* The default value, see comment in the legacy_set_geometry(). */
geo->metadata_size = 10;
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/*
* Now, the NAND chip with 2K page(data chunk is 512byte) shows below:
@@ -278,6 +307,131 @@
return 0;
}
+static int set_geometry_for_large_oob(struct gpmi_nand_data *this)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->mtd;
+ struct nand_chip *chip = mtd->priv;
+ unsigned int block_mark_bit_offset;
+ unsigned int max_ecc;
+ unsigned int bbm_chunk;
+ unsigned int i;
+
+
+ /* sanity check for the minimum ecc nand required */
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+ return -EINVAL;
+ geo->ecc_strength = chip->ecc_strength_ds;
+
+ /* check if platform can support this nand */
+ if (!gpmi_check_ecc(this)) {
+ dev_err(this->dev,
+ "unsupported NAND chip,\
+ minimum ecc required %d\n"
+ , geo->ecc_strength);
+ return -EINVAL;
+ }
+
+ /* calculate the maximum ecc platform can support*/
+ geo->metadata_size = 10;
+ geo->gf_len = 14;
+ geo->ecc_chunk0_size = 1024;
+ geo->ecc_chunkn_size = 1024;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
+ max_ecc = min(get_ecc_strength(this),
+ this->devdata->bch_max_ecc_strength);
+
+ /* search a supported ecc strength that makes bbm */
+ /* located in data chunk */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ while (!(geo->ecc_strength > max_ecc)) {
+ if (bbm_in_data_chunk(this, &bbm_chunk))
+ goto geo_setting;
+ geo->ecc_strength += 2;
+ }
+
+ /* if none of them works, keep using the minimum ecc */
+ /* nand required but changing ecc page layout */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ /* add extra ecc for meta data */
+ geo->ecc_chunk0_size = 0;
+ geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
+ geo->ecc_for_meta = 1;
+ /* check if oob can afford this extra ecc chunk */
+ if (mtd->oobsize * 8 < geo->metadata_size * 8 +
+ geo->gf_len * geo->ecc_strength
+ * geo->ecc_chunk_count) {
+ dev_err(this->dev, "unsupported NAND chip with new layout\n");
+ return -EINVAL;
+ }
+
+ /* calculate in which chunk bbm located */
+ bbm_chunk = (mtd->writesize * 8 - geo->metadata_size * 8 -
+ geo->gf_len * geo->ecc_strength) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) + 1;
+
+geo_setting:
+
+ geo->page_size = mtd->writesize + mtd->oobsize;
+ geo->payload_size = mtd->writesize;
+
+ /*
+ * The auxiliary buffer contains the metadata and the ECC status. The
+ * metadata is padded to the nearest 32-bit boundary. The ECC status
+ * contains one byte for every ECC chunk, and is also padded to the
+ * nearest 32-bit boundary.
+ */
+ geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4);
+ geo->auxiliary_size = ALIGN(geo->metadata_size, 4)
+ + ALIGN(geo->ecc_chunk_count, 4);
+
+ if (!this->swap_block_mark)
+ return 0;
+
+ /* calculate the number of ecc chunk behind the bbm */
+ i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
+
+ block_mark_bit_offset = mtd->writesize * 8 -
+ (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
+ + geo->metadata_size * 8);
+
+ geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+ geo->block_mark_bit_offset = block_mark_bit_offset % 8;
+
+ dev_dbg(this->dev, "BCH Geometry :\n"
+ "GF length : %u\n"
+ "ECC Strength : %u\n"
+ "Page Size in Bytes : %u\n"
+ "Metadata Size in Bytes : %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
+ "ECC Chunk Count : %u\n"
+ "Payload Size in Bytes : %u\n"
+ "Auxiliary Size in Bytes: %u\n"
+ "Auxiliary Status Offset: %u\n"
+ "Block Mark Byte Offset : %u\n"
+ "Block Mark Bit Offset : %u\n"
+ "Block Mark in chunk : %u\n"
+ "Ecc for Meta data : %u\n",
+ geo->gf_len,
+ geo->ecc_strength,
+ geo->page_size,
+ geo->metadata_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
+ geo->ecc_chunk_count,
+ geo->payload_size,
+ geo->auxiliary_size,
+ geo->auxiliary_status_offset,
+ geo->block_mark_byte_offset,
+ geo->block_mark_bit_offset,
+ bbm_chunk,
+ geo->ecc_for_meta);
+
+ return 0;
+}
+
static int legacy_set_geometry(struct gpmi_nand_data *this)
{
struct bch_geometry *geo = &this->bch_geometry;
@@ -297,13 +451,15 @@
geo->gf_len = 13;
/* The default for chunk size. */
- geo->ecc_chunk_size = 512;
- while (geo->ecc_chunk_size < mtd->oobsize) {
- geo->ecc_chunk_size *= 2; /* keep C >= O */
+ geo->ecc_chunk0_size = 512;
+ geo->ecc_chunkn_size = 512;
+ while (geo->ecc_chunkn_size < mtd->oobsize) {
+ geo->ecc_chunk0_size *= 2; /* keep C >= O */
+ geo->ecc_chunkn_size *= 2; /* keep C >= O */
geo->gf_len = 14;
}
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/* We use the same ECC strength for all chunks. */
geo->ecc_strength = get_ecc_strength(this);
@@ -393,15 +549,24 @@
int common_nfc_set_geometry(struct gpmi_nand_data *this)
{
+ struct mtd_info *mtd = &this->mtd;
+ struct nand_chip *chip = mtd->priv;
- if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
- || legacy_set_geometry(this))
- /* To align with the kobs-ng, use the maximum ecc strength */
- /* controller can support, rather than the minimum ecc nand */
- /* spec required. */
- return set_geometry_by_ecc_info(this);
+ if (chip->ecc_strength_ds > this->devdata->bch_max_ecc_strength) {
+ dev_err(this->dev,
+ "unsupported NAND chip, minimum ecc required %d\n"
+ , chip->ecc_strength_ds);
+ return -EINVAL;
+ }
- return 0;
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
+ !(mtd->oobsize > 1024))
+ return legacy_set_geometry(this);
+
+ if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
+ return set_geometry_for_large_oob(this);
+
+ return set_geometry_by_ecc_info(this);
}
struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
@@ -1035,6 +1200,61 @@
p[1] = (p[1] & mask) | (from_oob >> (8 - bit));
}
+static bool gpmi_erased_check(struct gpmi_nand_data *this,
+ unsigned char *data, unsigned int chunk, int page,
+ unsigned int *max_bitflips)
+{
+ struct nand_chip *chip = &this->nand;
+ struct mtd_info *mtd = &this->mtd;
+ struct bch_geometry *geo = &this->bch_geometry;
+ int base = geo->ecc_chunkn_size * chunk;
+ unsigned int flip_bits = 0, flip_bits_noecc = 0;
+ uint64_t *buf = (uint64_t *)this->data_buffer_dma;
+ unsigned int threshold;
+ int i;
+
+ threshold = geo->gf_len / 2;
+ if (threshold > geo->ecc_strength)
+ threshold = geo->ecc_strength;
+
+ /* Count bitflips */
+ for (i = 0; i < geo->ecc_chunkn_size; i++) {
+ flip_bits += hweight8(~data[base + i]);
+ if (flip_bits > threshold)
+ return false;
+ }
+
+ /*
+ * Read out the whole page with ECC disabled, and check it again,
+ * This is more strict then just read out a chunk, and it makes
+ * the code more simple.
+ */
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+ chip->read_buf(mtd, (uint8_t *)buf, mtd->writesize);
+
+ /* Count the bitflips for the no ECC buffer */
+ for (i = 0; i < mtd->writesize / 8; i++) {
+ flip_bits_noecc += hweight64(~buf[i]);
+ if (flip_bits_noecc > threshold)
+ return false;
+ }
+
+ /* Tell the upper layer the bitflips we corrected. */
+ mtd->ecc_stats.corrected += flip_bits;
+ *max_bitflips = max_t(unsigned int, *max_bitflips, flip_bits);
+
+ /*
+ * The geo->payload_size maybe not equal to the page size
+ * when the Subpage-Read is enabled.
+ */
+ memset(data, 0xff, geo->payload_size);
+
+ dev_dbg(this->dev, "The page(%d) is an erased page(%d,%d,%d,%d).\n",
+ page, chunk, threshold, flip_bits, flip_bits_noecc);
+
+ return true;
+}
+
static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
@@ -1094,6 +1314,9 @@
}
if (*status == STATUS_UNCORRECTABLE) {
+ if (gpmi_erased_check(this, payload_virt, i,
+ page, &max_bitflips))
+ break;
mtd->ecc_stats.failed++;
continue;
}
@@ -1164,9 +1387,23 @@
return gpmi_ecc_read_page(mtd, chip, buf, 0, page);
}
+ /*
+ * if there is an ECC dedicate for meta:
+ * - need to add an extra ECC size when calculating col and page_size,
+ * if the meta size is NOT zero.
+ *
+ * - chunk0 size need to set to the same size as other chunks,
+ * if the meta size is zero.
+ */
+
meta = geo->metadata_size;
if (first) {
- col = meta + (size + ecc_parity_size) * first;
+ if (geo->ecc_for_meta)
+ col = meta + ecc_parity_size
+ + (size + ecc_parity_size) * first;
+ else
+ col = meta + (size + ecc_parity_size) * first;
+
chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
meta = 0;
@@ -1179,21 +1416,37 @@
/* change the BCH registers and bch_geometry{} */
n = last - first + 1;
- page_size = meta + (size + ecc_parity_size) * n;
+
+ if (geo->ecc_for_meta && meta)
+ page_size = meta + ecc_parity_size
+ + (size + ecc_parity_size) * n;
+ else
+ page_size = meta + (size + ecc_parity_size) * n;
r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS |
BM_BCH_FLASH0LAYOUT0_META_SIZE);
- r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1)
+ r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(
+ (geo->ecc_for_meta && meta) ? n : n - 1)
| BF_BCH_FLASH0LAYOUT0_META_SIZE(meta);
+
+ /* set chunk0 size if meta size is 0 */
+ if (!meta) {
+ if (GPMI_IS_MX6(this) || GPMI_IS_MX7(this))
+ r1_new &= ~MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ else
+ r1_new &= ~BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ r1_new |= BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(size, this);
+ }
writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0);
r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE;
r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size);
writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1);
- geo->ecc_chunk_count = n;
+ geo->ecc_chunk_count = (geo->ecc_for_meta && meta) ? n + 1 : n;
geo->payload_size = n * size;
geo->page_size = page_size;
+ geo->metadata_size = meta;
geo->auxiliary_status_offset = ALIGN(meta, 4);
dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n",
@@ -1724,7 +1977,7 @@
ecc->read_oob = gpmi_ecc_read_oob;
ecc->write_oob = gpmi_ecc_write_oob;
ecc->mode = NAND_ECC_HW;
- ecc->size = bch_geo->ecc_chunk_size;
+ ecc->size = bch_geo->ecc_chunkn_size;
ecc->strength = bch_geo->ecc_strength;
ecc->layout = &gpmi_hw_ecclayout;
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index 5b0e141..7ee51fd 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -39,9 +39,9 @@
* @page_size: The size, in bytes, of a physical page, including
* both data and OOB.
* @metadata_size: The size, in bytes, of the metadata.
- * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note
- * the first chunk in the page includes both data and
- * metadata, so it's a bit larger than this value.
+ * @ecc_chunk0_size: The size, in bytes, of a first ECC chunk.
+ * @ecc_chunkn_size: The size, in bytes, of a single ECC chunk after
+ * the first chunk in the page.
* @ecc_chunk_count: The number of ECC chunks in the page,
* @payload_size: The size, in bytes, of the payload buffer.
* @auxiliary_size: The size, in bytes, of the auxiliary buffer.
@@ -51,19 +51,23 @@
* which the underlying physical block mark appears.
* @block_mark_bit_offset: The bit offset into the ECC-based page view at
* which the underlying physical block mark appears.
+ * @ecc_for_meta: The flag to indicate if there is a dedicate ecc
+ * for meta.
*/
struct bch_geometry {
unsigned int gf_len;
unsigned int ecc_strength;
unsigned int page_size;
unsigned int metadata_size;
- unsigned int ecc_chunk_size;
+ unsigned int ecc_chunk0_size;
+ unsigned int ecc_chunkn_size;
unsigned int ecc_chunk_count;
unsigned int payload_size;
unsigned int auxiliary_size;
unsigned int auxiliary_status_offset;
unsigned int block_mark_byte_offset;
unsigned int block_mark_bit_offset;
+ unsigned int ecc_for_meta; /* ECC for meta data */
};
/**
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 49f81ca..d7ea954 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -2900,6 +2900,7 @@
}
phy_disconnect(fep->phy_dev);
+ fep->phy_dev = NULL;
fec_enet_clk_enable(ndev, false);
pm_qos_remove_request(&ndev->pm_qos_req);
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index cb19c83..ede0750 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -267,7 +267,11 @@
value = readl(snvs_base + SNVS_LPCR);
/* set TOP and DP_EN bit */
writel(value | 0x60, snvs_base + SNVS_LPCR);
- clk_disable(clk_snvs);
+ /*
+ * Do not turn off snvs clock otherwise PMIC_ON_REQ can't be pulled
+ * high by press ONOFF. This is design limitation.
+ */
+ /* clk_disable(clk_snvs); */
}
static int snvs_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index f1390168..b69ee35 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -216,7 +216,6 @@
struct regulator *reg_lcd;
bool wait4vsync;
struct completion vsync_complete;
- ktime_t vsync_nf_timestamp;
struct completion flip_complete;
int cur_blank;
int restore_blank;
@@ -413,7 +412,6 @@
writel(CTRL1_VSYNC_EDGE_IRQ_EN,
host->base + LCDC_CTRL1 + REG_CLR);
host->wait4vsync = 0;
- host->vsync_nf_timestamp = ktime_get();
complete(&host->vsync_complete);
}
@@ -870,16 +868,7 @@
switch (cmd) {
case MXCFB_WAIT_FOR_VSYNC:
- {
- long long timestamp;
- struct mxsfb_info *host = to_imxfb_host(fb_info);
- ret = mxsfb_wait_for_vsync(fb_info);
- timestamp = ktime_to_ns(host->vsync_nf_timestamp);
- if ((ret == 0) && copy_to_user((void *)arg,
- ×tamp, sizeof(timestamp))) {
- ret = -EFAULT;
- }
- }
+ ret = mxsfb_wait_for_vsync(fb_info);
break;
default:
break;
@@ -963,13 +952,13 @@
host->base + LCDC_CTRL1 + REG_SET);
ret = wait_for_completion_timeout(&host->flip_complete, HZ / 2);
- if (ret < 0) {
+ if (!ret) {
dev_err(fb_info->device,
"mxs wait for pan flip timeout\n");
- ret = -ETIMEDOUT;
+ return -ETIMEDOUT;
}
- return ret;
+ return 0;
}
static int mxsfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 66aec0c..bc26852 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -3140,9 +3140,67 @@
};
#ifdef CONFIG_PM
+static void wm8994_store_context(struct wm8994 *wm8994)
+{
+ struct device *dev = wm8994->dev;
+ int ret;
+
+ /* Disable LDO pulldowns while the device is suspended if we
+ * don't know that something will be driving them. */
+ if (!wm8994->ldo_ena_always_driven)
+ wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
+
+ /* Explicitly put the device into reset in case regulators
+ * don't get disabled in order to ensure consistent restart.
+ */
+ wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
+ wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
+
+ regcache_mark_dirty(wm8994->regmap);
+
+ /* Restore GPIO registers to prevent problems with mismatched
+ * pin configurations.
+ */
+ ret = regcache_sync_region(wm8994->regmap, WM8994_GPIO_1,
+ WM8994_GPIO_11);
+ if (ret != 0)
+ dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
+
+ /* In case one of the GPIOs is used as a wake input. */
+ ret = regcache_sync_region(wm8994->regmap,
+ WM8994_INTERRUPT_STATUS_1_MASK,
+ WM8994_INTERRUPT_STATUS_1_MASK);
+ if (ret != 0)
+ dev_err(dev, "Failed to restore interrupt mask: %d\n", ret);
+
+ regcache_cache_only(wm8994->regmap, true);
+}
+
+static int wm8994_load_context(struct wm8994 *wm8994)
+{
+ struct device *dev = wm8994->dev;
+ int ret;
+
+ regcache_cache_only(wm8994->regmap, false);
+ ret = regcache_sync(wm8994->regmap);
+ if (ret != 0) {
+ dev_err(dev, "Failed to restore register map: %d\n", ret);
+ return ret;
+ }
+
+ /* Disable LDO pulldowns while the device is active */
+ wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, 0);
+
+ return 0;
+}
+
static int wm8994_codec_suspend(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int i, ret;
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
@@ -3154,16 +3212,24 @@
i + 1, ret);
}
- wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ wm8994_store_context(control);
+ wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int wm8994_codec_resume(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int i, ret;
+ ret = wm8994_load_context(control);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to load context: %d\n", ret);
+ return ret;
+ }
+
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
if (!wm8994->fll_suspend[i].out)
continue;