diff options
25 files changed, 667 insertions, 86 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000000..c0d0de1dab5b --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,69 @@ +image: $CI_IMAGE + +variables: +# uncomment for the pipeline debug purpose +# CI_DEBUG_TRACE: "true" + +# Please choose possible 32/64 builder image and appropriate compiler + CI_IMAGE: gitlab.int.toradex.com:4567/yuiry.erofeev/linux-toradex/ci-kernel-builder:latest + #CI_IMAGE: gitlab.int.toradex.com:4567/yuiry.erofeev/linux-toradex/ci-kernel-builder:aarch64 + #CI_IMAGE: gitlab.int.toradex.com:4567/yuiry.erofeev/linux-toradex/ci-kernel-builder:aarch64-linaro + DOCKER_HOST: tcp://docker:2375 + DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" + +# Kernel Configuration Section +# Supplementary Tool Section + # Artifacts configuring section + KERNEL_CONFIG_BUILD_LOG_FILE_NAME: build_config.log + KERNEL_BUILD_LOG_FILE_NAME: build.log + KERNEL_CONFIGURATION_FILE: .config +# Defining temporary build folder to do outside of the box builds. Absolute path + TEMP_BUILD_FOLDER: /builds/temp-builds + +stages: + - build-product + +.build_base: + stage: build-product + variables: + GIT_STRATEGY: fetch +# To run just on merge request +# only: +# - merge_requests +# when: manual + script: | + #set -o xtrace + cd $CI_PROJECT_DIR + echo -e "Compiler used to build binaries is" + which ${CROSS_COMPILE}gcc + ${CROSS_COMPILE}gcc --version + echo -e "Arch is \e[36m$ARCH\e[39m" + # due to specific of the kernel build we need to use the latest configuration from the nightly builds. We are getting $Version dynamically , as a variable , based on parsing URL page with Nightly builds ID + rm -f index.html + wget http://10.1.8.33:83/image-oe-torizon-master-matrix/Nightly/artifacts/ + version=$( cat index.html| grep ^"<a" | sed -e 's/[<>="//]/ /g' | awk '{ print $3}' | sort -nrk1,1 | head -1) + wget http://10.1.8.33:83/image-oe-torizon-master-matrix/Nightly/artifacts/$version/$KERNEL_FILE_PATH/images/kernel-config + mkdir -p $TEMP_BUILD_FOLDER + cp kernel-config $TEMP_BUILD_FOLDER/$KERNEL_CONFIGURATION_FILE + ##### + make O=$TEMP_BUILD_FOLDER -j3 2>&1 | tee $KERNEL_BUILD_LOG_FILE_NAME + artifacts: + when: always + name: "$CI_COMMIT_REF_NAME" + paths: + - $KERNEL_BUILD_LOG_FILE_NAME + #As we do not generate config for 5.x and use generated one, we have just kernel config and kernel build log + - kernel-config + allow_failure: true + after_script: + - set -o xtrace + - rm -rf $TEMP_BUILD_FOLDER + + # If you need additional products build just copy-paste build_******_product section with new config name +build_default_defconfig : + extends: .build_base + variables: + # Defining the path, which we will use to take a config file to build a kernel + KERNEL_FILE_PATH: colibri-imx7_torizon-core-docker + stage: build-product
\ No newline at end of file diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt index 164cbb15f04c..adbd2ca0af2f 100644 --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt @@ -18,6 +18,7 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt. Optional properties: - vdd-supply: Power supply for DAC +- de-active: data-enable pulse is active low/high/ignored Example ------- diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts index 9a5d6c94cca4..e59b5cbfdc52 100644 --- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts @@ -99,7 +99,6 @@ compatible = "fsl,imx-parallel-display"; #address-cells = <1>; #size-cells = <0>; - interface-pix-fmt = "bgr666"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ipu1_lcdif>; status = "okay"; @@ -121,13 +120,25 @@ }; }; - panel: panel { - /* - * edt,et057090dhu: EDT 5.7" LCD TFT - * edt,et070080dh6: EDT 7.0" LCD TFT - */ - compatible = "edt,et057090dhu"; + panel_dpi: panel-dpi { + compatible = "panel-dpi"; backlight = <&backlight>; + width-mm = <115>; + height-mm = <86>; + + data-mapping = "bgr666"; + + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hsync-len = <30>; + hfront-porch = <16>; + hback-porch = <114>; + vsync-len = <3>; + vfront-porch = <10>; + vback-porch = <32>; + }; port { lcd_panel_in: endpoint { @@ -154,6 +165,12 @@ interrupt-parent = <&gpio3>; interrupts = <27 0x2>; spi-max-frequency = <10000000>; + status = "disabled"; + }; + spidev0: spidev@1 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <23000000>; status = "okay"; }; }; diff --git a/arch/arm/boot/dts/imx6q-apalis-eval.dts b/arch/arm/boot/dts/imx6q-apalis-eval.dts index 0edd3043d9c1..6174f9f36d20 100644 --- a/arch/arm/boot/dts/imx6q-apalis-eval.dts +++ b/arch/arm/boot/dts/imx6q-apalis-eval.dts @@ -84,10 +84,9 @@ compatible = "fsl,imx-parallel-display"; #address-cells = <1>; #size-cells = <0>; - interface-pix-fmt = "rgb24"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ipu1_lcdif>; - status = "okay"; + status = "disabled"; port@0 { reg = <0>; @@ -106,14 +105,28 @@ }; }; - panel: panel { - /* - * edt,et057090dhu: EDT 5.7" LCD TFT - * edt,et070080dh6: EDT 7.0" LCD TFT - */ - compatible = "edt,et057090dhu"; + panel_dpi: panel-dpi { + compatible = "panel-dpi"; + backlight = <&backlight>; - power-supply = <®_3v3_sw>; + + width-mm = <115>; + height-mm = <86>; + + data-mapping = "rgb24"; + status = "disabled"; + + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hsync-len = <30>; + hfront-porch = <16>; + hback-porch = <114>; + vsync-len = <3>; + vfront-porch = <10>; + vback-porch = <32>; + }; port { lcd_panel_in: endpoint { @@ -122,6 +135,39 @@ }; }; + panel_lvds: panel-lvds { + compatible = "panel-lvds"; + + backlight = <&backlight>; + + width-mm = <218>; + height-mm = <137>; + + data-mapping = "vesa-24"; + status = "disabled"; + + panel-timing { + clock-frequency = <68930000>; + hactive = <1280>; + vactive = <800>; + hback-porch = <64>; + hfront-porch = <64>; + vback-porch = <5>; + vfront-porch = <5>; + hsync-len = <40>; + vsync-len = <6>; + hsync-active = <0>; + vsync-active = <0>; + pixelclk-active = <0>; + }; + + port { + lvds_panel_in: endpoint { + remote-endpoint = <&lvds_out>; + }; + }; + }; + reg_pcie_switch: regulator-pcie-switch { compatible = "regulator-fixed"; regulator-name = "pcie_switch"; @@ -140,6 +186,16 @@ regulator-max-microvolt = <3300000>; regulator-always-on; }; + + vga { + compatible = "vga-connector"; + + port { + vga_con_in: endpoint { + remote-endpoint = <&vga_bridge_out>; + }; + }; + }; }; &backlight { @@ -159,6 +215,35 @@ status = "okay"; }; +/* Apalis SPI1 */ +&ecspi1 { + status = "okay"; + + spidev0: spidev@1 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <18000000>; + }; +}; + +/* Apalis SPI2 */ +&ecspi2 { + status = "okay"; + + spidev1: spidev@2 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <18000000>; + }; +}; + +&clks { + assigned-clocks = <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>, + <&clks IMX6QDL_CLK_IPU2_DI0_PRE_SEL>; + assigned-clock-parents = <&clks IMX6QDL_CLK_PLL2_PFD2_396M>, + <&clks IMX6QDL_CLK_PLL2_PFD2_396M>; +}; + &hdmi { status = "okay"; }; @@ -192,7 +277,20 @@ }; &ldb { - status = "okay"; + status = "disabled"; + + lvds-channel@0 { + status = "okay"; + primary; + + port@4 { + reg = <4>; + + lvds_out: endpoint { + remote-endpoint = <&lvds_panel_in>; + }; + }; + }; }; &pcie { @@ -283,6 +381,24 @@ status = "okay"; }; +&vgabridge { + status = "okay"; + + ports { + port@1 { + reg = <1>; + + vga_bridge_out: endpoint { + remote-endpoint = <&vga_con_in>; + }; + }; + }; +}; + +&vgadisplay { + status = "okay"; +}; + &iomuxc { /* * Mux the Apalis GPIOs diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts index b94bb687be6b..dc75a88b37a0 100644 --- a/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts +++ b/arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts @@ -164,6 +164,28 @@ status = "okay"; }; +/* Apalis SPI1 */ +&ecspi1 { + status = "okay"; + + spidev0: spidev@1 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <18000000>; + }; +}; + +/* Apalis SPI2 */ +&ecspi2 { + status = "okay"; + + spidev1: spidev@2 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <18000000>; + }; +}; + &hdmi { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts b/arch/arm/boot/dts/imx6q-apalis-ixora.dts index 302fd6adc8a7..db29c25abafc 100644 --- a/arch/arm/boot/dts/imx6q-apalis-ixora.dts +++ b/arch/arm/boot/dts/imx6q-apalis-ixora.dts @@ -163,6 +163,28 @@ status = "okay"; }; +/* Apalis SPI1 */ +&ecspi1 { + status = "okay"; + + spidev0: spidev@1 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <18000000>; + }; +}; + +/* Apalis SPI2 */ +&ecspi2 { + status = "okay"; + + spidev1: spidev@2 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <18000000>; + }; +}; + &hdmi { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi index 7c4ad541c3f5..4b6b8b60ea19 100644 --- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi +++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi @@ -139,6 +139,54 @@ spdif-out; status = "disabled"; }; + + vgabridge: bridge { + compatible = "dumb-vga-dac"; + #address-cells = <1>; + #size-cells = <0>; + de-active = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + vga_bridge_in: endpoint { + remote-endpoint = <&vga_display_out>; + }; + }; + }; + }; + + vgadisplay: display@di0 { + compatible = "fsl,imx-parallel-display"; + #address-cells = <1>; + #size-cells = <0>; + interface-pix-fmt = "rgb565"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu2_vdac>; + status = "disabled"; + + port@0 { + reg = <0>; + + vga_display_in: endpoint { + remote-endpoint = <&ipu2_di0_disp0>; + }; + }; + + port@1 { + reg = <1>; + + vga_display_out: endpoint { + remote-endpoint = <&vga_bridge_in>; + }; + }; + }; + }; &audmux { @@ -380,6 +428,10 @@ status = "disabled"; }; +&ipu2_di0_disp0 { + remote-endpoint = <&vga_display_in>; +}; + &pwm1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm1>; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index 81d4b4925127..33d3468c0222 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -227,6 +227,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI1>, <&clks IMX6UL_CLK_ECSPI1>; clock-names = "ipg", "per"; + dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -239,6 +241,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI2>, <&clks IMX6UL_CLK_ECSPI2>; clock-names = "ipg", "per"; + dmas = <&sdma 5 7 1>, <&sdma 6 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -251,6 +255,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI3>, <&clks IMX6UL_CLK_ECSPI3>; clock-names = "ipg", "per"; + dmas = <&sdma 7 7 1>, <&sdma 8 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -263,6 +269,8 @@ clocks = <&clks IMX6UL_CLK_ECSPI4>, <&clks IMX6UL_CLK_ECSPI4>; clock-names = "ipg", "per"; + dmas = <&sdma 9 7 1>, <&sdma 10 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi index b6147c76d159..aeb5d3011d4f 100644 --- a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi +++ b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dtsi @@ -79,6 +79,13 @@ spi-max-frequency = <10000000>; vdd-supply = <®_3v3>; xceiver-supply = <®_5v0>; + status = "disabled"; + }; + + spidev0: spidev@0 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <23000000>; status = "okay"; }; }; diff --git a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi index 3f2746169181..57eab2866ac8 100644 --- a/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi +++ b/arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi @@ -52,13 +52,30 @@ clock-frequency = <16000000>; }; - panel: panel { - compatible = "edt,et057090dhu"; + panel_dpi: panel-dpi { + compatible = "panel-dpi"; backlight = <&bl>; power-supply = <®_3v3>; + width-mm = <115>; + height-mm = <86>; + + data-mapping = "bgr666"; + + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hsync-len = <30>; + hfront-porch = <16>; + hback-porch = <114>; + vsync-len = <3>; + vfront-porch = <10>; + vback-porch = <32>; + }; + port { - panel_in: endpoint { + lcd_panel_in: endpoint { remote-endpoint = <&lcdif_out>; }; }; @@ -120,6 +137,13 @@ spi-max-frequency = <10000000>; vdd-supply = <®_3v3>; xceiver-supply = <®_5v0>; + status = "disabled"; + }; + + spidev0: spidev@0 { + compatible = "toradex,evalspi"; + reg = <0>; + spi-max-frequency = <23000000>; status = "okay"; }; }; @@ -143,7 +167,7 @@ port { lcdif_out: endpoint { - remote-endpoint = <&panel_in>; + remote-endpoint = <&lcd_panel_in>; }; }; }; diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index c1ed83131b49..37aeba999be3 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -319,7 +319,6 @@ assigned-clock-rates = <400000000>; bus-width = <8>; fsl,tuning-step = <2>; - max-frequency = <100000000>; vmmc-supply = <®_module_3v3>; vqmmc-supply = <®_DCDC3>; non-removable; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 6323a9462afa..6a093a1e7567 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -698,6 +698,8 @@ clocks = <&clks IMX7D_ECSPI4_ROOT_CLK>, <&clks IMX7D_ECSPI4_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 6 7 1>, <&sdma 7 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -825,6 +827,8 @@ clocks = <&clks IMX7D_ECSPI1_ROOT_CLK>, <&clks IMX7D_ECSPI1_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 0 7 1>, <&sdma 1 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -837,6 +841,8 @@ clocks = <&clks IMX7D_ECSPI2_ROOT_CLK>, <&clks IMX7D_ECSPI2_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 2 7 1>, <&sdma 3 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -849,6 +855,8 @@ clocks = <&clks IMX7D_ECSPI3_ROOT_CLK>, <&clks IMX7D_ECSPI3_ROOT_CLK>; clock-names = "ipg", "per"; + dmas = <&sdma 4 7 1>, <&sdma 5 7 2>; + dma-names = "rx", "tx"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts index 5965150ecdd2..bfc6faaff99a 100644 --- a/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts +++ b/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts @@ -95,6 +95,11 @@ vdd-supply = <®_3v3>; xceiver-supply = <®_5v0>; }; + spidev0: spi@1 { + compatible = "spidev"; + reg = <1>; + spi-max-frequency = <25000000>; + }; }; /* SD/MMC */ diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c index f82ccd39a913..a7e2deab930a 100644 --- a/drivers/firmware/psci/psci.c +++ b/drivers/firmware/psci/psci.c @@ -82,6 +82,7 @@ static u32 psci_function_id[PSCI_FN_MAX]; static u32 psci_cpu_suspend_feature; static bool psci_system_reset2_supported; +static struct notifier_block psci_restart_handler; static inline bool psci_has_ext_power_state(void) { @@ -250,7 +251,8 @@ static int get_set_conduit_method(struct device_node *np) return 0; } -static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd) +static int psci_sys_reset(struct notifier_block *this, + unsigned long reboot_mode, void *cmd) { if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) && psci_system_reset2_supported) { @@ -263,6 +265,8 @@ static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd) } else { invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); } + + return NOTIFY_DONE; } static void psci_sys_poweroff(void) @@ -562,6 +566,8 @@ static void __init psci_init_smccc(void) static void __init psci_0_2_set_functions(void) { + int ret; + pr_info("Using standard PSCI v0.2 function IDs\n"); psci_ops.get_version = psci_get_version; @@ -582,7 +588,14 @@ static void __init psci_0_2_set_functions(void) psci_ops.migrate_info_type = psci_migrate_info_type; - arm_pm_restart = psci_sys_reset; + psci_restart_handler.notifier_call = psci_sys_reset; + psci_restart_handler.priority = 160; + + ret = register_restart_handler(&psci_restart_handler); + if (ret) { + pr_err("Cannot register restart handler, %d\n", ret); + return; + } pm_power_off = psci_sys_poweroff; } diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c index d32885b906ae..751c4000870e 100644 --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c @@ -175,6 +175,7 @@ static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev) static int dumb_vga_probe(struct platform_device *pdev) { struct dumb_vga *vga; + u32 de; vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL); if (!vga) @@ -190,6 +191,23 @@ static int dumb_vga_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret); } + vga->bridge.funcs = &dumb_vga_bridge_funcs; + vga->bridge.of_node = pdev->dev.of_node; + vga->bridge.timings = of_device_get_match_data(&pdev->dev); + + if (!vga->bridge.timings && + !of_property_read_u32(pdev->dev.of_node, "de-active", &de)) { + struct drm_bridge_timings *timings; + + timings = devm_kzalloc(&pdev->dev, sizeof(*timings), GFP_KERNEL); + if (!timings) + return -ENOMEM; + + timings->input_bus_flags = de ? DRM_BUS_FLAG_DE_HIGH : + DRM_BUS_FLAG_DE_LOW; + vga->bridge.timings = timings; + } + vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev); if (IS_ERR(vga->ddc)) { if (PTR_ERR(vga->ddc) == -ENODEV) { @@ -201,10 +219,6 @@ static int dumb_vga_probe(struct platform_device *pdev) } } - vga->bridge.funcs = &dumb_vga_bridge_funcs; - vga->bridge.of_node = pdev->dev.of_node; - vga->bridge.timings = of_device_get_match_data(&pdev->dev); - drm_bridge_add(&vga->bridge); return 0; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 5418a1a87b2c..8453fc05dcf2 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -4,7 +4,9 @@ */ #include <linux/clk.h> +#include <linux/cma.h> #include <linux/component.h> +#include <linux/dma-contiguous.h> #include <linux/dma-fence.h> #include <linux/moduleparam.h> #include <linux/of_device.h> @@ -724,11 +726,18 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) */ if (!(gpu->identity.features & chipFeatures_PIPE_3D) || (gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) { - u32 dma_mask = (u32)dma_get_required_mask(gpu->dev); - if (dma_mask < PHYS_OFFSET + SZ_2G) + struct cma *cma = dev_get_cma_area(gpu->dev); + phys_addr_t end_mask; + + if (cma) + end_mask = cma_get_base(cma) - 1 + cma_get_size(cma); + else + end_mask = dma_get_required_mask(gpu->dev); + + if (end_mask < PHYS_OFFSET + SZ_2G) gpu->memory_base = PHYS_OFFSET; else - gpu->memory_base = dma_mask - SZ_2G + 1; + gpu->memory_base = end_mask - SZ_2G + 1; } else if (PHYS_OFFSET >= SZ_2G) { dev_info(gpu->dev, "Need to move linear window on MC1.0, disabling TS\n"); gpu->memory_base = PHYS_OFFSET; diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 1a76de1e8e7b..5e8ea973bc71 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -231,6 +231,9 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data) if (ret && ret != -ENODEV) return ret; + if (imxpd->bridge && imxpd->bridge->timings) + imxpd->bus_flags = imxpd->bridge->timings->input_bus_flags; + imxpd->dev = dev; ret = imx_pd_register(drm, imxpd); diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c index 1ec57d0806a8..200c6169daa5 100644 --- a/drivers/gpu/drm/panel/panel-lvds.c +++ b/drivers/gpu/drm/panel/panel-lvds.c @@ -23,6 +23,11 @@ #include <drm/drm_crtc.h> #include <drm/drm_panel.h> +enum panel_type { + PANEL_LVDS, + PANEL_DPI +}; + struct panel_lvds { struct drm_panel panel; struct device *dev; @@ -124,7 +129,9 @@ static int panel_lvds_get_modes(struct drm_panel *panel) connector->display_info.height_mm = lvds->height; drm_display_info_set_bus_formats(&connector->display_info, &lvds->bus_format, 1); - connector->display_info.bus_flags = lvds->data_mirror + drm_bus_flags_from_videomode(&lvds->video_mode, + &connector->display_info.bus_flags); + connector->display_info.bus_flags |= lvds->data_mirror ? DRM_BUS_FLAG_DATA_LSB_TO_MSB : DRM_BUS_FLAG_DATA_MSB_TO_LSB; @@ -145,6 +152,7 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds) struct display_timing timing; const char *mapping; int ret; + enum panel_type type; ret = of_get_display_timing(np, "panel-timing", &timing); if (ret < 0) @@ -174,13 +182,30 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds) return -ENODEV; } - if (!strcmp(mapping, "jeida-18")) { - lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG; - } else if (!strcmp(mapping, "jeida-24")) { - lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA; - } else if (!strcmp(mapping, "vesa-24")) { - lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG; - } else { + type = (enum panel_type)of_device_get_match_data(lvds->dev); + switch (type) { + case PANEL_LVDS: + if (!strcmp(mapping, "jeida-18")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG; + } else if (!strcmp(mapping, "jeida-24")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA; + } else if (!strcmp(mapping, "vesa-24")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG; + } + break; + case PANEL_DPI: + if (!strcmp(mapping, "rgb24")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB888_1X24; + } else if (!strcmp(mapping, "rgb565")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB565_1X16; + } else if (!strcmp(mapping, "bgr666")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X18; + } else if (!strcmp(mapping, "lvds666")) { + lvds->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; + } + }; + + if (!lvds->bus_format) { dev_err(lvds->dev, "%pOF: invalid or missing %s DT property\n", np, "data-mapping"); return -EINVAL; @@ -288,7 +313,8 @@ static int panel_lvds_remove(struct platform_device *pdev) } static const struct of_device_id panel_lvds_of_table[] = { - { .compatible = "panel-lvds", }, + { .compatible = "panel-lvds", .data = (void *)PANEL_LVDS }, + { .compatible = "panel-dpi", .data = (void *)PANEL_DPI }, { /* Sentinel */ }, }; @@ -298,7 +324,7 @@ static struct platform_driver panel_lvds_driver = { .probe = panel_lvds_probe, .remove = panel_lvds_remove, .driver = { - .name = "panel-lvds", + .name = "panel-generic", .of_match_table = panel_lvds_of_table, }, }; diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 15f6cde6452f..0f8f8b1267b0 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -407,7 +407,7 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) dma->chan_using = NULL; } -static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) +static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic) { unsigned long orig_jiffies = jiffies; unsigned int temp; @@ -437,15 +437,39 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) "<%s> I2C bus is busy\n", __func__); return -ETIMEDOUT; } - schedule(); + if (!atomic) + schedule(); + else + udelay(100); } return 0; } -static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) +static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic) { - wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); + if (!atomic) { + wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); + } else { + int counter = 0; + + while (1) { + unsigned int reg; + + reg = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); + i2c_imx->i2csr = reg; + if (reg & I2SR_IIF) + break; + + if (counter > 1000) { + dev_err(&i2c_imx->adapter.dev, "<%s> TXR timeout\n", __func__); + return -EIO; + } + udelay(100); + counter++; + } + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); + } if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); @@ -523,7 +547,7 @@ static int i2c_imx_clk_notifier_call(struct notifier_block *nb, return NOTIFY_OK; } -static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) +static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic) { unsigned int temp = 0; int result; @@ -536,23 +560,32 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR); /* Wait controller to be stable */ - usleep_range(50, 150); + if (!atomic) + usleep_range(50, 150); + else + udelay(50); /* Start I2C transaction */ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp |= I2CR_MSTA; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - result = i2c_imx_bus_busy(i2c_imx, 1); + result = i2c_imx_bus_busy(i2c_imx, 1, atomic); if (result) return result; - temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; + if (!atomic) { + temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; + } else { + temp |= I2CR_MTX | I2CR_TXAK; + temp &= ~I2CR_IIEN; /* Disable interrupt */ + } + temp &= ~I2CR_DMAEN; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); return result; } -static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) +static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic) { unsigned int temp = 0; @@ -574,7 +607,7 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) } if (!i2c_imx->stopped) - i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx_bus_busy(i2c_imx, 0, atomic); /* Disable I2C controller */ temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, @@ -655,7 +688,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx, /* The last data byte must be transferred by the CPU. */ imx_i2c_write_reg(msgs->buf[msgs->len-1], i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, false); if (result) return result; @@ -714,7 +747,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, msgs->buf[msgs->len-2] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* read n byte data */ - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, false); if (result) return result; @@ -727,7 +760,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx_bus_busy(i2c_imx, 0, false); } else { /* * For i2c master receiver repeat restart operation like: @@ -745,7 +778,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, return 0; } -static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) +static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool atomic) { int i, result; @@ -754,7 +787,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) /* write slave address */ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; result = i2c_imx_acked(i2c_imx); @@ -768,7 +801,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) "<%s> write byte: B%d=0x%X\n", __func__, i, msgs->buf[i]); imx_i2c_write_reg(msgs->buf[i], i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; result = i2c_imx_acked(i2c_imx); @@ -778,7 +811,7 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) return 0; } -static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool is_lastmsg) +static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool is_lastmsg, bool atomic) { int i, result; unsigned int temp; @@ -791,7 +824,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo /* write slave address */ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; result = i2c_imx_acked(i2c_imx); @@ -824,7 +857,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo for (i = 0; i < msgs->len; i++) { u8 len = 0; - result = i2c_imx_trx_complete(i2c_imx); + result = i2c_imx_trx_complete(i2c_imx, atomic); if (result) return result; /* @@ -852,7 +885,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~(I2CR_MSTA | I2CR_MTX); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx_bus_busy(i2c_imx, 0, atomic); } else { /* * For i2c master receiver repeat restart operation like: @@ -883,8 +916,8 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo return 0; } -static int i2c_imx_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, int num) +static int i2c_imx_xfer_common(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num, bool atomic) { unsigned int i, temp; int result; @@ -898,11 +931,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, goto out; /* Start I2C transfer */ - result = i2c_imx_start(i2c_imx); + result = i2c_imx_start(i2c_imx, atomic); if (result) { if (i2c_imx->adapter.bus_recovery_info) { i2c_recover_bus(&i2c_imx->adapter); - result = i2c_imx_start(i2c_imx); + result = i2c_imx_start(i2c_imx, atomic); } } @@ -920,7 +953,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp |= I2CR_RSTA; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - result = i2c_imx_bus_busy(i2c_imx, 1); + result = i2c_imx_bus_busy(i2c_imx, 1, atomic); if (result) goto fail0; } @@ -944,13 +977,17 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, (temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0), (temp & I2SR_RXAK ? 1 : 0)); #endif - if (msgs[i].flags & I2C_M_RD) - result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg); - else { - if (i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD) - result = i2c_imx_dma_write(i2c_imx, &msgs[i]); - else - result = i2c_imx_write(i2c_imx, &msgs[i]); + if (msgs[i].flags & I2C_M_RD) { + result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic); + } else { + if (!atomic) { + if (i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD) + result = i2c_imx_dma_write(i2c_imx, &msgs[i]); + else + result = i2c_imx_write(i2c_imx, &msgs[i], atomic); + } else { + result = i2c_imx_write(i2c_imx, &msgs[i], atomic); + } } if (result) goto fail0; @@ -958,7 +995,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, fail0: /* Stop I2C transfer */ - i2c_imx_stop(i2c_imx); + i2c_imx_stop(i2c_imx, atomic); pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent); pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent); @@ -970,6 +1007,18 @@ out: return (result < 0) ? result : num; } +static int i2c_imx_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + return i2c_imx_xfer_common(adapter, msgs, num, false); +} + +static int i2c_imx_xfer_atomic(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + return i2c_imx_xfer_common(adapter, msgs, num, true); +} + static void i2c_imx_prepare_recovery(struct i2c_adapter *adap) { struct imx_i2c_struct *i2c_imx; @@ -1042,8 +1091,9 @@ static u32 i2c_imx_func(struct i2c_adapter *adapter) } static const struct i2c_algorithm i2c_imx_algo = { - .master_xfer = i2c_imx_xfer, - .functionality = i2c_imx_func, + .master_xfer = i2c_imx_xfer, + .master_xfer_atomic = i2c_imx_xfer_atomic, + .functionality = i2c_imx_func, }; static int i2c_imx_probe(struct platform_device *pdev) @@ -1121,6 +1171,14 @@ static int i2c_imx_probe(struct platform_device *pdev) /* Set up platform driver data */ platform_set_drvdata(pdev, i2c_imx); + /* + * Driver's PM callbacks are safe to be called in atomic contexts. + * Providing this information to the PM subsystem is required for the + * 'master_xfer_atomic' implementation that calls PM routines in IRQ + * less/atomic contexts. + */ + pm_runtime_irq_safe(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_active(&pdev->dev); diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 63dedec0433d..e17054fdd9e0 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -1033,8 +1033,6 @@ static struct phy_driver ksphy_driver[] = { .get_sset_count = kszphy_get_sset_count, .get_strings = kszphy_get_strings, .get_stats = kszphy_get_stats, - .suspend = genphy_suspend, - .resume = genphy_resume, }, { .phy_id = PHY_ID_KSZ8041RNLI, .phy_id_mask = MICREL_PHY_ID_MASK, diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index aabf22eaa6b9..b201ad54463f 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -31,6 +31,7 @@ #include <linux/reset.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> +#include <asm/opcodes.h> #include "pcie-designware.h" @@ -57,6 +58,7 @@ enum imx6_pcie_variants { struct imx6_pcie_drvdata { enum imx6_pcie_variants variant; u32 flags; + int dbi_length; }; struct imx6_pcie { @@ -303,8 +305,14 @@ static int imx6q_pcie_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { unsigned long pc = instruction_pointer(regs); - unsigned long instr = *(unsigned long *)pc; - int reg = (instr >> 12) & 15; + unsigned long instr; + int reg; + + if (user_mode(regs)) + return 1; + + instr = *(unsigned long *)pc; + reg = (instr >> 12) & 15; /* * If the instruction being executed was a read, @@ -373,6 +381,59 @@ static int imx6_pcie_attach_pd(struct device *dev) return 0; } +static int imx6q_pcie_abort_handler_thumb2(unsigned long addr, + unsigned int fsr, struct pt_regs *regs) +{ + unsigned long pc = instruction_pointer(regs); + unsigned long instr; + + if (user_mode(regs)) + return 1; + + instr = __mem_to_opcode_thumb32(*(unsigned long *)pc); + + if (__opcode_is_thumb32(instr)) { + /* Load word/byte and halfword immediate offset */ + if ((instr & 0xff100000UL) == 0xf8100000UL) { + int reg = (instr >> 12) & 0xf; + unsigned long val; + + if ((instr & 0x00700000UL) == 0x00100000UL) + val = 0xff; + else if ((instr & 0x00700000UL) == 0x00300000UL) + val = 0xffff; + else + val = 0xffffffffUL; + + regs->uregs[reg] = val; + regs->ARM_pc += 4; + return 0; + } + } else { + instr = __mem_to_opcode_thumb16(*(unsigned long *)pc); + + /* Load word/byte and halfword immediate offset */ + if (((instr & 0xe800) == 0x6800) || + ((instr & 0xf800) == 0x8800)) { + int reg = instr & 0x7; + unsigned long val; + + if (instr & 0x1000) + val = 0xff; + else if (instr & 0x8000) + val = 0xffff; + else + val = 0xffffffffUL; + + regs->uregs[reg] = val; + regs->ARM_pc += 2; + return 0; + } + } + + return 1; +} + static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) { struct device *dev = imx6_pcie->pci->dev; @@ -1212,6 +1273,7 @@ static const struct imx6_pcie_drvdata drvdata[] = { .variant = IMX6Q, .flags = IMX6_PCIE_FLAG_IMX6_PHY | IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, + .dbi_length = 0x200, }, [IMX6SX] = { .variant = IMX6SX, @@ -1254,9 +1316,42 @@ static struct platform_driver imx6_pcie_driver = { .shutdown = imx6_pcie_shutdown, }; +static void imx6_pcie_quirk(struct pci_dev *dev) +{ + struct pci_bus *bus = dev->bus; + struct pcie_port *pp = bus->sysdata; + + /* Bus parent is the PCI bridge, its parent is this platform driver */ + if (!bus->dev.parent || !bus->dev.parent->parent) + return; + + /* Make sure we only quirk devices associated with this driver */ + if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver) + return; + + if (bus->number == pp->root_bus_nr) { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); + + /* + * Limit config length to avoid the kernel reading beyond + * the register set and causing an abort on i.MX 6Quad + */ + if (imx6_pcie->drvdata->dbi_length) { + dev->cfg_size = imx6_pcie->drvdata->dbi_length; + dev_info(&dev->dev, "Limiting cfg_size to %d\n", + dev->cfg_size); + } + } +} +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, + PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk); + static int __init imx6_pcie_init(void) { #ifdef CONFIG_ARM + bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); + /* * Since probe() can be deferred we need to make sure that * hook_fault_code is not called after __init memory is freed @@ -1264,7 +1359,8 @@ static int __init imx6_pcie_init(void) * we can install the handler here without risking it * accessing some uninitialized driver state. */ - hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0, + hook_fault_code(8, thumb2 ? imx6q_pcie_abort_handler_thumb2 : + imx6q_pcie_abort_handler, SIGBUS, 0, "external abort on non-linefetch"); #endif diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 255786f2e844..c43ad883548a 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -665,6 +665,7 @@ static const struct of_device_id spidev_dt_ids[] = { { .compatible = "lwn,bk4" }, { .compatible = "dh,dhcom-board" }, { .compatible = "menlo,m53cpld" }, + { .compatible = "toradex,evalspi" }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 57d6e6ba556e..49c622bf2fd3 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1957,7 +1957,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) * If the port was already initialised (eg, by a boot loader), * try to determine the current setup. */ -static void __init +static void imx_uart_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { @@ -2016,7 +2016,7 @@ imx_uart_console_get_options(struct imx_port *sport, int *baud, } } -static int __init +static int imx_uart_console_setup(struct console *co, char *options) { struct imx_port *sport; @@ -2076,7 +2076,7 @@ static struct console imx_uart_console = { .data = &imx_uart_uart_driver, }; -#define IMX_CONSOLE &imx_uart_console +#define IMX_CONSOLE (&imx_uart_console) #ifdef CONFIG_OF static void imx_uart_console_early_putchar(struct uart_port *port, int ch) @@ -2369,8 +2369,17 @@ static int imx_uart_probe(struct platform_device *pdev) static int imx_uart_remove(struct platform_device *pdev) { struct imx_port *sport = platform_get_drvdata(pdev); + int ret; + + ret = uart_remove_one_port(&imx_uart_uart_driver, &sport->port); - return uart_remove_one_port(&imx_uart_uart_driver, &sport->port); + if (IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE) && IMX_CONSOLE->index >= 0) { + clk_unprepare(sport->clk_ipg); + clk_unprepare(sport->clk_per); + IMX_CONSOLE->index = -1; + } + + return ret; } static void imx_uart_restore_context(struct imx_port *sport) @@ -44,11 +44,13 @@ phys_addr_t cma_get_base(const struct cma *cma) { return PFN_PHYS(cma->base_pfn); } +EXPORT_SYMBOL_GPL(cma_get_base); unsigned long cma_get_size(const struct cma *cma) { return cma->count << PAGE_SHIFT; } +EXPORT_SYMBOL_GPL(cma_get_size); const char *cma_get_name(const struct cma *cma) { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 44f899b970c2..77768d325060 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1988,9 +1988,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) mutex_lock(&client_mutex); for_each_card_prelinks(card, i, dai_link) { ret = soc_init_dai_link(card, dai_link); - if (ret) { + if (ret && ret != -EPROBE_DEFER) { dev_err(card->dev, "ASoC: failed to init link %s: %d\n", dai_link->name, ret); + } + if (ret) { mutex_unlock(&client_mutex); return ret; } |