Compare commits
148
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eff4d587d2 | ||
|
|
366514a4be | ||
|
|
f9b2980f86 | ||
|
|
494a158389 | ||
|
|
a409dcbfec | ||
|
|
98f77a3a33 | ||
|
|
fd2bf45a19 | ||
|
|
0c0127fdc3 | ||
|
|
4e346d269a | ||
|
|
8e4d11a333 | ||
|
|
3543245775 | ||
|
|
cbf2e8abe9 | ||
|
|
acf07bcb94 | ||
|
|
e449ec78a4 | ||
|
|
35a4c34d22 | ||
|
|
e07a012ff0 | ||
|
|
a87a23eb5b | ||
|
|
8530ab4958 | ||
|
|
bd1802e48c | ||
|
|
75be9aeeac | ||
|
|
dd86f157f6 | ||
|
|
ee65e16217 | ||
|
|
84af317cf3 | ||
|
|
a64e4bf1c1 | ||
|
|
a75c8520d0 | ||
|
|
bbf04e9a89 | ||
|
|
c66af1b766 | ||
|
|
2458ea9a04 | ||
|
|
14f6277465 | ||
|
|
d786880067 | ||
|
|
e3d103cf3e | ||
|
|
c7a50eb91f | ||
|
|
84d6d81d7e | ||
|
|
18b308e7ed | ||
|
|
fe8a0116e4 | ||
|
|
ea82274201 | ||
|
|
9fcb37425f | ||
|
|
10d17dbcce | ||
|
|
bc5942c904 | ||
|
|
b54985fe3d | ||
|
|
3091c05197 | ||
|
|
f11ecb413d | ||
|
|
74ff5e5f6d | ||
|
|
31811f31cc | ||
|
|
a5329b2b64 | ||
|
|
b9088d4a23 | ||
|
|
fddd6304c2 | ||
|
|
5150f5d841 | ||
|
|
322c8e45b5 | ||
|
|
7b4c276857 | ||
|
|
820e88911d | ||
|
|
e9d731ffb6 | ||
|
|
3f763023a0 | ||
|
|
96595f6b1b | ||
|
|
28a7b211f7 | ||
|
|
a00de5720b | ||
|
|
176ffad43c | ||
|
|
4c56a02679 | ||
|
|
9856c0e55d | ||
|
|
cb59995ea8 | ||
|
|
1ae6f14cf5 | ||
|
|
913fd81513 | ||
|
|
10ce718089 | ||
|
|
f487855fe4 | ||
|
|
70b6a47406 | ||
|
|
6243bfbf66 | ||
|
|
3b9f47e3eb | ||
|
|
74f0caece2 | ||
|
|
a03b6f66bc | ||
|
|
9873589051 | ||
|
|
56ea16deb2 | ||
|
|
de4822b2cd | ||
|
|
f249e36754 | ||
|
|
d1e3693094 | ||
|
|
fd293334af | ||
|
|
3296008419 | ||
|
|
c8fd7d765c | ||
|
|
317014bc1c | ||
|
|
cc4cd8a3c6 | ||
|
|
9acaeaaf9b | ||
|
|
0c44639c93 | ||
|
|
ae145cf0ce | ||
|
|
4dafef233b | ||
|
|
403913ad76 | ||
|
|
61454e44bd | ||
|
|
40510b5744 | ||
|
|
e47d24e45e | ||
|
|
03a4db0586 | ||
|
|
dee32fa9a0 | ||
|
|
1b14f1b567 | ||
|
|
972da4752e | ||
|
|
9e0a4a690f | ||
|
|
e58928e559 | ||
|
|
209d82d0ab | ||
|
|
d3f3e70dad | ||
|
|
756247da37 | ||
|
|
8202f10782 | ||
|
|
b671a469df | ||
|
|
4efe795b62 | ||
|
|
b821768cef | ||
|
|
81117ffffe | ||
|
|
43f3dece0a | ||
|
|
9334c17ced | ||
|
|
8c1109c2a6 | ||
|
|
ede5ebe26b | ||
|
|
f2cd633afe | ||
|
|
d53cf85bcb | ||
|
|
9bc36a47ff | ||
|
|
2561655eb4 | ||
|
|
8207bb4fc6 | ||
|
|
59f8f7a811 | ||
|
|
98672e71bd | ||
|
|
a910dcea09 | ||
|
|
0b928354a0 | ||
|
|
a89e369cf2 | ||
|
|
59a45f29ee | ||
|
|
d0bf78d473 | ||
|
|
49b8aeda99 | ||
|
|
7de2507df7 | ||
|
|
3872ea97ca | ||
|
|
66bd4205f3 | ||
|
|
4535649c39 | ||
|
|
a78fa2cdf4 | ||
|
|
846ada9e33 | ||
|
|
dbffbcb14d | ||
|
|
05629d040e | ||
|
|
a0543b422c | ||
|
|
0e0c4d980c | ||
|
|
3283c40ce3 | ||
|
|
49ab99dea7 | ||
|
|
75b5fa2f68 | ||
|
|
97c550d455 | ||
|
|
a4b10a99ff | ||
|
|
200397ed67 | ||
|
|
6516ffb4c2 | ||
|
|
16f8d9d290 | ||
|
|
2a4d8783a5 | ||
|
|
3ccf195e5b | ||
|
|
de738636ef | ||
|
|
3c57813597 | ||
|
|
6109842b1a | ||
|
|
4726d21918 | ||
|
|
7e0f740103 | ||
|
|
c35c0f4c06 | ||
|
|
7bf5d17757 | ||
|
|
ea0b719033 | ||
|
|
c9d97a2bba | ||
|
|
3336d897c6 |
No files matched your search
+11
@@ -1707,6 +1707,17 @@ devicetree_library(
|
||||
deps = ["//common:dtc_includes_aarch64"],
|
||||
)
|
||||
|
||||
devicetree_library(
|
||||
name = "all_nvidia_dts",
|
||||
hdrs = glob([
|
||||
"arch/arm64/boot/dts/nvidia/*.dtsi",
|
||||
"arch/arm64/boot/dts/nvidia/*.dts",
|
||||
]),
|
||||
includes = ["arch/arm64/boot/dts/nvidia"],
|
||||
visibility = ["//vendor:__subpackages__"],
|
||||
deps = [":dtc_includes_aarch64"],
|
||||
)
|
||||
|
||||
_KSELFTEST_DIR = "testcases/selftests"
|
||||
|
||||
_KSELFTEST_COPTS = [
|
||||
|
||||
@@ -240,6 +240,17 @@ properties:
|
||||
- const: google,smaug-rev1
|
||||
- const: google,smaug
|
||||
- const: nvidia,tegra210
|
||||
- description: NVIDIA Shield TV 2015
|
||||
items:
|
||||
- const: nvidia,p2571-0930
|
||||
- const: nvidia,foster_e
|
||||
- const: nvidia,tegra210
|
||||
- description: NVIDIA Shield TV Pro 2015
|
||||
items:
|
||||
- const: nvidia,p2571-0932
|
||||
- const: nvidia,foster_e_hdd
|
||||
- const: nvidia,foster_e
|
||||
- const: nvidia,tegra210
|
||||
- description: Jetson TX2 Developer Kit
|
||||
items:
|
||||
- const: nvidia,p2771-0000
|
||||
|
||||
@@ -32,6 +32,7 @@ properties:
|
||||
- nvidia,tegra30-car
|
||||
- nvidia,tegra114-car
|
||||
- nvidia,tegra210-car
|
||||
- nvidia,tegra210b01-car
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
MAX77812 voltage regulator
|
||||
|
||||
Required properties:
|
||||
- compatible: "maxim,max77812-regulator"
|
||||
- reg: I2C slave address
|
||||
|
||||
Regulators subnode:
|
||||
|
||||
MAX77812 supports four regulators, regulators should be described under
|
||||
regualtors subnode.
|
||||
|
||||
Optional properties:
|
||||
-maxim,ramp-up-slew-rate: to configure slew rate during regulator
|
||||
voltage ramp up time
|
||||
-maxim,ramp-down-slew-rate: to configre slew rate during regulator
|
||||
voltage ramp down time
|
||||
-maxim,soft-start-slew-rate: to configure slew rate during regulator
|
||||
enable time
|
||||
-maxim,shutdown-slew-rate: to configure slew rate during regulator
|
||||
disable time or shutdown time
|
||||
|
||||
Each regulator is defined using the standard binding for regulators.
|
||||
|
||||
Example:
|
||||
|
||||
max77812@1b {
|
||||
compatible = "maxim,max77812-regulator";
|
||||
reg = <0x1b>;
|
||||
|
||||
regulators {
|
||||
m1vout {
|
||||
regulator-name = "mvout1";
|
||||
regulator-min-microvolt = <250000>;
|
||||
regulator-max-microvolt = <1525000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-init-mode = <REGULATOR_MODE_NORMAL>;
|
||||
};
|
||||
|
||||
m2vout {
|
||||
regulator-name = "mvout2";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <250000>;
|
||||
regulator-max-microvolt = <1525000>;
|
||||
regulator-init-mode = <REGULATOR_MODE_NORMAL>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/usb/rohm,bm92t.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rohm BM92TXX USB Type-C and Power Delivery controller
|
||||
|
||||
maintainers:
|
||||
- CTCaer <ctcaer@gmail.com>
|
||||
- Alexandre Hamamdjian <azkali.limited@gmail.com>
|
||||
|
||||
description:
|
||||
The Rohm BM92TXX is a family of USB Type-C and Power Delivery
|
||||
controllers with an integrated MCU. The host communicates with the
|
||||
device over I2C and is notified of state changes through a dedicated
|
||||
interrupt line.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bm92t
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vbus-supply:
|
||||
description: VBUS sink regulator.
|
||||
|
||||
vbus-source-supply:
|
||||
description: VBUS source (provider) regulator.
|
||||
|
||||
pd_bat_chg-supply:
|
||||
description: Battery charger regulator gated by Power Delivery state.
|
||||
|
||||
rohm,vconn-en-gpio:
|
||||
maxItems: 1
|
||||
description: GPIO controlling the external VCONN switch.
|
||||
|
||||
rohm,dp-disable:
|
||||
type: boolean
|
||||
description: Disable DisplayPort alternate-mode handling.
|
||||
|
||||
rohm,dp-alerts-enable:
|
||||
type: boolean
|
||||
description: Enable DisplayPort status alerts.
|
||||
|
||||
rohm,dp-signal-toggle-on-resume:
|
||||
type: boolean
|
||||
description:
|
||||
Toggle the DisplayPort signal on resume to work around sinks that
|
||||
do not re-train after system resume.
|
||||
|
||||
rohm,dp-lanes:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [2, 4]
|
||||
default: 2
|
||||
description: Number of DisplayPort lanes to negotiate.
|
||||
|
||||
rohm,led-static-on-suspend:
|
||||
type: boolean
|
||||
description:
|
||||
Keep the charge LED in a static state during system suspend
|
||||
instead of letting the controller animate it.
|
||||
|
||||
rohm,dock-power-limit-disable:
|
||||
type: boolean
|
||||
description:
|
||||
Disable the lower power limit applied when a dock is detected.
|
||||
|
||||
rohm,pd-5v-current-limit-ma:
|
||||
description: Charging current limit in mA when 5V PD contract is active.
|
||||
|
||||
rohm,pd-9v-current-limit-ma:
|
||||
description: Charging current limit in mA when 9V PD contract is active.
|
||||
|
||||
rohm,pd-12v-current-limit-ma:
|
||||
description: Charging current limit in mA when 12V PD contract is active.
|
||||
|
||||
rohm,pd-15v-current-limit-ma:
|
||||
description: Charging current limit in mA when 15V PD contract is active.
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output port linking to a USB role switch consumer endpoint.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
typec@18 {
|
||||
compatible = "rohm,bm92t";
|
||||
reg = <0x18>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
vbus-supply = <&vbus_reg>;
|
||||
vbus-source-supply = <&vbus_src_reg>;
|
||||
pd_bat_chg-supply = <&pd_bat_chg_reg>;
|
||||
|
||||
rohm,dp-lanes = <4>;
|
||||
rohm,pd-5v-current-limit-ma = <2000>;
|
||||
rohm,pd-9v-current-limit-ma = <2000>;
|
||||
rohm,pd-12v-current-limit-ma = <1500>;
|
||||
rohm,pd-15v-current-limit-ma = <1200>;
|
||||
|
||||
port {
|
||||
bm92t_ep: endpoint {
|
||||
remote-endpoint = <&usb_role_sw>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -23259,6 +23259,14 @@ L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/iio/pressure/rohm-bm1390.c
|
||||
|
||||
ROHM BM92TXX USB TYPE-C CONTROLLER DRIVER
|
||||
M: CTCaer <ctcaer@gmail.com>
|
||||
M: Alexandre Hamamdjian <azkali.limited@gmail.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/usb/rohm,bm92t.yaml
|
||||
F: drivers/usb/typec/bm92txx.c
|
||||
|
||||
ROHM BU270xx LIGHT SENSOR DRIVERs
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
||||
@@ -2391,6 +2391,12 @@ config CMDLINE_FROM_BOOTLOADER
|
||||
the boot loader doesn't provide any, the default kernel command
|
||||
string provided in CMDLINE will be used.
|
||||
|
||||
config CMDLINE_EXTEND
|
||||
bool "Extend bootloader kernel arguments"
|
||||
help
|
||||
The command-line arguments provided by the boot loader will be
|
||||
appended to the default kernel command string.
|
||||
|
||||
config CMDLINE_FORCE
|
||||
bool "Always use the default kernel command string"
|
||||
help
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
# Enables support for device-tree overlays
|
||||
DTC_FLAGS_tegra210-p2371-2180 := -@
|
||||
DTC_FLAGS_tegra210-p2571-0930 := -@
|
||||
DTC_FLAGS_tegra210-p2571-0932 := -@
|
||||
DTC_FLAGS_tegra210-p3450-0000 := -@
|
||||
DTC_FLAGS_tegra210-p3541-0000 := -@
|
||||
DTC_FLAGS_tegra186-p2771-0000 := -@
|
||||
@@ -20,10 +22,19 @@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571-0930.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571-0932.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p3450-0000.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p3541-0000.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2894-0050-a08.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-p2894-2551-b00.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-p3425-0050-a04.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-odin.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-p2894-0050-a08.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-odin.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-vali.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-fric.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p3509-0000+p3636-0001.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p2972-0000.dtb
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
i2c7 = "/i2c@31e0000";
|
||||
mmc0 = "/mmc@3460000";
|
||||
mmc1 = "/mmc@3400000";
|
||||
mmc2 = "/mmc@3440000";
|
||||
serial0 = &uarta;
|
||||
serial3 = &uartd;
|
||||
};
|
||||
|
||||
chosen {
|
||||
@@ -66,6 +68,24 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
serial@3130000 {
|
||||
/delete-property/ reg-shift;
|
||||
status = "okay";
|
||||
compatible = "nvidia,tegra30-hsuart";
|
||||
reset-names = "serial";
|
||||
|
||||
bluetooth {
|
||||
compatible = "brcm,bcm43540-bt";
|
||||
device-wakeup-gpios = <&gpio TEGRA186_MAIN_GPIO(Y, 4) GPIO_ACTIVE_HIGH>;
|
||||
shutdown-gpios = <&gpio TEGRA186_MAIN_GPIO(H, 5) GPIO_ACTIVE_HIGH>;
|
||||
interrupt-parent = <&gpio_aon>;
|
||||
interrupts = <TEGRA186_AON_GPIO(FF, 4) IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-names = "host-wakeup";
|
||||
vbat-supply = <&vdd_5v0_sys>;
|
||||
vddio-supply = <&vdd_1v8>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@3160000 {
|
||||
status = "okay";
|
||||
|
||||
@@ -147,7 +167,21 @@
|
||||
/* SDMMC3 (SDIO) */
|
||||
mmc@3440000 {
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
non-removable;
|
||||
power-gpios = <&gpio TEGRA186_MAIN_GPIO(N, 0) GPIO_ACTIVE_HIGH>;
|
||||
vqmmc-supply = <&vddio_sdmmc3>;
|
||||
vmmc-supply = <&vdd_1v8>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
wifi@1 {
|
||||
compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac";
|
||||
reg = <1>;
|
||||
interrupt-parent = <&gpio_aon>;
|
||||
interrupts = <TEGRA186_AON_GPIO(FF, 3) IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "host-wake";
|
||||
};
|
||||
};
|
||||
|
||||
/* SDMMC4 (eMMC) */
|
||||
@@ -348,8 +382,8 @@
|
||||
|
||||
vddio_sdmmc3: ldo5 {
|
||||
regulator-name = "VDDIO_SDMMC3_AP";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
vdd_hdmi_1v05: ldo7 {
|
||||
|
||||
@@ -1954,6 +1954,8 @@
|
||||
denver_0: cpu@0 {
|
||||
compatible = "nvidia,tegra186-denver";
|
||||
device_type = "cpu";
|
||||
operating-points-v2 = <&dnv_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
|
||||
i-cache-size = <0x20000>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -1967,6 +1969,8 @@
|
||||
denver_1: cpu@1 {
|
||||
compatible = "nvidia,tegra186-denver";
|
||||
device_type = "cpu";
|
||||
operating-points-v2 = <&dnv_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
|
||||
i-cache-size = <0x20000>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -1980,6 +1984,8 @@
|
||||
ca57_0: cpu@2 {
|
||||
compatible = "arm,cortex-a57";
|
||||
device_type = "cpu";
|
||||
operating-points-v2 = <&a57_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
|
||||
i-cache-size = <0xC000>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <256>;
|
||||
@@ -1993,6 +1999,8 @@
|
||||
ca57_1: cpu@3 {
|
||||
compatible = "arm,cortex-a57";
|
||||
device_type = "cpu";
|
||||
operating-points-v2 = <&a57_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
|
||||
i-cache-size = <0xC000>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <256>;
|
||||
@@ -2006,6 +2014,8 @@
|
||||
ca57_2: cpu@4 {
|
||||
compatible = "arm,cortex-a57";
|
||||
device_type = "cpu";
|
||||
operating-points-v2 = <&a57_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
|
||||
i-cache-size = <0xC000>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <256>;
|
||||
@@ -2019,6 +2029,8 @@
|
||||
ca57_3: cpu@5 {
|
||||
compatible = "arm,cortex-a57";
|
||||
device_type = "cpu";
|
||||
operating-points-v2 = <&a57_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
|
||||
i-cache-size = <0xC000>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <256>;
|
||||
@@ -2193,4 +2205,309 @@
|
||||
interrupt-parent = <&gic>;
|
||||
always-on;
|
||||
};
|
||||
|
||||
dnv_opp_tbl: opp-table-cluster0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-998400000 {
|
||||
opp-hz = /bits/ 64 <998400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1036800000 {
|
||||
opp-hz = /bits/ 64 <1036800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1075200000 {
|
||||
opp-hz = /bits/ 64 <1075200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1152000000 {
|
||||
opp-hz = /bits/ 64 <1152000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1190400000 {
|
||||
opp-hz = /bits/ 64 <1190400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1228800000 {
|
||||
opp-hz = /bits/ 64 <1228800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1267200000 {
|
||||
opp-hz = /bits/ 64 <1267200000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1305600000 {
|
||||
opp-hz = /bits/ 64 <1305600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1344000000 {
|
||||
opp-hz = /bits/ 64 <1344000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1382400000 {
|
||||
opp-hz = /bits/ 64 <1382400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1420800000 {
|
||||
opp-hz = /bits/ 64 <1420800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1459200000 {
|
||||
opp-hz = /bits/ 64 <1459200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1497600000 {
|
||||
opp-hz = /bits/ 64 <1497600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1536000000 {
|
||||
opp-hz = /bits/ 64 <1536000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1574400000 {
|
||||
opp-hz = /bits/ 64 <1574400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1612800000 {
|
||||
opp-hz = /bits/ 64 <1612800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1651200000 {
|
||||
opp-hz = /bits/ 64 <1651200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1689600000 {
|
||||
opp-hz = /bits/ 64 <1689600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1728000000 {
|
||||
opp-hz = /bits/ 64 <1728000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1766400000 {
|
||||
opp-hz = /bits/ 64 <1766400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1804800000 {
|
||||
opp-hz = /bits/ 64 <1804800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1843200000 {
|
||||
opp-hz = /bits/ 64 <1843200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1881600000 {
|
||||
opp-hz = /bits/ 64 <1881600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1920000000 {
|
||||
opp-hz = /bits/ 64 <1920000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1958400000 {
|
||||
opp-hz = /bits/ 64 <1958400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1996800000 {
|
||||
opp-hz = /bits/ 64 <1996800000>;
|
||||
opp-peak-kBps = <3732000>;
|
||||
};
|
||||
|
||||
opp-2035200000 {
|
||||
opp-hz = /bits/ 64 <2035200000>;
|
||||
opp-peak-kBps = <3732000>;
|
||||
};
|
||||
};
|
||||
|
||||
a57_opp_tbl: opp-table-cluster1 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-883200000 {
|
||||
opp-hz = /bits/ 64 <883200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-921600000 {
|
||||
opp-hz = /bits/ 64 <921600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-960000000 {
|
||||
opp-hz = /bits/ 64 <960000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-998400000 {
|
||||
opp-hz = /bits/ 64 <998400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1036800000 {
|
||||
opp-hz = /bits/ 64 <1036800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1075200000 {
|
||||
opp-hz = /bits/ 64 <1075200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1152000000 {
|
||||
opp-hz = /bits/ 64 <1152000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1190400000 {
|
||||
opp-hz = /bits/ 64 <1190400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1228800000 {
|
||||
opp-hz = /bits/ 64 <1228800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1267200000 {
|
||||
opp-hz = /bits/ 64 <1267200000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1305600000 {
|
||||
opp-hz = /bits/ 64 <1305600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1344000000 {
|
||||
opp-hz = /bits/ 64 <1344000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1382400000 {
|
||||
opp-hz = /bits/ 64 <1382400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1420800000 {
|
||||
opp-hz = /bits/ 64 <1420800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1459200000 {
|
||||
opp-hz = /bits/ 64 <1459200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1497600000 {
|
||||
opp-hz = /bits/ 64 <1497600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1536000000 {
|
||||
opp-hz = /bits/ 64 <1536000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1574400000 {
|
||||
opp-hz = /bits/ 64 <1574400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1612800000 {
|
||||
opp-hz = /bits/ 64 <1612800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1651200000 {
|
||||
opp-hz = /bits/ 64 <1651200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1689600000 {
|
||||
opp-hz = /bits/ 64 <1689600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1728000000 {
|
||||
opp-hz = /bits/ 64 <1728000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1766400000 {
|
||||
opp-hz = /bits/ 64 <1766400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1804800000 {
|
||||
opp-hz = /bits/ 64 <1804800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1843200000 {
|
||||
opp-hz = /bits/ 64 <1843200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1881600000 {
|
||||
opp-hz = /bits/ 64 <1881600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1920000000 {
|
||||
opp-hz = /bits/ 64 <1920000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1958400000 {
|
||||
opp-hz = /bits/ 64 <1958400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1996800000 {
|
||||
opp-hz = /bits/ 64 <1996800000>;
|
||||
opp-peak-kBps = <3732000>;
|
||||
};
|
||||
|
||||
opp-2035200000 {
|
||||
opp-hz = /bits/ 64 <2035200000>;
|
||||
opp-peak-kBps = <3732000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1722,7 +1722,7 @@
|
||||
nvidia,apbmisc = <&apbmisc>;
|
||||
};
|
||||
|
||||
iommu@10000000 {
|
||||
smmu_iso: iommu@10000000 {
|
||||
compatible = "nvidia,tegra194-smmu", "nvidia,smmu-500";
|
||||
reg = <0x0 0x10000000 0x0 0x800000>;
|
||||
interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
|
||||
@@ -1795,7 +1795,7 @@
|
||||
#iommu-cells = <1>;
|
||||
|
||||
nvidia,memory-controller = <&mc>;
|
||||
status = "disabled";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
smmu: iommu@12000000 {
|
||||
@@ -1962,6 +1962,7 @@
|
||||
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
|
||||
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
|
||||
interconnect-names = "dma-mem", "read-1";
|
||||
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
|
||||
|
||||
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
|
||||
nvidia,head = <0>;
|
||||
@@ -1980,6 +1981,7 @@
|
||||
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
|
||||
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
|
||||
interconnect-names = "dma-mem", "read-1";
|
||||
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
|
||||
|
||||
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
|
||||
nvidia,head = <1>;
|
||||
@@ -1998,6 +2000,7 @@
|
||||
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
|
||||
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
|
||||
interconnect-names = "dma-mem", "read-1";
|
||||
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
|
||||
|
||||
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
|
||||
nvidia,head = <2>;
|
||||
@@ -2016,6 +2019,7 @@
|
||||
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
|
||||
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
|
||||
interconnect-names = "dma-mem", "read-1";
|
||||
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
|
||||
|
||||
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
|
||||
nvidia,head = <3>;
|
||||
@@ -2877,6 +2881,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x000>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl0_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -2891,6 +2897,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x001>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl0_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -2905,6 +2913,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x100>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl1_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -2919,6 +2929,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x101>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl1_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -2933,6 +2945,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x200>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl2_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -2947,6 +2961,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x201>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl2_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -2961,6 +2977,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x300>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl3_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER3 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -2975,6 +2993,8 @@
|
||||
device_type = "cpu";
|
||||
reg = <0x301>;
|
||||
enable-method = "psci";
|
||||
operating-points-v2 = <&cl3_opp_tbl>;
|
||||
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER3 &emc>;
|
||||
i-cache-size = <131072>;
|
||||
i-cache-line-size = <64>;
|
||||
i-cache-sets = <512>;
|
||||
@@ -3167,4 +3187,624 @@
|
||||
interrupt-parent = <&gic>;
|
||||
always-on;
|
||||
};
|
||||
|
||||
cl0_opp_tbl: opp-table-cluster0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-115200000 {
|
||||
opp-hz = /bits/ 64 <115200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-192000000 {
|
||||
opp-hz = /bits/ 64 <192000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-268800000 {
|
||||
opp-hz = /bits/ 64 <268800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-345600000 {
|
||||
opp-hz = /bits/ 64 <345600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-422400000 {
|
||||
opp-hz = /bits/ 64 <422400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-499200000 {
|
||||
opp-hz = /bits/ 64 <499200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-576000000 {
|
||||
opp-hz = /bits/ 64 <576000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-652800000 {
|
||||
opp-hz = /bits/ 64 <652800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-729600000 {
|
||||
opp-hz = /bits/ 64 <729600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-806400000 {
|
||||
opp-hz = /bits/ 64 <806400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-883200000 {
|
||||
opp-hz = /bits/ 64 <883200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-960000000 {
|
||||
opp-hz = /bits/ 64 <960000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1036800000 {
|
||||
opp-hz = /bits/ 64 <1036800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1190400000 {
|
||||
opp-hz = /bits/ 64 <1190400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1267200000 {
|
||||
opp-hz = /bits/ 64 <1267200000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1344000000 {
|
||||
opp-hz = /bits/ 64 <1344000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1420800000 {
|
||||
opp-hz = /bits/ 64 <1420800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1497600000 {
|
||||
opp-hz = /bits/ 64 <1497600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1574400000 {
|
||||
opp-hz = /bits/ 64 <1574400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1651200000 {
|
||||
opp-hz = /bits/ 64 <1651200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1728000000 {
|
||||
opp-hz = /bits/ 64 <1728000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1804800000 {
|
||||
opp-hz = /bits/ 64 <1804800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1881600000 {
|
||||
opp-hz = /bits/ 64 <1881600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1907200000 {
|
||||
opp-hz = /bits/ 64 <1907200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1958400000 {
|
||||
opp-hz = /bits/ 64 <1958400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2035200000 {
|
||||
opp-hz = /bits/ 64 <2035200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2112000000 {
|
||||
opp-hz = /bits/ 64 <2112000000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2188800000 {
|
||||
opp-hz = /bits/ 64 <2188800000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2265600000 {
|
||||
opp-hz = /bits/ 64 <2265600000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
};
|
||||
|
||||
cl1_opp_tbl: opp-table-cluster1 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-115200000 {
|
||||
opp-hz = /bits/ 64 <115200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-192000000 {
|
||||
opp-hz = /bits/ 64 <192000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-268800000 {
|
||||
opp-hz = /bits/ 64 <268800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-345600000 {
|
||||
opp-hz = /bits/ 64 <345600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-422400000 {
|
||||
opp-hz = /bits/ 64 <422400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-499200000 {
|
||||
opp-hz = /bits/ 64 <499200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-576000000 {
|
||||
opp-hz = /bits/ 64 <576000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-652800000 {
|
||||
opp-hz = /bits/ 64 <652800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-729600000 {
|
||||
opp-hz = /bits/ 64 <729600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-806400000 {
|
||||
opp-hz = /bits/ 64 <806400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-883200000 {
|
||||
opp-hz = /bits/ 64 <883200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-960000000 {
|
||||
opp-hz = /bits/ 64 <960000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1036800000 {
|
||||
opp-hz = /bits/ 64 <1036800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1190400000 {
|
||||
opp-hz = /bits/ 64 <1190400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1267200000 {
|
||||
opp-hz = /bits/ 64 <1267200000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1344000000 {
|
||||
opp-hz = /bits/ 64 <1344000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1420800000 {
|
||||
opp-hz = /bits/ 64 <1420800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1497600000 {
|
||||
opp-hz = /bits/ 64 <1497600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1574400000 {
|
||||
opp-hz = /bits/ 64 <1574400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1651200000 {
|
||||
opp-hz = /bits/ 64 <1651200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1728000000 {
|
||||
opp-hz = /bits/ 64 <1728000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1804800000 {
|
||||
opp-hz = /bits/ 64 <1804800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1881600000 {
|
||||
opp-hz = /bits/ 64 <1881600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1907200000 {
|
||||
opp-hz = /bits/ 64 <1907200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1958400000 {
|
||||
opp-hz = /bits/ 64 <1958400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2035200000 {
|
||||
opp-hz = /bits/ 64 <2035200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2112000000 {
|
||||
opp-hz = /bits/ 64 <2112000000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2188800000 {
|
||||
opp-hz = /bits/ 64 <2188800000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2265600000 {
|
||||
opp-hz = /bits/ 64 <2265600000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
};
|
||||
|
||||
cl2_opp_tbl: opp-table-cluster2 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-115200000 {
|
||||
opp-hz = /bits/ 64 <115200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-192000000 {
|
||||
opp-hz = /bits/ 64 <192000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-268800000 {
|
||||
opp-hz = /bits/ 64 <268800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-345600000 {
|
||||
opp-hz = /bits/ 64 <345600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-422400000 {
|
||||
opp-hz = /bits/ 64 <422400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-499200000 {
|
||||
opp-hz = /bits/ 64 <499200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-576000000 {
|
||||
opp-hz = /bits/ 64 <576000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-652800000 {
|
||||
opp-hz = /bits/ 64 <652800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-729600000 {
|
||||
opp-hz = /bits/ 64 <729600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-806400000 {
|
||||
opp-hz = /bits/ 64 <806400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-883200000 {
|
||||
opp-hz = /bits/ 64 <883200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-960000000 {
|
||||
opp-hz = /bits/ 64 <960000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1036800000 {
|
||||
opp-hz = /bits/ 64 <1036800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1190400000 {
|
||||
opp-hz = /bits/ 64 <1190400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1267200000 {
|
||||
opp-hz = /bits/ 64 <1267200000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1344000000 {
|
||||
opp-hz = /bits/ 64 <1344000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1420800000 {
|
||||
opp-hz = /bits/ 64 <1420800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1497600000 {
|
||||
opp-hz = /bits/ 64 <1497600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1574400000 {
|
||||
opp-hz = /bits/ 64 <1574400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1651200000 {
|
||||
opp-hz = /bits/ 64 <1651200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1728000000 {
|
||||
opp-hz = /bits/ 64 <1728000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1804800000 {
|
||||
opp-hz = /bits/ 64 <1804800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1881600000 {
|
||||
opp-hz = /bits/ 64 <1881600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1907200000 {
|
||||
opp-hz = /bits/ 64 <1907200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1958400000 {
|
||||
opp-hz = /bits/ 64 <1958400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2035200000 {
|
||||
opp-hz = /bits/ 64 <2035200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2112000000 {
|
||||
opp-hz = /bits/ 64 <2112000000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2188800000 {
|
||||
opp-hz = /bits/ 64 <2188800000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2265600000 {
|
||||
opp-hz = /bits/ 64 <2265600000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
};
|
||||
|
||||
cl3_opp_tbl: opp-table-cluster3 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-115200000 {
|
||||
opp-hz = /bits/ 64 <115200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-192000000 {
|
||||
opp-hz = /bits/ 64 <192000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-268800000 {
|
||||
opp-hz = /bits/ 64 <268800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-345600000 {
|
||||
opp-hz = /bits/ 64 <345600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-422400000 {
|
||||
opp-hz = /bits/ 64 <422400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-499200000 {
|
||||
opp-hz = /bits/ 64 <499200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-576000000 {
|
||||
opp-hz = /bits/ 64 <576000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-652800000 {
|
||||
opp-hz = /bits/ 64 <652800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-729600000 {
|
||||
opp-hz = /bits/ 64 <729600000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-806400000 {
|
||||
opp-hz = /bits/ 64 <806400000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-883200000 {
|
||||
opp-hz = /bits/ 64 <883200000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-960000000 {
|
||||
opp-hz = /bits/ 64 <960000000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1036800000 {
|
||||
opp-hz = /bits/ 64 <1036800000>;
|
||||
opp-peak-kBps = <816000>;
|
||||
};
|
||||
|
||||
opp-1113600000 {
|
||||
opp-hz = /bits/ 64 <1113600000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1190400000 {
|
||||
opp-hz = /bits/ 64 <1190400000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1267200000 {
|
||||
opp-hz = /bits/ 64 <1267200000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1344000000 {
|
||||
opp-hz = /bits/ 64 <1344000000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1420800000 {
|
||||
opp-hz = /bits/ 64 <1420800000>;
|
||||
opp-peak-kBps = <1600000>;
|
||||
};
|
||||
|
||||
opp-1497600000 {
|
||||
opp-hz = /bits/ 64 <1497600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1574400000 {
|
||||
opp-hz = /bits/ 64 <1574400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1651200000 {
|
||||
opp-hz = /bits/ 64 <1651200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1728000000 {
|
||||
opp-hz = /bits/ 64 <1728000000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1804800000 {
|
||||
opp-hz = /bits/ 64 <1804800000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1881600000 {
|
||||
opp-hz = /bits/ 64 <1881600000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1907200000 {
|
||||
opp-hz = /bits/ 64 <1907200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-1958400000 {
|
||||
opp-hz = /bits/ 64 <1958400000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2035200000 {
|
||||
opp-hz = /bits/ 64 <2035200000>;
|
||||
opp-peak-kBps = <3200000>;
|
||||
};
|
||||
|
||||
opp-2112000000 {
|
||||
opp-hz = /bits/ 64 <2112000000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2188800000 {
|
||||
opp-hz = /bits/ 64 <2188800000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
|
||||
opp-2265600000 {
|
||||
opp-hz = /bits/ 64 <2265600000>;
|
||||
opp-peak-kBps = <4266000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -2,6 +2,7 @@
|
||||
#include <dt-bindings/mfd/max77620.h>
|
||||
|
||||
#include "tegra210.dtsi"
|
||||
#include "tegra210-p2180-emc.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Jetson TX1";
|
||||
|
||||
@@ -16,16 +16,16 @@
|
||||
vddio-pex-ctl-supply = <&vdd_1v8>;
|
||||
|
||||
pci@1,0 {
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>;
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
|
||||
phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pci@2,0 {
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
|
||||
phy-names = "pcie-0";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <dt-bindings/mfd/max77620.h>
|
||||
|
||||
#include "tegra210.dtsi"
|
||||
|
||||
/ {
|
||||
@@ -6,8 +8,10 @@
|
||||
compatible = "nvidia,p2530", "nvidia,tegra210";
|
||||
|
||||
aliases {
|
||||
rtc0 = "/i2c@7000d000/pmic@3c";
|
||||
rtc1 = "/rtc@7000e000";
|
||||
serial0 = &uarta;
|
||||
serial3 = &uartd;
|
||||
};
|
||||
|
||||
chosen {
|
||||
@@ -19,6 +23,27 @@
|
||||
reg = <0x0 0x80000000 0x0 0xc0000000>;
|
||||
};
|
||||
|
||||
gpu@57000000 {
|
||||
vdd-supply = <&vdd_gpu>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pinmux@700008d4 {
|
||||
dvfs_pwm_active_state: pinmux-dvfs-pwm-active {
|
||||
dvfs_pwm_pbb1 {
|
||||
nvidia,pins = "dvfs_pwm_pbb1";
|
||||
nvidia,tristate = <TEGRA_PIN_DISABLE>;
|
||||
};
|
||||
};
|
||||
|
||||
dvfs_pwm_inactive_state: pinmux-dvfs-pwm-inactive {
|
||||
dvfs_pwm_pbb1 {
|
||||
nvidia,pins = "dvfs_pwm_pbb1";
|
||||
nvidia,tristate = <TEGRA_PIN_ENABLE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* debug port */
|
||||
serial@70006000 {
|
||||
/delete-property/ dmas;
|
||||
@@ -26,13 +51,279 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
/delete-property/ reg-shift;
|
||||
status = "okay";
|
||||
compatible = "nvidia,tegra30-hsuart";
|
||||
reset-names = "serial";
|
||||
|
||||
bluetooth {
|
||||
compatible = "brcm,bcm43540-bt";
|
||||
device-wakeup-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>;
|
||||
shutdown-gpios = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(H, 5) IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-names = "host-wakeup";
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
status = "okay";
|
||||
clock-frequency = <400000>;
|
||||
|
||||
pmic: pmic@3c {
|
||||
compatible = "maxim,max77620";
|
||||
reg = <0x3c>;
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&max77620_default>;
|
||||
|
||||
fps {
|
||||
fps0 {
|
||||
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
|
||||
maxim,shutdown-fps-time-period-us = <5120>;
|
||||
};
|
||||
|
||||
fps1 {
|
||||
maxim,device-state-on-disabled-event = <MAX77620_FPS_INACTIVE_STATE_SLEEP>;
|
||||
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
|
||||
maxim,shutdown-fps-time-period-us = <5120>;
|
||||
};
|
||||
|
||||
fps2 {
|
||||
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
|
||||
};
|
||||
};
|
||||
|
||||
max77620_default: pinmux {
|
||||
gpio0 {
|
||||
pins = "gpio0";
|
||||
function = "gpio";
|
||||
};
|
||||
|
||||
gpio1 {
|
||||
pins = "gpio1";
|
||||
function = "fps-out";
|
||||
drive-push-pull = <1>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
maxim,active-fps-power-up-slot = <7>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
};
|
||||
|
||||
gpio2_3 {
|
||||
pins = "gpio2", "gpio3";
|
||||
function = "fps-out";
|
||||
drive-open-drain = <1>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
};
|
||||
|
||||
gpio4 {
|
||||
pins = "gpio4";
|
||||
function = "32k-out1";
|
||||
};
|
||||
|
||||
gpio5_6_7 {
|
||||
pins = "gpio5", "gpio6", "gpio7";
|
||||
function = "gpio";
|
||||
drive-push-pull = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
in-ldo0-1-supply = <&vdd_pre>;
|
||||
in-ldo7-8-supply = <&vdd_pre>;
|
||||
|
||||
vdd_soc: sd0 {
|
||||
regulator-name = "VDD_SOC";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-enable-ramp-delay = <146>;
|
||||
regulator-ramp-delay = <9100>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
|
||||
};
|
||||
|
||||
vdd_ddr: sd1 {
|
||||
regulator-name = "VDD_DDR_1V1_PMIC";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-enable-ramp-delay = <130>;
|
||||
regulator-ramp-delay = <9100>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
};
|
||||
|
||||
vdd_pre: sd2 {
|
||||
regulator-name = "VDD_PRE_REG_1V35";
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
|
||||
regulator-enable-ramp-delay = <176>;
|
||||
regulator-ramp-delay = <7900>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
};
|
||||
|
||||
vdd_1v8: sd3 {
|
||||
regulator-name = "VDD_1V8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-enable-ramp-delay = <242>;
|
||||
regulator-ramp-delay = <7700>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
};
|
||||
|
||||
vdd_sys_1v2: ldo0 {
|
||||
regulator-name = "AVDD_SYS_1V2";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-enable-ramp-delay = <26>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
};
|
||||
|
||||
vdd_pex_1v05: ldo1 {
|
||||
regulator-name = "VDD_PEX_1V05";
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1050000>;
|
||||
|
||||
regulator-enable-ramp-delay = <22>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
|
||||
};
|
||||
|
||||
vddio_sdmmc: ldo2 {
|
||||
regulator-name = "VDDIO_SDMMC";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
};
|
||||
|
||||
vdd_cam_hv: ldo3 {
|
||||
regulator-name = "VDD_CAM_HV";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
};
|
||||
|
||||
vdd_rtc: ldo4 {
|
||||
regulator-name = "VDD_RTC";
|
||||
regulator-min-microvolt = <850000>;
|
||||
regulator-max-microvolt = <850000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-enable-ramp-delay = <22>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
};
|
||||
|
||||
vdd_ts_hv: ldo5 {
|
||||
regulator-name = "VDD_TS_HV";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
regulator-enable-ramp-delay = <62>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
};
|
||||
|
||||
vdd_ts: ldo6 {
|
||||
regulator-name = "VDD_TS_1V8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-enable-ramp-delay = <36>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
};
|
||||
|
||||
avdd_1v05_pll: ldo7 {
|
||||
regulator-name = "AVDD_1V05_PLL";
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1050000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-enable-ramp-delay = <24>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
|
||||
};
|
||||
|
||||
avdd_1v05: ldo8 {
|
||||
regulator-name = "AVDD_SATA_HDMI_DP_1V05";
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1050000>;
|
||||
|
||||
regulator-enable-ramp-delay = <22>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pmc@7000e400 {
|
||||
nvidia,invert-interrupt;
|
||||
nvidia,suspend-mode = <0>;
|
||||
nvidia,cpu-pwr-good-time = <0>;
|
||||
nvidia,cpu-pwr-off-time = <0>;
|
||||
nvidia,core-pwr-good-time = <4587 3876>;
|
||||
nvidia,core-pwr-off-time = <39065>;
|
||||
nvidia,core-power-req-active-high;
|
||||
nvidia,sys-clock-req-active-high;
|
||||
};
|
||||
|
||||
|
||||
mmc@700b0200 {
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
non-removable;
|
||||
power-gpios = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
|
||||
vqmmc-supply = <&vdd_1v8>;
|
||||
vmmc-supply = <&vdd_3v3_sys>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
wifi@1 {
|
||||
compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac";
|
||||
reg = <1>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(H, 2) IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "host-wake";
|
||||
};
|
||||
};
|
||||
|
||||
/* eMMC */
|
||||
@@ -40,6 +331,29 @@
|
||||
status = "okay";
|
||||
bus-width = <8>;
|
||||
non-removable;
|
||||
vqmmc-supply = <&vdd_1v8>;
|
||||
vmmc-supply = <&vdd_3v3_sys>;
|
||||
};
|
||||
|
||||
clock@70110000 {
|
||||
status = "okay";
|
||||
|
||||
nvidia,cf = <6>;
|
||||
nvidia,ci = <0>;
|
||||
nvidia,cg = <2>;
|
||||
nvidia,droop-ctrl = <0x00000f00>;
|
||||
nvidia,force-mode = <1>;
|
||||
nvidia,sample-rate = <25000>;
|
||||
|
||||
nvidia,pwm-min-microvolts = <708000>;
|
||||
nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */
|
||||
nvidia,pwm-to-pmic;
|
||||
nvidia,pwm-tristate-microvolts = <1000000>;
|
||||
nvidia,pwm-voltage-step-microvolts = <19200>;
|
||||
|
||||
pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
|
||||
pinctrl-0 = <&dvfs_pwm_active_state>;
|
||||
pinctrl-1 = <&dvfs_pwm_inactive_state>;
|
||||
};
|
||||
|
||||
clk32k_in: clock-32k {
|
||||
@@ -64,10 +378,50 @@
|
||||
cpu@3 {
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
idle-states {
|
||||
cpu-sleep {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
psci {
|
||||
compatible = "arm,psci-0.2";
|
||||
method = "smc";
|
||||
};
|
||||
|
||||
vdd_3v3_sys: regulator-vdd-3v3-sys {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VDD_3V3_SYS";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
gpio = <&pmic 3 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
vdd_3v3_sd: regulator-vdd-3v3-sd {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VDD_3V3_SD";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpio = <&gpio TEGRA_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
vin-supply = <&vdd_3v3_sys>;
|
||||
|
||||
regulator-enable-ramp-delay = <472>;
|
||||
};
|
||||
|
||||
vdd_gpu: regulator-vdd-gpu {
|
||||
compatible = "pwm-regulator";
|
||||
pwms = <&pwm 1 8000>;
|
||||
regulator-name = "VDD_GPU";
|
||||
regulator-min-microvolt = <710000>;
|
||||
regulator-max-microvolt = <1320000>;
|
||||
enable-gpios = <&pmic 6 GPIO_ACTIVE_HIGH>;
|
||||
regulator-ramp-delay = <160>;
|
||||
regulator-enable-ramp-delay = <2000>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "tegra210-p2571.dts"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Shield TV 2015";
|
||||
compatible = "nvidia,p2571-0930", "nvidia,tegra210";
|
||||
|
||||
hda@70030000 {
|
||||
nvidia,model = "NVIDIA SHIELD TV APE";
|
||||
};
|
||||
|
||||
sound {
|
||||
label = "NVIDIA SHIELD TV APE";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "tegra210-p2571-0930.dts"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Shield TV Pro 2015";
|
||||
compatible = "nvidia,p2571-0932", "nvidia,p2571-0930", "nvidia,tegra210";
|
||||
|
||||
sata@70020000 {
|
||||
status = "okay";
|
||||
phys = <&{/padctl@7009f000/pads/sata/lanes/sata-0}>;
|
||||
};
|
||||
|
||||
mmc@700b0600 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
@@ -8,6 +8,24 @@
|
||||
model = "NVIDIA Tegra210 P2571 reference design";
|
||||
compatible = "nvidia,p2571", "nvidia,tegra210";
|
||||
|
||||
host1x@50000000 {
|
||||
dpaux@54040000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sor@54580000 {
|
||||
status = "okay";
|
||||
|
||||
avdd-io-hdmi-dp-supply = <&avdd_1v05>;
|
||||
vdd-hdmi-dp-pll-supply = <&vdd_1v8>;
|
||||
hdmi-supply = <&vdd_hdmi>;
|
||||
|
||||
nvidia,ddc-i2c-bus = <&hdmi_ddc>;
|
||||
nvidia,hpd-gpio = <&gpio TEGRA_GPIO(CC, 1)
|
||||
GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
pinmux: pinmux@700008d4 {
|
||||
pinctrl-names = "boot";
|
||||
pinctrl-0 = <&state_boot>;
|
||||
@@ -1300,4 +1318,329 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pwm@7000a000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* HDMI DDC */
|
||||
hdmi_ddc: i2c@7000c700 {
|
||||
status = "okay";
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
||||
hda@70030000 {
|
||||
status = "okay";
|
||||
nvidia,model = "NVIDIA P2571 HDA";
|
||||
};
|
||||
|
||||
usb@70090000 {
|
||||
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
|
||||
<&{/padctl@7009f000/pads/usb2/lanes/usb2-1}>,
|
||||
<&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
|
||||
<&{/padctl@7009f000/pads/usb2/lanes/usb2-3}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
|
||||
phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", "usb3-0",
|
||||
"usb3-1", "usb3-2";
|
||||
dvddio-pex-supply = <&vdd_pex_1v05>;
|
||||
hvddio-pex-supply = <&vdd_1v8>;
|
||||
avdd-usb-supply = <&vdd_3v3_sys>;
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
padctl@7009f000 {
|
||||
status = "okay";
|
||||
|
||||
avdd-pll-utmip-supply = <&vdd_1v8>;
|
||||
avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
|
||||
dvdd-pex-pll-supply = <&vdd_pex_1v05>;
|
||||
hvdd-pex-pll-e-supply = <&vdd_1v8>;
|
||||
|
||||
pads {
|
||||
usb2 {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
micro_b: usb2-0 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-3 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pcie {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
pcie-0 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-1 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-2 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-3 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-4 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-5 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-6 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sata {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
sata-0 {
|
||||
nvidia,function = "sata";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
usb2-0 {
|
||||
status = "okay";
|
||||
vbus-supply = <&vdd_sys_mux>;
|
||||
usb-role-switch;
|
||||
mode = "otg";
|
||||
|
||||
connector {
|
||||
compatible = "gpio-usb-b-connector",
|
||||
"usb-b-connector";
|
||||
label = "micro-USB";
|
||||
type = "micro";
|
||||
vbus-gpios = <&gpio TEGRA_GPIO(Z, 0)
|
||||
GPIO_ACTIVE_LOW>;
|
||||
id-gpios = <&pmic 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
usb2-1 {
|
||||
status = "okay";
|
||||
vbus-supply = <&vdd_usb_vbus0>;
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
status = "okay";
|
||||
vbus-supply = <&vdd_usb_vbus1>;
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
usb2-3 {
|
||||
status = "okay";
|
||||
vbus-supply = <&vdd_usb_vbus2>;
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
usb3-0 {
|
||||
nvidia,usb2-companion = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb3-1 {
|
||||
nvidia,usb2-companion = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb3-2 {
|
||||
nvidia,usb2-companion = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* MMC/SD */
|
||||
mmc@700b0000 {
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
|
||||
cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
|
||||
disable-wp;
|
||||
|
||||
vqmmc-supply = <&vddio_sdmmc>;
|
||||
vmmc-supply = <&vdd_3v3_sd>;
|
||||
};
|
||||
|
||||
usb@700d0000 {
|
||||
status = "okay";
|
||||
phys = <µ_b>;
|
||||
phy-names = "usb2-0";
|
||||
avddio-usb-supply = <&vdd_3v3_sys>;
|
||||
hvdd-usb-supply = <&vdd_1v8>;
|
||||
};
|
||||
|
||||
fan: pwm-fan {
|
||||
compatible = "pwm-fan";
|
||||
pwms = <&pwm 3 45334>;
|
||||
fan-supply = <&vdd_fan>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(G, 0) IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
cooling-levels = <0 64 128 255>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
vdd_sys_mux: regulator-vdd-sys-mux {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VDD_SYS_MUX";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
vdd_5v0_sys: regulator-vdd-5v0-sys {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VDD_5V0_SYS";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
vin-supply = <&vdd_sys_mux>;
|
||||
};
|
||||
|
||||
vdd_hdmi: regulator-vdd-hdmi {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VDD_HDMI_5V0";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
gpio = <&gpio TEGRA_GPIO(CC, 7) GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
vin-supply = <&vdd_5v0_sys>;
|
||||
};
|
||||
|
||||
vdd_usb_vbus0: regulator-vdd-usb-vbus0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "USB_VBUS_EN0";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
vdd_usb_vbus1: regulator-vdd-usb-vbus1 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "USB_VBUS_EN1";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
gpio = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
vdd_usb_vbus2: regulator-vdd-usb-vbus2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "USB_VBUS_EN2";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
gpio = <&gpio TEGRA_GPIO(D, 4) GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
vdd_fan: regulator-vdd-fan {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "VDD_FAN";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
gpio = <&gpio TEGRA_GPIO(E, 4) GPIO_ACTIVE_LOW>;
|
||||
enable-active-high;
|
||||
|
||||
regulator-enable-ramp-delay = <284>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu-thermal {
|
||||
trips {
|
||||
cpu_trip_critical: critical {
|
||||
temperature = <96500>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
|
||||
cpu_trip_hot: hot {
|
||||
temperature = <70000>;
|
||||
hysteresis = <2000>;
|
||||
type = "hot";
|
||||
};
|
||||
|
||||
cpu_trip_active: active {
|
||||
temperature = <50000>;
|
||||
hysteresis = <2000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
cpu_trip_passive: passive {
|
||||
temperature = <30000>;
|
||||
hysteresis = <2000>;
|
||||
type = "passive";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
cooling-device = <&fan 3 3>;
|
||||
trip = <&cpu_trip_critical>;
|
||||
};
|
||||
|
||||
map1 {
|
||||
cooling-device = <&fan 2 2>;
|
||||
trip = <&cpu_trip_hot>;
|
||||
};
|
||||
|
||||
map2 {
|
||||
cooling-device = <&fan 1 1>;
|
||||
trip = <&cpu_trip_active>;
|
||||
};
|
||||
|
||||
map3 {
|
||||
cooling-device = <&fan 0 0>;
|
||||
trip = <&cpu_trip_passive>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,9 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "tegra210.dtsi"
|
||||
#include "tegra210-p2894.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Shield TV";
|
||||
compatible = "nvidia,p2894-0050-a08", "nvidia,darcy", "nvidia,tegra210";
|
||||
|
||||
mmc@700b0200 {
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
non-removable;
|
||||
power-gpios = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
|
||||
vqmmc-supply = <&max77620_sd3>;
|
||||
vmmc-supply = <&vdd_3v3>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
wifi@1 {
|
||||
compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac";
|
||||
reg = <1>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(H, 2) IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "host-wake";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -4,11 +4,11 @@
|
||||
#include <dt-bindings/input/gpio-keys.h>
|
||||
#include <dt-bindings/mfd/max77620.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
||||
#include "tegra210.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
serial0 = &uarta;
|
||||
serial3 = &uartd;
|
||||
};
|
||||
|
||||
chosen {
|
||||
@@ -21,6 +21,43 @@
|
||||
reg = <0x0 0x80000000 0x0 0xc0000000>;
|
||||
};
|
||||
|
||||
pcie@1003000 {
|
||||
status = "okay";
|
||||
|
||||
hvddio-pex-supply = <&max77620_sd3>;
|
||||
dvddio-pex-supply = <&max77620_ldo1>;
|
||||
vddio-pex-ctl-supply = <&max77620_sd3>;
|
||||
|
||||
pci@2,0 {
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
|
||||
phy-names = "pcie-0";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
host1x@50000000 {
|
||||
dpaux@54040000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sor@54580000 {
|
||||
status = "okay";
|
||||
|
||||
avdd-io-hdmi-dp-supply = <&max77620_ldo8>;
|
||||
vdd-hdmi-dp-pll-supply = <&max77620_sd3>;
|
||||
hdmi-supply = <&vdd_hdmi>;
|
||||
|
||||
nvidia,ddc-i2c-bus = <&hdmi_ddc>;
|
||||
nvidia,hpd-gpio = <&gpio TEGRA_GPIO(CC, 1)
|
||||
GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
gpu@57000000 {
|
||||
vdd-supply = <&vdd_gpu>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pinmux: pinmux@700008d4 {
|
||||
status = "okay";
|
||||
pinctrl-names = "boot";
|
||||
@@ -1318,6 +1355,20 @@
|
||||
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
|
||||
};
|
||||
};
|
||||
|
||||
dvfs_pwm_active_state: pinmux-dvfs-pwm-active {
|
||||
dvfs_pwm_pbb1 {
|
||||
nvidia,pins = "dvfs_pwm_pbb1";
|
||||
nvidia,tristate = <TEGRA_PIN_DISABLE>;
|
||||
};
|
||||
};
|
||||
|
||||
dvfs_pwm_inactive_state: pinmux-dvfs-pwm-inactive {
|
||||
dvfs_pwm_pbb1 {
|
||||
nvidia,pins = "dvfs_pwm_pbb1";
|
||||
nvidia,tristate = <TEGRA_PIN_ENABLE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
@@ -1326,6 +1377,26 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pwm@7000a000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
/delete-property/ reg-shift;
|
||||
status = "okay";
|
||||
compatible = "nvidia,tegra30-hsuart";
|
||||
reset-names = "serial";
|
||||
|
||||
bluetooth {
|
||||
compatible = "brcm,bcm43540-bt";
|
||||
device-wakeup-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>;
|
||||
shutdown-gpios = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(H, 5) IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-names = "host-wakeup";
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
status = "okay";
|
||||
clock-frequency = <400000>;
|
||||
@@ -1570,6 +1641,12 @@
|
||||
};
|
||||
};
|
||||
|
||||
/* HDMI DDC */
|
||||
hdmi_ddc: i2c@7000c700 {
|
||||
status = "okay";
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
||||
pmc@7000e400 {
|
||||
nvidia,invert-interrupt;
|
||||
nvidia,suspend-mode = <0>;
|
||||
@@ -1582,12 +1659,154 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
hda@70030000 {
|
||||
status = "okay";
|
||||
nvidia,model = "NVIDIA SHIELD TV HDA";
|
||||
};
|
||||
|
||||
usb@70090000 {
|
||||
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
|
||||
<&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
|
||||
phy-names = "usb2-0", "usb2-2", "usb3-0", "usb3-1";
|
||||
dvddio-pex-supply = <&max77620_ldo1>;
|
||||
hvddio-pex-supply = <&max77620_sd3>;
|
||||
avdd-usb-supply = <&vdd_3v3>;
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
padctl@7009f000 {
|
||||
status = "okay";
|
||||
|
||||
avdd-pll-utmip-supply = <&max77620_sd3>;
|
||||
avdd-pll-uerefe-supply = <&max77620_ldo7>;
|
||||
dvdd-pex-pll-supply = <&max77620_ldo1>;
|
||||
hvdd-pex-pll-e-supply = <&max77620_sd3>;
|
||||
|
||||
pads {
|
||||
usb2 {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
usb2-0 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
nvidia,function = "xusb";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pcie {
|
||||
status = "okay";
|
||||
|
||||
lanes {
|
||||
pcie-0 {
|
||||
nvidia,function = "pcie-x1";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-1 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-2 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-3 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-4 {
|
||||
nvidia,function = "pcie-x4";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-5 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie-6 {
|
||||
nvidia,function = "usb3-ss";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
usb2-0 {
|
||||
status = "okay";
|
||||
vbus-supply = <&usb_vbus1>;
|
||||
usb-role-switch;
|
||||
role-switch-default-mode = "peripheral";
|
||||
mode = "otg";
|
||||
};
|
||||
|
||||
usb2-2 {
|
||||
status = "okay";
|
||||
vbus-supply = <&usb_vbus2>;
|
||||
mode = "host";
|
||||
};
|
||||
|
||||
usb3-0 {
|
||||
nvidia,usb2-companion = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb3-1 {
|
||||
nvidia,usb2-companion = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mmc@700b0600 {
|
||||
bus-width = <8>;
|
||||
non-removable;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@700d0000 {
|
||||
status = "okay";
|
||||
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>;
|
||||
phy-names = "usb2-0", "usb3-0";
|
||||
avddio-usb-supply = <&max77620_ldo1>;
|
||||
hvdd-usb-supply = <&vdd_3v3>;
|
||||
};
|
||||
|
||||
clock@70110000 {
|
||||
status = "okay";
|
||||
|
||||
nvidia,cf = <6>;
|
||||
nvidia,ci = <0>;
|
||||
nvidia,cg = <2>;
|
||||
nvidia,droop-ctrl = <0x00000f00>;
|
||||
nvidia,force-mode = <1>;
|
||||
nvidia,sample-rate = <25000>;
|
||||
|
||||
nvidia,pwm-min-microvolts = <708000>;
|
||||
nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */
|
||||
nvidia,pwm-to-pmic;
|
||||
nvidia,pwm-tristate-microvolts = <1000000>;
|
||||
nvidia,pwm-voltage-step-microvolts = <19200>;
|
||||
|
||||
pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
|
||||
pinctrl-0 = <&dvfs_pwm_active_state>;
|
||||
pinctrl-1 = <&dvfs_pwm_inactive_state>;
|
||||
};
|
||||
|
||||
clk32k_in: clock-32k {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <32768>;
|
||||
@@ -1637,6 +1856,18 @@
|
||||
method = "smc";
|
||||
};
|
||||
|
||||
fan: pwm-fan {
|
||||
compatible = "pwm-fan";
|
||||
pwms = <&pwm 3 65536>;
|
||||
fan-supply = <&vdd_fan>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(G, 0) IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
/* cooling level (0, 1, 2, 3) - pwm inverted */
|
||||
cooling-levels = <255 128 64 0>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
battery_reg: regulator-vdd-ac-bat {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vdd-ac-bat";
|
||||
@@ -1831,4 +2062,68 @@
|
||||
enable-active-high;
|
||||
gpio-open-drain;
|
||||
};
|
||||
|
||||
vdd_gpu: regulator-vdd-gpu {
|
||||
compatible = "pwm-regulator";
|
||||
pwms = <&pwm 1 8000>;
|
||||
regulator-name = "VDD_GPU";
|
||||
regulator-min-microvolt = <710000>;
|
||||
regulator-max-microvolt = <1320000>;
|
||||
enable-gpios = <&pmic 6 GPIO_ACTIVE_HIGH>;
|
||||
regulator-ramp-delay = <80>;
|
||||
regulator-enable-ramp-delay = <2000>;
|
||||
regulator-settling-time-us = <160>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu-thermal {
|
||||
trips {
|
||||
cpu_trip_critical: critical {
|
||||
temperature = <96500>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
|
||||
cpu_trip_hot: hot {
|
||||
temperature = <70000>;
|
||||
hysteresis = <2000>;
|
||||
type = "hot";
|
||||
};
|
||||
|
||||
cpu_trip_active: active {
|
||||
temperature = <50000>;
|
||||
hysteresis = <2000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
cpu_trip_passive: passive {
|
||||
temperature = <30000>;
|
||||
hysteresis = <2000>;
|
||||
type = "passive";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
cooling-device = <&fan 3 3>;
|
||||
trip = <&cpu_trip_critical>;
|
||||
};
|
||||
|
||||
map1 {
|
||||
cooling-device = <&fan 2 2>;
|
||||
trip = <&cpu_trip_hot>;
|
||||
};
|
||||
|
||||
map2 {
|
||||
cooling-device = <&fan 1 1>;
|
||||
trip = <&cpu_trip_active>;
|
||||
};
|
||||
|
||||
map3 {
|
||||
cooling-device = <&fan 0 0>;
|
||||
trip = <&cpu_trip_passive>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1018,6 +1018,21 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
bpmp: bpmp@70016000 {
|
||||
compatible = "nvidia,tegra210-bpmp";
|
||||
reg = <0x0 0x70016000 0x0 0x2000
|
||||
0x0 0x60001000 0x0 0x1000>;
|
||||
status = "disabled";
|
||||
|
||||
interrupts = <GIC_SPI 6 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 4 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "tx", "rx";
|
||||
|
||||
iommus = <&mc TEGRA_SWGROUP_AVPC>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
mc: memory-controller@70019000 {
|
||||
compatible = "nvidia,tegra210-mc";
|
||||
reg = <0x0 0x70019000 0x0 0x1000>;
|
||||
@@ -1028,6 +1043,7 @@
|
||||
|
||||
#iommu-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#interconnect-cells = <1>;
|
||||
};
|
||||
|
||||
emc: external-memory-controller@7001b000 {
|
||||
@@ -1041,6 +1057,7 @@
|
||||
nvidia,memory-controller = <&mc>;
|
||||
operating-points-v2 = <&emc_icc_dvfs_opp_table>;
|
||||
|
||||
#interconnect-cells = <0>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
@@ -1293,11 +1310,9 @@
|
||||
nvidia,pad-autocal-pull-down-offset-sdr104 = <0x0>;
|
||||
nvidia,default-tap = <0x2>;
|
||||
nvidia,default-trim = <0x4>;
|
||||
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_C4_OUT0>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_C4>;
|
||||
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>;
|
||||
assigned-clock-rates = <200000000>, <1000000000>, <1000000000>;
|
||||
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -1360,8 +1375,8 @@
|
||||
nvidia,default-tap = <0x8>;
|
||||
nvidia,default-trim = <0x0>;
|
||||
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_C4_OUT0>;
|
||||
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>;
|
||||
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
nvidia,dqs-trim = <40>;
|
||||
mmc-hs400-1_8v;
|
||||
status = "disabled";
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "tegra210b01.dtsi"
|
||||
#include "tegra210-p2894.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Shield TV Pro 2019";
|
||||
compatible = "nvidia,p2894-2551-b00", "nvidia,darcy", "nvidia,tegra210b01",
|
||||
"nvidia,tegra210";
|
||||
|
||||
pcie@1003000 {
|
||||
pci@1,0 {
|
||||
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>;
|
||||
phy-names = "pcie-0", "pcie-1";
|
||||
status = "okay";
|
||||
|
||||
wifi@0,0 {
|
||||
compatible = "brcm,bcm4356-fmac", "brcm,bcm4329-fmac";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pinmux@700008d4 {
|
||||
pinmux {
|
||||
pex_l0_rst_n_pa0 {
|
||||
nvidia,function = "pe0";
|
||||
nvidia,pull = <TEGRA_PIN_PULL_UP>;
|
||||
nvidia,tristate = <TEGRA_PIN_DISABLE>;
|
||||
};
|
||||
pex_l0_clkreq_n_pa1 {
|
||||
nvidia,pull = <TEGRA_PIN_PULL_UP>;
|
||||
nvidia,io-hv = <TEGRA_PIN_DISABLE>;
|
||||
};
|
||||
pex_wake_n_pa2 {
|
||||
nvidia,pull = <TEGRA_PIN_PULL_UP>;
|
||||
nvidia,tristate = <TEGRA_PIN_ENABLE>;
|
||||
nvidia,io-hv = <TEGRA_PIN_DISABLE>;
|
||||
};
|
||||
wifi_wake_ap_ph2 {
|
||||
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
|
||||
};
|
||||
pz1 {
|
||||
nvidia,pull = <TEGRA_PIN_PULL_UP>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
pmic@3c {
|
||||
regulators {
|
||||
sd2 {
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
usb@70090000 {
|
||||
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
|
||||
<&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
|
||||
phy-names = "usb2-0", "usb2-2", "usb3-0", "usb3-1";
|
||||
dvddio-pex-supply = <&max77620_ldo1>;
|
||||
hvddio-pex-supply = <&max77620_sd3>;
|
||||
avdd-usb-supply = <&vdd_3v3>;
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
padctl@7009f000 {
|
||||
pads {
|
||||
pcie {
|
||||
lanes {
|
||||
pcie-1 {
|
||||
nvidia,function = "usb3-ss";
|
||||
};
|
||||
|
||||
pcie-4 {
|
||||
nvidia,function = "usb3-ss";
|
||||
};
|
||||
|
||||
pcie-6 {
|
||||
/delete-property/ nvidia,function;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
usb@700d0000 {
|
||||
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
|
||||
};
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,142 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "tegra210b01-nx.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Nintendo Switch Lite";
|
||||
compatible = "nvidia,vali", "nintendo,hoag", "nintendo,nx", "nvidia,tegra210b01", "nvidia,tegra210";
|
||||
|
||||
/* Joycon/Fan power (usb) */
|
||||
v_vdd50_b: v-vdd50-b {
|
||||
status = "disabled"; /* Only enabled on Odin/Modin */
|
||||
};
|
||||
|
||||
en_vdd_jcl_chgr: left-joycon-charger {
|
||||
status = "disabled"; /* Only enabled on Odin/Modin/Fric */
|
||||
};
|
||||
|
||||
en_vdd_jcr_chgr: right-joycon-charger {
|
||||
status = "disabled"; /* Only enabled on Odin/Modin/Fric */
|
||||
};
|
||||
|
||||
spi@7000da00 {
|
||||
status = "disabled"; /* Disabled for Vali since Sio uses it */
|
||||
};
|
||||
|
||||
/* Right Joycon */
|
||||
serial@70006040 {
|
||||
status = "disabled";
|
||||
|
||||
joyconr {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
/* Left Joycon / Sio */
|
||||
serial@70006200 {
|
||||
status = "okay";
|
||||
/delete-property/ nvidia,invert-txd;
|
||||
/delete-property/ nvidia,invert-rts;
|
||||
|
||||
joyconl {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sio {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
bm92t: bm92t@18 {
|
||||
status = "disabled";
|
||||
/delete-property/ rohm,dp-signal-toggle-on-resume;
|
||||
rohm,dp-disable;
|
||||
rohm,pd-5v-current-limit-ma = <2000>;
|
||||
rohm,pd-9v-current-limit-ma = <1500>;
|
||||
rohm,pd-12v-current-limit-ma = <1200>;
|
||||
rohm,pd-15v-current-limit-ma = <900>;
|
||||
};
|
||||
|
||||
bq2419x: bq24193@6b {
|
||||
battery_charger: charger {
|
||||
ti,charge-voltage-limit-millivolt = <4320>; /* Adjusted by cell age */
|
||||
ti,fast-charge-current-limit-milliamp = <1664>;
|
||||
ti,temp-range = <0 18 47 58>;
|
||||
ti,charge-thermal-voltage-limit = <4320 4320 4320 4080>; /* Adjusted by cell age */
|
||||
ti,charge-current-limit = <512 640 1664 1664>;
|
||||
};
|
||||
};
|
||||
|
||||
fuel_gauge: fuel-gauge@36 {
|
||||
maxim,over-volt = <4320>; /* Actual: 4370 mV */
|
||||
maxim,kernel-maximum-soc = <100>; /* Adjusted by cell age */
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
pmic_b: pmic@3c {
|
||||
regulators {
|
||||
/* Vali: Powers LDO 2V8 for Sio VDD
|
||||
* Powers LDO 1V8 for I2C1 VDDQ and ALC5639.
|
||||
*/
|
||||
ldo8 {
|
||||
regulator-name = "vdd-i2c1";
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c@546c0000 {
|
||||
bus-pullup-supply = <&battery_reg>;
|
||||
};
|
||||
|
||||
host1x@50000000 {
|
||||
/* tegradc.1: DP */
|
||||
dc@54240000 {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
xusb: usb@70090000 {
|
||||
status = "okay";
|
||||
|
||||
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
|
||||
phy-names = "usb2-0", "usb3-0";
|
||||
|
||||
extcon = <&bm92t 0>;
|
||||
extcon-cable-names = "vbus";
|
||||
|
||||
avdd-usb-supply = <&vdd_3v3>;
|
||||
dvddio-pex-supply = <&max77620_ldo1>;
|
||||
hvddio-pex-supply = <&max77620_sd3>;
|
||||
};
|
||||
|
||||
xudc: usb@700d0000 {
|
||||
status = "okay";
|
||||
|
||||
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
|
||||
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
|
||||
phy-names = "usb2-0", "usb3-0";
|
||||
|
||||
extcon = <&bm92t 1>;
|
||||
extcon-cable-names = "id";
|
||||
|
||||
hvdd-usb-supply = <&vdd_3v3>;
|
||||
avddio-usb-supply = <&max77620_ldo1>;
|
||||
};
|
||||
|
||||
padctl@7009f000 {
|
||||
status = "okay";
|
||||
|
||||
avdd-pll-utmip-supply = <&max77620_sd3>;
|
||||
avdd-pll-uerefe-supply = <&max77620_ldo1>;
|
||||
dvdd-pex-pll-supply = <&max77620_ldo1>;
|
||||
hvdd-pex-pll-e-supply = <&max77620_sd3>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,184 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "tegra210.dtsi"
|
||||
|
||||
/delete-node/ &emc;
|
||||
/delete-node/ &{/sata@70020000};
|
||||
|
||||
/ {
|
||||
compatible = "nvidia,tegra210b01", "nvidia,tegra210";
|
||||
|
||||
pcie@1003000 {
|
||||
compatible = "nvidia,tegra210b01-pcie";
|
||||
|
||||
/delete-property/ pinctrl-names;
|
||||
/delete-property/ pinctrl-0;
|
||||
/delete-property/ pinctrl-1;
|
||||
};
|
||||
|
||||
host1x@50000000 {
|
||||
/delete-node/ sor@54540000;
|
||||
/delete-node/ dpaux@545c0000;
|
||||
/delete-node/ vi@54080000;
|
||||
/delete-node/ i2c@546c0000;
|
||||
|
||||
dc@54200000 {
|
||||
nvidia,outputs = <&dsia &dsib &sor1>;
|
||||
};
|
||||
|
||||
dc@54240000 {
|
||||
nvidia,outputs = <&dsia &dsib &sor1>;
|
||||
};
|
||||
|
||||
dsi@54300000 {
|
||||
compatible = "nvidia,tegra210b01-dsi";
|
||||
};
|
||||
|
||||
dsi@54400000 {
|
||||
compatible = "nvidia,tegra210b01-dsi";
|
||||
};
|
||||
};
|
||||
|
||||
clock@60006000 {
|
||||
compatible = "nvidia,tegra210b01-car";
|
||||
};
|
||||
|
||||
actmon@6000c800 {
|
||||
clocks = <&tegra_car TEGRA210_CLK_ACTMON>,
|
||||
<&bpmp 0>;
|
||||
};
|
||||
|
||||
pinmux@700008d4 {
|
||||
compatible = "nvidia,tegra210b01-pinmux";
|
||||
|
||||
pinmux-sdmmc1-1v8-drv {
|
||||
sdmmc1 {
|
||||
nvidia,pull-down-strength = <0x8>;
|
||||
nvidia,pull-up-strength = <0x8>;
|
||||
};
|
||||
};
|
||||
|
||||
pinmux-sdmmc3-1v8-drv {
|
||||
sdmmc3 {
|
||||
nvidia,pull-down-strength = <0x8>;
|
||||
nvidia,pull-up-strength = <0x8>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c@7000d100 {
|
||||
/delete-property/ pinctrl-0;
|
||||
/delete-property/ pinctrl-1;
|
||||
/delete-property/ pinctrl-names;
|
||||
};
|
||||
|
||||
memory-controller@70019000 {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
emc: external-memory-controller@7001b000 {
|
||||
compatible = "nvidia,tegra186-emc";
|
||||
reg = <0x0 0x7001b000 0x0 0x1000>;
|
||||
clocks = <&bpmp 0>;
|
||||
clock-names = "emc";
|
||||
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
#cooling-cells = <2>;
|
||||
#interconnect-cells = <0>;
|
||||
|
||||
nvidia,bpmp = <&bpmp>;
|
||||
};
|
||||
};
|
||||
|
||||
mmc@700b0000 {
|
||||
compatible = "nvidia,tegra210b01-sdhci";
|
||||
nvidia,pad-autocal-pull-up-offset-3v3 = <0x06>;
|
||||
nvidia,pad-autocal-pull-down-offset-3v3 = <0x06>;
|
||||
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
|
||||
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
|
||||
nvidia,default-tap = <0xb>;
|
||||
nvidia,default-trim = <0xe>;
|
||||
|
||||
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
};
|
||||
|
||||
mmc@700b0200 {
|
||||
compatible = "nvidia,tegra210b01-sdhci";
|
||||
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
|
||||
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
|
||||
nvidia,default-tap = <0x8>;
|
||||
nvidia,default-trim = <0xd>;
|
||||
};
|
||||
|
||||
mmc@700b0400 {
|
||||
compatible = "nvidia,tegra210b01-sdhci";
|
||||
nvidia,pad-autocal-pull-up-offset-3v3 = <0x06>;
|
||||
nvidia,pad-autocal-pull-down-offset-3v3 = <0x06>;
|
||||
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
|
||||
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
|
||||
nvidia,default-tap = <0xb>;
|
||||
nvidia,default-trim = <0x12>;
|
||||
};
|
||||
|
||||
mmc@700b0600 {
|
||||
compatible = "nvidia,tegra210b01-sdhci";
|
||||
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
|
||||
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
|
||||
nvidia,default-tap = <0x9>;
|
||||
nvidia,default-trim = <0xd>;
|
||||
|
||||
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
|
||||
assigned-clock-rates = <199680000>, <199680000>;
|
||||
};
|
||||
|
||||
/* Tegra210B01 has MBIST patched and is missing VI unit */
|
||||
pmc@7000e400 {
|
||||
compatible = "nvidia,tegra210b01-pmc";
|
||||
|
||||
powergates {
|
||||
/delete-node/ venc;
|
||||
};
|
||||
};
|
||||
|
||||
bpmp@70016000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usb@70090000 {
|
||||
compatible = "nvidia,tegra210b01-xusb";
|
||||
};
|
||||
|
||||
padctl@7009f000 {
|
||||
compatible = "nvidia,tegra210b01-xusb-padctl";
|
||||
|
||||
pads {
|
||||
pcie {
|
||||
clocks = <&tegra_car TEGRA210_CLK_PLL_E>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_P_UPHY_OUT>;
|
||||
clock-names = "pll", "uphy_mgmt";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
usb@700d0000 {
|
||||
compatible = "nvidia,tegra210b01-xudc";
|
||||
};
|
||||
|
||||
thermal-sensor@700e2000 {
|
||||
compatible = "nvidia,tegra210b01-soctherm";
|
||||
|
||||
throttle-cfgs {
|
||||
heavy {
|
||||
nvidia,cpu-throt-percent = <0>;
|
||||
nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_NONE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
clock@70110000 {
|
||||
compatible = "nvidia,tegra210b01-dfll";
|
||||
};
|
||||
};
|
||||
@@ -872,6 +872,7 @@ CONFIG_REGULATOR_HI6421V530=y
|
||||
CONFIG_REGULATOR_HI655X=y
|
||||
CONFIG_REGULATOR_LP873X=m
|
||||
CONFIG_REGULATOR_MAX77620=y
|
||||
CONFIG_REGULATOR_MAX77812=y
|
||||
CONFIG_REGULATOR_MAX8973=y
|
||||
CONFIG_REGULATOR_MAX20411=m
|
||||
CONFIG_REGULATOR_MP8859=y
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_LOCALVERSION="-4k"
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_GENERIC_IRQ_DEBUGFS=y
|
||||
CONFIG_TIME_KUNIT_TEST=m
|
||||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
@@ -9,7 +10,6 @@ CONFIG_BPF_JIT_ALWAYS_ON=y
|
||||
# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
|
||||
CONFIG_BPF_LSM=y
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_SCHED_CLASS_EXT=y
|
||||
CONFIG_IRQ_TIME_ACCOUNTING=y
|
||||
CONFIG_TASKSTATS=y
|
||||
CONFIG_TASK_DELAY_ACCT=y
|
||||
@@ -43,14 +43,12 @@ CONFIG_RT_SOFTIRQ_AWARE_SCHED=y
|
||||
CONFIG_RELAY=y
|
||||
# CONFIG_RD_BZIP2 is not set
|
||||
# CONFIG_RD_LZMA is not set
|
||||
# CONFIG_RD_XZ is not set
|
||||
# CONFIG_RD_LZO is not set
|
||||
CONFIG_BOOT_CONFIG=y
|
||||
CONFIG_EXPERT=y
|
||||
# CONFIG_FHANDLE is not set
|
||||
# CONFIG_RSEQ is not set
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_RUST=y
|
||||
CONFIG_ARCH_SUNXI=y
|
||||
CONFIG_ARCH_HISI=y
|
||||
CONFIG_ARCH_QCOM=y
|
||||
@@ -70,6 +68,7 @@ CONFIG_RANDOMIZE_BASE=y
|
||||
# CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set
|
||||
CONFIG_UNWIND_PATCH_PAC_INTO_SCS=y
|
||||
CONFIG_CMDLINE="console=ttynull stack_depot_disable=on cgroup_disable=pressure kasan.stacktrace=off kvm-arm.mode=protected bootconfig ioremap_guard"
|
||||
CONFIG_CMDLINE_EXTEND=y
|
||||
# CONFIG_DMI is not set
|
||||
CONFIG_HIBERNATION=y
|
||||
CONFIG_PM_USERSPACE_AUTOSLEEP=y
|
||||
@@ -422,7 +421,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=32
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=0
|
||||
CONFIG_SERIAL_8250_DW=y
|
||||
# CONFIG_SERIAL_8250_TEGRA is not set
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SERIAL_AMBA_PL011=y
|
||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||
@@ -441,7 +439,6 @@ CONFIG_HW_RANDOM=y
|
||||
# CONFIG_HW_RANDOM_HISI is not set
|
||||
# CONFIG_HW_RANDOM_HISTB is not set
|
||||
CONFIG_HW_RANDOM_CCTRNG=m
|
||||
# CONFIG_DEVMEM is not set
|
||||
# CONFIG_DEVPORT is not set
|
||||
# CONFIG_I2C_HELPER_AUTO is not set
|
||||
# CONFIG_I2C_TEGRA_BPMP is not set
|
||||
@@ -607,15 +604,16 @@ CONFIG_VIRTIO_BALLOON=m
|
||||
CONFIG_VHOST_VSOCK=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_ASHMEM=y
|
||||
CONFIG_ASHMEM_RUST=y
|
||||
CONFIG_COMMON_CLK_SCPI=y
|
||||
# CONFIG_SUNXI_CCU is not set
|
||||
CONFIG_CLK_KUNIT_TEST=m
|
||||
CONFIG_CLK_GATE_KUNIT_TEST=m
|
||||
CONFIG_HWSPINLOCK=y
|
||||
CONFIG_TEGRA186_TIMER=y
|
||||
# CONFIG_SUN50I_ERRATUM_UNKNOWN1 is not set
|
||||
CONFIG_TEGRA_HSP_MBOX=y
|
||||
CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y
|
||||
CONFIG_TEGRA_IOMMU_SMMU=y
|
||||
CONFIG_REMOTEPROC=y
|
||||
CONFIG_REMOTEPROC_CDEV=y
|
||||
CONFIG_RPMSG_CHAR=y
|
||||
@@ -628,6 +626,7 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y
|
||||
CONFIG_DEVFREQ_GOV_PASSIVE=y
|
||||
CONFIG_PM_DEVFREQ_EVENT=y
|
||||
CONFIG_MEMORY=y
|
||||
CONFIG_TEGRA210_EMC=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_IIO_BUFFER=y
|
||||
CONFIG_IIO_TRIGGER=y
|
||||
@@ -763,8 +762,6 @@ CONFIG_STACKTRACE_BUILD_ID=y
|
||||
CONFIG_DYNAMIC_DEBUG_CORE=y
|
||||
CONFIG_DEBUG_INFO_DWARF5=y
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
|
||||
CONFIG_DEBUG_INFO_BTF=y
|
||||
CONFIG_MODULE_ALLOW_BTF_MISMATCH=y
|
||||
CONFIG_HEADERS_INSTALL=y
|
||||
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
@@ -192,6 +193,37 @@ struct gcs_context {
|
||||
__u64 reserved;
|
||||
};
|
||||
|
||||
#else /* CONFIG_64BIT */
|
||||
|
||||
/*
|
||||
* Signal context structure - contains all info to do with the state
|
||||
* before the signal handler was invoked. Note: only add new entries
|
||||
* to the end of the structure.
|
||||
*/
|
||||
struct sigcontext {
|
||||
unsigned long trap_no;
|
||||
unsigned long error_code;
|
||||
unsigned long oldmask;
|
||||
unsigned long arm_r0;
|
||||
unsigned long arm_r1;
|
||||
unsigned long arm_r2;
|
||||
unsigned long arm_r3;
|
||||
unsigned long arm_r4;
|
||||
unsigned long arm_r5;
|
||||
unsigned long arm_r6;
|
||||
unsigned long arm_r7;
|
||||
unsigned long arm_r8;
|
||||
unsigned long arm_r9;
|
||||
unsigned long arm_r10;
|
||||
unsigned long arm_fp;
|
||||
unsigned long arm_ip;
|
||||
unsigned long arm_sp;
|
||||
unsigned long arm_lr;
|
||||
unsigned long arm_pc;
|
||||
unsigned long arm_cpsr;
|
||||
unsigned long fault_address;
|
||||
};
|
||||
#endif /* CONFIG_64BIT */
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
#include <asm/sve_context.h>
|
||||
|
||||
@@ -525,7 +525,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr4[] = {
|
||||
static const struct arm64_ftr_bits ftr_ctr[] = {
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_EL0_DIC_SHIFT, 1, 1),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_EL0_IDC_SHIFT, 1, 1),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, CTR_EL0_IDC_SHIFT, 1, 1),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_EL0_CWG_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_EL0_ERG_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_EL0_DminLine_SHIFT, 4, 1),
|
||||
@@ -570,6 +570,7 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
|
||||
* of support.
|
||||
*/
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_EL1_PMUVer_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64DFR0_EL1_TraceVer_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_EL1_DebugVer_SHIFT, 4, 0x6),
|
||||
ARM64_FTR_END,
|
||||
};
|
||||
@@ -715,8 +716,8 @@ static const struct arm64_ftr_bits ftr_id_dfr0[] = {
|
||||
/* [31:28] TraceFilt */
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_DFR0_EL1_PerfMon_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MProfDbg_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapTrc_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopTrc_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapTrc_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopTrc_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapDbg_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopSDbg_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopDbg_SHIFT, 4, 0),
|
||||
|
||||
@@ -385,8 +385,11 @@ static __init void parse_cmdline(const void *fdt, int chosen)
|
||||
static char const cmdline[] __initconst = CONFIG_CMDLINE;
|
||||
const u8 *prop = get_bootargs_cmdline(fdt, chosen);
|
||||
|
||||
if (IS_ENABLED(CONFIG_CMDLINE_FORCE) || !prop)
|
||||
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
||||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
|
||||
!prop) {
|
||||
__parse_cmdline(cmdline, true);
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && prop)
|
||||
__parse_cmdline(prop, true);
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -6,7 +6,7 @@ if ARM_AMBA
|
||||
|
||||
config TEGRA_AHB
|
||||
bool "Enable AHB driver for NVIDIA Tegra SoCs" if COMPILE_TEST
|
||||
default y if ARCH_TEGRA && !GKI_HACKS_TO_FIX
|
||||
default y if (ARCH_TEGRA && ARM) || ARCH_TEGRA_210_SOC
|
||||
help
|
||||
Adds AHB configuration functionality for NVIDIA Tegra SoCs,
|
||||
which controls AHB bus master arbitration and some performance
|
||||
|
||||
@@ -2236,6 +2236,15 @@ static int fw_devlink_create_devlink(struct device *con,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* SYNC_STATE_ONLY links are useless once a consumer device has probed.
|
||||
* So, only create it if the consumer hasn't probed yet.
|
||||
*/
|
||||
if (flags & DL_FLAG_SYNC_STATE_ONLY &&
|
||||
con->links.status != DL_DEV_NO_DRIVER &&
|
||||
con->links.status != DL_DEV_PROBING)
|
||||
goto out;
|
||||
|
||||
if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
|
||||
dev_err(con, "Failed to create device link (0x%x) with supplier %s for %pfwf\n",
|
||||
flags, dev_name(sup_dev), link->consumer);
|
||||
|
||||
+23
-2
@@ -2464,6 +2464,13 @@ static void clk_change_rate(struct clk_core *core)
|
||||
if (core->ops->post_rate_change)
|
||||
core->ops->post_rate_change(core->hw, old_rate, core->rate);
|
||||
|
||||
/*
|
||||
* Allow children to be aware that next set rate operation is triggered
|
||||
* by downward rate propagation, rather than direct set rate on itself.
|
||||
*/
|
||||
if (core->notifier_count)
|
||||
__clk_notify(core, PRE_SUBTREE_CHANGE, old_rate, core->rate);
|
||||
|
||||
/*
|
||||
* Use safe iteration, as change_rate can actually swap parents
|
||||
* for certain clock types.
|
||||
@@ -2479,6 +2486,9 @@ static void clk_change_rate(struct clk_core *core)
|
||||
if (core->new_child)
|
||||
clk_change_rate(core->new_child);
|
||||
|
||||
if (core->notifier_count)
|
||||
__clk_notify(core, POST_SUBTREE_CHANGE, old_rate, core->rate);
|
||||
|
||||
clk_pm_runtime_put(core);
|
||||
}
|
||||
|
||||
@@ -2858,6 +2868,7 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
|
||||
int ret = 0;
|
||||
int p_index = 0;
|
||||
unsigned long p_rate = 0;
|
||||
unsigned long old_p_rate = 0;
|
||||
|
||||
lockdep_assert_held(&prepare_lock);
|
||||
|
||||
@@ -2900,13 +2911,23 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
|
||||
if (ret & NOTIFY_STOP_MASK)
|
||||
goto runtime_put;
|
||||
|
||||
/* do the re-parent */
|
||||
ret = __clk_set_parent(core, parent, p_index);
|
||||
|
||||
/* propagate PRE_PARENT_CHANGE notifications */
|
||||
if (core->parent)
|
||||
old_p_rate = core->parent->rate;
|
||||
|
||||
ret = __clk_notify(core, PRE_PARENT_CHANGE, old_p_rate, p_rate);
|
||||
|
||||
/* do the re-parent if no objections */
|
||||
if (!(ret & NOTIFY_STOP_MASK))
|
||||
ret = __clk_set_parent(core, parent, p_index);
|
||||
|
||||
/* propagate rate an accuracy recalculation accordingly */
|
||||
if (ret) {
|
||||
__clk_notify(core, ABORT_PARENT_CHANGE, old_p_rate, p_rate);
|
||||
__clk_recalc_rates(core, true, ABORT_RATE_CHANGE);
|
||||
} else {
|
||||
__clk_notify(core, POST_PARENT_CHANGE, old_p_rate, p_rate);
|
||||
__clk_recalc_rates(core, true, POST_RATE_CHANGE);
|
||||
__clk_recalc_accuracies(core);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ obj-$(CONFIG_TEGRA124_CLK_EMC) += clk-tegra124-emc.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
|
||||
obj-y += cvb.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210b01.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210-emc.o
|
||||
obj-$(CONFIG_CLK_TEGRA_BPMP) += clk-bpmp.o
|
||||
obj-y += clk-utils.o
|
||||
+326
-15
@@ -31,6 +31,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -193,6 +194,37 @@
|
||||
*/
|
||||
#define REF_CLK_CYC_PER_DVCO_SAMPLE 4
|
||||
|
||||
/*
|
||||
* DFLL_OUTPUT_RAMP_DELAY: after the DFLL's I2C PMIC output starts
|
||||
* requesting the minimum TUNE_HIGH voltage, the minimum number of
|
||||
* microseconds to wait for the PMIC's voltage output to finish
|
||||
* slewing
|
||||
*/
|
||||
#define DFLL_OUTPUT_RAMP_DELAY 100
|
||||
|
||||
/*
|
||||
* DFLL_TUNE_HIGH_DELAY: number of microseconds to wait between tests
|
||||
* to see if the high voltage has been reached yet, during a
|
||||
* transition from the low-voltage range to the high-voltage range
|
||||
*/
|
||||
#define DFLL_TUNE_HIGH_DELAY 2000
|
||||
|
||||
/*
|
||||
* DFLL_TUNE_HIGH_MARGIN_STEPS: attempt to initially program the DFLL
|
||||
* voltage target to a (DFLL_TUNE_HIGH_MARGIN_STEPS * 10 millivolt)
|
||||
* margin above the high voltage floor, in closed-loop mode in the
|
||||
* high-voltage range
|
||||
*/
|
||||
#define DFLL_TUNE_HIGH_MARGIN_STEPS 2
|
||||
|
||||
/*
|
||||
* I2C_OUTPUT_ACTIVE_TEST_US: mandatory minimum interval (in
|
||||
* microseconds) between testing whether the I2C controller is
|
||||
* currently sending a voltage-set command. Some comments list this
|
||||
* as being a worst-case margin for "disable propagation."
|
||||
*/
|
||||
#define I2C_OUTPUT_ACTIVE_TEST_US 2
|
||||
|
||||
/*
|
||||
* REF_CLOCK_RATE: the DFLL reference clock rate currently supported by this
|
||||
* driver, in Hz
|
||||
@@ -224,6 +256,9 @@ enum dfll_ctrl_mode {
|
||||
* enum dfll_tune_range - voltage range that the driver believes it's in
|
||||
* @DFLL_TUNE_UNINITIALIZED: DFLL tuning not yet programmed
|
||||
* @DFLL_TUNE_LOW: DFLL in the low-voltage range (or open-loop mode)
|
||||
* @DFLL_TUNE_WAIT_DFLL: waiting for DFLL voltage output to reach high
|
||||
* @DFLL_TUNE_WAIT_PMIC: waiting for PMIC to react to DFLL output
|
||||
* @DFLL_TUNE_HIGH: DFLL in the high-voltage range
|
||||
*
|
||||
* Some DFLL tuning parameters may need to change depending on the
|
||||
* DVCO's voltage; these states represent the ranges that the driver
|
||||
@@ -232,7 +267,10 @@ enum dfll_ctrl_mode {
|
||||
*/
|
||||
enum dfll_tune_range {
|
||||
DFLL_TUNE_UNINITIALIZED = 0,
|
||||
DFLL_TUNE_LOW = 1,
|
||||
DFLL_TUNE_LOW,
|
||||
DFLL_TUNE_WAIT_DFLL,
|
||||
DFLL_TUNE_WAIT_PMIC,
|
||||
DFLL_TUNE_HIGH,
|
||||
};
|
||||
|
||||
|
||||
@@ -285,6 +323,10 @@ struct tegra_dfll {
|
||||
struct dfll_rate_req last_req;
|
||||
unsigned long last_unrounded_rate;
|
||||
|
||||
struct hrtimer tune_timer;
|
||||
ktime_t tune_delay;
|
||||
ktime_t tune_ramp_delay;
|
||||
|
||||
/* Parameters from DT */
|
||||
u32 droop_ctrl;
|
||||
u32 sample_rate;
|
||||
@@ -305,6 +347,11 @@ struct tegra_dfll {
|
||||
int lut_size;
|
||||
u8 lut_bottom, lut_min, lut_max, lut_safe;
|
||||
|
||||
/* tuning parameters */
|
||||
u8 tune_high_out_start;
|
||||
u8 tune_high_out_min;
|
||||
u8 tune_out_last;
|
||||
|
||||
/* PWM interface */
|
||||
enum tegra_dfll_pmu_if pmu_if;
|
||||
unsigned long pwm_rate;
|
||||
@@ -312,6 +359,9 @@ struct tegra_dfll {
|
||||
struct pinctrl_state *pwm_enable_state;
|
||||
struct pinctrl_state *pwm_disable_state;
|
||||
u32 reg_init_uV;
|
||||
|
||||
/* spinlock protecting register accesses */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
|
||||
@@ -324,6 +374,8 @@ static const char * const mode_name[] = {
|
||||
[DFLL_CLOSED_LOOP] = "closed_loop",
|
||||
};
|
||||
|
||||
static void dfll_load_i2c_lut(struct tegra_dfll *td);
|
||||
|
||||
/*
|
||||
* Register accessors
|
||||
*/
|
||||
@@ -361,6 +413,36 @@ static inline void dfll_i2c_wmb(struct tegra_dfll *td)
|
||||
dfll_i2c_readl(td, DFLL_I2C_CFG);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_output_i2c_req_pending - is an I2C voltage-set command in progress?
|
||||
* @pdev: DFLL instance
|
||||
*
|
||||
* Returns 1 if an I2C request is in progress, or 0 if not. The DFLL
|
||||
* IP block requires two back-to-back reads of the I2C_REQ_PENDING
|
||||
* field to return 0 before the software can be sure that no I2C
|
||||
* request is currently pending. Also, a minimum time interval
|
||||
* between DFLL_I2C_STS reads is required by the IP block.
|
||||
*/
|
||||
static int is_output_i2c_req_pending(struct tegra_dfll *td)
|
||||
{
|
||||
u32 sts;
|
||||
|
||||
if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
|
||||
return 0;
|
||||
|
||||
sts = dfll_i2c_readl(td, DFLL_I2C_STS);
|
||||
if (sts & DFLL_I2C_STS_I2C_REQ_PENDING)
|
||||
return 1;
|
||||
|
||||
udelay(I2C_OUTPUT_ACTIVE_TEST_US);
|
||||
|
||||
sts = dfll_i2c_readl(td, DFLL_I2C_STS);
|
||||
if (sts & DFLL_I2C_STS_I2C_REQ_PENDING)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfll_is_running - is the DFLL currently generating a clock?
|
||||
* @td: DFLL instance
|
||||
@@ -452,13 +534,139 @@ static void dfll_tune_low(struct tegra_dfll *td)
|
||||
td->tune_range = DFLL_TUNE_LOW;
|
||||
|
||||
dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune0_low, DFLL_TUNE0);
|
||||
dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1, DFLL_TUNE1);
|
||||
dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1_low, DFLL_TUNE1);
|
||||
dfll_wmb(td);
|
||||
|
||||
if (td->soc->set_clock_trimmers_low)
|
||||
td->soc->set_clock_trimmers_low();
|
||||
}
|
||||
|
||||
/**
|
||||
* dfll_tune_high - tune DFLL and CPU clock shaper for high voltages
|
||||
* @td: DFLL instance
|
||||
*
|
||||
* Tune the DFLL oscillator parameters and the CPU clock shaper
|
||||
* for the high-voltage range. The bottom end of the high-voltage
|
||||
* range is represented by the index td->soc->tune_high_min_millivolts.
|
||||
* Used in closed-loop mode. No return value.
|
||||
*/
|
||||
static void dfll_tune_high(struct tegra_dfll *td)
|
||||
{
|
||||
u32 tune0_high;
|
||||
u32 tune1_high;
|
||||
|
||||
td->tune_range = DFLL_TUNE_HIGH;
|
||||
|
||||
tune0_high = td->soc->cvb->cpu_dfll_data.tune0_high;
|
||||
if (!tune0_high)
|
||||
tune0_high = td->soc->cvb->cpu_dfll_data.tune0_low;
|
||||
dfll_writel(td, tune0_high, DFLL_TUNE0);
|
||||
|
||||
tune1_high = td->soc->cvb->cpu_dfll_data.tune1_high;
|
||||
if (!tune1_high)
|
||||
tune1_high = td->soc->cvb->cpu_dfll_data.tune1_low;
|
||||
dfll_writel(td, tune1_high, DFLL_TUNE1);
|
||||
|
||||
dfll_wmb(td);
|
||||
|
||||
if (td->soc->set_clock_trimmers_high)
|
||||
td->soc->set_clock_trimmers_high();
|
||||
}
|
||||
|
||||
/**
|
||||
* dfll_set_close_loop_config - prepare to switch to closed-loop mode
|
||||
* @pdev: DFLL instance
|
||||
* @req: requested output rate
|
||||
*
|
||||
* Prepare to switch the DFLL to closed-loop mode. This involves
|
||||
* switching the DFLL's tuning voltage regime (if necessary), and
|
||||
* rewriting the LUT to restrict the minimum and maximum voltages. No
|
||||
* return value.
|
||||
*/
|
||||
static void dfll_set_close_loop_config(struct tegra_dfll *td,
|
||||
struct dfll_rate_req *req)
|
||||
{
|
||||
bool sample_tune_out_last = false;
|
||||
|
||||
switch (td->tune_range) {
|
||||
case DFLL_TUNE_LOW:
|
||||
if (req->lut_index > td->tune_high_out_start) {
|
||||
hrtimer_start(&td->tune_timer, td->tune_delay,
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
sample_tune_out_last = true;
|
||||
break;
|
||||
|
||||
case DFLL_TUNE_HIGH:
|
||||
case DFLL_TUNE_WAIT_DFLL:
|
||||
case DFLL_TUNE_WAIT_PMIC:
|
||||
if (req->lut_index <= td->tune_high_out_start)
|
||||
dfll_tune_low(td);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
td->lut_min = td->tune_range == DFLL_TUNE_LOW ?
|
||||
0 : td->tune_high_out_min;
|
||||
|
||||
if (sample_tune_out_last && td->pmu_if == TEGRA_DFLL_PMU_I2C) {
|
||||
u32 val;
|
||||
|
||||
val = dfll_i2c_readl(td, DFLL_I2C_STS);
|
||||
td->tune_out_last = val >> DFLL_I2C_STS_I2C_LAST_SHIFT;
|
||||
td->tune_out_last &= OUT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dfll_tune_timer_cb - timer callback while tuning low to high
|
||||
* @data: struct platform_device * of the DFLL instance
|
||||
*
|
||||
* Timer callback, used when switching from TUNE_LOW to TUNE_HIGH in
|
||||
* closed-loop mode. Waits for DFLL I2C voltage command output to
|
||||
* reach tune_high_out_min, then waits for the PMIC to react to the
|
||||
* command. No return value.
|
||||
*/
|
||||
static enum hrtimer_restart dfll_tune_timer_cb(struct hrtimer *timer)
|
||||
{
|
||||
struct tegra_dfll *td;
|
||||
u32 val, out_min, out_last;
|
||||
bool use_ramp_delay;
|
||||
|
||||
td = container_of(timer, struct tegra_dfll, tune_timer);
|
||||
|
||||
if (td->tune_range == DFLL_TUNE_WAIT_DFLL) {
|
||||
out_min = td->lut_min;
|
||||
|
||||
if (td->pmu_if == TEGRA_DFLL_PMU_I2C) {
|
||||
val = dfll_i2c_readl(td, DFLL_I2C_STS);
|
||||
out_last = val >> DFLL_I2C_STS_I2C_LAST_SHIFT;
|
||||
out_last &= OUT_MASK;
|
||||
} else {
|
||||
out_last = out_min;
|
||||
}
|
||||
|
||||
use_ramp_delay = !is_output_i2c_req_pending(td);
|
||||
use_ramp_delay |= td->tune_out_last != out_last;
|
||||
|
||||
if (use_ramp_delay &&
|
||||
(out_last >= td->tune_high_out_min) &&
|
||||
(out_min >= td->tune_high_out_min)) {
|
||||
td->tune_range = DFLL_TUNE_WAIT_PMIC;
|
||||
hrtimer_start(&td->tune_timer, td->tune_ramp_delay,
|
||||
HRTIMER_MODE_REL);
|
||||
} else {
|
||||
hrtimer_start(&td->tune_timer, td->tune_delay,
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
} else if (td->tune_range == DFLL_TUNE_WAIT_PMIC) {
|
||||
dfll_tune_high(td);
|
||||
}
|
||||
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output clock scaler helpers
|
||||
*/
|
||||
@@ -554,7 +762,6 @@ static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DFLL-to-PWM controller interface
|
||||
*/
|
||||
@@ -679,10 +886,10 @@ static void dfll_load_i2c_lut(struct tegra_dfll *td)
|
||||
u32 val;
|
||||
|
||||
for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
|
||||
if (i < td->lut_min)
|
||||
lut_index = td->lut_min;
|
||||
else if (i > td->lut_max)
|
||||
lut_index = td->lut_max;
|
||||
if (i < td->lut_bottom)
|
||||
lut_index = td->lut_bottom;
|
||||
else if (i > td->lut_size - 1)
|
||||
lut_index = td->lut_size - 1;
|
||||
else
|
||||
lut_index = i;
|
||||
|
||||
@@ -813,6 +1020,28 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_mv_out_cap - find the out_map index with voltage >= @mv
|
||||
* @td: DFLL instance
|
||||
* @mv: millivolts
|
||||
*
|
||||
* Find the lut index with voltage greater than or equal to @mv,
|
||||
* and return it. If all of the voltages in out_map are less than
|
||||
* @mv, then return the lut index * corresponding to the highest
|
||||
* possible voltage, even though it's less than @mv.
|
||||
*/
|
||||
static u8 find_mv_out_cap(struct tegra_dfll *td, int mv)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = td->lut_bottom; i < td->lut_size; i++) {
|
||||
if (td->lut_uv[i] >= mv * 1000)
|
||||
return i;
|
||||
}
|
||||
|
||||
return i - 1; /* maximum possible output */
|
||||
}
|
||||
|
||||
/**
|
||||
* dfll_calculate_rate_request - calculate DFLL parameters for a given rate
|
||||
* @td: DFLL instance
|
||||
@@ -913,6 +1142,7 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
|
||||
{
|
||||
int ret;
|
||||
struct dfll_rate_req req;
|
||||
unsigned long flags;
|
||||
|
||||
if (td->mode == DFLL_UNINITIALIZED) {
|
||||
dev_err(td->dev, "%s: Cannot set DFLL rate in %s mode\n",
|
||||
@@ -927,8 +1157,12 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
|
||||
td->last_unrounded_rate = rate;
|
||||
td->last_req = req;
|
||||
|
||||
if (td->mode == DFLL_CLOSED_LOOP)
|
||||
if (td->mode == DFLL_CLOSED_LOOP) {
|
||||
spin_lock_irqsave(&td->lock, flags);
|
||||
dfll_set_close_loop_config(td, &td->last_req);
|
||||
dfll_set_frequency_request(td, &td->last_req);
|
||||
spin_unlock_irqrestore(&td->lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -946,13 +1180,18 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
|
||||
*/
|
||||
static int dfll_disable(struct tegra_dfll *td)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (td->mode != DFLL_OPEN_LOOP) {
|
||||
dev_err(td->dev, "cannot disable DFLL in %s mode\n",
|
||||
mode_name[td->mode]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&td->lock, flags);
|
||||
dfll_set_mode(td, DFLL_DISABLED);
|
||||
spin_unlock_irqrestore(&td->lock, flags);
|
||||
|
||||
pm_runtime_put_sync(td->dev);
|
||||
|
||||
return 0;
|
||||
@@ -1016,6 +1255,7 @@ static void dfll_set_open_loop_config(struct tegra_dfll *td)
|
||||
static int dfll_lock(struct tegra_dfll *td)
|
||||
{
|
||||
struct dfll_rate_req *req = &td->last_req;
|
||||
unsigned long flags;
|
||||
|
||||
switch (td->mode) {
|
||||
case DFLL_CLOSED_LOOP:
|
||||
@@ -1033,9 +1273,12 @@ static int dfll_lock(struct tegra_dfll *td)
|
||||
else
|
||||
dfll_i2c_set_output_enabled(td, true);
|
||||
|
||||
spin_lock_irqsave(&td->lock, flags);
|
||||
dfll_set_mode(td, DFLL_CLOSED_LOOP);
|
||||
dfll_set_close_loop_config(td, req);
|
||||
dfll_set_frequency_request(td, req);
|
||||
dfll_set_force_output_enabled(td, false);
|
||||
spin_unlock_irqrestore(&td->lock, flags);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
@@ -1055,14 +1298,19 @@ static int dfll_lock(struct tegra_dfll *td)
|
||||
*/
|
||||
static int dfll_unlock(struct tegra_dfll *td)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
switch (td->mode) {
|
||||
case DFLL_CLOSED_LOOP:
|
||||
spin_lock_irqsave(&td->lock, flags);
|
||||
dfll_set_open_loop_config(td);
|
||||
dfll_set_mode(td, DFLL_OPEN_LOOP);
|
||||
if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
|
||||
dfll_pwm_set_output_enabled(td, false);
|
||||
else
|
||||
dfll_i2c_set_output_enabled(td, false);
|
||||
|
||||
spin_unlock_irqrestore(&td->lock, flags);
|
||||
return 0;
|
||||
|
||||
case DFLL_OPEN_LOOP:
|
||||
@@ -1325,8 +1573,10 @@ static int attr_registers_show(struct seq_file *s, void *data)
|
||||
{
|
||||
u32 val, offs;
|
||||
struct tegra_dfll *td = s->private;
|
||||
unsigned long flags;
|
||||
|
||||
seq_puts(s, "CONTROL REGISTERS:\n");
|
||||
spin_lock_irqsave(&td->lock, flags);
|
||||
for (offs = 0; offs <= DFLL_MONITOR_DATA; offs += 4) {
|
||||
if (offs == DFLL_OUTPUT_CFG)
|
||||
val = dfll_i2c_readl(td, offs);
|
||||
@@ -1355,6 +1605,8 @@ static int attr_registers_show(struct seq_file *s, void *data)
|
||||
__raw_readl(td->lut_base + offs));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&td->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1445,6 +1697,53 @@ static int dfll_init_clks(struct tegra_dfll *td)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfll_init_tuning_thresholds - set up the high voltage range, if possible
|
||||
* @td: DFLL instance
|
||||
*
|
||||
* Determine whether the DFLL tuning parameters need to be
|
||||
* reprogrammed when the DFLL voltage reaches a certain minimum
|
||||
* threshold. No return value.
|
||||
*/
|
||||
static void dfll_init_tuning_thresholds(struct tegra_dfll *td)
|
||||
{
|
||||
u8 out_min, out_start, max_voltage_index;
|
||||
|
||||
max_voltage_index = td->lut_size - 1;
|
||||
|
||||
/*
|
||||
* Convert high tuning voltage threshold into output LUT
|
||||
* index, and add necessary margin. If voltage threshold is
|
||||
* outside operating range set it at maximum output level to
|
||||
* effectively disable tuning parameters adjustment.
|
||||
*/
|
||||
td->tune_high_out_min = max_voltage_index;
|
||||
td->tune_high_out_start = max_voltage_index;
|
||||
if (td->soc->tune_high_min_millivolts < td->soc->min_millivolts)
|
||||
return; /* no difference between low & high voltage range */
|
||||
|
||||
out_min = find_mv_out_cap(td, td->soc->tune_high_min_millivolts);
|
||||
if ((out_min + 2) > max_voltage_index)
|
||||
return;
|
||||
|
||||
if (td->soc->cvb->cpu_dfll_data.tune_high_margin_millivolts) {
|
||||
unsigned int mv;
|
||||
|
||||
mv = td->soc->tune_high_min_millivolts +
|
||||
td->soc->cvb->cpu_dfll_data.tune_high_margin_millivolts;
|
||||
if (mv * 1000 > td->lut_uv[max_voltage_index])
|
||||
return;
|
||||
out_start = max((u8)(out_min + 1), find_mv_out_cap(td, mv));
|
||||
} else {
|
||||
out_start = out_min + DFLL_TUNE_HIGH_MARGIN_STEPS;
|
||||
}
|
||||
if (out_start > max_voltage_index)
|
||||
return;
|
||||
|
||||
td->tune_high_out_min = out_min;
|
||||
td->tune_high_out_start = out_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* dfll_init - Prepare the DFLL IP block for use
|
||||
* @td: DFLL instance
|
||||
@@ -1501,6 +1800,8 @@ static int dfll_init(struct tegra_dfll *td)
|
||||
|
||||
dfll_init_out_if(td);
|
||||
|
||||
dfll_init_tuning_thresholds(td);
|
||||
|
||||
pm_runtime_put_sync(td->dev);
|
||||
|
||||
return 0;
|
||||
@@ -1647,7 +1948,7 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
|
||||
int i;
|
||||
unsigned long rate, reg_volt;
|
||||
u8 lut_bottom = MAX_DFLL_VOLTAGES;
|
||||
int v_min = td->soc->cvb->min_millivolts * 1000;
|
||||
int v_min = td->soc->min_millivolts * 1000;
|
||||
|
||||
for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
|
||||
reg_volt = td->lut_uv[i];
|
||||
@@ -1667,7 +1968,7 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
|
||||
if ((lut_bottom == MAX_DFLL_VOLTAGES) ||
|
||||
(lut_bottom + 1 >= td->lut_size)) {
|
||||
dev_err(td->dev, "no voltage above DFLL minimum %d mV\n",
|
||||
td->soc->cvb->min_millivolts);
|
||||
td->soc->min_millivolts);
|
||||
return -EINVAL;
|
||||
}
|
||||
td->lut_bottom = lut_bottom;
|
||||
@@ -1676,7 +1977,7 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
|
||||
rate = get_dvco_rate_below(td, td->lut_bottom);
|
||||
if (!rate) {
|
||||
dev_err(td->dev, "no opp below DFLL minimum voltage %d mV\n",
|
||||
td->soc->cvb->min_millivolts);
|
||||
td->soc->min_millivolts);
|
||||
return -EINVAL;
|
||||
}
|
||||
td->dvco_rate_min = rate;
|
||||
@@ -1699,17 +2000,20 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
|
||||
*/
|
||||
static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
|
||||
{
|
||||
unsigned long rate, v, v_opp;
|
||||
unsigned long rate, v, v_opp, v_min_align;
|
||||
int ret = -EINVAL;
|
||||
int j, selector, lut;
|
||||
|
||||
v = td->soc->cvb->min_millivolts * 1000;
|
||||
v = td->soc->min_millivolts * 1000;
|
||||
lut = find_vdd_map_entry_exact(td, v);
|
||||
if (lut < 0)
|
||||
goto out;
|
||||
td->lut[0] = lut;
|
||||
td->lut_bottom = 0;
|
||||
|
||||
v_min_align = DIV_ROUND_UP(td->soc->min_millivolts * 1000,
|
||||
td->soc->alignment.step_uv) * td->soc->alignment.step_uv;
|
||||
|
||||
for (j = 1, rate = 0; ; rate++) {
|
||||
struct dev_pm_opp *opp;
|
||||
|
||||
@@ -1718,7 +2022,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
|
||||
break;
|
||||
v_opp = dev_pm_opp_get_voltage(opp);
|
||||
|
||||
if (v_opp <= td->soc->cvb->min_millivolts * 1000)
|
||||
if (v_opp <= v_min_align)
|
||||
td->dvco_rate_min = dev_pm_opp_get_freq(opp);
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
@@ -1749,7 +2053,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
|
||||
|
||||
if (!td->dvco_rate_min)
|
||||
dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
|
||||
td->soc->cvb->min_millivolts);
|
||||
td->soc->min_millivolts);
|
||||
else {
|
||||
ret = 0;
|
||||
for (j = 0; j < td->lut_size; j++)
|
||||
@@ -2057,12 +2361,19 @@ int tegra_dfll_register(struct platform_device *pdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_init(&td->lock);
|
||||
|
||||
ret = dfll_register_clk(td);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "DFLL clk registration failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize tuning timer */
|
||||
hrtimer_setup(&td->tune_timer, dfll_tune_timer_cb, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
td->tune_delay = ktime_set(0, DFLL_TUNE_HIGH_DELAY * 1000);
|
||||
td->tune_ramp_delay = ktime_set(0, DFLL_OUTPUT_RAMP_DELAY * 1000);
|
||||
|
||||
dfll_debug_init(td);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -31,6 +31,8 @@ struct tegra_dfll_soc_data {
|
||||
unsigned long max_freq;
|
||||
const struct cvb_table *cvb;
|
||||
struct rail_alignment alignment;
|
||||
unsigned int min_millivolts;
|
||||
unsigned int tune_high_min_millivolts;
|
||||
|
||||
void (*init_clock_trimmers)(void);
|
||||
void (*set_clock_trimmers_high)(void);
|
||||
|
||||
@@ -878,6 +878,9 @@ static void __init periph_clk_init(void __iomem *clk_base,
|
||||
if (!bank)
|
||||
continue;
|
||||
|
||||
if (tegra_clks[data->clk_id].use_integer_div)
|
||||
data->periph.divider.flags |= TEGRA_DIVIDER_INT;
|
||||
|
||||
data->periph.gate.regs = bank;
|
||||
clk = tegra_clk_register_periph_data(clk_base, data);
|
||||
*dt_clk = clk;
|
||||
|
||||
@@ -64,7 +64,7 @@ static const unsigned long tegra114_cpu_max_freq_table[] = {
|
||||
.cpu_dfll_data = { \
|
||||
.tune0_low = 0x00b0039d, \
|
||||
.tune0_high = 0x00b0009d, \
|
||||
.tune1 = 0x0000001f, \
|
||||
.tune1_low = 0x0000001f, \
|
||||
.tune_high_min_millivolts = 1050, \
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ static const struct cvb_table tegra114_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x00b0019d,
|
||||
.tune0_high = 0x00b0019d,
|
||||
.tune1 = 0x0000001f,
|
||||
.tune1_low = 0x0000001f,
|
||||
.tune_high_min_millivolts = 1000,
|
||||
}
|
||||
},
|
||||
@@ -167,7 +167,7 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x005020ff,
|
||||
.tune0_high = 0x005040ff,
|
||||
.tune1 = 0x00000060,
|
||||
.tune1_low = 0x00000060,
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -335,7 +335,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -348,7 +348,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -361,7 +361,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -373,7 +373,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -385,7 +385,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -397,7 +397,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -409,7 +409,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -422,7 +422,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -434,7 +434,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
TEGRA210_CPU_CVB_TABLE,
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -445,7 +445,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
TEGRA210_CPU_CVB_TABLE,
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune1 = 0x25501d0,
|
||||
.tune1_low = 0x25501d0,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -457,7 +457,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -470,7 +470,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x25501d0,
|
||||
.tune1_low = 0x25501d0,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -482,7 +482,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
TEGRA210_CPU_CVB_TABLE_XA,
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune1 = 0x17711BD,
|
||||
.tune1_low = 0x17711BD,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -494,7 +494,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -507,7 +507,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x25501d0,
|
||||
.tune1_low = 0x25501d0,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -519,7 +519,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
TEGRA210_CPU_CVB_TABLE,
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -530,7 +530,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
TEGRA210_CPU_CVB_TABLE,
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune1 = 0x25501d0,
|
||||
.tune1_low = 0x25501d0,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -542,7 +542,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -555,7 +555,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x25501d0,
|
||||
.tune1_low = 0x25501d0,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -568,7 +568,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x20091d9,
|
||||
.tune1_low = 0x20091d9,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
@@ -581,12 +581,157 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0xffead0ff,
|
||||
.tune0_high = 0xffead0ff,
|
||||
.tune1 = 0x25501d0,
|
||||
.tune1_low = 0x25501d0,
|
||||
.tune_high_min_millivolts = 864,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static const unsigned long tegra210b01_cpu_max_freq_table[] = {
|
||||
[0] = 1963500000UL,
|
||||
[1] = 1963500000UL,
|
||||
[2] = 2091000000UL,
|
||||
[3] = 2014500000UL,
|
||||
};
|
||||
|
||||
#define CPUB01_CVB_TABLE_SLT_B1 \
|
||||
.speedo_scale = 100, \
|
||||
.voltage_scale = 1000, \
|
||||
.entries = { \
|
||||
{ 204000000UL, { 732856, -17335, 113 } }, \
|
||||
{ 306000000UL, { 760024, -18195, 113 } }, \
|
||||
{ 408000000UL, { 789258, -19055, 113 } }, \
|
||||
{ 510000000UL, { 820558, -19915, 113 } }, \
|
||||
{ 612000000UL, { 853926, -20775, 113 } }, \
|
||||
{ 714000000UL, { 889361, -21625, 113 } }, \
|
||||
{ 816000000UL, { 926862, -22485, 113 } }, \
|
||||
{ 918000000UL, { 966431, -23345, 113 } }, \
|
||||
{ 1020000000UL, { 1008066, -24205, 113 } }, \
|
||||
{ 1122000000UL, { 1051768, -25065, 113 } }, \
|
||||
{ 1224000000UL, { 1097537, -25925, 113 } }, \
|
||||
{ 1326000000UL, { 1145373, -26785, 113 } }, \
|
||||
{ 1428000000UL, { 1195276, -27645, 113 } }, \
|
||||
{ 1581000000UL, { 1274006, -28935, 113 } }, \
|
||||
{ 1683000000UL, { 1329076, -29795, 113 } }, \
|
||||
{ 1785000000UL, { 1386213, -30655, 113 } }, \
|
||||
{ 1887000000UL, { 1445416, -31515, 113 } }, \
|
||||
{ 1963500000UL, { 1490873, -32155, 113 } }, \
|
||||
{ 2065500000UL, { 1553683, -33015, 113 } }, \
|
||||
{ 2091000000UL, { 1580725, -33235, 113 } }, \
|
||||
{ 0UL, { 0, 0, 0 } }, \
|
||||
}
|
||||
|
||||
#define CPUB01_CVB_TABLE_SLT_B0 \
|
||||
.speedo_scale = 100, \
|
||||
.voltage_scale = 1000, \
|
||||
.entries = { \
|
||||
{ 204000000UL, { 732856, -17335, 113 } }, \
|
||||
{ 306000000UL, { 760024, -18195, 113 } }, \
|
||||
{ 408000000UL, { 789258, -19055, 113 } }, \
|
||||
{ 510000000UL, { 820558, -19915, 113 } }, \
|
||||
{ 612000000UL, { 853926, -20775, 113 } }, \
|
||||
{ 714000000UL, { 889361, -21625, 113 } }, \
|
||||
{ 816000000UL, { 926862, -22485, 113 } }, \
|
||||
{ 918000000UL, { 966431, -23345, 113 } }, \
|
||||
{ 1020000000UL, { 1008066, -24205, 113 } }, \
|
||||
{ 1122000000UL, { 1051768, -25065, 113 } }, \
|
||||
{ 1224000000UL, { 1097537, -25925, 113 } }, \
|
||||
{ 1326000000UL, { 1145373, -26785, 113 } }, \
|
||||
{ 1428000000UL, { 1195276, -27645, 113 } }, \
|
||||
{ 1581000000UL, { 1274006, -28935, 113 } }, \
|
||||
{ 1683000000UL, { 1329076, -29795, 113 } }, \
|
||||
{ 1785000000UL, { 1386213, -30655, 113 } }, \
|
||||
{ 1887000000UL, { 1445416, -31515, 113 } }, \
|
||||
{ 1963500000UL, { 1490873, -32155, 113 } }, \
|
||||
{ 2065500000UL, { 1553683, -33015, 113 } }, \
|
||||
{ 2091000000UL, { 1580725, -33235, 113 } }, \
|
||||
{ 0UL, { 0, 0, 0 } }, \
|
||||
}
|
||||
|
||||
#define CPUB01_CVB_TABLE \
|
||||
.speedo_scale = 100, \
|
||||
.voltage_scale = 1000, \
|
||||
.entries = { \
|
||||
{ 204000000UL, { 721589, -12695, 27 } }, \
|
||||
{ 306000000UL, { 747134, -14195, 27 } }, \
|
||||
{ 408000000UL, { 776324, -15705, 27 } }, \
|
||||
{ 510000000UL, { 809160, -17205, 27 } }, \
|
||||
{ 612000000UL, { 845641, -18715, 27 } }, \
|
||||
{ 714000000UL, { 885768, -20215, 27 } }, \
|
||||
{ 816000000UL, { 929540, -21725, 27 } }, \
|
||||
{ 918000000UL, { 976958, -23225, 27 } }, \
|
||||
{ 1020000000UL, { 1028021, -24725, 27 } }, \
|
||||
{ 1122000000UL, { 1082730, -26235, 27 } }, \
|
||||
{ 1224000000UL, { 1141084, -27735, 27 } }, \
|
||||
{ 1326000000UL, { 1203084, -29245, 27 } }, \
|
||||
{ 1428000000UL, { 1268729, -30745, 27 } }, \
|
||||
{ 1581000000UL, { 1374032, -33005, 27 } }, \
|
||||
{ 1683000000UL, { 1448791, -34505, 27 } }, \
|
||||
{ 1785000000UL, { 1527196, -36015, 27 } }, \
|
||||
{ 1887000000UL, { 1609246, -37515, 27 } }, \
|
||||
{ 1963500000UL, { 1675751, -38635, 27 } }, \
|
||||
{ 2014500000UL, { 1716501, -39395, 27 } }, \
|
||||
{ 0UL, { 0, 0, 0 } }, \
|
||||
}
|
||||
|
||||
static struct cvb_table tegra210b01_cpu_cvb_tables[] = {
|
||||
{
|
||||
.speedo_id = 3,
|
||||
.process_id = -1,
|
||||
.max_millivolts = 1120,
|
||||
CPUB01_CVB_TABLE,
|
||||
.vmin_coefficients = { 620000, 0, 0 },
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x0000ffcf,
|
||||
.tune1_low = 0x012207ff,
|
||||
.tune1_high = 0x03FFF7FF,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
{
|
||||
.speedo_id = 2,
|
||||
.process_id = 1,
|
||||
.max_millivolts = 1120,
|
||||
CPUB01_CVB_TABLE_SLT_B1,
|
||||
.vmin_coefficients = { 600000, 0, 0 },
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x0000ffa0,
|
||||
.tune0_high = 0x0000ffff,
|
||||
.tune1_low = 0x021107ff,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
{
|
||||
.speedo_id = 2,
|
||||
.process_id = 0,
|
||||
.max_millivolts = 1120,
|
||||
CPUB01_CVB_TABLE_SLT_B0,
|
||||
.vmin_coefficients = { 600000, 0, 0 },
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x0000ff90,
|
||||
.tune0_high = 0x0000ffff,
|
||||
.tune1_low = 0x021107ff,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
{
|
||||
.speedo_id = -1,
|
||||
.process_id = -1,
|
||||
.max_millivolts = 1120,
|
||||
CPUB01_CVB_TABLE,
|
||||
.vmin_coefficients = { 620000, 0, 0 },
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x0000ffcf,
|
||||
.tune1_low = 0x012207ff,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dfll_fcpu_data tegra114_dfll_fcpu_data = {
|
||||
.cpu_max_freq_table = tegra114_cpu_max_freq_table,
|
||||
.cpu_max_freq_table_size = ARRAY_SIZE(tegra114_cpu_max_freq_table),
|
||||
@@ -608,6 +753,13 @@ static const struct dfll_fcpu_data tegra210_dfll_fcpu_data = {
|
||||
.cpu_cvb_tables_size = ARRAY_SIZE(tegra210_cpu_cvb_tables),
|
||||
};
|
||||
|
||||
static const struct dfll_fcpu_data tegra210b01_dfll_fcpu_data = {
|
||||
.cpu_max_freq_table = tegra210b01_cpu_max_freq_table,
|
||||
.cpu_max_freq_table_size = ARRAY_SIZE(tegra210b01_cpu_max_freq_table),
|
||||
.cpu_cvb_tables = tegra210b01_cpu_cvb_tables,
|
||||
.cpu_cvb_tables_size = ARRAY_SIZE(tegra210b01_cpu_cvb_tables),
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
|
||||
{
|
||||
.compatible = "nvidia,tegra114-dfll",
|
||||
@@ -621,6 +773,10 @@ static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
|
||||
.compatible = "nvidia,tegra210-dfll",
|
||||
.data = &tegra210_dfll_fcpu_data
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra210b01-dfll",
|
||||
.data = &tegra210b01_dfll_fcpu_data
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -698,7 +854,8 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
|
||||
soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables,
|
||||
fcpu_data->cpu_cvb_tables_size,
|
||||
&align, process_id, speedo_id,
|
||||
speedo_value, soc->max_freq);
|
||||
speedo_value, soc->max_freq,
|
||||
&soc->min_millivolts);
|
||||
soc->alignment = align;
|
||||
|
||||
if (IS_ERR(soc->cvb)) {
|
||||
@@ -707,6 +864,9 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(soc->cvb);
|
||||
}
|
||||
|
||||
soc->tune_high_min_millivolts =
|
||||
soc->cvb->cpu_dfll_data.tune_high_min_millivolts;
|
||||
|
||||
err = tegra_dfll_register(pdev, soc);
|
||||
if (err < 0) {
|
||||
tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
|
||||
|
||||
@@ -1812,7 +1812,7 @@ static struct div_nmp pllss_nmp = {
|
||||
static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = {
|
||||
{ 12000000, 600000000, 50, 1, 1, 0 },
|
||||
{ 13000000, 600000000, 46, 1, 1, 0 }, /* actual: 598.0 MHz */
|
||||
{ 38400000, 600000000, 62, 4, 1, 0 }, /* actual: 595.2 MHz */
|
||||
{ 38400000, 998400000, 78, 3, 1, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
@@ -1824,14 +1824,16 @@ static const struct clk_div_table pll_vco_post_div_table[] = {
|
||||
{ .val = 4, .div = 5 },
|
||||
{ .val = 5, .div = 6 },
|
||||
{ .val = 6, .div = 8 },
|
||||
{ .val = 7, .div = 10 },
|
||||
{ .val = 8, .div = 12 },
|
||||
{ .val = 9, .div = 16 },
|
||||
{ .val = 10, .div = 12 },
|
||||
{ .val = 7, .div = 9 },
|
||||
{ .val = 8, .div = 10 },
|
||||
{ .val = 9, .div = 12 },
|
||||
{ .val = 10, .div = 15 },
|
||||
{ .val = 11, .div = 16 },
|
||||
{ .val = 12, .div = 20 },
|
||||
{ .val = 13, .div = 24 },
|
||||
{ .val = 14, .div = 32 },
|
||||
{ .val = 12, .div = 18 },
|
||||
{ .val = 13, .div = 20 },
|
||||
{ .val = 14, .div = 24 },
|
||||
{ .val = 15, .div = 30 },
|
||||
{ .val = 16, .div = 32 },
|
||||
{ .val = 0, .div = 0 },
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -12,11 +12,11 @@
|
||||
int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
|
||||
u8 frac_width, u8 flags)
|
||||
{
|
||||
u64 divider_ux1 = parent_rate;
|
||||
s64 divider_ux1 = parent_rate;
|
||||
int mul;
|
||||
|
||||
if (!rate)
|
||||
return 0;
|
||||
return div_mask(width);
|
||||
|
||||
mul = 1 << frac_width;
|
||||
|
||||
@@ -31,13 +31,13 @@ int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
|
||||
if (flags & TEGRA_DIVIDER_INT)
|
||||
divider_ux1 *= mul;
|
||||
|
||||
if (divider_ux1 < mul)
|
||||
return 0;
|
||||
|
||||
divider_ux1 -= mul;
|
||||
|
||||
if (divider_ux1 > div_mask(width))
|
||||
return div_mask(width);
|
||||
|
||||
if (div1_5_not_allowed && (divider_ux1 > 0) && (divider_ux1 < mul))
|
||||
divider_ux1 = (flags & TEGRA_DIVIDER_ROUND_UP) ? mul : 0;
|
||||
|
||||
return divider_ux1;
|
||||
}
|
||||
+17
-2
@@ -26,6 +26,7 @@ static struct tegra_cpu_car_ops dummy_car_ops;
|
||||
struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
|
||||
|
||||
int *periph_clk_enb_refcnt;
|
||||
bool div1_5_not_allowed;
|
||||
static int periph_banks;
|
||||
static u32 *periph_state_ctx;
|
||||
static struct clk **clks;
|
||||
@@ -289,13 +290,27 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl,
|
||||
}
|
||||
}
|
||||
|
||||
if (tbl->rate)
|
||||
if (clk_set_rate(clk, tbl->rate)) {
|
||||
if (tbl->rate) {
|
||||
bool can_set_rate = true;
|
||||
|
||||
if ((tbl->flags & TEGRA_TABLE_RATE_CHANGE_OVERCLOCK) &&
|
||||
__clk_is_enabled(clk)) {
|
||||
if (tbl->rate != clk_get_rate(clk)) {
|
||||
pr_err("%s: Can't set rate %lu of %s\n",
|
||||
__func__, tbl->rate,
|
||||
__clk_get_name(clk));
|
||||
WARN_ON(1);
|
||||
}
|
||||
can_set_rate = false;
|
||||
}
|
||||
|
||||
if (can_set_rate && clk_set_rate(clk, tbl->rate)) {
|
||||
pr_err("%s: Failed to set rate %lu of %s\n",
|
||||
__func__, tbl->rate,
|
||||
__clk_get_name(clk));
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (tbl->state)
|
||||
if (clk_prepare_enable(clk)) {
|
||||
|
||||
@@ -87,6 +87,7 @@ struct tegra_clk_sync_source {
|
||||
|
||||
extern const struct clk_ops tegra_clk_sync_source_ops;
|
||||
extern int *periph_clk_enb_refcnt;
|
||||
extern bool div1_5_not_allowed;
|
||||
|
||||
struct clk *tegra_clk_register_sync_source(const char *name,
|
||||
unsigned long max_rate);
|
||||
@@ -800,14 +801,18 @@ struct clk *tegra_clk_register_sdmmc_mux_div(const char *name,
|
||||
* @parent_id: parent clock id as mentioned in device tree bindings
|
||||
* @rate: rate to set
|
||||
* @state: enable/disable
|
||||
* @flags: clock initialization flags
|
||||
*/
|
||||
struct tegra_clk_init_table {
|
||||
unsigned int clk_id;
|
||||
unsigned int parent_id;
|
||||
unsigned long rate;
|
||||
int state;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
#define TEGRA_TABLE_RATE_CHANGE_OVERCLOCK BIT(0)
|
||||
|
||||
/**
|
||||
* struct clk_duplicate - duplicate clocks
|
||||
* @clk_id: clock id as mentioned in device tree bindings
|
||||
@@ -830,6 +835,7 @@ struct tegra_clk_duplicate {
|
||||
struct tegra_clk {
|
||||
int dt_id;
|
||||
bool present;
|
||||
bool use_integer_div;
|
||||
};
|
||||
|
||||
struct tegra_devclk {
|
||||
|
||||
+13
-4
@@ -54,13 +54,18 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up)
|
||||
|
||||
static int build_opp_table(struct device *dev, const struct cvb_table *table,
|
||||
struct rail_alignment *align,
|
||||
int speedo_value, unsigned long max_freq)
|
||||
int speedo_value, unsigned long max_freq, int *vmin)
|
||||
{
|
||||
int i, ret, dfll_mv, min_mv, max_mv;
|
||||
|
||||
min_mv = round_voltage(table->min_millivolts, align, UP);
|
||||
max_mv = round_voltage(table->max_millivolts, align, DOWN);
|
||||
|
||||
dfll_mv = get_cvb_voltage(
|
||||
speedo_value, table->speedo_scale, &table->vmin_coefficients);
|
||||
dfll_mv = round_cvb_voltage(dfll_mv, table->voltage_scale, align);
|
||||
min_mv = max(min_mv, dfll_mv);
|
||||
|
||||
for (i = 0; i < MAX_DVFS_FREQS; i++) {
|
||||
const struct cvb_table_freq_entry *entry = &table->entries[i];
|
||||
|
||||
@@ -78,6 +83,9 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vmin)
|
||||
*vmin = min_mv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -90,7 +98,8 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
|
||||
* @process_id: process id of the HW module
|
||||
* @speedo_id: speedo id of the HW module
|
||||
* @speedo_value: speedo value of the HW module
|
||||
* @max_freq: highest safe clock rate
|
||||
* @max_rate: highest safe clock rate
|
||||
* @vmin: final minimum voltage returned to the caller
|
||||
*
|
||||
* On Tegra, a CVB table encodes the relationship between operating voltage
|
||||
* and safe maximal frequency for a given module (e.g. GPU or CPU). This
|
||||
@@ -103,7 +112,7 @@ const struct cvb_table *
|
||||
tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
|
||||
size_t count, struct rail_alignment *align,
|
||||
int process_id, int speedo_id, int speedo_value,
|
||||
unsigned long max_freq)
|
||||
unsigned long max_freq, int *vmin)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
@@ -118,7 +127,7 @@ tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
|
||||
continue;
|
||||
|
||||
ret = build_opp_table(dev, table, align, speedo_value,
|
||||
max_freq);
|
||||
max_freq, vmin);
|
||||
return ret ? ERR_PTR(ret) : table;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,10 @@ struct cvb_table_freq_entry {
|
||||
struct cvb_cpu_dfll_data {
|
||||
u32 tune0_low;
|
||||
u32 tune0_high;
|
||||
u32 tune1;
|
||||
u32 tune1_low;
|
||||
u32 tune1_high;
|
||||
unsigned int tune_high_min_millivolts;
|
||||
unsigned int tune_high_margin_millivolts;
|
||||
};
|
||||
|
||||
struct cvb_table {
|
||||
@@ -46,13 +48,14 @@ struct cvb_table {
|
||||
int voltage_scale;
|
||||
struct cvb_table_freq_entry entries[MAX_DVFS_FREQS];
|
||||
struct cvb_cpu_dfll_data cpu_dfll_data;
|
||||
struct cvb_coefficients vmin_coefficients;
|
||||
};
|
||||
|
||||
const struct cvb_table *
|
||||
tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
|
||||
size_t count, struct rail_alignment *align,
|
||||
int process_id, int speedo_id, int speedo_value,
|
||||
unsigned long max_freq);
|
||||
unsigned long max_freq, int *vmin);
|
||||
void tegra_cvb_remove_opp_table(struct device *dev,
|
||||
const struct cvb_table *table,
|
||||
unsigned long max_freq);
|
||||
|
||||
@@ -285,9 +285,9 @@ static void gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
gpiochip_enable_irq(&chips->chip, hwirq);
|
||||
|
||||
status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
|
||||
status &= IRQ_TYPE_EDGE_BOTH;
|
||||
if (!status)
|
||||
status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
|
||||
status = IRQ_TYPE_EDGE_BOTH;
|
||||
|
||||
if (status & IRQ_TYPE_EDGE_FALLING)
|
||||
writel_relaxed(mask, &g->set_falling);
|
||||
@@ -297,7 +297,7 @@ static void gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
static int gpio_irq_type(struct irq_data *d, unsigned trigger)
|
||||
{
|
||||
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
if (trigger & ~IRQ_TYPE_EDGE_BOTH)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -400,7 +400,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
|
||||
|
||||
mask = __gpio_mask(i);
|
||||
|
||||
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
if (trigger & ~IRQ_TYPE_EDGE_BOTH)
|
||||
return -EINVAL;
|
||||
|
||||
writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||
|
||||
@@ -160,7 +160,7 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
|
||||
rg->hlevel | rg->llevel) & mask)
|
||||
return 0;
|
||||
|
||||
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
type = IRQ_TYPE_EDGE_BOTH;
|
||||
}
|
||||
|
||||
rg->rising &= ~mask;
|
||||
|
||||
@@ -1263,14 +1263,14 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||
gc = irq_get_domain_generic_chip(mvchip->domain, 0);
|
||||
gc->private = mvchip;
|
||||
ct = &gc->chip_types[0];
|
||||
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
|
||||
ct->type = IRQ_TYPE_LEVEL_MASK;
|
||||
ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
|
||||
ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
|
||||
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
|
||||
ct->chip.name = mvchip->chip.label;
|
||||
|
||||
ct = &gc->chip_types[1];
|
||||
ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
ct->type = IRQ_TYPE_EDGE_BOTH;
|
||||
ct->chip.irq_ack = mvebu_gpio_irq_ack;
|
||||
ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
|
||||
ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
|
||||
|
||||
@@ -198,7 +198,7 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
|
||||
gc->private = port;
|
||||
|
||||
ct = &gc->chip_types[0];
|
||||
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
|
||||
ct->type = IRQ_TYPE_LEVEL_MASK;
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_disable_reg;
|
||||
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
|
||||
@@ -210,7 +210,7 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
|
||||
ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR;
|
||||
|
||||
ct = &gc->chip_types[1];
|
||||
ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
ct->type = IRQ_TYPE_EDGE_BOTH;
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_disable_reg;
|
||||
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
|
||||
|
||||
@@ -432,8 +432,7 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
if (type & ~IRQ_TYPE_SENSE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if (!bank->regs->leveldetect0 &&
|
||||
(type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
|
||||
if (!bank->regs->leveldetect0 && (type & IRQ_TYPE_LEVEL_MASK))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock_irqsave(&bank->lock, flags);
|
||||
@@ -450,9 +449,9 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
/*
|
||||
* Edge IRQs are already cleared/acked in irq_handler and
|
||||
* not need to be masked, as result handle_edge_irq()
|
||||
@@ -702,7 +701,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
|
||||
* after enabing the interrupt to clear the wakeup status.
|
||||
*/
|
||||
if (bank->regs->leveldetect0 && bank->regs->wkup_en &&
|
||||
trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
|
||||
trigger & IRQ_TYPE_LEVEL_MASK)
|
||||
omap_clear_gpio_irqstatus(bank, offset);
|
||||
|
||||
if (trigger)
|
||||
|
||||
@@ -132,8 +132,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
if (offset < 0 || offset >= PL061_GPIO_NR)
|
||||
return -EINVAL;
|
||||
|
||||
if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
|
||||
(trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))
|
||||
if ((trigger & IRQ_TYPE_LEVEL_MASK) && (trigger & IRQ_TYPE_EDGE_BOTH))
|
||||
{
|
||||
dev_err(gc->parent,
|
||||
"trying to configure line %d for both level and edge "
|
||||
@@ -149,7 +148,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
gpiois = readb(pl061->base + GPIOIS);
|
||||
gpioibe = readb(pl061->base + GPIOIBE);
|
||||
|
||||
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
|
||||
if (trigger & IRQ_TYPE_LEVEL_MASK) {
|
||||
bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
|
||||
|
||||
/* Disable edge detection */
|
||||
|
||||
@@ -406,7 +406,7 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
|
||||
if (__gpio_is_occupied(pchip, gpio))
|
||||
return 0;
|
||||
|
||||
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
type = IRQ_TYPE_EDGE_BOTH;
|
||||
}
|
||||
|
||||
gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
|
||||
|
||||
@@ -169,9 +169,9 @@ static int rda_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
if (flow_type & IRQ_TYPE_LEVEL_MASK)
|
||||
irq_set_handler_locked(data, handle_level_irq);
|
||||
else if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
else if (flow_type & IRQ_TYPE_EDGE_BOTH)
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -134,7 +134,7 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
|
||||
if (type == IRQ_TYPE_PROBE) {
|
||||
if ((sgc->irqrising | sgc->irqfalling) & mask)
|
||||
return 0;
|
||||
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
type = IRQ_TYPE_EDGE_BOTH;
|
||||
}
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
|
||||
@@ -158,7 +158,7 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
|
||||
|
||||
sd->gc->private = sd;
|
||||
ct = sd->gc->chip_types;
|
||||
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
|
||||
ct->type = IRQ_TYPE_LEVEL_MASK;
|
||||
ct->regs.eoi = GPSTR;
|
||||
ct->regs.mask = GPIO_INT;
|
||||
ct->chip.irq_mask = irq_gc_mask_clr_bit;
|
||||
|
||||
@@ -149,7 +149,7 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
int regoffset = offset / 8;
|
||||
int mask = BIT(offset % 8);
|
||||
|
||||
if (type & IRQ_TYPE_LEVEL_LOW || type & IRQ_TYPE_LEVEL_HIGH)
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
/* STMPE801 and STMPE 1600 don't have RE and FE registers */
|
||||
|
||||
@@ -172,18 +172,11 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
|
||||
tegra_gpio_enable(tgi, offset);
|
||||
|
||||
ret = pinctrl_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
dev_err(tgi->dev,
|
||||
"Failed to set pinctrl input direction of GPIO %d: %d",
|
||||
chip->base + offset, ret);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gpio_direction_output(struct gpio_chip *chip,
|
||||
@@ -191,19 +184,12 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip,
|
||||
int value)
|
||||
{
|
||||
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
tegra_gpio_set(chip, offset, value);
|
||||
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
|
||||
tegra_gpio_enable(tgi, offset);
|
||||
|
||||
ret = pinctrl_gpio_direction_output(chip, offset);
|
||||
if (ret < 0)
|
||||
dev_err(tgi->dev,
|
||||
"Failed to set pinctrl output direction of GPIO %d: %d",
|
||||
chip->base + offset, ret);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gpio_get_direction(struct gpio_chip *chip,
|
||||
@@ -356,9 +342,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
|
||||
if (d->parent_data)
|
||||
@@ -722,7 +708,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)
|
||||
tgi->gc.direction_output = tegra_gpio_direction_output;
|
||||
tgi->gc.set = tegra_gpio_set;
|
||||
tgi->gc.get_direction = tegra_gpio_get_direction;
|
||||
tgi->gc.base = 0;
|
||||
tgi->gc.ngpio = tgi->bank_count * 32;
|
||||
tgi->gc.parent = &pdev->dev;
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
|
||||
if (ver > 2)
|
||||
bflr = ioread32(tgpio->membase + TGPIO_BFLR);
|
||||
|
||||
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
|
||||
if (trigger & IRQ_TYPE_LEVEL_MASK) {
|
||||
bflr &= ~(1 << offset);
|
||||
flr &= ~(1 << offset);
|
||||
if (trigger & IRQ_TYPE_LEVEL_HIGH)
|
||||
|
||||
@@ -4,7 +4,6 @@ config DRM_NOUVEAU
|
||||
depends on DRM && PCI
|
||||
select IOMMU_API
|
||||
select FW_LOADER
|
||||
select FW_CACHE if PM_SLEEP
|
||||
select DRM_CLIENT_SELECTION
|
||||
select DRM_DISPLAY_DP_HELPER
|
||||
select DRM_DISPLAY_HDMI_HELPER
|
||||
|
||||
@@ -134,5 +134,6 @@ int gf100_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
|
||||
int gk104_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||
int gk20a_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||
int gm20b_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||
int gm20b_b01_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||
int gp10b_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||
#endif
|
||||
@@ -42,4 +42,5 @@ int gf117_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
|
||||
int gk104_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
|
||||
int gk20a_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
|
||||
int gm20b_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
|
||||
int gm20b_b01_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
|
||||
#endif
|
||||
@@ -73,7 +73,7 @@ nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags)
|
||||
enum ttm_caching caching;
|
||||
|
||||
if (nvbo->force_coherent)
|
||||
caching = ttm_uncached;
|
||||
caching = ttm_write_combined;
|
||||
else if (drm->agp.bridge)
|
||||
caching = ttm_write_combined;
|
||||
else
|
||||
|
||||
@@ -2072,6 +2072,31 @@ nv12b_chipset = {
|
||||
.sw = { 0x00000001, gf100_sw_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
nv12e_chipset = {
|
||||
.name = "GM20B",
|
||||
.acr = { 0x00000001, gm20b_acr_new },
|
||||
.bar = { 0x00000001, gm20b_bar_new },
|
||||
.bus = { 0x00000001, gf100_bus_new },
|
||||
.clk = { 0x00000001, gm20b_b01_clk_new },
|
||||
.fb = { 0x00000001, gm20b_fb_new },
|
||||
.fuse = { 0x00000001, gm107_fuse_new },
|
||||
.imem = { 0x00000001, gk20a_instmem_new },
|
||||
.ltc = { 0x00000001, gm200_ltc_new },
|
||||
.mc = { 0x00000001, gk20a_mc_new },
|
||||
.mmu = { 0x00000001, gm20b_mmu_new },
|
||||
.pmu = { 0x00000001, gm20b_pmu_new },
|
||||
.privring = { 0x00000001, gk20a_privring_new },
|
||||
.timer = { 0x00000001, gk20a_timer_new },
|
||||
.top = { 0x00000001, gk104_top_new },
|
||||
.volt = { 0x00000001, gm20b_b01_volt_new },
|
||||
.ce = { 0x00000004, gm200_ce_new },
|
||||
.dma = { 0x00000001, gf119_dma_new },
|
||||
.fifo = { 0x00000001, gm200_fifo_new },
|
||||
.gr = { 0x00000001, gm20b_gr_new },
|
||||
.sw = { 0x00000001, gf100_sw_new },
|
||||
};
|
||||
|
||||
static const struct nvkm_device_chip
|
||||
nv130_chipset = {
|
||||
.name = "GP100",
|
||||
@@ -3328,6 +3353,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
|
||||
case 0x124: device->chip = &nv124_chipset; break;
|
||||
case 0x126: device->chip = &nv126_chipset; break;
|
||||
case 0x12b: device->chip = &nv12b_chipset; break;
|
||||
case 0x12e: device->chip = &nv12e_chipset; break;
|
||||
case 0x130: device->chip = &nv130_chipset; break;
|
||||
case 0x132: device->chip = &nv132_chipset; break;
|
||||
case 0x134: device->chip = &nv134_chipset; break;
|
||||
|
||||
@@ -717,6 +717,112 @@ gm20b_pstates[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct nvkm_pstate
|
||||
gm20b_b01_pstates[] = {
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 76800,
|
||||
.voltage = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 153600,
|
||||
.voltage = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 230400,
|
||||
.voltage = 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 307200,
|
||||
.voltage = 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 384000,
|
||||
.voltage = 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 460800,
|
||||
.voltage = 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 537600,
|
||||
.voltage = 6,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 614400,
|
||||
.voltage = 7,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 691200,
|
||||
.voltage = 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 768000,
|
||||
.voltage = 9,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 844800,
|
||||
.voltage = 10,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 921600,
|
||||
.voltage = 11,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 998400,
|
||||
.voltage = 12,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 1075200,
|
||||
.voltage = 13,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 1152000,
|
||||
.voltage = 14,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 1228800,
|
||||
.voltage = 15,
|
||||
},
|
||||
},
|
||||
{
|
||||
.base = {
|
||||
.domain[nv_clk_src_gpc] = 1267200,
|
||||
.voltage = 16,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static void
|
||||
gm20b_clk_fini(struct nvkm_clk *base)
|
||||
{
|
||||
@@ -912,6 +1018,23 @@ gm20b_clk = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct nvkm_clk_func
|
||||
gm20b_b01_clk = {
|
||||
.init = gm20b_clk_init,
|
||||
.fini = gk20a_clk_fini,
|
||||
.read = gk20a_clk_read,
|
||||
.calc = gk20a_clk_calc,
|
||||
.prog = gk20a_clk_prog,
|
||||
.tidy = gk20a_clk_tidy,
|
||||
.pstates = gm20b_b01_pstates,
|
||||
.nr_pstates = ARRAY_SIZE(gm20b_b01_pstates),
|
||||
.domains = {
|
||||
{ nv_clk_src_crystal, 0xff },
|
||||
{ nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
|
||||
{ nv_clk_src_max },
|
||||
},
|
||||
};
|
||||
|
||||
static int
|
||||
gm20b_clk_new_speedo0(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_clk **pclk)
|
||||
@@ -1074,3 +1197,63 @@ gm20b_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
gm20b_b01_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_clk **pclk)
|
||||
{
|
||||
struct nvkm_device_tegra *tdev = device->func->tegra(device);
|
||||
struct gm20b_clk *clk;
|
||||
struct nvkm_subdev *subdev;
|
||||
struct gk20a_clk_pllg_params *clk_params;
|
||||
int ret;
|
||||
|
||||
/* Speedo 0 GPUs cannot use noise-aware PLL */
|
||||
if (tdev->gpu_speedo_id == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Speedo >= 1, use NAPLL */
|
||||
clk = kzalloc(sizeof(*clk) + sizeof(*clk_params), GFP_KERNEL);
|
||||
if (!clk)
|
||||
return -ENOMEM;
|
||||
*pclk = &clk->base.base;
|
||||
subdev = &clk->base.base.subdev;
|
||||
|
||||
/* duplicate the clock parameters since we will patch them below */
|
||||
clk_params = (void *) (clk + 1);
|
||||
*clk_params = gm20b_pllg_params;
|
||||
ret = gk20a_clk_ctor(device, type, inst, &gm20b_b01_clk, clk_params, &clk->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* NAPLL can only work with max_u, clamp the m range so
|
||||
* gk20a_pllg_calc_mnp always uses it
|
||||
*/
|
||||
clk_params->max_m = clk_params->min_m = DIV_ROUND_UP(clk_params->max_u,
|
||||
(clk->base.parent_rate / KHZ));
|
||||
if (clk_params->max_m == 0) {
|
||||
nvkm_error(subdev, "cannot use NAPLL, and legacy clock unavailable...\n");
|
||||
kfree(clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
clk->base.pl_to_div = pl_to_div;
|
||||
clk->base.div_to_pl = div_to_pl;
|
||||
|
||||
clk->dvfs_params = &gm20b_dvfs_params;
|
||||
|
||||
ret = gm20b_clk_init_fused_params(clk);
|
||||
/*
|
||||
* we will calibrate during init - should never happen on
|
||||
* prod parts
|
||||
*/
|
||||
if (ret)
|
||||
nvkm_warn(subdev, "no fused calibration parameters\n");
|
||||
|
||||
ret = gm20b_clk_init_safe_fmax(clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -91,3 +91,54 @@ gm20b_volt_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
return gk20a_volt_ctor(device, type, inst, gm20b_cvb_coef,
|
||||
ARRAY_SIZE(gm20b_cvb_coef), vmin, volt);
|
||||
}
|
||||
|
||||
static const struct cvb_coef gm20b_b01_na_cvb_coef[] = {
|
||||
/* KHz, c0, c1, c2, c3, c4, c5 */
|
||||
/* 76800 */ { 610000, 0, 0, 0, 0, 0 },
|
||||
/* 153600 */ { 610000, 0, 0, 0, 0, 0 },
|
||||
/* 230400 */ { 610000, 0, 0, 0, 0, 0 },
|
||||
/* 307200 */ { 610000, 0, 0, 0, 0, 0 },
|
||||
/* 384000 */ { 610000, 0, 0, 0, 0, 0 },
|
||||
/* 460800 */ { 610000, 0, 0, 0, 0, 0 },
|
||||
/* 537600 */ { 801688, -10900, -163, 298, -10599, 162 },
|
||||
/* 614400 */ { 824214, -5743, -452, 238, -6325, 81 },
|
||||
/* 691200 */ { 848830, -3903, -552, 119, -4030, -2 },
|
||||
/* 768000 */ { 891575, -4409, -584, 0, -2849, 39 },
|
||||
/* 844800 */ { 940071, -5367, -602, -60, -63, -93 },
|
||||
/* 921600 */ { 986765, -6637, -614, -179, 1905, -13 },
|
||||
/* 998400 */ { 1098475, -13529, -497, -179, 3626, 9 },
|
||||
/* 1075200 */ { 1163644, -12688, -648, 0, 1077, 40 },
|
||||
/* 1152000 */ { 1204812, -9908, -830, 0, 1469, 110 },
|
||||
/* 1228800 */ { 1277303, -11675, -859, 0, 3722, 313 },
|
||||
/* 1267200 */ { 1335531, -12567, -867, 0, 3681, 559 },
|
||||
};
|
||||
|
||||
int
|
||||
gm20b_b01_volt_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
struct nvkm_volt **pvolt)
|
||||
{
|
||||
struct nvkm_device_tegra *tdev = device->func->tegra(device);
|
||||
struct gk20a_volt *volt;
|
||||
u32 vmin;
|
||||
|
||||
if (tdev->gpu_speedo_id >= ARRAY_SIZE(speedo_to_vmin)) {
|
||||
nvdev_error(device, "unsupported speedo %d\n",
|
||||
tdev->gpu_speedo_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
volt = kzalloc(sizeof(*volt), GFP_KERNEL);
|
||||
if (!volt)
|
||||
return -ENOMEM;
|
||||
*pvolt = &volt->base;
|
||||
|
||||
vmin = speedo_to_vmin[tdev->gpu_speedo_id];
|
||||
|
||||
switch (tdev->gpu_speedo_id) {
|
||||
case 1:
|
||||
return gk20a_volt_ctor(device, type, inst, gm20b_b01_na_cvb_coef,
|
||||
ARRAY_SIZE(gm20b_b01_na_cvb_coef), vmin, volt);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -354,6 +354,15 @@ config DRM_PANEL_JDI_LPM102A188A
|
||||
The panel has a 2560×1800 resolution. It provides a MIPI DSI interface
|
||||
to the host.
|
||||
|
||||
config DRM_PANEL_NX_DSI
|
||||
tristate "Nintendo Switch 720x1280 DSI panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for the DSI panels
|
||||
used in the Nintendo Switch.
|
||||
|
||||
config DRM_PANEL_JDI_LT070ME05000
|
||||
tristate "JDI LT070ME05000 WUXGA DSI panel"
|
||||
depends on OF
|
||||
|
||||
@@ -62,6 +62,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37700F) += panel-novatek-nt37700f.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37801) += panel-novatek-nt37801.o
|
||||
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
|
||||
obj-$(CONFIG_DRM_PANEL_NX_DSI) += panel-nx-dsi.o
|
||||
obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
|
||||
obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
|
||||
obj-$(CONFIG_DRM_PANEL_ORISETECH_OTA5601A) += panel-orisetech-ota5601a.o
|
||||
|
||||
@@ -0,0 +1,772 @@
|
||||
/*
|
||||
* Copyright (C) 2018 SwtcR <swtcr0@gmail.com>
|
||||
* Copyright (C) 2023-2024 Azkali <a.ffcc7@gmail.com>
|
||||
*
|
||||
* Based on Sharp ls043t1le01 panel driver by Werner Johansson <werner.johansson@sonymobile.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_modes.h>
|
||||
|
||||
/*! MIPI DCS Panel Private CMDs. */
|
||||
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE ((u8)0xA0)
|
||||
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET ((u8)0xB0)
|
||||
#define MIPI_DCS_PRIV_SM_SET_ELVSS ((u8)0xB1) /* OLED backlight tuning. Byte7: PWM transition time in frames. */
|
||||
#define MIPI_DCS_PRIV_SET_POWER_CONTROL ((u8)0xB1)
|
||||
#define MIPI_DCS_PRIV_SET_EXTC ((u8)0xB9) /* Enable extended commands. */
|
||||
#define MIPI_DCS_PRIV_UNK_BD ((u8)0xBD)
|
||||
#define MIPI_DCS_PRIV_UNK_D5 ((u8)0xD5)
|
||||
#define MIPI_DCS_PRIV_UNK_D6 ((u8)0xD6)
|
||||
#define MIPI_DCS_PRIV_UNK_D8 ((u8)0xD8)
|
||||
#define MIPI_DCS_PRIV_UNK_D9 ((u8)0xD9)
|
||||
|
||||
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK ((u8)0xE2)
|
||||
|
||||
/* BL Control */
|
||||
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT ((u8)BIT(2))
|
||||
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL ((u8)BIT(2))
|
||||
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL ((u8)BIT(3))
|
||||
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL ((u8)BIT(5))
|
||||
|
||||
/* OLED Panels color mode */
|
||||
#define DCS_SM_COLOR_MODE_SATURATED ((u8)0x00) /* Disabled. Similar to vivid but over-saturated. Wide gamut? */
|
||||
#define DCS_SM_COLOR_MODE_WASHED ((u8)0x45)
|
||||
#define DCS_SM_COLOR_MODE_BASIC ((u8)0x03)
|
||||
#define DCS_SM_COLOR_MODE_POR_RESET ((u8)0x20) /* Reset value on power on. */
|
||||
#define DCS_SM_COLOR_MODE_NATURAL ((u8)0x23) /* Not actually natural.. */
|
||||
#define DCS_SM_COLOR_MODE_VIVID ((u8)0x65)
|
||||
#define DCS_SM_COLOR_MODE_NIGHT0 ((u8)0x43) /* Based on washed out. */
|
||||
#define DCS_SM_COLOR_MODE_NIGHT1 ((u8)0x15) /* Based on basic. */
|
||||
#define DCS_SM_COLOR_MODE_NIGHT2 ((u8)0x35) /* Based on natural. */
|
||||
#define DCS_SM_COLOR_MODE_NIGHT3 ((u8)0x75) /* Based on vivid. */
|
||||
|
||||
#define DCS_SM_COLOR_MODE_ENABLE ((u8)BIT(0))
|
||||
|
||||
enum
|
||||
{
|
||||
PANEL_JDI_XXX062M = 0x10,
|
||||
PANEL_JDI_LAM062M109A = 0x0910,
|
||||
PANEL_JDI_LPM062M326A = 0x2610,
|
||||
PANEL_INL_P062CCA_AZ1 = 0x0F20,
|
||||
PANEL_AUO_A062TAN01 = 0x0F30,
|
||||
PANEL_INL_2J055IA_27A = 0x1020,
|
||||
PANEL_AUO_A055TAN01 = 0x1030,
|
||||
PANEL_SHP_LQ055T1SW10 = 0x1040,
|
||||
PANEL_SAM_AMS699VC01 = 0x2050,
|
||||
PANEL_RR_SUPER5_OLED_V1 = 0x10E0,
|
||||
PANEL_RR_SUPER5_OLED_HD_V1 = 0x10E1,
|
||||
PANEL_RR_SUPER7_IPS_V1 = 0x0FE0,
|
||||
PANEL_RR_SUPER7_IPS_HD_V1 = 0x0FE1,
|
||||
PANEL_RR_SUPER7_OLED_7_V1 = 0x20E0,
|
||||
PANEL_RR_SUPER7_OLED_HD_7_V1 = 0x20E1,
|
||||
|
||||
// Found on 6/2" clones. Unknown markings. Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F].
|
||||
PANEL_OEM_CLONE_6_2 = 0x0F83,
|
||||
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
|
||||
PANEL_OEM_CLONE_5_5 = 0x00B3,
|
||||
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
|
||||
PANEL_OEM_CLONE = 0x0000
|
||||
};
|
||||
|
||||
struct init_cmd {
|
||||
u8 cmd;
|
||||
int length;
|
||||
u8 data[64];
|
||||
};
|
||||
|
||||
struct nx_panel {
|
||||
struct drm_panel base;
|
||||
struct mipi_dsi_device *dsi;
|
||||
|
||||
struct backlight_device *backlight;
|
||||
struct regulator *supply1;
|
||||
struct regulator *supply2;
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
bool prepared;
|
||||
bool enabled;
|
||||
|
||||
const struct drm_display_mode *mode;
|
||||
|
||||
struct init_cmd *init_cmds;
|
||||
struct init_cmd *suspend_cmds;
|
||||
|
||||
u16 display_id;
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_default[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
120,
|
||||
},
|
||||
{ MIPI_DCS_SET_DISPLAY_ON, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
20,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_JDI_XXX062M[] = {
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x00, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D8, 24, { 0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x01, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D8,
|
||||
38,
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x02, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D8,
|
||||
14,
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x00, 0x00 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D9, 2, { 0x06, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0x00, 0x00, 0x00 } },
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
{ MIPI_DCS_SET_DISPLAY_ON, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
20,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_JDI_XXX062M[] = {
|
||||
{ MIPI_DCS_SET_DISPLAY_OFF, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D5,
|
||||
32,
|
||||
{ 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
|
||||
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
|
||||
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 } },
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL,
|
||||
10,
|
||||
{ 0x41, 0x0F, 0x4F, 0x33, 0xA4, 0x79, 0xF1, 0x81, 0x2D, 0x00 } },
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0x00, 0x00, 0x00 } },
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_SAM_AMS699VC01[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
|
||||
// Set color mode to basic (natural). Stock is Saturated (0x00). (Reset value is 0x20).
|
||||
{ MIPI_DCS_PRIV_SM_SET_COLOR_MODE, 2, { 0x23, 0x0 } },
|
||||
|
||||
// Enable backlight and smooth PWM.
|
||||
{ MIPI_DCS_WRITE_CONTROL_DISPLAY, 2, { 0x28, 0x0 } },
|
||||
|
||||
// Unlock Level 2 registers.
|
||||
{ 0x05, 9, { 0x0, 0x0, 0xE2, 0x5A, 0x5A, 0x5A, 0x5A, 0x0, 0x0 } },
|
||||
|
||||
// Set registers offset and set PWM transition to 6 frames (100ms).
|
||||
{ MIPI_DCS_PRIV_SM_SET_REG_OFFSET, 2, { 0x07, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_SM_SET_ELVSS, 2, { 0x06, 0x0 } },
|
||||
|
||||
// Relock Level 2 registers.
|
||||
{ 0x05, 9, { 0x0, 0x0, 0xE2, 0x5A, 0x5A, 0xA5, 0xA5, 0x0, 0x0 } },
|
||||
|
||||
// MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%.
|
||||
{ 0x03, 7, { 0x00, 0x00, 0x51, 0x0, 0x0, 0x0, 0x0 } },
|
||||
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_AUO_A062TAN01[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 6, { 0x48, 0x11, 0x71, 0x09, 0x32, 0x14 } },
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_AUO_A062TAN01[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_AUO_A055TAN01[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x11, 0x71, 0x09, 0x32, 0x14, 0x71, 0x31, 0x4D, 0x11 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_INL_P062CCA_AZ1[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 6, { 0x48, 0x15, 0x75, 0x09, 0x32, 0x14 } },
|
||||
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_INL_2J055IA_27A[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x15, 0x75, 0x09, 0x32, 0x14, 0x71, 0x31, 0x4D, 0x11 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_SHP_LQ055T1SW10[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x13, 0x73, 0x09, 0x32, 0x24, 0x71, 0x31, 0x4C, 0x00 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_SAM_AMS699VC01[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
120,
|
||||
},
|
||||
};
|
||||
|
||||
static inline struct nx_panel *to_nx_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct nx_panel, base);
|
||||
}
|
||||
|
||||
static void nx_panel_detect(struct nx_panel *nx)
|
||||
{
|
||||
int ret;
|
||||
nx->init_cmds = NULL;
|
||||
nx->suspend_cmds = NULL;
|
||||
|
||||
memset(&(nx->display_id), 0, sizeof(nx->display_id));
|
||||
|
||||
ret = mipi_dsi_dcs_read(nx->dsi, MIPI_DCS_GET_DISPLAY_ID,
|
||||
&(nx->display_id), sizeof(nx->display_id));
|
||||
if (ret < 0) {
|
||||
dev_err(&nx->dsi->dev, "failed to read panel ID: %d\n", ret);
|
||||
} else {
|
||||
dev_info(&nx->dsi->dev, "display ID[%d]: %04x\n",
|
||||
ret, nx->display_id);
|
||||
}
|
||||
|
||||
dev_info(&nx->dsi->dev,
|
||||
"setting init sequence for ID %04x\n", nx->display_id);
|
||||
|
||||
switch (nx->display_id) {
|
||||
case PANEL_JDI_XXX062M:
|
||||
nx->init_cmds = init_cmds_PANEL_JDI_XXX062M;
|
||||
break;
|
||||
case PANEL_SAM_AMS699VC01:
|
||||
nx->init_cmds = init_cmds_PANEL_SAM_AMS699VC01;
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
nx->init_cmds = init_cmds_PANEL_INL_P062CCA_AZ1;
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
nx->init_cmds = init_cmds_PANEL_AUO_A062TAN01;
|
||||
break;
|
||||
case PANEL_INL_2J055IA_27A:
|
||||
case PANEL_AUO_A055TAN01:
|
||||
case PANEL_SHP_LQ055T1SW10:
|
||||
default:
|
||||
dev_info(&nx->dsi->dev, "using default init sequence\n");
|
||||
nx->init_cmds = init_cmds_default;
|
||||
break;
|
||||
}
|
||||
|
||||
dev_info(&nx->dsi->dev,
|
||||
"setting suspend sequence for ID %04x\n", nx->display_id);
|
||||
|
||||
switch (nx->display_id) {
|
||||
case PANEL_JDI_XXX062M:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_JDI_XXX062M;
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_AUO_A062TAN01;
|
||||
break;
|
||||
case PANEL_INL_2J055IA_27A:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_INL_2J055IA_27A;
|
||||
break;
|
||||
case PANEL_AUO_A055TAN01:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_AUO_A055TAN01;
|
||||
break;
|
||||
case PANEL_SHP_LQ055T1SW10:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_SHP_LQ055T1SW10;
|
||||
break;
|
||||
case PANEL_SAM_AMS699VC01:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_SAM_AMS699VC01;
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
default:
|
||||
dev_info(&nx->dsi->dev, "using default suspend sequence\n");
|
||||
break;
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
static int nx_mipi_dsi_dcs_cmds(struct init_cmd *cmds, struct nx_panel *nx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (cmds && cmds->length != -1) {
|
||||
if (cmds->cmd == 0xFF)
|
||||
msleep(cmds->length);
|
||||
else {
|
||||
ret = mipi_dsi_dcs_write(nx->dsi, cmds->cmd,
|
||||
cmds->data, cmds->length);
|
||||
if (ret < 0) {
|
||||
dev_err(&nx->dsi->dev,
|
||||
"failed to write dsi_cmd: %d error: %d\n",
|
||||
cmds->cmd, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
cmds++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nx_panel_init(struct nx_panel *nx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = nx->dsi;
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = mipi_dsi_set_maximum_return_packet_size(dsi, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set maximum return packet size: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nx_panel_detect(nx);
|
||||
|
||||
ret = nx_mipi_dsi_dcs_cmds(nx->init_cmds, nx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_column_address(dsi, 0, nx->mode->hdisplay - 1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set page address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_page_address(dsi, 0, nx->mode->vdisplay - 1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set column address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set vblank tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set pixel format: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
|
||||
if (nx->enabled)
|
||||
return 0;
|
||||
|
||||
backlight_enable(nx->backlight);
|
||||
|
||||
nx->enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
|
||||
if (!nx->enabled)
|
||||
return 0;
|
||||
|
||||
backlight_disable(nx->backlight);
|
||||
|
||||
nx->enabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
int ret;
|
||||
|
||||
if (!nx->prepared)
|
||||
return 0;
|
||||
|
||||
nx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = nx_mipi_dsi_dcs_cmds(nx->suspend_cmds, nx);
|
||||
if (ret < 0)
|
||||
dev_err(&nx->dsi->dev, "failed to write suspend cmds: %d\n",
|
||||
ret);
|
||||
|
||||
if (nx->reset_gpio)
|
||||
gpiod_set_value(nx->reset_gpio, 0);
|
||||
|
||||
msleep(10);
|
||||
regulator_disable(nx->supply2);
|
||||
msleep(10);
|
||||
regulator_disable(nx->supply1);
|
||||
|
||||
nx->prepared = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
if (nx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(nx->supply1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(10);
|
||||
|
||||
ret = regulator_enable(nx->supply2);
|
||||
if (ret < 0)
|
||||
goto poweroff;
|
||||
msleep(10);
|
||||
|
||||
if (nx->reset_gpio) {
|
||||
gpiod_set_value(nx->reset_gpio, 0);
|
||||
msleep(10);
|
||||
gpiod_set_value(nx->reset_gpio, 1);
|
||||
msleep(60);
|
||||
}
|
||||
nx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = nx_panel_init(nx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to init panel: %d\n", ret);
|
||||
goto reset;
|
||||
}
|
||||
|
||||
nx->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
||||
reset:
|
||||
if (nx->reset_gpio)
|
||||
gpiod_set_value(nx->reset_gpio, 0);
|
||||
regulator_disable(nx->supply2);
|
||||
|
||||
poweroff:
|
||||
regulator_disable(nx->supply1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode default_mode = {
|
||||
.clock = 78000,
|
||||
.hdisplay = 720,
|
||||
.hsync_start = 720 + 136,
|
||||
.hsync_end = 720 + 136 + 72,
|
||||
.htotal = 720 + 136 + 72 + 72,
|
||||
.vdisplay = 1280,
|
||||
.vsync_start = 1280 + 10,
|
||||
.vsync_end = 1280 + 10 + 2,
|
||||
.vtotal = 1280 + 10 + 1 + 9,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static int nx_panel_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &default_mode);
|
||||
if (!mode) {
|
||||
dev_err(dev, "failed to add mode %ux%ux@%u\n",
|
||||
default_mode.hdisplay, default_mode.vdisplay,
|
||||
drm_mode_vrefresh(&default_mode));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
connector->display_info.width_mm = 77;
|
||||
connector->display_info.height_mm = 137;
|
||||
connector->display_info.bpc = 8;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs nx_panel_funcs = {
|
||||
.prepare = nx_panel_prepare,
|
||||
.unprepare = nx_panel_unprepare,
|
||||
.enable = nx_panel_enable,
|
||||
.disable = nx_panel_disable,
|
||||
.get_modes = nx_panel_get_modes,
|
||||
};
|
||||
|
||||
static int nx_panel_add(struct nx_panel *nx)
|
||||
{
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
struct device_node *np;
|
||||
|
||||
nx->mode = &default_mode;
|
||||
|
||||
nx->supply1 = devm_regulator_get(dev, "vdd1");
|
||||
if (IS_ERR(nx->supply1))
|
||||
return PTR_ERR(nx->supply1);
|
||||
|
||||
nx->supply2 = devm_regulator_get(dev, "vdd2");
|
||||
if (IS_ERR(nx->supply2))
|
||||
return PTR_ERR(nx->supply2);
|
||||
|
||||
nx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(nx->reset_gpio)) {
|
||||
dev_err(dev, "cannot get reset-gpios %ld\n",
|
||||
PTR_ERR(nx->reset_gpio));
|
||||
nx->reset_gpio = NULL;
|
||||
} else {
|
||||
gpiod_set_value(nx->reset_gpio, 0);
|
||||
}
|
||||
|
||||
usleep_range(2000, 4000);
|
||||
|
||||
np = of_parse_phandle(dev->of_node, "backlight", 0);
|
||||
if (np) {
|
||||
nx->backlight = of_find_backlight_by_node(np);
|
||||
of_node_put(np);
|
||||
|
||||
if (!nx->backlight)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
drm_panel_init(&nx->base, &nx->dsi->dev, &nx_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
drm_panel_add(&nx->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nx_panel_del(struct nx_panel *nx)
|
||||
{
|
||||
if (nx->base.dev)
|
||||
drm_panel_remove(&nx->base);
|
||||
|
||||
if (nx->backlight)
|
||||
put_device(&nx->backlight->dev);
|
||||
}
|
||||
|
||||
static int nx_panel_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct nx_panel *nx;
|
||||
int ret;
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS |
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
nx = devm_kzalloc(&dsi->dev, sizeof(*nx), GFP_KERNEL);
|
||||
if (!nx)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, nx);
|
||||
|
||||
nx->dsi = dsi;
|
||||
|
||||
ret = nx_panel_add(nx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
nx_panel_del(nx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nx_panel_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct nx_panel *nx = mipi_dsi_get_drvdata(dsi);
|
||||
int ret;
|
||||
|
||||
ret = nx_panel_disable(&nx->base);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
|
||||
|
||||
ret = mipi_dsi_detach(dsi);
|
||||
if (ret < 0)
|
||||
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
|
||||
|
||||
nx_panel_del(nx);
|
||||
}
|
||||
|
||||
static void nx_panel_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct nx_panel *nx = mipi_dsi_get_drvdata(dsi);
|
||||
nx_panel_disable(&nx->base);
|
||||
}
|
||||
|
||||
static const struct of_device_id nx_panel_of_match[] = {
|
||||
{
|
||||
.compatible = "nintendo,nx-dsi",
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, nx_panel_of_match);
|
||||
|
||||
static struct mipi_dsi_driver nx_panel_driver = {
|
||||
.driver = {
|
||||
.name = "panel-nx-dsi",
|
||||
.of_match_table = nx_panel_of_match,
|
||||
},
|
||||
.probe = nx_panel_probe,
|
||||
.remove = nx_panel_remove,
|
||||
.shutdown = nx_panel_shutdown,
|
||||
};
|
||||
module_mipi_dsi_driver(nx_panel_driver);
|
||||
|
||||
MODULE_AUTHOR("SwtcR <swtcr0@gmail.com>");
|
||||
MODULE_DESCRIPTION("Nintendo Switch DSI (720x1280) panel driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -25,6 +25,7 @@ tegra-drm-y := \
|
||||
falcon.o \
|
||||
vic.o \
|
||||
nvdec.o \
|
||||
nvenc.o \
|
||||
nvjpg.o \
|
||||
riscv.o
|
||||
|
||||
|
||||
@@ -36,6 +36,103 @@
|
||||
#include "hub.h"
|
||||
#include "plane.h"
|
||||
|
||||
static const u16 default_srgb_lut[] = {
|
||||
0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4, 0x6469, 0x64F0, 0x656B, 0x65DF, 0x664A,
|
||||
0x66B0, 0x6711, 0x676D, 0x67C4, 0x6819, 0x686A, 0x68B8, 0x6904, 0x694D, 0x6994, 0x69D8,
|
||||
0x6A1B, 0x6A5D, 0x6A9C, 0x6ADA, 0x6B17, 0x6B52, 0x6B8C, 0x6BC5, 0x6BFD, 0x6C33, 0x6C69,
|
||||
0x6C9E, 0x6CD1, 0x6D04, 0x6D36, 0x6D67, 0x6D98, 0x6DC7, 0x6DF6, 0x6E25, 0x6E52, 0x6E7F,
|
||||
0x6EAC, 0x6ED7, 0x6F03, 0x6F2D, 0x6F58, 0x6F81, 0x6FAA, 0x6FD3, 0x6FFB, 0x7023, 0x704B,
|
||||
0x7071, 0x7098, 0x70BE, 0x70E4, 0x7109, 0x712E, 0x7153, 0x7177, 0x719B, 0x71BF, 0x71E2,
|
||||
0x7205, 0x7227, 0x724A, 0x726C, 0x728E, 0x72AF, 0x72D0, 0x72F1, 0x7312, 0x7333, 0x7353,
|
||||
0x7373, 0x7392, 0x73B2, 0x73D1, 0x73F0, 0x740F, 0x742D, 0x744C, 0x746A, 0x7488, 0x74A6,
|
||||
0x74C3, 0x74E0, 0x74FE, 0x751B, 0x7537, 0x7554, 0x7570, 0x758D, 0x75A9, 0x75C4, 0x75E0,
|
||||
0x75FC, 0x7617, 0x7632, 0x764D, 0x7668, 0x7683, 0x769E, 0x76B8, 0x76D3, 0x76ED, 0x7707,
|
||||
0x7721, 0x773B, 0x7754, 0x776E, 0x7787, 0x77A0, 0x77B9, 0x77D2, 0x77EB, 0x7804, 0x781D,
|
||||
0x7835, 0x784E, 0x7866, 0x787E, 0x7896, 0x78AE, 0x78C6, 0x78DD, 0x78F5, 0x790D, 0x7924,
|
||||
0x793B, 0x7952, 0x796A, 0x7981, 0x7997, 0x79AE, 0x79C5, 0x79DB, 0x79F2, 0x7A08, 0x7A1F,
|
||||
0x7A35, 0x7A4B, 0x7A61, 0x7A77, 0x7A8D, 0x7AA3, 0x7AB8, 0x7ACE, 0x7AE3, 0x7AF9, 0x7B0E,
|
||||
0x7B24, 0x7B39, 0x7B4E, 0x7B63, 0x7B78, 0x7B8D, 0x7BA2, 0x7BB6, 0x7BCB, 0x7BE0, 0x7BF4,
|
||||
0x7C08, 0x7C1D, 0x7C31, 0x7C45, 0x7C59, 0x7C6E, 0x7C82, 0x7C96, 0x7CA9, 0x7CBD, 0x7CD1,
|
||||
0x7CE5, 0x7CF8, 0x7D0C, 0x7D1F, 0x7D33, 0x7D46, 0x7D59, 0x7D6D, 0x7D80, 0x7D93, 0x7DA6,
|
||||
0x7DB9, 0x7DCC, 0x7DDF, 0x7DF2, 0x7E04, 0x7E17, 0x7E2A, 0x7E3C, 0x7E4F, 0x7E61, 0x7E74,
|
||||
0x7E86, 0x7E98, 0x7EAB, 0x7EBD, 0x7ECF, 0x7EE1, 0x7EF3, 0x7F05, 0x7F17, 0x7F29, 0x7F3B,
|
||||
0x7F4D, 0x7F5E, 0x7F70, 0x7F82, 0x7F93, 0x7FA5, 0x7FB6, 0x7FC8, 0x7FD9, 0x7FEB, 0x7FFC,
|
||||
0x800D, 0x801E, 0x8030, 0x8041, 0x8052, 0x8063, 0x8074, 0x8085, 0x8096, 0x80A7, 0x80B7,
|
||||
0x80C8, 0x80D9, 0x80EA, 0x80FA, 0x810B, 0x811C, 0x812C, 0x813D, 0x814D, 0x815D, 0x816E,
|
||||
0x817E, 0x818E, 0x819F, 0x81AF, 0x81BF, 0x81CF, 0x81DF, 0x81EF, 0x81FF, 0x820F, 0x821F,
|
||||
0x822F, 0x823F, 0x824F, 0x825F, 0x826F, 0x827E, 0x828E, 0x829E, 0x82AD, 0x82BD, 0x82CC,
|
||||
0x82DC, 0x82EB, 0x82FB, 0x830A, 0x831A, 0x8329, 0x8338, 0x8348, 0x8357, 0x8366, 0x8375,
|
||||
0x8385, 0x8394, 0x83A3, 0x83B2, 0x83C1, 0x83D0, 0x83DF, 0x83EE, 0x83FD, 0x840C, 0x841A,
|
||||
0x8429, 0x8438, 0x8447, 0x8455, 0x8464, 0x8473, 0x8481, 0x8490, 0x849F, 0x84AD, 0x84BC,
|
||||
0x84CA, 0x84D9, 0x84E7, 0x84F5, 0x8504, 0x8512, 0x8521, 0x852F, 0x853D, 0x854B, 0x855A,
|
||||
0x8568, 0x8576, 0x8584, 0x8592, 0x85A0, 0x85AE, 0x85BC, 0x85CA, 0x85D8, 0x85E6, 0x85F4,
|
||||
0x8602, 0x8610, 0x861E, 0x862C, 0x8639, 0x8647, 0x8655, 0x8663, 0x8670, 0x867E, 0x868C,
|
||||
0x8699, 0x86A7, 0x86B5, 0x86C2, 0x86D0, 0x86DD, 0x86EB, 0x86F8, 0x8705, 0x8713, 0x8720,
|
||||
0x872E, 0x873B, 0x8748, 0x8756, 0x8763, 0x8770, 0x877D, 0x878B, 0x8798, 0x87A5, 0x87B2,
|
||||
0x87BF, 0x87CC, 0x87D9, 0x87E6, 0x87F3, 0x8801, 0x880E, 0x881A, 0x8827, 0x8834, 0x8841,
|
||||
0x884E, 0x885B, 0x8868, 0x8875, 0x8882, 0x888E, 0x889B, 0x88A8, 0x88B5, 0x88C1, 0x88CE,
|
||||
0x88DB, 0x88E7, 0x88F4, 0x8900, 0x890D, 0x891A, 0x8926, 0x8933, 0x893F, 0x894C, 0x8958,
|
||||
0x8965, 0x8971, 0x897D, 0x898A, 0x8996, 0x89A3, 0x89AF, 0x89BB, 0x89C8, 0x89D4, 0x89E0,
|
||||
0x89EC, 0x89F9, 0x8A05, 0x8A11, 0x8A1D, 0x8A29, 0x8A36, 0x8A42, 0x8A4E, 0x8A5A, 0x8A66,
|
||||
0x8A72, 0x8A7E, 0x8A8A, 0x8A96, 0x8AA2, 0x8AAE, 0x8ABA, 0x8AC6, 0x8AD2, 0x8ADE, 0x8AEA,
|
||||
0x8AF5, 0x8B01, 0x8B0D, 0x8B19, 0x8B25, 0x8B31, 0x8B3C, 0x8B48, 0x8B54, 0x8B60, 0x8B6B,
|
||||
0x8B77, 0x8B83, 0x8B8E, 0x8B9A, 0x8BA6, 0x8BB1, 0x8BBD, 0x8BC8, 0x8BD4, 0x8BDF, 0x8BEB,
|
||||
0x8BF6, 0x8C02, 0x8C0D, 0x8C19, 0x8C24, 0x8C30, 0x8C3B, 0x8C47, 0x8C52, 0x8C5D, 0x8C69,
|
||||
0x8C74, 0x8C80, 0x8C8B, 0x8C96, 0x8CA1, 0x8CAD, 0x8CB8, 0x8CC3, 0x8CCF, 0x8CDA, 0x8CE5,
|
||||
0x8CF0, 0x8CFB, 0x8D06, 0x8D12, 0x8D1D, 0x8D28, 0x8D33, 0x8D3E, 0x8D49, 0x8D54, 0x8D5F,
|
||||
0x8D6A, 0x8D75, 0x8D80, 0x8D8B, 0x8D96, 0x8DA1, 0x8DAC, 0x8DB7, 0x8DC2, 0x8DCD, 0x8DD8,
|
||||
0x8DE3, 0x8DEE, 0x8DF9, 0x8E04, 0x8E0E, 0x8E19, 0x8E24, 0x8E2F, 0x8E3A, 0x8E44, 0x8E4F,
|
||||
0x8E5A, 0x8E65, 0x8E6F, 0x8E7A, 0x8E85, 0x8E90, 0x8E9A, 0x8EA5, 0x8EB0, 0x8EBA, 0x8EC5,
|
||||
0x8ECF, 0x8EDA, 0x8EE5, 0x8EEF, 0x8EFA, 0x8F04, 0x8F0F, 0x8F19, 0x8F24, 0x8F2E, 0x8F39,
|
||||
0x8F43, 0x8F4E, 0x8F58, 0x8F63, 0x8F6D, 0x8F78, 0x8F82, 0x8F8C, 0x8F97, 0x8FA1, 0x8FAC,
|
||||
0x8FB6, 0x8FC0, 0x8FCB, 0x8FD5, 0x8FDF, 0x8FEA, 0x8FF4, 0x8FFE, 0x9008, 0x9013, 0x901D,
|
||||
0x9027, 0x9031, 0x903C, 0x9046, 0x9050, 0x905A, 0x9064, 0x906E, 0x9079, 0x9083, 0x908D,
|
||||
0x9097, 0x90A1, 0x90AB, 0x90B5, 0x90BF, 0x90C9, 0x90D3, 0x90DD, 0x90E7, 0x90F1, 0x90FB,
|
||||
0x9105, 0x910F, 0x9119, 0x9123, 0x912D, 0x9137, 0x9141, 0x914B, 0x9155, 0x915F, 0x9169,
|
||||
0x9173, 0x917D, 0x9186, 0x9190, 0x919A, 0x91A4, 0x91AE, 0x91B8, 0x91C1, 0x91CB, 0x91D5,
|
||||
0x91DF, 0x91E9, 0x91F2, 0x91FC, 0x9206, 0x9210, 0x9219, 0x9223, 0x922D, 0x9236, 0x9240,
|
||||
0x924A, 0x9253, 0x925D, 0x9267, 0x9270, 0x927A, 0x9283, 0x928D, 0x9297, 0x92A0, 0x92AA,
|
||||
0x92B3, 0x92BD, 0x92C6, 0x92D0, 0x92DA, 0x92E3, 0x92ED, 0x92F6, 0x9300, 0x9309, 0x9313,
|
||||
0x931C, 0x9325, 0x932F, 0x9338, 0x9342, 0x934B, 0x9355, 0x935E, 0x9367, 0x9371, 0x937A,
|
||||
0x9384, 0x938D, 0x9396, 0x93A0, 0x93A9, 0x93B2, 0x93BC, 0x93C5, 0x93CE, 0x93D7, 0x93E1,
|
||||
0x93EA, 0x93F3, 0x93FC, 0x9406, 0x940F, 0x9418, 0x9421, 0x942B, 0x9434, 0x943D, 0x9446,
|
||||
0x944F, 0x9459, 0x9462, 0x946B, 0x9474, 0x947D, 0x9486, 0x948F, 0x9499, 0x94A2, 0x94AB,
|
||||
0x94B4, 0x94BD, 0x94C6, 0x94CF, 0x94D8, 0x94E1, 0x94EA, 0x94F3, 0x94FC, 0x9505, 0x950E,
|
||||
0x9517, 0x9520, 0x9529, 0x9532, 0x953B, 0x9544, 0x954D, 0x9556, 0x955F, 0x9568, 0x9571,
|
||||
0x957A, 0x9583, 0x958C, 0x9595, 0x959D, 0x95A6, 0x95AF, 0x95B8, 0x95C1, 0x95CA, 0x95D3,
|
||||
0x95DB, 0x95E4, 0x95ED, 0x95F6, 0x95FF, 0x9608, 0x9610, 0x9619, 0x9622, 0x962B, 0x9633,
|
||||
0x963C, 0x9645, 0x964E, 0x9656, 0x965F, 0x9668, 0x9671, 0x9679, 0x9682, 0x968B, 0x9693,
|
||||
0x969C, 0x96A5, 0x96AD, 0x96B6, 0x96BF, 0x96C7, 0x96D0, 0x96D9, 0x96E1, 0x96EA, 0x96F2,
|
||||
0x96FB, 0x9704, 0x970C, 0x9715, 0x971D, 0x9726, 0x972E, 0x9737, 0x9740, 0x9748, 0x9751,
|
||||
0x9759, 0x9762, 0x976A, 0x9773, 0x977B, 0x9784, 0x978C, 0x9795, 0x979D, 0x97A6, 0x97AE,
|
||||
0x97B6, 0x97BF, 0x97C7, 0x97D0, 0x97D8, 0x97E1, 0x97E9, 0x97F1, 0x97FA, 0x9802, 0x980B,
|
||||
0x9813, 0x981B, 0x9824, 0x982C, 0x9834, 0x983D, 0x9845, 0x984D, 0x9856, 0x985E, 0x9866,
|
||||
0x986F, 0x9877, 0x987F, 0x9888, 0x9890, 0x9898, 0x98A0, 0x98A9, 0x98B1, 0x98B9, 0x98C1,
|
||||
0x98CA, 0x98D2, 0x98DA, 0x98E2, 0x98EB, 0x98F3, 0x98FB, 0x9903, 0x990B, 0x9914, 0x991C,
|
||||
0x9924, 0x992C, 0x9934, 0x993C, 0x9945, 0x994D, 0x9955, 0x995D, 0x9965, 0x996D, 0x9975,
|
||||
0x997D, 0x9986, 0x998E, 0x9996, 0x999E, 0x99A6, 0x99AE, 0x99B6, 0x99BE, 0x99C6, 0x99CE,
|
||||
0x99D6, 0x99DE, 0x99E6, 0x99EE, 0x99F6, 0x99FE, 0x9A06, 0x9A0E, 0x9A16, 0x9A1E, 0x9A26,
|
||||
0x9A2E, 0x9A36, 0x9A3E, 0x9A46, 0x9A4E, 0x9A56, 0x9A5E, 0x9A66, 0x9A6E, 0x9A76, 0x9A7E,
|
||||
0x9A86, 0x9A8E, 0x9A96, 0x9A9D, 0x9AA5, 0x9AAD, 0x9AB5, 0x9ABD, 0x9AC5, 0x9ACD, 0x9AD5,
|
||||
0x9ADC, 0x9AE4, 0x9AEC, 0x9AF4, 0x9AFC, 0x9B04, 0x9B0C, 0x9B13, 0x9B1B, 0x9B23, 0x9B2B,
|
||||
0x9B33, 0x9B3A, 0x9B42, 0x9B4A, 0x9B52, 0x9B59, 0x9B61, 0x9B69, 0x9B71, 0x9B79, 0x9B80,
|
||||
0x9B88, 0x9B90, 0x9B97, 0x9B9F, 0x9BA7, 0x9BAF, 0x9BB6, 0x9BBE, 0x9BC6, 0x9BCD, 0x9BD5,
|
||||
0x9BDD, 0x9BE5, 0x9BEC, 0x9BF4, 0x9BFC, 0x9C03, 0x9C0B, 0x9C12, 0x9C1A, 0x9C22, 0x9C29,
|
||||
0x9C31, 0x9C39, 0x9C40, 0x9C48, 0x9C50, 0x9C57, 0x9C5F, 0x9C66, 0x9C6E, 0x9C75, 0x9C7D,
|
||||
0x9C85, 0x9C8C, 0x9C94, 0x9C9B, 0x9CA3, 0x9CAA, 0x9CB2, 0x9CBA, 0x9CC1, 0x9CC9, 0x9CD0,
|
||||
0x9CD8, 0x9CDF, 0x9CE7, 0x9CEE, 0x9CF6, 0x9CFD, 0x9D05, 0x9D0C, 0x9D14, 0x9D1B, 0x9D23,
|
||||
0x9D2A, 0x9D32, 0x9D39, 0x9D40, 0x9D48, 0x9D4F, 0x9D57, 0x9D5E, 0x9D66, 0x9D6D, 0x9D75,
|
||||
0x9D7C, 0x9D83, 0x9D8B, 0x9D92, 0x9D9A, 0x9DA1, 0x9DA8, 0x9DB0, 0x9DB7, 0x9DBE, 0x9DC6,
|
||||
0x9DCD, 0x9DD5, 0x9DDC, 0x9DE3, 0x9DEB, 0x9DF2, 0x9DF9, 0x9E01, 0x9E08, 0x9E0F, 0x9E17,
|
||||
0x9E1E, 0x9E25, 0x9E2D, 0x9E34, 0x9E3B, 0x9E43, 0x9E4A, 0x9E51, 0x9E58, 0x9E60, 0x9E67,
|
||||
0x9E6E, 0x9E75, 0x9E7D, 0x9E84, 0x9E8B, 0x9E92, 0x9E9A, 0x9EA1, 0x9EA8, 0x9EAF, 0x9EB7,
|
||||
0x9EBE, 0x9EC5, 0x9ECC, 0x9ED4, 0x9EDB, 0x9EE2, 0x9EE9, 0x9EF0, 0x9EF7, 0x9EFF, 0x9F06,
|
||||
0x9F0D, 0x9F14, 0x9F1B, 0x9F23, 0x9F2A, 0x9F31, 0x9F38, 0x9F3F, 0x9F46, 0x9F4D, 0x9F55,
|
||||
0x9F5C, 0x9F63, 0x9F6A, 0x9F71, 0x9F78, 0x9F7F, 0x9F86, 0x9F8D, 0x9F95, 0x9F9C, 0x9FA3,
|
||||
0x9FAA, 0x9FB1, 0x9FB8, 0x9FBF, 0x9FC6, 0x9FCD, 0x9FD4, 0x9FDB, 0x9FE2, 0x9FE9, 0x9FF0,
|
||||
0x9FF7, 0x9FFF,
|
||||
};
|
||||
|
||||
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
|
||||
@@ -3251,6 +3348,25 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
||||
if (dc->irq < 0)
|
||||
return -ENXIO;
|
||||
|
||||
if (dc->soc->has_nvdisplay) {
|
||||
unsigned int i;
|
||||
u64 r;
|
||||
|
||||
dc->cmu_output_lut =
|
||||
dmam_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
|
||||
&dc->cmu_output_lut_phys, GFP_KERNEL);
|
||||
|
||||
if (!dc->cmu_output_lut) {
|
||||
dev_err(dc->dev, "failed to allocate lut for cmu\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
|
||||
r = default_srgb_lut[i];
|
||||
dc->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
|
||||
}
|
||||
}
|
||||
|
||||
err = tegra_dc_rgb_probe(dc);
|
||||
if (err < 0 && err != -ENODEV)
|
||||
return dev_err_probe(&pdev->dev, err,
|
||||
|
||||
@@ -103,6 +103,9 @@ struct tegra_dc {
|
||||
const struct tegra_dc_soc_info *soc;
|
||||
|
||||
bool has_opp_table;
|
||||
|
||||
u64 *cmu_output_lut;
|
||||
dma_addr_t cmu_output_lut_phys;
|
||||
};
|
||||
|
||||
static inline struct tegra_dc *
|
||||
@@ -447,6 +450,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
|
||||
#define BASE_COLOR_SIZE_888 ( 8 << 0)
|
||||
#define BASE_COLOR_SIZE_101010 ( 10 << 0)
|
||||
#define BASE_COLOR_SIZE_121212 ( 12 << 0)
|
||||
#define CMU_ENABLE_ENABLE (1 << 20)
|
||||
|
||||
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
|
||||
#define SC1_H_QUALIFIER_NONE (1 << 16)
|
||||
@@ -732,6 +736,15 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
|
||||
#define PROTOCOL_MASK (0xf << 8)
|
||||
#define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
|
||||
|
||||
#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT 0x431
|
||||
#define OUTPUT_LUT_MODE_MASK (3 << 5)
|
||||
#define OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
|
||||
#define OUTPUT_LUT_SIZE_MASK (3 << 1)
|
||||
#define OUTPUT_LUT_SIZE_SIZE_1025 (2 << 1)
|
||||
|
||||
#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE 0x432
|
||||
#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI 0x433
|
||||
|
||||
#define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR 0x442
|
||||
#define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR 0x446
|
||||
|
||||
|
||||
@@ -1378,10 +1378,12 @@ static const struct of_device_id host1x_drm_subdevs[] = {
|
||||
{ .compatible = "nvidia,tegra132-dsi", },
|
||||
{ .compatible = "nvidia,tegra210-dc", },
|
||||
{ .compatible = "nvidia,tegra210-dsi", },
|
||||
{ .compatible = "nvidia,tegra210b01-dsi", },
|
||||
{ .compatible = "nvidia,tegra210-sor", },
|
||||
{ .compatible = "nvidia,tegra210-sor1", },
|
||||
{ .compatible = "nvidia,tegra210-vic", },
|
||||
{ .compatible = "nvidia,tegra210-nvdec", },
|
||||
{ .compatible = "nvidia,tegra210-nvenc", },
|
||||
{ .compatible = "nvidia,tegra210-nvjpg", },
|
||||
{ .compatible = "nvidia,tegra186-display", },
|
||||
{ .compatible = "nvidia,tegra186-dc", },
|
||||
@@ -1389,13 +1391,19 @@ static const struct of_device_id host1x_drm_subdevs[] = {
|
||||
{ .compatible = "nvidia,tegra186-sor1", },
|
||||
{ .compatible = "nvidia,tegra186-vic", },
|
||||
{ .compatible = "nvidia,tegra186-nvdec", },
|
||||
{ .compatible = "nvidia,tegra186-nvenc", },
|
||||
{ .compatible = "nvidia,tegra186-nvjpg", },
|
||||
{ .compatible = "nvidia,tegra194-display", },
|
||||
{ .compatible = "nvidia,tegra194-dc", },
|
||||
{ .compatible = "nvidia,tegra194-sor", },
|
||||
{ .compatible = "nvidia,tegra194-vic", },
|
||||
{ .compatible = "nvidia,tegra194-nvdec", },
|
||||
{ .compatible = "nvidia,tegra194-nvenc", },
|
||||
{ .compatible = "nvidia,tegra194-nvjpg", },
|
||||
{ .compatible = "nvidia,tegra234-vic", },
|
||||
{ .compatible = "nvidia,tegra234-nvdec", },
|
||||
{ .compatible = "nvidia,tegra234-nvenc", },
|
||||
{ .compatible = "nvidia,tegra234-nvjpg", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@@ -1421,6 +1429,7 @@ static struct platform_driver * const drivers[] = {
|
||||
&tegra_gr3d_driver,
|
||||
&tegra_vic_driver,
|
||||
&tegra_nvdec_driver,
|
||||
&tegra_nvenc_driver,
|
||||
&tegra_nvjpg_driver,
|
||||
};
|
||||
|
||||
|
||||
@@ -129,9 +129,22 @@ void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
|
||||
|
||||
struct cec_notifier;
|
||||
|
||||
struct notify_dev {
|
||||
const char *name;
|
||||
struct device *dev;
|
||||
int index;
|
||||
int state;
|
||||
|
||||
ssize_t (*print_name)(struct notify_dev *sdev, char *buf);
|
||||
ssize_t (*print_state)(struct notify_dev *sdev, char *buf);
|
||||
};
|
||||
|
||||
struct tegra_output {
|
||||
struct device_node *of_node;
|
||||
struct device *dev;
|
||||
struct notify_dev notify_data;
|
||||
struct class *switch_class;
|
||||
atomic_t switch_count;
|
||||
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_panel *panel;
|
||||
@@ -214,6 +227,7 @@ extern struct platform_driver tegra_gr2d_driver;
|
||||
extern struct platform_driver tegra_gr3d_driver;
|
||||
extern struct platform_driver tegra_vic_driver;
|
||||
extern struct platform_driver tegra_nvdec_driver;
|
||||
extern struct platform_driver tegra_nvenc_driver;
|
||||
extern struct platform_driver tegra_nvjpg_driver;
|
||||
|
||||
#endif /* HOST1X_DRM_H */
|
||||
+139
-38
@@ -54,6 +54,21 @@ to_dsi_state(struct drm_connector_state *state)
|
||||
return container_of(state, struct tegra_dsi_state, base);
|
||||
}
|
||||
|
||||
/*
|
||||
* remap of registers revised in Tegra210B01
|
||||
*/
|
||||
struct dsi_regmap {
|
||||
int init_seq_data_15;
|
||||
int slew_impedance[4];
|
||||
int preemphasis;
|
||||
int bias;
|
||||
int ganged_mode_control;
|
||||
int ganged_mode_start;
|
||||
int ganged_mode_size;
|
||||
int dbg_regs_cnt;
|
||||
struct debugfs_reg32 dbg_regs_ext[16];
|
||||
};
|
||||
|
||||
struct tegra_dsi {
|
||||
struct host1x_client client;
|
||||
struct tegra_output output;
|
||||
@@ -83,6 +98,8 @@ struct tegra_dsi {
|
||||
/* for ganged-mode support */
|
||||
struct tegra_dsi *master;
|
||||
struct tegra_dsi *slave;
|
||||
|
||||
const struct dsi_regmap *regmap;
|
||||
};
|
||||
|
||||
static inline struct tegra_dsi *
|
||||
@@ -124,7 +141,7 @@ static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value,
|
||||
|
||||
#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
|
||||
|
||||
static const struct debugfs_reg32 tegra_dsi_regs[] = {
|
||||
static const struct debugfs_reg32 tegra_dsi_regs_common[] = {
|
||||
DEBUGFS_REG32(DSI_INCR_SYNCPT),
|
||||
DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL),
|
||||
DEBUGFS_REG32(DSI_INCR_SYNCPT_ERROR),
|
||||
@@ -183,19 +200,6 @@ static const struct debugfs_reg32 tegra_dsi_regs[] = {
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_2),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_3),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_4),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_START),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE),
|
||||
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT),
|
||||
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15),
|
||||
};
|
||||
|
||||
static int tegra_dsi_show_regs(struct seq_file *s, void *data)
|
||||
@@ -214,10 +218,17 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs); i++) {
|
||||
unsigned int offset = tegra_dsi_regs[i].offset;
|
||||
for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs_common); i++) {
|
||||
unsigned int offset = tegra_dsi_regs_common[i].offset;
|
||||
|
||||
seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs[i].name,
|
||||
seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs_common[i].name,
|
||||
offset, tegra_dsi_readl(dsi, offset));
|
||||
}
|
||||
|
||||
for (i = 0; i < dsi->regmap->dbg_regs_cnt; i++) {
|
||||
unsigned int offset = dsi->regmap->dbg_regs_ext[i].offset;
|
||||
|
||||
seq_printf(s, "%-32s %#05x %08x\n", dsi->regmap->dbg_regs_ext[i].name,
|
||||
offset, tegra_dsi_readl(dsi, offset));
|
||||
}
|
||||
|
||||
@@ -448,11 +459,11 @@ static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start,
|
||||
{
|
||||
u32 value;
|
||||
|
||||
tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START);
|
||||
tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE);
|
||||
tegra_dsi_writel(dsi, start, dsi->regmap->ganged_mode_start);
|
||||
tegra_dsi_writel(dsi, size << 16 | size, dsi->regmap->ganged_mode_size);
|
||||
|
||||
value = DSI_GANGED_MODE_CONTROL_ENABLE;
|
||||
tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL);
|
||||
tegra_dsi_writel(dsi, value, dsi->regmap->ganged_mode_control);
|
||||
}
|
||||
|
||||
static void tegra_dsi_enable(struct tegra_dsi *dsi)
|
||||
@@ -656,9 +667,9 @@ static void tegra_dsi_video_disable(struct tegra_dsi *dsi)
|
||||
|
||||
static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
|
||||
{
|
||||
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
|
||||
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
|
||||
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_start);
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_size);
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_control);
|
||||
}
|
||||
|
||||
static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
|
||||
@@ -674,7 +685,7 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
|
||||
static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
|
||||
{
|
||||
u32 value;
|
||||
int err;
|
||||
int err, i;
|
||||
|
||||
/*
|
||||
* XXX Is this still needed? The module reset is deasserted right
|
||||
@@ -682,21 +693,29 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
|
||||
*/
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
|
||||
for (i = 0; i < ARRAY_SIZE(dsi->regmap->slew_impedance); i++) {
|
||||
if (dsi->regmap->slew_impedance[i])
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->slew_impedance[i]);
|
||||
}
|
||||
|
||||
/* start calibration */
|
||||
tegra_dsi_pad_enable(dsi);
|
||||
|
||||
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
|
||||
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
|
||||
DSI_PAD_OUT_CLK(0x0);
|
||||
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
|
||||
/* do not set padctl 2 slew by default */
|
||||
if (of_property_read_bool(dsi->dev->of_node, "nvidia,slew-enable")) {
|
||||
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
|
||||
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
|
||||
DSI_PAD_OUT_CLK(0x0);
|
||||
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
|
||||
}
|
||||
|
||||
value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
|
||||
value = tegra_dsi_readl(dsi, dsi->regmap->preemphasis);
|
||||
|
||||
value |= DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
|
||||
DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
|
||||
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
|
||||
tegra_dsi_writel(dsi, value, dsi->regmap->preemphasis);
|
||||
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->bias);
|
||||
|
||||
err = tegra_mipi_start_calibration(dsi->mipi);
|
||||
if (err < 0)
|
||||
@@ -1069,7 +1088,7 @@ static int tegra_dsi_init(struct host1x_client *client)
|
||||
dev_err(dsi->dev, "failed to initialize output: %d\n",
|
||||
err);
|
||||
|
||||
dsi->output.encoder.possible_crtcs = 0x3;
|
||||
tegra_output_find_possible_crtcs(&dsi->output, drm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1633,6 +1652,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
|
||||
goto remove;
|
||||
}
|
||||
|
||||
dsi->regmap = of_device_get_match_data(&pdev->dev);
|
||||
if (IS_ERR(dsi->regmap)) {
|
||||
err = PTR_ERR(dsi->regmap);
|
||||
goto remove;
|
||||
}
|
||||
|
||||
dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
|
||||
if (IS_ERR(dsi->mipi)) {
|
||||
err = PTR_ERR(dsi->mipi);
|
||||
@@ -1688,11 +1713,87 @@ static void tegra_dsi_remove(struct platform_device *pdev)
|
||||
tegra_mipi_free(dsi->mipi);
|
||||
}
|
||||
|
||||
static const struct dsi_regmap tegra_dsi_regmap = {
|
||||
.init_seq_data_15 = DSI_INIT_SEQ_DATA_15,
|
||||
.slew_impedance = { DSI_PAD_CONTROL_2 },
|
||||
.preemphasis = DSI_PAD_CONTROL_3,
|
||||
.bias = DSI_PAD_CONTROL_4,
|
||||
.ganged_mode_control = DSI_GANGED_MODE_CONTROL,
|
||||
.ganged_mode_start = DSI_GANGED_MODE_START,
|
||||
.ganged_mode_size = DSI_GANGED_MODE_SIZE,
|
||||
.dbg_regs_cnt = 13,
|
||||
.dbg_regs_ext = {
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_START),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE),
|
||||
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT),
|
||||
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dsi_regmap tegra_dsi_regmap_b01 = {
|
||||
.init_seq_data_15 = DSI_INIT_SEQ_DATA_15_B01,
|
||||
.slew_impedance = {
|
||||
DSI_PAD_CONTROL_2,
|
||||
DSI_PAD_CONTROL_3,
|
||||
DSI_PAD_CONTROL_4,
|
||||
DSI_PAD_CONTROL_5_B01,
|
||||
},
|
||||
.preemphasis = DSI_PAD_CONTROL_6_B01,
|
||||
.bias = DSI_PAD_CONTROL_7_B01,
|
||||
.ganged_mode_control = DSI_GANGED_MODE_CONTROL_B01,
|
||||
.ganged_mode_start = DSI_GANGED_MODE_START_B01,
|
||||
.ganged_mode_size = DSI_GANGED_MODE_SIZE_B01,
|
||||
.dbg_regs_cnt = 16,
|
||||
.dbg_regs_ext = {
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_5_B01),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_6_B01),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_7_B01),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL_B01),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_START_B01),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE_B01),
|
||||
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT_B01),
|
||||
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15_B01),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_dsi_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra210-dsi", },
|
||||
{ .compatible = "nvidia,tegra132-dsi", },
|
||||
{ .compatible = "nvidia,tegra124-dsi", },
|
||||
{ .compatible = "nvidia,tegra114-dsi", },
|
||||
{
|
||||
.compatible = "nvidia,tegra210b01-dsi",
|
||||
.data = &tegra_dsi_regmap_b01
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra210-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra132-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra124-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra114-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
|
||||
|
||||
@@ -130,6 +130,24 @@
|
||||
#define DSI_INIT_SEQ_DATA_14 0x5e
|
||||
#define DSI_INIT_SEQ_DATA_15 0x5f
|
||||
|
||||
// Tegra210B01 has a revised set of regs
|
||||
#define DSI_PAD_CONTROL_5_B01 0x53
|
||||
#define DSI_PAD_CONTROL_6_B01 0x54
|
||||
#define DSI_PAD_CONTROL_7_B01 0x55
|
||||
#define DSI_GANGED_MODE_CONTROL_B01 0x56
|
||||
#define DSI_GANGED_MODE_START_B01 0x57
|
||||
#define DSI_GANGED_MODE_SIZE_B01 0x58
|
||||
#define DSI_RAW_DATA_BYTE_COUNT_B01 0x59
|
||||
#define DSI_ULTRA_LOW_POWER_CONTROL_B01 0x5a
|
||||
#define DSI_INIT_SEQ_DATA_8_B01 0x5b
|
||||
#define DSI_INIT_SEQ_DATA_9_B01 0x5c
|
||||
#define DSI_INIT_SEQ_DATA_10_B01 0x5d
|
||||
#define DSI_INIT_SEQ_DATA_11_B01 0x5e
|
||||
#define DSI_INIT_SEQ_DATA_12_B01 0x5f
|
||||
#define DSI_INIT_SEQ_DATA_13_B01 0x60
|
||||
#define DSI_INIT_SEQ_DATA_14_B01 0x61
|
||||
#define DSI_INIT_SEQ_DATA_15_B01 0x62
|
||||
|
||||
/*
|
||||
* pixel format as used in the DSI_CONTROL_FORMAT field
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/host1x.h>
|
||||
#include <linux/iommu.h>
|
||||
@@ -43,6 +44,7 @@ struct nvdec {
|
||||
struct clk_bulk_data clks[3];
|
||||
unsigned int num_clks;
|
||||
struct reset_control *reset;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
/* Platform configuration */
|
||||
const struct nvdec_config *config;
|
||||
@@ -63,6 +65,75 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
|
||||
writel(value, nvdec->regs + offset);
|
||||
}
|
||||
|
||||
static int nvdec_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
u32 flags)
|
||||
{
|
||||
struct nvdec *nvdec = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = clk_set_rate(nvdec->clks[0].clk, *freq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
*freq = clk_get_rate(nvdec->clks[0].clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvdec_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
|
||||
{
|
||||
struct nvdec *nvdec = dev_get_drvdata(dev);
|
||||
|
||||
*freq = clk_get_rate(nvdec->clks[0].clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct devfreq_dev_profile nvdec_devfreq_profile = {
|
||||
.polling_ms = 50,
|
||||
.target = nvdec_devfreq_target,
|
||||
.get_cur_freq = nvdec_devfreq_get_cur_freq,
|
||||
};
|
||||
|
||||
static int nvdec_devfreq_init(struct nvdec *nvdec)
|
||||
{
|
||||
struct clk *clk = nvdec->clks[0].clk;
|
||||
unsigned long max_rate = clk_round_rate(clk, ULONG_MAX);
|
||||
unsigned long min_rate = clk_round_rate(clk, 0);
|
||||
unsigned long margin = clk_round_rate(clk, min_rate + 1) - min_rate;
|
||||
unsigned long rate = min_rate;
|
||||
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
if (min_rate == max_rate) {
|
||||
dev_info(nvdec->dev, "Only one supported clock rate, disabling devfreq\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Only allow up to 20 rates
|
||||
if (hw_rates > 20)
|
||||
margin *= DIV_ROUND_UP(hw_rates, 20);
|
||||
|
||||
while (rate < max_rate) {
|
||||
dev_pm_opp_add(nvdec->dev, rate, 0);
|
||||
rate += margin;
|
||||
}
|
||||
|
||||
// The margin step may not fall on max rate exactly, so add max rate explicitly
|
||||
dev_pm_opp_add(nvdec->dev, max_rate, 0);
|
||||
|
||||
devfreq = devm_devfreq_add_device(nvdec->dev,
|
||||
&nvdec_devfreq_profile,
|
||||
DEVFREQ_GOV_USERSPACE,
|
||||
NULL);
|
||||
if (IS_ERR(devfreq))
|
||||
return PTR_ERR(devfreq);
|
||||
|
||||
nvdec->devfreq = devfreq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvdec_boot_falcon(struct nvdec *nvdec)
|
||||
{
|
||||
u32 stream_id;
|
||||
@@ -329,6 +400,12 @@ static __maybe_unused int nvdec_runtime_resume(struct device *dev)
|
||||
goto disable;
|
||||
}
|
||||
|
||||
if (nvdec->devfreq) {
|
||||
err = devfreq_resume_device(nvdec->devfreq);
|
||||
if (err < 0)
|
||||
goto disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
disable:
|
||||
@@ -339,6 +416,13 @@ disable:
|
||||
static __maybe_unused int nvdec_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct nvdec *nvdec = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
if (nvdec->devfreq) {
|
||||
err = devfreq_suspend_device(nvdec->devfreq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
host1x_channel_stop(nvdec->channel);
|
||||
|
||||
@@ -530,12 +614,20 @@ static int nvdec_probe(struct platform_device *pdev)
|
||||
goto exit_falcon;
|
||||
}
|
||||
|
||||
err = nvdec_devfreq_init(nvdec);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
|
||||
goto unregister_client;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 500);
|
||||
|
||||
return 0;
|
||||
|
||||
unregister_client:
|
||||
host1x_client_unregister(&nvdec->client.base);
|
||||
exit_falcon:
|
||||
falcon_exit(&nvdec->falcon);
|
||||
|
||||
|
||||
@@ -0,0 +1,551 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/host1x.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "drm.h"
|
||||
#include "falcon.h"
|
||||
#include "vic.h"
|
||||
|
||||
#define NVENC_TFBIF_TRANSCFG 0x1844
|
||||
|
||||
struct nvenc_config {
|
||||
const char *firmware;
|
||||
unsigned int version;
|
||||
bool supports_sid;
|
||||
};
|
||||
|
||||
struct nvenc {
|
||||
struct falcon falcon;
|
||||
|
||||
void __iomem *regs;
|
||||
struct tegra_drm_client client;
|
||||
struct host1x_channel *channel;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
/* Platform configuration */
|
||||
const struct nvenc_config *config;
|
||||
};
|
||||
|
||||
static inline struct nvenc *to_nvenc(struct tegra_drm_client *client)
|
||||
{
|
||||
return container_of(client, struct nvenc, client);
|
||||
}
|
||||
|
||||
static inline void nvenc_writel(struct nvenc *nvenc, u32 value,
|
||||
unsigned int offset)
|
||||
{
|
||||
writel(value, nvenc->regs + offset);
|
||||
}
|
||||
|
||||
static int nvenc_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
u32 flags)
|
||||
{
|
||||
struct nvenc *nvenc = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = clk_set_rate(nvenc->clk, *freq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
*freq = clk_get_rate(nvenc->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvenc_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
|
||||
{
|
||||
struct nvenc *nvenc = dev_get_drvdata(dev);
|
||||
|
||||
*freq = clk_get_rate(nvenc->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct devfreq_dev_profile nvenc_devfreq_profile = {
|
||||
.polling_ms = 50,
|
||||
.target = nvenc_devfreq_target,
|
||||
.get_cur_freq = nvenc_devfreq_get_cur_freq,
|
||||
};
|
||||
|
||||
static int nvenc_devfreq_init(struct nvenc *nvenc)
|
||||
{
|
||||
unsigned long max_rate = clk_round_rate(nvenc->clk, ULONG_MAX);
|
||||
unsigned long min_rate = clk_round_rate(nvenc->clk, 0);
|
||||
unsigned long margin = clk_round_rate(nvenc->clk, min_rate + 1) - min_rate;
|
||||
unsigned long rate = min_rate;
|
||||
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
if (min_rate == max_rate) {
|
||||
dev_info(nvenc->dev, "Only one supported clock rate, disabling devfreq\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Only allow up to 20 rates
|
||||
if (hw_rates > 20)
|
||||
margin *= DIV_ROUND_UP(hw_rates, 20);
|
||||
|
||||
while (rate < max_rate) {
|
||||
dev_pm_opp_add(nvenc->dev, rate, 0);
|
||||
rate += margin;
|
||||
}
|
||||
|
||||
// The margin step may not fall on max rate exactly, so add max rate explicitly
|
||||
dev_pm_opp_add(nvenc->dev, max_rate, 0);
|
||||
|
||||
devfreq = devm_devfreq_add_device(nvenc->dev,
|
||||
&nvenc_devfreq_profile,
|
||||
DEVFREQ_GOV_USERSPACE,
|
||||
NULL);
|
||||
if (IS_ERR(devfreq))
|
||||
return PTR_ERR(devfreq);
|
||||
|
||||
nvenc->devfreq = devfreq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvenc_init(struct host1x_client *client)
|
||||
{
|
||||
struct tegra_drm_client *drm = host1x_to_drm_client(client);
|
||||
struct drm_device *dev = dev_get_drvdata(client->host);
|
||||
struct tegra_drm *tegra = dev->dev_private;
|
||||
struct nvenc *nvenc = to_nvenc(drm);
|
||||
int err;
|
||||
|
||||
err = host1x_client_iommu_attach(client);
|
||||
if (err < 0 && err != -ENODEV) {
|
||||
dev_err(nvenc->dev, "failed to attach to domain: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
nvenc->channel = host1x_channel_request(client);
|
||||
if (!nvenc->channel) {
|
||||
err = -ENOMEM;
|
||||
goto detach;
|
||||
}
|
||||
|
||||
client->syncpts[0] = host1x_syncpt_request(client, 0);
|
||||
if (!client->syncpts[0]) {
|
||||
err = -ENOMEM;
|
||||
goto free_channel;
|
||||
}
|
||||
|
||||
err = tegra_drm_register_client(tegra, drm);
|
||||
if (err < 0)
|
||||
goto free_syncpt;
|
||||
|
||||
/*
|
||||
* Inherit the DMA parameters (such as maximum segment size) from the
|
||||
* parent host1x device.
|
||||
*/
|
||||
client->dev->dma_parms = client->host->dma_parms;
|
||||
|
||||
return 0;
|
||||
|
||||
free_syncpt:
|
||||
host1x_syncpt_put(client->syncpts[0]);
|
||||
free_channel:
|
||||
host1x_channel_put(nvenc->channel);
|
||||
detach:
|
||||
host1x_client_iommu_detach(client);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nvenc_exit(struct host1x_client *client)
|
||||
{
|
||||
struct tegra_drm_client *drm = host1x_to_drm_client(client);
|
||||
struct drm_device *dev = dev_get_drvdata(client->host);
|
||||
struct tegra_drm *tegra = dev->dev_private;
|
||||
struct nvenc *nvenc = to_nvenc(drm);
|
||||
int err;
|
||||
|
||||
/* avoid a dangling pointer just in case this disappears */
|
||||
client->dev->dma_parms = NULL;
|
||||
|
||||
err = tegra_drm_unregister_client(tegra, drm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
pm_runtime_dont_use_autosuspend(client->dev);
|
||||
pm_runtime_force_suspend(client->dev);
|
||||
|
||||
host1x_syncpt_put(client->syncpts[0]);
|
||||
host1x_channel_put(nvenc->channel);
|
||||
host1x_client_iommu_detach(client);
|
||||
|
||||
nvenc->channel = NULL;
|
||||
|
||||
if (client->group) {
|
||||
dma_unmap_single(nvenc->dev, nvenc->falcon.firmware.phys,
|
||||
nvenc->falcon.firmware.size, DMA_TO_DEVICE);
|
||||
tegra_drm_free(tegra, nvenc->falcon.firmware.size,
|
||||
nvenc->falcon.firmware.virt,
|
||||
nvenc->falcon.firmware.iova);
|
||||
} else {
|
||||
dma_free_coherent(nvenc->dev, nvenc->falcon.firmware.size,
|
||||
nvenc->falcon.firmware.virt,
|
||||
nvenc->falcon.firmware.iova);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct host1x_client_ops nvenc_client_ops = {
|
||||
.init = nvenc_init,
|
||||
.exit = nvenc_exit,
|
||||
};
|
||||
|
||||
static int nvenc_load_falcon_firmware(struct nvenc *nvenc)
|
||||
{
|
||||
struct host1x_client *client = &nvenc->client.base;
|
||||
struct tegra_drm *tegra = nvenc->client.drm;
|
||||
dma_addr_t iova;
|
||||
size_t size;
|
||||
void *virt;
|
||||
int err;
|
||||
|
||||
if (nvenc->falcon.firmware.virt)
|
||||
return 0;
|
||||
|
||||
err = falcon_read_firmware(&nvenc->falcon, nvenc->config->firmware);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
size = nvenc->falcon.firmware.size;
|
||||
|
||||
if (!client->group) {
|
||||
virt = dma_alloc_coherent(nvenc->dev, size, &iova, GFP_KERNEL);
|
||||
if (!virt)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
virt = tegra_drm_alloc(tegra, size, &iova);
|
||||
if (IS_ERR(virt))
|
||||
return PTR_ERR(virt);
|
||||
}
|
||||
|
||||
nvenc->falcon.firmware.virt = virt;
|
||||
nvenc->falcon.firmware.iova = iova;
|
||||
|
||||
err = falcon_load_firmware(&nvenc->falcon);
|
||||
if (err < 0)
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* In this case we have received an IOVA from the shared domain, so we
|
||||
* need to make sure to get the physical address so that the DMA API
|
||||
* knows what memory pages to flush the cache for.
|
||||
*/
|
||||
if (client->group) {
|
||||
dma_addr_t phys;
|
||||
|
||||
phys = dma_map_single(nvenc->dev, virt, size, DMA_TO_DEVICE);
|
||||
|
||||
err = dma_mapping_error(nvenc->dev, phys);
|
||||
if (err < 0)
|
||||
goto cleanup;
|
||||
|
||||
nvenc->falcon.firmware.phys = phys;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
if (!client->group)
|
||||
dma_free_coherent(nvenc->dev, size, virt, iova);
|
||||
else
|
||||
tegra_drm_free(tegra, size, virt, iova);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nvenc_boot_falcon(struct nvenc *nvenc)
|
||||
{
|
||||
u32 stream_id;
|
||||
int err;
|
||||
|
||||
if (nvenc->config->supports_sid && tegra_dev_iommu_get_stream_id(nvenc->dev, &stream_id)) {
|
||||
u32 value;
|
||||
|
||||
value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW);
|
||||
nvenc_writel(nvenc, value, NVENC_TFBIF_TRANSCFG);
|
||||
|
||||
nvenc_writel(nvenc, stream_id, VIC_THI_STREAMID0);
|
||||
nvenc_writel(nvenc, stream_id, VIC_THI_STREAMID1);
|
||||
}
|
||||
|
||||
err = falcon_boot(&nvenc->falcon);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = falcon_wait_idle(&nvenc->falcon);
|
||||
if (err < 0) {
|
||||
dev_err(nvenc->dev, "falcon boot timed out\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int nvenc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct nvenc *nvenc = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = clk_prepare_enable(nvenc->clk);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
usleep_range(20, 30);
|
||||
|
||||
err = nvenc_load_falcon_firmware(nvenc);
|
||||
if (err < 0)
|
||||
goto disable_clk;
|
||||
|
||||
err = nvenc_boot_falcon(nvenc);
|
||||
if (err < 0)
|
||||
goto disable_clk;
|
||||
|
||||
if (nvenc->devfreq) {
|
||||
err = devfreq_resume_device(nvenc->devfreq);
|
||||
if (err < 0)
|
||||
goto disable_clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
disable_clk:
|
||||
clk_disable_unprepare(nvenc->clk);
|
||||
return err;
|
||||
}
|
||||
|
||||
static __maybe_unused int nvenc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct nvenc *nvenc = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
if (nvenc->devfreq) {
|
||||
err = devfreq_suspend_device(nvenc->devfreq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
host1x_channel_stop(nvenc->channel);
|
||||
|
||||
clk_disable_unprepare(nvenc->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvenc_open_channel(struct tegra_drm_client *client,
|
||||
struct tegra_drm_context *context)
|
||||
{
|
||||
struct nvenc *nvenc = to_nvenc(client);
|
||||
|
||||
context->channel = host1x_channel_get(nvenc->channel);
|
||||
if (!context->channel)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvenc_close_channel(struct tegra_drm_context *context)
|
||||
{
|
||||
host1x_channel_put(context->channel);
|
||||
}
|
||||
|
||||
static int nvenc_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported)
|
||||
{
|
||||
*supported = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tegra_drm_client_ops nvenc_ops = {
|
||||
.open_channel = nvenc_open_channel,
|
||||
.close_channel = nvenc_close_channel,
|
||||
.submit = tegra_drm_submit,
|
||||
.get_streamid_offset = tegra_drm_get_streamid_offset_thi,
|
||||
.can_use_memory_ctx = nvenc_can_use_memory_ctx,
|
||||
};
|
||||
|
||||
#define NVIDIA_TEGRA_210_NVENC_FIRMWARE "nvidia/tegra210/nvenc.bin"
|
||||
|
||||
static const struct nvenc_config nvenc_t210_config = {
|
||||
.firmware = NVIDIA_TEGRA_210_NVENC_FIRMWARE,
|
||||
.version = 0x21,
|
||||
.supports_sid = false,
|
||||
};
|
||||
|
||||
#define NVIDIA_TEGRA_186_NVENC_FIRMWARE "nvidia/tegra186/nvenc.bin"
|
||||
|
||||
static const struct nvenc_config nvenc_t186_config = {
|
||||
.firmware = NVIDIA_TEGRA_186_NVENC_FIRMWARE,
|
||||
.version = 0x18,
|
||||
.supports_sid = true,
|
||||
};
|
||||
|
||||
#define NVIDIA_TEGRA_194_NVENC_FIRMWARE "nvidia/tegra194/nvenc.bin"
|
||||
|
||||
static const struct nvenc_config nvenc_t194_config = {
|
||||
.firmware = NVIDIA_TEGRA_194_NVENC_FIRMWARE,
|
||||
.version = 0x19,
|
||||
.supports_sid = true,
|
||||
};
|
||||
|
||||
#define NVIDIA_TEGRA_234_NVENC_FIRMWARE "nvidia/tegra234/nvenc.bin"
|
||||
|
||||
static const struct nvenc_config nvenc_t234_config = {
|
||||
.firmware = NVIDIA_TEGRA_234_NVENC_FIRMWARE,
|
||||
.version = 0x23,
|
||||
.supports_sid = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_nvenc_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra210-nvenc", .data = &nvenc_t210_config },
|
||||
{ .compatible = "nvidia,tegra186-nvenc", .data = &nvenc_t186_config },
|
||||
{ .compatible = "nvidia,tegra194-nvenc", .data = &nvenc_t194_config },
|
||||
{ .compatible = "nvidia,tegra234-nvenc", .data = &nvenc_t234_config },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_nvenc_of_match);
|
||||
|
||||
static int nvenc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct host1x_syncpt **syncpts;
|
||||
struct nvenc *nvenc;
|
||||
u32 host_class;
|
||||
int err;
|
||||
|
||||
/* inherit DMA mask from host1x parent */
|
||||
err = dma_coerce_mask_and_coherent(dev, *dev->parent->dma_mask);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
nvenc = devm_kzalloc(dev, sizeof(*nvenc), GFP_KERNEL);
|
||||
if (!nvenc)
|
||||
return -ENOMEM;
|
||||
|
||||
nvenc->config = of_device_get_match_data(dev);
|
||||
|
||||
syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
|
||||
if (!syncpts)
|
||||
return -ENOMEM;
|
||||
|
||||
nvenc->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(nvenc->regs))
|
||||
return PTR_ERR(nvenc->regs);
|
||||
|
||||
nvenc->clk = devm_clk_get(dev, "nvenc");
|
||||
if (IS_ERR(nvenc->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
return PTR_ERR(nvenc->clk);
|
||||
}
|
||||
|
||||
err = clk_set_rate(nvenc->clk, ULONG_MAX);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to set clock rate\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
nvenc->falcon.dev = dev;
|
||||
nvenc->falcon.regs = nvenc->regs;
|
||||
|
||||
err = falcon_init(&nvenc->falcon);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = of_property_read_u32(dev->of_node, "nvidia,host1x-class", &host_class);
|
||||
if (err < 0)
|
||||
host_class = HOST1X_CLASS_NVENC;
|
||||
|
||||
platform_set_drvdata(pdev, nvenc);
|
||||
|
||||
INIT_LIST_HEAD(&nvenc->client.base.list);
|
||||
nvenc->client.base.ops = &nvenc_client_ops;
|
||||
nvenc->client.base.dev = dev;
|
||||
nvenc->client.base.class = host_class;
|
||||
nvenc->client.base.syncpts = syncpts;
|
||||
nvenc->client.base.num_syncpts = 1;
|
||||
nvenc->dev = dev;
|
||||
|
||||
INIT_LIST_HEAD(&nvenc->client.list);
|
||||
nvenc->client.version = nvenc->config->version;
|
||||
nvenc->client.ops = &nvenc_ops;
|
||||
|
||||
err = host1x_client_register(&nvenc->client.base);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to register host1x client: %d\n", err);
|
||||
goto exit_falcon;
|
||||
}
|
||||
|
||||
err = nvenc_devfreq_init(nvenc);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
|
||||
goto unregister_client;
|
||||
}
|
||||
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 500);
|
||||
devm_pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
unregister_client:
|
||||
host1x_client_unregister(&nvenc->client.base);
|
||||
exit_falcon:
|
||||
falcon_exit(&nvenc->falcon);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void nvenc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct nvenc *nvenc = platform_get_drvdata(pdev);
|
||||
|
||||
host1x_client_unregister(&nvenc->client.base);
|
||||
falcon_exit(&nvenc->falcon);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops nvenc_pm_ops = {
|
||||
RUNTIME_PM_OPS(nvenc_runtime_suspend, nvenc_runtime_resume, NULL)
|
||||
SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
struct platform_driver tegra_nvenc_driver = {
|
||||
.driver = {
|
||||
.name = "tegra-nvenc",
|
||||
.of_match_table = tegra_nvenc_of_match,
|
||||
.pm = &nvenc_pm_ops
|
||||
},
|
||||
.probe = nvenc_probe,
|
||||
.remove = nvenc_remove,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_210_NVENC_FIRMWARE);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_186_NVENC_FIRMWARE);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_194_NVENC_FIRMWARE);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_234_NVENC_FIRMWARE);
|
||||
#endif
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/host1x.h>
|
||||
#include <linux/iommu.h>
|
||||
@@ -12,10 +13,14 @@
|
||||
|
||||
#include "drm.h"
|
||||
#include "falcon.h"
|
||||
#include "vic.h"
|
||||
|
||||
#define NVJPG_TFBIF_TRANSCFG 0x1444
|
||||
|
||||
struct nvjpg_config {
|
||||
const char *firmware;
|
||||
unsigned int version;
|
||||
bool supports_sid;
|
||||
};
|
||||
|
||||
struct nvjpg {
|
||||
@@ -23,8 +28,10 @@ struct nvjpg {
|
||||
|
||||
void __iomem *regs;
|
||||
struct tegra_drm_client client;
|
||||
struct host1x_channel *channel;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
/* Platform configuration */
|
||||
const struct nvjpg_config *config;
|
||||
@@ -35,6 +42,80 @@ static inline struct nvjpg *to_nvjpg(struct tegra_drm_client *client)
|
||||
return container_of(client, struct nvjpg, client);
|
||||
}
|
||||
|
||||
static inline void nvjpg_writel(struct nvjpg *nvjpg, u32 value,
|
||||
unsigned int offset)
|
||||
{
|
||||
writel(value, nvjpg->regs + offset);
|
||||
}
|
||||
|
||||
static int nvjpg_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
u32 flags)
|
||||
{
|
||||
struct nvjpg *nvjpg = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = clk_set_rate(nvjpg->clk, *freq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
*freq = clk_get_rate(nvjpg->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvjpg_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
|
||||
{
|
||||
struct nvjpg *nvjpg = dev_get_drvdata(dev);
|
||||
|
||||
*freq = clk_get_rate(nvjpg->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct devfreq_dev_profile nvjpg_devfreq_profile = {
|
||||
.polling_ms = 50,
|
||||
.target = nvjpg_devfreq_target,
|
||||
.get_cur_freq = nvjpg_devfreq_get_cur_freq,
|
||||
};
|
||||
|
||||
static int nvjpg_devfreq_init(struct nvjpg *nvjpg)
|
||||
{
|
||||
unsigned long max_rate = clk_round_rate(nvjpg->clk, ULONG_MAX);
|
||||
unsigned long min_rate = clk_round_rate(nvjpg->clk, 0);
|
||||
unsigned long margin = clk_round_rate(nvjpg->clk, min_rate + 1) - min_rate;
|
||||
unsigned long rate = min_rate;
|
||||
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
if (min_rate == max_rate) {
|
||||
dev_info(nvjpg->dev, "Only one supported clock rate, disabling devfreq\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Only allow up to 20 rates
|
||||
if (hw_rates > 20)
|
||||
margin *= DIV_ROUND_UP(hw_rates, 20);
|
||||
|
||||
while (rate < max_rate) {
|
||||
dev_pm_opp_add(nvjpg->dev, rate, 0);
|
||||
rate += margin;
|
||||
}
|
||||
|
||||
// The margin step may not fall on max rate exactly, so add max rate explicitly
|
||||
dev_pm_opp_add(nvjpg->dev, max_rate, 0);
|
||||
|
||||
devfreq = devm_devfreq_add_device(nvjpg->dev,
|
||||
&nvjpg_devfreq_profile,
|
||||
DEVFREQ_GOV_USERSPACE,
|
||||
NULL);
|
||||
if (IS_ERR(devfreq))
|
||||
return PTR_ERR(devfreq);
|
||||
|
||||
nvjpg->devfreq = devfreq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvjpg_init(struct host1x_client *client)
|
||||
{
|
||||
struct tegra_drm_client *drm = host1x_to_drm_client(client);
|
||||
@@ -49,9 +130,21 @@ static int nvjpg_init(struct host1x_client *client)
|
||||
return err;
|
||||
}
|
||||
|
||||
nvjpg->channel = host1x_channel_request(client);
|
||||
if (!nvjpg->channel) {
|
||||
err = -ENOMEM;
|
||||
goto detach;
|
||||
}
|
||||
|
||||
client->syncpts[0] = host1x_syncpt_request(client, 0);
|
||||
if (!client->syncpts[0]) {
|
||||
err = -ENOMEM;
|
||||
goto free_channel;
|
||||
}
|
||||
|
||||
err = tegra_drm_register_client(tegra, drm);
|
||||
if (err < 0)
|
||||
goto detach;
|
||||
goto free_syncpt;
|
||||
|
||||
/*
|
||||
* Inherit the DMA parameters (such as maximum segment size) from the
|
||||
@@ -61,6 +154,10 @@ static int nvjpg_init(struct host1x_client *client)
|
||||
|
||||
return 0;
|
||||
|
||||
free_syncpt:
|
||||
host1x_syncpt_put(client->syncpts[0]);
|
||||
free_channel:
|
||||
host1x_channel_put(nvjpg->channel);
|
||||
detach:
|
||||
host1x_client_iommu_detach(client);
|
||||
|
||||
@@ -85,8 +182,12 @@ static int nvjpg_exit(struct host1x_client *client)
|
||||
pm_runtime_dont_use_autosuspend(client->dev);
|
||||
pm_runtime_force_suspend(client->dev);
|
||||
|
||||
host1x_syncpt_put(client->syncpts[0]);
|
||||
host1x_channel_put(nvjpg->channel);
|
||||
host1x_client_iommu_detach(client);
|
||||
|
||||
nvjpg->channel = NULL;
|
||||
|
||||
if (client->group) {
|
||||
dma_unmap_single(nvjpg->dev, nvjpg->falcon.firmware.phys,
|
||||
nvjpg->falcon.firmware.size, DMA_TO_DEVICE);
|
||||
@@ -170,6 +271,34 @@ cleanup:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nvjpg_boot_falcon(struct nvjpg *nvjpg)
|
||||
{
|
||||
u32 stream_id;
|
||||
int err;
|
||||
|
||||
if (nvjpg->config->supports_sid && tegra_dev_iommu_get_stream_id(nvjpg->dev, &stream_id)) {
|
||||
u32 value;
|
||||
|
||||
value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW);
|
||||
nvjpg_writel(nvjpg, value, NVJPG_TFBIF_TRANSCFG);
|
||||
|
||||
nvjpg_writel(nvjpg, stream_id, VIC_THI_STREAMID0);
|
||||
nvjpg_writel(nvjpg, stream_id, VIC_THI_STREAMID1);
|
||||
}
|
||||
|
||||
err = falcon_boot(&nvjpg->falcon);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = falcon_wait_idle(&nvjpg->falcon);
|
||||
if (err < 0) {
|
||||
dev_err(nvjpg->dev, "falcon boot timed out\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int nvjpg_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct nvjpg *nvjpg = dev_get_drvdata(dev);
|
||||
@@ -185,10 +314,16 @@ static __maybe_unused int nvjpg_runtime_resume(struct device *dev)
|
||||
if (err < 0)
|
||||
goto disable_clk;
|
||||
|
||||
err = falcon_boot(&nvjpg->falcon);
|
||||
err = nvjpg_boot_falcon(nvjpg);
|
||||
if (err < 0)
|
||||
goto disable_clk;
|
||||
|
||||
if (nvjpg->devfreq) {
|
||||
err = devfreq_resume_device(nvjpg->devfreq);
|
||||
if (err < 0)
|
||||
goto disable_clk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
disable_clk:
|
||||
@@ -199,21 +334,50 @@ disable_clk:
|
||||
static __maybe_unused int nvjpg_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct nvjpg *nvjpg = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
if (nvjpg->devfreq) {
|
||||
err = devfreq_suspend_device(nvjpg->devfreq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
host1x_channel_stop(nvjpg->channel);
|
||||
|
||||
clk_disable_unprepare(nvjpg->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nvjpg_open_channel(struct tegra_drm_client *client,
|
||||
struct tegra_drm_context *context)
|
||||
{
|
||||
struct nvjpg *nvjpg = to_nvjpg(client);
|
||||
|
||||
context->channel = host1x_channel_get(nvjpg->channel);
|
||||
if (!context->channel)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvjpg_close_channel(struct tegra_drm_context *context)
|
||||
{
|
||||
host1x_channel_put(context->channel);
|
||||
}
|
||||
|
||||
static int nvjpg_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported)
|
||||
{
|
||||
*supported = false;
|
||||
*supported = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tegra_drm_client_ops nvjpg_ops = {
|
||||
.get_streamid_offset = NULL,
|
||||
.open_channel = nvjpg_open_channel,
|
||||
.close_channel = nvjpg_close_channel,
|
||||
.submit = tegra_drm_submit,
|
||||
.get_streamid_offset = tegra_drm_get_streamid_offset_thi,
|
||||
.can_use_memory_ctx = nvjpg_can_use_memory_ctx,
|
||||
};
|
||||
|
||||
@@ -222,10 +386,38 @@ static const struct tegra_drm_client_ops nvjpg_ops = {
|
||||
static const struct nvjpg_config tegra210_nvjpg_config = {
|
||||
.firmware = NVIDIA_TEGRA_210_NVJPG_FIRMWARE,
|
||||
.version = 0x21,
|
||||
.supports_sid = false,
|
||||
};
|
||||
|
||||
#define NVIDIA_TEGRA_186_NVJPG_FIRMWARE "nvidia/tegra186/nvjpg.bin"
|
||||
|
||||
static const struct nvjpg_config tegra186_nvjpg_config = {
|
||||
.firmware = NVIDIA_TEGRA_186_NVJPG_FIRMWARE,
|
||||
.version = 0x18,
|
||||
.supports_sid = true,
|
||||
};
|
||||
|
||||
#define NVIDIA_TEGRA_194_NVJPG_FIRMWARE "nvidia/tegra194/nvjpg.bin"
|
||||
|
||||
static const struct nvjpg_config tegra194_nvjpg_config = {
|
||||
.firmware = NVIDIA_TEGRA_194_NVJPG_FIRMWARE,
|
||||
.version = 0x19,
|
||||
.supports_sid = true,
|
||||
};
|
||||
|
||||
#define NVIDIA_TEGRA_234_NVJPG_FIRMWARE "nvidia/tegra234/nvjpg.bin"
|
||||
|
||||
static const struct nvjpg_config tegra234_nvjpg_config = {
|
||||
.firmware = NVIDIA_TEGRA_234_NVJPG_FIRMWARE,
|
||||
.version = 0x23,
|
||||
.supports_sid = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_nvjpg_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra210-nvjpg", .data = &tegra210_nvjpg_config },
|
||||
{ .compatible = "nvidia,tegra186-nvjpg", .data = &tegra186_nvjpg_config },
|
||||
{ .compatible = "nvidia,tegra194-nvjpg", .data = &tegra194_nvjpg_config },
|
||||
{ .compatible = "nvidia,tegra234-nvjpg", .data = &tegra234_nvjpg_config },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_nvjpg_of_match);
|
||||
@@ -233,7 +425,9 @@ MODULE_DEVICE_TABLE(of, tegra_nvjpg_of_match);
|
||||
static int nvjpg_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct host1x_syncpt **syncpts;
|
||||
struct nvjpg *nvjpg;
|
||||
u32 host_class;
|
||||
int err;
|
||||
|
||||
/* inherit DMA mask from host1x parent */
|
||||
@@ -249,6 +443,10 @@ static int nvjpg_probe(struct platform_device *pdev)
|
||||
|
||||
nvjpg->config = of_device_get_match_data(dev);
|
||||
|
||||
syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
|
||||
if (!syncpts)
|
||||
return -ENOMEM;
|
||||
|
||||
nvjpg->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(nvjpg->regs))
|
||||
return PTR_ERR(nvjpg->regs);
|
||||
@@ -272,12 +470,18 @@ static int nvjpg_probe(struct platform_device *pdev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = of_property_read_u32(dev->of_node, "nvidia,host1x-class", &host_class);
|
||||
if (err < 0)
|
||||
host_class = HOST1X_CLASS_NVJPG;
|
||||
|
||||
platform_set_drvdata(pdev, nvjpg);
|
||||
|
||||
INIT_LIST_HEAD(&nvjpg->client.base.list);
|
||||
nvjpg->client.base.ops = &nvjpg_client_ops;
|
||||
nvjpg->client.base.dev = dev;
|
||||
nvjpg->client.base.class = HOST1X_CLASS_NVJPG;
|
||||
nvjpg->client.base.class = host_class;
|
||||
nvjpg->client.base.syncpts = syncpts;
|
||||
nvjpg->client.base.num_syncpts = 1;
|
||||
nvjpg->dev = dev;
|
||||
|
||||
INIT_LIST_HEAD(&nvjpg->client.list);
|
||||
@@ -290,12 +494,20 @@ static int nvjpg_probe(struct platform_device *pdev)
|
||||
goto exit_falcon;
|
||||
}
|
||||
|
||||
err = nvjpg_devfreq_init(nvjpg);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
|
||||
goto unregister_client;
|
||||
}
|
||||
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 500);
|
||||
devm_pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
unregister_client:
|
||||
host1x_client_unregister(&nvjpg->client.base);
|
||||
exit_falcon:
|
||||
falcon_exit(&nvjpg->falcon);
|
||||
|
||||
@@ -328,3 +540,12 @@ struct platform_driver tegra_nvjpg_driver = {
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_210_NVJPG_FIRMWARE);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_186_NVJPG_FIRMWARE);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_194_NVJPG_FIRMWARE);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
|
||||
MODULE_FIRMWARE(NVIDIA_TEGRA_234_NVJPG_FIRMWARE);
|
||||
#endif
|
||||
@@ -18,6 +18,117 @@
|
||||
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
static ssize_t state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
struct notify_dev *sdev = (struct notify_dev *)
|
||||
dev_get_drvdata(dev);
|
||||
|
||||
if (sdev->print_state) {
|
||||
ret = sdev->print_state(sdev, buf);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
}
|
||||
return sprintf(buf, "%d\n", sdev->state);
|
||||
}
|
||||
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int ret;
|
||||
struct notify_dev *sdev = (struct notify_dev *)
|
||||
dev_get_drvdata(dev);
|
||||
|
||||
if (sdev->print_name) {
|
||||
ret = sdev->print_name(sdev, buf);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
}
|
||||
return sprintf(buf, "%s\n", sdev->name);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(state);
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static int create_switch_class(struct class **switch_class, atomic_t *switch_count)
|
||||
{
|
||||
if (!*switch_class) {
|
||||
*switch_class = class_create("switch");
|
||||
if (IS_ERR(*switch_class))
|
||||
return PTR_ERR(*switch_class);
|
||||
atomic_set(switch_count, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disp_uevent_dev_register(struct notify_dev *sdev, struct class **switch_class, atomic_t *switch_count)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!*switch_class) {
|
||||
ret = create_switch_class(switch_class, switch_count);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
sdev->index = atomic_inc_return(switch_count);
|
||||
sdev->dev = device_create(*switch_class, NULL,
|
||||
MKDEV(0, sdev->index), NULL, sdev->name);
|
||||
if (IS_ERR(sdev->dev))
|
||||
return PTR_ERR(sdev->dev);
|
||||
|
||||
ret = device_create_file(sdev->dev, &dev_attr_state);
|
||||
if (ret < 0)
|
||||
goto err_create_file_1;
|
||||
ret = device_create_file(sdev->dev, &dev_attr_name);
|
||||
if (ret < 0)
|
||||
goto err_create_file_2;
|
||||
|
||||
dev_set_drvdata(sdev->dev, sdev);
|
||||
sdev->state = 0;
|
||||
return 0;
|
||||
|
||||
err_create_file_2:
|
||||
device_remove_file(sdev->dev, &dev_attr_state);
|
||||
err_create_file_1:
|
||||
device_destroy(*switch_class, MKDEV(0, sdev->index));
|
||||
printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void disp_uevent_dev_unregister(struct notify_dev *sdev, struct class *switch_class)
|
||||
{
|
||||
device_remove_file(sdev->dev, &dev_attr_name);
|
||||
device_remove_file(sdev->dev, &dev_attr_state);
|
||||
device_destroy(switch_class, MKDEV(0, sdev->index));
|
||||
dev_set_drvdata(sdev->dev, NULL);
|
||||
}
|
||||
|
||||
static int notify_uevent_user(struct notify_dev *sdev, int state)
|
||||
{
|
||||
char *envp[3];
|
||||
char name_buf[120];
|
||||
char state_buf[120];
|
||||
|
||||
if (sdev == NULL)
|
||||
return -1;
|
||||
|
||||
if (sdev->state != state)
|
||||
sdev->state = state;
|
||||
|
||||
snprintf(name_buf, sizeof(name_buf), "SWITCH_NAME=%s", sdev->name);
|
||||
envp[0] = name_buf;
|
||||
snprintf(state_buf, sizeof(state_buf), "SWITCH_STATE=%d", sdev->state);
|
||||
envp[1] = state_buf;
|
||||
envp[2] = NULL;
|
||||
|
||||
kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_output_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct tegra_output *output = connector_to_output(connector);
|
||||
@@ -88,9 +199,14 @@ static irqreturn_t hpd_irq(int irq, void *data)
|
||||
{
|
||||
struct tegra_output *output = data;
|
||||
|
||||
if (output->connector.dev)
|
||||
if (output->connector.dev) {
|
||||
drm_helper_hpd_irq_event(output->connector.dev);
|
||||
|
||||
if (output->connector.connector_type == DRM_MODE_CONNECTOR_HDMIA ||
|
||||
output->connector.connector_type == DRM_MODE_CONNECTOR_HDMIB)
|
||||
notify_uevent_user(&output->notify_data, (output->connector.status == connector_status_connected ? 1 : 0));
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -207,13 +323,7 @@ void tegra_output_remove(struct tegra_output *output)
|
||||
int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
|
||||
{
|
||||
int connector_type;
|
||||
|
||||
/*
|
||||
* The connector is now registered and ready to receive hotplug events
|
||||
* so the hotplug interrupt can be enabled.
|
||||
*/
|
||||
if (output->hpd_gpio)
|
||||
enable_irq(output->hpd_irq);
|
||||
int err;
|
||||
|
||||
connector_type = output->connector.connector_type;
|
||||
/*
|
||||
@@ -228,8 +338,29 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
|
||||
&conn_info);
|
||||
if (!output->cec)
|
||||
return -ENOMEM;
|
||||
|
||||
if (output->hpd_gpio) {
|
||||
output->notify_data.name = "hdmi"; // now hwc not support DP
|
||||
output->notify_data.index = 0;
|
||||
output->notify_data.state = 0;
|
||||
err = disp_uevent_dev_register(&output->notify_data, &output->switch_class, &output->switch_count);
|
||||
if (err < 0) {
|
||||
dev_err(output->dev, "switch_dev_register failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (tegra_output_connector_detect(&output->connector, false) == connector_status_connected)
|
||||
notify_uevent_user(&output->notify_data, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The connector is now registered and ready to receive hotplug events
|
||||
* so the hotplug interrupt can be enabled.
|
||||
*/
|
||||
if (output->hpd_gpio)
|
||||
enable_irq(output->hpd_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -239,8 +370,10 @@ void tegra_output_exit(struct tegra_output *output)
|
||||
* The connector is going away, so the interrupt must be disabled to
|
||||
* prevent the hotplug interrupt handler from potentially crashing.
|
||||
*/
|
||||
if (output->hpd_gpio)
|
||||
if (output->hpd_gpio) {
|
||||
disable_irq(output->hpd_irq);
|
||||
disp_uevent_dev_unregister(&output->notify_data, output->switch_class);
|
||||
}
|
||||
}
|
||||
|
||||
void tegra_output_find_possible_crtcs(struct tegra_output *output,
|
||||
|
||||
@@ -55,7 +55,6 @@ struct tegra_sor_hdmi_settings {
|
||||
u8 preemphasis[4];
|
||||
};
|
||||
|
||||
#if 1
|
||||
static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
|
||||
{
|
||||
.frequency = 54000000,
|
||||
@@ -134,8 +133,8 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
|
||||
.preemphasis = { 0x00, 0x00, 0x00, 0x00 },
|
||||
},
|
||||
};
|
||||
#else
|
||||
static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
|
||||
|
||||
static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_odin[] = {
|
||||
{
|
||||
.frequency = 75000000,
|
||||
.vcocap = 0x3,
|
||||
@@ -198,7 +197,6 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
|
||||
.preemphasis = { 0x02, 0x3f, 0x3f, 0x3f },
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct tegra_sor_hdmi_settings tegra186_sor_hdmi_defaults[] = {
|
||||
{
|
||||
@@ -2557,6 +2555,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
|
||||
value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
|
||||
value &= ~DITHER_CONTROL_MASK;
|
||||
value &= ~BASE_COLOR_SIZE_MASK;
|
||||
if (dc->soc->has_nvdisplay) {
|
||||
tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
|
||||
tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
|
||||
|
||||
tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
|
||||
DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
|
||||
|
||||
value |= CMU_ENABLE_ENABLE;
|
||||
}
|
||||
|
||||
switch (state->bpc) {
|
||||
case 6:
|
||||
@@ -2921,6 +2930,20 @@ static void tegra_sor_dp_enable(struct drm_encoder *encoder)
|
||||
if (err < 0)
|
||||
dev_err(sor->dev, "failed to attach SOR: %d\n", err);
|
||||
|
||||
if (dc->soc->has_nvdisplay) {
|
||||
value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
|
||||
tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
|
||||
tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
|
||||
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
|
||||
|
||||
tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
|
||||
DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
|
||||
|
||||
value |= CMU_ENABLE_ENABLE;
|
||||
tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
|
||||
}
|
||||
|
||||
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
|
||||
value |= SOR_ENABLE(sor->index);
|
||||
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
|
||||
@@ -3508,6 +3531,26 @@ static const struct tegra_sor_soc tegra210_sor1 = {
|
||||
.tx_pu = tegra124_sor_tx_pu,
|
||||
};
|
||||
|
||||
static const struct tegra_sor_soc tegra210_sor1_odin = {
|
||||
.supports_lvds = false,
|
||||
.supports_hdmi = true,
|
||||
.supports_dp = true,
|
||||
.supports_audio = true,
|
||||
.supports_hdcp = true,
|
||||
|
||||
.regs = &tegra210_sor_regs,
|
||||
.has_nvdisplay = false,
|
||||
|
||||
.num_settings = ARRAY_SIZE(tegra210_sor_hdmi_odin),
|
||||
.settings = tegra210_sor_hdmi_odin,
|
||||
.xbar_cfg = tegra210_sor_xbar_cfg,
|
||||
.lane_map = tegra210_sor_lane_map,
|
||||
.voltage_swing = tegra124_sor_voltage_swing,
|
||||
.pre_emphasis = tegra124_sor_pre_emphasis,
|
||||
.post_cursor = tegra124_sor_post_cursor,
|
||||
.tx_pu = tegra124_sor_tx_pu,
|
||||
};
|
||||
|
||||
static const struct tegra_sor_regs tegra186_sor_regs = {
|
||||
.head_state0 = 0x151,
|
||||
.head_state1 = 0x154,
|
||||
@@ -3631,6 +3674,7 @@ static const struct of_device_id tegra_sor_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra194-sor", .data = &tegra194_sor },
|
||||
{ .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor },
|
||||
{ .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 },
|
||||
{ .compatible = "nvidia,tegra210-sor1-odin", .data = &tegra210_sor1_odin },
|
||||
{ .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor },
|
||||
{ .compatible = "nvidia,tegra132-sor", .data = &tegra132_sor },
|
||||
{ .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor },
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/host1x.h>
|
||||
#include <linux/iommu.h>
|
||||
@@ -35,6 +36,7 @@ struct vic {
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
struct reset_control *rst;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
bool can_use_context;
|
||||
|
||||
@@ -52,6 +54,74 @@ static void vic_writel(struct vic *vic, u32 value, unsigned int offset)
|
||||
writel(value, vic->regs + offset);
|
||||
}
|
||||
|
||||
static int vic_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
u32 flags)
|
||||
{
|
||||
struct vic *vic = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
err = clk_set_rate(vic->clk, *freq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
*freq = clk_get_rate(vic->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vic_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
|
||||
{
|
||||
struct vic *vic = dev_get_drvdata(dev);
|
||||
|
||||
*freq = clk_get_rate(vic->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct devfreq_dev_profile vic_devfreq_profile = {
|
||||
.polling_ms = 50,
|
||||
.target = vic_devfreq_target,
|
||||
.get_cur_freq = vic_devfreq_get_cur_freq,
|
||||
};
|
||||
|
||||
static int vic_devfreq_init(struct vic *vic)
|
||||
{
|
||||
unsigned long max_rate = clk_round_rate(vic->clk, ULONG_MAX);
|
||||
unsigned long min_rate = clk_round_rate(vic->clk, 0);
|
||||
unsigned long margin = clk_round_rate(vic->clk, min_rate + 1) - min_rate;
|
||||
unsigned long rate = min_rate;
|
||||
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
|
||||
struct devfreq *devfreq;
|
||||
|
||||
if (min_rate == max_rate) {
|
||||
dev_info(vic->dev, "Only one supported clock rate, disabling devfreq\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Only allow up to 20 rates
|
||||
if (hw_rates > 20)
|
||||
margin *= DIV_ROUND_UP(hw_rates, 20);
|
||||
|
||||
while (rate < max_rate) {
|
||||
dev_pm_opp_add(vic->dev, rate, 0);
|
||||
rate += margin;
|
||||
}
|
||||
|
||||
// The margin step may not fall on max rate exactly, so add max rate explicitly
|
||||
dev_pm_opp_add(vic->dev, max_rate, 0);
|
||||
|
||||
devfreq = devm_devfreq_add_device(vic->dev,
|
||||
&vic_devfreq_profile,
|
||||
DEVFREQ_GOV_USERSPACE,
|
||||
NULL);
|
||||
if (IS_ERR(devfreq))
|
||||
return PTR_ERR(devfreq);
|
||||
|
||||
vic->devfreq = devfreq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vic_boot(struct vic *vic)
|
||||
{
|
||||
u32 fce_ucode_size, fce_bin_data_offset, stream_id;
|
||||
@@ -328,6 +398,12 @@ static int __maybe_unused vic_runtime_resume(struct device *dev)
|
||||
if (err < 0)
|
||||
goto assert;
|
||||
|
||||
if (vic->devfreq) {
|
||||
err = devfreq_resume_device(vic->devfreq);
|
||||
if (err < 0)
|
||||
goto assert;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
assert:
|
||||
@@ -342,6 +418,12 @@ static int __maybe_unused vic_runtime_suspend(struct device *dev)
|
||||
struct vic *vic = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
if (vic->devfreq) {
|
||||
err = devfreq_suspend_device(vic->devfreq);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
host1x_channel_stop(vic->channel);
|
||||
|
||||
err = reset_control_assert(vic->rst);
|
||||
@@ -520,12 +602,20 @@ static int vic_probe(struct platform_device *pdev)
|
||||
goto exit_falcon;
|
||||
}
|
||||
|
||||
err = vic_devfreq_init(vic);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
|
||||
goto unregister_client;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 500);
|
||||
|
||||
return 0;
|
||||
|
||||
unregister_client:
|
||||
host1x_client_unregister(&vic->client.base);
|
||||
exit_falcon:
|
||||
falcon_exit(&vic->falcon);
|
||||
|
||||
|
||||
@@ -97,6 +97,9 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
|
||||
bus = of_node_get(adap->dev.of_node);
|
||||
|
||||
for_each_available_child_of_node(bus, node) {
|
||||
if (!strcmp(node->name, "prod-settings"))
|
||||
continue;
|
||||
|
||||
if (of_node_test_and_set_flag(node, OF_POPULATED))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ menuconfig INPUT_TOUCHSCREEN
|
||||
If unsure, say Y.
|
||||
|
||||
if INPUT_TOUCHSCREEN
|
||||
source "drivers/input/touchscreen/stm/Kconfig"
|
||||
|
||||
config TOUCHSCREEN_88PM860X
|
||||
tristate "Marvell 88PM860x touchscreen"
|
||||
|
||||
@@ -119,3 +119,4 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_IQS7211) += iqs7211.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_FTM4) += stm/
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# STMicroelectronics TOUCH driver configuration
|
||||
#
|
||||
|
||||
config TOUCHSCREEN_FTM4
|
||||
tristate "STMicroelectronics i2c multitouch touchscreen - FTM4 with FingerTipS"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to enable STMicroelectronics touchscreen support.
|
||||
If unsure, say N.
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called fts_touch.
|
||||
|
||||
config TOUCHSCREEN_FTM4_SHOW_EVENTS
|
||||
bool "Enable debug of FTM4 events"
|
||||
depends on TOUCHSCREEN_FTM4
|
||||
help
|
||||
Say Y here to enable dumping of touch driver events. This should
|
||||
only be enabled for debugging and not for shipping code.
|
||||
@@ -0,0 +1,3 @@
|
||||
# FTM4 driver
|
||||
obj-$(CONFIG_TOUCHSCREEN_FTM4) += ftm4.o
|
||||
ftm4-objs += ftm4_ts.o
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,374 @@
|
||||
/******************************** FingerTipS 4CD60D ****************************
|
||||
*
|
||||
* File Name : fts.c
|
||||
* Authors : Copyright (c) 2012 STMicroelectronics, Analog Mems Sensor Team
|
||||
* Copyright (c) 2019-2020 Billy Laws <blaws05@gmail.com>
|
||||
* Copyright (c) 2019-2021 Kostas Missos <ctcaer@gmail.com>
|
||||
* Description : FTS Capacitive touch screen controller (FingerTipS)
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
|
||||
* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
|
||||
* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
|
||||
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
|
||||
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
|
||||
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LINUX_FTM4_TS_H_
|
||||
#define _LINUX_FTM4_TS_H_
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
#include <linux/printk.h>
|
||||
#define tsp_debug_dbg(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
|
||||
#define tsp_debug_info(dev, fmt, ...) dev_info(dev, fmt, ## __VA_ARGS__)
|
||||
#define tsp_debug_err(dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__)
|
||||
#ifdef CONFIG_TOUCHSCREEN_FTM4_SHOW_EVENTS
|
||||
#define tsp_debug_event(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define tsp_debug_event(dev, fmt, ...)
|
||||
#endif
|
||||
|
||||
#define FTS_INPUT_OPEN_DWORK_TIME 10
|
||||
|
||||
#define FTS_TS_DRV_NAME "fts_touch"
|
||||
#define FTS_TS_DRV_VERSION "4CD60D"
|
||||
|
||||
#define STM_DEVICE_NAME "STM"
|
||||
|
||||
#define FTS_ID0 0x36
|
||||
#define FTS_ID1 0x70
|
||||
|
||||
#define FTS_DIGITAL_REV_1 0x01
|
||||
#define FTS_DIGITAL_REV_2 0x02
|
||||
#define FTS_FIFO_MAX 32
|
||||
#define FTS_EVENT_SIZE 8
|
||||
#define FTS_FW_UPDATE_RETRY 3
|
||||
#define FTS_LOCKDOWNCODE_SIZE 13
|
||||
|
||||
#define PRESSURE_MIN 0
|
||||
#define PRESSURE_MAX 500
|
||||
#define FINGER_MAX 10
|
||||
|
||||
#define EVENTID_NO_EVENT 0x00
|
||||
#define EVENTID_ENTER_POINTER 0x03
|
||||
#define EVENTID_LEAVE_POINTER 0x04
|
||||
#define EVENTID_HOS_EVENT 0x04
|
||||
#define EVENTID_MOTION_POINTER 0x05
|
||||
#define EVENTID_HOVER_ENTER_POINTER 0x07
|
||||
#define EVENTID_HOVER_LEAVE_POINTER 0x08
|
||||
#define EVENTID_MOTION_POINTER 0x05
|
||||
#define EVENTID_HOVER_MOTION_POINTER 0x09
|
||||
#define EVENTID_PROXIMITY_IN 0x0B
|
||||
#define EVENTID_PROXIMITY_OUT 0x0C
|
||||
#define EVENTID_MSKEY 0x0E
|
||||
#define EVENTID_ERROR 0x0F
|
||||
#define EVENTID_CONTROLLER_READY 0x10
|
||||
#define EVENTID_SLEEPOUT_CONTROLLER_READY 0x11
|
||||
#define EVENTID_RESULT_READ_REGISTER 0x12
|
||||
#define EVENTID_STATUS_REQUEST_COMP 0x13
|
||||
|
||||
#define EVENTID_STATUS_EVENT 0x16
|
||||
#define EVENTID_INTERNAL_RELEASE_INFO 0x14
|
||||
#define EVENTID_EXTERNAL_RELEASE_INFO 0x15
|
||||
|
||||
#define EVENTID_FROM_STRING 0x80
|
||||
#define EVENTID_GESTURE 0x20
|
||||
|
||||
#define EVENTID_SIDE_SCROLL 0x40
|
||||
/* side touch event-id for debug, remove after f/w fixed */
|
||||
#define EVENTID_SIDE_TOUCH_DEBUG 0xDB
|
||||
#define EVENTID_SIDE_TOUCH 0x0B
|
||||
|
||||
#define EVENTID_ERROR_FLASH_CORRUPTION 0x03
|
||||
|
||||
/* define flash corruption type */
|
||||
#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_1 0x01
|
||||
#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_2 0x02
|
||||
#define EVENTID_ERROR_CX_FLASH_CORRUPTION 0x03
|
||||
|
||||
#define EVENTID_LOCKDOWN_CODE 0x1E
|
||||
#define EVENTID_ERROR_LOCKDOWN 0x0B
|
||||
|
||||
#define STATUS_EVENT_MS_CX_TUNING_DONE 0x01
|
||||
#define STATUS_EVENT_SS_CX_TUNING_DONE 0x02
|
||||
#define STATUS_EVENT_FLASH_WRITE_CONFIG 0x03
|
||||
#define STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE 0x04
|
||||
#define STATUS_EVENT_FORCE_CAL_MUTUAL_SELF 0x05
|
||||
#define STATUS_EVENT_FORCE_CAL_DONE 0x06
|
||||
|
||||
#define STATUS_EVENT_FORCE_CAL_MUTUAL 0x15
|
||||
#define STATUS_EVENT_FORCE_CAL_SELF 0x06
|
||||
#define STATUS_EVENT_PARAM1_FCAL_MS_SS_DONE 0x23
|
||||
#define STATUS_EVENT_WATERMODE_ON 0x07
|
||||
#define STATUS_EVENT_WATERMODE_OFF 0x08
|
||||
#define STATUS_EVENT_RTUNE_MUTUAL 0x09
|
||||
#define STATUS_EVENT_RTUNE_SELF 0x0A
|
||||
#define STATUS_EVENT_PANEL_TEST_RESULT 0x0B
|
||||
#define STATUS_EVENT_GLOVE_MODE 0x0C
|
||||
#define STATUS_EVENT_RAW_DATA_READY 0x0D
|
||||
#define STATUS_EVENT_MUTUAL_CAL_FRAME_CHECK 0xC1
|
||||
#define STATUS_EVENT_SELF_CAL_FRAME_CHECK 0xC2
|
||||
#define STATUS_EVENT_CHARGER_CONNECTED 0xCC
|
||||
#define STATUS_EVENT_CHARGER_DISCONNECTED 0xCD
|
||||
#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_WRITE_FINISH 0x10
|
||||
#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_CLEAR_FINISH 0x11
|
||||
|
||||
#define INT_ENABLE 0x48
|
||||
#define INT_DISABLE 0x08
|
||||
|
||||
#define FTS_READ_STATUS 0x84
|
||||
#define FTS_READ_ONE_EVENT 0x85
|
||||
#define FTS_READ_ALL_EVENT 0x86
|
||||
|
||||
#define FTS_CMD_SENSEOFF 0x92
|
||||
#define FTS_CMD_SENSEON 0x93
|
||||
#define FTS_CMD_HOVER_OFF 0x94
|
||||
#define FTS_CMD_HOVER_ON 0x95
|
||||
|
||||
#define FTS_CMD_MSKEY_AUTOTUNE 0x96
|
||||
#define FTS_CMD_TRIM_LOW_POWER_OSCILLATOR 0x97
|
||||
|
||||
#define FTS_CMD_KEY_SENSE_OFF 0x9A
|
||||
#define FTS_CMD_KEY_SENSE_ON 0x9B
|
||||
#define FTS_CMD_SET_FAST_GLOVE_MODE 0x9D
|
||||
|
||||
#define FTS_CMD_MSHOVER_OFF 0x9E
|
||||
#define FTS_CMD_MSHOVER_ON 0x9F
|
||||
#define FTS_CMD_SET_NOR_GLOVE_MODE 0x9F
|
||||
|
||||
#define FTS_CMD_FLUSHBUFFER 0xA1
|
||||
#define FTS_CMD_FORCECALIBRATION 0xA2
|
||||
#define FTS_CMD_MS_CX_TUNING 0xA3
|
||||
#define FTS_CMD_SS_CX_TUNING 0xA4
|
||||
|
||||
#define FTS_CMD_ITO_CHECK 0xA7
|
||||
|
||||
#define FTS_CMD_CHARGER_PLUGGED 0xA8
|
||||
#define FTS_CMD_CHARGER_UNPLUGGED 0xAB
|
||||
|
||||
#define FTS_CMD_RELEASEINFO 0xAA
|
||||
#define FTS_CMD_STYLUS_OFF 0xAB
|
||||
#define FTS_CMD_STYLUS_ON 0xAC
|
||||
#define FTS_CMD_LOWPOWER_MODE 0xAD
|
||||
|
||||
#define FTS_CMD_WRITE_REG 0xB6
|
||||
|
||||
#define FTS_CMS_ENABLE_FEATURE 0xC1
|
||||
#define FTS_CMS_DISABLE_FEATURE 0xC2
|
||||
#define FTS_CMD_SWITCH_SENSE_MODE 0xC3
|
||||
#define FTS_CMD_LOCKDOWN_READ 0xC4
|
||||
|
||||
#define FTS_CMD_WRITE_PRAM 0xF0
|
||||
#define FTS_CMD_BURN_PROG_FLASH 0xF2
|
||||
#define FTS_CMD_ERASE_PROG_FLASH 0xF3
|
||||
#define FTS_CMD_READ_FLASH_STAT 0xF4
|
||||
#define FTS_CMD_UNLOCK_FLASH 0xF7
|
||||
#define FTS_CMD_SAVE_FWCONFIG 0xFB
|
||||
#define FTS_CMD_SAVE_CX_TUNING 0xFC
|
||||
|
||||
#define FTS_CMD_FAST_SCAN 0x01
|
||||
#define FTS_CMD_SLOW_SCAN 0x02
|
||||
#define FTS_CMD_USLOW_SCAN 0x03
|
||||
|
||||
#define FTS_STYLUS_MODE 0x00
|
||||
#define FTS_FINGER_MODE 0x01
|
||||
#define FTS_HOVER_MODE 0x02
|
||||
|
||||
#define FTS_REPORT_RATE_90HZ 0
|
||||
#define FTS_REPORT_RATE_60HZ 1
|
||||
#define FTS_REPORT_RATE_30HZ 2
|
||||
|
||||
#define FTS_CMD_STRING_ACCESS 0xEC00
|
||||
#define FTS_CMD_NOTIFY 0xC0
|
||||
|
||||
#define FTS_RETRY_COUNT 10
|
||||
|
||||
/* QUICK SHOT : Quick Camera Launching */
|
||||
#define FTS_STRING_EVENT_REAR_CAM (1 << 0)
|
||||
#define FTS_STRING_EVENT_FRONT_CAM (1 << 1)
|
||||
|
||||
/* SCRUB : Display Watch, Event Status / Fast Access Event */
|
||||
#define FTS_STRING_EVENT_WATCH_STATUS (1 << 2)
|
||||
#define FTS_STRING_EVENT_FAST_ACCESS (1 << 3)
|
||||
#define FTS_STRING_EVENT_DIRECT_INDICATOR ((1 << 3) | (1 << 2))
|
||||
#define FTS_STRING_EVENT_SPAY (1 << 4)
|
||||
#define FTS_STRING_EVENT_SPAY1 (1 << 5)
|
||||
#define FTS_STRING_EVENT_SPAY2 ((1 << 4) | (1 << 5))
|
||||
|
||||
#define FTS_SIDEGESTURE_EVENT_SINGLE_STROKE 0xE0
|
||||
#define FTS_SIDEGESTURE_EVENT_DOUBLE_STROKE 0xE1
|
||||
#define FTS_SIDEGESTURE_EVENT_INNER_STROKE 0xE3
|
||||
|
||||
#define FTS_SIDETOUCH_EVENT_LONG_PRESS 0xBB
|
||||
#define FTS_SIDETOUCH_EVENT_REBOOT_BY_ESD 0xED
|
||||
|
||||
#define FTS_ENABLE 1
|
||||
#define FTS_DISABLE 0
|
||||
|
||||
#define FTS_MODE_QUICK_SHOT (1 << 0)
|
||||
#define FTS_MODE_SCRUB (1 << 1)
|
||||
#define FTS_MODE_SPAY (1 << 1)
|
||||
#define FTS_MODE_QUICK_APP_ACCESS (1 << 2)
|
||||
#define FTS_MODE_DIRECT_INDICATOR (1 << 3)
|
||||
|
||||
#define TSP_BUF_SIZE 2048
|
||||
#define CMD_STR_LEN 32
|
||||
#define CMD_RESULT_STR_LEN 2048
|
||||
#define CMD_PARAM_NUM 8
|
||||
|
||||
#define FTS_LOWP_FLAG_QUICK_CAM (1 << 0)
|
||||
#define FTS_LOWP_FLAG_2ND_SCREEN (1 << 1)
|
||||
#define FTS_LOWP_FLAG_BLACK_UI (1 << 2)
|
||||
#define FTS_LOWP_FLAG_QUICK_APP_ACCESS (1 << 3)
|
||||
#define FTS_LOWP_FLAG_DIRECT_INDICATOR (1 << 4)
|
||||
#define FTS_LOWP_FLAG_SPAY (1 << 5)
|
||||
#define FTS_LOWP_FLAG_TEMP_CMD (1 << 6)
|
||||
|
||||
enum fts_error_return {
|
||||
FTS_NOT_ERROR = 0,
|
||||
FTS_ERROR_INVALID_CHIP_ID,
|
||||
FTS_ERROR_INVALID_CHIP_VERSION_ID,
|
||||
FTS_ERROR_INVALID_SW_VERSION,
|
||||
FTS_ERROR_EVENT_ID,
|
||||
FTS_ERROR_TIMEOUT,
|
||||
FTS_ERROR_FW_UPDATE_FAIL,
|
||||
};
|
||||
#define RAW_MAX 3750
|
||||
/**
|
||||
* struct fts_finger - Represents fingers.
|
||||
* @ state: finger status (Event ID).
|
||||
* @ mcount: moving counter for debug.
|
||||
*/
|
||||
struct fts_finger {
|
||||
unsigned char state;
|
||||
int lx;
|
||||
int ly;
|
||||
};
|
||||
|
||||
enum tsp_power_mode {
|
||||
FTS_POWER_STATE_ACTIVE = 0,
|
||||
FTS_POWER_STATE_POWERDOWN,
|
||||
};
|
||||
|
||||
enum fts_customer_feature {
|
||||
FTS_FEATURE_ORIENTATION_GESTURE = 1,
|
||||
FTS_FEATURE_STYLUS,
|
||||
FTS_FEATURE_QUICK_SHORT_CAMERA_ACCESS,
|
||||
FTS_FEATURE_SIDE_GUSTURE,
|
||||
FTS_FEATURE_COVER_GLASS,
|
||||
FTS_FEATURE_COVER_WALLET,
|
||||
FTS_FEATURE_COVER_LED,
|
||||
FTS_FEATURE_COVER_CLEAR_FLIP,
|
||||
FTS_FEATURE_DUAL_SIDE_GUSTURE,
|
||||
FTS_FEATURE_CUSTOM_COVER_GLASS_ON,
|
||||
};
|
||||
|
||||
struct fts_flash_corruption_info {
|
||||
bool fw_broken;
|
||||
bool cfg_broken;
|
||||
bool cx_broken;
|
||||
};
|
||||
|
||||
struct fts_i2c_platform_data {
|
||||
bool disable_tuning;
|
||||
bool delayed_open;
|
||||
unsigned int delayed_open_time;
|
||||
int max_x;
|
||||
int max_y;
|
||||
|
||||
struct regulator *regulator_dvdd;
|
||||
struct regulator *regulator_avdd;
|
||||
|
||||
int (*power)(void *data, bool on);
|
||||
|
||||
unsigned gpio;
|
||||
int vdd_gpio;
|
||||
int vio_gpio;
|
||||
int irq_type;
|
||||
|
||||
int coord_factor;
|
||||
int x_axis_real_max;
|
||||
int y_axis_real_max;
|
||||
int x_axis_edge_offset;
|
||||
int y_axis_edge_offset;
|
||||
};
|
||||
|
||||
struct fts_ts_info {
|
||||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
struct work_struct work;
|
||||
|
||||
int irq;
|
||||
int irq_type;
|
||||
atomic_t irq_enabled;
|
||||
struct fts_i2c_platform_data *board;
|
||||
|
||||
bool run_autotune;
|
||||
|
||||
int power_state;
|
||||
int touch_count;
|
||||
struct fts_finger finger[FINGER_MAX];
|
||||
bool palm_pressed;
|
||||
int palm_touch_id;
|
||||
|
||||
int touch_mode;
|
||||
|
||||
struct delayed_work open_work;
|
||||
|
||||
struct mutex i2c_mutex;
|
||||
struct mutex device_mutex;
|
||||
spinlock_t lock;
|
||||
|
||||
unsigned char data[FTS_EVENT_SIZE * FTS_FIFO_MAX];
|
||||
|
||||
struct fts_flash_corruption_info flash_corruption_info;
|
||||
};
|
||||
|
||||
#define WRITE_CHUNK_SIZE 32
|
||||
#define FLASH_CHUNK (64 * 1024)
|
||||
#define DMA_CHUNK 32
|
||||
|
||||
#define FW_HEADER_SIZE 64
|
||||
#define FW_HEADER_FTB_SIGNATURE 0xAA55AA55
|
||||
#define FW_FTB_VER 0x00000001
|
||||
#define FW_BYTES_ALLIGN 4
|
||||
#define FW_BIN_VER_OFFSET 16
|
||||
#define FW_BIN_CONFIG_VER_OFFSET 20
|
||||
|
||||
/* Command for flash */
|
||||
#define FLASH_CMD_UNLOCK 0xF7
|
||||
#define FLASH_CMD_WRITE_64K 0xF8
|
||||
#define FLASH_CMD_READ_REGISTER 0xF9
|
||||
#define FLASH_CMD_WRITE_REGISTER 0xFA
|
||||
|
||||
/* Parameters for commands */
|
||||
#define ADDR_WARM_BOOT 0x001E
|
||||
#define WARM_BOOT_VALUE 0x38
|
||||
#define FLASH_ADDR_CODE 0x00000000
|
||||
#define FLASH_ADDR_CONFIG 0x0000FC00
|
||||
|
||||
#define FLASH_UNLOCK_CODE0 0x74
|
||||
#define FLASH_UNLOCK_CODE1 0x45
|
||||
|
||||
#define FLASH_ERASE_UNLOCK_CODE0 0x72
|
||||
#define FLASH_ERASE_UNLOCK_CODE1 0x03
|
||||
#define FLASH_ERASE_UNLOCK_CODE2 0x02
|
||||
#define FLASH_ERASE_CODE0 0x02
|
||||
#define FLASH_ERASE_CODE1 0xC0
|
||||
#define FLASH_DMA_CODE0 0x05
|
||||
#define FLASH_DMA_CODE1 0xC0
|
||||
#define FLASH_DMA_CONFIG 0x06
|
||||
|
||||
#endif /* _LINUX_FTM4_TS_H_ */
|
||||
@@ -55,6 +55,7 @@ config TEGRA210_EMC
|
||||
tristate "NVIDIA Tegra210 External Memory Controller driver"
|
||||
depends on ARCH_TEGRA_210_SOC || COMPILE_TEST
|
||||
select TEGRA210_EMC_TABLE
|
||||
select PM_OPP
|
||||
help
|
||||
This driver is for the External Memory Controller (EMC) found on
|
||||
Tegra210 chips. The EMC controls the external DRAM on the board.
|
||||
|
||||
@@ -541,6 +541,14 @@ int tegra30_mc_probe(struct tegra_mc *mc)
|
||||
if (err < 0)
|
||||
return dev_err_probe(mc->dev, err, "failed to setup timings\n");
|
||||
|
||||
err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,17 @@ struct tegra186_emc_dvfs {
|
||||
unsigned long rate;
|
||||
};
|
||||
|
||||
enum emc_rate_request_type {
|
||||
EMC_RATE_DEBUG,
|
||||
EMC_RATE_ICC,
|
||||
EMC_RATE_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct emc_rate_request {
|
||||
unsigned long min_rate;
|
||||
unsigned long max_rate;
|
||||
};
|
||||
|
||||
struct tegra186_emc {
|
||||
struct tegra_bpmp *bpmp;
|
||||
struct device *dev;
|
||||
@@ -34,8 +45,90 @@ struct tegra186_emc {
|
||||
} debugfs;
|
||||
|
||||
struct icc_provider provider;
|
||||
|
||||
/*
|
||||
* There are multiple sources in the EMC driver which could request
|
||||
* a min/max clock rate, these rates are contained in this array.
|
||||
*/
|
||||
struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
|
||||
|
||||
/* protect shared rate-change code path */
|
||||
struct mutex rate_lock;
|
||||
};
|
||||
|
||||
static void tegra186_emc_rate_requests_init(struct tegra186_emc *emc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
|
||||
emc->requested_rate[i].min_rate = 0;
|
||||
emc->requested_rate[i].max_rate = ULONG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static int emc_request_rate(struct tegra186_emc *emc,
|
||||
unsigned long new_min_rate,
|
||||
unsigned long new_max_rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = emc->requested_rate;
|
||||
unsigned long min_rate = 0, max_rate = ULONG_MAX;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
/* select minimum and maximum rates among the requested rates */
|
||||
for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
|
||||
if (i == type) {
|
||||
min_rate = max(new_min_rate, min_rate);
|
||||
max_rate = min(new_max_rate, max_rate);
|
||||
} else {
|
||||
min_rate = max(req->min_rate, min_rate);
|
||||
max_rate = min(req->max_rate, max_rate);
|
||||
}
|
||||
}
|
||||
|
||||
if (min_rate > max_rate) {
|
||||
dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
|
||||
__func__, type, min_rate, max_rate);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
err = clk_set_rate(emc->clk, min_rate);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
emc->requested_rate[type].min_rate = new_min_rate;
|
||||
emc->requested_rate[type].max_rate = new_max_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emc_set_min_rate(struct tegra186_emc *emc, unsigned long rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = &emc->requested_rate[type];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&emc->rate_lock);
|
||||
ret = emc_request_rate(emc, rate, req->max_rate, type);
|
||||
mutex_unlock(&emc->rate_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int emc_set_max_rate(struct tegra186_emc *emc, unsigned long rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = &emc->requested_rate[type];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&emc->rate_lock);
|
||||
ret = emc_request_rate(emc, req->min_rate, rate, type);
|
||||
mutex_unlock(&emc->rate_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* debugfs interface
|
||||
*
|
||||
@@ -108,7 +201,7 @@ static int tegra186_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
if (!tegra186_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = clk_set_min_rate(emc->clk, rate);
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -138,7 +231,7 @@ static int tegra186_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
if (!tegra186_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = clk_set_max_rate(emc->clk, rate);
|
||||
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -218,6 +311,12 @@ static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc *emc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct tegra186_emc *
|
||||
to_tegra186_emc_provider(struct icc_provider *provider)
|
||||
{
|
||||
return container_of(provider, struct tegra186_emc, provider);
|
||||
}
|
||||
|
||||
/*
|
||||
* tegra186_emc_icc_set_bw() - Set BW api for EMC provider
|
||||
* @src: ICC node for External Memory Controller (EMC)
|
||||
@@ -228,6 +327,33 @@ static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc *emc)
|
||||
*/
|
||||
static int tegra186_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
struct tegra186_emc *emc = to_tegra186_emc_provider(dst->provider);
|
||||
struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent);
|
||||
unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
|
||||
unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
|
||||
unsigned long long rate = max(avg_bw, peak_bw);
|
||||
const unsigned int ddr = 2;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Do nothing here if bwmgr is supported in BPMP-FW. BPMP-FW sets the final
|
||||
* Freq based on the passed values.
|
||||
*/
|
||||
if (mc->bwmgr_mrq_supported)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Tegra186 EMC runs on a clock rate of SDRAM bus. This means that
|
||||
* EMC clock rate is twice smaller than the peak data rate because
|
||||
* data is sampled on both EMC clock edges.
|
||||
*/
|
||||
do_div(rate, ddr);
|
||||
rate = min_t(u64, rate, U32_MAX);
|
||||
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -317,6 +443,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
if (!emc)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&emc->rate_lock);
|
||||
|
||||
emc->bpmp = tegra_bpmp_get(&pdev->dev);
|
||||
if (IS_ERR(emc->bpmp))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp),
|
||||
@@ -339,6 +467,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, emc);
|
||||
emc->dev = &pdev->dev;
|
||||
|
||||
tegra186_emc_rate_requests_init(emc);
|
||||
|
||||
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_EMC_DVFS_LATENCY)) {
|
||||
err = tegra186_emc_get_emc_dvfs_latency(emc);
|
||||
if (err)
|
||||
@@ -393,6 +523,9 @@ static const struct of_device_id tegra186_emc_of_match[] = {
|
||||
#if defined(CONFIG_ARCH_TEGRA_186_SOC)
|
||||
{ .compatible = "nvidia,tegra186-emc" },
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
{ .compatible = "nvidia,tegra210b01-emc" },
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_TEGRA_194_SOC)
|
||||
{ .compatible = "nvidia,tegra194-emc" },
|
||||
#endif
|
||||
|
||||
@@ -898,6 +898,14 @@ static const struct tegra_mc_client tegra186_mc_clients[] = {
|
||||
.security = 0x51c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER0,
|
||||
.name = "sw_cluster0",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER1,
|
||||
.name = "sw_cluster1",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -910,6 +918,99 @@ static const struct tegra_mc_intmask tegra186_mc_intmasks[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int tegra186_mc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
/* TODO: program PTSA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
struct icc_provider *p = node->provider;
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
|
||||
|
||||
if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
|
||||
node->id == TEGRA_ICC_MC_CPU_CLUSTER1) {
|
||||
if (mc)
|
||||
peak_bw = peak_bw * mc->num_channels;
|
||||
}
|
||||
|
||||
/*
|
||||
* ISO clients need to reserve extra bandwidth up-front because
|
||||
* there could be high bandwidth pressure during initial filling
|
||||
* of the client's FIFO buffers. Secondly, we need to take into
|
||||
* account impurities of the memory subsystem.
|
||||
*/
|
||||
if (tag & TEGRA_MC_ICC_TAG_ISO)
|
||||
peak_bw = tegra_mc_scale_percents(peak_bw, 400);
|
||||
|
||||
*agg_avg += avg_bw;
|
||||
*agg_peak = max(*agg_peak, peak_bw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node_data *
|
||||
tegra186_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
|
||||
const struct tegra_mc_client *client;
|
||||
unsigned int i, idx = spec->args[0];
|
||||
struct icc_node_data *ndata;
|
||||
struct icc_node *node;
|
||||
|
||||
list_for_each_entry(node, &mc->provider.nodes, node_list) {
|
||||
if (node->id != idx)
|
||||
continue;
|
||||
|
||||
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
|
||||
if (!ndata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
client = &mc->soc->clients[idx];
|
||||
ndata->node = node;
|
||||
|
||||
switch (client->sid) {
|
||||
case TEGRA186_SID_NVDISPLAY:
|
||||
case TEGRA186_SID_VI:
|
||||
/* these clients are isochronous by default */
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
|
||||
break;
|
||||
|
||||
default:
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ndata;
|
||||
}
|
||||
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == idx)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static const struct tegra_mc_icc_ops tegra186_mc_icc_ops = {
|
||||
.xlate_extended = tegra186_mc_of_icc_xlate_extended,
|
||||
.aggregate = tegra186_mc_icc_aggregate,
|
||||
.get_bw = tegra186_mc_icc_get_init_bw,
|
||||
.set = tegra186_mc_icc_set,
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra186_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra186_mc_clients),
|
||||
.clients = tegra186_mc_clients,
|
||||
@@ -919,6 +1020,7 @@ const struct tegra_mc_soc tegra186_mc_soc = {
|
||||
.intmasks = tegra186_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra186_mc_intmasks),
|
||||
.ops = &tegra186_mc_ops,
|
||||
.icc_ops = &tegra186_mc_icc_ops,
|
||||
.ch_intmask = 0x0000000f,
|
||||
.global_intstatus_channel_shift = 0,
|
||||
.regs = &tegra20_mc_regs,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/dev_printk.h>
|
||||
#include <linux/of.h>
|
||||
#include <soc/tegra/mc.h>
|
||||
|
||||
#include <dt-bindings/memory/tegra194-mc.h>
|
||||
@@ -1340,6 +1342,22 @@ static const struct tegra_mc_client tegra194_mc_clients[] = {
|
||||
.security = 0x7fc,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER0,
|
||||
.name = "sw_cluster0",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER1,
|
||||
.name = "sw_cluster1",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER2,
|
||||
.name = "sw_cluster2",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER3,
|
||||
.name = "sw_cluster3",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1352,6 +1370,92 @@ static const struct tegra_mc_intmask tegra194_mc_intmasks[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int tegra194_mc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
/* TODO: program PTSA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra194_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
struct icc_provider *p = node->provider;
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
|
||||
|
||||
if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
|
||||
node->id == TEGRA_ICC_MC_CPU_CLUSTER1 ||
|
||||
node->id == TEGRA_ICC_MC_CPU_CLUSTER2 ||
|
||||
node->id == TEGRA_ICC_MC_CPU_CLUSTER3) {
|
||||
if (mc)
|
||||
peak_bw = peak_bw * mc->num_channels;
|
||||
}
|
||||
|
||||
*agg_avg += avg_bw;
|
||||
*agg_peak = max(*agg_peak, peak_bw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra194_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node_data *
|
||||
tegra194_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
|
||||
const struct tegra_mc_client *client;
|
||||
unsigned int i, idx = spec->args[0];
|
||||
struct icc_node_data *ndata;
|
||||
struct icc_node *node;
|
||||
|
||||
list_for_each_entry(node, &mc->provider.nodes, node_list) {
|
||||
if (node->id != idx)
|
||||
continue;
|
||||
|
||||
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
|
||||
if (!ndata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
client = &mc->soc->clients[idx];
|
||||
ndata->node = node;
|
||||
|
||||
switch (client->sid) {
|
||||
case TEGRA194_SID_NVDISPLAY:
|
||||
case TEGRA194_SID_VI:
|
||||
/* these clients are isochronous by default */
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
|
||||
break;
|
||||
|
||||
default:
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ndata;
|
||||
}
|
||||
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == idx)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static const struct tegra_mc_icc_ops tegra194_mc_icc_ops = {
|
||||
.xlate_extended = tegra194_mc_of_icc_xlate_extended,
|
||||
.aggregate = tegra194_mc_icc_aggregate,
|
||||
.get_bw = tegra194_mc_icc_get_init_bw,
|
||||
.set = tegra194_mc_icc_set,
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra194_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra194_mc_clients),
|
||||
.clients = tegra194_mc_clients,
|
||||
@@ -1362,7 +1466,7 @@ const struct tegra_mc_soc tegra194_mc_soc = {
|
||||
.num_intmasks = ARRAY_SIZE(tegra194_mc_intmasks),
|
||||
.has_addr_hi_reg = true,
|
||||
.ops = &tegra186_mc_ops,
|
||||
.icc_ops = &tegra_mc_icc_ops,
|
||||
.icc_ops = &tegra194_mc_icc_ops,
|
||||
.ch_intmask = 0x00000f00,
|
||||
.global_intstatus_channel_shift = 8,
|
||||
.regs = &tegra20_mc_regs,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <soc/tegra/fuse.h>
|
||||
@@ -87,6 +88,13 @@
|
||||
|
||||
#define LPDDR2_MR4_SRR GENMASK(2, 0)
|
||||
|
||||
/*
|
||||
* Tegra210 memory layout can be 1 channel at 64-bit or 2 channels at 32-bit
|
||||
* each. Either way, the total bus width will always be 64-bit.
|
||||
*/
|
||||
#define DRAM_DATA_BUS_WIDTH_BYTES (64 / 8)
|
||||
#define DDR 2
|
||||
|
||||
static const struct tegra210_emc_sequence *tegra210_emc_sequences[] = {
|
||||
&tegra210_emc_r21021,
|
||||
};
|
||||
@@ -1569,6 +1577,79 @@ static int tegra210_emc_set_rate(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra210_emc_rate_requests_init(struct tegra210_emc *emc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
|
||||
emc->requested_rate[i].min_rate = 0;
|
||||
emc->requested_rate[i].max_rate = ULONG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static int emc_request_rate(struct tegra210_emc *emc,
|
||||
unsigned long new_min_rate,
|
||||
unsigned long new_max_rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = emc->requested_rate;
|
||||
unsigned long min_rate = 0, max_rate = ULONG_MAX;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
/* select minimum and maximum rates among the requested rates */
|
||||
for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
|
||||
if (i == type) {
|
||||
min_rate = max(new_min_rate, min_rate);
|
||||
max_rate = min(new_max_rate, max_rate);
|
||||
} else {
|
||||
min_rate = max(req->min_rate, min_rate);
|
||||
max_rate = min(req->max_rate, max_rate);
|
||||
}
|
||||
}
|
||||
|
||||
if (min_rate > max_rate) {
|
||||
dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
|
||||
__func__, type, min_rate, max_rate);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
err = clk_set_rate(emc->clk, min_rate);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
emc->requested_rate[type].min_rate = new_min_rate;
|
||||
emc->requested_rate[type].max_rate = new_max_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emc_set_min_rate(struct tegra210_emc *emc, unsigned long rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = &emc->requested_rate[type];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&emc->rate_lock);
|
||||
ret = emc_request_rate(emc, rate, req->max_rate, type);
|
||||
mutex_unlock(&emc->rate_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int emc_set_max_rate(struct tegra210_emc *emc, unsigned long rate,
|
||||
enum emc_rate_request_type type)
|
||||
{
|
||||
struct emc_rate_request *req = &emc->requested_rate[type];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&emc->rate_lock);
|
||||
ret = emc_request_rate(emc, req->min_rate, rate, type);
|
||||
mutex_unlock(&emc->rate_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* debugfs interface
|
||||
*
|
||||
@@ -1641,7 +1722,7 @@ static int tegra210_emc_debug_min_rate_set(void *data, u64 rate)
|
||||
if (!tegra210_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = clk_set_min_rate(emc->clk, rate);
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -1671,7 +1752,7 @@ static int tegra210_emc_debug_max_rate_set(void *data, u64 rate)
|
||||
if (!tegra210_emc_validate_rate(emc, rate))
|
||||
return -EINVAL;
|
||||
|
||||
err = clk_set_max_rate(emc->clk, rate);
|
||||
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -1758,6 +1839,194 @@ static void tegra210_emc_debugfs_init(struct tegra210_emc *emc)
|
||||
&tegra210_emc_debug_temperature_fops);
|
||||
}
|
||||
|
||||
static inline struct tegra210_emc *
|
||||
to_tegra210_emc_provider(struct icc_provider *provider)
|
||||
{
|
||||
return container_of(provider, struct tegra210_emc, icc_provider);
|
||||
}
|
||||
|
||||
static struct icc_node_data *
|
||||
emc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct icc_provider *provider = data;
|
||||
struct icc_node_data *ndata;
|
||||
struct icc_node *node;
|
||||
|
||||
/* External Memory is the only possible ICC route */
|
||||
list_for_each_entry(node, &provider->nodes, node_list) {
|
||||
if (node->id != TEGRA_ICC_EMEM)
|
||||
continue;
|
||||
|
||||
ndata = kzalloc_obj(*ndata);
|
||||
if (!ndata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/*
|
||||
* SRC and DST nodes should have matching TAG in order to have
|
||||
* it set by default for a requested path.
|
||||
*/
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
|
||||
ndata->node = node;
|
||||
|
||||
return ndata;
|
||||
}
|
||||
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
struct tegra210_emc *emc = to_tegra210_emc_provider(dst->provider);
|
||||
unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
|
||||
unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
|
||||
unsigned long long rate = max(avg_bw, peak_bw);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Tegra210 EMC runs on a clock rate of SDRAM bus. This means that
|
||||
* EMC clock rate is twice smaller than the peak data rate because
|
||||
* data is sampled on both EMC clock edges.
|
||||
*/
|
||||
do_div(rate, DDR * DRAM_DATA_BUS_WIDTH_BYTES);
|
||||
rate = min_t(u64, rate, U32_MAX);
|
||||
|
||||
err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_emc_interconnect_init(struct tegra210_emc *emc)
|
||||
{
|
||||
const struct tegra_mc_soc *soc = emc->mc->soc;
|
||||
struct icc_node *node;
|
||||
int err;
|
||||
|
||||
emc->icc_provider.dev = emc->dev;
|
||||
emc->icc_provider.set = emc_icc_set;
|
||||
emc->icc_provider.data = &emc->icc_provider;
|
||||
emc->icc_provider.aggregate = soc->icc_ops->aggregate;
|
||||
emc->icc_provider.xlate_extended = emc_of_icc_xlate_extended;
|
||||
emc->icc_provider.get_bw = tegra210_emc_icc_get_init_bw;
|
||||
|
||||
icc_provider_init(&emc->icc_provider);
|
||||
|
||||
/* create External Memory Controller node */
|
||||
node = icc_node_create(TEGRA_ICC_EMC);
|
||||
if (IS_ERR(node))
|
||||
return PTR_ERR(node);
|
||||
|
||||
node->name = "External Memory Controller";
|
||||
icc_node_add(node, &emc->icc_provider);
|
||||
|
||||
/* link External Memory Controller to External Memory (DRAM) */
|
||||
err = icc_link_create(node, TEGRA_ICC_EMEM);
|
||||
if (err)
|
||||
goto remove_nodes;
|
||||
|
||||
/* create External Memory node */
|
||||
node = icc_node_create(TEGRA_ICC_EMEM);
|
||||
if (IS_ERR(node)) {
|
||||
err = PTR_ERR(node);
|
||||
goto remove_nodes;
|
||||
}
|
||||
|
||||
node->name = "External Memory (DRAM)";
|
||||
icc_node_add(node, &emc->icc_provider);
|
||||
|
||||
err = icc_provider_register(&emc->icc_provider);
|
||||
if (err)
|
||||
goto remove_nodes;
|
||||
|
||||
return 0;
|
||||
|
||||
remove_nodes:
|
||||
icc_nodes_remove(&emc->icc_provider);
|
||||
|
||||
return dev_err_probe(emc->dev, err, "failed to initialize ICC\n");
|
||||
}
|
||||
|
||||
static int tegra210_emc_opp_table_init(struct tegra210_emc *emc)
|
||||
{
|
||||
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||
struct dev_pm_opp *opp;
|
||||
unsigned long rate;
|
||||
int err, max_opps, i;
|
||||
|
||||
err = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
|
||||
if (err < 0)
|
||||
return dev_err_probe(emc->dev, err, "failed to set OPP supported HW\n");
|
||||
|
||||
emc->hw_opp_token = err;
|
||||
|
||||
err = dev_pm_opp_of_add_table(emc->dev);
|
||||
if (err) {
|
||||
if (err == -ENODEV)
|
||||
dev_err_probe(emc->dev, err,
|
||||
"OPP table not found, please update your device tree\n");
|
||||
else
|
||||
dev_err_probe(emc->dev, err, "failed to add OPP table\n");
|
||||
|
||||
goto put_hw_table;
|
||||
}
|
||||
|
||||
max_opps = dev_pm_opp_get_opp_count(emc->dev);
|
||||
if (max_opps <= 0) {
|
||||
err = max_opps ?: -EINVAL;
|
||||
dev_err_probe(emc->dev, err, "Failed to add OPPs\n");
|
||||
goto remove_table;
|
||||
}
|
||||
|
||||
if (emc->num_timings != max_opps) {
|
||||
err = -EINVAL;
|
||||
dev_err_probe(emc->dev, err, "OPP table does not match emc table\n");
|
||||
goto remove_table;
|
||||
}
|
||||
|
||||
for (i = 0; i < emc->num_timings; i++) {
|
||||
rate = emc->timings[i].rate * 1000;
|
||||
opp = dev_pm_opp_find_freq_exact(emc->dev, rate, true);
|
||||
if (IS_ERR(opp)) {
|
||||
err = PTR_ERR(opp);
|
||||
dev_err_probe(emc->dev, err, "Rate %lu not found in OPP table\n", rate);
|
||||
goto remove_table;
|
||||
}
|
||||
|
||||
dev_pm_opp_put(opp);
|
||||
}
|
||||
|
||||
dev_info_once(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
|
||||
hw_version, clk_get_rate(emc->clk) / 1000000);
|
||||
|
||||
return 0;
|
||||
|
||||
remove_table:
|
||||
dev_pm_opp_of_remove_table(emc->dev);
|
||||
put_hw_table:
|
||||
dev_pm_opp_put_supported_hw(emc->hw_opp_token);
|
||||
emc->hw_opp_token = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void tegra210_emc_opp_table_cleanup(struct tegra210_emc *emc)
|
||||
{
|
||||
if (emc->hw_opp_token) {
|
||||
dev_pm_opp_of_remove_table(emc->dev);
|
||||
dev_pm_opp_put_supported_hw(emc->hw_opp_token);
|
||||
emc->hw_opp_token = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra210_emc_detect(struct tegra210_emc *emc)
|
||||
{
|
||||
u32 value;
|
||||
@@ -1784,6 +2053,226 @@ static void tegra210_emc_detect(struct tegra210_emc *emc)
|
||||
emc->num_channels = 1;
|
||||
}
|
||||
|
||||
static struct device_node *
|
||||
tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
|
||||
{
|
||||
struct device_node *np;
|
||||
int err;
|
||||
|
||||
for_each_child_of_node(node, np) {
|
||||
u32 value;
|
||||
|
||||
err = of_property_read_u32(np, "nvidia,ram-code", &value);
|
||||
if (err || (value != ram_code))
|
||||
continue;
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int load_one_timing_from_dt(struct tegra210_emc *emc,
|
||||
struct tegra210_emc_timing *timing,
|
||||
struct device_node *node)
|
||||
{
|
||||
int err;
|
||||
|
||||
#define EMC_READ_PROP(prop, dtprop) { \
|
||||
err = of_property_read_u32(node, dtprop, &timing->prop); \
|
||||
if (err) { \
|
||||
dev_err(emc->dev, "timing %pOFn: failed to read " #prop ": %d\n", \
|
||||
node, err); \
|
||||
return err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define EMC_READ_PROP_STRING(prop, dtprop) { \
|
||||
err = of_property_read_string(node, dtprop, (const char **)&timing->prop); \
|
||||
if (err) { \
|
||||
dev_err(emc->dev, "timing %pOFn: failed to read " #prop ": %d\n", \
|
||||
node, err); \
|
||||
return err; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define EMC_READ_PROP_ARRAY(prop, dtprop, length) { \
|
||||
err = of_property_read_u32_array(node, dtprop, timing->prop, length); \
|
||||
if (err) { \
|
||||
dev_err(emc->dev, "timing %pOFn: failed to read " #prop ": %d\n", \
|
||||
node, err); \
|
||||
return err; \
|
||||
} \
|
||||
}
|
||||
|
||||
EMC_READ_PROP_STRING(clock_src, "nvidia,source")
|
||||
EMC_READ_PROP_STRING(dvfs_ver, "nvidia,dvfs-version")
|
||||
|
||||
EMC_READ_PROP(revision, "nvidia,revision")
|
||||
EMC_READ_PROP(rate, "clock-frequency")
|
||||
EMC_READ_PROP(min_volt, "nvidia,emc-min-mv")
|
||||
EMC_READ_PROP(gpu_min_volt, "nvidia,gk20a-min-mv")
|
||||
EMC_READ_PROP(clk_src_emc, "nvidia,src-sel-reg")
|
||||
EMC_READ_PROP(num_burst, "nvidia,burst-regs-num")
|
||||
EMC_READ_PROP(emc_cfg_2, "nvidia,emc-cfg-2")
|
||||
EMC_READ_PROP(emc_sel_dpd_ctrl, "nvidia,emc-sel-dpd-ctrl")
|
||||
EMC_READ_PROP(emc_auto_cal_config, "nvidia,emc-auto-cal-config")
|
||||
EMC_READ_PROP(emc_auto_cal_config2, "nvidia,emc-auto-cal-config2")
|
||||
EMC_READ_PROP(emc_auto_cal_config3, "nvidia,emc-auto-cal-config3")
|
||||
EMC_READ_PROP(latency, "nvidia,emc-clock-latency-change")
|
||||
EMC_READ_PROP_ARRAY(burst_regs, "nvidia,emc-registers", timing->num_burst)
|
||||
EMC_READ_PROP(needs_training, "nvidia,needs-training")
|
||||
EMC_READ_PROP(trained, "nvidia,trained")
|
||||
|
||||
if (timing->revision >= 0x6) {
|
||||
EMC_READ_PROP(periodic_training, "nvidia,periodic_training")
|
||||
EMC_READ_PROP(trained_dram_clktree[C0D0U0], "nvidia,trained_dram_clktree_c0d0u0")
|
||||
EMC_READ_PROP(trained_dram_clktree[C0D0U1], "nvidia,trained_dram_clktree_c0d0u1")
|
||||
EMC_READ_PROP(trained_dram_clktree[C0D1U0], "nvidia,trained_dram_clktree_c0d1u0")
|
||||
EMC_READ_PROP(trained_dram_clktree[C0D1U1], "nvidia,trained_dram_clktree_c0d1u1")
|
||||
EMC_READ_PROP(trained_dram_clktree[C1D0U0], "nvidia,trained_dram_clktree_c1d0u0")
|
||||
EMC_READ_PROP(trained_dram_clktree[C1D0U1], "nvidia,trained_dram_clktree_c1d0u1")
|
||||
EMC_READ_PROP(trained_dram_clktree[C1D1U0], "nvidia,trained_dram_clktree_c1d1u0")
|
||||
EMC_READ_PROP(trained_dram_clktree[C1D1U1], "nvidia,trained_dram_clktree_c1d1u1")
|
||||
EMC_READ_PROP(current_dram_clktree[C0D0U0], "nvidia,current_dram_clktree_c0d0u0")
|
||||
EMC_READ_PROP(current_dram_clktree[C0D0U1], "nvidia,current_dram_clktree_c0d0u1")
|
||||
EMC_READ_PROP(current_dram_clktree[C0D1U0], "nvidia,current_dram_clktree_c0d1u0")
|
||||
EMC_READ_PROP(current_dram_clktree[C0D1U1], "nvidia,current_dram_clktree_c0d1u1")
|
||||
EMC_READ_PROP(current_dram_clktree[C1D0U0], "nvidia,current_dram_clktree_c1d0u0")
|
||||
EMC_READ_PROP(current_dram_clktree[C1D0U1], "nvidia,current_dram_clktree_c1d0u1")
|
||||
EMC_READ_PROP(current_dram_clktree[C1D1U0], "nvidia,current_dram_clktree_c1d1u0")
|
||||
EMC_READ_PROP(current_dram_clktree[C1D1U1], "nvidia,current_dram_clktree_c1d1u1")
|
||||
EMC_READ_PROP(run_clocks, "nvidia,run_clocks")
|
||||
EMC_READ_PROP(tree_margin, "nvidia,tree_margin")
|
||||
}
|
||||
|
||||
EMC_READ_PROP(num_burst_per_ch, "nvidia,burst-regs-per-ch-num")
|
||||
EMC_READ_PROP(num_trim, "nvidia,trim-regs-num")
|
||||
EMC_READ_PROP(num_trim_per_ch, "nvidia,trim-regs-per-ch-num")
|
||||
EMC_READ_PROP(num_mc_regs, "nvidia,burst-mc-regs-num")
|
||||
EMC_READ_PROP(num_up_down, "nvidia,la-scale-regs-num")
|
||||
EMC_READ_PROP(vref_num, "nvidia,vref-regs-num")
|
||||
EMC_READ_PROP(dram_timing_num, "nvidia,dram-timing-regs-num")
|
||||
EMC_READ_PROP(min_mrs_wait, "nvidia,min-mrs-wait")
|
||||
EMC_READ_PROP(emc_mrw, "nvidia,emc-mrw")
|
||||
EMC_READ_PROP(emc_mrw2, "nvidia,emc-mrw2")
|
||||
EMC_READ_PROP(emc_mrw3, "nvidia,emc-mrw3")
|
||||
EMC_READ_PROP(emc_mrw4, "nvidia,emc-mrw4")
|
||||
EMC_READ_PROP(emc_mrw9, "nvidia,emc-mrw9")
|
||||
EMC_READ_PROP(emc_mrs, "nvidia,emc-mrs")
|
||||
EMC_READ_PROP(emc_emrs, "nvidia,emc-emrs")
|
||||
EMC_READ_PROP(emc_emrs2, "nvidia,emc-emrs2")
|
||||
EMC_READ_PROP(emc_auto_cal_config4, "nvidia,emc-auto-cal-config4")
|
||||
EMC_READ_PROP(emc_auto_cal_config5, "nvidia,emc-auto-cal-config5")
|
||||
EMC_READ_PROP(emc_auto_cal_config6, "nvidia,emc-auto-cal-config6")
|
||||
EMC_READ_PROP(emc_auto_cal_config7, "nvidia,emc-auto-cal-config7")
|
||||
EMC_READ_PROP(emc_auto_cal_config8, "nvidia,emc-auto-cal-config8")
|
||||
EMC_READ_PROP(emc_fdpd_ctrl_cmd_no_ramp, "nvidia,emc-fdpd-ctrl-cmd-no-ramp")
|
||||
EMC_READ_PROP(dll_clk_src, "nvidia,dll-clk-src")
|
||||
EMC_READ_PROP(clk_out_enb_x_0_clk_enb_emc_dll, "nvidia,clk-out-enb-x-0-clk-enb-emc-dll")
|
||||
|
||||
if (timing->revision >= 0x7)
|
||||
EMC_READ_PROP_ARRAY(ptfv_list, "nvidia,ptfv", ARRAY_SIZE(timing->ptfv_list))
|
||||
|
||||
EMC_READ_PROP_ARRAY(burst_reg_per_ch, "nvidia,emc-burst-regs-per-ch",
|
||||
timing->num_burst_per_ch)
|
||||
EMC_READ_PROP_ARRAY(shadow_regs_ca_train, "nvidia,emc-shadow-regs-ca-train",
|
||||
timing->num_burst)
|
||||
EMC_READ_PROP_ARRAY(shadow_regs_quse_train, "nvidia,emc-shadow-regs-quse-train",
|
||||
timing->num_burst)
|
||||
EMC_READ_PROP_ARRAY(shadow_regs_rdwr_train, "nvidia,emc-shadow-regs-rdwr-train",
|
||||
timing->num_burst)
|
||||
EMC_READ_PROP_ARRAY(trim_regs, "nvidia,emc-trim-regs", timing->num_trim)
|
||||
EMC_READ_PROP_ARRAY(trim_perch_regs, "nvidia,emc-trim-regs-per-ch", timing->num_trim_per_ch)
|
||||
EMC_READ_PROP_ARRAY(vref_perch_regs, "nvidia,emc-vref-regs", timing->vref_num)
|
||||
EMC_READ_PROP_ARRAY(dram_timings, "nvidia,emc-dram-timing-regs", timing->dram_timing_num)
|
||||
EMC_READ_PROP_ARRAY(burst_mc_regs, "nvidia,emc-burst-mc-regs", timing->num_mc_regs)
|
||||
EMC_READ_PROP_ARRAY(la_scale_regs, "nvidia,emc-la-scale-regs", timing->num_up_down)
|
||||
|
||||
#undef EMC_READ_PROP
|
||||
#undef EMC_READ_STRING
|
||||
#undef EMC_READ_PROP_ARRAY
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NOMINAL_COMPATIBLE "nvidia,tegra21-emc-table"
|
||||
#define DERATED_COMPATIBLE "nvidia,tegra21-emc-table-derated"
|
||||
static int tegra210_emc_load_timings_from_dt(struct tegra210_emc *emc,
|
||||
struct device_node *node)
|
||||
{
|
||||
struct tegra210_emc_timing *timing;
|
||||
unsigned int num_nominal = 0, num_derated = 0;
|
||||
int err;
|
||||
|
||||
emc->num_timings = 0;
|
||||
for_each_child_of_node_scoped(node, child) {
|
||||
if (of_device_is_compatible(child, NOMINAL_COMPATIBLE))
|
||||
emc->num_timings++;
|
||||
else if (of_device_is_compatible(child, DERATED_COMPATIBLE))
|
||||
num_derated++;
|
||||
}
|
||||
|
||||
if (!emc->num_timings || (num_derated && (emc->num_timings != num_derated)))
|
||||
return -EINVAL;
|
||||
|
||||
emc->nominal = devm_kcalloc(emc->dev, emc->num_timings, sizeof(*timing),
|
||||
GFP_KERNEL);
|
||||
if (!emc->nominal)
|
||||
return -ENOMEM;
|
||||
|
||||
if (num_derated) {
|
||||
num_derated = 0;
|
||||
emc->derated = devm_kcalloc(emc->dev, emc->num_timings, sizeof(*timing),
|
||||
GFP_KERNEL);
|
||||
if (!emc->derated)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for_each_child_of_node_scoped(node, child) {
|
||||
if (of_device_is_compatible(child, NOMINAL_COMPATIBLE))
|
||||
timing = &emc->nominal[num_nominal++];
|
||||
else if (of_device_is_compatible(child, DERATED_COMPATIBLE))
|
||||
timing = &emc->derated[num_derated++];
|
||||
else
|
||||
continue;
|
||||
|
||||
err = load_one_timing_from_dt(emc, timing, child);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_emc_parse_dt(struct tegra210_emc *emc)
|
||||
{
|
||||
struct device_node *node, *np = emc->dev->of_node;
|
||||
int ram_code, ret = 0;
|
||||
|
||||
if (!np) {
|
||||
dev_err(emc->dev, "Unable to find emc node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_find_property(np, "nvidia,use-ram-code", NULL)) {
|
||||
ram_code = tegra_read_ram_code();
|
||||
node = tegra_emc_find_node_by_ram_code(np, ram_code);
|
||||
|
||||
if (!node) {
|
||||
dev_warn(emc->dev, "can't find emc table for ram-code\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = tegra210_emc_load_timings_from_dt(emc, node);
|
||||
of_node_put(node);
|
||||
} else {
|
||||
ret = tegra210_emc_load_timings_from_dt(emc, np);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tegra210_emc_validate_timings(struct tegra210_emc *emc,
|
||||
struct tegra210_emc_timing *timings,
|
||||
unsigned int num_timings)
|
||||
@@ -1816,6 +2305,7 @@ static int tegra210_emc_probe(struct platform_device *pdev)
|
||||
struct device_node *np;
|
||||
unsigned int i;
|
||||
int err;
|
||||
bool have_dt_tables = false;
|
||||
|
||||
emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
|
||||
if (!emc)
|
||||
@@ -1848,16 +2338,20 @@ static int tegra210_emc_probe(struct platform_device *pdev)
|
||||
np = pdev->dev.of_node;
|
||||
|
||||
/* attach to the nominal and (optional) derated tables */
|
||||
err = of_reserved_mem_device_init_by_name(emc->dev, np, "nominal");
|
||||
if (err < 0) {
|
||||
dev_err(emc->dev, "failed to get nominal EMC table: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (of_reserved_mem_device_init_by_name(emc->dev, np, "nominal") >= 0) {
|
||||
err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
|
||||
if (err < 0 && err != -ENODEV) {
|
||||
dev_err(emc->dev, "failed to get derated EMC table: %d\n", err);
|
||||
goto release;
|
||||
}
|
||||
} else {
|
||||
err = tegra210_emc_parse_dt(emc);
|
||||
if (err < 0) {
|
||||
dev_err(emc->dev, "failed to get EMC tables: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
|
||||
if (err < 0 && err != -ENODEV) {
|
||||
dev_err(emc->dev, "failed to get derated EMC table: %d\n", err);
|
||||
goto release;
|
||||
have_dt_tables = true;
|
||||
}
|
||||
|
||||
/* validate the tables */
|
||||
@@ -1966,22 +2460,33 @@ static int tegra210_emc_probe(struct platform_device *pdev)
|
||||
|
||||
tegra210_emc_debugfs_init(emc);
|
||||
|
||||
err = tegra210_emc_opp_table_init(emc);
|
||||
if (!err) {
|
||||
tegra210_emc_rate_requests_init(emc);
|
||||
tegra210_emc_interconnect_init(emc);
|
||||
} else if (err != -ENODEV) {
|
||||
goto detach;
|
||||
}
|
||||
|
||||
cd = devm_thermal_of_child_cooling_device_register(emc->dev, np, "emc", emc,
|
||||
&tegra210_emc_cd_ops);
|
||||
if (IS_ERR(cd)) {
|
||||
err = PTR_ERR(cd);
|
||||
dev_err(emc->dev, "failed to register cooling device: %d\n",
|
||||
err);
|
||||
goto detach;
|
||||
goto cleanup_table;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_table:
|
||||
tegra210_emc_opp_table_cleanup(emc);
|
||||
detach:
|
||||
debugfs_remove_recursive(emc->debugfs.root);
|
||||
tegra210_clk_emc_detach(emc->clk);
|
||||
release:
|
||||
of_reserved_mem_device_release(emc->dev);
|
||||
if (!have_dt_tables)
|
||||
of_reserved_mem_device_release(emc->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1990,6 +2495,7 @@ static void tegra210_emc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra210_emc *emc = platform_get_drvdata(pdev);
|
||||
|
||||
tegra210_emc_opp_table_cleanup(emc);
|
||||
debugfs_remove_recursive(emc->debugfs.root);
|
||||
tegra210_clk_emc_detach(emc->clk);
|
||||
of_reserved_mem_device_release(emc->dev);
|
||||
@@ -2050,6 +2556,7 @@ static struct platform_driver tegra210_emc_driver = {
|
||||
.name = "tegra210-emc",
|
||||
.of_match_table = tegra210_emc_of_match,
|
||||
.pm = &tegra210_emc_pm_ops,
|
||||
.sync_state = icc_sync_state,
|
||||
},
|
||||
.probe = tegra210_emc_probe,
|
||||
.remove = tegra210_emc_remove,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
@@ -784,6 +785,17 @@ enum {
|
||||
#define TRIM_REGS_SIZE 138
|
||||
#define BURST_REGS_SIZE 221
|
||||
|
||||
enum emc_rate_request_type {
|
||||
EMC_RATE_DEBUG,
|
||||
EMC_RATE_ICC,
|
||||
EMC_RATE_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct emc_rate_request {
|
||||
unsigned long min_rate;
|
||||
unsigned long max_rate;
|
||||
};
|
||||
|
||||
struct tegra210_emc_per_channel_regs {
|
||||
u16 bank;
|
||||
u16 offset;
|
||||
@@ -932,6 +944,18 @@ struct tegra210_emc {
|
||||
} debugfs;
|
||||
|
||||
struct tegra210_clk_emc_provider provider;
|
||||
|
||||
struct icc_provider icc_provider;
|
||||
int hw_opp_token;
|
||||
|
||||
/*
|
||||
* There are multiple sources in the EMC driver which could request
|
||||
* a min/max clock rate, these rates are contained in this array.
|
||||
*/
|
||||
struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
|
||||
|
||||
/* protect shared rate-change code path */
|
||||
struct mutex rate_lock;
|
||||
};
|
||||
|
||||
struct tegra210_emc_sequence {
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
* Copyright (C) 2015-2026 NVIDIA CORPORATION. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <dt-bindings/memory/tegra210-mc.h>
|
||||
|
||||
#include "mc.h"
|
||||
@@ -1282,6 +1285,83 @@ static const struct tegra_mc_intmask tegra210_mc_intmasks[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int tegra210_mc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
/* TODO: program PTSA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
/*
|
||||
* ISO clients need to reserve extra bandwidth up-front because
|
||||
* there could be high bandwidth pressure during initial filling
|
||||
* of the client's FIFO buffers. Secondly, we need to take into
|
||||
* account impurities of the memory subsystem.
|
||||
*/
|
||||
if (tag & TEGRA_MC_ICC_TAG_ISO)
|
||||
peak_bw = tegra_mc_scale_percents(peak_bw, 400);
|
||||
|
||||
*agg_avg += avg_bw;
|
||||
*agg_peak = max(*agg_peak, peak_bw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node_data *
|
||||
tegra210_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
|
||||
const struct tegra_mc_client *client;
|
||||
unsigned int i, idx = spec->args[0];
|
||||
struct icc_node_data *ndata;
|
||||
struct icc_node *node;
|
||||
|
||||
list_for_each_entry(node, &mc->provider.nodes, node_list) {
|
||||
if (node->id != idx)
|
||||
continue;
|
||||
|
||||
ndata = kzalloc_obj(*ndata);
|
||||
if (!ndata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
client = &mc->soc->clients[idx];
|
||||
ndata->node = node;
|
||||
|
||||
switch (client->swgroup) {
|
||||
case TEGRA_SWGROUP_DC:
|
||||
case TEGRA_SWGROUP_DCB:
|
||||
case TEGRA_SWGROUP_PTC:
|
||||
case TEGRA_SWGROUP_VI:
|
||||
/* these clients are isochronous by default */
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
|
||||
break;
|
||||
|
||||
default:
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ndata;
|
||||
}
|
||||
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == idx)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static const struct tegra_mc_icc_ops tegra210_mc_icc_ops = {
|
||||
.xlate_extended = tegra210_mc_of_icc_xlate_extended,
|
||||
.aggregate = tegra210_mc_icc_aggregate,
|
||||
.set = tegra210_mc_icc_set,
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra210_mc_soc = {
|
||||
.clients = tegra210_mc_clients,
|
||||
.num_clients = ARRAY_SIZE(tegra210_mc_clients),
|
||||
@@ -1294,6 +1374,7 @@ const struct tegra_mc_soc tegra210_mc_soc = {
|
||||
.reset_ops = &tegra_mc_reset_ops_common,
|
||||
.resets = tegra210_mc_resets,
|
||||
.num_resets = ARRAY_SIZE(tegra210_mc_resets),
|
||||
.icc_ops = &tegra210_mc_icc_ops,
|
||||
.ops = &tegra30_mc_ops,
|
||||
.regs = &tegra20_mc_regs,
|
||||
.handle_irq = tegra30_mc_irq_handlers,
|
||||
|
||||
@@ -1506,6 +1506,19 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
|
||||
.max_tap_delay = 185,
|
||||
};
|
||||
|
||||
static const struct sdhci_tegra_soc_data soc_data_tegra210b01 = {
|
||||
.pdata = &sdhci_tegra210_pdata,
|
||||
.dma_mask = DMA_BIT_MASK(34),
|
||||
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
|
||||
NVQUIRK_HAS_PADCALIB |
|
||||
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
|
||||
NVQUIRK_ENABLE_SDR50 |
|
||||
NVQUIRK_ENABLE_SDR104 |
|
||||
NVQUIRK_HAS_TMCLK,
|
||||
.min_tap_delay = 91,
|
||||
.max_tap_delay = 149,
|
||||
};
|
||||
|
||||
static const struct sdhci_ops tegra186_sdhci_ops = {
|
||||
.get_ro = tegra_sdhci_get_ro,
|
||||
.read_w = tegra_sdhci_readw,
|
||||
@@ -1577,6 +1590,7 @@ static const struct of_device_id sdhci_tegra_dt_match[] = {
|
||||
{ .compatible = "nvidia,tegra194-sdhci", .data = &soc_data_tegra194 },
|
||||
{ .compatible = "nvidia,tegra186-sdhci", .data = &soc_data_tegra186 },
|
||||
{ .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 },
|
||||
{ .compatible = "nvidia,tegra210b01-sdhci", .data = &soc_data_tegra210b01 },
|
||||
{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 },
|
||||
{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
|
||||
{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
|
||||
|
||||
+46
-24
@@ -1089,10 +1089,33 @@ int __init early_init_dt_scan_memory(void)
|
||||
return found_memory;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert configs to something easy to use in C code
|
||||
*/
|
||||
#if defined(CONFIG_CMDLINE_FORCE)
|
||||
static const int overwrite_incoming_cmdline = 1;
|
||||
static const int read_dt_cmdline;
|
||||
static const int concat_cmdline;
|
||||
#elif defined(CONFIG_CMDLINE_EXTEND)
|
||||
static const int overwrite_incoming_cmdline;
|
||||
static const int read_dt_cmdline = 1;
|
||||
static const int concat_cmdline = 1;
|
||||
#else /* CMDLINE_FROM_BOOTLOADER */
|
||||
static const int overwrite_incoming_cmdline;
|
||||
static const int read_dt_cmdline = 1;
|
||||
static const int concat_cmdline;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CMDLINE
|
||||
static const char *config_cmdline = CONFIG_CMDLINE;
|
||||
#else
|
||||
static const char *config_cmdline = "";
|
||||
#endif
|
||||
|
||||
int __init early_init_dt_scan_chosen(char *cmdline)
|
||||
{
|
||||
int l, node;
|
||||
const char *p;
|
||||
int l = 0, node;
|
||||
const char *p = NULL;
|
||||
const void *rng_seed;
|
||||
const void *fdt = initial_boot_params;
|
||||
|
||||
@@ -1121,30 +1144,29 @@ int __init early_init_dt_scan_chosen(char *cmdline)
|
||||
fdt_totalsize(initial_boot_params));
|
||||
}
|
||||
|
||||
/* Retrieve command line */
|
||||
p = of_get_flat_dt_prop(node, "bootargs", &l);
|
||||
if (p != NULL && l > 0)
|
||||
strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE));
|
||||
/* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */
|
||||
if (overwrite_incoming_cmdline || !cmdline[0])
|
||||
strscpy(cmdline, config_cmdline, COMMAND_LINE_SIZE);
|
||||
|
||||
/* Retrieve command line unless forcing */
|
||||
if (read_dt_cmdline)
|
||||
p = of_get_flat_dt_prop(node, "bootargs", &l);
|
||||
if (p != NULL && l > 0) {
|
||||
if (concat_cmdline) {
|
||||
int cmdline_len;
|
||||
int copy_len;
|
||||
strlcat(cmdline, " ", COMMAND_LINE_SIZE);
|
||||
cmdline_len = strlen(cmdline);
|
||||
copy_len = COMMAND_LINE_SIZE - cmdline_len - 1;
|
||||
copy_len = min((int)l, copy_len);
|
||||
strncpy(cmdline + cmdline_len, p, copy_len);
|
||||
cmdline[cmdline_len + copy_len] = '\0';
|
||||
} else {
|
||||
strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
handle_cmdline:
|
||||
/*
|
||||
* CONFIG_CMDLINE is meant to be a default in case nothing else
|
||||
* managed to set the command line, unless CONFIG_CMDLINE_FORCE
|
||||
* is set in which case we override whatever was found earlier.
|
||||
*/
|
||||
#ifdef CONFIG_CMDLINE
|
||||
#if defined(CONFIG_CMDLINE_EXTEND)
|
||||
strlcat(cmdline, " ", COMMAND_LINE_SIZE);
|
||||
strlcat(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
#elif defined(CONFIG_CMDLINE_FORCE)
|
||||
strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
#else
|
||||
/* No arguments from boot loader, use kernel's cmdl*/
|
||||
if (!((char *)cmdline)[0])
|
||||
strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||
#endif
|
||||
#endif /* CONFIG_CMDLINE */
|
||||
|
||||
pr_debug("Command line is: %s\n", (char *)cmdline);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Author: Mike Rapoport <mike@compulab.co.il>
|
||||
*
|
||||
* Based on NVIDIA PCIe driver
|
||||
* Copyright (c) 2008-2009, NVIDIA Corporation.
|
||||
* Copyright (c) 2008-2020, NVIDIA Corporation.
|
||||
*
|
||||
* Bits taken from arch/arm/mach-dove/pcie.c
|
||||
*
|
||||
@@ -165,10 +165,64 @@
|
||||
|
||||
#define AFI_PLLE_CONTROL 0x160
|
||||
#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
|
||||
#define AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL (1 << 8)
|
||||
#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
|
||||
#define AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN (1 << 0)
|
||||
|
||||
#define AFI_PEXBIAS_CTRL_0 0x168
|
||||
|
||||
|
||||
#define RP_PRIV_XP_DL 0x00000494
|
||||
#define RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD (0x1ff << 1)
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_CTL 0xc00
|
||||
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2 (0x1 << 0)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1 (0x1 << 1)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2 (0x1 << 2)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1 (0x1 << 3)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK (0xff << 8)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT 8
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK (0x3 << 16)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT 16
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK (0x1f << 19)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT 19
|
||||
#define RP_L1_PM_SUBSTATES_CTL_HIDE_CAP (0x1 << 24)
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_1_CTL 0xc04
|
||||
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK 0x1fff
|
||||
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY 0x26
|
||||
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK (0x1ff << 13)
|
||||
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY (0x27 << 13)
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL 0xc08
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK 0x1fff
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY 0x4d
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK (0xff << 13)
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND (0x13 << 13)
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK (0xf << 21)
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP (0x2 << 21)
|
||||
|
||||
#define RP_RX_HDR_LIMIT 0x00000e00
|
||||
#define RP_RX_HDR_LIMIT_PW_MASK (0xff << 8)
|
||||
#define RP_RX_HDR_LIMIT_PW (0x0e << 8)
|
||||
|
||||
#define RP_TIMEOUT0 0xe24
|
||||
#define RP_TIMEOUT0_PAD_PWRUP_MASK 0xff
|
||||
#define RP_TIMEOUT0_PAD_PWRUP 0xa
|
||||
#define RP_TIMEOUT0_PAD_PWRUP_CM_MASK 0xffff00
|
||||
#define RP_TIMEOUT0_PAD_PWRUP_CM (0x180 << 8)
|
||||
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK (0xff << 24)
|
||||
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2 (0xa << 24)
|
||||
|
||||
#define RP_TIMEOUT1 0xe28
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK (0xff << 16)
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE (0x10 << 16)
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK (0xff << 24)
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE (0x74 << 24)
|
||||
|
||||
#define RP_ECTL_1_R1 0x00000e80
|
||||
#define RP_ECTL_1_R1_TX_DRV_AMP_1C_MASK 0x3f
|
||||
|
||||
#define RP_ECTL_2_R1 0x00000e84
|
||||
#define RP_ECTL_2_R1_RX_CTLE_1C_MASK 0xffff
|
||||
|
||||
@@ -182,6 +236,9 @@
|
||||
#define RP_ECTL_6_R1 0x00000e94
|
||||
#define RP_ECTL_6_R1_RX_EQ_CTRL_H_1C_MASK 0xffffffff
|
||||
|
||||
#define RP_ECTL_1_R2 0x00000ea0
|
||||
#define RP_ECTL_1_R2_TX_DRV_AMP_1C_MASK 0x3f
|
||||
|
||||
#define RP_ECTL_2_R2 0x00000ea4
|
||||
#define RP_ECTL_2_R2_RX_CTLE_1C_MASK 0xffff
|
||||
|
||||
@@ -201,6 +258,19 @@
|
||||
#define RP_VEND_XP_OPPORTUNISTIC_UPDATEFC (1 << 28)
|
||||
#define RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK (0xff << 18)
|
||||
|
||||
#define RP_VEND_XP1 0xf04
|
||||
#define RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S (1 << 23)
|
||||
#define RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT (1 << 21)
|
||||
|
||||
|
||||
#define RP_XP_REF 0xf30
|
||||
#define RP_XP_REF_MICROSECOND_LIMIT_MASK 0xff
|
||||
#define RP_XP_REF_MICROSECOND_LIMIT 0x14
|
||||
#define RP_XP_REF_MICROSECOND_ENABLE (1 << 8)
|
||||
#define RP_XP_REF_CPL_TO_OVERRIDE (1 << 13)
|
||||
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK (0x1ffff << 14)
|
||||
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE (0x1770 << 14)
|
||||
|
||||
#define RP_VEND_CTL0 0x00000f44
|
||||
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH_MASK (0xf << 12)
|
||||
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH (0x9 << 12)
|
||||
@@ -224,12 +294,23 @@
|
||||
#define RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD (0xf << 24)
|
||||
#define RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE (1 << 31)
|
||||
|
||||
#define RP_VEND_XP_PAD_PWRDN 0x00000f50
|
||||
#define RP_VEND_XP_PAD_PWRDN_L1_EN (1 << 0)
|
||||
#define RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN (1 << 1)
|
||||
#define RP_VEND_XP_PAD_PWRDN_DISABLED_EN (1 << 2)
|
||||
#define RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN (1 << 15)
|
||||
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP (3 << 5)
|
||||
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP (3 << 3)
|
||||
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP (3 << 16)
|
||||
|
||||
#define RP_LINK_CONTROL_STATUS 0x00000090
|
||||
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
|
||||
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
|
||||
|
||||
#define RP_LINK_CONTROL_STATUS_2 0x000000b0
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_CAP 0x144
|
||||
|
||||
#define PADS_CTL_SEL 0x0000009c
|
||||
|
||||
#define PADS_CTL 0x000000a0
|
||||
@@ -306,12 +387,18 @@ struct tegra_pcie_soc {
|
||||
bool program_deskew_time;
|
||||
bool update_fc_timer;
|
||||
bool has_cache_bars;
|
||||
bool enable_wrap;
|
||||
bool has_aspm_l1;
|
||||
bool has_aspm_l1ss;
|
||||
bool l1ss_rp_wake_fixup;
|
||||
struct {
|
||||
struct {
|
||||
u32 rp_ectl_1_r1;
|
||||
u32 rp_ectl_2_r1;
|
||||
u32 rp_ectl_4_r1;
|
||||
u32 rp_ectl_5_r1;
|
||||
u32 rp_ectl_6_r1;
|
||||
u32 rp_ectl_1_r2;
|
||||
u32 rp_ectl_2_r2;
|
||||
u32 rp_ectl_4_r2;
|
||||
u32 rp_ectl_5_r2;
|
||||
@@ -368,6 +455,8 @@ struct tegra_pcie_port {
|
||||
void __iomem *base;
|
||||
unsigned int index;
|
||||
unsigned int lanes;
|
||||
unsigned int aspm_state;
|
||||
bool supports_clkreq;
|
||||
|
||||
struct phy **phys;
|
||||
|
||||
@@ -396,6 +485,14 @@ static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset)
|
||||
return readl(pcie->pads + offset);
|
||||
}
|
||||
|
||||
static bool tegra_pcie_link_up(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = readl(port->base + RP_LINK_CONTROL_STATUS);
|
||||
return !!(value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The configuration space mapping on Tegra is somewhat similar to the ECAM
|
||||
* defined by PCIe. However it deviates a bit in how the 4 bits for extended
|
||||
@@ -461,20 +558,50 @@ static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus,
|
||||
static int tegra_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 *value)
|
||||
{
|
||||
struct tegra_pcie *pcie = bus->sysdata;
|
||||
struct pci_dev *bridge;
|
||||
struct tegra_pcie_port *port;
|
||||
|
||||
if (bus->number == 0)
|
||||
return pci_generic_config_read32(bus, devfn, where, size,
|
||||
value);
|
||||
|
||||
bridge = pcie_find_root_port(bus->self);
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list)
|
||||
if (port->index + 1 == PCI_SLOT(bridge->devfn))
|
||||
break;
|
||||
|
||||
/* If there is no link, then there is no device */
|
||||
if (!tegra_pcie_link_up(port)) {
|
||||
*value = 0xffffffff;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return pci_generic_config_read(bus, devfn, where, size, value);
|
||||
}
|
||||
|
||||
static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 value)
|
||||
{
|
||||
struct tegra_pcie *pcie = bus->sysdata;
|
||||
struct tegra_pcie_port *port;
|
||||
struct pci_dev *bridge;
|
||||
|
||||
if (bus->number == 0)
|
||||
return pci_generic_config_write32(bus, devfn, where, size,
|
||||
value);
|
||||
|
||||
bridge = pcie_find_root_port(bus->self);
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list)
|
||||
if (port->index + 1 == PCI_SLOT(bridge->devfn))
|
||||
break;
|
||||
|
||||
/* If there is no link, then there is no device */
|
||||
if (!tegra_pcie_link_up(port))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
return pci_generic_config_write(bus, devfn, where, size, value);
|
||||
}
|
||||
|
||||
@@ -531,6 +658,44 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
|
||||
}
|
||||
}
|
||||
|
||||
static void disable_aspm_l0s(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_VEND_XP1);
|
||||
val |= RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S;
|
||||
writel(val, port->base + RP_VEND_XP1);
|
||||
}
|
||||
|
||||
static void disable_aspm_l10(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_VEND_XP1);
|
||||
val &= ~RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
|
||||
writel(val, port->base + RP_VEND_XP1);
|
||||
}
|
||||
|
||||
static void disable_aspm_l11(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1;
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1;
|
||||
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
}
|
||||
|
||||
static void disable_aspm_l12(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2;
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2;
|
||||
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
}
|
||||
|
||||
static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
|
||||
{
|
||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||
@@ -567,6 +732,47 @@ static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
|
||||
}
|
||||
|
||||
writel(value, port->base + RP_PRIV_MISC);
|
||||
|
||||
if (soc->has_aspm_l1) {
|
||||
/* Advertise ASPM-L1 state capability*/
|
||||
value = readl(port->base + RP_VEND_XP1);
|
||||
value |= RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
|
||||
writel(value, port->base + RP_VEND_XP1);
|
||||
|
||||
/* Power saving configuration for L1 sleep/idle */
|
||||
value = readl(port->base + RP_VEND_XP_PAD_PWRDN);
|
||||
value |= RP_VEND_XP_PAD_PWRDN_DISABLED_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_L1_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP;
|
||||
writel(value, port->base + RP_VEND_XP_PAD_PWRDN);
|
||||
|
||||
if (port->aspm_state & 0x1)
|
||||
disable_aspm_l0s(port);
|
||||
if (port->aspm_state & 0x2)
|
||||
disable_aspm_l10(port);
|
||||
}
|
||||
|
||||
if (soc->has_aspm_l1ss) {
|
||||
if (port->aspm_state & 0x2) {
|
||||
disable_aspm_l11(port);
|
||||
disable_aspm_l12(port);
|
||||
}
|
||||
if (port->aspm_state & 0x4)
|
||||
disable_aspm_l11(port);
|
||||
if (port->aspm_state & 0x8)
|
||||
disable_aspm_l12(port);
|
||||
|
||||
/* Disable L1SS capability if CLKREQ# is not present */
|
||||
if (!port->supports_clkreq) {
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
value |= RP_L1_PM_SUBSTATES_CTL_HIDE_CAP;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
||||
@@ -574,6 +780,11 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||
u32 value;
|
||||
|
||||
value = readl(port->base + RP_ECTL_1_R1);
|
||||
value &= ~RP_ECTL_1_R1_TX_DRV_AMP_1C_MASK;
|
||||
value |= soc->ectl.regs.rp_ectl_1_r1;
|
||||
writel(value, port->base + RP_ECTL_1_R1);
|
||||
|
||||
value = readl(port->base + RP_ECTL_2_R1);
|
||||
value &= ~RP_ECTL_2_R1_RX_CTLE_1C_MASK;
|
||||
value |= soc->ectl.regs.rp_ectl_2_r1;
|
||||
@@ -595,6 +806,11 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
||||
value |= soc->ectl.regs.rp_ectl_6_r1;
|
||||
writel(value, port->base + RP_ECTL_6_R1);
|
||||
|
||||
value = readl(port->base + RP_ECTL_1_R2);
|
||||
value &= ~RP_ECTL_1_R2_TX_DRV_AMP_1C_MASK;
|
||||
value |= soc->ectl.regs.rp_ectl_1_r2;
|
||||
writel(value, port->base + RP_ECTL_1_R2);
|
||||
|
||||
value = readl(port->base + RP_ECTL_2_R2);
|
||||
value &= ~RP_ECTL_2_R2_RX_CTLE_1C_MASK;
|
||||
value |= soc->ectl.regs.rp_ectl_2_r2;
|
||||
@@ -617,6 +833,26 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
||||
writel(value, port->base + RP_ECTL_6_R2);
|
||||
}
|
||||
|
||||
static void tegra_pcie_enable_wrap(void)
|
||||
{
|
||||
u32 val;
|
||||
void __iomem *msel_base;
|
||||
|
||||
#define MSELECT_CONFIG_BASE 0x50060000
|
||||
#define MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1 BIT(28)
|
||||
#define MSELECT_CONFIG_ERR_RESP_EN_SLAVE1 BIT(24)
|
||||
|
||||
/* Config MSELECT to support wrap trans for normal NC & GRE mapping */
|
||||
msel_base = ioremap(MSELECT_CONFIG_BASE, 4);
|
||||
val = readl(msel_base);
|
||||
/* Enable WRAP_TO_INCR_SLAVE1 */
|
||||
val |= MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1;
|
||||
/* Disable ERR_RESP_EN_SLAVE1 */
|
||||
val &= ~MSELECT_CONFIG_ERR_RESP_EN_SLAVE1;
|
||||
writel(val, msel_base);
|
||||
iounmap(msel_base);
|
||||
}
|
||||
|
||||
static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
|
||||
{
|
||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||
@@ -651,6 +887,76 @@ static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
|
||||
value &= ~PCI_EXP_LNKSTA_CLS;
|
||||
value |= PCI_EXP_LNKSTA_CLS_2_5GB;
|
||||
writel(value, port->base + RP_LINK_CONTROL_STATUS_2);
|
||||
|
||||
if (soc->enable_wrap)
|
||||
tegra_pcie_enable_wrap();
|
||||
|
||||
if (soc->has_aspm_l1ss) {
|
||||
/* Set port Common_Mode_Restore_Time to 30us */
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
value &= ~RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK;
|
||||
value |= (0x1E << RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT);
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
|
||||
/* set port T_POWER_ON to 70us */
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
value &= ~(RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK |
|
||||
RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK);
|
||||
value |= (1 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT) |
|
||||
(7 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT);
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
|
||||
/* Following is based on clk_m being 19.2 MHz */
|
||||
value = readl(port->base + RP_TIMEOUT0);
|
||||
value &= ~RP_TIMEOUT0_PAD_PWRUP_MASK;
|
||||
value |= RP_TIMEOUT0_PAD_PWRUP;
|
||||
value &= ~RP_TIMEOUT0_PAD_PWRUP_CM_MASK;
|
||||
value |= RP_TIMEOUT0_PAD_PWRUP_CM;
|
||||
value &= ~RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK;
|
||||
value |= RP_TIMEOUT0_PAD_SPDCHNG_GEN2;
|
||||
writel(value, port->base + RP_TIMEOUT0);
|
||||
|
||||
value = readl(port->base + RP_TIMEOUT1);
|
||||
value &= ~RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK;
|
||||
value |= RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE;
|
||||
value &= ~RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK;
|
||||
value |= RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE;
|
||||
writel(value, port->base + RP_TIMEOUT1);
|
||||
|
||||
value = readl(port->base + RP_XP_REF);
|
||||
value &= ~RP_XP_REF_MICROSECOND_LIMIT_MASK;
|
||||
value |= RP_XP_REF_MICROSECOND_LIMIT;
|
||||
value |= RP_XP_REF_MICROSECOND_ENABLE;
|
||||
value |= RP_XP_REF_CPL_TO_OVERRIDE;
|
||||
value &= ~RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK;
|
||||
value |= RP_XP_REF_CPL_TO_CUSTOM_VALUE;
|
||||
writel(value, port->base + RP_XP_REF);
|
||||
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
value &= ~RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_2_CTL);
|
||||
value &= ~RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY;
|
||||
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND;
|
||||
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_2_CTL);
|
||||
}
|
||||
|
||||
if (soc->l1ss_rp_wake_fixup) {
|
||||
/*
|
||||
* Set CLKREQ asserted delay greater than Power_Off
|
||||
* time (2us) to avoid RP wakeup in L1.2.ENTRY
|
||||
*/
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
value &= ~RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK;
|
||||
value |= RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
|
||||
@@ -663,8 +969,12 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
|
||||
value = afi_readl(port->pcie, ctrl);
|
||||
value |= AFI_PEX_CTRL_REFCLK_EN;
|
||||
|
||||
if (soc->has_pex_clkreq_en)
|
||||
value |= AFI_PEX_CTRL_CLKREQ_EN;
|
||||
if (soc->has_pex_clkreq_en) {
|
||||
if (port->supports_clkreq)
|
||||
value &= ~AFI_PEX_CTRL_CLKREQ_EN;
|
||||
else
|
||||
value |= AFI_PEX_CTRL_CLKREQ_EN;
|
||||
}
|
||||
|
||||
value |= AFI_PEX_CTRL_OVERRIDE_EN;
|
||||
|
||||
@@ -1094,10 +1404,20 @@ static void tegra_pcie_enable_controller(struct tegra_pcie *pcie)
|
||||
unsigned long value;
|
||||
|
||||
/* enable PLL power down */
|
||||
if (pcie->phy) {
|
||||
if (soc->has_aspm_l1ss) {
|
||||
value = afi_readl(pcie, AFI_PLLE_CONTROL);
|
||||
value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
||||
value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list) {
|
||||
if (!port->supports_clkreq) {
|
||||
value &= ~AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
value &= ~AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL;
|
||||
value |= AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN;
|
||||
afi_writel(pcie, value, AFI_PLLE_CONTROL);
|
||||
}
|
||||
|
||||
@@ -1529,6 +1849,11 @@ static void tegra_pcie_pme_turnoff(struct tegra_pcie_port *port)
|
||||
val = afi_readl(pcie, AFI_PCIE_PME);
|
||||
val &= ~(0x1 << soc->ports[port->index].pme.turnoff_bit);
|
||||
afi_writel(pcie, val, AFI_PCIE_PME);
|
||||
|
||||
/* PCIe link is in L2, bypass CLKREQ# control over PLLE power down */
|
||||
val = afi_readl(pcie, AFI_PLLE_CONTROL);
|
||||
val |= AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
||||
afi_writel(pcie, val, AFI_PLLE_CONTROL);
|
||||
}
|
||||
|
||||
static void tegra_pcie_msi_irq(struct irq_desc *desc)
|
||||
@@ -1820,6 +2145,13 @@ static void tegra_pcie_disable_interrupts(struct tegra_pcie *pcie)
|
||||
afi_writel(pcie, value, AFI_INTR_MASK);
|
||||
}
|
||||
|
||||
static void update_rp_lanes(struct tegra_pcie *pcie, u32 lanes)
|
||||
{
|
||||
struct tegra_pcie_port *port = NULL;
|
||||
list_for_each_entry(port, &pcie->ports, list)
|
||||
port->lanes = (lanes >> (port->index << 3)) & 0xFF;
|
||||
}
|
||||
|
||||
static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
|
||||
u32 *xbar)
|
||||
{
|
||||
@@ -1848,6 +2180,20 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
|
||||
"switching to default 2x1, 1x1, 1x1 "
|
||||
"configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211;
|
||||
update_rp_lanes(pcie, 0x010102);
|
||||
return 0;
|
||||
}
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra210b01-pcie")) {
|
||||
switch (lanes) {
|
||||
case 0x0104:
|
||||
dev_info(dev, "4x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
|
||||
return 0;
|
||||
default:
|
||||
dev_info(dev, "wrong configuration updated in DT, "
|
||||
"switching to default 4x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
|
||||
update_rp_lanes(pcie, 0x0104);
|
||||
return 0;
|
||||
}
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") ||
|
||||
@@ -1862,6 +2208,13 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
|
||||
dev_info(dev, "2x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
dev_info(dev, "wrong configuration updated in DT, "
|
||||
"switching to default 4x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
|
||||
update_rp_lanes(pcie, 0x0104);
|
||||
return 0;
|
||||
}
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
|
||||
switch (lanes) {
|
||||
@@ -1984,7 +2337,8 @@ static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
|
||||
pcie->supplies[i++].supply = "hvdd-pex-pll";
|
||||
pcie->supplies[i++].supply = "hvdd-pex";
|
||||
pcie->supplies[i++].supply = "vddio-pexctl-aud";
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra210-pcie") ||
|
||||
of_device_is_compatible(np, "nvidia,tegra210b01-pcie")) {
|
||||
pcie->num_supplies = 3;
|
||||
|
||||
pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
|
||||
@@ -2164,6 +2518,14 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
|
||||
"failed to get reset GPIO\n");
|
||||
}
|
||||
|
||||
err = of_property_read_u32(port, "nvidia,disable-aspm-states",
|
||||
&rp->aspm_state);
|
||||
if (err < 0)
|
||||
rp->aspm_state = 0;
|
||||
|
||||
rp->supports_clkreq = of_property_read_bool(port,
|
||||
"supports-clkreq");
|
||||
|
||||
list_add_tail(&rp->list, &pcie->ports);
|
||||
}
|
||||
|
||||
@@ -2352,6 +2714,10 @@ static const struct tegra_pcie_soc tegra20_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = true,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = false,
|
||||
.has_aspm_l1ss = false,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
@@ -2381,6 +2747,10 @@ static const struct tegra_pcie_soc tegra30_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = false,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
@@ -2402,6 +2772,10 @@ static const struct tegra_pcie_soc tegra124_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = false,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
@@ -2425,12 +2799,18 @@ static const struct tegra_pcie_soc tegra210_pcie = {
|
||||
.program_deskew_time = true,
|
||||
.update_fc_timer = true,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = true,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = true,
|
||||
.l1ss_rp_wake_fixup = true,
|
||||
.ectl = {
|
||||
.regs = {
|
||||
.rp_ectl_1_r1 = 0x0000001f,
|
||||
.rp_ectl_2_r1 = 0x0000000f,
|
||||
.rp_ectl_4_r1 = 0x00000067,
|
||||
.rp_ectl_5_r1 = 0x55010000,
|
||||
.rp_ectl_6_r1 = 0x00000001,
|
||||
.rp_ectl_1_r2 = 0x0000001f,
|
||||
.rp_ectl_2_r2 = 0x0000008f,
|
||||
.rp_ectl_4_r2 = 0x000000c7,
|
||||
.rp_ectl_5_r2 = 0x55010000,
|
||||
@@ -2440,6 +2820,42 @@ static const struct tegra_pcie_soc tegra210_pcie = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct tegra_pcie_soc tegra210b01_pcie = {
|
||||
.num_ports = 2,
|
||||
.ports = tegra20_pcie_ports,
|
||||
.msi_base_shift = 8,
|
||||
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
|
||||
.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
|
||||
.pads_refclk_cfg0 = 0xb0b880b8,
|
||||
/* FC threshold is bit[25:18] */
|
||||
.update_fc_threshold = 0x01800000,
|
||||
.has_pex_clkreq_en = true,
|
||||
.has_pex_bias_ctrl = true,
|
||||
.has_intr_prsnt_sense = true,
|
||||
.has_cml_clk = true,
|
||||
.has_gen2 = true,
|
||||
.force_pca_enable = true,
|
||||
.program_uphy = true,
|
||||
.program_deskew_time = true,
|
||||
.update_fc_timer = true,
|
||||
.has_cache_bars = false,
|
||||
.ectl = {
|
||||
.regs = {
|
||||
.rp_ectl_1_r1 = 0x00000027,
|
||||
.rp_ectl_2_r1 = 0x0000000f,
|
||||
.rp_ectl_4_r1 = 0x00000067,
|
||||
.rp_ectl_5_r1 = 0x00000000,
|
||||
.rp_ectl_6_r1 = 0x00000000,
|
||||
.rp_ectl_1_r2 = 0x00000027,
|
||||
.rp_ectl_2_r2 = 0x0000008f,
|
||||
.rp_ectl_4_r2 = 0x000000c7,
|
||||
.rp_ectl_5_r2 = 0x00000000,
|
||||
.rp_ectl_6_r2 = 0x00000000,
|
||||
},
|
||||
.enable = true,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct tegra_pcie_port_soc tegra186_pcie_ports[] = {
|
||||
{ .pme.turnoff_bit = 0, .pme.ack_bit = 5 },
|
||||
{ .pme.turnoff_bit = 8, .pme.ack_bit = 10 },
|
||||
@@ -2466,12 +2882,17 @@ static const struct tegra_pcie_soc tegra186_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = true,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_pcie_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra186-pcie", .data = &tegra186_pcie },
|
||||
{ .compatible = "nvidia,tegra210-pcie", .data = &tegra210_pcie },
|
||||
{ .compatible = "nvidia,tegra210b01-pcie", .data = &tegra210b01_pcie },
|
||||
{ .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie },
|
||||
{ .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie },
|
||||
{ .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie },
|
||||
@@ -2595,6 +3016,8 @@ static int tegra_pcie_probe(struct platform_device *pdev)
|
||||
goto pm_runtime_put;
|
||||
}
|
||||
|
||||
pci_add_flags(PCI_REASSIGN_ALL_BUS);
|
||||
|
||||
host->ops = &tegra_pcie_ops;
|
||||
host->map_irq = tegra_pcie_map_irq;
|
||||
|
||||
|
||||
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user