diff options
author | guoyin.chen <guoyin.chen@freescale.com> | 2015-11-06 15:35:54 +0800 |
---|---|---|
committer | guoyin.chen <guoyin.chen@freescale.com> | 2015-11-06 15:35:54 +0800 |
commit | 0178da8d0207290467c801866fc98eb03f43431b (patch) | |
tree | 3e45b1b9f2a26d49162992c6d4d4ba1c1fc28a11 | |
parent | 8cb4f07ce0a29100fee20b685d2d027dd05c1eb7 (diff) | |
parent | 44869a7d1715ec022d17f793cd20a5cc7dc34ffa (diff) | |
download | freescale-0178da8d0207290467c801866fc98eb03f43431b.tar.gz |
Merge remote-tracking branch 'fsl-linux-sdk/imx_3.14.y' into imx_3.14.y_android
42 files changed, 479 insertions, 312 deletions
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 715db929d34..a50978f3eb3 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -236,6 +236,7 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6ul-14x14-evk-btwifi.dtb \ imx6ul-14x14-evk-csi.dtb \ imx6ul-9x9-evk.dtb \ + imx6ul-9x9-evk-btwifi.dtb \ imx6ul-9x9-evk-ldo.dtb \ imx6ul-9x9-evk-csi.dtb \ vf610-cosmic.dtb \ diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi index 79c48b212fa..d39576be2d9 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi @@ -501,6 +501,7 @@ regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; + regulator-ramp-delay = <6250>; }; sw3a_reg: sw3a { diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts index a4f066c0757..a77b375353c 100644 --- a/arch/arm/boot/dts/imx6qp-sabresd.dts +++ b/arch/arm/boot/dts/imx6qp-sabresd.dts @@ -13,6 +13,10 @@ model = "Freescale i.MX6 Quad Plus SABRE Smart Device Board"; }; +&cpu0 { + arm-supply = <&sw2_reg>; +}; + &iomuxc { imx6qdl-sabresd { pinctrl_usdhc2: usdhc2grp { diff --git a/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts b/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts index 3696c1a1fd6..f76bab1e31b 100644 --- a/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts +++ b/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts @@ -61,6 +61,7 @@ }; &qspi_m4 { + reg = <0x021e0000 0x4000>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts index 575ed3ce79f..a74d274a099 100644 --- a/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts +++ b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts @@ -24,7 +24,6 @@ regulator-name = "wlreg_on"; gpio = <&gpio6 10 0>; startup-delay-us = <100>; - regulator-always-on; enable-active-high; }; }; @@ -93,6 +92,10 @@ bus-width = <1>; }; +&vcc_sd3 { + regulator-always-on; +}; + &usdhc3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_wifi>; diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts index 97a21dc54f6..4613799a97c 100644 --- a/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts +++ b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts @@ -6,46 +6,5 @@ * 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 */ -}; +#include "imx6ul-evk-btwifi.dtsi" diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts index f2ef1f27a0b..6c98f61cca1 100644 --- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts +++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts @@ -284,7 +284,11 @@ assigned-clocks = <&clks IMX6UL_CLK_SIM_SEL>; assigned-clock-parents = <&clks IMX6UL_CLK_SIM_PODF>; assigned-clock-rates = <240000000>; - pinctrl-assert-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>; + /* GPIO_ACTIVE_HIGH/LOW:sim card voltage control + * NCN8025:Vcc = ACTIVE_HIGH?5V:3V + * TDA8035:Vcc = ACTIVE_HIGH?5V:1.8V + */ + pinctrl-assert-gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>; port = <1>; sven_low_active; status = "okay"; @@ -345,6 +349,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; no-1-8-v; + non-removable; keep-power-in-suspend; enable-sdio-wakeup; status = "okay"; @@ -544,10 +549,10 @@ pinctrl_sim2_1: sim2grp-1 { fsl,pins = < MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD 0xb808 - MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK 0x31 - MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B 0xb808 - MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN 0xb808 - MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD 0xb809 + MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK 0x11 + MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B 0xb810 + MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN 0xb810 + MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD 0xb811 MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x3008 >; }; diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts b/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts new file mode 100644 index 00000000000..de89052d97f --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-9x9-evk-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 "imx6ul-9x9-evk.dts" +#include "imx6ul-evk-btwifi.dtsi" diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk.dts b/arch/arm/boot/dts/imx6ul-9x9-evk.dts index 3b9047c30df..e04ff804612 100644 --- a/arch/arm/boot/dts/imx6ul-9x9-evk.dts +++ b/arch/arm/boot/dts/imx6ul-9x9-evk.dts @@ -758,7 +758,7 @@ pinctrl-0 = <&pinctrl_usdhc1>; pinctrl-1 = <&pinctrl_usdhc1_100mhz>; pinctrl-2 = <&pinctrl_usdhc1_200mhz>; - cd-gpios = <&gpio1 19 0>; + cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; keep-power-in-suspend; enable-sdio-wakeup; vmmc-supply = <®_sd1_vmmc>; @@ -769,6 +769,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usdhc2>; no-1-8-v; + non-removable; keep-power-in-suspend; enable-sdio-wakeup; status = "okay"; diff --git a/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi b/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi new file mode 100644 index 00000000000..99a67cf8991 --- /dev/null +++ b/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi @@ -0,0 +1,53 @@ +/* + * 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). + */ + +/ { + 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 + >; + }; + }; +}; + +®_sd1_vmmc { + regulator-always-on; +}; + +&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/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts index 46b359f2a97..1c8de620f2d 100644 --- a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts +++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts @@ -5,6 +5,10 @@ memory { linux,usable-memory = <0x80000000 0x3ff00000>; }; + + gpio-keys { + status = "disabled"; + }; }; &adc1 { @@ -15,17 +19,6 @@ status = "disabled"; }; -&iomuxc { - imx7d-12x12-lpddr3-arm2 { - pinctrl_uart2_1: uart2grp-1 { - fsl,pins = < - MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 0x79 - MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX 0x79 - >; - }; - }; -}; - &gpt3 { status = "disabled"; }; @@ -47,11 +40,7 @@ }; &uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart2_1>; - assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>; - assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; - status = "okay"; + status = "disabled"; }; &wdog3{ diff --git a/arch/arm/boot/dts/imx7d-sdb-epdc.dts b/arch/arm/boot/dts/imx7d-sdb-epdc.dts index acdbf761b6a..1cef0c3c092 100644 --- a/arch/arm/boot/dts/imx7d-sdb-epdc.dts +++ b/arch/arm/boot/dts/imx7d-sdb-epdc.dts @@ -20,6 +20,10 @@ status = "disabled"; }; +&flexcan2 { + status = "disabled"; +}; + &max17135 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx7d-sdb-m4.dts b/arch/arm/boot/dts/imx7d-sdb-m4.dts index d0bb0496c43..a6642a8d828 100644 --- a/arch/arm/boot/dts/imx7d-sdb-m4.dts +++ b/arch/arm/boot/dts/imx7d-sdb-m4.dts @@ -13,6 +13,11 @@ linux,usable-memory = <0x80000000 0x3ff00000>; reg = <0x80000000 0x80000000>; }; + + m4_tcm: tcml@007f8000 { + compatible = "fsl, m4_tcml"; + reg = <0x007f8000 0x8000>; + }; }; &adc1 { @@ -31,17 +36,6 @@ status = "disabled"; }; -&iomuxc { - imx7d-sdb { - pinctrl_uart2_1: uart2grp-1 { - fsl,pins = < - MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 0x79 - MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX 0x79 - >; - }; - }; -}; - &gpt3 { status = "disabled"; }; @@ -63,11 +57,7 @@ }; &uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart2_1>; - assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>; - assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>; - status = "okay"; + status = "disabled"; }; &wdog3{ diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts index 2086b7006dc..d84d1a78ef4 100644 --- a/arch/arm/boot/dts/imx7d-sdb.dts +++ b/arch/arm/boot/dts/imx7d-sdb.dts @@ -74,7 +74,7 @@ regulator-name = "can2-3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio1 7 GPIO_ACTIVE_LOW>; + gpio = <&gpio2 14 GPIO_ACTIVE_LOW>; }; reg_vref_1v8: regulator@3 { @@ -977,7 +977,7 @@ pinctrl_hog_2: hoggrp-2 { fsl,pins = < MX7D_PAD_GPIO1_IO05__GPIO1_IO5 0x14 - MX7D_PAD_GPIO1_IO07__GPIO1_IO7 0x59 /* CAN_STBY */ + MX7D_PAD_EPDC_DATA14__GPIO2_IO14 0x59 /* CAN_STBY */ MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x74 >; }; diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig index abdf1dffcf2..e3315f315c1 100644 --- a/arch/arm/configs/imx_v7_defconfig +++ b/arch/arm/configs/imx_v7_defconfig @@ -152,18 +152,15 @@ CONFIG_USB_RTL8150=m CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_CDC_EEM=m -CONFIG_ATH_CARDS=y -CONFIG_ATH6KL=m -CONFIG_ATH6KL_SDIO=m CONFIG_BCMDHD=m CONFIG_BCMDHD_SDIO=y CONFIG_BCMDHD_FW_PATH="/lib/firmware/bcm/fw_bcmdhd.bin" CONFIG_BCMDHD_NVRAM_PATH="/lib/firmware/bcm/bcmdhd.cal" +# CONFIG_RTL_CARDS is not set # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVBUG=m CONFIG_KEYBOARD_GPIO=y -CONFIG_KEYBOARD_SNVS_PWRKEY=y CONFIG_KEYBOARD_IMX=y CONFIG_MOUSE_PS2=m CONFIG_MOUSE_PS2_ELANTECH=y @@ -341,7 +338,6 @@ CONFIG_MXC_IPU=y CONFIG_MXC_GPU_VIV=y CONFIG_MXC_IPU_V3_PRE=y CONFIG_MXC_MIPI_CSI2=y -CONFIG_MXC_MLB150=m CONFIG_MXC_SIM=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c index 784c77a8294..079c90b59a9 100644 --- a/arch/arm/mach-imx/busfreq-imx.c +++ b/arch/arm/mach-imx/busfreq-imx.c @@ -1303,6 +1303,9 @@ static int busfreq_probe(struct platform_device *pdev) high_bus_count++; } + if (cpu_is_imx7d() && imx_src_is_m4_enabled()) + high_bus_count++; + if (err) { dev_err(busfreq_dev, "Busfreq init of ddr controller failed\n"); return err; diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index a41a00058bf..cb3873fb211 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -101,6 +101,8 @@ bool imx_src_is_m4_enabled(void); void mcc_receive_from_mu_buffer(unsigned int index, unsigned int *data); void mcc_send_via_mu_buffer(unsigned int index, unsigned int data); bool imx_mu_is_m4_in_low_freq(void); +bool imx_mu_is_m4_in_stop(void); +int imx_mu_lpm_ready(bool ready); unsigned int imx_gpcv2_is_mf_mix_off(void); int imx_gpc_mf_power_on(unsigned int irq, unsigned int on); #ifdef CONFIG_HAVE_IMX_GPCV2 diff --git a/arch/arm/mach-imx/gpcv2.c b/arch/arm/mach-imx/gpcv2.c index dbe99b7e0d0..56010dfd17d 100644 --- a/arch/arm/mach-imx/gpcv2.c +++ b/arch/arm/mach-imx/gpcv2.c @@ -116,8 +116,9 @@ void imx_gpcv2_set_slot_ack(u32 index, enum imx_gpc_slot m_core, if (index >= MAX_SLOT_NUMBER) pr_err("Invalid slot index!\n"); /* set slot */ - writel_relaxed((mode + 1) << (m_core * 2), gpc_base + - GPC_SLOT0_CFG + index * 4); + writel_relaxed(readl_relaxed(gpc_base + GPC_SLOT0_CFG + index * 4)| + ((mode + 1) << (m_core * 2)), + gpc_base + GPC_SLOT0_CFG + index * 4); if (ack) { /* set ack */ @@ -306,16 +307,16 @@ void imx_gpcv2_set_cpu_power_gate_in_idle(bool pdn) if (pdn) { imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false); if (num_online_cpus() > 1) - imx_gpcv2_set_slot_ack(1, CORE1_A7, false, false); - imx_gpcv2_set_slot_ack(2, SCU_A7, false, true); + imx_gpcv2_set_slot_ack(2, CORE1_A7, false, false); + imx_gpcv2_set_slot_ack(3, SCU_A7, false, true); imx_gpcv2_set_slot_ack(6, SCU_A7, true, false); imx_gpcv2_set_slot_ack(7, CORE0_A7, true, false); if (num_online_cpus() > 1) imx_gpcv2_set_slot_ack(8, CORE1_A7, true, true); } else { writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 0 * 0x4); - writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 1 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 2 * 0x4); + writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 3 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 6 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 7 * 0x4); writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 8 * 0x4); @@ -352,7 +353,9 @@ static void imx_gpcv2_mf_mix_off(void) return; pr_info("Turn off Mega/Fast mix in DSM\n"); - imx_gpcv2_set_mix_phy_gate_by_lpm(1, 5); + + imx_gpcv2_set_slot_ack(1, FAST_MEGA_MIX, false, false); + imx_gpcv2_set_slot_ack(5, FAST_MEGA_MIX, true, false); imx_gpcv2_set_m_core_pgc(true, GPC_PGC_FM); } @@ -399,8 +402,9 @@ void imx_gpcv2_pre_suspend(bool arm_power_off) */ imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false); imx_gpcv2_set_slot_ack(2, SCU_A7, false, true); - - imx_gpcv2_mf_mix_off(); + if ((!imx_src_is_m4_enabled()) || + (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop())) + imx_gpcv2_mf_mix_off(); imx_gpcv2_set_slot_ack(6, SCU_A7, true, false); imx_gpcv2_set_slot_ack(7, CORE0_A7, true, true); @@ -427,9 +431,10 @@ void imx_gpcv2_post_resume(void) val = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC); val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP; writel_relaxed(val, gpc_base + GPC_LPCR_A7_BSC); - /* mask m4 dsm trigger */ - writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) | - BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4); + /* mask m4 dsm trigger if M4 not enabled*/ + if (!imx_src_is_m4_enabled()) + writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) | + BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4); /* set mega/fast mix in A7 domain */ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_MAPPING); /* set SCU timing */ @@ -437,8 +442,10 @@ void imx_gpcv2_post_resume(void) gpc_base + GPC_PGC_SCU_TIMING); val = readl_relaxed(gpc_base + GPC_SLPCR); - val &= ~(BM_SLPCR_EN_DSM | BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN | - BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY); + val &= ~(BM_SLPCR_EN_DSM); + if (!imx_src_is_m4_enabled()) + val &= ~(BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN | + BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY); val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE; writel_relaxed(val, gpc_base + GPC_SLPCR); @@ -458,7 +465,11 @@ void imx_gpcv2_post_resume(void) imx_gpcv2_set_m_core_pgc(false, GPC_PGC_SCU); imx_gpcv2_set_m_core_pgc(false, GPC_PGC_FM); for (i = 0; i < MAX_SLOT_NUMBER; i++) + { + if (i==1||i==4) /* skip slts m4 uses */ + continue; writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + i * 0x4); + } writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK | BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK, gpc_base + GPC_PGC_ACK_SEL_A7); @@ -647,9 +658,10 @@ void __init imx_gpcv2_init(void) val = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC); val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP; writel_relaxed(val, gpc_base + GPC_LPCR_A7_BSC); - /* mask m4 dsm trigger */ - writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) | - BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4); + /* mask m4 dsm trigger if M4 not enabled*/ + if (!imx_src_is_m4_enabled()) + writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) | + BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4); /* set mega/fast mix in A7 domain */ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_MAPPING); /* set SCU timing */ @@ -660,8 +672,10 @@ void __init imx_gpcv2_init(void) gpc_base + GPC_PGC_ACK_SEL_A7); val = readl_relaxed(gpc_base + GPC_SLPCR); - val &= ~(BM_SLPCR_EN_DSM | BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN | - BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY); + val &= ~(BM_SLPCR_EN_DSM); + if (!imx_src_is_m4_enabled()) + val &= ~(BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN | + BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY); val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE; writel_relaxed(val, gpc_base + GPC_SLPCR); diff --git a/arch/arm/mach-imx/mu.c b/arch/arm/mach-imx/mu.c index 56ab9ce18a6..69ae71844e4 100644 --- a/arch/arm/mach-imx/mu.c +++ b/arch/arm/mach-imx/mu.c @@ -47,6 +47,11 @@ #define MU_LPM_M4_WAKEUP_ENABLE_MASK 0xF #define MU_LPM_M4_WAKEUP_ENABLE_SHIFT 0x0 +#define MU_LPM_M4_A7_READY 0xFFFFAAAA +#define MU_LPM_M4_RUN_MODE 0x5A5A0001 +#define MU_LPM_M4_WAIT_MODE 0x5A5A0002 +#define MU_LPM_M4_STOP_MODE 0x5A5A0003 + struct imx_mu_rpmsg_box { const char *name; struct blocking_notifier_head notifier; @@ -62,6 +67,7 @@ static u32 m4_message; static struct delayed_work mu_work, rpmsg_work; static u32 m4_wake_irqs[4]; static bool m4_freq_low; +static bool m4_in_stop; struct imx_sema4_mutex *mcc_shm_ptr; unsigned int imx_mcc_buffer_freed = 0, imx_mcc_buffer_queued = 0; @@ -70,6 +76,11 @@ static DECLARE_WAIT_QUEUE_HEAD(buffer_freed_wait_queue); /* Used for blocking recv */ static DECLARE_WAIT_QUEUE_HEAD(buffer_queued_wait_queue); +bool imx_mu_is_m4_in_stop(void) +{ + return m4_in_stop; +} + bool imx_mu_is_m4_in_low_freq(void) { return m4_freq_low; @@ -163,10 +174,18 @@ static void mu_work_handler(struct work_struct *work) pr_debug("receive M4 message 0x%x\n", m4_message); switch (m4_message) { + case MU_LPM_M4_RUN_MODE: + case MU_LPM_M4_WAIT_MODE: + m4_in_stop = false; + break; + case MU_LPM_M4_STOP_MODE: + m4_in_stop = true; + break; case MU_LPM_M4_REQUEST_HIGH_BUS: request_bus_freq(BUS_FREQ_HIGH); #ifdef CONFIG_SOC_IMX6SX - imx6sx_set_m4_highfreq(true); + if (cpu_is_imx6sx()) + imx6sx_set_m4_highfreq(true); #endif imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX, MU_LPM_BUS_HIGH_READY_FOR_M4); @@ -175,10 +194,12 @@ static void mu_work_handler(struct work_struct *work) case MU_LPM_M4_RELEASE_HIGH_BUS: release_bus_freq(BUS_FREQ_HIGH); #ifdef CONFIG_SOC_IMX6SX - imx6sx_set_m4_highfreq(false); + if (cpu_is_imx6sx()) { + imx6sx_set_m4_highfreq(false); + imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX, + MU_LPM_M4_FREQ_CHANGE_READY); + } #endif - imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX, - MU_LPM_M4_FREQ_CHANGE_READY); m4_freq_low = true; break; default: @@ -219,6 +240,18 @@ int imx_mu_rpmsg_send(unsigned int rpmsg) return imx_mu_send_message(MU_RPMSG_HANDSHAKE_INDEX, rpmsg); } +int imx_mu_lpm_ready(bool ready) +{ + u32 val; + + val = readl_relaxed(mu_base + MU_ACR); + if (ready) + writel_relaxed(val | BIT(0), mu_base + MU_ACR); + else + writel_relaxed(val & ~BIT(0), mu_base + MU_ACR); + return 0; +} + int imx_mu_rpmsg_register_nb(const char *name, struct notifier_block *nb) { if ((name == NULL) || (nb == NULL)) @@ -566,6 +599,12 @@ static int imx_mu_probe(struct platform_device *pdev) /* enable the bit31(GIE3) of MU_ACR, used for MCC */ writel_relaxed(readl_relaxed(mu_base + MU_ACR) | BIT(31), mu_base + MU_ACR); + INIT_DELAYED_WORK(&mu_work, mu_work_handler); + INIT_DELAYED_WORK(&rpmsg_work, rpmsg_work_handler); + /* enable the bit26(RIE1) of MU_ACR */ + writel_relaxed(readl_relaxed(mu_base + MU_ACR) | + BIT(26) | BIT(27), mu_base + MU_ACR); + imx_mu_lpm_ready(true); } else { INIT_DELAYED_WORK(&mu_work, mu_work_handler); diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c index cd6b9185a8f..00bb02a9f5c 100644 --- a/arch/arm/mach-imx/pm-imx7.c +++ b/arch/arm/mach-imx/pm-imx7.c @@ -9,6 +9,7 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <linux/busfreq-imx.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> @@ -115,6 +116,11 @@ #define GPIO_IMR 0x14 #define GPIO_EDGE 0x1c +#define M4RCR 0x0C +#define M4_SP_OFF 0x00 +#define M4_PC_OFF 0x04 +#define M4_RCR_HALT 0xAB +#define M4_RCR_GO 0xAA extern unsigned long iram_tlb_base_addr; extern unsigned long iram_tlb_phys_addr; @@ -123,6 +129,11 @@ static void __iomem *ocram_base; static unsigned int ocram_size; static unsigned int *lpm_ocram_saved_in_ddr; static void __iomem *lpm_ocram_base; + +static unsigned int *lpm_m4tcm_saved_in_ddr; +static void __iomem *lpm_m4tcm_base; +static void __iomem *m4_bootrom_base; + static unsigned int lpm_ocram_size; static void __iomem *ccm_base; static void __iomem *lpsr_base; @@ -693,6 +704,10 @@ static int imx7_pm_enter(suspend_state_t state) imx_anatop_pre_suspend(); imx_gpcv2_pre_suspend(true); if (imx_gpcv2_is_mf_mix_off()) { + /* stop m4 if mix will also be shutdown */ + if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()) + writel(M4_RCR_HALT, + pm_info->src_base.vbase + M4RCR); imx7_console_save(console_saved_reg); memcpy(ocram_saved_in_ddr, ocram_base, ocram_size); if (lpsr_enabled) { @@ -726,6 +741,24 @@ static int imx7_pm_enter(suspend_state_t state) imx7_pm_is_resume_from_lpsr()) { memcpy(ocram_base, ocram_saved_in_ddr, ocram_size); imx7_console_restore(console_saved_reg); + if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()) { + /* restore M4 image */ + memcpy(lpm_m4tcm_base, + lpm_m4tcm_saved_in_ddr, SZ_32K); + /* set sp from word in the image */ + writel(*(lpm_m4tcm_saved_in_ddr), + m4_bootrom_base + M4_SP_OFF); + /* set PC from next word */ + writel(*(lpm_m4tcm_saved_in_ddr+1), + m4_bootrom_base + M4_PC_OFF); + /* kick m4 to enable */ + writel(M4_RCR_GO, + pm_info->src_base.vbase + M4RCR); + /* offset high bus count for m4 image */ + request_bus_freq(BUS_FREQ_HIGH); + /* gpc wakeup */ + imx_mu_lpm_ready(true); + } } /* clear LPSR resume address */ imx7_pm_set_lpsr_resume_addr(0); @@ -1016,7 +1049,27 @@ void __init imx7d_pm_init(void) { struct device_node *np; struct resource res; + if (imx_src_is_m4_enabled()) { + /* map the 32K of M4 TCM */ + np = of_find_node_by_path( + "/tcml@007f8000"); + if (np) + lpm_m4tcm_base = of_iomap(np, 0); + WARN_ON(!lpm_m4tcm_base); + /* map the m4 bootrom from dtb */ + np = of_find_node_by_path( + "/soc/sram@00180000"); + if (np) + m4_bootrom_base = of_iomap(np, 0); + WARN_ON(!m4_bootrom_base); + + lpm_m4tcm_saved_in_ddr = kzalloc(SZ_32K, GFP_KERNEL); + WARN_ON(!lpm_m4tcm_saved_in_ddr); + + /* save M4 Image to DDR */ + memcpy(lpm_m4tcm_saved_in_ddr, lpm_m4tcm_base, SZ_32K); + } np = of_find_compatible_node(NULL, NULL, "fsl,lpm-sram"); if (of_get_property(np, "fsl,enable-lpsr", NULL)) lpsr_enabled = true; diff --git a/arch/arm/mach-imx/suspend-imx7.S b/arch/arm/mach-imx/suspend-imx7.S index 34910ad7c24..ea0712349e6 100644 --- a/arch/arm/mach-imx/suspend-imx7.S +++ b/arch/arm/mach-imx/suspend-imx7.S @@ -551,6 +551,12 @@ wfi_ddr_retention_out: restore_ttbr1 standby_out: + /* make sure SNVS clk is disabled */ + ldr r11, [r0, #PM_INFO_MX7_CCM_V_OFFSET] + add r11, r11, #0x4000 + ldr r7, =0x0 + str r7, [r11, #CCM_SNVS_LPCG] + pop {r4-r12} /* return to suspend finish */ mov pc, lr @@ -585,6 +591,11 @@ resume: dsm_ddr_self_refresh_out: ddrc_exit_self_refresh dsm_ddr_retention_out: + /* make sure SNVS clk is disabled */ + ldr r11, [r0, #PM_INFO_MX7_CCM_P_OFFSET] + add r11, r11, #0x4000 + ldr r7, =0x0 + str r7, [r11, #CCM_SNVS_LPCG] mov pc, lr ENDPROC(imx7_suspend) diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c index 5225bcf57a8..48d751d342c 100644 --- a/drivers/dma/pxp/pxp_dma_v2.c +++ b/drivers/dma/pxp/pxp_dma_v2.c @@ -1319,6 +1319,7 @@ static irqreturn_t pxp_irq(int irq, void *dev_id) if (list_empty(&head)) { pxp->pxp_ongoing = 0; + pxp->lut_state = 0; spin_unlock_irqrestore(&pxp->lock, flags); return IRQ_NONE; } @@ -1349,6 +1350,7 @@ static irqreturn_t pxp_irq(int irq, void *dev_id) complete(&pxp->complete); pxp->pxp_ongoing = 0; + pxp->lut_state = 0; mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms)); spin_unlock_irqrestore(&pxp->lock, flags); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 47a4bd339f8..79d523587b5 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2155,7 +2155,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, y = 0; for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) { timeout = mmc_erase_timeout(card, arg, qty + x); - if (timeout > host->max_discard_to) + if (timeout > host->max_busy_timeout) break; if (timeout < last_timeout) break; @@ -2187,7 +2187,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) struct mmc_host *host = card->host; unsigned int max_discard, max_trim; - if (!host->max_discard_to) + if (!host->max_busy_timeout) return UINT_MAX; /* @@ -2207,7 +2207,7 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) max_discard = 0; } pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n", - mmc_hostname(host), max_discard, host->max_discard_to); + mmc_hostname(host), max_discard, host->max_busy_timeout); return max_discard; } EXPORT_SYMBOL(mmc_calc_max_discard); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 0731155465b..abff3c35ce9 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -273,6 +273,97 @@ static void mmc_select_card_type(struct mmc_card *card) card->ext_csd.card_type = card_type; } +static void mmc_manage_enhanced_area(struct mmc_card *card, u8 *ext_csd) +{ + u8 hc_erase_grp_sz, hc_wp_grp_sz; + + /* + * Disable these attributes by default + */ + card->ext_csd.enhanced_area_offset = -EINVAL; + card->ext_csd.enhanced_area_size = -EINVAL; + + /* + * Enhanced area feature support -- check whether the eMMC + * card has the Enhanced area enabled. If so, export enhanced + * area offset and size to user by adding sysfs interface. + */ + if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && + (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { + if (card->ext_csd.partition_setting_completed) { + hc_erase_grp_sz = + ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; + hc_wp_grp_sz = + ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + + /* + * calculate the enhanced data area offset, in bytes + */ + card->ext_csd.enhanced_area_offset = + (ext_csd[139] << 24) + (ext_csd[138] << 16) + + (ext_csd[137] << 8) + ext_csd[136]; + if (mmc_card_blockaddr(card)) + card->ext_csd.enhanced_area_offset <<= 9; + /* + * calculate the enhanced data area size, in kilobytes + */ + card->ext_csd.enhanced_area_size = + (ext_csd[142] << 16) + (ext_csd[141] << 8) + + ext_csd[140]; + card->ext_csd.enhanced_area_size *= + (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); + card->ext_csd.enhanced_area_size <<= 9; + } else { + pr_warn("%s: defines enhanced area without partition setting complete\n", + mmc_hostname(card->host)); + } + } +} + +static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd) +{ + int idx; + u8 hc_erase_grp_sz, hc_wp_grp_sz; + unsigned int part_size; + + /* + * General purpose partition feature support -- + * If ext_csd has the size of general purpose partitions, + * set size, part_cfg, partition name in mmc_part. + */ + if (ext_csd[EXT_CSD_PARTITION_SUPPORT] & + EXT_CSD_PART_SUPPORT_PART_EN) { + hc_erase_grp_sz = + ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; + hc_wp_grp_sz = + ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + + for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) { + if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] && + !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] && + !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]) + continue; + if (card->ext_csd.partition_setting_completed == 0) { + pr_warn("%s: has partition size defined without partition complete\n", + mmc_hostname(card->host)); + break; + } + part_size = + (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2] + << 16) + + (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] + << 8) + + ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3]; + part_size *= (size_t)(hc_erase_grp_sz * + hc_wp_grp_sz); + mmc_part_add(card, part_size << 19, + EXT_CSD_PART_CONFIG_ACC_GP0 + idx, + "gp%d", idx, false, + MMC_BLK_DATA_AREA_GP); + } + } +} + /* * Decode extended CSD. */ @@ -280,7 +371,6 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) { int err = 0, idx; unsigned int part_size; - u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0; BUG_ON(!card); @@ -382,80 +472,16 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_TRIM_MULT]; card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if (card->ext_csd.rev >= 4) { - /* - * Enhanced area feature support -- check whether the eMMC - * card has the Enhanced area enabled. If so, export enhanced - * area offset and size to user by adding sysfs interface. - */ - if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && - (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { - hc_erase_grp_sz = - ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; - hc_wp_grp_sz = - ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED] & + EXT_CSD_PART_SETTING_COMPLETED) + card->ext_csd.partition_setting_completed = 1; + else + card->ext_csd.partition_setting_completed = 0; - card->ext_csd.enhanced_area_en = 1; - /* - * calculate the enhanced data area offset, in bytes - */ - card->ext_csd.enhanced_area_offset = - (ext_csd[139] << 24) + (ext_csd[138] << 16) + - (ext_csd[137] << 8) + ext_csd[136]; - if (mmc_card_blockaddr(card)) - card->ext_csd.enhanced_area_offset <<= 9; - /* - * calculate the enhanced data area size, in kilobytes - */ - card->ext_csd.enhanced_area_size = - (ext_csd[142] << 16) + (ext_csd[141] << 8) + - ext_csd[140]; - card->ext_csd.enhanced_area_size *= - (size_t)(hc_erase_grp_sz * hc_wp_grp_sz); - card->ext_csd.enhanced_area_size <<= 9; - } else { - /* - * If the enhanced area is not enabled, disable these - * device attributes. - */ - card->ext_csd.enhanced_area_offset = -EINVAL; - card->ext_csd.enhanced_area_size = -EINVAL; - } + mmc_manage_enhanced_area(card, ext_csd); - /* - * General purpose partition feature support -- - * If ext_csd has the size of general purpose partitions, - * set size, part_cfg, partition name in mmc_part. - */ - if (ext_csd[EXT_CSD_PARTITION_SUPPORT] & - EXT_CSD_PART_SUPPORT_PART_EN) { - if (card->ext_csd.enhanced_area_en != 1) { - hc_erase_grp_sz = - ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; - hc_wp_grp_sz = - ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; - - card->ext_csd.enhanced_area_en = 1; - } + mmc_manage_gp_partitions(card, ext_csd); - for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) { - if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] && - !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] && - !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]) - continue; - part_size = - (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2] - << 16) + - (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] - << 8) + - ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3]; - part_size *= (size_t)(hc_erase_grp_sz * - hc_wp_grp_sz); - mmc_part_add(card, part_size << 19, - EXT_CSD_PART_CONFIG_ACC_GP0 + idx, - "gp%d", idx, false, - MMC_BLK_DATA_AREA_GP); - } - } card->ext_csd.sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.sec_erase_mult = @@ -1448,7 +1474,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF * bit. This bit will be lost every time after a reset or power off. */ - if (card->ext_csd.enhanced_area_en || + if (card->ext_csd.partition_setting_completed || (card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_ERASE_GROUP_DEF, 1, diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 9a7d42c39dc..23919909c87 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -990,9 +990,22 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) return esdhc_change_pinstate(host, uhs); } -static unsigned int esdhc_get_max_timeout_counter(struct sdhci_host *host) +static unsigned int esdhc_get_max_timeout_count(struct sdhci_host *host) { - return 1 << 28; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + + return esdhc_is_usdhc(imx_data) ? 1 << 28 : 1 << 27; +} + +static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + + /* use maximum timeout counter */ + sdhci_writeb(host, esdhc_is_usdhc(imx_data) ? 0xF : 0xE, + SDHCI_TIMEOUT_CONTROL); } static struct sdhci_ops sdhci_esdhc_ops = { @@ -1004,8 +1017,10 @@ static struct sdhci_ops sdhci_esdhc_ops = { .set_clock = esdhc_pltfm_set_clock, .get_max_clock = esdhc_pltfm_get_max_clock, .get_min_clock = esdhc_pltfm_get_min_clock, + .get_max_timeout_count = esdhc_get_max_timeout_count, .get_ro = esdhc_pltfm_get_ro, .platform_bus_width = esdhc_pltfm_bus_width, + .set_timeout = esdhc_set_timeout, .set_uhs_signaling = esdhc_set_uhs_signaling, }; @@ -1170,9 +1185,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) writel(readl(host->ioaddr + SDHCI_HOST_CONTROL) | ESDHC_BURST_LEN_EN_INCR, host->ioaddr + SDHCI_HOST_CONTROL); - - host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN | - SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER; + host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; host->mmc->caps |= MMC_CAP_1_8V_DDR; /* @@ -1180,8 +1193,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) * TO1.1, it's harmless for MX6SL */ writel(readl(host->ioaddr + 0x6c) | BIT(7), host->ioaddr + 0x6c); - sdhci_esdhc_ops.get_max_timeout_counter = - esdhc_get_max_timeout_counter; } if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7a879289302..0af163737e4 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -717,19 +717,28 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); } -static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) { u8 count; + + if (host->ops->set_timeout) { + host->ops->set_timeout(host, cmd); + } else { + count = sdhci_calc_timeout(host, cmd); + sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); + } +} + +static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +{ u8 ctrl; struct mmc_data *data = cmd->data; int ret; WARN_ON(host->data); - if (data || (cmd->flags & MMC_RSP_BUSY)) { - count = sdhci_calc_timeout(host, cmd); - sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); - } + if (data || (cmd->flags & MMC_RSP_BUSY)) + sdhci_set_timeout(host, cmd); if (!data) return; @@ -1218,7 +1227,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) clock_set: if (real_div) host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div; - clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT; @@ -1453,6 +1461,18 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) sdhci_set_clock(host, ios->clock); + if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && + host->clock) { + host->timeout_clk = host->mmc->actual_clock ? + host->mmc->actual_clock / 1000 : + host->clock / 1000; + host->mmc->max_busy_timeout = + host->ops->get_max_timeout_count ? + host->ops->get_max_timeout_count(host) : + 1 << 27; + host->mmc->max_busy_timeout /= host->timeout_clk; + } + if (ios->power_mode == MMC_POWER_OFF) vdd_bit = sdhci_set_power(host, -1); else @@ -3026,36 +3046,26 @@ int sdhci_add_host(struct sdhci_host *host) } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; - host->timeout_clk = - (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; - if (host->timeout_clk == 0) { - if (host->ops->get_timeout_clock) { - host->timeout_clk = host->ops->get_timeout_clock(host); - } else if (!(host->quirks & - SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { - pr_err("%s: Hardware doesn't specify timeout clock " - "frequency.\n", mmc_hostname(mmc)); - return -ENODEV; + if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { + host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> + SDHCI_TIMEOUT_CLK_SHIFT; + if (host->timeout_clk == 0) { + if (host->ops->get_timeout_clock) { + host->timeout_clk = + host->ops->get_timeout_clock(host); + } else { + pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", + mmc_hostname(mmc)); + return -ENODEV; + } } - } - if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) - host->timeout_clk *= 1000; - if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - host->timeout_clk = mmc->f_max / 1000; + if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT) + host->timeout_clk *= 1000; - if (host->quirks2 & SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER) { - if (host->ops->get_max_timeout_counter) { - mmc->max_discard_to = - host->ops->get_max_timeout_counter(host) - / host->timeout_clk; - } else { - pr_err("%s: Hardware doesn't specify max timeout " - "counter\n", mmc_hostname(mmc)); - return -ENODEV; - } - } else { - mmc->max_discard_to = (1 << 27) / host->timeout_clk; + mmc->max_busy_timeout = host->ops->get_max_timeout_count ? + host->ops->get_max_timeout_count(host) : 1 << 27; + mmc->max_busy_timeout /= host->timeout_clk; } mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 4d38c29892b..8c58ba527c7 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -290,7 +290,9 @@ struct sdhci_ops { unsigned int (*get_max_clock)(struct sdhci_host *host); unsigned int (*get_min_clock)(struct sdhci_host *host); unsigned int (*get_timeout_clock)(struct sdhci_host *host); - unsigned int (*get_max_timeout_counter)(struct sdhci_host *host); + unsigned int (*get_max_timeout_count)(struct sdhci_host *host); + void (*set_timeout)(struct sdhci_host *host, + struct mmc_command *cmd); int (*platform_bus_width)(struct sdhci_host *host, int width); void (*platform_send_init_74_clocks)(struct sdhci_host *host, diff --git a/drivers/mxc/sim/imx_sim.c b/drivers/mxc/sim/imx_sim.c index 318f9d753e9..3687242c5ea 100755 --- a/drivers/mxc/sim/imx_sim.c +++ b/drivers/mxc/sim/imx_sim.c @@ -926,69 +926,36 @@ static void sim_start(struct sim_t *sim) __raw_writel(reg_data, sim->ioaddr + sim->port_detect_reg); }; -static void sim_activate(struct sim_t *sim) -{ - u32 reg_data; - pr_debug("%s Activate on the sim port.\n", __func__); - /* activate on sequence */ - if (sim->present != SIM_PRESENT_REMOVED) { - /*Disable Reset pin*/ - reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); - reg_data &= ~SIM_PORT_CNTL_SRST; - /*If sven is low active, we need to set sevn to be high*/ - if (sim->sven_low_active) - reg_data |= SIM_PORT_CNTL_SVEN; - - __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg); - - /*Enable VCC pin*/ - reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); - - if (sim->sven_low_active) - reg_data &= ~SIM_PORT_CNTL_SVEN; - else - reg_data |= SIM_PORT_CNTL_SVEN; - - __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg); - - msleep(10); - /*Enable clock pin*/ - reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); - reg_data |= SIM_PORT_CNTL_SCEN; - __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg); - msleep(10); - } else { - pr_err("No card%s\n", __func__); - } -} - static void sim_cold_reset_sequency(struct sim_t *sim) { u32 reg_data; sim->state = SIM_STATE_RESET_SEQUENCY; - reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); - reg_data &= ~SIM_PORT_CNTL_SRST; - __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg); - reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); + /*set VCC*/ + reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); if (sim->sven_low_active) reg_data &= ~SIM_PORT_CNTL_SVEN; else reg_data |= SIM_PORT_CNTL_SVEN; - __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg); + msleep(9); + /*enable CLK*/ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); reg_data |= SIM_PORT_CNTL_SCEN; __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg); + /*RST low time*/ sim_reset_low_timing(sim, EMV_RESET_LOW_CYCLES); + /*RST high*/ reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg); reg_data |= SIM_PORT_CNTL_SRST; __raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg); + + /*wait for ATR*/ sim_set_gpc_timer(sim, ATR_MAX_DELAY_CLK); }; @@ -1406,7 +1373,6 @@ static long sim_ioctl(struct file *file, sim_reset_module(sim); sim_data_reset(sim); sim_start(sim); - sim_activate(sim); sim_cold_reset(sim); break; diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index c7f587c8320..4b628e94234 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -24,6 +24,10 @@ * $Id: dhd_sdio.c 506047 2014-10-02 12:43:31Z $ */ +#include <linux/mmc/host.h> +#include <linux/mmc/card.h> +#include <linux/mmc/sdio_func.h> + #include <typedefs.h> #include <osl.h> #include <bcmsdh.h> @@ -53,6 +57,7 @@ #include <sbsdpcmdev.h> #include <bcmsdpcm.h> #include <bcmsdbus.h> +#include <bcmsdh_sdmmc.h> #include <proto/ethernet.h> #include <proto/802.1d.h> @@ -1737,6 +1742,9 @@ static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txs uint32 swhdr_offset; bool alloc_new_pkt = FALSE; uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN; + sdioh_info_t *sd = bus->sdh->sdioh; + struct sdio_func *sdio_func = sd->func[0]; + struct mmc_host *host = sdio_func->card->host; *new_pkt = NULL; osh = bus->dhd->osh; @@ -1814,7 +1822,7 @@ static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txs * Use the padding packet to avoid memory copy if applicable, * otherwise, just allocate a new pkt. */ - if (bus->pad_pkt) { + if (bus->pad_pkt && (host->max_segs > 1)) { *pad_pkt_len = chain_tail_padding; bus->tx_tailpad_chain++; } else { diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 90c653d9c3e..405c184dafa 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -1412,11 +1412,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) * reserved ddr memory after write the ddr_test_region * content to rc. */ - if (is_imx7d_pcie(imx6_pcie)) - pcie_arb_base_addr = ioremap_nocache(pp->mem_base, - test_region_size); - else - pcie_arb_base_addr = ioremap_cache(pp->mem_base, + pcie_arb_base_addr = ioremap_nocache(pp->mem_base, test_region_size); if (!pcie_arb_base_addr) { diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 67b1526bd71..78b4a8ed1ae 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -246,7 +246,6 @@ struct imx_port { unsigned int tx_bytes; unsigned int dma_tx_nents; struct delayed_work tsk_dma_tx; - struct work_struct tsk_dma_rx; wait_queue_head_t dma_wait; unsigned int saved_reg[10]; #define DMA_TX_IS_WORKING 1 @@ -896,7 +895,6 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) } #define RX_BUF_SIZE (PAGE_SIZE) -static int start_rx_dma(struct imx_port *sport); static void dma_rx_push_data(struct imx_port *sport, struct tty_struct *tty, unsigned int start, unsigned int end) @@ -917,9 +915,8 @@ static void dma_rx_push_data(struct imx_port *sport, struct tty_struct *tty, } } -static void dma_rx_work(struct work_struct *w) +static void dma_rx_work(struct imx_port *sport) { - struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx); struct tty_struct *tty = sport->port.state->port.tty; unsigned int cur_idx = sport->rx_buf.cur_idx; @@ -970,14 +967,6 @@ static void dma_rx_callback(void *data) status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state); count = RX_BUF_SIZE - state.residue; - - if (readl(sport->port.membase + USR2) & USR2_IDLE) { - /* In condition [3] the SDMA counted up too early */ - count--; - - writel(USR2_IDLE, sport->port.membase + USR2); - } - sport->rx_buf.buf_info[sport->rx_buf.cur_idx].filled = true; sport->rx_buf.buf_info[sport->rx_buf.cur_idx].rx_bytes = count; sport->rx_buf.cur_idx++; @@ -988,7 +977,7 @@ static void dma_rx_callback(void *data) dev_err(sport->port.dev, "overwrite!\n"); if (count) - schedule_work(&sport->tsk_dma_rx); + dma_rx_work(sport); } static int start_rx_dma(struct imx_port *sport) @@ -1227,10 +1216,8 @@ static int imx_startup(struct uart_port *port) && !sport->dma_is_inited) imx_uart_dma_init(sport); - if (sport->dma_is_inited) { + if (sport->dma_is_inited) INIT_DELAYED_WORK(&sport->tsk_dma_tx, dma_tx_work); - INIT_WORK(&sport->tsk_dma_rx, dma_rx_work); - } spin_lock_irqsave(&sport->port.lock, flags); /* diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 3fa83dbb862..db3b830df19 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -664,6 +664,15 @@ static int mxsfb_set_par(struct fb_info *fb_info) if (host->cur_blank != FB_BLANK_UNBLANK) return 0; + line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3); + fb_info->fix.line_length = line_size; + fb_size = fb_info->var.yres_virtual * line_size; + + if (fb_size > fb_info->fix.smem_len) { + dev_err(&host->pdev->dev, "exceeds the fb buffer size limit!\n"); + return -ENOMEM; + } + /* * It seems, you can't re-program the controller if it is still running. * This may lead into shifted pictures (FIFO issue?). @@ -677,19 +686,6 @@ static int mxsfb_set_par(struct fb_info *fb_info) /* clear the FIFOs */ writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET); - line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3); - fb_info->fix.line_length = line_size; - fb_size = fb_info->var.yres_virtual * line_size; - - /* Reallocate memory */ - if (!fb_info->fix.smem_start || (fb_size > fb_info->fix.smem_len)) { - if (fb_info->fix.smem_start) - mxsfb_unmap_videomem(fb_info); - - if (mxsfb_map_videomem(fb_info) < 0) - return -ENOMEM; - } - ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER | CTRL_SET_BUS_WIDTH(host->ld_intf_width); @@ -1259,6 +1255,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host) fb_info->fix.line_length = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3); + fb_info->fix.smem_len = SZ_32M; /* Memory allocation for framebuffer */ if (mxsfb_map_videomem(fb_info) < 0) diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 84e005e7034..b7a90c4b22c 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -75,7 +75,7 @@ struct mmc_ext_csd { unsigned int sec_trim_mult; /* Secure trim multiplier */ unsigned int sec_erase_mult; /* Secure erase multiplier */ unsigned int trim_timeout; /* In milliseconds */ - bool enhanced_area_en; /* enable bit */ + bool partition_setting_completed; /* enable bit */ unsigned long long enhanced_area_offset; /* Units: Byte */ unsigned int enhanced_area_size; /* Units: KB */ unsigned int cache_size; /* Units: KB */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index d35e58b64cb..48953c7868f 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -315,7 +315,7 @@ struct mmc_host { unsigned int max_req_size; /* maximum number of bytes in one req */ unsigned int max_blk_size; /* maximum size of one mmc block */ unsigned int max_blk_count; /* maximum number of blocks in one req */ - unsigned int max_discard_to; /* max. discard timeout in ms */ + unsigned int max_busy_timeout; /* max busy timeout in ms */ /* private data */ spinlock_t lock; /* lock for claim and bus ops */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 05324379821..9776b2aa3af 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -281,6 +281,7 @@ struct _mmc_csd { #define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */ #define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ +#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ #define EXT_CSD_HPI_MGMT 161 /* R/W */ @@ -351,6 +352,7 @@ struct _mmc_csd { #define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3) #define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4) +#define EXT_CSD_PART_SETTING_COMPLETED (0x1) #define EXT_CSD_PART_SUPPORT_PART_EN (0x1) #define EXT_CSD_CMD_SET_NORMAL (1<<0) diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 0fdff063287..714ae21c9e9 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -101,7 +101,6 @@ struct sdhci_host { #define SDHCI_QUIRK2_NO_1_8_V (1<<2) #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) -#define SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER (1<<5) /* Controller has a non-standard host control register */ #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) /* Controller does not support HS200 */ diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 13412ab158e..5f2ce73096c 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -625,7 +625,8 @@ struct snd_soc_dapm_context { enum snd_soc_bias_level suspend_bias_level; struct delayed_work delayed_work; unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ - + /* Go to BIAS_OFF in suspend if the DAPM context is idle */ + unsigned int suspend_bias_off:1; void (*seq_notifier)(struct snd_soc_dapm_context *, enum snd_soc_dapm_type, int); diff --git a/include/sound/soc.h b/include/sound/soc.h index 59a47851f5c..91a9efd80b1 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -774,6 +774,7 @@ struct snd_soc_codec_driver { int (*set_bias_level)(struct snd_soc_codec *, enum snd_soc_bias_level level); bool idle_bias_off; + bool suspend_bias_off; void (*seq_notifier)(struct snd_soc_dapm_context *, enum snd_soc_dapm_type, int); diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 871536109e3..50079fa8b10 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1122,7 +1122,7 @@ static int wm8960_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { .probe = wm8960_probe, .set_bias_level = wm8960_set_bias_level, - .idle_bias_off = true, + .suspend_bias_off = true, }; static const struct regmap_config wm8960_regmap = { diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 8f5fe19669d..21667fd69fb 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1782,8 +1782,11 @@ SND_SOC_BYTES("HD Bass Coefficients", WM8962_HDBASS_AI_1, 30), SOC_DOUBLE("ALC Switch", WM8962_ALC1, WM8962_ALCL_ENA_SHIFT, WM8962_ALCR_ENA_SHIFT, 1, 0), -SND_SOC_BYTES_MASK("ALC Coefficients", WM8962_ALC1, 4, +SND_SOC_BYTES_MASK("ALC1", WM8962_ALC1, 1, WM8962_ALCL_ENA_MASK | WM8962_ALCR_ENA_MASK), +SND_SOC_BYTES("ALC2", WM8962_ALC2, 1), +SND_SOC_BYTES("ALC3", WM8962_ALC3, 1), +SND_SOC_BYTES("Noise Gate", WM8962_NOISE_GATE, 1), }; static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 56a21e726b6..e00ce586994 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4375,6 +4375,7 @@ int snd_soc_register_codec(struct device *dev, codec->dapm.codec = codec; codec->dapm.seq_notifier = codec_drv->seq_notifier; codec->dapm.stream_event = codec_drv->stream_event; + codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off; codec->dev = dev; codec->driver = codec_drv; codec->num_dai = num_dai; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f504fae027a..331a4403a64 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1807,6 +1807,22 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w, } } +static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm) +{ + if (dapm->idle_bias_off) + return true; + + switch (snd_power_get_state(dapm->card->snd_card)) { + case SNDRV_CTL_POWER_D3hot: + case SNDRV_CTL_POWER_D3cold: + return dapm->suspend_bias_off; + default: + break; + } + + return false; +} + /* * Scan each dapm widget for complete audio path. * A complete path is a route that has valid endpoints i.e.:- @@ -1828,7 +1844,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) trace_snd_soc_dapm_start(card); list_for_each_entry(d, &card->dapm_list, list) { - if (d->idle_bias_off) + if (dapm_idle_bias_off(d)) d->target_bias_level = SND_SOC_BIAS_OFF; else d->target_bias_level = SND_SOC_BIAS_STANDBY; @@ -1894,7 +1910,7 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) if (d->target_bias_level > bias) bias = d->target_bias_level; list_for_each_entry(d, &card->dapm_list, list) - if (!d->idle_bias_off) + if (!dapm_idle_bias_off(d)) d->target_bias_level = bias; trace_snd_soc_dapm_walk_done(card); |