blob: 804cfc880281fda8ea1c2de32a74e5a6b72cb4c8 [file] [log] [blame]
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