| From 06fa6c7a04358c4f91eb80a6876febdf3d3e5f78 Mon Sep 17 00:00:00 2001 |
| From: YH Lin <yueherngl@google.com> |
| Date: Wed, 22 May 2019 07:59:40 -0700 |
| Subject: [PATCH 2/8] Squash MTK ToT #151. |
| |
| Change-Id: Ie080c7dac060b7311398c783245a27082bcad854 |
| --- |
| .../display/mediatek/mediatek,dsi.txt | 2 +- |
| .../devicetree/bindings/mailbox/mtk-gce.txt | 37 +- |
| .../bindings/media/mediatek-vpu.txt | 2 +- |
| .../devicetree/bindings/mfd/cros-ec.txt | 5 +- |
| Makefile | 1 + |
| README | 1 + |
| arch/arm64/boot/dts/mediatek/Makefile | 1 + |
| arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 4 + |
| .../boot/dts/mediatek/mt8183-kukui-rev1.dts | 11 + |
| .../arm64/boot/dts/mediatek/mt8183-kukui.dtsi | 295 ++++++++- |
| arch/arm64/boot/dts/mediatek/mt8183.dtsi | 600 +++++++++++++++++- |
| .../arm64/chromiumos-arm64.flavour.config | 29 +- |
| .../arm64/chromiumos-mediatek.flavour.config | 47 +- |
| .../arm64/chromiumos-qualcomm.flavour.config | 7 + |
| .../chromiumos-rockchip64.flavour.config | 6 + |
| chromeos/config/arm64/common.config | 2 +- |
| chromeos/config/armel/common.config | 6 + |
| chromeos/config/base.config | 6 - |
| chromeos/config/x86_64/common.config | 8 +- |
| drivers/bluetooth/hci_qca.c | 2 + |
| drivers/clk/mediatek/Makefile | 2 + |
| drivers/clk/mediatek/clk-mt8183.c | 10 +- |
| drivers/clk/mediatek/clk-mtk.h | 3 + |
| drivers/clk/mediatek/reset.c | 57 +- |
| drivers/gpu/drm/mediatek/Makefile | 2 + |
| drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +- |
| drivers/gpu/drm/mediatek/mtk_dsi.c | 240 +++++-- |
| drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 344 +--------- |
| drivers/gpu/drm/panel/panel-innolux-p079zca.c | 139 +++- |
| drivers/mailbox/Kconfig | 18 + |
| drivers/mailbox/Makefile | 1 + |
| drivers/mailbox/mtk-cmdq-mailbox.c | 99 ++- |
| drivers/media/platform/mtk-vpu/mtk_vpu.c | 425 ++++++++++--- |
| drivers/media/platform/mtk-vpu/mtk_vpu.h | 25 + |
| drivers/memory/Kconfig | 9 + |
| drivers/memory/Makefile | 1 + |
| drivers/mfd/cros_ec_dev.c | 10 + |
| drivers/mmc/host/Makefile | 2 +- |
| drivers/mmc/host/mtk-sd.c | 5 + |
| drivers/net/wireless/ath/ath10k/core.c | 36 +- |
| drivers/net/wireless/ath/ath10k/htt_rx.c | 4 +- |
| drivers/net/wireless/ath/ath10k/htt_tx.c | 16 +- |
| drivers/net/wireless/ath/ath10k/hw.h | 4 + |
| drivers/net/wireless/ath/ath10k/sdio.c | 2 - |
| drivers/net/wireless/ath/ath10k/txrx.c | 2 +- |
| drivers/pwm/pwm-mtk-disp.c | 54 +- |
| drivers/remoteproc/Kconfig | 10 + |
| drivers/remoteproc/Makefile | 1 + |
| drivers/rpmsg/Kconfig | 9 + |
| drivers/rpmsg/Makefile | 1 + |
| drivers/soc/mediatek/mtk-cmdq-helper.c | 215 ++++++- |
| drivers/tty/serial/8250/8250_mtk.c | 497 +++++++++++++-- |
| drivers/usb/mtu3/mtu3_core.c | 14 +- |
| drivers/usb/mtu3/mtu3_dr.c | 2 +- |
| include/linux/mailbox/mtk-cmdq-mailbox.h | 5 + |
| include/linux/mfd/cros_ec.h | 1 + |
| include/linux/mfd/cros_ec_commands.h | 10 + |
| include/linux/soc/mediatek/mtk-cmdq.h | 62 +- |
| sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 16 + |
| 59 files changed, 2797 insertions(+), 630 deletions(-) |
| |
| diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt |
| index fadf327c7cdf7..bd68195458b9b 100644 |
| --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt |
| +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt |
| @@ -26,7 +26,7 @@ The MIPI TX configuration module controls the MIPI D-PHY. |
| |
| Required properties: |
| - compatible: "mediatek,<chip>-mipi-tx" |
| - the supported chips are mt2701 and mt8173. |
| + the supported chips are mt2701 , mt8173 and mt8183. |
| - reg: Physical base address and length of the controller's registers |
| - clocks: PLL reference clock |
| - clock-output-names: name of the output clock line to the DSI encoder |
| diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt |
| index 7d72b21c9e94d..755b30fd6041b 100644 |
| --- a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt |
| +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt |
| @@ -9,7 +9,7 @@ CMDQ driver uses mailbox framework for communication. Please refer to |
| mailbox.txt for generic information about mailbox device-tree bindings. |
| |
| Required properties: |
| -- compatible: Must be "mediatek,mt8173-gce" |
| +- compatible: can be "mediatek,mt8173-gce" or "mediatek,mt8183-gce" |
| - reg: Address range of the GCE unit |
| - interrupts: The interrupt signal from the GCE block |
| - clock: Clocks according to the common clock binding |
| @@ -21,15 +21,31 @@ Required properties: |
| priority: Priority of GCE thread. |
| atomic_exec: GCE processing continuous packets of commands in atomic |
| way. |
| +- #event-cells: Should be 1. |
| + <&phandle event_number> |
| + phandle: Label name of a gce node. |
| + event_number: the event number defined in 'dt-bindings/gce/mt8173-gce.h' |
| + or 'dt-binding/gce/mt8183-gce.h'. |
| +- #subsys-cells: Should be 3. |
| + <&phandle subsys_number start_offset size> |
| + phandle: Label name of a gce node. |
| + subsys_number: specify the sub-system id which is corresponding |
| + to the register address. |
| + start_offset: the start offset of register address that GCE can access. |
| + size: the total size of register address that GCE can access. |
| |
| Required properties for a client device: |
| - mboxes: Client use mailbox to communicate with GCE, it should have this |
| property and list of phandle, mailbox specifiers. |
| -- mediatek,gce-subsys: u32, specify the sub-system id which is corresponding |
| +Optional propertier for a client device: |
| +- mediatek,gce-client-reg: u32, specify the sub-system id which is corresponding |
| to the register address. |
| +- mediatek,gce-event-names: the event name can be defined by user. |
| +- mediatek,gce-events: u32, the event number defined in |
| + 'dt-bindings/gce/mt8173-gce.h' or 'dt-binding/gce/mt8183-gce.h'. |
| |
| -Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. Such as |
| -sub-system ids, thread priority, event ids. |
| +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h' |
| +or 'dt-binding/gce/mt8183-gce.h'. Such as sub-system ids, thread priority, event ids. |
| |
| Example: |
| |
| @@ -39,8 +55,9 @@ Example: |
| interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>; |
| clocks = <&infracfg CLK_INFRA_GCE>; |
| clock-names = "gce"; |
| - thread-num = CMDQ_THR_MAX_COUNT; |
| #mbox-cells = <3>; |
| + #event-cells = <1>; |
| + #subsys-cells = <2>; |
| }; |
| |
| Example for a client device: |
| @@ -49,9 +66,11 @@ Example for a client device: |
| compatible = "mediatek,mt8173-mmsys"; |
| mboxes = <&gce 0 CMDQ_THR_PRIO_LOWEST 1>, |
| <&gce 1 CMDQ_THR_PRIO_LOWEST 1>; |
| - mediatek,gce-subsys = <SUBSYS_1400XXXX>; |
| - mutex-event-eof = <CMDQ_EVENT_MUTEX0_STREAM_EOF |
| - CMDQ_EVENT_MUTEX1_STREAM_EOF>; |
| - |
| + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x3000 0x1000>, |
| + <&gce SUBSYS_1401XXXX 0x2000 0x100>; |
| + mediatek,gce-event-names = "rdma0_sof", |
| + "rsz0_sof"; |
| + mediatek,gce-events = <&gce CMDQ_EVENT_MDP_RDMA0_SOF>, |
| + <&gce CMDQ_EVENT_MDP_RSZ0_SOF>; |
| ... |
| }; |
| diff --git a/Documentation/devicetree/bindings/media/mediatek-vpu.txt b/Documentation/devicetree/bindings/media/mediatek-vpu.txt |
| index 2a5bac37f9a22..015123250b825 100644 |
| --- a/Documentation/devicetree/bindings/media/mediatek-vpu.txt |
| +++ b/Documentation/devicetree/bindings/media/mediatek-vpu.txt |
| @@ -4,7 +4,7 @@ Video Processor Unit is a HW video controller. It controls HW Codec including |
| H.264/VP8/VP9 Decode, H.264/VP8 Encode and Image Processor (scale/rotate/color convert). |
| |
| Required properties: |
| - - compatible: "mediatek,mt8173-vpu" |
| + - compatible:"mediatek,mt8173-vpu", "mediatek,mt8183-vpu", "mediatek,reserve-memory-vpu_share" |
| - reg: Must contain an entry for each entry in reg-names. |
| - reg-names: Must include the following entries: |
| "tcm": tcm base |
| diff --git a/Documentation/devicetree/bindings/mfd/cros-ec.txt b/Documentation/devicetree/bindings/mfd/cros-ec.txt |
| index 6245c9b1a68bb..4860eabd0f729 100644 |
| --- a/Documentation/devicetree/bindings/mfd/cros-ec.txt |
| +++ b/Documentation/devicetree/bindings/mfd/cros-ec.txt |
| @@ -3,7 +3,7 @@ ChromeOS Embedded Controller |
| Google's ChromeOS EC is a Cortex-M device which talks to the AP and |
| implements various function such as keyboard and battery charging. |
| |
| -The EC can be connect through various means (I2C, SPI, LPC) and the |
| +The EC can be connect through various means (I2C, SPI, LPC, RPMSG) and the |
| compatible string used depends on the interface. Each connection method has |
| its own driver which connects to the top level interface-agnostic EC driver. |
| Other Linux driver (such as cros-ec-keyb for the matrix keyboard) connect to |
| @@ -17,6 +17,9 @@ Required properties (SPI): |
| - compatible: "google,cros-ec-spi" |
| - reg: SPI chip select |
| |
| +Required properties (RPMSG): |
| +- compatible: "google,cros-ec-rpmsg" |
| + |
| Optional properties (SPI): |
| - google,cros-ec-spi-pre-delay: Some implementations of the EC need a little |
| time to wake up from sleep before they can receive SPI transfers at a high |
| diff --git a/Makefile b/Makefile |
| index cb22f3dc7848f..520a4f465963b 100644 |
| --- a/Makefile |
| +++ b/Makefile |
| @@ -1,3 +1,4 @@ |
| +# kukui ToT! |
| # SPDX-License-Identifier: GPL-2.0 |
| VERSION = 4 |
| PATCHLEVEL = 19 |
| diff --git a/README b/README |
| index 2c927ccbd9705..768caa3970ef9 100644 |
| --- a/README |
| +++ b/README |
| @@ -1,3 +1,4 @@ |
| +MTK TOT |
| Linux kernel |
| ============ |
| |
| diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile |
| index d9124842fdd08..3a55c454b65dd 100644 |
| --- a/arch/arm64/boot/dts/mediatek/Makefile |
| +++ b/arch/arm64/boot/dts/mediatek/Makefile |
| @@ -9,3 +9,4 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb |
| dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb |
| dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb |
| dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-rev1.dtb |
| +dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-rev2.dtb |
| diff --git a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts |
| index 50dc1e1a6881f..d9980051f9b68 100644 |
| --- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts |
| +++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts |
| @@ -38,6 +38,10 @@ |
| }; |
| }; |
| |
| +&auxadc { |
| + status = "okay"; |
| +}; |
| + |
| &gpu { |
| supply-names = "mali","mali_sram"; |
| mali-supply = <&mt6358_vgpu_reg>; |
| diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-rev1.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-rev1.dts |
| index 46b8f0c16d7b2..9a19b9d7a8fdb 100644 |
| --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-rev1.dts |
| +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-rev1.dts |
| @@ -212,6 +212,17 @@ |
| ""; |
| }; |
| |
| +&scp_pins { |
| + pins_scp_uart { |
| + pinmux = <PINMUX_GPIO11__FUNC_TP_URXD1_AO>, |
| + <PINMUX_GPIO12__FUNC_TP_UTXD1_AO>; |
| + }; |
| +}; |
| + |
| +&i2c6 { |
| + status = "disabled"; |
| +}; |
| + |
| /* Touch reset pin is active-high on rev1. */ |
| &touchscreen { |
| reset-gpios = <&pio 156 0>; |
| diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi |
| index f8e1c7f9f6035..467bc98f551ea 100644 |
| --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi |
| +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi |
| @@ -14,6 +14,17 @@ |
| serial0 = &uart0; |
| }; |
| |
| + backlight_lcd0: backlight_lcd0 { |
| + compatible = "pwm-backlight"; |
| + pwms = <&pwm0 0 500000>; |
| + power-supply = <&bl_pp5000>; |
| + enable-gpios = <&pio 176 0>; |
| + brightness-levels = <0 1023>; |
| + num-interpolated-steps = <1023>; |
| + default-brightness-level = <576>; |
| + status = "okay"; |
| + }; |
| + |
| memory@40000000 { |
| device_type = "memory"; |
| reg = <0 0x40000000 0 0x80000000>; |
| @@ -23,6 +34,31 @@ |
| stdout-path = "serial0:115200n8"; |
| }; |
| |
| + clk32k: oscillator@1 { |
| + compatible = "fixed-clock"; |
| + #clock-cells = <0>; |
| + clock-frequency = <32768>; |
| + clock-output-names = "clk32k"; |
| + }; |
| + |
| + lcd_pp3300: regulator@1 { |
| + compatible = "regulator-fixed"; |
| + regulator-name = "lcd_pp3300"; |
| + regulator-min-microvolt = <3300000>; |
| + regulator-max-microvolt = <3300000>; |
| + regulator-always-on; |
| + regulator-boot-on; |
| + }; |
| + |
| + bl_pp5000: regulator@2 { |
| + compatible = "regulator-fixed"; |
| + regulator-name = "bl_pp5000"; |
| + regulator-min-microvolt = <5000000>; |
| + regulator-max-microvolt = <5000000>; |
| + regulator-always-on; |
| + regulator-boot-on; |
| + }; |
| + |
| reserved_memory: reserved-memory { |
| #address-cells = <2>; |
| #size-cells = <2>; |
| @@ -37,6 +73,94 @@ |
| alloc-ranges = <0 0x40000000 0 0x60000000>; |
| }; |
| }; |
| + |
| + max98357a: max98357a { |
| + compatible = "maxim,max98357a"; |
| + sdmode-gpios = <&pio 175 0>; |
| + }; |
| + |
| + btsco: bt-sco { |
| + compatible = "linux,bt-sco"; |
| + }; |
| + |
| + sound: mt8183-mt6358-ts3a227e-max98357a { |
| + compatible = "mediatek,mt8183_mt6358_ts3a227_max98357"; |
| + mediatek,platform = <&afe>; |
| + mediatek,headset-codec = <&ts3a227e>; |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&aud_pins>; |
| + status = "okay"; |
| + }; |
| +}; |
| + |
| +&afe { |
| + i2s3-share = "I2S2"; |
| + i2s0-share = "I2S5"; |
| +}; |
| + |
| +&cci { |
| + proc-supply = <&mt6358_vproc12_reg>; |
| +}; |
| + |
| +&cpu0 { |
| + proc-supply = <&mt6358_vproc12_reg>; |
| +}; |
| + |
| +&cpu1 { |
| + proc-supply = <&mt6358_vproc12_reg>; |
| +}; |
| + |
| +&cpu2 { |
| + proc-supply = <&mt6358_vproc12_reg>; |
| +}; |
| + |
| +&cpu3 { |
| + proc-supply = <&mt6358_vproc12_reg>; |
| +}; |
| + |
| +&cpu4 { |
| + proc-supply = <&mt6358_vproc11_reg>; |
| +}; |
| + |
| +&cpu5 { |
| + proc-supply = <&mt6358_vproc11_reg>; |
| +}; |
| + |
| +&cpu6 { |
| + proc-supply = <&mt6358_vproc11_reg>; |
| +}; |
| + |
| +&cpu7 { |
| + proc-supply = <&mt6358_vproc11_reg>; |
| +}; |
| + |
| +&dsi0 { |
| + status = "okay"; |
| + #address-cells = <1>; |
| + #size-cells = <0>; |
| + panel: panel@0 { |
| + compatible = "innolux,p079zca"; |
| + reg = <0>; |
| + enable-gpios = <&pio 45 0>; |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&panel_pins_default>; |
| + power-supply = <&lcd_pp3300>; |
| + backlight = <&backlight_lcd0>; |
| + status = "okay"; |
| + port { |
| + panel_in: endpoint { |
| + remote-endpoint = <&dsi_out>; |
| + }; |
| + }; |
| + }; |
| + |
| + ports { |
| + port { |
| + dsi_out: endpoint { |
| + remote-endpoint = <&panel_in>; |
| + }; |
| + }; |
| + }; |
| }; |
| |
| &gpu { |
| @@ -111,6 +235,17 @@ |
| pinctrl-0 = <&i2c5_pins>; |
| status = "okay"; |
| clock-frequency = <100000>; |
| + #address-cells = <1>; |
| + #size-cells = <0>; |
| + |
| + ts3a227e: ts3a227e@3b { |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&ts3a227e_pins>; |
| + compatible = "ti,ts3a227e"; |
| + reg = <0x3b>; |
| + interrupt-parent = <&pio>; |
| + interrupts = <157 IRQ_TYPE_LEVEL_LOW>; |
| + }; |
| }; |
| |
| &i2c6 { |
| @@ -127,6 +262,10 @@ |
| clock-frequency = <100000>; |
| }; |
| |
| +&mipi_tx0 { |
| + status = "okay"; |
| +}; |
| + |
| &mmc0 { |
| status = "okay"; |
| pinctrl-names = "default", "state_uhs"; |
| @@ -173,7 +312,46 @@ |
| regulator-always-on; |
| }; |
| |
| +&mt6358codec { |
| + Avdd-supply = <&mt6358_vaud28_reg>; |
| +}; |
| + |
| &pio { |
| + aud_pins: audiopins { |
| + pins_bus { |
| + pinmux = <PINMUX_GPIO97__FUNC_I2S2_MCK>, |
| + <PINMUX_GPIO98__FUNC_I2S2_BCK>, |
| + <PINMUX_GPIO101__FUNC_I2S2_LRCK>, |
| + <PINMUX_GPIO102__FUNC_I2S2_DI>, |
| + <PINMUX_GPIO3__FUNC_I2S3_DO>, /*i2s to da7219/max98357*/ |
| + <PINMUX_GPIO89__FUNC_I2S5_BCK>, |
| + <PINMUX_GPIO90__FUNC_I2S5_LRCK>, |
| + <PINMUX_GPIO91__FUNC_I2S5_DO>, |
| + <PINMUX_GPIO174__FUNC_I2S0_DI>, /*i2s to wifi/bt*/ |
| + <PINMUX_GPIO136__FUNC_AUD_CLK_MOSI>, |
| + <PINMUX_GPIO137__FUNC_AUD_SYNC_MOSI>, |
| + <PINMUX_GPIO138__FUNC_AUD_DAT_MOSI0>, |
| + <PINMUX_GPIO139__FUNC_AUD_DAT_MOSI1>, |
| + <PINMUX_GPIO140__FUNC_AUD_CLK_MISO>, |
| + <PINMUX_GPIO141__FUNC_AUD_SYNC_MISO>, |
| + <PINMUX_GPIO142__FUNC_AUD_DAT_MISO0>, |
| + <PINMUX_GPIO143__FUNC_AUD_DAT_MISO1>, /*mtkaif3.0*/ |
| + <PINMUX_GPIO169__FUNC_TDM_BCK_2ND>, |
| + <PINMUX_GPIO170__FUNC_TDM_LRCK_2ND>, |
| + <PINMUX_GPIO171__FUNC_TDM_DATA0_2ND>, |
| + <PINMUX_GPIO172__FUNC_TDM_DATA1_2ND>, |
| + <PINMUX_GPIO173__FUNC_TDM_DATA2_2ND>, |
| + <PINMUX_GPIO10__FUNC_TDM_DATA3>; /*8ch-i2s to it6505*/ |
| + }; |
| + }; |
| + |
| + bt_pins: bt_pins { |
| + pins_bt_en { |
| + pinmux = <PINMUX_GPIO120__FUNC_GPIO120>; |
| + output-low; |
| + }; |
| + }; |
| + |
| ec_ap_int_odl: ec_ap_int_odl { |
| pins1 { |
| pinmux = <PINMUX_GPIO151__FUNC_GPIO151>; |
| @@ -344,11 +522,6 @@ |
| pinmux = <PINMUX_GPIO119__FUNC_GPIO119>; |
| output-high; |
| }; |
| - |
| - pins_bt { |
| - pinmux = <PINMUX_GPIO120__FUNC_GPIO120>; |
| - output-high; |
| - }; |
| }; |
| |
| mmc1_pins_uhs: mmc1@0 { |
| @@ -371,6 +544,38 @@ |
| }; |
| }; |
| |
| + panel_pins_default: panel_pins_default { |
| + panel_reset { |
| + pinmux = <PINMUX_GPIO45__FUNC_GPIO45>; |
| + output-low; |
| + bias-pull-up; |
| + }; |
| + }; |
| + |
| + pwm0_pin_default: pwm0_pin_default { |
| + pins1 { |
| + pinmux = <PINMUX_GPIO176__FUNC_GPIO176>; |
| + output-high; |
| + bias-pull-up; |
| + }; |
| + pins2 { |
| + pinmux = <PINMUX_GPIO43__FUNC_DISP_PWM>; |
| + }; |
| + }; |
| + |
| + scp_pins: scp { |
| + pins_eint { |
| + pinmux = <PINMUX_GPIO5__FUNC_TP_GPIO5_AO>, |
| + <PINMUX_GPIO6__FUNC_TP_GPIO6_AO>, |
| + <PINMUX_GPIO7__FUNC_TP_GPIO7_AO>; |
| + }; |
| + |
| + pins_scp_uart { |
| + pinmux = <PINMUX_GPIO110__FUNC_TP_URXD1_AO>, |
| + <PINMUX_GPIO112__FUNC_TP_UTXD1_AO>; |
| + }; |
| + }; |
| + |
| spi_pins_0: spi0@0 { |
| pins_spi{ |
| pinmux = <PINMUX_GPIO85__FUNC_SPI0_MI>, |
| @@ -446,12 +651,72 @@ |
| output-low; |
| }; |
| }; |
| + |
| + ts3a227e_pins: ts3a227e_pins { |
| + pins1 { |
| + pinmux = <PINMUX_GPIO157__FUNC_GPIO157>; |
| + input-enable; |
| + bias-enable; |
| + bias-pull-up; |
| + }; |
| + }; |
| + |
| + uart0_pin: uart0default { |
| + pins_rx { |
| + pinmux = <PINMUX_GPIO95__FUNC_URXD0>; |
| + input-enable; |
| + bias-pull-up; |
| + }; |
| + pins_tx { |
| + pinmux = <PINMUX_GPIO96__FUNC_UTXD0>; |
| + }; |
| + }; |
| + |
| + uart1_pin: uart1default { |
| + pins_rx { |
| + pinmux = <PINMUX_GPIO121__FUNC_URXD1>; |
| + input-enable; |
| + bias-pull-up; |
| + }; |
| + pins_tx { |
| + pinmux = <PINMUX_GPIO115__FUNC_UTXD1>; |
| + }; |
| + pins_rts { |
| + pinmux = <PINMUX_GPIO47__FUNC_URTS1>; |
| + output-enable; |
| + }; |
| + pins_cts { |
| + pinmux = <PINMUX_GPIO46__FUNC_UCTS1>; |
| + input-enable; |
| + }; |
| + }; |
| +}; |
| + |
| +&pwm0 { |
| + status = "okay"; |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&pwm0_pin_default>; |
| +}; |
| + |
| +&scp { |
| + status = "okay"; |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&scp_pins>; |
| + |
| + cros_ec { |
| + compatible = "google,cros-ec-rpmsg"; |
| + mtk,rpmsg-name = "cros-ec-rpmsg"; |
| + }; |
| }; |
| |
| &scpsys { |
| mfg-supply = <&mt6358_vgpu_reg>; |
| }; |
| |
| +&soc_data { |
| + status = "okay"; |
| +}; |
| + |
| &spi0 { |
| pinctrl-names = "default"; |
| pinctrl-0 = <&spi_pins_0>; |
| @@ -546,7 +811,8 @@ |
| }; |
| |
| &ssusb { |
| - dr_mode = "host"; |
| + maximum-speed = "high-speed"; |
| + enable-manual-drd; |
| vusb33-supply = <&mt6358_vusb_reg>; |
| status = "okay"; |
| }; |
| @@ -561,9 +827,26 @@ |
| }; |
| |
| &uart0 { |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&uart0_pin>; |
| status = "okay"; |
| }; |
| |
| +&uart1 { |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&uart1_pin>; |
| + status = "okay"; |
| + |
| + bluetooth: qca6174-bt { |
| + pinctrl-names = "default"; |
| + pinctrl-0 = <&bt_pins>; |
| + status = "okay"; |
| + compatible = "qcom,qca6174-bt"; |
| + enable-gpios = <&pio 120 0>; |
| + clocks = <&clk32k>; |
| + }; |
| +}; |
| + |
| #include <arm/cros-ec-keyboard.dtsi> |
| #include <arm/cros-ec-sbs.dtsi> |
| |
| diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi |
| index 2f55a63f0bfd4..eaf3be4b35689 100644 |
| --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi |
| +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi |
| @@ -6,11 +6,14 @@ |
| */ |
| |
| #include <dt-bindings/clock/mt8183-clk.h> |
| +#include <dt-bindings/gce/mt8183-gce.h> |
| #include <dt-bindings/interrupt-controller/arm-gic.h> |
| #include <dt-bindings/interrupt-controller/irq.h> |
| #include <dt-bindings/memory/mt8183-larb-port.h> |
| #include <dt-bindings/phy/phy.h> |
| #include <dt-bindings/power/mt8183-power.h> |
| +#include <dt-bindings/reset-controller/mt8183-resets.h> |
| +#include <dt-bindings/thermal/thermal.h> |
| #include "mt8183-pinfunc.h" |
| |
| / { |
| @@ -39,6 +42,220 @@ |
| i2c11 = &i2c11; |
| }; |
| |
| + cluster0_opp: opp_table1 { |
| + compatible = "operating-points-v2"; |
| + opp-shared; |
| + opp00 { |
| + opp-hz = /bits/ 64 <793000000>; |
| + opp-microvolt = <650000>; |
| + }; |
| + opp01 { |
| + opp-hz = /bits/ 64 <910000000>; |
| + opp-microvolt = <675000>; |
| + }; |
| + opp02 { |
| + opp-hz = /bits/ 64 <1014000000>; |
| + opp-microvolt = <700000>; |
| + }; |
| + opp03 { |
| + opp-hz = /bits/ 64 <1131000000>; |
| + opp-microvolt = <725000>; |
| + }; |
| + opp04 { |
| + opp-hz = /bits/ 64 <1248000000>; |
| + opp-microvolt = <750000>; |
| + }; |
| + opp05 { |
| + opp-hz = /bits/ 64 <1326000000>; |
| + opp-microvolt = <775000>; |
| + }; |
| + opp06 { |
| + opp-hz = /bits/ 64 <1417000000>; |
| + opp-microvolt = <800000>; |
| + }; |
| + opp07 { |
| + opp-hz = /bits/ 64 <1508000000>; |
| + opp-microvolt = <825000>; |
| + }; |
| + opp08 { |
| + opp-hz = /bits/ 64 <1586000000>; |
| + opp-microvolt = <850000>; |
| + }; |
| + opp09 { |
| + opp-hz = /bits/ 64 <1625000000>; |
| + opp-microvolt = <862500>; |
| + }; |
| + opp10 { |
| + opp-hz = /bits/ 64 <1677000000>; |
| + opp-microvolt = <881250>; |
| + }; |
| + opp11 { |
| + opp-hz = /bits/ 64 <1716000000>; |
| + opp-microvolt = <900000>; |
| + }; |
| + opp12 { |
| + opp-hz = /bits/ 64 <1781000000>; |
| + opp-microvolt = <925000>; |
| + }; |
| + opp13 { |
| + opp-hz = /bits/ 64 <1846000000>; |
| + opp-microvolt = <950000>; |
| + }; |
| + opp14 { |
| + opp-hz = /bits/ 64 <1924000000>; |
| + opp-microvolt = <975000>; |
| + }; |
| + opp15 { |
| + opp-hz = /bits/ 64 <1989000000>; |
| + opp-microvolt = <1000000>; |
| + }; }; |
| + |
| + cluster1_opp: opp_table2 { |
| + compatible = "operating-points-v2"; |
| + opp-shared; |
| + opp00 { |
| + opp-hz = /bits/ 64 <793000000>; |
| + opp-microvolt = <650000>; |
| + }; |
| + opp01 { |
| + opp-hz = /bits/ 64 <910000000>; |
| + opp-microvolt = <675000>; |
| + }; |
| + opp02 { |
| + opp-hz = /bits/ 64 <1014000000>; |
| + opp-microvolt = <700000>; |
| + }; |
| + opp03 { |
| + opp-hz = /bits/ 64 <1131000000>; |
| + opp-microvolt = <725000>; |
| + }; |
| + opp04 { |
| + opp-hz = /bits/ 64 <1248000000>; |
| + opp-microvolt = <750000>; |
| + }; |
| + opp05 { |
| + opp-hz = /bits/ 64 <1326000000>; |
| + opp-microvolt = <775000>; |
| + }; |
| + opp06 { |
| + opp-hz = /bits/ 64 <1417000000>; |
| + opp-microvolt = <800000>; |
| + }; |
| + opp07 { |
| + opp-hz = /bits/ 64 <1508000000>; |
| + opp-microvolt = <825000>; |
| + }; |
| + opp08 { |
| + opp-hz = /bits/ 64 <1586000000>; |
| + opp-microvolt = <850000>; |
| + }; |
| + opp09 { |
| + opp-hz = /bits/ 64 <1625000000>; |
| + opp-microvolt = <862500>; |
| + }; |
| + opp10 { |
| + opp-hz = /bits/ 64 <1677000000>; |
| + opp-microvolt = <881250>; |
| + }; |
| + opp11 { |
| + opp-hz = /bits/ 64 <1716000000>; |
| + opp-microvolt = <900000>; |
| + }; |
| + opp12 { |
| + opp-hz = /bits/ 64 <1781000000>; |
| + opp-microvolt = <925000>; |
| + }; |
| + opp13 { |
| + opp-hz = /bits/ 64 <1846000000>; |
| + opp-microvolt = <950000>; |
| + }; |
| + opp14 { |
| + opp-hz = /bits/ 64 <1924000000>; |
| + opp-microvolt = <975000>; |
| + }; |
| + opp15 { |
| + opp-hz = /bits/ 64 <1989000000>; |
| + opp-microvolt = <1000000>; |
| + }; |
| + }; |
| + |
| + cluster2_opp: opp_table3 { |
| + compatible = "operating-points-v2"; |
| + opp-shared; |
| + opp00 { |
| + opp-hz = /bits/ 64 <273000000>; |
| + opp-microvolt = <650000>; |
| + }; |
| + opp01 { |
| + opp-hz = /bits/ 64 <338000000>; |
| + opp-microvolt = <675000>; |
| + }; |
| + opp02 { |
| + opp-hz = /bits/ 64 <403000000>; |
| + opp-microvolt = <700000>; |
| + }; |
| + opp03 { |
| + opp-hz = /bits/ 64 <463000000>; |
| + opp-microvolt = <725000>; |
| + }; |
| + opp04 { |
| + opp-hz = /bits/ 64 <546000000>; |
| + opp-microvolt = <750000>; |
| + }; |
| + opp05 { |
| + opp-hz = /bits/ 64 <624000000>; |
| + opp-microvolt = <775000>; |
| + }; |
| + opp06 { |
| + opp-hz = /bits/ 64 <689000000>; |
| + opp-microvolt = <800000>; |
| + }; |
| + opp07 { |
| + opp-hz = /bits/ 64 <767000000>; |
| + opp-microvolt = <825000>; |
| + }; |
| + opp08 { |
| + opp-hz = /bits/ 64 <845000000>; |
| + opp-microvolt = <850000>; |
| + }; |
| + opp09 { |
| + opp-hz = /bits/ 64 <871000000>; |
| + opp-microvolt = <862500>; |
| + }; |
| + opp10 { |
| + opp-hz = /bits/ 64 <923000000>; |
| + opp-microvolt = <881250>; |
| + }; |
| + opp11 { |
| + opp-hz = /bits/ 64 <962000000>; |
| + opp-microvolt = <900000>; |
| + }; |
| + opp12 { |
| + opp-hz = /bits/ 64 <1027000000>; |
| + opp-microvolt = <925000>; |
| + }; |
| + opp13 { |
| + opp-hz = /bits/ 64 <1092000000>; |
| + opp-microvolt = <950000>; |
| + }; |
| + opp14 { |
| + opp-hz = /bits/ 64 <1144000000>; |
| + opp-microvolt = <975000>; |
| + }; |
| + opp15 { |
| + opp-hz = /bits/ 64 <1196000000>; |
| + opp-microvolt = <1000000>; |
| + }; |
| + }; |
| + |
| + |
| + cci: cci { |
| + compatible = "mediatek,mt8183-cci"; |
| + clocks = <&apmixedsys CLK_APMIXED_CCIPLL>; |
| + clock-names = "cci_clock"; |
| + operating-points-v2 = <&cluster2_opp>; |
| + }; |
| + |
| cpus { |
| #address-cells = <1>; |
| #size-cells = <0>; |
| @@ -80,6 +297,13 @@ |
| compatible = "arm,cortex-a53"; |
| reg = <0x000>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <741>; |
| + dynamic-power-coefficient = <84>; |
| + clocks = <&mcucfg CLK_MCU_MP0_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster0_opp>; |
| + #cooling-cells = <2>; |
| }; |
| |
| cpu1: cpu@1 { |
| @@ -87,6 +311,13 @@ |
| compatible = "arm,cortex-a53"; |
| reg = <0x001>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <741>; |
| + dynamic-power-coefficient = <84>; |
| + clocks = <&mcucfg CLK_MCU_MP0_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster0_opp>; |
| + #cooling-cells = <2>; |
| }; |
| |
| cpu2: cpu@2 { |
| @@ -94,6 +325,13 @@ |
| compatible = "arm,cortex-a53"; |
| reg = <0x002>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <741>; |
| + dynamic-power-coefficient = <84>; |
| + clocks = <&mcucfg CLK_MCU_MP0_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster0_opp>; |
| + #cooling-cells = <2>; |
| }; |
| |
| cpu3: cpu@3 { |
| @@ -101,6 +339,13 @@ |
| compatible = "arm,cortex-a53"; |
| reg = <0x003>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <741>; |
| + dynamic-power-coefficient = <84>; |
| + clocks = <&mcucfg CLK_MCU_MP0_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster0_opp>; |
| + #cooling-cells = <2>; |
| }; |
| |
| cpu4: cpu@100 { |
| @@ -108,6 +353,13 @@ |
| compatible = "arm,cortex-a73"; |
| reg = <0x100>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <1024>; |
| + dynamic-power-coefficient = <211>; |
| + clocks = <&mcucfg CLK_MCU_MP2_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster1_opp>; |
| + #cooling-cells = <2>; |
| }; |
| |
| cpu5: cpu@101 { |
| @@ -115,6 +367,13 @@ |
| compatible = "arm,cortex-a73"; |
| reg = <0x101>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <1024>; |
| + dynamic-power-coefficient = <211>; |
| + clocks = <&mcucfg CLK_MCU_MP2_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster1_opp>; |
| + #cooling-cells = <2>; |
| }; |
| |
| cpu6: cpu@102 { |
| @@ -122,6 +381,13 @@ |
| compatible = "arm,cortex-a73"; |
| reg = <0x102>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <1024>; |
| + dynamic-power-coefficient = <211>; |
| + clocks = <&mcucfg CLK_MCU_MP2_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster1_opp>; |
| + #cooling-cells = <2>; |
| }; |
| |
| cpu7: cpu@103 { |
| @@ -129,6 +395,13 @@ |
| compatible = "arm,cortex-a73"; |
| reg = <0x103>; |
| enable-method = "psci"; |
| + capacity-dmips-mhz = <1024>; |
| + dynamic-power-coefficient = <211>; |
| + clocks = <&mcucfg CLK_MCU_MP2_SEL>, |
| + <&topckgen CLK_TOP_ARMPLL_DIV_PLL1>; |
| + clock-names = "cpu", "intermediate"; |
| + operating-points-v2 = <&cluster1_opp>; |
| + #cooling-cells = <2>; |
| }; |
| }; |
| |
| @@ -156,6 +429,24 @@ |
| clock-output-names = "clk26m"; |
| }; |
| |
| + reserved-memory { |
| + #address-cells = <2>; |
| + #size-cells = <2>; |
| + ranges; |
| + reserve-memory-vpu_share { |
| + compatible = "mediatek,reserve-memory-vpu_share"; |
| + no-map; |
| + size = <0 0x01400000>; /*20 MB share mem size */ |
| + alignment = <0 0x1000000>; |
| + alloc-ranges = <0 0x50000000 0 0x10000000>; |
| + }; |
| + scp_mem_reserved: scp_mem_region { |
| + compatible = "shared-dma-pool"; |
| + reg = <0 0x50000000 0 0x2300000>; |
| + no-map; |
| + }; |
| + }; |
| + |
| timer { |
| compatible = "arm,armv8-timer"; |
| interrupt-parent = <&gic>; |
| @@ -171,6 +462,15 @@ |
| compatible = "simple-bus"; |
| ranges; |
| |
| + soc_data: soc_data@8000000 { |
| + compatible = "mediatek,mt8183-efuse", |
| + "mediatek,efuse"; |
| + reg = <0 0x08000000 0 0x0010>; |
| + #address-cells = <1>; |
| + #size-cells = <1>; |
| + status = "disabled"; |
| + }; |
| + |
| gic: interrupt-controller@c000000 { |
| compatible = "arm,gic-v3"; |
| #interrupt-cells = <4>; |
| @@ -218,6 +518,7 @@ |
| compatible = "mediatek,mt8183-infracfg", "syscon"; |
| reg = <0 0x10001000 0 0x1000>; |
| #clock-cells = <1>; |
| + #reset-cells = <1>; |
| }; |
| |
| pio: pinctrl@10005000 { |
| @@ -300,6 +601,12 @@ |
| smi_comm = <&smi_common>; |
| }; |
| |
| + watchdog: watchdog@10007000 { |
| + compatible = "mediatek,mt8183-wdt", |
| + "mediatek,mt6589-wdt"; |
| + reg = <0 0x10007000 0 0x100>; |
| + }; |
| + |
| apmixedsys: syscon@1000c000 { |
| compatible = "mediatek,mt8183-apmixedsys", "syscon"; |
| reg = <0 0x1000c000 0 0x1000>; |
| @@ -325,6 +632,60 @@ |
| #iommu-cells = <1>; |
| }; |
| |
| + emi@10219000 { |
| + compatible = "mediatek,mt8183-emi"; |
| + reg = <0 0x10219000 0 0x1000>, /* CEN EMI */ |
| + <0 0x10226000 0 0x1000>, /* EMI MPU */ |
| + <0 0x1022d000 0 0x1000>, /* CHA EMI */ |
| + <0 0x10235000 0 0x1000>; /* CHB EMI */ |
| + interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_LOW>, /* MPU */ |
| + <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, /* CGM */ |
| + <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; /* ELM */ |
| + }; |
| + |
| + gce: gce@10238000 { |
| + compatible = "mediatek,mt8183-gce"; |
| + reg = <0 0x10238000 0 0x4000>; |
| + interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_LOW>; |
| + #mbox-cells = <3>; |
| + #gce-event-cells = <1>; |
| + #gce-subsys-cells = <2>; |
| + clocks = <&infracfg CLK_INFRA_GCE>; |
| + clock-names = "gce"; |
| + }; |
| + |
| + vpu: vpu@10500000 { |
| + compatible = "mediatek,mt8183-vpu", "mediatek,mt8173-vpu"; |
| + reg = <0 0x10500000 0 0x80000>, |
| + <0 0x105c0000 0 0x1000>; |
| + reg-names = "tcm", "cfg_reg"; |
| + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; |
| + clocks = <&infracfg CLK_INFRA_SCPSYS>; |
| + clock-names = "main"; |
| + status = "disabled"; |
| + }; |
| + |
| + scp: scp@10500000 { |
| + compatible = "mediatek,mt8183-scp"; |
| + reg = <0 0x10500000 0 0x80000>, |
| + <0 0x105c0000 0 0x5000>; |
| + reg-names = "sram", "cfg"; |
| + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; |
| + clocks = <&infracfg CLK_INFRA_SCPSYS>; |
| + clock-names = "main"; |
| + memory-region = <&scp_mem_reserved>; |
| + status = "disabled"; |
| + }; |
| + |
| + auxadc: auxadc@11001000 { |
| + compatible = "mediatek,mt8183-auxadc", "mediatek,mt8173-auxadc"; |
| + reg = <0 0x11001000 0 0x1000>; |
| + clocks = <&infracfg CLK_INFRA_AUXADC>; |
| + clock-names = "main"; |
| + #io-channel-cells = <1>; |
| + status = "disabled"; |
| + }; |
| + |
| uart0: serial@11002000 { |
| compatible = "mediatek,mt8183-uart", |
| "mediatek,mt6577-uart"; |
| @@ -414,6 +775,111 @@ |
| status = "disabled"; |
| }; |
| |
| + thermal: thermal@1100b000 { |
| + #thermal-sensor-cells = <1>; |
| + compatible = "mediatek,mt8183-thermal"; |
| + reg = <0 0x1100b000 0 0x1000>; |
| + interrupts = <0 76 IRQ_TYPE_LEVEL_LOW>; |
| + clocks = <&infracfg CLK_INFRA_THERM>, |
| + <&infracfg CLK_INFRA_AUXADC>; |
| + clock-names = "therm", "auxadc"; |
| + resets = <&infracfg MT8183_INFRACFG_AO_THERM_SW_RST>; |
| + mediatek,auxadc = <&auxadc>; |
| + mediatek,apmixedsys = <&apmixedsys>; |
| + mediatek,hw-reset-temp = <117000>; |
| + nvmem-cells = <&thermal_calibration>; |
| + nvmem-cell-names = "calibration-data"; |
| + }; |
| + |
| + thermal-zones { |
| + cpu_thermal: cpu_thermal { |
| + polling-delay-passive = <100>; /* milliseconds */ |
| + polling-delay = <500>; /* milliseconds */ |
| + |
| + thermal-sensors = <&thermal 0>; |
| + sustainable-power = <1500>; /* milliwatts */ |
| + |
| + trips { |
| + threshold: trip-point@0 { |
| + temperature = <68000>; |
| + hysteresis = <2000>; |
| + type = "passive"; |
| + }; |
| + |
| + target: trip-point@1 { |
| + temperature = <85000>; |
| + hysteresis = <2000>; |
| + type = "passive"; |
| + }; |
| + |
| + cpu_crit: cpu-crit { |
| + temperature = <115000>; |
| + hysteresis = <2000>; |
| + type = "critical"; |
| + }; |
| + }; |
| + |
| + cooling-maps { |
| + map0 { |
| + trip = <&target>; |
| + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, |
| + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, |
| + <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, |
| + <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; |
| + contribution = <3072>; |
| + }; |
| + map1 { |
| + trip = <&target>; |
| + cooling-device = <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, |
| + <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, |
| + <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, |
| + <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; |
| + contribution = <1024>; |
| + }; |
| + map2 { |
| + trip = <&target>; |
| + cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; |
| + contribution = <2048>; |
| + }; |
| + }; |
| + }; |
| + |
| + tzts1: tzts1 { |
| + polling-delay-passive = <1000>; /* milliseconds */ |
| + polling-delay = <1000>; /* milliseconds */ |
| + |
| + thermal-sensors = <&thermal 1>; |
| + }; |
| + |
| + tzts2: tzts2{ |
| + polling-delay-passive = <1000>; /* milliseconds */ |
| + polling-delay = <1000>; /* milliseconds */ |
| + |
| + thermal-sensors = <&thermal 2>; |
| + }; |
| + |
| + tzts3: tzts3{ |
| + polling-delay-passive = <1000>; /* milliseconds */ |
| + polling-delay = <1000>; /* milliseconds */ |
| + |
| + thermal-sensors = <&thermal 3>; |
| + }; |
| + |
| + tzts4: tzts4{ |
| + polling-delay-passive = <1000>; /* milliseconds */ |
| + polling-delay = <1000>; /* milliseconds */ |
| + |
| + thermal-sensors = <&thermal 4>; |
| + }; |
| + |
| + tzts5: tzts5{ |
| + polling-delay-passive = <1000>; /* milliseconds */ |
| + polling-delay = <1000>; /* milliseconds */ |
| + |
| + thermal-sensors = <&thermal 5>; |
| + }; |
| + }; |
| + |
| pwm0: pwm@1100e000 { |
| compatible = "mediatek,mt8183-disp-pwm"; |
| reg = <0 0x1100e000 0 0x1000>; |
| @@ -646,10 +1112,100 @@ |
| }; |
| }; |
| |
| - audiosys: syscon@11220000 { |
| + audiosys: audiosys@11220000 { |
| compatible = "mediatek,mt8183-audiosys", "syscon"; |
| reg = <0 0x11220000 0 0x1000>; |
| #clock-cells = <1>; |
| + |
| + afe: mt8183-afe-pcm { |
| + compatible = "mediatek,mt8183-audio"; |
| + interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>; |
| + power-domains = <&scpsys MT8183_POWER_DOMAIN_AUDIO>; |
| + clocks = <&audiosys CLK_AUDIO_AFE>, |
| + <&audiosys CLK_AUDIO_DAC>, |
| + <&audiosys CLK_AUDIO_DAC_PREDIS>, |
| + <&audiosys CLK_AUDIO_ADC>, |
| + <&audiosys CLK_AUDIO_PDN_ADDA6_ADC>, |
| + <&audiosys CLK_AUDIO_22M>, |
| + <&audiosys CLK_AUDIO_24M>, |
| + <&audiosys CLK_AUDIO_APLL_TUNER>, |
| + <&audiosys CLK_AUDIO_APLL2_TUNER>, |
| + <&audiosys CLK_AUDIO_I2S1>, |
| + <&audiosys CLK_AUDIO_I2S2>, |
| + <&audiosys CLK_AUDIO_I2S3>, |
| + <&audiosys CLK_AUDIO_I2S4>, |
| + <&audiosys CLK_AUDIO_TDM>, |
| + <&audiosys CLK_AUDIO_TML>, |
| + <&infracfg CLK_INFRA_AUDIO>, |
| + <&infracfg CLK_INFRA_AUDIO_26M_BCLK>, |
| + <&topckgen CLK_TOP_MUX_AUDIO>, |
| + <&topckgen CLK_TOP_MUX_AUD_INTBUS>, |
| + <&topckgen CLK_TOP_SYSPLL_D2_D4>, |
| + <&topckgen CLK_TOP_MUX_AUD_1>, |
| + <&topckgen CLK_TOP_APLL1_CK>, |
| + <&topckgen CLK_TOP_MUX_AUD_2>, |
| + <&topckgen CLK_TOP_APLL2_CK>, |
| + <&topckgen CLK_TOP_MUX_AUD_ENG1>, |
| + <&topckgen CLK_TOP_APLL1_D8>, |
| + <&topckgen CLK_TOP_MUX_AUD_ENG2>, |
| + <&topckgen CLK_TOP_APLL2_D8>, |
| + <&topckgen CLK_TOP_MUX_APLL_I2S0>, |
| + <&topckgen CLK_TOP_MUX_APLL_I2S1>, |
| + <&topckgen CLK_TOP_MUX_APLL_I2S2>, |
| + <&topckgen CLK_TOP_MUX_APLL_I2S3>, |
| + <&topckgen CLK_TOP_MUX_APLL_I2S4>, |
| + <&topckgen CLK_TOP_MUX_APLL_I2S5>, |
| + <&topckgen CLK_TOP_APLL12_DIV0>, |
| + <&topckgen CLK_TOP_APLL12_DIV1>, |
| + <&topckgen CLK_TOP_APLL12_DIV2>, |
| + <&topckgen CLK_TOP_APLL12_DIV3>, |
| + <&topckgen CLK_TOP_APLL12_DIV4>, |
| + <&topckgen CLK_TOP_APLL12_DIVB>, |
| + /*<&topckgen CLK_TOP_APLL12_DIV5>,*/ |
| + <&clk26m>; |
| + clock-names = "aud_afe_clk", |
| + "aud_dac_clk", |
| + "aud_dac_predis_clk", |
| + "aud_adc_clk", |
| + "aud_adc_adda6_clk", |
| + "aud_apll22m_clk", |
| + "aud_apll24m_clk", |
| + "aud_apll1_tuner_clk", |
| + "aud_apll2_tuner_clk", |
| + "aud_i2s1_bclk_sw", |
| + "aud_i2s2_bclk_sw", |
| + "aud_i2s3_bclk_sw", |
| + "aud_i2s4_bclk_sw", |
| + "aud_tdm_clk", |
| + "aud_tml_clk", |
| + "aud_infra_clk", |
| + "mtkaif_26m_clk", |
| + "top_mux_audio", |
| + "top_mux_aud_intbus", |
| + "top_syspll_d2_d4", |
| + "top_mux_aud_1", |
| + "top_apll1_ck", |
| + "top_mux_aud_2", |
| + "top_apll2_ck", |
| + "top_mux_aud_eng1", |
| + "top_apll1_d8", |
| + "top_mux_aud_eng2", |
| + "top_apll2_d8", |
| + "top_i2s0_m_sel", |
| + "top_i2s1_m_sel", |
| + "top_i2s2_m_sel", |
| + "top_i2s3_m_sel", |
| + "top_i2s4_m_sel", |
| + "top_i2s5_m_sel", |
| + "top_apll12_div0", |
| + "top_apll12_div1", |
| + "top_apll12_div2", |
| + "top_apll12_div3", |
| + "top_apll12_div4", |
| + "top_apll12_divb", |
| + /*"top_apll12_div5",*/ |
| + "top_clk26m_clk"; |
| + }; |
| }; |
| |
| mmc0: mmc@11230000 { |
| @@ -676,6 +1232,26 @@ |
| status = "disabled"; |
| }; |
| |
| + mipi_tx0: mipi-dphy@11e50000 { |
| + compatible = "mediatek,mt8183-mipi-tx"; |
| + reg = <0 0x11e50000 0 0x1000>; |
| + clocks = <&apmixedsys CLK_APMIXED_MIPID0_26M>; |
| + clock-names = "ref_clk"; |
| + #clock-cells = <0>; |
| + #phy-cells = <0>; |
| + clock-output-names = "mipi_tx0_pll"; |
| + }; |
| + |
| + efuse: efuse@11f10000 { |
| + compatible = "mediatek,efuse"; |
| + reg = <0 0x11f10000 0 0x1000>; |
| + #address-cells = <1>; |
| + #size-cells = <1>; |
| + thermal_calibration: calib@180 { |
| + reg = <0x180 0xc>; |
| + }; |
| + }; |
| + |
| u3phy: usb-phy@11f40000 { |
| compatible = "mediatek,generic-tphy-v2"; |
| #address-cells = <2>; |
| @@ -965,6 +1541,28 @@ |
| clocks = <&mmsys CLK_MM_DISP_DITHER0>; |
| }; |
| |
| + dsi0: dsi@14014000 { |
| + compatible = "mediatek,mt8183-dsi", |
| + "mediatek,mt8183-dsi"; |
| + reg = <0 0x14014000 0 0x1000>; |
| + interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_LOW>; |
| + power-domains = <&scpsys MT8183_POWER_DOMAIN_DISP>; |
| + mediatek,syscon-dsi = <&mmsys 0x140>; |
| + clocks = <&mmsys CLK_MM_DSI0_MM>, |
| + <&mmsys CLK_MM_DSI0_IF>, |
| + <&mipi_tx0>; |
| + clock-names = "engine", "digital", "hs"; |
| + phys = <&mipi_tx0>; |
| + phy-names = "dphy"; |
| + }; |
| + |
| + mutex: mutex@14016000 { |
| + compatible = "mediatek,mt8183-disp-mutex"; |
| + reg = <0 0x14016000 0 0x1000>; |
| + interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_LOW>; |
| + power-domains = <&scpsys MT8183_POWER_DOMAIN_DISP>; |
| + }; |
| + |
| larb0: larb@14017000 { |
| compatible = "mediatek,mt8183-smi-larb"; |
| reg = <0 0x14017000 0 0x1000>; |
| diff --git a/chromeos/config/arm64/chromiumos-arm64.flavour.config b/chromeos/config/arm64/chromiumos-arm64.flavour.config |
| index 14dbbc992e29c..86ef390d61605 100644 |
| --- a/chromeos/config/arm64/chromiumos-arm64.flavour.config |
| +++ b/chromeos/config/arm64/chromiumos-arm64.flavour.config |
| @@ -124,6 +124,7 @@ CONFIG_COMMON_CLK_RK808=y |
| CONFIG_COMMON_CLK_XGENE=y |
| CONFIG_CPUFREQ_DT=y |
| CONFIG_CPUFREQ_DT_PLATDEV=y |
| +CONFIG_CROS_EC_RPMSG=m |
| # CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set |
| # CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set |
| # CONFIG_CRYPTO_DEV_QCE is not set |
| @@ -204,7 +205,7 @@ CONFIG_EFI_STUB=y |
| # CONFIG_EFI_VARS is not set |
| CONFIG_EINT_MTK=y |
| # CONFIG_EMAC_ROCKCHIP is not set |
| -# CONFIG_ENERGY_MODEL is not set |
| +CONFIG_ENERGY_MODEL=y |
| # CONFIG_ENIC is not set |
| # CONFIG_EPIC100 is not set |
| # CONFIG_ET131X is not set |
| @@ -389,13 +390,17 @@ CONFIG_MSM_GCC_8916=y |
| # CONFIG_MTD_INTEL_VR_NOR is not set |
| CONFIG_MTD_MT81xx_NOR=y |
| # CONFIG_MTD_PMC551 is not set |
| -# CONFIG_MTK_CMDQ is not set |
| -# CONFIG_MTK_CMDQ_MBOX is not set |
| +CONFIG_MTK_CMDQ=y |
| +CONFIG_MTK_CMDQ_DEBUG=y |
| +CONFIG_MTK_CMDQ_DEBUG_SOC=8183 |
| +CONFIG_MTK_CMDQ_MBOX=y |
| CONFIG_MTK_EFUSE=y |
| +CONFIG_MTK_EMI_MBW=y |
| # CONFIG_MTK_HSDMA is not set |
| CONFIG_MTK_INFRACFG=y |
| CONFIG_MTK_IOMMU=y |
| CONFIG_MTK_PMIC_WRAP=y |
| +CONFIG_MTK_SCP=m |
| CONFIG_MTK_SCPSYS=y |
| CONFIG_MTK_SMI=y |
| CONFIG_MTK_THERMAL=y |
| @@ -668,6 +673,7 @@ CONFIG_ROCKCHIP_THERMAL=y |
| CONFIG_ROCKCHIP_TIMER=y |
| CONFIG_RPMSG=y |
| CONFIG_RPMSG_CHAR=y |
| +CONFIG_RPMSG_MTK_SCP=m |
| CONFIG_RPMSG_QCOM_GLINK_NATIVE=y |
| CONFIG_RPMSG_QCOM_GLINK_SMEM=y |
| CONFIG_RPMSG_QCOM_SMD=y |
| @@ -920,22 +926,33 @@ CONFIG_TOUCHSCREEN_MELFAS_MIP4=y |
| # CONFIG_TYPHOON is not set |
| CONFIG_UCS2_STRING=y |
| # CONFIG_USB_AMD5536UDC is not set |
| +CONFIG_USB_CONFIGFS=y |
| +CONFIG_USB_CONFIGFS_ACM=y |
| +CONFIG_USB_CONFIGFS_MASS_STORAGE=y |
| +CONFIG_USB_CONFIGFS_SERIAL=y |
| CONFIG_USB_DWC3_HAPS=y |
| CONFIG_USB_DWC3_QCOM=y |
| # CONFIG_USB_EG20T is not set |
| CONFIG_USB_EHCI_PCI=y |
| +CONFIG_USB_F_ACM=y |
| +CONFIG_USB_F_FS=y |
| +CONFIG_USB_F_MASS_STORAGE=y |
| +CONFIG_USB_F_SERIAL=y |
| # CONFIG_USB_GOKU is not set |
| +CONFIG_USB_LIBCOMPOSITE=y |
| CONFIG_USB_MTU3=y |
| -# CONFIG_USB_MTU3_DEBUG is not set |
| -# CONFIG_USB_MTU3_DUAL_ROLE is not set |
| +CONFIG_USB_MTU3_DEBUG=y |
| +CONFIG_USB_MTU3_DUAL_ROLE=y |
| # CONFIG_USB_MTU3_GADGET is not set |
| -CONFIG_USB_MTU3_HOST=y |
| +# CONFIG_USB_MTU3_HOST is not set |
| # CONFIG_USB_NET2280 is not set |
| CONFIG_USB_OHCI_HCD_PCI=y |
| CONFIG_USB_PCI=y |
| # CONFIG_USB_UHCI_HCD is not set |
| +CONFIG_USB_U_SERIAL=y |
| CONFIG_USB_XHCI_MTK=y |
| CONFIG_USB_XHCI_PCI=y |
| +# CONFIG_U_SERIAL_CONSOLE is not set |
| CONFIG_V4L2_MEM2MEM_DEV=y |
| CONFIG_VGA_ARB=y |
| CONFIG_VGA_ARB_MAX_GPUS=16 |
| diff --git a/chromeos/config/arm64/chromiumos-mediatek.flavour.config b/chromeos/config/arm64/chromiumos-mediatek.flavour.config |
| index 30e9317390a8a..cf176ec20448d 100644 |
| --- a/chromeos/config/arm64/chromiumos-mediatek.flavour.config |
| +++ b/chromeos/config/arm64/chromiumos-mediatek.flavour.config |
| @@ -24,6 +24,7 @@ CONFIG_ATH10K_TRACING=y |
| # CONFIG_ATH10K_USB is not set |
| CONFIG_ATH_COMMON=m |
| # CONFIG_BACKLIGHT_GPIO is not set |
| +CONFIG_BLK_MQ_VIRTIO=y |
| # CONFIG_BT_HCIUART_3WIRE is not set |
| # CONFIG_BT_HCIUART_BCM is not set |
| # CONFIG_BT_HCIUART_LL is not set |
| @@ -57,6 +58,9 @@ CONFIG_COMMON_CLK_MT8183_VDECSYS=y |
| CONFIG_COMMON_CLK_MT8183_VENCSYS=y |
| CONFIG_COMMON_CLK_XGENE=y |
| # CONFIG_CPUFREQ_DT is not set |
| +CONFIG_CROS_EC_RPMSG=m |
| +CONFIG_CRYPTO_DEV_VIRTIO=m |
| +CONFIG_CRYPTO_ENGINE=m |
| CONFIG_DRM_ANALOGIX_ANX78XX=y |
| CONFIG_DRM_GEM_CMA_HELPER=y |
| CONFIG_DRM_MEDIATEK=y |
| @@ -75,14 +79,16 @@ CONFIG_DRM_PANEL_INNOLUX_P079ZCA=y |
| # CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set |
| # CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set |
| # CONFIG_DRM_TI_SN65DSI86 is not set |
| +# CONFIG_DRM_VIRTIO_GPU is not set |
| # CONFIG_DW_WATCHDOG is not set |
| # CONFIG_EDAC is not set |
| # CONFIG_EFI is not set |
| CONFIG_EINT_MTK=y |
| -# CONFIG_ENERGY_MODEL is not set |
| +CONFIG_ENERGY_MODEL=y |
| # CONFIG_FAILOVER is not set |
| # CONFIG_HWSPINLOCK is not set |
| CONFIG_HW_RANDOM_MTK=y |
| +# CONFIG_HW_RANDOM_VIRTIO is not set |
| CONFIG_I2C_HID=y |
| CONFIG_I2C_MT65XX=y |
| # CONFIG_I2C_RK3X is not set |
| @@ -114,13 +120,17 @@ CONFIG_MEDIA_CONTROLLER_REQUEST_API=y |
| # CONFIG_MMC_DW is not set |
| CONFIG_MMC_MTK=y |
| CONFIG_MTD_MT81xx_NOR=y |
| -# CONFIG_MTK_CMDQ is not set |
| -# CONFIG_MTK_CMDQ_MBOX is not set |
| +CONFIG_MTK_CMDQ=y |
| +CONFIG_MTK_CMDQ_DEBUG=y |
| +CONFIG_MTK_CMDQ_DEBUG_SOC=8183 |
| +CONFIG_MTK_CMDQ_MBOX=y |
| CONFIG_MTK_EFUSE=y |
| +CONFIG_MTK_EMI_MBW=y |
| # CONFIG_MTK_HSDMA is not set |
| CONFIG_MTK_INFRACFG=y |
| CONFIG_MTK_IOMMU=y |
| CONFIG_MTK_PMIC_WRAP=y |
| +CONFIG_MTK_SCP=m |
| CONFIG_MTK_SCPSYS=y |
| CONFIG_MTK_SMI=y |
| CONFIG_MTK_THERMAL=y |
| @@ -152,13 +162,17 @@ CONFIG_REGULATOR_MT6358=y |
| # CONFIG_REGULATOR_TPS51632 is not set |
| # CONFIG_REGULATOR_TPS62360 is not set |
| # CONFIG_REGULATOR_TPS6586X is not set |
| -# CONFIG_REMOTEPROC is not set |
| +CONFIG_REMOTEPROC=y |
| # CONFIG_RMNET is not set |
| +CONFIG_RPMSG=m |
| +# CONFIG_RPMSG_CHAR is not set |
| +CONFIG_RPMSG_MTK_SCP=m |
| # CONFIG_RTC_DRV_AS3722 is not set |
| CONFIG_RTC_DRV_MT6397=y |
| # CONFIG_RTC_DRV_MT7622 is not set |
| # CONFIG_RTC_DRV_TPS6586X is not set |
| # CONFIG_SCSI_UFSHCD is not set |
| +# CONFIG_SCSI_VIRTIO is not set |
| # CONFIG_SENSORS_LM90 is not set |
| # CONFIG_SENSORS_NTC_THERMISTOR is not set |
| CONFIG_SENSORS_TMP401=y |
| @@ -194,15 +208,27 @@ CONFIG_SPI_MT65XX=y |
| # CONFIG_SPMI is not set |
| CONFIG_STAGING_MEDIA=y |
| CONFIG_TCG_CR50_I2C=y |
| +# CONFIG_TCG_VIRTIO_VTPM is not set |
| # CONFIG_THERMAL_GOV_FAIR_SHARE is not set |
| # CONFIG_THERMAL_WRITABLE_TRIPS is not set |
| CONFIG_TOUCHSCREEN_MELFAS_MIP4=y |
| +CONFIG_USB_CONFIGFS=y |
| +CONFIG_USB_CONFIGFS_ACM=y |
| +CONFIG_USB_CONFIGFS_MASS_STORAGE=y |
| +CONFIG_USB_CONFIGFS_SERIAL=y |
| +CONFIG_USB_F_ACM=y |
| +CONFIG_USB_F_FS=y |
| +CONFIG_USB_F_MASS_STORAGE=y |
| +CONFIG_USB_F_SERIAL=y |
| +CONFIG_USB_LIBCOMPOSITE=y |
| CONFIG_USB_MTU3=y |
| -# CONFIG_USB_MTU3_DEBUG is not set |
| -# CONFIG_USB_MTU3_DUAL_ROLE is not set |
| +CONFIG_USB_MTU3_DEBUG=y |
| +CONFIG_USB_MTU3_DUAL_ROLE=y |
| # CONFIG_USB_MTU3_GADGET is not set |
| -CONFIG_USB_MTU3_HOST=y |
| +# CONFIG_USB_MTU3_HOST is not set |
| +CONFIG_USB_U_SERIAL=y |
| CONFIG_USB_XHCI_MTK=y |
| +# CONFIG_U_SERIAL_CONSOLE is not set |
| CONFIG_V4L2_MEM2MEM_DEV=y |
| CONFIG_VIDEOBUF2_CORE=y |
| CONFIG_VIDEOBUF2_DMA_CONTIG=y |
| @@ -212,4 +238,11 @@ CONFIG_VIDEO_MEDIATEK_MDP=y |
| CONFIG_VIDEO_MEDIATEK_VCODEC=y |
| CONFIG_VIDEO_MEDIATEK_VPU=y |
| # CONFIG_VIDEO_V4L2_SUBDEV_API is not set |
| +CONFIG_VIRTIO=y |
| +# CONFIG_VIRTIO_BALLOON is not set |
| +# CONFIG_VIRTIO_BLK is not set |
| +# CONFIG_VIRTIO_CONSOLE is not set |
| +# CONFIG_VIRTIO_INPUT is not set |
| # CONFIG_VIRTIO_MMIO is not set |
| +# CONFIG_VIRTIO_NET is not set |
| +# CONFIG_VIRTIO_WL is not set |
| diff --git a/chromeos/config/arm64/chromiumos-qualcomm.flavour.config b/chromeos/config/arm64/chromiumos-qualcomm.flavour.config |
| index d80920df41f92..df8dee5a9ad25 100644 |
| --- a/chromeos/config/arm64/chromiumos-qualcomm.flavour.config |
| +++ b/chromeos/config/arm64/chromiumos-qualcomm.flavour.config |
| @@ -43,6 +43,7 @@ CONFIG_COMMON_CLK_QCOM=y |
| # CONFIG_COMMON_CLK_XGENE is not set |
| CONFIG_CPUFREQ_DT=y |
| CONFIG_CPUFREQ_DT_PLATDEV=y |
| +# CONFIG_CROS_EC_RPMSG is not set |
| # CONFIG_CRYPTO_DEV_QCE is not set |
| # CONFIG_CRYPTO_DEV_QCOM_RNG is not set |
| CONFIG_CRYPTO_DEV_VIRTIO=m |
| @@ -278,7 +279,13 @@ CONFIG_SPMI_MSM_PMIC_ARB=y |
| CONFIG_THERMAL_GOV_FAIR_SHARE=y |
| CONFIG_THERMAL_WRITABLE_TRIPS=y |
| # CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set |
| +CONFIG_USB_CONFIGFS=m |
| +# CONFIG_USB_CONFIGFS_ACM is not set |
| +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set |
| +# CONFIG_USB_CONFIGFS_SERIAL is not set |
| CONFIG_USB_DWC3_QCOM=y |
| +CONFIG_USB_F_FS=m |
| +CONFIG_USB_LIBCOMPOSITE=m |
| CONFIG_VIDEOBUF2_CORE=m |
| CONFIG_VIDEOBUF2_MEMOPS=m |
| CONFIG_VIDEOBUF2_V4L2=m |
| diff --git a/chromeos/config/arm64/chromiumos-rockchip64.flavour.config b/chromeos/config/arm64/chromiumos-rockchip64.flavour.config |
| index 80931110c50af..74542fedbd29b 100644 |
| --- a/chromeos/config/arm64/chromiumos-rockchip64.flavour.config |
| +++ b/chromeos/config/arm64/chromiumos-rockchip64.flavour.config |
| @@ -546,10 +546,16 @@ CONFIG_THERMAL_WRITABLE_TRIPS=y |
| # CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set |
| # CONFIG_TYPHOON is not set |
| # CONFIG_USB_AMD5536UDC is not set |
| +CONFIG_USB_CONFIGFS=m |
| +# CONFIG_USB_CONFIGFS_ACM is not set |
| +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set |
| +# CONFIG_USB_CONFIGFS_SERIAL is not set |
| CONFIG_USB_DWC3_HAPS=y |
| # CONFIG_USB_EG20T is not set |
| CONFIG_USB_EHCI_PCI=y |
| +CONFIG_USB_F_FS=m |
| # CONFIG_USB_GOKU is not set |
| +CONFIG_USB_LIBCOMPOSITE=m |
| # CONFIG_USB_NET2280 is not set |
| CONFIG_USB_OHCI_HCD_PCI=y |
| CONFIG_USB_PCI=y |
| diff --git a/chromeos/config/arm64/common.config b/chromeos/config/arm64/common.config |
| index e31977035cfe4..7073cb8566dc9 100644 |
| --- a/chromeos/config/arm64/common.config |
| +++ b/chromeos/config/arm64/common.config |
| @@ -161,7 +161,7 @@ CONFIG_CHARGER_CROS_USBPD=y |
| CONFIG_CHARGER_GPIO=y |
| # CONFIG_CHARGER_MANAGER is not set |
| # CONFIG_CHARGER_TPS65090 is not set |
| -CONFIG_CLANG_VERSION=90000 |
| +CONFIG_CLANG_VERSION=80000 |
| # CONFIG_CLK_HSDK is not set |
| # CONFIG_CLK_QORIQ is not set |
| # CONFIG_CLOCK_THERMAL is not set |
| diff --git a/chromeos/config/armel/common.config b/chromeos/config/armel/common.config |
| index 879eb506cb82e..d7ddad0f26b48 100644 |
| --- a/chromeos/config/armel/common.config |
| +++ b/chromeos/config/armel/common.config |
| @@ -870,15 +870,21 @@ CONFIG_TIMER_PROBE=y |
| # CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set |
| # CONFIG_UACCESS_WITH_MEMCPY is not set |
| CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" |
| +CONFIG_USB_CONFIGFS=m |
| +# CONFIG_USB_CONFIGFS_ACM is not set |
| +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set |
| +# CONFIG_USB_CONFIGFS_SERIAL is not set |
| CONFIG_USB_DWC2=y |
| # CONFIG_USB_DWC2_DEBUG is not set |
| CONFIG_USB_DWC2_HOST=y |
| # CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set |
| # CONFIG_USB_DWC3 is not set |
| CONFIG_USB_EHCI_HCD_PLATFORM=y |
| +CONFIG_USB_F_FS=m |
| CONFIG_USB_GADGET=m |
| # CONFIG_USB_GADGET_XILINX is not set |
| # CONFIG_USB_HCD_BCMA is not set |
| +CONFIG_USB_LIBCOMPOSITE=m |
| # CONFIG_USB_SNP_UDC_PLAT is not set |
| # CONFIG_USB_STORAGE_REALTEK is not set |
| CONFIG_USE_OF=y |
| diff --git a/chromeos/config/base.config b/chromeos/config/base.config |
| index e76dd4414e689..f9fcd8e0e4eac 100644 |
| --- a/chromeos/config/base.config |
| +++ b/chromeos/config/base.config |
| @@ -3009,8 +3009,6 @@ CONFIG_USB_ARCH_HAS_HCD=y |
| # CONFIG_USB_CHAOSKEY is not set |
| # CONFIG_USB_CHIPIDEA is not set |
| CONFIG_USB_COMMON=y |
| -CONFIG_USB_CONFIGFS=m |
| -# CONFIG_USB_CONFIGFS_ACM is not set |
| # CONFIG_USB_CONFIGFS_ECM is not set |
| # CONFIG_USB_CONFIGFS_ECM_SUBSET is not set |
| # CONFIG_USB_CONFIGFS_EEM is not set |
| @@ -3024,11 +3022,9 @@ CONFIG_USB_CONFIGFS_F_FS=y |
| # CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set |
| # CONFIG_USB_CONFIGFS_F_UAC2 is not set |
| # CONFIG_USB_CONFIGFS_F_UVC is not set |
| -# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set |
| # CONFIG_USB_CONFIGFS_NCM is not set |
| # CONFIG_USB_CONFIGFS_OBEX is not set |
| # CONFIG_USB_CONFIGFS_RNDIS is not set |
| -# CONFIG_USB_CONFIGFS_SERIAL is not set |
| CONFIG_USB_CONFIGFS_UEVENT=y |
| # CONFIG_USB_CYPRESS_CY7C63 is not set |
| # CONFIG_USB_CYTHERM is not set |
| @@ -3045,7 +3041,6 @@ CONFIG_USB_EZUSB_FX2=m |
| # CONFIG_USB_FOTG210_HCD is not set |
| # CONFIG_USB_FOTG210_UDC is not set |
| # CONFIG_USB_FTDI_ELAN is not set |
| -CONFIG_USB_F_FS=m |
| # CONFIG_USB_GADGET_DEBUG is not set |
| # CONFIG_USB_GADGET_DEBUG_FILES is not set |
| # CONFIG_USB_GADGET_DEBUG_FS is not set |
| @@ -3075,7 +3070,6 @@ CONFIG_USB_HIDDEV=y |
| # CONFIG_USB_LEDS_TRIGGER_USBPORT is not set |
| # CONFIG_USB_LED_TRIG is not set |
| # CONFIG_USB_LEGOTOWER is not set |
| -CONFIG_USB_LIBCOMPOSITE=m |
| # CONFIG_USB_LINK_LAYER_TEST is not set |
| # CONFIG_USB_M66592 is not set |
| # CONFIG_USB_MAX3421_HCD is not set |
| diff --git a/chromeos/config/x86_64/common.config b/chromeos/config/x86_64/common.config |
| index de448d408582c..89cc91210bc5c 100644 |
| --- a/chromeos/config/x86_64/common.config |
| +++ b/chromeos/config/x86_64/common.config |
| @@ -235,7 +235,7 @@ CONFIG_CHROMEOS=y |
| CONFIG_CHROMEOS_LAPTOP=y |
| CONFIG_CHROMEOS_PSTORE=y |
| CONFIG_CHROMEOS_TBMC=y |
| -CONFIG_CLANG_VERSION=90000 |
| +CONFIG_CLANG_VERSION=80000 |
| CONFIG_CLKBLD_I8253=y |
| CONFIG_CLKEVT_I8253=y |
| CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y |
| @@ -1270,6 +1270,10 @@ CONFIG_UEFI_CPER_X86=y |
| # CONFIG_UNWINDER_GUESS is not set |
| CONFIG_UNWINDER_ORC=y |
| # CONFIG_USB_AMD5536UDC is not set |
| +CONFIG_USB_CONFIGFS=m |
| +# CONFIG_USB_CONFIGFS_ACM is not set |
| +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set |
| +# CONFIG_USB_CONFIGFS_SERIAL is not set |
| # CONFIG_USB_DWC2 is not set |
| CONFIG_USB_DWC3=m |
| CONFIG_USB_DWC3_GADGET=y |
| @@ -1279,8 +1283,10 @@ CONFIG_USB_DWC3_PCI=m |
| # CONFIG_USB_EG20T is not set |
| # CONFIG_USB_EHCI_HCD_PLATFORM is not set |
| CONFIG_USB_EHCI_PCI=y |
| +CONFIG_USB_F_FS=m |
| CONFIG_USB_GADGET=m |
| # CONFIG_USB_GOKU is not set |
| +CONFIG_USB_LIBCOMPOSITE=m |
| # CONFIG_USB_NET2280 is not set |
| CONFIG_USB_OHCI_HCD=y |
| CONFIG_USB_OHCI_HCD_PCI=y |
| diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c |
| index 9b8d4d7802fcb..caa6c1b34aa24 100644 |
| --- a/drivers/bluetooth/hci_qca.c |
| +++ b/drivers/bluetooth/hci_qca.c |
| @@ -535,6 +535,8 @@ static int qca_open(struct hci_uart *hu) |
| qcadev = serdev_device_get_drvdata(hu->serdev); |
| if (qcadev->btsoc_type != QCA_WCN3990) { |
| gpiod_set_value_cansleep(qcadev->bt_en, 1); |
| + /* Controller needs time to bootup. */ |
| + msleep(150); |
| } else { |
| hu->init_speed = qcadev->init_speed; |
| hu->oper_speed = qcadev->oper_speed; |
| diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile |
| index 3dc1b9f15ea2f..5df0e476e94d8 100644 |
| --- a/drivers/clk/mediatek/Makefile |
| +++ b/drivers/clk/mediatek/Makefile |
| @@ -44,3 +44,5 @@ obj-$(CONFIG_COMMON_CLK_MT8183_MFGCFG) += clk-mt8183-mfgcfg.o |
| obj-$(CONFIG_COMMON_CLK_MT8183_MMSYS) += clk-mt8183-mm.o |
| obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o |
| obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o |
| +obj-$(CONFIG_COMMON_CLK_MT8183) += clkdbg.o clkdbg-mt8183.o |
| +obj-$(CONFIG_COMMON_CLK_MT8183) += clkchk.o clkchk-mt8183.o |
| diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c |
| index 68f157b31b289..d1458b4314630 100644 |
| --- a/drivers/clk/mediatek/clk-mt8183.c |
| +++ b/drivers/clk/mediatek/clk-mt8183.c |
| @@ -1204,13 +1204,21 @@ static int clk_mt8183_infra_probe(struct platform_device *pdev) |
| { |
| struct clk_onecell_data *clk_data; |
| struct device_node *node = pdev->dev.of_node; |
| + int r; |
| |
| clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); |
| |
| mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), |
| clk_data); |
| |
| - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); |
| + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); |
| + if (r) |
| + pr_err("%s(): could not register clock provider: %d\n", |
| + __func__, r); |
| + |
| + mtk_register_reset_controller_set_clr(node, 4, 0x120); |
| + |
| + return r; |
| } |
| |
| static int clk_mt8183_mcu_probe(struct platform_device *pdev) |
| diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h |
| index 37ae944548e9b..8f6282ec40006 100644 |
| --- a/drivers/clk/mediatek/clk-mtk.h |
| +++ b/drivers/clk/mediatek/clk-mtk.h |
| @@ -236,4 +236,7 @@ struct clk *mtk_clk_register_ref2usb_tx(const char *name, |
| void mtk_register_reset_controller(struct device_node *np, |
| unsigned int num_regs, int regofs); |
| |
| +void mtk_register_reset_controller_set_clr(struct device_node *np, |
| + unsigned int num_regs, int regofs); |
| + |
| #endif /* __DRV_CLK_MTK_H */ |
| diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c |
| index d3551d5efef24..e6dff4db74300 100644 |
| --- a/drivers/clk/mediatek/reset.c |
| +++ b/drivers/clk/mediatek/reset.c |
| @@ -27,6 +27,23 @@ struct mtk_reset { |
| struct reset_controller_dev rcdev; |
| }; |
| |
| +static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev, |
| + unsigned long id) |
| +{ |
| + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev); |
| + |
| + return regmap_write(data->regmap, data->regofs + ((id / 32) << 4), 1); |
| +} |
| + |
| +static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev, |
| + unsigned long id) |
| +{ |
| + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev); |
| + |
| + return regmap_write(data->regmap, |
| + data->regofs + ((id / 32) << 4) + 0x4, 1); |
| +} |
| + |
| static int mtk_reset_assert(struct reset_controller_dev *rcdev, |
| unsigned long id) |
| { |
| @@ -57,14 +74,33 @@ static int mtk_reset(struct reset_controller_dev *rcdev, |
| return mtk_reset_deassert(rcdev, id); |
| } |
| |
| +static int mtk_reset_set_clr(struct reset_controller_dev *rcdev, |
| + unsigned long id) |
| +{ |
| + int ret; |
| + |
| + ret = mtk_reset_assert_set_clr(rcdev, id); |
| + if (ret) |
| + return ret; |
| + |
| + return mtk_reset_deassert_set_clr(rcdev, id); |
| +} |
| + |
| static const struct reset_control_ops mtk_reset_ops = { |
| .assert = mtk_reset_assert, |
| .deassert = mtk_reset_deassert, |
| .reset = mtk_reset, |
| }; |
| |
| -void mtk_register_reset_controller(struct device_node *np, |
| - unsigned int num_regs, int regofs) |
| +static const struct reset_control_ops mtk_reset_ops_set_clr = { |
| + .assert = mtk_reset_assert_set_clr, |
| + .deassert = mtk_reset_deassert_set_clr, |
| + .reset = mtk_reset_set_clr, |
| +}; |
| + |
| +void mtk_register_reset_controller_common(struct device_node *np, |
| + unsigned int num_regs, int regofs, |
| + const struct reset_control_ops *reset_ops) |
| { |
| struct mtk_reset *data; |
| int ret; |
| @@ -85,7 +121,7 @@ void mtk_register_reset_controller(struct device_node *np, |
| data->regofs = regofs; |
| data->rcdev.owner = THIS_MODULE; |
| data->rcdev.nr_resets = num_regs * 32; |
| - data->rcdev.ops = &mtk_reset_ops; |
| + data->rcdev.ops = reset_ops; |
| data->rcdev.of_node = np; |
| |
| ret = reset_controller_register(&data->rcdev); |
| @@ -95,3 +131,18 @@ void mtk_register_reset_controller(struct device_node *np, |
| return; |
| } |
| } |
| + |
| +void mtk_register_reset_controller(struct device_node *np, |
| + unsigned int num_regs, int regofs) |
| +{ |
| + mtk_register_reset_controller_common(np, num_regs, regofs, |
| + &mtk_reset_ops); |
| +} |
| + |
| +void mtk_register_reset_controller_set_clr(struct device_node *np, |
| + unsigned int num_regs, int regofs) |
| +{ |
| + mtk_register_reset_controller_common(np, num_regs, regofs, |
| + &mtk_reset_ops_set_clr); |
| +} |
| + |
| diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile |
| index 82ae49c642211..8067a4be83115 100644 |
| --- a/drivers/gpu/drm/mediatek/Makefile |
| +++ b/drivers/gpu/drm/mediatek/Makefile |
| @@ -12,6 +12,8 @@ mediatek-drm-y := mtk_disp_color.o \ |
| mtk_drm_plane.o \ |
| mtk_dsi.o \ |
| mtk_mipi_tx.o \ |
| + mtk_mt8173_mipi_tx.o \ |
| + mtk_mt8183_mipi_tx.o \ |
| mtk_dpi.o |
| |
| obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o |
| diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c |
| index 28d5766ecb747..faea762594579 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c |
| @@ -703,8 +703,8 @@ static struct platform_driver * const mtk_drm_drivers[] = { |
| &mtk_disp_rdma_driver, |
| &mtk_dpi_driver, |
| &mtk_drm_platform_driver, |
| - &mtk_dsi_driver, |
| &mtk_mipi_tx_driver, |
| + &mtk_dsi_driver, |
| }; |
| |
| static int __init mtk_drm_init(void) |
| diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c |
| index 27b507eb4a997..5d8227c90371c 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_dsi.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c |
| @@ -21,10 +21,12 @@ |
| #include <linux/component.h> |
| #include <linux/iopoll.h> |
| #include <linux/irq.h> |
| +#include <linux/mfd/syscon.h> |
| #include <linux/of.h> |
| #include <linux/of_platform.h> |
| #include <linux/phy/phy.h> |
| #include <linux/platform_device.h> |
| +#include <linux/regmap.h> |
| #include <video/mipi_display.h> |
| #include <video/videomode.h> |
| |
| @@ -78,6 +80,7 @@ |
| #define DSI_VBP_NL 0x24 |
| #define DSI_VFP_NL 0x28 |
| #define DSI_VACT_NL 0x2C |
| +#define DSI_SIZE_CON 0x38 |
| #define DSI_HSA_WC 0x50 |
| #define DSI_HBP_WC 0x54 |
| #define DSI_HFP_WC 0x58 |
| @@ -131,7 +134,10 @@ |
| #define VM_CMD_EN BIT(0) |
| #define TS_VFP_EN BIT(5) |
| |
| -#define DSI_CMDQ0 0x180 |
| +#define DSI_SHADOW_DEBUG 0x190U |
| +#define FORCE_COMMIT BIT(0) |
| +#define BYPASS_SHADOW BIT(1) |
| + |
| #define CONFIG (0xff << 0) |
| #define SHORT_PACKET 0 |
| #define LONG_PACKET 2 |
| @@ -146,6 +152,8 @@ |
| #define T_HS_EXIT 7 |
| #define T_HS_ZERO 10 |
| |
| +#define MMSYS_SW_RST_DSI_B BIT(25) |
| + |
| #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) |
| |
| #define MTK_DSI_HOST_IS_READ(type) \ |
| @@ -154,8 +162,33 @@ |
| (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \ |
| (type == MIPI_DSI_DCS_READ)) |
| |
| +struct mtk_phy_timing { |
| + u32 lpx; |
| + u32 da_hs_prepare; |
| + u32 da_hs_zero; |
| + u32 da_hs_trail; |
| + |
| + u32 ta_go; |
| + u32 ta_sure; |
| + u32 ta_get; |
| + u32 da_hs_exit; |
| + |
| + u32 clk_hs_zero; |
| + u32 clk_hs_trail; |
| + |
| + u32 clk_hs_prepare; |
| + u32 clk_hs_post; |
| + u32 clk_hs_exit; |
| +}; |
| + |
| struct phy; |
| |
| +struct mtk_dsi_driver_data { |
| + const u32 reg_cmdq_off; |
| + bool has_shadow_ctl; |
| + bool has_size_ctl; |
| +}; |
| + |
| struct mtk_dsi { |
| struct mtk_ddp_comp ddp_comp; |
| struct device *dev; |
| @@ -165,6 +198,8 @@ struct mtk_dsi { |
| struct drm_panel *panel; |
| struct drm_bridge *bridge; |
| struct phy *phy; |
| + struct regmap *mmsys_sw_rst_b; |
| + u32 sw_rst_b; |
| |
| void __iomem *regs; |
| |
| @@ -172,16 +207,18 @@ struct mtk_dsi { |
| struct clk *digital_clk; |
| struct clk *hs_clk; |
| |
| - u32 data_rate; |
| + u64 data_rate; |
| |
| unsigned long mode_flags; |
| enum mipi_dsi_pixel_format format; |
| unsigned int lanes; |
| struct videomode vm; |
| + struct mtk_phy_timing phy_timing; |
| int refcount; |
| bool enabled; |
| u32 irq_data; |
| wait_queue_head_t irq_wait_queue; |
| + struct mtk_dsi_driver_data *driver_data; |
| }; |
| |
| static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e) |
| @@ -206,21 +243,48 @@ static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data) |
| writel((temp & ~mask) | (data & mask), dsi->regs + offset); |
| } |
| |
| -static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) |
| +static void mtk_dsi_phy_timing_calc(struct mtk_dsi *dsi) |
| { |
| - u32 timcon0, timcon1, timcon2, timcon3; |
| u32 ui, cycle_time; |
| + struct mtk_phy_timing *timing = &dsi->phy_timing; |
| |
| - ui = 1000 / dsi->data_rate + 0x01; |
| - cycle_time = 8000 / dsi->data_rate + 0x01; |
| + ui = 1000000000U / dsi->data_rate + 1U; |
| + cycle_time = 8000000000U / dsi->data_rate + 1U; |
| + |
| + timing->lpx = NS_TO_CYCLE(0x50, cycle_time); |
| + timing->da_hs_prepare = NS_TO_CYCLE((0x40 + 0x5 * ui), cycle_time); |
| + timing->da_hs_zero = NS_TO_CYCLE((0xc8 + 0x0a * ui), cycle_time); |
| + timing->da_hs_trail = NS_TO_CYCLE(((0x4 * ui) + 0x50), cycle_time); |
| + |
| + if (timing->da_hs_zero > timing->da_hs_prepare) |
| + timing->da_hs_zero -= timing->da_hs_prepare; |
| + |
| + timing->ta_go = 4U * timing->lpx; |
| + timing->ta_sure = 3U * timing->lpx / 2U; |
| + timing->ta_get = 5U * timing->lpx; |
| + timing->da_hs_exit = 2U * timing->lpx; |
| + |
| + timing->clk_hs_zero = NS_TO_CYCLE(0x150U, cycle_time); |
| + timing->clk_hs_trail = NS_TO_CYCLE(0x64U, cycle_time) + 0xaU; |
| + |
| + timing->clk_hs_prepare = NS_TO_CYCLE(0x40U, cycle_time); |
| + timing->clk_hs_post = NS_TO_CYCLE(80U + 52U * ui, cycle_time); |
| + timing->clk_hs_exit = 2U * timing->lpx; |
| +} |
| + |
| +static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) |
| +{ |
| + u32 timcon0, timcon1, timcon2, timcon3; |
| + struct mtk_phy_timing *timing = &dsi->phy_timing; |
| |
| - timcon0 = T_LPX | T_HS_PREP << 8 | T_HS_ZERO << 16 | T_HS_TRAIL << 24; |
| - timcon1 = 4 * T_LPX | (3 * T_LPX / 2) << 8 | 5 * T_LPX << 16 | |
| - T_HS_EXIT << 24; |
| - timcon2 = ((NS_TO_CYCLE(0x64, cycle_time) + 0xa) << 24) | |
| - (NS_TO_CYCLE(0x150, cycle_time) << 16); |
| - timcon3 = NS_TO_CYCLE(0x40, cycle_time) | (2 * T_LPX) << 16 | |
| - NS_TO_CYCLE(80 + 52 * ui, cycle_time) << 8; |
| + timcon0 = timing->lpx | timing->da_hs_prepare << 8 | |
| + timing->da_hs_zero << 16 | timing->da_hs_trail << 24; |
| + timcon1 = timing->ta_go | timing->ta_sure << 8 | |
| + timing->ta_get << 16 | timing->da_hs_exit << 24; |
| + timcon2 = 1 << 8 | timing->clk_hs_zero << 16 | |
| + timing->clk_hs_trail << 24; |
| + timcon3 = timing->clk_hs_prepare | timing->clk_hs_post << 8 | |
| + timing->clk_hs_exit << 16; |
| |
| writel(timcon0, dsi->regs + DSI_PHY_TIMECON0); |
| writel(timcon1, dsi->regs + DSI_PHY_TIMECON1); |
| @@ -238,6 +302,16 @@ static void mtk_dsi_disable(struct mtk_dsi *dsi) |
| mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0); |
| } |
| |
| +static void mtk_dsi_reset_all(struct mtk_dsi *dsi) |
| +{ |
| + regmap_update_bits(dsi->mmsys_sw_rst_b, dsi->sw_rst_b, |
| + MMSYS_SW_RST_DSI_B, ~MMSYS_SW_RST_DSI_B); |
| + usleep_range(1000, 1100); |
| + |
| + regmap_update_bits(dsi->mmsys_sw_rst_b, dsi->sw_rst_b, |
| + MMSYS_SW_RST_DSI_B, MMSYS_SW_RST_DSI_B); |
| +} |
| + |
| static void mtk_dsi_reset_engine(struct mtk_dsi *dsi) |
| { |
| mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET); |
| @@ -421,6 +495,9 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) |
| writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL); |
| writel(vm->vactive, dsi->regs + DSI_VACT_NL); |
| |
| + if (dsi->driver_data->has_size_ctl) |
| + writel(vm->vactive << 16 | vm->hactive, dsi->regs + DSI_SIZE_CON); |
| + |
| horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10); |
| |
| if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) |
| @@ -530,8 +607,9 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) |
| { |
| struct device *dev = dsi->dev; |
| int ret; |
| - u64 pixel_clock, total_bits; |
| + u64 total_bits; |
| u32 htotal, htotal_bits, bit_per_pixel, overhead_cycles, overhead_bits; |
| + struct mtk_phy_timing *timing = &dsi->phy_timing; |
| |
| if (++dsi->refcount != 1) |
| return 0; |
| @@ -556,17 +634,22 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) |
| * mipi_ratio = (htotal_time + overhead_time) / htotal_time |
| * data_rate = pixel_clock * bit_per_pixel * mipi_ratio / num_lanes; |
| */ |
| - pixel_clock = dsi->vm.pixelclock; |
| htotal = dsi->vm.hactive + dsi->vm.hback_porch + dsi->vm.hfront_porch + |
| dsi->vm.hsync_len; |
| htotal_bits = htotal * bit_per_pixel; |
| |
| - overhead_cycles = T_LPX + T_HS_PREP + T_HS_ZERO + T_HS_TRAIL + |
| - T_HS_EXIT; |
| - overhead_bits = overhead_cycles * dsi->lanes * 8; |
| - total_bits = htotal_bits + overhead_bits; |
| + dsi->data_rate = dsi->vm.pixelclock * bit_per_pixel / dsi->lanes; |
| |
| - dsi->data_rate = DIV_ROUND_UP_ULL(pixel_clock * total_bits, |
| + mtk_dsi_phy_timing_calc(dsi); |
| + |
| + overhead_cycles = 2 * timing->lpx + timing->da_hs_prepare + |
| + timing->da_hs_zero + timing->da_hs_trail + |
| + timing->da_hs_exit + 1; |
| + |
| + overhead_bits = overhead_cycles * 8U; |
| + total_bits = (u64)htotal_bits + (u64)overhead_bits; |
| + |
| + dsi->data_rate = DIV_ROUND_UP_ULL(dsi->vm.pixelclock * total_bits, |
| htotal * dsi->lanes); |
| |
| ret = clk_set_rate(dsi->hs_clk, dsi->data_rate); |
| @@ -590,6 +673,11 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) |
| } |
| |
| mtk_dsi_enable(dsi); |
| + |
| + if (dsi->driver_data->has_shadow_ctl) |
| + writel(FORCE_COMMIT | BYPASS_SHADOW, |
| + dsi->regs + DSI_SHADOW_DEBUG); |
| + |
| mtk_dsi_reset_engine(dsi); |
| mtk_dsi_phy_timconfig(dsi); |
| |
| @@ -696,7 +784,6 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi) |
| } |
| } |
| |
| - mtk_dsi_stop(dsi); |
| mtk_dsi_poweroff(dsi); |
| |
| dsi->enabled = false; |
| @@ -831,6 +918,8 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi) |
| goto err_encoder_cleanup; |
| } |
| |
| + mtk_dsi_reset_all(dsi); |
| + |
| return 0; |
| |
| err_encoder_cleanup: |
| @@ -857,6 +946,7 @@ static void mtk_dsi_ddp_stop(struct mtk_ddp_comp *comp) |
| { |
| struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp); |
| |
| + mtk_dsi_stop(dsi); |
| mtk_dsi_poweroff(dsi); |
| } |
| |
| @@ -934,6 +1024,7 @@ static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg) |
| const char *tx_buf = msg->tx_buf; |
| u8 config, cmdq_size, cmdq_off, type = msg->type; |
| u32 reg_val, cmdq_mask, i; |
| + u32 reg_cmdq_off = dsi->driver_data->reg_cmdq_off; |
| |
| if (MTK_DSI_HOST_IS_READ(type)) |
| config = BTA; |
| @@ -953,9 +1044,11 @@ static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg) |
| } |
| |
| for (i = 0; i < msg->tx_len; i++) |
| - writeb(tx_buf[i], dsi->regs + DSI_CMDQ0 + cmdq_off + i); |
| + mtk_dsi_mask(dsi, (reg_cmdq_off + cmdq_off + i) & (~0x3U), |
| + (0xffUL << (((i + cmdq_off) & 3U) * 8U)), |
| + tx_buf[i] << (((i + cmdq_off) & 3U) * 8U)); |
| |
| - mtk_dsi_mask(dsi, DSI_CMDQ0, cmdq_mask, reg_val); |
| + mtk_dsi_mask(dsi, reg_cmdq_off, cmdq_mask, reg_val); |
| mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size); |
| } |
| |
| @@ -1045,12 +1138,6 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) |
| return ret; |
| } |
| |
| - ret = mipi_dsi_host_register(&dsi->host); |
| - if (ret < 0) { |
| - dev_err(dev, "failed to register DSI host: %d\n", ret); |
| - goto err_ddp_comp_unregister; |
| - } |
| - |
| ret = mtk_dsi_create_conn_enc(drm, dsi); |
| if (ret) { |
| DRM_ERROR("Encoder create failed with %d\n", ret); |
| @@ -1060,8 +1147,6 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) |
| return 0; |
| |
| err_unregister: |
| - mipi_dsi_host_unregister(&dsi->host); |
| -err_ddp_comp_unregister: |
| mtk_ddp_comp_unregister(drm, &dsi->ddp_comp); |
| return ret; |
| } |
| @@ -1082,14 +1167,40 @@ static const struct component_ops mtk_dsi_component_ops = { |
| .unbind = mtk_dsi_unbind, |
| }; |
| |
| +static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = { |
| + .reg_cmdq_off = 0x200, |
| +}; |
| + |
| +static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = { |
| + .reg_cmdq_off = 0x180, |
| +}; |
| + |
| +static const struct mtk_dsi_driver_data mt8183_dsi_driver_data = { |
| + .reg_cmdq_off = 0x200, |
| + .has_shadow_ctl = true, |
| + .has_size_ctl = true, |
| +}; |
| + |
| +static const struct of_device_id mtk_dsi_of_match[] = { |
| + { .compatible = "mediatek,mt2701-dsi", |
| + .data = &mt2701_dsi_driver_data }, |
| + { .compatible = "mediatek,mt8173-dsi", |
| + .data = &mt8173_dsi_driver_data }, |
| + { .compatible = "mediatek,mt8183-dsi", |
| + .data = &mt8183_dsi_driver_data }, |
| + { }, |
| +}; |
| + |
| static int mtk_dsi_probe(struct platform_device *pdev) |
| { |
| struct mtk_dsi *dsi; |
| struct device *dev = &pdev->dev; |
| + const struct of_device_id *of_id; |
| struct resource *regs; |
| int irq_num; |
| int comp_id; |
| int ret; |
| + struct regmap *regmap; |
| |
| dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); |
| if (!dsi) |
| @@ -1097,31 +1208,40 @@ static int mtk_dsi_probe(struct platform_device *pdev) |
| |
| dsi->host.ops = &mtk_dsi_ops; |
| dsi->host.dev = dev; |
| + dsi->dev = dev; |
| + ret = mipi_dsi_host_register(&dsi->host); |
| + if (ret < 0) { |
| + dev_err(dev, "failed to register DSI host: %d\n", ret); |
| + return ret; |
| + } |
| |
| ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, |
| &dsi->panel, &dsi->bridge); |
| if (ret) |
| - return ret; |
| + goto err_unregister_host; |
| + |
| + of_id = of_match_device(mtk_dsi_of_match, &pdev->dev); |
| + dsi->driver_data = (struct mtk_dsi_driver_data *)of_id->data; |
| |
| dsi->engine_clk = devm_clk_get(dev, "engine"); |
| if (IS_ERR(dsi->engine_clk)) { |
| ret = PTR_ERR(dsi->engine_clk); |
| dev_err(dev, "Failed to get engine clock: %d\n", ret); |
| - return ret; |
| + goto err_unregister_host; |
| } |
| |
| dsi->digital_clk = devm_clk_get(dev, "digital"); |
| if (IS_ERR(dsi->digital_clk)) { |
| ret = PTR_ERR(dsi->digital_clk); |
| dev_err(dev, "Failed to get digital clock: %d\n", ret); |
| - return ret; |
| + goto err_unregister_host; |
| } |
| |
| dsi->hs_clk = devm_clk_get(dev, "hs"); |
| if (IS_ERR(dsi->hs_clk)) { |
| ret = PTR_ERR(dsi->hs_clk); |
| dev_err(dev, "Failed to get hs clock: %d\n", ret); |
| - return ret; |
| + goto err_unregister_host; |
| } |
| |
| regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -1129,33 +1249,51 @@ static int mtk_dsi_probe(struct platform_device *pdev) |
| if (IS_ERR(dsi->regs)) { |
| ret = PTR_ERR(dsi->regs); |
| dev_err(dev, "Failed to ioremap memory: %d\n", ret); |
| - return ret; |
| + goto err_unregister_host; |
| } |
| |
| dsi->phy = devm_phy_get(dev, "dphy"); |
| if (IS_ERR(dsi->phy)) { |
| ret = PTR_ERR(dsi->phy); |
| dev_err(dev, "Failed to get MIPI-DPHY: %d\n", ret); |
| + goto err_unregister_host; |
| + } |
| + |
| + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, |
| + "mediatek,syscon-dsi"); |
| + ret = of_property_read_u32_index(dev->of_node, "mediatek,syscon-dsi", 1, |
| + &dsi->sw_rst_b); |
| + |
| + if (IS_ERR(regmap)) |
| + ret = PTR_ERR(regmap); |
| + |
| + if (ret) { |
| + ret = PTR_ERR(regmap); |
| + dev_err(dev, "Failed to get system configuration registers: %d\n", ret); |
| return ret; |
| } |
| |
| + dsi->mmsys_sw_rst_b = regmap; |
| + |
| comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DSI); |
| if (comp_id < 0) { |
| dev_err(dev, "Failed to identify by alias: %d\n", comp_id); |
| - return comp_id; |
| + ret = comp_id; |
| + goto err_unregister_host; |
| } |
| |
| ret = mtk_ddp_comp_init(dev, dev->of_node, &dsi->ddp_comp, comp_id, |
| &mtk_dsi_funcs); |
| if (ret) { |
| dev_err(dev, "Failed to initialize component: %d\n", ret); |
| - return ret; |
| + goto err_unregister_host; |
| } |
| |
| irq_num = platform_get_irq(pdev, 0); |
| if (irq_num < 0) { |
| - dev_err(&pdev->dev, "failed to request dsi irq resource\n"); |
| - return -EPROBE_DEFER; |
| + dev_err(&pdev->dev, "failed to get dsi irq_num: %d\n", irq_num); |
| + ret = irq_num; |
| + goto err_unregister_host; |
| } |
| |
| irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW); |
| @@ -1163,14 +1301,24 @@ static int mtk_dsi_probe(struct platform_device *pdev) |
| IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi); |
| if (ret) { |
| dev_err(&pdev->dev, "failed to request mediatek dsi irq\n"); |
| - return -EPROBE_DEFER; |
| + goto err_unregister_host; |
| } |
| |
| init_waitqueue_head(&dsi->irq_wait_queue); |
| |
| platform_set_drvdata(pdev, dsi); |
| |
| - return component_add(&pdev->dev, &mtk_dsi_component_ops); |
| + ret = component_add(&pdev->dev, &mtk_dsi_component_ops); |
| + if (ret) { |
| + dev_err(&pdev->dev, "failed to add component: %d\n", ret); |
| + goto err_unregister_host; |
| + } |
| + |
| + return 0; |
| + |
| +err_unregister_host: |
| + mipi_dsi_host_unregister(&dsi->host); |
| + return ret; |
| } |
| |
| static int mtk_dsi_remove(struct platform_device *pdev) |
| @@ -1178,17 +1326,13 @@ static int mtk_dsi_remove(struct platform_device *pdev) |
| struct mtk_dsi *dsi = platform_get_drvdata(pdev); |
| |
| mtk_output_dsi_disable(dsi); |
| + mtk_dsi_stop(dsi); |
| + mtk_dsi_poweroff(dsi); |
| component_del(&pdev->dev, &mtk_dsi_component_ops); |
| |
| return 0; |
| } |
| |
| -static const struct of_device_id mtk_dsi_of_match[] = { |
| - { .compatible = "mediatek,mt2701-dsi" }, |
| - { .compatible = "mediatek,mt8173-dsi" }, |
| - { }, |
| -}; |
| - |
| struct platform_driver mtk_dsi_driver = { |
| .probe = mtk_dsi_probe, |
| .remove = mtk_dsi_remove, |
| diff --git a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c |
| index 90e913108950d..73d19dfb38365 100644 |
| --- a/drivers/gpu/drm/mediatek/mtk_mipi_tx.c |
| +++ b/drivers/gpu/drm/mediatek/mtk_mipi_tx.c |
| @@ -11,292 +11,45 @@ |
| * GNU General Public License for more details. |
| */ |
| |
| -#include <linux/clk.h> |
| -#include <linux/clk-provider.h> |
| -#include <linux/delay.h> |
| -#include <linux/io.h> |
| -#include <linux/module.h> |
| -#include <linux/of_device.h> |
| -#include <linux/platform_device.h> |
| -#include <linux/phy/phy.h> |
| - |
| -#define MIPITX_DSI_CON 0x00 |
| -#define RG_DSI_LDOCORE_EN BIT(0) |
| -#define RG_DSI_CKG_LDOOUT_EN BIT(1) |
| -#define RG_DSI_BCLK_SEL (3 << 2) |
| -#define RG_DSI_LD_IDX_SEL (7 << 4) |
| -#define RG_DSI_PHYCLK_SEL (2 << 8) |
| -#define RG_DSI_DSICLK_FREQ_SEL BIT(10) |
| -#define RG_DSI_LPTX_CLMP_EN BIT(11) |
| - |
| -#define MIPITX_DSI_CLOCK_LANE 0x04 |
| -#define MIPITX_DSI_DATA_LANE0 0x08 |
| -#define MIPITX_DSI_DATA_LANE1 0x0c |
| -#define MIPITX_DSI_DATA_LANE2 0x10 |
| -#define MIPITX_DSI_DATA_LANE3 0x14 |
| -#define RG_DSI_LNTx_LDOOUT_EN BIT(0) |
| -#define RG_DSI_LNTx_CKLANE_EN BIT(1) |
| -#define RG_DSI_LNTx_LPTX_IPLUS1 BIT(2) |
| -#define RG_DSI_LNTx_LPTX_IPLUS2 BIT(3) |
| -#define RG_DSI_LNTx_LPTX_IMINUS BIT(4) |
| -#define RG_DSI_LNTx_LPCD_IPLUS BIT(5) |
| -#define RG_DSI_LNTx_LPCD_IMINUS BIT(6) |
| -#define RG_DSI_LNTx_RT_CODE (0xf << 8) |
| - |
| -#define MIPITX_DSI_TOP_CON 0x40 |
| -#define RG_DSI_LNT_INTR_EN BIT(0) |
| -#define RG_DSI_LNT_HS_BIAS_EN BIT(1) |
| -#define RG_DSI_LNT_IMP_CAL_EN BIT(2) |
| -#define RG_DSI_LNT_TESTMODE_EN BIT(3) |
| -#define RG_DSI_LNT_IMP_CAL_CODE (0xf << 4) |
| -#define RG_DSI_LNT_AIO_SEL (7 << 8) |
| -#define RG_DSI_PAD_TIE_LOW_EN BIT(11) |
| -#define RG_DSI_DEBUG_INPUT_EN BIT(12) |
| -#define RG_DSI_PRESERVE (7 << 13) |
| - |
| -#define MIPITX_DSI_BG_CON 0x44 |
| -#define RG_DSI_BG_CORE_EN BIT(0) |
| -#define RG_DSI_BG_CKEN BIT(1) |
| -#define RG_DSI_BG_DIV (0x3 << 2) |
| -#define RG_DSI_BG_FAST_CHARGE BIT(4) |
| -#define RG_DSI_VOUT_MSK (0x3ffff << 5) |
| -#define RG_DSI_V12_SEL (7 << 5) |
| -#define RG_DSI_V10_SEL (7 << 8) |
| -#define RG_DSI_V072_SEL (7 << 11) |
| -#define RG_DSI_V04_SEL (7 << 14) |
| -#define RG_DSI_V032_SEL (7 << 17) |
| -#define RG_DSI_V02_SEL (7 << 20) |
| -#define RG_DSI_BG_R1_TRIM (0xf << 24) |
| -#define RG_DSI_BG_R2_TRIM (0xf << 28) |
| - |
| -#define MIPITX_DSI_PLL_CON0 0x50 |
| -#define RG_DSI_MPPLL_PLL_EN BIT(0) |
| -#define RG_DSI_MPPLL_DIV_MSK (0x1ff << 1) |
| -#define RG_DSI_MPPLL_PREDIV (3 << 1) |
| -#define RG_DSI_MPPLL_TXDIV0 (3 << 3) |
| -#define RG_DSI_MPPLL_TXDIV1 (3 << 5) |
| -#define RG_DSI_MPPLL_POSDIV (7 << 7) |
| -#define RG_DSI_MPPLL_MONVC_EN BIT(10) |
| -#define RG_DSI_MPPLL_MONREF_EN BIT(11) |
| -#define RG_DSI_MPPLL_VOD_EN BIT(12) |
| - |
| -#define MIPITX_DSI_PLL_CON1 0x54 |
| -#define RG_DSI_MPPLL_SDM_FRA_EN BIT(0) |
| -#define RG_DSI_MPPLL_SDM_SSC_PH_INIT BIT(1) |
| -#define RG_DSI_MPPLL_SDM_SSC_EN BIT(2) |
| -#define RG_DSI_MPPLL_SDM_SSC_PRD (0xffff << 16) |
| - |
| -#define MIPITX_DSI_PLL_CON2 0x58 |
| - |
| -#define MIPITX_DSI_PLL_TOP 0x64 |
| -#define RG_DSI_MPPLL_PRESERVE (0xff << 8) |
| - |
| -#define MIPITX_DSI_PLL_PWR 0x68 |
| -#define RG_DSI_MPPLL_SDM_PWR_ON BIT(0) |
| -#define RG_DSI_MPPLL_SDM_ISO_EN BIT(1) |
| -#define RG_DSI_MPPLL_SDM_PWR_ACK BIT(8) |
| - |
| -#define MIPITX_DSI_SW_CTRL 0x80 |
| -#define SW_CTRL_EN BIT(0) |
| - |
| -#define MIPITX_DSI_SW_CTRL_CON0 0x84 |
| -#define SW_LNTC_LPTX_PRE_OE BIT(0) |
| -#define SW_LNTC_LPTX_OE BIT(1) |
| -#define SW_LNTC_LPTX_P BIT(2) |
| -#define SW_LNTC_LPTX_N BIT(3) |
| -#define SW_LNTC_HSTX_PRE_OE BIT(4) |
| -#define SW_LNTC_HSTX_OE BIT(5) |
| -#define SW_LNTC_HSTX_ZEROCLK BIT(6) |
| -#define SW_LNT0_LPTX_PRE_OE BIT(7) |
| -#define SW_LNT0_LPTX_OE BIT(8) |
| -#define SW_LNT0_LPTX_P BIT(9) |
| -#define SW_LNT0_LPTX_N BIT(10) |
| -#define SW_LNT0_HSTX_PRE_OE BIT(11) |
| -#define SW_LNT0_HSTX_OE BIT(12) |
| -#define SW_LNT0_LPRX_EN BIT(13) |
| -#define SW_LNT1_LPTX_PRE_OE BIT(14) |
| -#define SW_LNT1_LPTX_OE BIT(15) |
| -#define SW_LNT1_LPTX_P BIT(16) |
| -#define SW_LNT1_LPTX_N BIT(17) |
| -#define SW_LNT1_HSTX_PRE_OE BIT(18) |
| -#define SW_LNT1_HSTX_OE BIT(19) |
| -#define SW_LNT2_LPTX_PRE_OE BIT(20) |
| -#define SW_LNT2_LPTX_OE BIT(21) |
| -#define SW_LNT2_LPTX_P BIT(22) |
| -#define SW_LNT2_LPTX_N BIT(23) |
| -#define SW_LNT2_HSTX_PRE_OE BIT(24) |
| -#define SW_LNT2_HSTX_OE BIT(25) |
| - |
| -struct mtk_mipitx_data { |
| - const u32 mppll_preserve; |
| -}; |
| - |
| -struct mtk_mipi_tx { |
| - struct device *dev; |
| - void __iomem *regs; |
| - u32 data_rate; |
| - const struct mtk_mipitx_data *driver_data; |
| - struct clk_hw pll_hw; |
| - struct clk *pll; |
| -}; |
| +#include "mtk_mipi_tx.h" |
| |
| -static inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw) |
| +inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw) |
| { |
| return container_of(hw, struct mtk_mipi_tx, pll_hw); |
| } |
| |
| -static void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, |
| - u32 bits) |
| +void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, |
| + u32 bits) |
| { |
| u32 temp = readl(mipi_tx->regs + offset); |
| |
| writel(temp & ~bits, mipi_tx->regs + offset); |
| } |
| |
| -static void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, |
| - u32 bits) |
| +void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, |
| + u32 bits) |
| { |
| u32 temp = readl(mipi_tx->regs + offset); |
| |
| writel(temp | bits, mipi_tx->regs + offset); |
| } |
| |
| -static void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, |
| - u32 mask, u32 data) |
| +void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset, |
| + u32 mask, u32 data) |
| { |
| u32 temp = readl(mipi_tx->regs + offset); |
| |
| writel((temp & ~mask) | (data & mask), mipi_tx->regs + offset); |
| } |
| |
| -static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw) |
| +long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate, |
| + unsigned long *prate) |
| { |
| - struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); |
| - u8 txdiv, txdiv0, txdiv1; |
| - u64 pcw; |
| - |
| - dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate); |
| - |
| - if (mipi_tx->data_rate >= 500000000) { |
| - txdiv = 1; |
| - txdiv0 = 0; |
| - txdiv1 = 0; |
| - } else if (mipi_tx->data_rate >= 250000000) { |
| - txdiv = 2; |
| - txdiv0 = 1; |
| - txdiv1 = 0; |
| - } else if (mipi_tx->data_rate >= 125000000) { |
| - txdiv = 4; |
| - txdiv0 = 2; |
| - txdiv1 = 0; |
| - } else if (mipi_tx->data_rate > 62000000) { |
| - txdiv = 8; |
| - txdiv0 = 2; |
| - txdiv1 = 1; |
| - } else if (mipi_tx->data_rate >= 50000000) { |
| - txdiv = 16; |
| - txdiv0 = 2; |
| - txdiv1 = 2; |
| - } else { |
| - return -EINVAL; |
| - } |
| - |
| - mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_BG_CON, |
| - RG_DSI_VOUT_MSK | |
| - RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN, |
| - (4 << 20) | (4 << 17) | (4 << 14) | |
| - (4 << 11) | (4 << 8) | (4 << 5) | |
| - RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN); |
| - |
| - usleep_range(30, 100); |
| - |
| - mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON, |
| - RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN, |
| - (8 << 4) | RG_DSI_LNT_HS_BIAS_EN); |
| - |
| - mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_CON, |
| - RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN); |
| - |
| - mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR, |
| - RG_DSI_MPPLL_SDM_PWR_ON | |
| - RG_DSI_MPPLL_SDM_ISO_EN, |
| - RG_DSI_MPPLL_SDM_PWR_ON); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, |
| - RG_DSI_MPPLL_PLL_EN); |
| - |
| - mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0, |
| - RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 | |
| - RG_DSI_MPPLL_PREDIV, |
| - (txdiv0 << 3) | (txdiv1 << 5)); |
| - |
| - /* |
| - * PLL PCW config |
| - * PCW bit 24~30 = integer part of pcw |
| - * PCW bit 0~23 = fractional part of pcw |
| - * pcw = data_Rate*4*txdiv/(Ref_clk*2); |
| - * Post DIV =4, so need data_Rate*4 |
| - * Ref_clk is 26MHz |
| - */ |
| - pcw = div_u64(((u64)mipi_tx->data_rate * 2 * txdiv) << 24, |
| - 26000000); |
| - writel(pcw, mipi_tx->regs + MIPITX_DSI_PLL_CON2); |
| - |
| - mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON1, |
| - RG_DSI_MPPLL_SDM_FRA_EN); |
| - |
| - mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN); |
| - |
| - usleep_range(20, 100); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1, |
| - RG_DSI_MPPLL_SDM_SSC_EN); |
| - |
| - mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, |
| - RG_DSI_MPPLL_PRESERVE, |
| - mipi_tx->driver_data->mppll_preserve); |
| - |
| - return 0; |
| + return clamp_val(rate, 50000000, 1600000000); |
| } |
| |
| -static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw) |
| -{ |
| - struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); |
| - |
| - dev_dbg(mipi_tx->dev, "unprepare\n"); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, |
| - RG_DSI_MPPLL_PLL_EN); |
| - |
| - mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_TOP, |
| - RG_DSI_MPPLL_PRESERVE, 0); |
| - |
| - mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR, |
| - RG_DSI_MPPLL_SDM_ISO_EN | |
| - RG_DSI_MPPLL_SDM_PWR_ON, |
| - RG_DSI_MPPLL_SDM_ISO_EN); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON, |
| - RG_DSI_LNT_HS_BIAS_EN); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_CON, |
| - RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_BG_CON, |
| - RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0, |
| - RG_DSI_MPPLL_DIV_MSK); |
| -} |
| - |
| -static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate, |
| - unsigned long *prate) |
| -{ |
| - return clamp_val(rate, 50000000, 1250000000); |
| -} |
| - |
| -static int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate, |
| - unsigned long parent_rate) |
| +int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate, |
| + unsigned long parent_rate) |
| { |
| struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); |
| |
| @@ -307,37 +60,14 @@ static int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate, |
| return 0; |
| } |
| |
| -static unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw, |
| - unsigned long parent_rate) |
| +unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw, |
| + unsigned long parent_rate) |
| { |
| struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw); |
| |
| return mipi_tx->data_rate; |
| } |
| |
| -static const struct clk_ops mtk_mipi_tx_pll_ops = { |
| - .prepare = mtk_mipi_tx_pll_prepare, |
| - .unprepare = mtk_mipi_tx_pll_unprepare, |
| - .round_rate = mtk_mipi_tx_pll_round_rate, |
| - .set_rate = mtk_mipi_tx_pll_set_rate, |
| - .recalc_rate = mtk_mipi_tx_pll_recalc_rate, |
| -}; |
| - |
| -static int mtk_mipi_tx_power_on_signal(struct phy *phy) |
| -{ |
| - struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); |
| - u32 reg; |
| - |
| - for (reg = MIPITX_DSI_CLOCK_LANE; |
| - reg <= MIPITX_DSI_DATA_LANE3; reg += 4) |
| - mtk_mipi_tx_set_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN); |
| - |
| - mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON, |
| - RG_DSI_PAD_TIE_LOW_EN); |
| - |
| - return 0; |
| -} |
| - |
| static int mtk_mipi_tx_power_on(struct phy *phy) |
| { |
| struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); |
| @@ -349,30 +79,16 @@ static int mtk_mipi_tx_power_on(struct phy *phy) |
| return ret; |
| |
| /* Enable DSI Lane LDO outputs, disable pad tie low */ |
| - mtk_mipi_tx_power_on_signal(phy); |
| - |
| + mipi_tx->driver_data->mipi_tx_enable_signal(phy); |
| return 0; |
| } |
| |
| -static void mtk_mipi_tx_power_off_signal(struct phy *phy) |
| -{ |
| - struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); |
| - u32 reg; |
| - |
| - mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON, |
| - RG_DSI_PAD_TIE_LOW_EN); |
| - |
| - for (reg = MIPITX_DSI_CLOCK_LANE; |
| - reg <= MIPITX_DSI_DATA_LANE3; reg += 4) |
| - mtk_mipi_tx_clear_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN); |
| -} |
| - |
| static int mtk_mipi_tx_power_off(struct phy *phy) |
| { |
| struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy); |
| |
| /* Enable pad tie low, disable DSI Lane LDO outputs */ |
| - mtk_mipi_tx_power_off_signal(phy); |
| + mipi_tx->driver_data->mipi_tx_disable_signal(phy); |
| |
| /* Disable PLL and power down core */ |
| clk_disable_unprepare(mipi_tx->pll); |
| @@ -391,10 +107,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) |
| struct device *dev = &pdev->dev; |
| struct mtk_mipi_tx *mipi_tx; |
| struct resource *mem; |
| - struct clk *ref_clk; |
| const char *ref_clk_name; |
| struct clk_init_data clk_init = { |
| - .ops = &mtk_mipi_tx_pll_ops, |
| .num_parents = 1, |
| .parent_names = (const char * const *)&ref_clk_name, |
| .flags = CLK_SET_RATE_GATE, |
| @@ -408,6 +122,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) |
| return -ENOMEM; |
| |
| mipi_tx->driver_data = of_device_get_match_data(dev); |
| + |
| mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| mipi_tx->regs = devm_ioremap_resource(dev, mem); |
| if (IS_ERR(mipi_tx->regs)) { |
| @@ -416,13 +131,14 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) |
| return ret; |
| } |
| |
| - ref_clk = devm_clk_get(dev, NULL); |
| - if (IS_ERR(ref_clk)) { |
| - ret = PTR_ERR(ref_clk); |
| + mipi_tx->ref_clk = devm_clk_get(dev, NULL); |
| + if (IS_ERR(mipi_tx->ref_clk)) { |
| + ret = PTR_ERR(mipi_tx->ref_clk); |
| dev_err(dev, "Failed to get reference clock: %d\n", ret); |
| return ret; |
| } |
| - ref_clk_name = __clk_get_name(ref_clk); |
| + |
| + ref_clk_name = __clk_get_name(mipi_tx->ref_clk); |
| |
| ret = of_property_read_string(dev->of_node, "clock-output-names", |
| &clk_init.name); |
| @@ -431,6 +147,8 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) |
| return ret; |
| } |
| |
| + clk_init.ops = mipi_tx->driver_data->mipi_tx_clk_ops; |
| + |
| mipi_tx->pll_hw.init = &clk_init; |
| mipi_tx->pll = devm_clk_register(dev, &mipi_tx->pll_hw); |
| if (IS_ERR(mipi_tx->pll)) { |
| @@ -465,20 +183,14 @@ static int mtk_mipi_tx_remove(struct platform_device *pdev) |
| return 0; |
| } |
| |
| -static const struct mtk_mipitx_data mt2701_mipitx_data = { |
| - .mppll_preserve = (3 << 8) |
| -}; |
| - |
| -static const struct mtk_mipitx_data mt8173_mipitx_data = { |
| - .mppll_preserve = (0 << 8) |
| -}; |
| - |
| static const struct of_device_id mtk_mipi_tx_match[] = { |
| { .compatible = "mediatek,mt2701-mipi-tx", |
| .data = &mt2701_mipitx_data }, |
| { .compatible = "mediatek,mt8173-mipi-tx", |
| .data = &mt8173_mipitx_data }, |
| - {}, |
| + { .compatible = "mediatek,mt8183-mipi-tx", |
| + .data = &mt8183_mipitx_data }, |
| + { }, |
| }; |
| |
| struct platform_driver mtk_mipi_tx_driver = { |
| diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c |
| index 88c7d035ace66..3fbc90218c5eb 100644 |
| --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c |
| +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c |
| @@ -56,7 +56,7 @@ struct innolux_panel { |
| struct backlight_device *backlight; |
| struct regulator_bulk_data *supplies; |
| unsigned int num_supplies; |
| - struct gpio_desc *enable_gpio; |
| + struct gpio_desc *enable_gpio[2]; |
| |
| bool prepared; |
| bool enabled; |
| @@ -84,7 +84,7 @@ static int innolux_panel_disable(struct drm_panel *panel) |
| static int innolux_panel_unprepare(struct drm_panel *panel) |
| { |
| struct innolux_panel *innolux = to_innolux_panel(panel); |
| - int err; |
| + int err, i; |
| |
| if (!innolux->prepared) |
| return 0; |
| @@ -104,7 +104,8 @@ static int innolux_panel_unprepare(struct drm_panel *panel) |
| if (innolux->desc->sleep_mode_delay) |
| msleep(innolux->desc->sleep_mode_delay); |
| |
| - gpiod_set_value_cansleep(innolux->enable_gpio, 0); |
| + for (i = 0; i < ARRAY_SIZE(innolux->enable_gpio); i++) |
| + gpiod_set_value_cansleep(innolux->enable_gpio[i], 0); |
| |
| if (innolux->desc->power_down_delay) |
| msleep(innolux->desc->power_down_delay); |
| @@ -122,22 +123,28 @@ static int innolux_panel_unprepare(struct drm_panel *panel) |
| static int innolux_panel_prepare(struct drm_panel *panel) |
| { |
| struct innolux_panel *innolux = to_innolux_panel(panel); |
| - int err; |
| + int err, i; |
| |
| if (innolux->prepared) |
| return 0; |
| |
| - gpiod_set_value_cansleep(innolux->enable_gpio, 0); |
| + for (i = 0; i < ARRAY_SIZE(innolux->enable_gpio); i++) |
| + gpiod_set_value_cansleep(innolux->enable_gpio[i], 0); |
| |
| err = regulator_bulk_enable(innolux->desc->num_supplies, |
| innolux->supplies); |
| if (err < 0) |
| return err; |
| |
| - /* p079zca: t2 (20ms), p097pfg: t4 (15ms) */ |
| - usleep_range(20000, 21000); |
| + for (i = 0; i < ARRAY_SIZE(innolux->enable_gpio); i++) { |
| + if (!innolux->enable_gpio[i]) |
| + break; |
| |
| - gpiod_set_value_cansleep(innolux->enable_gpio, 1); |
| + /* p079zca: t2 (20ms), p097pfg: t4 (15ms); ssd2858: 20ms */ |
| + usleep_range(20000, 21000); |
| + |
| + gpiod_set_value_cansleep(innolux->enable_gpio[i], 1); |
| + } |
| |
| /* p079zca: t4, p097pfg: t5 */ |
| usleep_range(20000, 21000); |
| @@ -158,6 +165,18 @@ static int innolux_panel_prepare(struct drm_panel *panel) |
| goto poweroff; |
| } |
| |
| + /* |
| + * If the command list contains exit sleep mode or set |
| + * display on, wait the appropriate time (needed for |
| + * displays behind a bridge). |
| + */ |
| + /* T6: 120ms - 1000ms*/ |
| + if (cmd->data[0] == MIPI_DCS_EXIT_SLEEP_MODE) |
| + msleep(120); |
| + /* T7: 5ms */ |
| + if (cmd->data[0] == MIPI_DCS_SET_DISPLAY_ON) |
| + usleep_range(5000, 6000); |
| + |
| /* |
| * Included by random guessing, because without this |
| * (or at least, some delay), the panel sometimes |
| @@ -197,7 +216,8 @@ static int innolux_panel_prepare(struct drm_panel *panel) |
| return 0; |
| |
| poweroff: |
| - gpiod_set_value_cansleep(innolux->enable_gpio, 0); |
| + for (i = 0; i < ARRAY_SIZE(innolux->enable_gpio); i++) |
| + gpiod_set_value_cansleep(innolux->enable_gpio[i], 0); |
| regulator_bulk_disable(innolux->desc->num_supplies, innolux->supplies); |
| |
| return err; |
| @@ -405,6 +425,90 @@ static const struct panel_desc innolux_p097pfg_panel_desc = { |
| .sleep_mode_delay = 100, /* T15 */ |
| }; |
| |
| +static const char * const innolux_p097pfg_ssd2858_supply_names[] = { |
| + "avdd", |
| + "avee", |
| + "pp1800", |
| + "pp3300", |
| + "pp1200-bridge", |
| + "vddio-bridge", |
| +}; |
| + |
| +static const struct drm_display_mode innolux_p097pfg_ssd2858_mode = { |
| + .clock = 229000, |
| + .hdisplay = 1536, |
| + .hsync_start = 1536 + 80, |
| + .hsync_end = 1536 + 80 + 26, |
| + .htotal = 1536 + 80 + 26 + 54, |
| + .vdisplay = 2048, |
| + .vsync_start = 2048 + 20, |
| + .vsync_end = 2048 + 20 + 2, |
| + .vtotal = 2048 + 20 + 2 + 10, |
| + .vrefresh = 60, |
| +}; |
| + |
| +static const struct panel_init_cmd innolux_p097pfg_ssd2858_init_cmds[] = { |
| + /* SSD2858 config */ |
| + _INIT_CMD(0xff, 0x00), |
| + /* LOCKCNT=0x1f4, MRX=0, POSTDIV=1 (/2), MULT=0x49 |
| + * 27 Mhz => 985.5 Mhz */ |
| + _INIT_CMD(0x00, 0x08, 0x01, 0xf4, 0x01, 0x49), |
| + /* MTXDIV=1, SYSDIV=3 (=> 4) */ |
| + _INIT_CMD(0x00, 0x0c, 0x00, 0x00, 0x00, 0x03), |
| + /* MTXVPF=24bpp, MRXLS=4 lanes, MRXVB=bypass, MRXECC=1, MRXEOT=1 |
| + * MRXEE=1 */ |
| + _INIT_CMD(0x00, 0x14, 0x0c, 0x3d, 0x80, 0x0f), |
| + _INIT_CMD(0x00, 0x20, 0x15, 0x92, 0x56, 0x7d), |
| + _INIT_CMD(0x00, 0x24, 0x00, 0x00, 0x30, 0x00), |
| + |
| + _INIT_CMD(0x10, 0x08, 0x01, 0x20, 0x08, 0x45), |
| + _INIT_CMD(0x10, 0x1c, 0x00, 0x00, 0x00, 0x00), |
| + _INIT_CMD(0x20, 0x0c, 0x00, 0x00, 0x00, 0x04), |
| + /* Pixel clock 985.5 Mhz * 0x49/0x4b = 959 Mhz */ |
| + _INIT_CMD(0x20, 0x10, 0x00, 0x4b, 0x00, 0x49), |
| + _INIT_CMD(0x20, 0xa0, 0x00, 0x00, 0x00, 0x00), |
| + /* EOT=1, LPE = 0, LSOUT=4 lanes, LPD=25 */ |
| + _INIT_CMD(0x60, 0x08, 0x00, 0xd9, 0x00, 0x08), |
| + _INIT_CMD(0x60, 0x14, 0x01, 0x00, 0x01, 0x06), |
| + /* DSI0 enable (default: probably not needed) */ |
| + _INIT_CMD(0x60, 0x80, 0x00, 0x00, 0x00, 0x0f), |
| + /* DSI1 enable */ |
| + _INIT_CMD(0x60, 0xa0, 0x00, 0x00, 0x00, 0x0f), |
| + |
| + /* HSA=0x18, VSA=0x02, HBP=0x50, VBP=0x0c */ |
| + _INIT_CMD(0x60, 0x0c, 0x0c, 0x50, 0x02, 0x18), |
| + /* VACT= 0x800 (2048), VFP= 0x14, HFP=0x50 */ |
| + _INIT_CMD(0x60, 0x10, 0x08, 0x00, 0x14, 0x50), |
| + /* HACT=0x300 (768) */ |
| + _INIT_CMD(0x60, 0x84, 0x00, 0x00, 0x03, 0x00), |
| + _INIT_CMD(0x60, 0xa4, 0x00, 0x00, 0x03, 0x00), |
| + |
| + /* Take panel out of sleep. */ |
| + _INIT_CMD(0xff, 0x01), |
| + _INIT_CMD(0x11), |
| + _INIT_CMD(0x29), |
| + _INIT_CMD(0xff, 0x00), |
| + |
| + {}, |
| +}; |
| + |
| +static const struct panel_desc innolux_p097pfg_ssd2858_panel_desc = { |
| + .mode = &innolux_p097pfg_ssd2858_mode, |
| + .bpc = 8, |
| + .size = { |
| + .width = 147, |
| + .height = 196, |
| + }, |
| + .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | |
| + MIPI_DSI_MODE_LPM, |
| + .format = MIPI_DSI_FMT_RGB888, |
| + .init_cmds = innolux_p097pfg_ssd2858_init_cmds, |
| + .lanes = 4, |
| + .supply_names = innolux_p097pfg_ssd2858_supply_names, |
| + .num_supplies = ARRAY_SIZE(innolux_p097pfg_ssd2858_supply_names), |
| + .sleep_mode_delay = 100, /* T15 */ |
| +}; |
| + |
| static int innolux_panel_get_modes(struct drm_panel *panel) |
| { |
| struct innolux_panel *innolux = to_innolux_panel(panel); |
| @@ -446,6 +550,9 @@ static const struct of_device_id innolux_of_match[] = { |
| { .compatible = "innolux,p097pfg", |
| .data = &innolux_p097pfg_panel_desc |
| }, |
| + { .compatible = "innolux,p097pfg_ssd2858", |
| + .data = &innolux_p097pfg_ssd2858_panel_desc |
| + }, |
| { } |
| }; |
| MODULE_DEVICE_TABLE(of, innolux_of_match); |
| @@ -477,12 +584,14 @@ static int innolux_panel_add(struct mipi_dsi_device *dsi, |
| if (err < 0) |
| return err; |
| |
| - innolux->enable_gpio = devm_gpiod_get_optional(dev, "enable", |
| - GPIOD_OUT_HIGH); |
| - if (IS_ERR(innolux->enable_gpio)) { |
| - err = PTR_ERR(innolux->enable_gpio); |
| - dev_dbg(dev, "failed to get enable gpio: %d\n", err); |
| - innolux->enable_gpio = NULL; |
| + for (i = 0; i < ARRAY_SIZE(innolux->enable_gpio); i++) { |
| + innolux->enable_gpio[i] = devm_gpiod_get_index_optional(dev, |
| + "enable", i, GPIOD_OUT_HIGH); |
| + if (IS_ERR(innolux->enable_gpio[i])) { |
| + err = PTR_ERR(innolux->enable_gpio[i]); |
| + dev_err(dev, "failed to get enable gpio: %d\n", err); |
| + innolux->enable_gpio[i] = NULL; |
| + } |
| } |
| |
| innolux->backlight = devm_of_find_backlight(dev); |
| diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig |
| index 841c005d8ebb2..31dc4c5e37e1c 100644 |
| --- a/drivers/mailbox/Kconfig |
| +++ b/drivers/mailbox/Kconfig |
| @@ -205,4 +205,22 @@ config MTK_CMDQ_MBOX |
| mailbox driver. The CMDQ is used to help read/write registers with |
| critical time limitation, such as updating display configuration |
| during the vblank. |
| + |
| +config MTK_CMDQ_DEBUG |
| + tristate "MediaTek CMDQ Mailbox Debug" |
| + depends on MTK_CMDQ_MBOX |
| + help |
| + Say yes here to add support for debugging CMDQ driver when timeout |
| + or irq status error happens. It will print some useful information |
| + for location problem, such as thread id, PC value and instructions |
| + of command queue buffer. |
| + |
| +config MTK_CMDQ_DEBUG_SOC |
| + int "MediaTek CMDQ Mailbox Debug SOC" |
| + depends on MTK_CMDQ_DEBUG |
| + help |
| + Enter the SOC id that you want to debug CMDQ driver when timeout |
| + or irq status error happens. |
| + The SOC id is a decimal integer, e.g. 8173 for MT8173 SOC. |
| + You must enter the id. |
| endif |
| diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile |
| index c818b5d011aef..b356e36d8f2ac 100644 |
| --- a/drivers/mailbox/Makefile |
| +++ b/drivers/mailbox/Makefile |
| @@ -44,3 +44,4 @@ obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o |
| obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o |
| |
| obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o |
| +obj-$(CONFIG_MTK_CMDQ_DEBUG) += mtk-cmdq-debug.o |
| diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c |
| index aec46d5d35061..2c53ece47abd7 100644 |
| --- a/drivers/mailbox/mtk-cmdq-mailbox.c |
| +++ b/drivers/mailbox/mtk-cmdq-mailbox.c |
| @@ -15,9 +15,11 @@ |
| #include <linux/mailbox_controller.h> |
| #include <linux/mailbox/mtk-cmdq-mailbox.h> |
| #include <linux/of_device.h> |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| +#include "mtk-cmdq-debug.h" |
| +#endif |
| |
| #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) |
| -#define CMDQ_IRQ_MASK 0xffff |
| #define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE) |
| |
| #define CMDQ_CURR_IRQ_STATUS 0x10 |
| @@ -34,6 +36,7 @@ |
| #define CMDQ_THR_END_ADDR 0x24 |
| #define CMDQ_THR_WAIT_TOKEN 0x30 |
| #define CMDQ_THR_PRIORITY 0x40 |
| +#define CMDQ_SYNC_TOKEN_UPDATE 0x68 |
| |
| #define CMDQ_THR_ACTIVE_SLOT_CYCLES 0x3200 |
| #define CMDQ_THR_ENABLED 0x1 |
| @@ -71,11 +74,38 @@ struct cmdq { |
| void __iomem *base; |
| u32 irq; |
| u32 thread_nr; |
| + u32 irq_mask; |
| struct cmdq_thread *thread; |
| struct clk *clock; |
| bool suspended; |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| + struct workqueue_struct *buf_dump_wq; |
| +#endif |
| }; |
| |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| +static void cmdq_buf_dump_schedule(struct cmdq_task *task, bool timeout, |
| + u32 pa_curr) |
| +{ |
| + struct device *dev = task->cmdq->mbox.dev; |
| + struct cmdq_buf_dump *buf_dump; |
| + |
| + buf_dump = kmalloc(sizeof(*buf_dump), GFP_ATOMIC); |
| + buf_dump->dev = dev; |
| + buf_dump->timeout = timeout; |
| + buf_dump->cmd_buf = kmalloc(task->pkt->cmd_buf_size, GFP_ATOMIC); |
| + buf_dump->cmd_buf_size = task->pkt->cmd_buf_size; |
| + buf_dump->pa_offset = pa_curr - task->pa_base; |
| + dma_sync_single_for_cpu(dev, task->pa_base, |
| + task->pkt->cmd_buf_size, DMA_TO_DEVICE); |
| + memcpy(buf_dump->cmd_buf, task->pkt->va_base, task->pkt->cmd_buf_size); |
| + dma_sync_single_for_device(dev, task->pa_base, |
| + task->pkt->cmd_buf_size, DMA_TO_DEVICE); |
| + INIT_WORK(&buf_dump->dump_work, cmdq_debug_buf_dump_work); |
| + queue_work(task->cmdq->buf_dump_wq, &buf_dump->dump_work); |
| +} |
| +#endif |
| + |
| static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread) |
| { |
| u32 status; |
| @@ -103,8 +133,12 @@ static void cmdq_thread_resume(struct cmdq_thread *thread) |
| |
| static void cmdq_init(struct cmdq *cmdq) |
| { |
| + int i; |
| + |
| WARN_ON(clk_enable(cmdq->clock) < 0); |
| writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); |
| + for (i = 0; i <= CMDQ_MAX_EVENT; i++) |
| + writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE); |
| clk_disable(cmdq->clock); |
| } |
| |
| @@ -211,12 +245,19 @@ static void cmdq_task_exec_done(struct cmdq_task *task, enum cmdq_cb_status sta) |
| list_del(&task->list_entry); |
| } |
| |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| +static void cmdq_task_handle_error(struct cmdq_task *task, u32 pa_curr) |
| +#else |
| static void cmdq_task_handle_error(struct cmdq_task *task) |
| +#endif |
| { |
| struct cmdq_thread *thread = task->thread; |
| struct cmdq_task *next_task; |
| |
| dev_err(task->cmdq->mbox.dev, "task 0x%p error\n", task); |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| + cmdq_buf_dump_schedule(task, false, pa_curr); |
| +#endif |
| WARN_ON(cmdq_thread_suspend(task->cmdq, thread) < 0); |
| next_task = list_first_entry_or_null(&thread->task_busy_list, |
| struct cmdq_task, list_entry); |
| @@ -264,7 +305,11 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, |
| kfree(task); |
| } else if (err) { |
| cmdq_task_exec_done(task, CMDQ_CB_ERROR); |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| + cmdq_task_handle_error(curr_task, curr_pa); |
| +#else |
| cmdq_task_handle_error(curr_task); |
| +#endif |
| kfree(task); |
| } |
| |
| @@ -284,11 +329,11 @@ static irqreturn_t cmdq_irq_handler(int irq, void *dev) |
| unsigned long irq_status, flags = 0L; |
| int bit; |
| |
| - irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS) & CMDQ_IRQ_MASK; |
| - if (!(irq_status ^ CMDQ_IRQ_MASK)) |
| + irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS) & cmdq->irq_mask; |
| + if (!(irq_status ^ cmdq->irq_mask)) |
| return IRQ_NONE; |
| |
| - for_each_clear_bit(bit, &irq_status, fls(CMDQ_IRQ_MASK)) { |
| + for_each_clear_bit(bit, &irq_status, cmdq->thread_nr) { |
| struct cmdq_thread *thread = &cmdq->thread[bit]; |
| |
| spin_lock_irqsave(&thread->chan->lock, flags); |
| @@ -337,6 +382,9 @@ static int cmdq_remove(struct platform_device *pdev) |
| { |
| struct cmdq *cmdq = platform_get_drvdata(pdev); |
| |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| + destroy_workqueue(cmdq->buf_dump_wq); |
| +#endif |
| mbox_controller_unregister(&cmdq->mbox); |
| clk_unprepare(cmdq->clock); |
| |
| @@ -430,6 +478,36 @@ static int cmdq_mbox_startup(struct mbox_chan *chan) |
| |
| static void cmdq_mbox_shutdown(struct mbox_chan *chan) |
| { |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| + struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; |
| + struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); |
| + struct cmdq_task *task, *tmp; |
| + unsigned long flags; |
| + bool first_task = true; |
| + |
| + spin_lock_irqsave(&thread->chan->lock, flags); |
| + |
| + if (list_empty(&thread->task_busy_list)) { |
| + spin_unlock_irqrestore(&thread->chan->lock, flags); |
| + return; |
| + } |
| + |
| + dev_err(cmdq->mbox.dev, "cmdq timeout\n"); |
| + list_for_each_entry_safe(task, tmp, &thread->task_busy_list, |
| + list_entry) { |
| + if (first_task) { |
| + cmdq_buf_dump_schedule(task, true, readl( |
| + thread->base + CMDQ_THR_CURR_ADDR)); |
| + first_task = false; |
| + } |
| + cmdq_task_exec_done(task, CMDQ_CB_ERROR); |
| + kfree(task); |
| + } |
| + |
| + cmdq_thread_disable(cmdq, thread); |
| + clk_disable(cmdq->clock); |
| + spin_unlock_irqrestore(&thread->chan->lock, flags); |
| +#endif |
| } |
| |
| static const struct mbox_chan_ops cmdq_mbox_chan_ops = { |
| @@ -478,6 +556,9 @@ static int cmdq_probe(struct platform_device *pdev) |
| dev_err(dev, "failed to get irq\n"); |
| return -EINVAL; |
| } |
| + |
| + cmdq->thread_nr = (u32)(unsigned long)of_device_get_match_data(dev); |
| + cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0); |
| err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, |
| "mtk_cmdq", cmdq); |
| if (err < 0) { |
| @@ -494,7 +575,6 @@ static int cmdq_probe(struct platform_device *pdev) |
| return PTR_ERR(cmdq->clock); |
| } |
| |
| - cmdq->thread_nr = (u32)(unsigned long)of_device_get_match_data(dev); |
| cmdq->mbox.dev = dev; |
| cmdq->mbox.chans = devm_kcalloc(dev, cmdq->thread_nr, |
| sizeof(*cmdq->mbox.chans), GFP_KERNEL); |
| @@ -532,6 +612,14 @@ static int cmdq_probe(struct platform_device *pdev) |
| |
| cmdq_init(cmdq); |
| |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| + cmdq->buf_dump_wq = alloc_ordered_workqueue( |
| + "%s", WQ_MEM_RECLAIM | WQ_HIGHPRI, |
| + "cmdq_buf_dump"); |
| +#endif |
| + for (i = 0; i <= CMDQ_MAX_EVENT; i++) |
| + writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE); |
| + |
| return 0; |
| } |
| |
| @@ -542,6 +630,7 @@ static const struct dev_pm_ops cmdq_pm_ops = { |
| |
| static const struct of_device_id cmdq_of_ids[] = { |
| {.compatible = "mediatek,mt8173-gce", .data = (void *)16}, |
| + {.compatible = "mediatek,mt8183-gce", .data = (void *)24}, |
| {} |
| }; |
| |
| diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c |
| index f8d35e3ac1dcc..01cab05e7b818 100644 |
| --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c |
| +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c |
| @@ -49,25 +49,63 @@ |
| #define VPU_P_FW_SIZE (VPU_PTCM_SIZE + VPU_EXT_P_SIZE) |
| #define VPU_D_FW_SIZE (VPU_DTCM_SIZE + VPU_EXT_D_SIZE) |
| /* the size of share buffer between Host and VPU */ |
| -#define SHARE_BUF_SIZE 48 |
| |
| /* binary firmware name */ |
| #define VPU_P_FW "vpu_p.bin" |
| #define VPU_D_FW "vpu_d.bin" |
| |
| -#define VPU_RESET 0x0 |
| -#define VPU_TCM_CFG 0x0008 |
| -#define VPU_PMEM_EXT0_ADDR 0x000C |
| -#define VPU_PMEM_EXT1_ADDR 0x0010 |
| -#define VPU_TO_HOST 0x001C |
| -#define VPU_DMEM_EXT0_ADDR 0x0014 |
| -#define VPU_DMEM_EXT1_ADDR 0x0018 |
| -#define HOST_TO_VPU 0x0024 |
| -#define VPU_PC_REG 0x0060 |
| -#define VPU_WDT_REG 0x0084 |
| +enum vpu_regs_idx { |
| + VPU_RESET, |
| + VPU_TCM_CFG, |
| + VPU_TO_HOST, |
| + HOST_TO_VPU, |
| + VPU_PC_REG, |
| + VPU_WDT_REG, |
| + |
| + /* MT8173 only regs */ |
| + VPU_PMEM_EXT0_ADDR, |
| + VPU_PMEM_EXT1_ADDR, |
| + VPU_DMEM_EXT0_ADDR, |
| + VPU_DMEM_EXT1_ADDR, |
| +}; |
| + |
| +enum vpu_type { |
| + VPU_MT8173, |
| + VPU_MT8183, |
| +}; |
| |
| -/* vpu inter-processor communication interrupt */ |
| -#define VPU_IPC_INT BIT(8) |
| +/** |
| + * struct hw_type - VPU hardware type |
| + * |
| + * @regs: the register index for VPU configuration |
| + * @dtcm_offset: the offset to get data tcm address |
| + * @share_obj_sz: share object size, including id, len, share_buf |
| + * @ptcm_sz: maximum program TCM (Tightly-Coupled Memory) size |
| + * @dtcm_sz: maximum data TCM (Tightly-Coupled Memory) size |
| + * @ext_p_sz: daynamic allocated maximum extended program memory size |
| + * @ext_d_sz: daynamic allocated maximum extended data memory size |
| + * @type: the soc where VPU embedded |
| + * @ext_mem_support: extended memory support |
| + * @fw_p: program firmware name |
| + * @fw_d: data firmware name |
| + * @ipc_int: inter-processor communication interrupt bit |
| + * @wdt_int: vpu watch dog timer interrupt bit |
| + */ |
| +struct hw_type { |
| + int *regs; |
| + unsigned long dtcm_offset; |
| + size_t share_obj_sz; |
| + size_t ptcm_sz; |
| + size_t dtcm_sz; |
| + size_t ext_p_sz; |
| + size_t ext_d_sz; |
| + u32 type; |
| + bool ext_mem_support; |
| + char *fw_p; |
| + char *fw_d; |
| + u32 ipc_int; |
| + u32 wdt_int; |
| +}; |
| |
| /** |
| * enum vpu_fw_type - VPU firmware type |
| @@ -173,7 +211,8 @@ struct vpu_ipi_desc { |
| struct share_obj { |
| s32 id; |
| u32 len; |
| - unsigned char share_buf[SHARE_BUF_SIZE]; |
| + /* "share_buf" must be in the last member of this data structure */ |
| + unsigned char *share_buf; |
| }; |
| |
| /** |
| @@ -188,6 +227,7 @@ struct share_obj { |
| * @send_buf: VPU DTCM share buffer for sending |
| * @dev: VPU struct device |
| * @clk: VPU clock on/off |
| + * @hw: the different VPU hardware embedded into mtk SoCs |
| * @fw_loaded: indicate VPU firmware loaded |
| * @enable_4GB: VPU 4GB mode on/off |
| * @vpu_mutex: protect mtk_vpu (except recv_buf) and ensure only |
| @@ -195,7 +235,7 @@ struct share_obj { |
| * suppose a client is using VPU to decode VP8. |
| * If the other client wants to encode VP8, |
| * it has to wait until VP8 decode completes. |
| - * @wdt_refcnt: WDT reference count to make sure the watchdog can be |
| + * @wdt_refcnt: WDT reference count to make sure the watchdog can be |
| * disabled if no other client is using VPU service |
| * @ack_wq: The wait queue for each codec and mdp. When sleeping |
| * processes wake up, they will check the condition |
| @@ -215,6 +255,7 @@ struct mtk_vpu { |
| struct share_obj *send_buf; |
| struct device *dev; |
| struct clk *clk; |
| + const struct hw_type *hw; |
| bool fw_loaded; |
| bool enable_4GB; |
| struct mutex vpu_mutex; /* for protecting vpu data data structure */ |
| @@ -223,14 +264,64 @@ struct mtk_vpu { |
| bool ipi_id_ack[IPI_MAX]; |
| }; |
| |
| +static int mt8173_regs[] = { |
| + [VPU_RESET] = 0x0, |
| + [VPU_TCM_CFG] = 0x8, |
| + [VPU_TO_HOST] = 0x1C, |
| + [HOST_TO_VPU] = 0x24, |
| + [VPU_PC_REG] = 0x60, |
| + [VPU_WDT_REG] = 0x84, |
| + [VPU_PMEM_EXT0_ADDR] = 0x0C, |
| + [VPU_PMEM_EXT1_ADDR] = 0x10, |
| + [VPU_DMEM_EXT0_ADDR] = 0x14, |
| + [VPU_DMEM_EXT1_ADDR] = 0x18, |
| +}; |
| + |
| +static int mt8183_regs[] = { |
| + [VPU_RESET] = 0x0, |
| + [VPU_TO_HOST] = 0x1C, |
| + [HOST_TO_VPU] = 0x28, |
| + [VPU_PC_REG] = 0xB4, |
| + [VPU_WDT_REG] = 0x1C, |
| +}; |
| + |
| +static const struct hw_type vpu_mt8173 = { |
| + .regs = mt8173_regs, |
| + .dtcm_offset = 0x18000, |
| + .share_obj_sz = (8+48), |
| + .ptcm_sz = (96 * SZ_1K), |
| + .dtcm_sz = (32 * SZ_1K), |
| + .ext_p_sz = SZ_1M, |
| + .ext_d_sz = SZ_4M, |
| + .type = VPU_MT8173, |
| + .ext_mem_support = true, |
| + .fw_p = "vpu_p.bin", |
| + .fw_d = "vpu_d.bin", |
| + .ipc_int = BIT(8), |
| +}; |
| + |
| +static const struct hw_type vpu_mt8183 = { |
| + .regs = mt8183_regs, |
| + .dtcm_offset = 0, |
| + .share_obj_sz = (8+288), |
| + .ptcm_sz = (512 * SZ_1K), |
| + .dtcm_sz = (512 * SZ_1K), |
| + .ext_p_sz = 0, |
| + .ext_d_sz = 0, |
| + .type = VPU_MT8183, |
| + .ext_mem_support = false, |
| + .ipc_int = BIT(0), |
| + .wdt_int = BIT(8), |
| +}; |
| + |
| static inline void vpu_cfg_writel(struct mtk_vpu *vpu, u32 val, u32 offset) |
| { |
| - writel(val, vpu->reg.cfg + offset); |
| + writel(val, vpu->reg.cfg + vpu->hw->regs[offset]); |
| } |
| |
| static inline u32 vpu_cfg_readl(struct mtk_vpu *vpu, u32 offset) |
| { |
| - return readl(vpu->reg.cfg + offset); |
| + return readl(vpu->reg.cfg + vpu->hw->regs[offset]); |
| } |
| |
| static inline bool vpu_running(struct mtk_vpu *vpu) |
| @@ -295,9 +386,10 @@ int vpu_ipi_register(struct platform_device *pdev, |
| } |
| EXPORT_SYMBOL_GPL(vpu_ipi_register); |
| |
| -int vpu_ipi_send(struct platform_device *pdev, |
| +int vpu_ipi_send_sync_async(struct platform_device *pdev, |
| enum ipi_id id, void *buf, |
| - unsigned int len) |
| + unsigned int len, |
| + unsigned int wait) |
| { |
| struct mtk_vpu *vpu = platform_get_drvdata(pdev); |
| struct share_obj *send_obj = vpu->send_buf; |
| @@ -305,7 +397,7 @@ int vpu_ipi_send(struct platform_device *pdev, |
| int ret = 0; |
| |
| if (id <= IPI_VPU_INIT || id >= IPI_MAX || |
| - len > sizeof(send_obj->share_buf) || !buf) { |
| + len > (vpu->hw->share_obj_sz - 8) || !buf) { |
| dev_err(vpu->dev, "failed to send ipi message\n"); |
| return -EINVAL; |
| } |
| @@ -333,24 +425,27 @@ int vpu_ipi_send(struct platform_device *pdev, |
| } |
| } while (vpu_cfg_readl(vpu, HOST_TO_VPU)); |
| |
| - memcpy((void *)send_obj->share_buf, buf, len); |
| + memcpy((void *)&send_obj->share_buf, buf, len); |
| send_obj->len = len; |
| send_obj->id = id; |
| |
| vpu->ipi_id_ack[id] = false; |
| + mb(); |
| /* send the command to VPU */ |
| vpu_cfg_writel(vpu, 0x1, HOST_TO_VPU); |
| |
| mutex_unlock(&vpu->vpu_mutex); |
| |
| - /* wait for VPU's ACK */ |
| - timeout = msecs_to_jiffies(IPI_TIMEOUT_MS); |
| - ret = wait_event_timeout(vpu->ack_wq, vpu->ipi_id_ack[id], timeout); |
| - vpu->ipi_id_ack[id] = false; |
| - if (ret == 0) { |
| - dev_err(vpu->dev, "vpu ipi %d ack time out !", id); |
| - ret = -EIO; |
| - goto clock_disable; |
| + if (wait) { |
| + /* wait for VPU's ACK */ |
| + timeout = msecs_to_jiffies(IPI_TIMEOUT_MS); |
| + ret = wait_event_timeout(vpu->ack_wq, vpu->ipi_id_ack[id], timeout); |
| + vpu->ipi_id_ack[id] = false; |
| + if (ret == 0) { |
| + dev_err(vpu->dev, "vpu ipi %d ack time out !", id); |
| + ret = -EIO; |
| + goto clock_disable; |
| + } |
| } |
| vpu_clock_disable(vpu); |
| |
| @@ -363,6 +458,15 @@ int vpu_ipi_send(struct platform_device *pdev, |
| |
| return ret; |
| } |
| +EXPORT_SYMBOL_GPL(vpu_ipi_send_sync_async); |
| + |
| +int vpu_ipi_send(struct platform_device *pdev, |
| + enum ipi_id id, void *buf, |
| + unsigned int len) |
| +{ |
| + return vpu_ipi_send_sync_async(pdev, id, buf, len, 1); |
| + |
| +} |
| EXPORT_SYMBOL_GPL(vpu_ipi_send); |
| |
| static void vpu_wdt_reset_func(struct work_struct *ws) |
| @@ -442,16 +546,16 @@ void *vpu_mapping_dm_addr(struct platform_device *pdev, |
| struct mtk_vpu *vpu = platform_get_drvdata(pdev); |
| |
| if (!dtcm_dmem_addr || |
| - (dtcm_dmem_addr > (VPU_DTCM_SIZE + VPU_EXT_D_SIZE))) { |
| + (dtcm_dmem_addr > (vpu->hw->dtcm_sz + vpu->hw->ext_d_sz))) { |
| dev_err(vpu->dev, "invalid virtual data memory address\n"); |
| return ERR_PTR(-EINVAL); |
| } |
| |
| - if (dtcm_dmem_addr < VPU_DTCM_SIZE) |
| + if (dtcm_dmem_addr < vpu->hw->dtcm_sz) |
| return (__force void *)(dtcm_dmem_addr + vpu->reg.tcm + |
| - VPU_DTCM_OFFSET); |
| + vpu->hw->dtcm_offset); |
| |
| - return vpu->extmem[D_FW].va + (dtcm_dmem_addr - VPU_DTCM_SIZE); |
| + return vpu->extmem[D_FW].va + (dtcm_dmem_addr - vpu->hw->dtcm_sz); |
| } |
| EXPORT_SYMBOL_GPL(vpu_mapping_dm_addr); |
| |
| @@ -478,14 +582,138 @@ struct platform_device *vpu_get_plat_device(struct platform_device *pdev) |
| } |
| EXPORT_SYMBOL_GPL(vpu_get_plat_device); |
| |
| +#if VPU_RESERVED_MEM |
| +phys_addr_t vpu_mem_base_phys; |
| +phys_addr_t vpu_mem_base_virt; |
| +phys_addr_t vpu_mem_size; |
| + |
| +#ifdef CONFIG_OF_RESERVED_MEM |
| +#define VPU_MEM_RESERVED_KEY "mediatek,reserve-memory-vpu_share" |
| + |
| +static struct vpu_reserve_mblock vpu_reserve_mblock[] = { |
| + { |
| + .num = ISP_MEM_ID, |
| + .start_phys = 0x0, |
| + .start_virt = 0x0, |
| + .size = 0x1400000, /*20MB*/ |
| + }, |
| +}; |
| + |
| +int vpu_reserve_mem_of_init(struct reserved_mem *rmem) |
| +{ |
| + enum vpu_reserve_mem_id_t id; |
| + phys_addr_t accumlate_memory_size = 0; |
| + |
| + vpu_mem_base_phys = (phys_addr_t) rmem->base; |
| + vpu_mem_size = (phys_addr_t) rmem->size; |
| + if ((vpu_mem_base_phys >= (0x90000000ULL)) || (vpu_mem_base_phys <= 0x0)) { |
| + /*The vpu remap region is fixed, only |
| + * 0x4000_0000ULL~0x9FFF_FFFFULL |
| + * can be accessible |
| + */ |
| + pr_err("[VPU] The allocated memory(0x%llx) is larger than expected\n", vpu_mem_base_phys); |
| + /*should not call WARN_ON() here or there is no log, return -1 |
| + * instead. |
| + */ |
| + return -1; |
| + } |
| + |
| + pr_debug("[VPU] phys:0x%llx - 0x%llx (0x%llx)\n", (phys_addr_t)rmem->base, |
| + (phys_addr_t)rmem->base + (phys_addr_t)rmem->size, (phys_addr_t)rmem->size); |
| + accumlate_memory_size = 0; |
| + for (id = 0; id < NUMS_MEM_ID; id++) { |
| + vpu_reserve_mblock[id].start_phys = vpu_mem_base_phys + accumlate_memory_size; |
| + accumlate_memory_size += vpu_reserve_mblock[id].size; |
| + pr_debug("[VPU][reserve_mem:%d]: phys:0x%llx - 0x%llx (0x%llx)\n", id, |
| + vpu_reserve_mblock[id].start_phys, |
| + vpu_reserve_mblock[id].start_phys+vpu_reserve_mblock[id].size, |
| + vpu_reserve_mblock[id].size); |
| + } |
| + return 0; |
| +} |
| + |
| +RESERVEDMEM_OF_DECLARE(vpu_reserve_mem_init, VPU_MEM_RESERVED_KEY, vpu_reserve_mem_of_init); |
| +#endif |
| + |
| +static int vpu_reserve_memory_ioremap(void) |
| +{ |
| + enum vpu_reserve_mem_id_t id; |
| + phys_addr_t accumlate_memory_size; |
| + |
| + |
| + if ((vpu_mem_base_phys >= (0x90000000ULL)) || (vpu_mem_base_phys <= 0x0)) { |
| + /*The vpu remap region is fixed, only |
| + * 0x4000_0000ULL~0x8FFF_FFFFULL |
| + * can be accessible |
| + */ |
| + pr_err("[VPU] The allocated memory(0x%llx) is larger than expected\n", vpu_mem_base_phys); |
| + /*call WARN_ON() here to assert the unexpected memory allocation |
| + */ |
| + WARN_ON(1); |
| + return -1; |
| + } |
| + accumlate_memory_size = 0; |
| + vpu_mem_base_virt = (phys_addr_t)(size_t)ioremap_wc(vpu_mem_base_phys, vpu_mem_size); |
| + pr_debug("[VPU]reserve mem: virt:0x%llx - 0x%llx (0x%llx)\n", (phys_addr_t)vpu_mem_base_virt, |
| + (phys_addr_t)vpu_mem_base_virt + (phys_addr_t)vpu_mem_size, vpu_mem_size); |
| + for (id = 0; id < NUMS_MEM_ID; id++) { |
| + vpu_reserve_mblock[id].start_virt = vpu_mem_base_virt + accumlate_memory_size; |
| + accumlate_memory_size += vpu_reserve_mblock[id].size; |
| + } |
| + /* the reserved memory should be larger then expected memory |
| + * or vpu_reserve_mblock does not match dts |
| + */ |
| + WARN_ON(accumlate_memory_size > vpu_mem_size); |
| +#ifdef DEBUG |
| + for (id = 0; id < NUMS_MEM_ID; id++) { |
| + pr_info("[VPU][mem_reserve-%d] phys:0x%llx,virt:0x%llx,size:0x%llx\n", |
| + id, vpu_get_reserve_mem_phys(id), vpu_get_reserve_mem_virt(id), vpu_get_reserve_mem_size(id)); |
| + } |
| +#endif |
| + return 0; |
| +} |
| + |
| +phys_addr_t vpu_get_reserve_mem_phys(enum vpu_reserve_mem_id_t id) |
| +{ |
| + if (id >= NUMS_MEM_ID) { |
| + pr_err("[VPU] no reserve memory for %d", id); |
| + return 0; |
| + } else |
| + return vpu_reserve_mblock[id].start_phys; |
| +} |
| +EXPORT_SYMBOL_GPL(vpu_get_reserve_mem_phys); |
| + |
| +phys_addr_t vpu_get_reserve_mem_virt(enum vpu_reserve_mem_id_t id) |
| +{ |
| + if (id >= NUMS_MEM_ID) { |
| + pr_err("[VPU] no reserve memory for %d", id); |
| + return 0; |
| + } else |
| + return vpu_reserve_mblock[id].start_virt; |
| +} |
| +EXPORT_SYMBOL_GPL(vpu_get_reserve_mem_virt); |
| + |
| +phys_addr_t vpu_get_reserve_mem_size(enum vpu_reserve_mem_id_t id) |
| +{ |
| + if (id >= NUMS_MEM_ID) { |
| + pr_err("[VPU] no reserve memory for %d", id); |
| + return 0; |
| + } else |
| + return vpu_reserve_mblock[id].size; |
| +} |
| +EXPORT_SYMBOL_GPL(vpu_get_reserve_mem_size); |
| +#endif |
| + |
| /* load vpu program/data memory */ |
| static int load_requested_vpu(struct mtk_vpu *vpu, |
| const struct firmware *vpu_fw, |
| u8 fw_type) |
| { |
| - size_t tcm_size = fw_type ? VPU_DTCM_SIZE : VPU_PTCM_SIZE; |
| - size_t fw_size = fw_type ? VPU_D_FW_SIZE : VPU_P_FW_SIZE; |
| - char *fw_name = fw_type ? VPU_D_FW : VPU_P_FW; |
| + size_t tcm_size = fw_type ? vpu->hw->dtcm_sz : vpu->hw->ptcm_sz; |
| + size_t fw_size = fw_type |
| + ? vpu->hw->dtcm_sz + vpu->hw->ext_d_sz |
| + : vpu->hw->ptcm_sz + vpu->hw->ext_p_sz; |
| + char *fw_name = fw_type ? vpu->hw->fw_d : vpu->hw->fw_p; |
| size_t dl_size = 0; |
| size_t extra_fw_size = 0; |
| void *dest; |
| @@ -519,7 +747,7 @@ static int load_requested_vpu(struct mtk_vpu *vpu, |
| } |
| dest = (__force void *)vpu->reg.tcm; |
| if (fw_type == D_FW) |
| - dest += VPU_DTCM_OFFSET; |
| + dest += vpu->hw->dtcm_offset; |
| memcpy(dest, vpu_fw->data, dl_size); |
| /* download to extended memory if need */ |
| if (extra_fw_size > 0) { |
| @@ -567,21 +795,33 @@ int vpu_load_firmware(struct platform_device *pdev) |
| |
| run->signaled = false; |
| dev_dbg(vpu->dev, "firmware request\n"); |
| - /* Downloading program firmware to device*/ |
| - ret = load_requested_vpu(vpu, vpu_fw, P_FW); |
| - if (ret < 0) { |
| - dev_err(dev, "Failed to request %s, %d\n", VPU_P_FW, ret); |
| - goto OUT_LOAD_FW; |
| + if (vpu->hw->type == VPU_MT8173) { |
| + /* Downloading program firmware to device*/ |
| + ret = load_requested_vpu(vpu, vpu_fw, P_FW); |
| + if (ret < 0) { |
| + dev_err(dev, "Failed to request %s, %d\n", |
| + vpu->hw->fw_p, ret); |
| + goto OUT_LOAD_FW; |
| + } |
| + |
| + /* Downloading data firmware to device */ |
| + ret = load_requested_vpu(vpu, vpu_fw, D_FW); |
| + if (ret < 0) { |
| + dev_err(dev, "Failed to request %s, %d\n", |
| + vpu->hw->fw_d, ret); |
| + goto OUT_LOAD_FW; |
| + } |
| } |
| + vpu->fw_loaded = true; |
| |
| - /* Downloading data firmware to device */ |
| - ret = load_requested_vpu(vpu, vpu_fw, D_FW); |
| - if (ret < 0) { |
| - dev_err(dev, "Failed to request %s, %d\n", VPU_D_FW, ret); |
| +#if VPU_RESERVED_MEM |
| + ret = vpu_reserve_memory_ioremap(); |
| + if (ret) { |
| + dev_err(dev, "vpu_reserve_memory_ioremap failed\n"); |
| goto OUT_LOAD_FW; |
| } |
| +#endif |
| |
| - vpu->fw_loaded = true; |
| /* boot up vpu */ |
| vpu_cfg_writel(vpu, 0x1, VPU_RESET); |
| |
| @@ -631,12 +871,14 @@ static ssize_t vpu_debug_read(struct file *file, char __user *user_buf, |
| int ret; |
| struct device *dev = file->private_data; |
| struct mtk_vpu *vpu = dev_get_drvdata(dev); |
| + struct platform_device *pdev = to_platform_device(dev); |
| |
| ret = vpu_clock_enable(vpu); |
| if (ret) { |
| dev_err(vpu->dev, "[VPU] enable clock failed %d\n", ret); |
| return 0; |
| } |
| + vpu_load_firmware(pdev); |
| |
| /* vpu register status */ |
| running = vpu_running(vpu); |
| @@ -671,7 +913,10 @@ static const struct file_operations vpu_debug_fops = { |
| static void vpu_free_ext_mem(struct mtk_vpu *vpu, u8 fw_type) |
| { |
| struct device *dev = vpu->dev; |
| - size_t fw_ext_size = fw_type ? VPU_EXT_D_SIZE : VPU_EXT_P_SIZE; |
| + size_t fw_ext_size = fw_type ? vpu->hw->ext_d_sz : vpu->hw->ext_p_sz; |
| + |
| + if (!vpu->hw->ext_mem_support) |
| + return; |
| |
| dma_free_coherent(dev, fw_ext_size, vpu->extmem[fw_type].va, |
| vpu->extmem[fw_type].pa); |
| @@ -680,11 +925,14 @@ static void vpu_free_ext_mem(struct mtk_vpu *vpu, u8 fw_type) |
| static int vpu_alloc_ext_mem(struct mtk_vpu *vpu, u32 fw_type) |
| { |
| struct device *dev = vpu->dev; |
| - size_t fw_ext_size = fw_type ? VPU_EXT_D_SIZE : VPU_EXT_P_SIZE; |
| + size_t fw_ext_size = fw_type ? vpu->hw->ext_d_sz : vpu->hw->ext_p_sz; |
| u32 vpu_ext_mem0 = fw_type ? VPU_DMEM_EXT0_ADDR : VPU_PMEM_EXT0_ADDR; |
| u32 vpu_ext_mem1 = fw_type ? VPU_DMEM_EXT1_ADDR : VPU_PMEM_EXT1_ADDR; |
| u32 offset_4gb = vpu->enable_4GB ? 0x40000000 : 0; |
| |
| + if (!vpu->hw->ext_mem_support) |
| + return 0; |
| + |
| vpu->extmem[fw_type].va = dma_alloc_coherent(dev, |
| fw_ext_size, |
| &vpu->extmem[fw_type].pa, |
| @@ -711,9 +959,11 @@ static void vpu_ipi_handler(struct mtk_vpu *vpu) |
| { |
| struct share_obj *rcv_obj = vpu->recv_buf; |
| struct vpu_ipi_desc *ipi_desc = vpu->ipi_desc; |
| + char tmp_data[288]; |
| |
| if (rcv_obj->id < IPI_MAX && ipi_desc[rcv_obj->id].handler) { |
| - ipi_desc[rcv_obj->id].handler(rcv_obj->share_buf, |
| + memcpy_fromio(tmp_data, &rcv_obj->share_buf, rcv_obj->len); |
| + ipi_desc[rcv_obj->id].handler(&tmp_data[0], |
| rcv_obj->len, |
| ipi_desc[rcv_obj->id].priv); |
| if (rcv_obj->id > IPI_VPU_INIT) { |
| @@ -727,15 +977,31 @@ static void vpu_ipi_handler(struct mtk_vpu *vpu) |
| |
| static int vpu_ipi_init(struct mtk_vpu *vpu) |
| { |
| - /* Disable VPU to host interrupt */ |
| - vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST); |
| + if (vpu->hw->type == VPU_MT8173) { |
| + /* clear VPU to host interrupt */ |
| + vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST); |
| + /* get shared buffer */ |
| + vpu->recv_buf = (__force struct share_obj *)(vpu->reg.tcm + |
| + vpu->hw->dtcm_offset); |
| + vpu->send_buf = (__force struct share_obj *)(vpu->reg.tcm + |
| + vpu->hw->dtcm_offset + |
| + vpu->hw->share_obj_sz); |
| + } else if (vpu->hw->type == VPU_MT8183) { |
| + /* clear VPU to host interrupt */ |
| + vpu_cfg_writel(vpu, vpu->hw->ipc_int, VPU_TO_HOST); |
| + /* get shared buffer */ |
| + vpu->send_buf = (__force struct share_obj *) (vpu->reg.tcm + |
| + 0x800 - |
| + vpu->hw->share_obj_sz); |
| + |
| + vpu->recv_buf = (__force struct share_obj *)(vpu->reg.tcm + |
| + 0x800 - |
| + vpu->hw->share_obj_sz - |
| + vpu->hw->share_obj_sz); |
| + } |
| |
| - /* shared buffer initialization */ |
| - vpu->recv_buf = (__force struct share_obj *)(vpu->reg.tcm + |
| - VPU_DTCM_OFFSET); |
| - vpu->send_buf = vpu->recv_buf + 1; |
| - memset(vpu->recv_buf, 0, sizeof(struct share_obj)); |
| - memset(vpu->send_buf, 0, sizeof(struct share_obj)); |
| + memset_io(vpu->recv_buf, 0, vpu->hw->share_obj_sz); |
| + memset_io(vpu->send_buf, 0, vpu->hw->share_obj_sz); |
| |
| return 0; |
| } |
| @@ -757,20 +1023,41 @@ static irqreturn_t vpu_irq_handler(int irq, void *priv) |
| return IRQ_NONE; |
| } |
| vpu_to_host = vpu_cfg_readl(vpu, VPU_TO_HOST); |
| - if (vpu_to_host & VPU_IPC_INT) { |
| + if (vpu_to_host & vpu->hw->ipc_int) { |
| vpu_ipi_handler(vpu); |
| } else { |
| dev_err(vpu->dev, "vpu watchdog timeout! 0x%x", vpu_to_host); |
| queue_work(vpu->wdt.wq, &vpu->wdt.ws); |
| } |
| |
| - /* VPU won't send another interrupt until we set VPU_TO_HOST to 0. */ |
| - vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST); |
| + mb(); |
| + /* |
| + * VPU won't send another interrupt until |
| + * we clear the corresponding bits. |
| + */ |
| + if (vpu->hw->type == VPU_MT8173) |
| + vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST); |
| + else if (vpu->hw->type == VPU_MT8183) |
| + vpu_cfg_writel(vpu, vpu->hw->ipc_int | vpu->hw->wdt_int, |
| + VPU_TO_HOST); |
| clk_disable(vpu->clk); |
| |
| return IRQ_HANDLED; |
| } |
| |
| +static const struct of_device_id mtk_vpu_match[] = { |
| + { |
| + .compatible = "mediatek,mt8173-vpu", |
| + .data = &vpu_mt8173, |
| + }, |
| + { |
| + .compatible = "mediatek,mt8183-vpu", |
| + .data = &vpu_mt8183, |
| + }, |
| + {}, |
| +}; |
| +MODULE_DEVICE_TABLE(of, mtk_vpu_match); |
| + |
| #ifdef CONFIG_DEBUG_FS |
| static struct dentry *vpu_debugfs; |
| #endif |
| @@ -780,6 +1067,8 @@ static int mtk_vpu_probe(struct platform_device *pdev) |
| struct device *dev; |
| struct resource *res; |
| int ret = 0; |
| + const struct of_device_id *of_id = |
| + of_match_device(mtk_vpu_match, &pdev->dev); |
| |
| dev_dbg(&pdev->dev, "initialization\n"); |
| |
| @@ -789,6 +1078,7 @@ static int mtk_vpu_probe(struct platform_device *pdev) |
| return -ENOMEM; |
| |
| vpu->dev = &pdev->dev; |
| + vpu->hw = of_id->data; |
| res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tcm"); |
| vpu->reg.tcm = devm_ioremap_resource(dev, res); |
| if (IS_ERR((__force void *)vpu->reg.tcm)) |
| @@ -854,7 +1144,8 @@ static int mtk_vpu_probe(struct platform_device *pdev) |
| #endif |
| |
| /* Set PTCM to 96K and DTCM to 32K */ |
| - vpu_cfg_writel(vpu, 0x2, VPU_TCM_CFG); |
| + if (vpu->hw->type == VPU_MT8173) |
| + vpu_cfg_writel(vpu, 0x2, VPU_TCM_CFG); |
| |
| vpu->enable_4GB = !!(totalram_pages > (SZ_2G >> PAGE_SHIFT)); |
| dev_info(dev, "4GB mode %u\n", vpu->enable_4GB); |
| @@ -921,14 +1212,6 @@ static int mtk_vpu_probe(struct platform_device *pdev) |
| return ret; |
| } |
| |
| -static const struct of_device_id mtk_vpu_match[] = { |
| - { |
| - .compatible = "mediatek,mt8173-vpu", |
| - }, |
| - {}, |
| -}; |
| -MODULE_DEVICE_TABLE(of, mtk_vpu_match); |
| - |
| static int mtk_vpu_remove(struct platform_device *pdev) |
| { |
| struct mtk_vpu *vpu = platform_get_drvdata(pdev); |
| @@ -953,7 +1236,7 @@ static struct platform_driver mtk_vpu_driver = { |
| .remove = mtk_vpu_remove, |
| .driver = { |
| .name = "mtk_vpu", |
| - .of_match_table = mtk_vpu_match, |
| + .of_match_table = of_match_ptr(mtk_vpu_match), |
| }, |
| }; |
| |
| diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.h b/drivers/media/platform/mtk-vpu/mtk_vpu.h |
| index aec0268be3d01..ca09de70cedae 100644 |
| --- a/drivers/media/platform/mtk-vpu/mtk_vpu.h |
| +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.h |
| @@ -100,6 +100,10 @@ enum rst_id { |
| int vpu_ipi_register(struct platform_device *pdev, enum ipi_id id, |
| ipi_handler_t handler, const char *name, void *priv); |
| |
| +int vpu_ipi_send_sync_async(struct platform_device *pdev, |
| + enum ipi_id id, void *buf, |
| + unsigned int len, unsigned int wait); |
| + |
| /** |
| * vpu_ipi_send - send data from AP to vpu. |
| * |
| @@ -191,4 +195,25 @@ int vpu_load_firmware(struct platform_device *pdev); |
| **/ |
| void *vpu_mapping_dm_addr(struct platform_device *pdev, |
| u32 dtcm_dmem_addr); |
| + |
| +#define VPU_RESERVED_MEM (1) |
| +#if VPU_RESERVED_MEM |
| +/* vpu reserve memory ID definition*/ |
| +enum vpu_reserve_mem_id_t { |
| + ISP_MEM_ID, |
| + NUMS_MEM_ID, |
| +}; |
| + |
| +struct vpu_reserve_mblock { |
| + enum vpu_reserve_mem_id_t num; |
| + u64 start_phys; |
| + u64 start_virt; |
| + u64 size; |
| +}; |
| + |
| +extern phys_addr_t vpu_get_reserve_mem_phys(enum vpu_reserve_mem_id_t id); |
| +extern phys_addr_t vpu_get_reserve_mem_virt(enum vpu_reserve_mem_id_t id); |
| +extern phys_addr_t vpu_get_reserve_mem_size(enum vpu_reserve_mem_id_t id); |
| +#endif |
| + |
| #endif /* _MTK_VPU_H */ |
| diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig |
| index 63389f075f1dc..4a291dabf2ccb 100644 |
| --- a/drivers/memory/Kconfig |
| +++ b/drivers/memory/Kconfig |
| @@ -129,6 +129,15 @@ config JZ4780_NEMC |
| the Ingenic JZ4780. This controller is used to handle external |
| memory devices such as NAND and SRAM. |
| |
| +config MTK_EMI_MBW |
| + bool "Mediatek EMI bandwidth driver" |
| + depends on ARCH_MEDIATEK || COMPILE_TEST |
| + help |
| + This driver is for MTK EMI control. |
| + If unsure, use N. |
| + This is the first time emi upstream. |
| + Only support emi bw statistics. |
| + |
| config MTK_SMI |
| bool |
| depends on ARCH_MEDIATEK || COMPILE_TEST |
| diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile |
| index a01ab3e22f94d..dbd49ba94cab5 100644 |
| --- a/drivers/memory/Makefile |
| +++ b/drivers/memory/Makefile |
| @@ -17,6 +17,7 @@ obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o |
| obj-$(CONFIG_FSL_IFC) += fsl_ifc.o |
| obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o |
| obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o |
| +obj-$(CONFIG_MTK_EMI_MBW) += mtk-emi.o |
| obj-$(CONFIG_MTK_SMI) += mtk-smi.o |
| obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o |
| |
| diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c |
| index fef424efd65d2..41eb0510e080d 100644 |
| --- a/drivers/mfd/cros_ec_dev.c |
| +++ b/drivers/mfd/cros_ec_dev.c |
| @@ -667,6 +667,16 @@ static int ec_device_probe(struct platform_device *pdev) |
| ec_platform->ec_name = CROS_EC_DEV_ISH_NAME; |
| } |
| |
| + /* Check whether this is actually a SCP rather than an EC. */ |
| + if (cros_ec_check_features(ec, EC_FEATURE_SCP)) { |
| + dev_info(dev, "CrOS SCP MCU detected.\n"); |
| + /* |
| + * Help userspace differentiating ECs from SCP, |
| + * regardless of the probing order. |
| + */ |
| + ec_platform->ec_name = CROS_EC_DEV_SCP_NAME; |
| + } |
| + |
| /* |
| * Add the class device |
| * Link to the character device for creating the /dev entry |
| diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile |
| index ce8398e6f2c0e..c8f3fe701ea7b 100644 |
| --- a/drivers/mmc/host/Makefile |
| +++ b/drivers/mmc/host/Makefile |
| @@ -23,7 +23,7 @@ obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o |
| obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o |
| obj-$(CONFIG_MMC_WBSD) += wbsd.o |
| obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
| -obj-$(CONFIG_MMC_MTK) += mtk-sd.o |
| +obj-$(CONFIG_MMC_MTK) += mtk-sd.o mtk-sdio-proc.o |
| obj-$(CONFIG_MMC_OMAP) += omap.o |
| obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o |
| obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o |
| diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c |
| index 0de3749c9311c..8aaa5d4059871 100644 |
| --- a/drivers/mmc/host/mtk-sd.c |
| +++ b/drivers/mmc/host/mtk-sd.c |
| @@ -39,6 +39,8 @@ |
| #include <linux/mmc/sdio.h> |
| #include <linux/mmc/slot-gpio.h> |
| |
| +#include "mtk-sdio-proc.h" |
| + |
| #define MAX_BD_NUM 1024 |
| |
| /*--------------------------------------------------------------------------*/ |
| @@ -2234,6 +2236,9 @@ static int msdc_drv_probe(struct platform_device *pdev) |
| if (ret) |
| goto end; |
| |
| + if (host->mmc->caps & MMC_CAP_SDIO_IRQ) |
| + sdio_proc_init(host->mmc); |
| + |
| return 0; |
| end: |
| pm_runtime_disable(host->dev); |
| diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c |
| index 6a4c7b4887827..80a38ad0db15a 100644 |
| --- a/drivers/net/wireless/ath/ath10k/core.c |
| +++ b/drivers/net/wireless/ath/ath10k/core.c |
| @@ -167,6 +167,32 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { |
| .hw_filter_reset_required = true, |
| .fw_diag_ce_download = false, |
| }, |
| + { |
| + .id = QCA6174_HW_3_2_VERSION, |
| + .dev_id = QCA6174_3_2_DEVICE_ID, |
| + .bus = ATH10K_BUS_SDIO, |
| + .name = "qca6174 hw3.2 sdio", |
| + .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, |
| + .uart_pin = 19, |
| + .otp_exe_param = 0, |
| + .channel_counters_freq_hz = 88000, |
| + .max_probe_resp_desc_thres = 0, |
| + .cal_data_len = 0, |
| + .fw = { |
| + .dir = QCA6174_HW_3_0_FW_DIR, |
| + .board = QCA6174_HW_3_0_BOARD_DATA_FILE, |
| + .board_size = QCA6174_BOARD_DATA_SZ, |
| + .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, |
| + }, |
| + .hw_ops = &qca6174_ops, |
| + .hw_clk = qca6174_clk, |
| + .target_cpu_freq = 176000000, |
| + .decap_align_bytes = 4, |
| + .num_peers = 10, |
| + .ast_skid_limit = 0x10, |
| + .num_wds_entries = 0x20, |
| + .uart_print_check = true, |
| + }, |
| { |
| .id = QCA6174_HW_2_1_VERSION, |
| .dev_id = QCA6164_2_1_DEVICE_ID, |
| @@ -1925,8 +1951,16 @@ static int ath10k_init_uart(struct ath10k *ar) |
| return ret; |
| } |
| |
| - if (!uart_print) |
| + if (!uart_print && ar->hw_params.uart_print_check) { |
| + ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, |
| + ar->hw_params.uart_pin); |
| + if (ret) { |
| + ath10k_warn(ar, "failed to disable UART pin: %d", ret); |
| + return ret; |
| + } |
| + |
| return 0; |
| + } |
| |
| ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin); |
| if (ret) { |
| diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c |
| index 9373a63b86461..8c86359354afd 100644 |
| --- a/drivers/net/wireless/ath/ath10k/htt_rx.c |
| +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c |
| @@ -2043,7 +2043,9 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, |
| * Note that with only one concurrent reader and one concurrent |
| * writer, you don't need extra locking to use these macro. |
| */ |
| - if (!kfifo_put(&htt->txdone_fifo, tx_done)) { |
| + if (ar->hif.bus == ATH10K_BUS_SDIO) { |
| + ath10k_txrx_tx_unref(htt, &tx_done); |
| + } else if (!kfifo_put(&htt->txdone_fifo, tx_done)) { |
| ath10k_warn(ar, "txdone fifo overrun, msdu_id %d status %d\n", |
| tx_done.msdu_id, tx_done.status); |
| ath10k_txrx_tx_unref(htt, &tx_done); |
| diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c |
| index f54ef2c370441..d099681da42b6 100644 |
| --- a/drivers/net/wireless/ath/ath10k/htt_tx.c |
| +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c |
| @@ -554,7 +554,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) |
| |
| void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
| { |
| - dev_kfree_skb_any(skb); |
| + if (!(ar->hif.bus == ATH10K_BUS_SDIO)) |
| + dev_kfree_skb_any(skb); |
| } |
| |
| void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb) |
| @@ -1208,6 +1209,7 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm |
| u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth); |
| u8 flags0 = 0; |
| u16 flags1 = 0; |
| + u16 msdu_id = 0; |
| |
| data_len = msdu->len; |
| |
| @@ -1255,6 +1257,16 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm |
| } |
| } |
| |
| + if (ar->hif.bus == ATH10K_BUS_SDIO) { |
| + flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED; |
| + res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); |
| + if (res < 0) { |
| + ath10k_err(ar, "msdu_id allocation failed %d\n", res); |
| + goto out; |
| + } |
| + msdu_id = res; |
| + } |
| + |
| skb_push(msdu, sizeof(*cmd_hdr)); |
| skb_push(msdu, sizeof(*tx_desc)); |
| cmd_hdr = (struct htt_cmd_hdr *)msdu->data; |
| @@ -1264,7 +1276,7 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm |
| tx_desc->flags0 = flags0; |
| tx_desc->flags1 = __cpu_to_le16(flags1); |
| tx_desc->len = __cpu_to_le16(data_len); |
| - tx_desc->id = 0; |
| + tx_desc->id = __cpu_to_le16(msdu_id); |
| tx_desc->frags_paddr = 0; /* always zero */ |
| /* Initialize peer_id to INVALID_PEER because this is NOT |
| * Reinjection path |
| diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h |
| index 70682dff865f8..d863b57effdbe 100644 |
| --- a/drivers/net/wireless/ath/ath10k/hw.h |
| +++ b/drivers/net/wireless/ath/ath10k/hw.h |
| @@ -35,6 +35,7 @@ enum ath10k_bus { |
| #define QCA988X_2_0_DEVICE_ID (0x003c) |
| #define QCA6164_2_1_DEVICE_ID (0x0041) |
| #define QCA6174_2_1_DEVICE_ID (0x003e) |
| +#define QCA6174_3_2_DEVICE_ID (0x0042) |
| #define QCA99X0_2_0_DEVICE_ID (0x0040) |
| #define QCA9888_2_0_DEVICE_ID (0x0056) |
| #define QCA9984_1_0_DEVICE_ID (0x0046) |
| @@ -600,6 +601,9 @@ struct ath10k_hw_params { |
| /* target supporting shadow register for ce write */ |
| bool shadow_reg_support; |
| |
| + /* need to set uart pin if disable uart print */ |
| + bool uart_print_check; |
| + |
| /* target supporting retention restore on ddr */ |
| bool rri_on_ddr; |
| |
| diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c |
| index 9f631120a9be0..1ea6d2dc2f290 100644 |
| --- a/drivers/net/wireless/ath/ath10k/sdio.c |
| +++ b/drivers/net/wireless/ath/ath10k/sdio.c |
| @@ -2083,8 +2083,6 @@ static void ath10k_sdio_remove(struct sdio_func *func) |
| "sdio removed func %d vendor 0x%x device 0x%x\n", |
| func->num, func->vendor, func->device); |
| |
| - (void)ath10k_sdio_hif_disable_intrs(ar); |
| - cancel_work_sync(&ar_sdio->wr_async_work); |
| ath10k_core_unregister(ar); |
| ath10k_core_destroy(ar); |
| } |
| diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c |
| index f13d88906b5a7..6a87bd89418cb 100644 |
| --- a/drivers/net/wireless/ath/ath10k/txrx.c |
| +++ b/drivers/net/wireless/ath/ath10k/txrx.c |
| @@ -91,7 +91,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, |
| |
| ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); |
| ath10k_htt_tx_dec_pending(htt); |
| - if (htt->num_pending_tx == 0) |
| + if (ar->dev_type != ATH10K_DEV_TYPE_HL && htt->num_pending_tx == 0) |
| wake_up(&htt->empty_tx_wq); |
| spin_unlock_bh(&htt->tx_lock); |
| |
| diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c |
| index 893940d45f0d0..27079acc3e1d9 100644 |
| --- a/drivers/pwm/pwm-mtk-disp.c |
| +++ b/drivers/pwm/pwm-mtk-disp.c |
| @@ -106,13 +106,13 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, |
| high_width = div64_u64(rate * duty_ns, div); |
| value = period | (high_width << PWM_HIGH_WIDTH_SHIFT); |
| |
| - err = clk_enable(mdp->clk_main); |
| + err = clk_prepare_enable(mdp->clk_main); |
| if (err < 0) |
| return err; |
| |
| - err = clk_enable(mdp->clk_mm); |
| + err = clk_prepare_enable(mdp->clk_mm); |
| if (err < 0) { |
| - clk_disable(mdp->clk_main); |
| + clk_disable_unprepare(mdp->clk_main); |
| return err; |
| } |
| |
| @@ -132,8 +132,8 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, |
| 0x0); |
| } |
| |
| - clk_disable(mdp->clk_mm); |
| - clk_disable(mdp->clk_main); |
| + clk_disable_unprepare(mdp->clk_mm); |
| + clk_disable_unprepare(mdp->clk_main); |
| |
| return 0; |
| } |
| @@ -143,13 +143,13 @@ static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
| struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); |
| int err; |
| |
| - err = clk_enable(mdp->clk_main); |
| + err = clk_prepare_enable(mdp->clk_main); |
| if (err < 0) |
| return err; |
| |
| - err = clk_enable(mdp->clk_mm); |
| + err = clk_prepare_enable(mdp->clk_mm); |
| if (err < 0) { |
| - clk_disable(mdp->clk_main); |
| + clk_disable_unprepare(mdp->clk_main); |
| return err; |
| } |
| |
| @@ -166,8 +166,8 @@ static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) |
| mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask, |
| 0x0); |
| |
| - clk_disable(mdp->clk_mm); |
| - clk_disable(mdp->clk_main); |
| + clk_disable_unprepare(mdp->clk_mm); |
| + clk_disable_unprepare(mdp->clk_main); |
| } |
| |
| static const struct pwm_ops mtk_disp_pwm_ops = { |
| @@ -202,14 +202,6 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) |
| if (IS_ERR(mdp->clk_mm)) |
| return PTR_ERR(mdp->clk_mm); |
| |
| - ret = clk_prepare(mdp->clk_main); |
| - if (ret < 0) |
| - return ret; |
| - |
| - ret = clk_prepare(mdp->clk_mm); |
| - if (ret < 0) |
| - goto disable_clk_main; |
| - |
| mdp->chip.dev = &pdev->dev; |
| mdp->chip.ops = &mtk_disp_pwm_ops; |
| mdp->chip.base = -1; |
| @@ -218,7 +210,7 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) |
| ret = pwmchip_add(&mdp->chip); |
| if (ret < 0) { |
| dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); |
| - goto disable_clk_mm; |
| + return ret; |
| } |
| |
| platform_set_drvdata(pdev, mdp); |
| @@ -237,24 +229,13 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev) |
| } |
| |
| return 0; |
| - |
| -disable_clk_mm: |
| - clk_unprepare(mdp->clk_mm); |
| -disable_clk_main: |
| - clk_unprepare(mdp->clk_main); |
| - return ret; |
| } |
| |
| static int mtk_disp_pwm_remove(struct platform_device *pdev) |
| { |
| struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev); |
| - int ret; |
| - |
| - ret = pwmchip_remove(&mdp->chip); |
| - clk_unprepare(mdp->clk_mm); |
| - clk_unprepare(mdp->clk_main); |
| |
| - return ret; |
| + return pwmchip_remove(&mdp->chip); |
| } |
| |
| static const struct mtk_pwm_data mt2701_pwm_data = { |
| @@ -277,10 +258,21 @@ static const struct mtk_pwm_data mt8173_pwm_data = { |
| .commit_mask = 0x1, |
| }; |
| |
| +static const struct mtk_pwm_data mt8183_pwm_data = { |
| + .enable_mask = BIT(0), |
| + .con0 = 0x18, |
| + .con0_sel = 0x0, |
| + .con1 = 0x1c, |
| + .has_commit = false, |
| + .bls_debug = 0x80, |
| + .bls_debug_mask = 0x3, |
| +}; |
| + |
| static const struct of_device_id mtk_disp_pwm_of_match[] = { |
| { .compatible = "mediatek,mt2701-disp-pwm", .data = &mt2701_pwm_data}, |
| { .compatible = "mediatek,mt6595-disp-pwm", .data = &mt8173_pwm_data}, |
| { .compatible = "mediatek,mt8173-disp-pwm", .data = &mt8173_pwm_data}, |
| + { .compatible = "mediatek,mt8183-disp-pwm", .data = &mt8183_pwm_data}, |
| { } |
| }; |
| MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match); |
| diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig |
| index f0abd26080447..01182936f4fa8 100644 |
| --- a/drivers/remoteproc/Kconfig |
| +++ b/drivers/remoteproc/Kconfig |
| @@ -22,6 +22,16 @@ config IMX_REMOTEPROC |
| |
| It's safe to say N here. |
| |
| +config MTK_SCP |
| + tristate "Mediatek SCP support" |
| + depends on ARCH_MEDIATEK |
| + select RPMSG_MTK_SCP |
| + help |
| + Say y here to support Mediatek's System Companion Processor (SCP) via |
| + the remote processor framework. |
| + |
| + It's safe to say N here. |
| + |
| config OMAP_REMOTEPROC |
| tristate "OMAP remoteproc support" |
| depends on ARCH_OMAP4 || SOC_OMAP5 |
| diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile |
| index ce5d061e92be5..16b3e5e7a81c8 100644 |
| --- a/drivers/remoteproc/Makefile |
| +++ b/drivers/remoteproc/Makefile |
| @@ -10,6 +10,7 @@ remoteproc-y += remoteproc_sysfs.o |
| remoteproc-y += remoteproc_virtio.o |
| remoteproc-y += remoteproc_elf_loader.o |
| obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o |
| +obj-$(CONFIG_MTK_SCP) += mtk_scp.o mtk_scp_ipi.o |
| obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o |
| obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o |
| obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o |
| diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig |
| index d0322b41eca54..85e3cc075cb47 100644 |
| --- a/drivers/rpmsg/Kconfig |
| +++ b/drivers/rpmsg/Kconfig |
| @@ -15,6 +15,15 @@ config RPMSG_CHAR |
| in /dev. They make it possible for user-space programs to send and |
| receive rpmsg packets. |
| |
| +config RPMSG_MTK_SCP |
| + tristate "MediaTek SCP" |
| + depends on MTK_SCP |
| + select RPMSG |
| + help |
| + Say y here to enable support providing communication channels to |
| + remote processors in MediaTek platforms. |
| + This use IPI and IPC to communicate with remote processors. |
| + |
| config RPMSG_QCOM_GLINK_NATIVE |
| tristate |
| select RPMSG |
| diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile |
| index 9aa859502d275..ae92a7fb08f62 100644 |
| --- a/drivers/rpmsg/Makefile |
| +++ b/drivers/rpmsg/Makefile |
| @@ -1,6 +1,7 @@ |
| # SPDX-License-Identifier: GPL-2.0 |
| obj-$(CONFIG_RPMSG) += rpmsg_core.o |
| obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o |
| +obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o |
| obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o |
| obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o |
| obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o |
| diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c |
| index ff9fef5a032b3..317ec441ad609 100644 |
| --- a/drivers/soc/mediatek/mtk-cmdq-helper.c |
| +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c |
| @@ -9,17 +9,109 @@ |
| #include <linux/mailbox_controller.h> |
| #include <linux/soc/mediatek/mtk-cmdq.h> |
| |
| -#define CMDQ_ARG_A_WRITE_MASK 0xffff |
| +#define CMDQ_GET_ARG_B(arg) (((arg) & GENMASK(31, 16)) >> 16) |
| +#define CMDQ_GET_ARG_C(arg) ((arg) & GENMASK(15, 0)) |
| #define CMDQ_WRITE_ENABLE_MASK BIT(0) |
| #define CMDQ_EOC_IRQ_EN BIT(0) |
| #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ |
| << 32 | CMDQ_EOC_IRQ_EN) |
| +#define CMDQ_IMMEDIATE_VALUE 0 |
| +#define CMDQ_REG_TYPE 1 |
| + |
| +struct cmdq_instruction { |
| + s16 arg_c:16; |
| + s16 arg_b:16; |
| + s16 arg_a:16; |
| + u8 s_op:5; |
| + u8 arg_c_type:1; |
| + u8 arg_b_type:1; |
| + u8 arg_a_type:1; |
| + u8 op:8; |
| +}; |
| + |
| +static void cmdq_pkt_instr_encoder(struct cmdq_pkt *pkt, s16 arg_c, s16 arg_b, |
| + s16 arg_a, u8 s_op, u8 arg_c_type, |
| + u8 arg_b_type, u8 arg_a_type, u8 op) |
| +{ |
| + struct cmdq_instruction *cmdq_inst; |
| + |
| + cmdq_inst = pkt->va_base + pkt->cmd_buf_size; |
| + cmdq_inst->op = op; |
| + cmdq_inst->arg_a_type = arg_a_type; |
| + cmdq_inst->arg_b_type = arg_b_type; |
| + cmdq_inst->arg_c_type = arg_c_type; |
| + cmdq_inst->s_op = s_op; |
| + cmdq_inst->arg_a = arg_a; |
| + cmdq_inst->arg_b = arg_b; |
| + cmdq_inst->arg_c = arg_c; |
| + pkt->cmd_buf_size += CMDQ_INST_SIZE; |
| +} |
| + |
| +struct cmdq_subsys *cmdq_dev_get_subsys(struct device *dev, int idx) |
| +{ |
| + struct cmdq_subsys *subsys; |
| + struct of_phandle_args spec; |
| + |
| + subsys = devm_kzalloc(dev, sizeof(*subsys), GFP_KERNEL); |
| + if (!subsys) |
| + return NULL; |
| + |
| + if (of_parse_phandle_with_args(dev->of_node, "mediatek,gce-client-reg", |
| + "#subsys-cells", idx, &spec)) { |
| + dev_err(dev, "can't parse gce-client-reg property"); |
| + |
| + return(struct cmdq_subsys *)-ENODEV; |
| + } |
| + |
| + subsys->id = spec.args[0]; |
| + subsys->offset = spec.args[1]; |
| + subsys->size = spec.args[2]; |
| + of_node_put(spec.np); |
| + |
| + return subsys; |
| +} |
| +EXPORT_SYMBOL(cmdq_dev_get_subsys); |
| + |
| +s32 cmdq_dev_get_event(struct device *dev, const char *name) |
| +{ |
| + s32 index = 0; |
| + struct of_phandle_args spec; |
| + s32 result; |
| + |
| + if (!dev) |
| + return -EINVAL; |
| + |
| + index = of_property_match_string(dev->of_node, |
| + "mediatek,gce-event-names", name); |
| + if (index < 0) { |
| + dev_err(dev, "no gce-event-names property or no such event:%s", |
| + name); |
| + |
| + return index; |
| + } |
| + |
| + if (of_parse_phandle_with_args(dev->of_node, "mediatek,gce-events", |
| + "#event-cells", index, &spec)) { |
| + dev_err(dev, "can't parse gce-events property"); |
| + |
| + return -ENODEV; |
| + } |
| + |
| + result = spec.args[0]; |
| + of_node_put(spec.np); |
| + |
| + return result; |
| +} |
| +EXPORT_SYMBOL(cmdq_dev_get_event); |
| |
| static void cmdq_client_timeout(struct timer_list *t) |
| { |
| struct cmdq_client *client = from_timer(client, t, timer); |
| |
| dev_err(client->client.dev, "cmdq timeout!\n"); |
| +#ifdef CONFIG_MTK_CMDQ_DEBUG |
| + mbox_free_channel(client->chan); |
| +#endif |
| } |
| |
| struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) |
| @@ -110,10 +202,11 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt) |
| } |
| EXPORT_SYMBOL(cmdq_pkt_destroy); |
| |
| -static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, |
| - u32 arg_a, u32 arg_b) |
| +static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, s16 arg_c, s16 arg_b, |
| + s16 arg_a, u8 s_op, u8 arg_c_type, |
| + u8 arg_b_type, u8 arg_a_type, |
| + enum cmdq_code code) |
| { |
| - u64 *cmd_ptr; |
| |
| if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { |
| /* |
| @@ -129,77 +222,129 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, |
| __func__, (u32)pkt->buf_size); |
| return -ENOMEM; |
| } |
| - cmd_ptr = pkt->va_base + pkt->cmd_buf_size; |
| - (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b; |
| - pkt->cmd_buf_size += CMDQ_INST_SIZE; |
| + cmdq_pkt_instr_encoder(pkt, arg_c, arg_b, arg_a, s_op, arg_c_type, |
| + arg_b_type, arg_a_type, code); |
| |
| return 0; |
| } |
| |
| -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset) |
| +int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) |
| { |
| - u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | |
| - (subsys << CMDQ_SUBSYS_SHIFT); |
| - |
| - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value); |
| + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(value), |
| + CMDQ_GET_ARG_B(value), offset, subsys, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, CMDQ_CODE_WRITE); |
| } |
| EXPORT_SYMBOL(cmdq_pkt_write); |
| |
| -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, |
| - u32 subsys, u32 offset, u32 mask) |
| +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, |
| + u32 value, u32 mask) |
| { |
| u32 offset_mask = offset; |
| int err = 0; |
| |
| if (mask != 0xffffffff) { |
| - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask); |
| + err = cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(~mask), |
| + CMDQ_GET_ARG_B(~mask), |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_CODE_MASK); |
| offset_mask |= CMDQ_WRITE_ENABLE_MASK; |
| } |
| - err |= cmdq_pkt_write(pkt, value, subsys, offset_mask); |
| + err |= cmdq_pkt_write(pkt, subsys, offset_mask, value); |
| |
| return err; |
| } |
| EXPORT_SYMBOL(cmdq_pkt_write_mask); |
| |
| -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event) |
| +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) |
| { |
| - u32 arg_b; |
| - |
| if (event >= CMDQ_MAX_EVENT) |
| return -EINVAL; |
| |
| - /* |
| - * WFE arg_b |
| - * bit 0-11: wait value |
| - * bit 15: 1 - wait, 0 - no wait |
| - * bit 16-27: update value |
| - * bit 31: 1 - update, 0 - no update |
| - */ |
| - arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE; |
| - |
| - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, arg_b); |
| + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(CMDQ_WFE_OPTION), |
| + CMDQ_GET_ARG_B(CMDQ_WFE_OPTION), event, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_CODE_WFE); |
| } |
| EXPORT_SYMBOL(cmdq_pkt_wfe); |
| |
| -int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event) |
| +int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) |
| { |
| if (event >= CMDQ_MAX_EVENT) |
| return -EINVAL; |
| |
| - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, |
| - CMDQ_WFE_UPDATE); |
| + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(CMDQ_WFE_UPDATE), |
| + CMDQ_GET_ARG_B(CMDQ_WFE_UPDATE), event, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_CODE_WFE); |
| } |
| EXPORT_SYMBOL(cmdq_pkt_clear_event); |
| |
| +int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, |
| + u16 offset, u32 value, u32 mask) |
| +{ |
| + int err; |
| + |
| + if (mask != 0xffffffff) { |
| + err = cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(~mask), |
| + CMDQ_GET_ARG_B(~mask), |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_CODE_MASK); |
| + |
| + if (err != 0) |
| + return err; |
| + } |
| + offset = offset | 0x1; |
| + |
| + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(value), |
| + CMDQ_GET_ARG_B(value), |
| + offset, subsys, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_CODE_POLL); |
| +} |
| +EXPORT_SYMBOL(cmdq_pkt_poll); |
| + |
| static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) |
| { |
| int err; |
| |
| /* insert EOC and generate IRQ for each command iteration */ |
| - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN); |
| - |
| + err = cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(CMDQ_EOC_IRQ_EN), |
| + CMDQ_GET_ARG_B(CMDQ_EOC_IRQ_EN), |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_CODE_EOC); |
| + if (err < 0) |
| + return err; |
| /* JUMP to end */ |
| - err |= cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS); |
| + err = cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(CMDQ_JUMP_PASS), |
| + CMDQ_GET_ARG_B(CMDQ_JUMP_PASS), |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_IMMEDIATE_VALUE, |
| + CMDQ_CODE_JUMP); |
| |
| return err; |
| } |
| diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c |
| index c3f933d10295e..2c75937029543 100644 |
| --- a/drivers/tty/serial/8250/8250_mtk.c |
| +++ b/drivers/tty/serial/8250/8250_mtk.c |
| @@ -1,11 +1,23 @@ |
| -// SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * Mediatek 8250 driver. |
| * |
| * Copyright (c) 2014 MundoReader S.L. |
| * Author: Matthias Brugger <matthias.bgg@gmail.com> |
| + * |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License as published by |
| + * the Free Software Foundation; either version 2 of the License, or |
| + * (at your option) any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| */ |
| + |
| #include <linux/clk.h> |
| +#include <linux/console.h> |
| +#include <linux/dma-mapping.h> |
| #include <linux/io.h> |
| #include <linux/module.h> |
| #include <linux/of_irq.h> |
| @@ -14,20 +26,185 @@ |
| #include <linux/pm_runtime.h> |
| #include <linux/serial_8250.h> |
| #include <linux/serial_reg.h> |
| +#include <linux/tty.h> |
| +#include <linux/tty_flip.h> |
| +#include <linux/delay.h> |
| |
| #include "8250.h" |
| |
| -#define UART_MTK_HIGHS 0x09 /* Highspeed register */ |
| -#define UART_MTK_SAMPLE_COUNT 0x0a /* Sample count register */ |
| -#define UART_MTK_SAMPLE_POINT 0x0b /* Sample point register */ |
| +#define MTK_UART_HIGHS 0x09 /* Highspeed register */ |
| +#define MTK_UART_SAMPLE_COUNT 0x0a /* Sample count register */ |
| +#define MTK_UART_SAMPLE_POINT 0x0b /* Sample point register */ |
| +#define MTK_UART_AUTOBAUD 0x0c /* Auto Baud Monitor */ |
| #define MTK_UART_RATE_FIX 0x0d /* UART Rate Fix Register */ |
| +#define MTK_UART_GUARD 0x0f /* Guard time added register */ |
| +#define MTK_UART_ESCAPE_DAT 0x10 /* Escape Character register */ |
| +#define MTK_UART_ESCAPE_EN 0x11 /* Escape Enable register */ |
| +#define MTK_UART_SLEEP_EN 0x12 /* Sleep Enable register */ |
| +#define MTK_UART_DMA_EN 0x13 /* DMA Enable register */ |
| +#define MTK_UART_RXTRI_AD 0x14 /* RX Trigger address */ |
| +#define MTK_UART_FRACDIV_L 0x15 /* Fractional divider LSB address */ |
| +#define MTK_UART_FRACDIV_M 0x16 /* Fractional divider MSB address */ |
| +#define MTK_UART_FCR_RD 0x17 /* Fifo control register */ |
| +#define MTK_UART_DEBUG0 0x18 |
| +#define MTK_UART_RX_SEL 0x24 /* Uart rx pin sel */ |
| +#define MTK_UART_SLEEP_REQ 0x2d /* Sleep request register */ |
| +#define MTK_UART_SLEEP_ACK 0x2e /* Sleep ack register */ |
| + |
| +#define MTK_UART_IER_XOFFI 0x20 /* Enable XOFF character interrupt */ |
| +#define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */ |
| +#define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */ |
| + |
| +#define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */ |
| +#define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */ |
| +#define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */ |
| +#define MTK_UART_EFR_NO_SW_FC 0x0 /* no sw flow control */ |
| +#define MTK_UART_EFR_XON1_XOFF1 0xa /* XON1/XOFF1 as sw flow control */ |
| +#define MTK_UART_EFR_XON2_XOFF2 0x5 /* XON2/XOFF2 as sw flow control */ |
| +#define MTK_UART_EFR_SW_FC_MASK 0xf /* Enable CTS Modem status interrupt */ |
| +#define MTK_UART_EFR_HW_FC (MTK_UART_EFR_RTS | MTK_UART_EFR_CTS) |
| + |
| +#define MTK_UART_DMA_EN_TX 0x2 |
| +#define MTK_UART_DMA_EN_RX 0x5 |
| + |
| +#define MTK_UART_SEND_SLEEP_REQ 0x1 /* Request uart to sleep */ |
| +#define MTK_UART_SLEEP_ACK_IDLE 0x1 /* uart in idle state */ |
| +#define MTK_UART_WAIT_ACK_TIMES 50 |
| + |
| +#define MTK_UART_ESCAPE_CHAR 0x77 /* Escape char added under sw fc */ |
| + |
| +#define MTK_UART_TX_SIZE UART_XMIT_SIZE |
| +#define MTK_UART_RX_SIZE 0x8000 |
| +#define MTK_UART_TX_TRIGGER 1 |
| +#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE |
| + |
| + |
| +struct mtk8250_reg { |
| + unsigned int ier; |
| + unsigned int mcr; |
| + unsigned int msr; |
| + unsigned int scr; |
| + unsigned int dll; |
| + unsigned int dlm; |
| + unsigned int lcr; |
| + unsigned int efr; |
| + unsigned int xon1; |
| + unsigned int xon2; |
| + unsigned int xoff1; |
| + unsigned int xoff2; |
| + unsigned int highspeed; |
| + unsigned int sample_count; |
| + unsigned int sample_point; |
| + unsigned int guard; |
| + unsigned int escape_dat; |
| + unsigned int escape_en; |
| + unsigned int sleep_en; |
| + unsigned int dma_en; |
| + unsigned int rxtri_ad; |
| + unsigned int fracdiv_l; |
| + unsigned int fracdiv_m; |
| + unsigned int fcr_rd; |
| + unsigned int rx_sel; |
| +}; |
| |
| struct mtk8250_data { |
| int line; |
| + unsigned int rxpos; |
| + unsigned int clk_count; |
| struct clk *uart_clk; |
| struct clk *bus_clk; |
| + struct mtk8250_reg reg; |
| + struct uart_8250_dma *dma; |
| +}; |
| + |
| +/* flow control mode */ |
| +enum { |
| + MTK_UART_FC_NONE, /*NO flow control */ |
| + MTK_UART_FC_SW, /*MTK SW Flow Control, differs from Linux Flow Control */ |
| + MTK_UART_FC_HW, /*HW Flow Control */ |
| }; |
| |
| +static int mtk8250_startup(struct uart_port *port) |
| +{ |
| + memset(&port->icount, 0, sizeof(port->icount)); |
| + |
| + return serial8250_do_startup(port); |
| +} |
| + |
| +static void mtk8250_shutdown(struct uart_port *port) |
| +{ |
| + return serial8250_do_shutdown(port); |
| +} |
| + |
| +static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask) |
| +{ |
| + serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask)); |
| +} |
| + |
| +static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask) |
| +{ |
| + serial_out(up, UART_IER, serial_in(up, UART_IER) | mask); |
| +} |
| + |
| +static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode) |
| +{ |
| + struct uart_port *port = &up->port; |
| + int lcr = serial_in(up, UART_LCR); |
| + |
| + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| + serial_out(up, UART_EFR, UART_EFR_ECB); |
| + serial_out(up, UART_LCR, lcr); |
| + lcr = serial_in(up, UART_LCR); |
| + |
| + switch (mode) { |
| + case MTK_UART_FC_NONE: |
| + serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); |
| + serial_out(up, MTK_UART_ESCAPE_EN, 0x00); |
| + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| + serial_out(up, UART_EFR, serial_in(up, UART_EFR) & |
| + (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))); |
| + serial_out(up, UART_LCR, lcr); |
| + mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI | |
| + MTK_UART_IER_RTSI | MTK_UART_IER_CTSI); |
| + break; |
| + |
| + case MTK_UART_FC_HW: |
| + serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); |
| + serial_out(up, MTK_UART_ESCAPE_EN, 0x00); |
| + serial_out(up, UART_MCR, UART_MCR_RTS); |
| + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| + |
| + /*enable hw flow control*/ |
| + serial_out(up, UART_EFR, MTK_UART_EFR_HW_FC | |
| + (serial_in(up, UART_EFR) & |
| + (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); |
| + |
| + serial_out(up, UART_LCR, lcr); |
| + mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI); |
| + mtk8250_enable_intrs(up, MTK_UART_IER_CTSI | MTK_UART_IER_RTSI); |
| + break; |
| + |
| + case MTK_UART_FC_SW: /*MTK software flow control */ |
| + serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); |
| + serial_out(up, MTK_UART_ESCAPE_EN, 0x01); |
| + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); |
| + |
| + /*enable sw flow control */ |
| + serial_out(up, UART_EFR, MTK_UART_EFR_XON1_XOFF1 | |
| + (serial_in(up, UART_EFR) & |
| + (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); |
| + |
| + serial_out(up, UART_XON1, START_CHAR(port->state->port.tty)); |
| + serial_out(up, UART_XOFF1, STOP_CHAR(port->state->port.tty)); |
| + serial_out(up, UART_LCR, lcr); |
| + mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI); |
| + mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI); |
| + break; |
| + default: |
| + break; |
| + } |
| +} |
| + |
| static void |
| mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| struct ktermios *old) |
| @@ -35,11 +212,15 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| struct uart_8250_port *up = up_to_u8250p(port); |
| unsigned long flags; |
| unsigned int baud, quot; |
| + unsigned int fraction; |
| + unsigned short fraction_L_mapping[] = { 0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF }; |
| + unsigned short fraction_M_mapping[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3 }; |
| + int mode; |
| |
| serial8250_do_set_termios(port, termios, old); |
| |
| /* |
| - * Mediatek UARTs use an extra highspeed register (UART_MTK_HIGHS) |
| + * Mediatek UARTs use an extra highspeed register (MTK_UART_HIGHS) |
| * |
| * We need to recalcualte the quot register, as the claculation depends |
| * on the vaule in the highspeed register. |
| @@ -52,21 +233,14 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| * registers to their default values. |
| */ |
| baud = uart_get_baud_rate(port, termios, old, |
| - port->uartclk / 16 / UART_DIV_MAX, |
| + port->uartclk / 16 / 0xffff, |
| port->uartclk); |
| |
| - if (baud <= 115200) { |
| - serial_port_out(port, UART_MTK_HIGHS, 0x0); |
| + if (baud < 115200) { |
| + serial_port_out(port, MTK_UART_HIGHS, 0x0); |
| quot = uart_get_divisor(port, baud); |
| - } else if (baud <= 576000) { |
| - serial_port_out(port, UART_MTK_HIGHS, 0x2); |
| - |
| - /* Set to next lower baudrate supported */ |
| - if ((baud == 500000) || (baud == 576000)) |
| - baud = 460800; |
| - quot = DIV_ROUND_UP(port->uartclk, 4 * baud); |
| } else { |
| - serial_port_out(port, UART_MTK_HIGHS, 0x3); |
| + serial_port_out(port, MTK_UART_HIGHS, 0x3); |
| quot = DIV_ROUND_UP(port->uartclk, 256 * baud); |
| } |
| |
| @@ -83,18 +257,38 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| /* reset DLAB */ |
| serial_port_out(port, UART_LCR, up->lcr); |
| |
| - if (baud > 460800) { |
| + if (baud >= 115200) { |
| unsigned int tmp; |
| |
| - tmp = DIV_ROUND_CLOSEST(port->uartclk, quot * baud); |
| - serial_port_out(port, UART_MTK_SAMPLE_COUNT, tmp - 1); |
| - serial_port_out(port, UART_MTK_SAMPLE_POINT, |
| - (tmp - 2) >> 1); |
| + tmp = (port->uartclk / (baud * quot)) - 1; |
| + serial_port_out(port, MTK_UART_SAMPLE_COUNT, tmp); |
| + serial_port_out(port, MTK_UART_SAMPLE_POINT, |
| + (tmp >> 1) - 1); |
| + |
| + /*count fraction to set fractoin register */ |
| + fraction = ((port->uartclk * 100) / baud / quot) % 100; |
| + fraction = DIV_ROUND_CLOSEST(fraction, 10); |
| + serial_port_out(port, MTK_UART_FRACDIV_L, fraction_L_mapping[fraction]); |
| + serial_port_out(port, MTK_UART_FRACDIV_M, fraction_M_mapping[fraction]); |
| } else { |
| - serial_port_out(port, UART_MTK_SAMPLE_COUNT, 0x00); |
| - serial_port_out(port, UART_MTK_SAMPLE_POINT, 0xff); |
| + serial_port_out(port, MTK_UART_SAMPLE_COUNT, 0x00); |
| + serial_port_out(port, MTK_UART_SAMPLE_POINT, 0xff); |
| + serial_port_out(port, MTK_UART_FRACDIV_L, 0x00); |
| + serial_port_out(port, MTK_UART_FRACDIV_M, 0x00); |
| } |
| |
| + if ((termios->c_cflag & CRTSCTS) && (!(termios->c_iflag & CRTSCTS))) |
| + mode = MTK_UART_FC_HW; |
| + else if (termios->c_iflag & CRTSCTS) |
| + mode = MTK_UART_FC_SW; |
| + else |
| + mode = MTK_UART_FC_NONE; |
| + |
| + mtk8250_set_flow_ctrl(up, mode); |
| + |
| + if (uart_console(port)) |
| + up->port.cons->cflag = termios->c_cflag; |
| + |
| spin_unlock_irqrestore(&port->lock, flags); |
| /* Don't rewrite B0 */ |
| if (tty_termios_baud_rate(termios)) |
| @@ -104,9 +298,18 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, |
| static int __maybe_unused mtk8250_runtime_suspend(struct device *dev) |
| { |
| struct mtk8250_data *data = dev_get_drvdata(dev); |
| + struct uart_8250_port *up = serial8250_get_port(data->line); |
| |
| - clk_disable_unprepare(data->uart_clk); |
| - clk_disable_unprepare(data->bus_clk); |
| + /*wait until UART in idle status*/ |
| + while |
| + (serial_in(up, MTK_UART_DEBUG0)); |
| + |
| + if (data->clk_count == 0U) |
| + pr_debug("%s clock count is 0\n", __func__); |
| + else { |
| + clk_disable_unprepare(data->bus_clk); |
| + data->clk_count--; |
| + } |
| |
| return 0; |
| } |
| @@ -116,16 +319,15 @@ static int __maybe_unused mtk8250_runtime_resume(struct device *dev) |
| struct mtk8250_data *data = dev_get_drvdata(dev); |
| int err; |
| |
| - err = clk_prepare_enable(data->uart_clk); |
| - if (err) { |
| - dev_warn(dev, "Can't enable clock\n"); |
| - return err; |
| - } |
| - |
| - err = clk_prepare_enable(data->bus_clk); |
| - if (err) { |
| - dev_warn(dev, "Can't enable bus clock\n"); |
| - return err; |
| + if (data->clk_count > 0U) |
| + pr_debug("%s clock count is %d\n", __func__, data->clk_count); |
| + else { |
| + err = clk_prepare_enable(data->bus_clk); |
| + if (err) { |
| + dev_warn(dev, "Can't enable bus clock\n"); |
| + return err; |
| + } |
| + data->clk_count++; |
| } |
| |
| return 0; |
| @@ -135,14 +337,18 @@ static void |
| mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) |
| { |
| if (!state) |
| - pm_runtime_get_sync(port->dev); |
| + if (pm_runtime_get_sync(port->dev)) |
| + mtk8250_runtime_resume(port->dev); |
| |
| serial8250_do_pm(port, state, old); |
| |
| if (state) |
| - pm_runtime_put_sync_suspend(port->dev); |
| + if (!pm_runtime_put_sync_suspend(port->dev)) |
| + mtk8250_runtime_suspend(port->dev); |
| } |
| |
| + |
| + |
| static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, |
| struct mtk8250_data *data) |
| { |
| @@ -162,7 +368,12 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, |
| } |
| |
| data->bus_clk = devm_clk_get(&pdev->dev, "bus"); |
| - return PTR_ERR_OR_ZERO(data->bus_clk); |
| + if (IS_ERR(data->bus_clk)) |
| + return PTR_ERR(data->bus_clk); |
| + |
| + data->dma = NULL; |
| + |
| + return 0; |
| } |
| |
| static int mtk8250_probe(struct platform_device *pdev) |
| @@ -187,6 +398,8 @@ static int mtk8250_probe(struct platform_device *pdev) |
| if (!data) |
| return -ENOMEM; |
| |
| + data->clk_count = 0; |
| + |
| if (pdev->dev.of_node) { |
| err = mtk8250_probe_of(pdev, &uart.port, data); |
| if (err) |
| @@ -204,6 +417,8 @@ static int mtk8250_probe(struct platform_device *pdev) |
| uart.port.iotype = UPIO_MEM32; |
| uart.port.regshift = 2; |
| uart.port.private_data = data; |
| + uart.port.shutdown = mtk8250_shutdown; |
| + uart.port.startup = mtk8250_startup; |
| uart.port.set_termios = mtk8250_set_termios; |
| uart.port.uartclk = clk_get_rate(data->uart_clk); |
| |
| @@ -213,6 +428,7 @@ static int mtk8250_probe(struct platform_device *pdev) |
| |
| platform_set_drvdata(pdev, data); |
| |
| + pm_runtime_enable(&pdev->dev); |
| err = mtk8250_runtime_resume(&pdev->dev); |
| if (err) |
| return err; |
| @@ -221,9 +437,6 @@ static int mtk8250_probe(struct platform_device *pdev) |
| if (data->line < 0) |
| return data->line; |
| |
| - pm_runtime_set_active(&pdev->dev); |
| - pm_runtime_enable(&pdev->dev); |
| - |
| return 0; |
| } |
| |
| @@ -234,18 +447,217 @@ static int mtk8250_remove(struct platform_device *pdev) |
| pm_runtime_get_sync(&pdev->dev); |
| |
| serial8250_unregister_port(data->line); |
| - mtk8250_runtime_suspend(&pdev->dev); |
| |
| pm_runtime_disable(&pdev->dev); |
| pm_runtime_put_noidle(&pdev->dev); |
| |
| + if (!pm_runtime_status_suspended(&pdev->dev)) |
| + mtk8250_runtime_suspend(&pdev->dev); |
| + |
| return 0; |
| } |
| |
| +#ifdef CONFIG_PM_SLEEP |
| +int mtk8250_request_to_sleep(void) |
| +{ |
| + int i = 0; |
| + int line = 0; |
| + int sleep_req; |
| + struct uart_8250_port *up; |
| + struct mtk8250_data *data; |
| + |
| + for (line = 0; line < CONFIG_SERIAL_8250_NR_UARTS; line++) { |
| + up = serial8250_get_port(line); |
| + |
| + if (up->port.dev == NULL) |
| + continue; |
| + else if (dev_get_drvdata(up->port.dev) == NULL) |
| + continue; |
| + |
| + data = dev_get_drvdata(up->port.dev); |
| + if (data->clk_count <= 0U) |
| + continue; |
| + |
| + /* request UART to sleep */ |
| + sleep_req = serial_in(up, MTK_UART_SLEEP_REQ); |
| + serial_out(up, MTK_UART_SLEEP_REQ, |
| + sleep_req | MTK_UART_SEND_SLEEP_REQ); |
| + |
| + /* wait for UART to ACK */ |
| + while (!(serial_in(up, MTK_UART_SLEEP_ACK) |
| + & MTK_UART_SLEEP_ACK_IDLE)) { |
| + if (i++ >= MTK_UART_WAIT_ACK_TIMES) { |
| + serial_out(up, MTK_UART_SLEEP_REQ, sleep_req); |
| + pr_err("CANNOT GET UART%d SLEEP ACK\n", line); |
| + return -EBUSY; |
| + } |
| + udelay(10); |
| + } |
| + } |
| + |
| + return 0; |
| +} |
| +EXPORT_SYMBOL(mtk8250_request_to_sleep); |
| + |
| +int mtk8250_request_to_wakeup(void) |
| +{ |
| + int i = 0; |
| + int line = 0; |
| + int sleep_req; |
| + struct uart_8250_port *up; |
| + struct mtk8250_data *data; |
| + |
| + for (line = 0; line < CONFIG_SERIAL_8250_NR_UARTS; line++) { |
| + up = serial8250_get_port(line); |
| + |
| + if (up->port.dev == NULL) |
| + continue; |
| + else if (dev_get_drvdata(up->port.dev) == NULL) |
| + continue; |
| + |
| + data = dev_get_drvdata(up->port.dev); |
| + if (data->clk_count <= 0U) |
| + continue; |
| + |
| + /* wakeup uart */ |
| + sleep_req = serial_in(up, MTK_UART_SLEEP_REQ); |
| + serial_out(up, MTK_UART_SLEEP_REQ, |
| + sleep_req & (~MTK_UART_SEND_SLEEP_REQ)); |
| + |
| + /* wait for UART to ACK */ |
| + while (serial_in(up, MTK_UART_SLEEP_ACK) |
| + & MTK_UART_SLEEP_ACK_IDLE) { |
| + if (i++ >= MTK_UART_WAIT_ACK_TIMES) { |
| + serial_out(up, MTK_UART_SLEEP_REQ, sleep_req); |
| + pr_err("CANNOT GET UART%d WAKE ACK\n", line); |
| + return -EBUSY; |
| + } |
| + udelay(10); |
| + } |
| + } |
| + |
| + return 0; |
| +} |
| +EXPORT_SYMBOL(mtk8250_request_to_wakeup); |
| + |
| +static void mtk8250_save_dev(struct device *dev) |
| +{ |
| + unsigned long flags; |
| + struct mtk8250_data *data = dev_get_drvdata(dev); |
| + struct mtk8250_reg *reg = &data->reg; |
| + struct uart_8250_port *up = serial8250_get_port(data->line); |
| + |
| + /* DLL may be changed by console write. To avoid this, use spinlock */ |
| + spin_lock_irqsave(&up->port.lock, flags); |
| + |
| + /* save when LCR = 0xBF */ |
| + reg->lcr = serial_in(up, UART_LCR); |
| + serial_out(up, UART_LCR, 0xBF); |
| + reg->efr = serial_in(up, UART_EFR); |
| + serial_out(up, UART_LCR, reg->lcr); |
| + reg->fcr_rd = serial_in(up, MTK_UART_FCR_RD); |
| + |
| + /*save baudrate */ |
| + reg->highspeed = serial_in(up, MTK_UART_HIGHS); |
| + reg->fracdiv_l = serial_in(up, MTK_UART_FRACDIV_L); |
| + reg->fracdiv_m = serial_in(up, MTK_UART_FRACDIV_M); |
| + serial_out(up, UART_LCR, reg->lcr | UART_LCR_DLAB); |
| + reg->dll = serial_in(up, UART_DLL); |
| + reg->dlm = serial_in(up, UART_DLM); |
| + serial_out(up, UART_LCR, reg->lcr); |
| + reg->sample_count = serial_in(up, MTK_UART_SAMPLE_COUNT); |
| + reg->sample_point = serial_in(up, MTK_UART_SAMPLE_POINT); |
| + reg->guard = serial_in(up, MTK_UART_GUARD); |
| + |
| + /* save flow control */ |
| + reg->mcr = serial_in(up, UART_MCR); |
| + reg->ier = serial_in(up, UART_IER); |
| + reg->xon1 = serial_in(up, UART_XON1); |
| + reg->xon2 = serial_in(up, UART_XON2); |
| + reg->xoff1 = serial_in(up, UART_XOFF1); |
| + reg->xoff2 = serial_in(up, UART_XOFF2); |
| + reg->escape_dat = serial_in(up, MTK_UART_ESCAPE_DAT); |
| + reg->sleep_en = serial_in(up, MTK_UART_SLEEP_EN); |
| + |
| + /* save others */ |
| + reg->escape_en = serial_in(up, MTK_UART_ESCAPE_EN); |
| + reg->msr = serial_in(up, UART_MSR); |
| + reg->scr = serial_in(up, UART_SCR); |
| + reg->dma_en = serial_in(up, MTK_UART_DMA_EN); |
| + reg->rxtri_ad = serial_in(up, MTK_UART_RXTRI_AD); |
| + reg->rx_sel = serial_in(up, MTK_UART_RX_SEL); |
| + spin_unlock_irqrestore(&up->port.lock, flags); |
| +} |
| + |
| +void mtk8250_restore_dev(void) |
| +{ |
| + unsigned long flags; |
| + int line = 0; |
| + struct uart_8250_port *up; |
| + struct mtk8250_data *data; |
| + struct mtk8250_reg *reg; |
| + |
| + for (line = 0; line < CONFIG_SERIAL_8250_NR_UARTS; line++) { |
| + up = serial8250_get_port(line); |
| + data = dev_get_drvdata(up->port.dev); |
| + reg = &data->reg; |
| + |
| + if (!uart_console(&up->port)) |
| + continue; |
| + |
| + mtk8250_runtime_resume(up->port.dev); |
| + |
| + spin_lock_irqsave(&up->port.lock, flags); |
| + |
| + /* restore when LCR = 0xBF */ |
| + serial_out(up, UART_LCR, 0xBF); |
| + serial_out(up, UART_EFR, reg->efr); |
| + serial_out(up, UART_LCR, reg->lcr); |
| + serial_out(up, UART_FCR, reg->fcr_rd); |
| + |
| + /*restore baudrate */ |
| + serial_out(up, MTK_UART_HIGHS, reg->highspeed); |
| + serial_out(up, MTK_UART_FRACDIV_L, reg->fracdiv_l); |
| + serial_out(up, MTK_UART_FRACDIV_M, reg->fracdiv_m); |
| + serial_out(up, UART_LCR, reg->lcr | UART_LCR_DLAB); |
| + serial_out(up, UART_DLL, reg->dll); |
| + serial_out(up, UART_DLM, reg->dlm); |
| + serial_out(up, UART_LCR, reg->lcr); |
| + serial_out(up, MTK_UART_SAMPLE_COUNT, reg->sample_count); |
| + serial_out(up, MTK_UART_SAMPLE_POINT, reg->sample_point); |
| + serial_out(up, MTK_UART_GUARD, reg->guard); |
| + |
| + /* restore flow control */ |
| + serial_out(up, UART_MCR, reg->mcr); |
| + serial_out(up, UART_IER, reg->ier); |
| + serial_out(up, UART_XON1, reg->xon1); |
| + serial_out(up, UART_XON2, reg->xon2); |
| + serial_out(up, UART_XOFF1, reg->xoff1); |
| + serial_out(up, UART_XOFF2, reg->xoff2); |
| + serial_out(up, MTK_UART_ESCAPE_DAT, reg->escape_dat); |
| + serial_out(up, MTK_UART_SLEEP_EN, reg->sleep_en); |
| + |
| + /* restore others */ |
| + serial_out(up, MTK_UART_ESCAPE_EN, reg->escape_en); |
| + serial_out(up, UART_MSR, reg->msr); |
| + serial_out(up, UART_SCR, reg->scr); |
| + |
| + serial_out(up, MTK_UART_DMA_EN, reg->dma_en); |
| + serial_out(up, MTK_UART_RXTRI_AD, reg->rxtri_ad); |
| + serial_out(up, MTK_UART_FCR_RD, reg->fcr_rd); |
| + serial_out(up, MTK_UART_RX_SEL, reg->rx_sel); |
| + spin_unlock_irqrestore(&up->port.lock, flags); |
| + } |
| +} |
| +EXPORT_SYMBOL(mtk8250_restore_dev); |
| + |
| static int __maybe_unused mtk8250_suspend(struct device *dev) |
| { |
| struct mtk8250_data *data = dev_get_drvdata(dev); |
| + struct uart_8250_port *up = serial8250_get_port(data->line); |
| |
| + if (uart_console(&up->port) == 1) |
| + mtk8250_save_dev(dev); |
| serial8250_suspend_port(data->line); |
| |
| return 0; |
| @@ -259,6 +671,7 @@ static int __maybe_unused mtk8250_resume(struct device *dev) |
| |
| return 0; |
| } |
| +#endif /* CONFIG_PM_SLEEP */ |
| |
| static const struct dev_pm_ops mtk8250_pm_ops = { |
| SET_SYSTEM_SLEEP_PM_OPS(mtk8250_suspend, mtk8250_resume) |
| diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c |
| index 48d10a61e271c..542b67a6b5a65 100644 |
| --- a/drivers/usb/mtu3/mtu3_core.c |
| +++ b/drivers/usb/mtu3/mtu3_core.c |
| @@ -94,6 +94,7 @@ static int mtu3_device_enable(struct mtu3 *mtu) |
| { |
| void __iomem *ibase = mtu->ippc_base; |
| u32 check_clk = 0; |
| + struct ssusb_mtk *ssusb = mtu->ssusb; |
| |
| mtu3_clrbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); |
| |
| @@ -107,7 +108,7 @@ static int mtu3_device_enable(struct mtu3 *mtu) |
| (SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN | |
| SSUSB_U2_PORT_HOST_SEL)); |
| |
| - if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) { |
| + if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG && !ssusb->otg_switch.manual_drd_enabled) { |
| mtu3_setbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); |
| if (mtu->is_u3_ip) |
| mtu3_setbits(ibase, SSUSB_U3_CTRL(0), |
| @@ -120,6 +121,7 @@ static int mtu3_device_enable(struct mtu3 *mtu) |
| static void mtu3_device_disable(struct mtu3 *mtu) |
| { |
| void __iomem *ibase = mtu->ippc_base; |
| + struct ssusb_mtk *ssusb = mtu->ssusb; |
| |
| if (mtu->is_u3_ip) |
| mtu3_setbits(ibase, SSUSB_U3_CTRL(0), |
| @@ -128,7 +130,7 @@ static void mtu3_device_disable(struct mtu3 *mtu) |
| mtu3_setbits(ibase, SSUSB_U2_CTRL(0), |
| SSUSB_U2_PORT_DIS | SSUSB_U2_PORT_PDN); |
| |
| - if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG) |
| + if (mtu->ssusb->dr_mode == USB_DR_MODE_OTG && !ssusb->otg_switch.manual_drd_enabled) |
| mtu3_clrbits(ibase, SSUSB_U2_CTRL(0), SSUSB_U2_PORT_OTG_SEL); |
| |
| mtu3_setbits(ibase, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); |
| @@ -183,6 +185,9 @@ static void mtu3_intr_enable(struct mtu3 *mtu) |
| value = SUSPEND_INTR | RESUME_INTR | RESET_INTR | LPM_RESUME_INTR; |
| mtu3_writel(mbase, U3D_COMMON_USB_INTR_ENABLE, value); |
| |
| + mtu3_clrbits(mbase, U3D_DEVICE_CONTROL, DC_SESSION); |
| + mtu3_setbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); |
| + |
| if (mtu->is_u3_ip) { |
| /* Enable U3 LTSSM interrupts */ |
| value = HOT_RST_INTR | WARM_RST_INTR | VBUS_RISE_INTR | |
| @@ -759,7 +764,10 @@ static int mtu3_hw_init(struct mtu3 *mtu) |
| mtu->hw_version = mtu3_readl(mtu->ippc_base, U3D_SSUSB_HW_ID); |
| |
| cap_dev = mtu3_readl(mtu->ippc_base, U3D_SSUSB_IP_DEV_CAP); |
| - mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(cap_dev); |
| + if (mtu->max_speed <= USB_SPEED_HIGH) |
| + mtu->is_u3_ip = 0; |
| + else |
| + mtu->is_u3_ip = !!SSUSB_IP_DEV_U3_PORT_NUM(cap_dev); |
| |
| dev_info(mtu->dev, "IP version 0x%x(%s IP)\n", mtu->hw_version, |
| mtu->is_u3_ip ? "U3" : "U2"); |
| diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c |
| index ac60e9c8564e2..7660d107e5bcc 100644 |
| --- a/drivers/usb/mtu3/mtu3_dr.c |
| +++ b/drivers/usb/mtu3/mtu3_dr.c |
| @@ -401,7 +401,7 @@ void ssusb_set_force_mode(struct ssusb_mtk *ssusb, |
| break; |
| case MTU3_DR_FORCE_HOST: |
| value |= SSUSB_U2_PORT_FORCE_IDDIG; |
| - value &= ~SSUSB_U2_PORT_RG_IDDIG; |
| + value &= ~(SSUSB_U2_PORT_RG_IDDIG | SSUSB_U2_PORT_OTG_SEL); |
| break; |
| case MTU3_DR_FORCE_NONE: |
| value &= ~(SSUSB_U2_PORT_FORCE_IDDIG | SSUSB_U2_PORT_RG_IDDIG); |
| diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h |
| index ccb73422c2fa2..1dfd5ed5c8c52 100644 |
| --- a/include/linux/mailbox/mtk-cmdq-mailbox.h |
| +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h |
| @@ -19,6 +19,10 @@ |
| #define CMDQ_WFE_UPDATE BIT(31) |
| #define CMDQ_WFE_WAIT BIT(15) |
| #define CMDQ_WFE_WAIT_VALUE 0x1 |
| +#define CMDQ_WFE_OPTION (CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | \ |
| + CMDQ_WFE_WAIT_VALUE) |
| +/** cmdq event maximum */ |
| +#define CMDQ_MAX_EVENT 0x3ff |
| |
| /* |
| * CMDQ_CODE_MASK: |
| @@ -42,6 +46,7 @@ |
| enum cmdq_code { |
| CMDQ_CODE_MASK = 0x02, |
| CMDQ_CODE_WRITE = 0x04, |
| + CMDQ_CODE_POLL = 0x08, |
| CMDQ_CODE_JUMP = 0x10, |
| CMDQ_CODE_WFE = 0x20, |
| CMDQ_CODE_EOC = 0x40, |
| diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h |
| index 00443e4ed9b73..f84e71c586e23 100644 |
| --- a/include/linux/mfd/cros_ec.h |
| +++ b/include/linux/mfd/cros_ec.h |
| @@ -28,6 +28,7 @@ |
| #define CROS_EC_DEV_FP_NAME "cros_fp" |
| #define CROS_EC_DEV_TP_NAME "cros_tp" |
| #define CROS_EC_DEV_ISH_NAME "cros_ish" |
| +#define CROS_EC_DEV_SCP_NAME "cros_scp" |
| |
| /* |
| * The EC is unresponsive for a time after a reboot command. Add a |
| diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h |
| index 41cb61a17fb81..ff095219165ad 100644 |
| --- a/include/linux/mfd/cros_ec_commands.h |
| +++ b/include/linux/mfd/cros_ec_commands.h |
| @@ -1299,6 +1299,16 @@ enum ec_feature_code { |
| EC_FEATURE_CEC = 35, |
| /* EC supports tight sensor timestamping. */ |
| EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36, |
| + /* |
| + * EC supports tablet mode detection aligned to Chrome and allows |
| + * setting of threshold by host command using |
| + * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE. |
| + */ |
| + EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37, |
| + /* EC supports audio codec. */ |
| + EC_FEATURE_AUDIO_CODEC = 38, |
| + /* The MCU is a System Companion Processor (SCP). */ |
| + EC_FEATURE_SCP = 39, |
| /* The MCU is an Integrated Sensor Hub */ |
| EC_FEATURE_ISH = 40, |
| }; |
| diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h |
| index 54ade13a9b157..15884354af20a 100644 |
| --- a/include/linux/soc/mediatek/mtk-cmdq.h |
| +++ b/include/linux/soc/mediatek/mtk-cmdq.h |
| @@ -13,11 +13,14 @@ |
| |
| #define CMDQ_NO_TIMEOUT 0xffffffffu |
| |
| -/** cmdq event maximum */ |
| -#define CMDQ_MAX_EVENT 0x3ff |
| - |
| struct cmdq_pkt; |
| |
| +struct cmdq_subsys { |
| + u8 id; |
| + u16 offset; |
| + u16 size; |
| +}; |
| + |
| struct cmdq_client { |
| spinlock_t lock; |
| u32 pkt_cnt; |
| @@ -63,26 +66,26 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt); |
| /** |
| * cmdq_pkt_write() - append write command to the CMDQ packet |
| * @pkt: the CMDQ packet |
| - * @value: the specified target register value |
| * @subsys: the CMDQ sub system code |
| * @offset: register offset from CMDQ sub system |
| + * @value: the specified target register value |
| * |
| * Return: 0 for success; else the error code is returned |
| */ |
| -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset); |
| +int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); |
| |
| /** |
| * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet |
| * @pkt: the CMDQ packet |
| - * @value: the specified target register value |
| * @subsys: the CMDQ sub system code |
| * @offset: register offset from CMDQ sub system |
| + * @value: the specified target register value |
| * @mask: the specified target register mask |
| * |
| * Return: 0 for success; else the error code is returned |
| */ |
| -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, |
| - u32 subsys, u32 offset, u32 mask); |
| +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, |
| + u32 value, u32 mask); |
| |
| /** |
| * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet |
| @@ -91,7 +94,7 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, |
| * |
| * Return: 0 for success; else the error code is returned |
| */ |
| -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event); |
| +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event); |
| |
| /** |
| * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet |
| @@ -100,8 +103,23 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event); |
| * |
| * Return: 0 for success; else the error code is returned |
| */ |
| -int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event); |
| +int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); |
| |
| +/** |
| + * cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to |
| + * execute an instruction that wait for a specified hardware |
| + * register to check for the value. All GCE hardware |
| + * threads will be blocked by this instruction. |
| + * @pkt: the CMDQ packet |
| + * @subsys: the CMDQ sub system code |
| + * @offset: register offset from CMDQ sub system |
| + * @value: the specified target register value |
| + * @mask: the specified target register mask |
| + * |
| + * Return: 0 for success; else the error code is returned |
| + */ |
| +int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, |
| + u16 offset, u32 value, u32 mask); |
| /** |
| * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ |
| * packet and call back at the end of done packet |
| @@ -130,4 +148,28 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, |
| */ |
| int cmdq_pkt_flush(struct cmdq_pkt *pkt); |
| |
| +/** |
| + * cmdq_dev_get_subsys() - parse sub system from the device node of CMDQ client |
| + * @dev: device of CMDQ mailbox client |
| + * @idx: the index of desired subsys |
| + * |
| + * Return: CMDQ subsys pointer |
| + * |
| + * Help CMDQ client pasing the sub system number |
| + * from the device node of CMDQ client. |
| + */ |
| +struct cmdq_subsys *cmdq_dev_get_subsys(struct device *dev, int idx); |
| + |
| +/** |
| + * cmdq_dev_get_event() - parse event from the device node of CMDQ client |
| + * @dev: device of CMDQ mailbox client |
| + * @name: the name of desired event |
| + * |
| + * Return: CMDQ event number |
| + * |
| + * Help CMDQ client pasing the event number |
| + * from the device node of CMDQ client. |
| + */ |
| +s32 cmdq_dev_get_event(struct device *dev, const char *name); |
| + |
| #endif /* __MTK_CMDQ_H__ */ |
| diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c |
| index 1bc0fafe5e290..d569157fe9457 100644 |
| --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c |
| +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c |
| @@ -955,6 +955,20 @@ static irqreturn_t mt8183_afe_irq_handler(int irq_id, void *dev) |
| return irq_ret; |
| } |
| |
| +static int mt8183_afe_suspend(struct device *dev) |
| +{ |
| + struct mtk_base_afe *afe = dev_get_drvdata(dev); |
| + |
| + return mt8183_afe_disable_clock(afe); |
| +} |
| + |
| +static int mt8183_afe_resume(struct device *dev) |
| +{ |
| + struct mtk_base_afe *afe = dev_get_drvdata(dev); |
| + |
| + return mt8183_afe_enable_clock(afe); |
| +} |
| + |
| static int mt8183_afe_runtime_suspend(struct device *dev) |
| { |
| struct mtk_base_afe *afe = dev_get_drvdata(dev); |
| @@ -1232,6 +1246,8 @@ static const struct of_device_id mt8183_afe_pcm_dt_match[] = { |
| MODULE_DEVICE_TABLE(of, mt8183_afe_pcm_dt_match); |
| |
| static const struct dev_pm_ops mt8183_afe_pm_ops = { |
| + SET_SYSTEM_SLEEP_PM_OPS(mt8183_afe_suspend, |
| + mt8183_afe_resume) |
| SET_RUNTIME_PM_OPS(mt8183_afe_runtime_suspend, |
| mt8183_afe_runtime_resume, NULL) |
| }; |
| -- |
| 2.22.0.rc1.257.g3120a18244-goog |
| |