Compare commits
122
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81536e184f | ||
|
|
9695c7dbec | ||
|
|
9200398a8e | ||
|
|
edb1a77268 | ||
|
|
2e86a8e7d7 | ||
|
|
be77b6992d | ||
|
|
7943c58d69 | ||
|
|
53d6115483 | ||
|
|
a649219eac | ||
|
|
566df49d42 | ||
|
|
facb57bae3 | ||
|
|
5cc184ae32 | ||
|
|
7c63b83f01 | ||
|
|
baccdc9e58 | ||
|
|
33b21c2d6c | ||
|
|
4d226a839b | ||
|
|
388bf6d873 | ||
|
|
edc8773c3a | ||
|
|
a52522ec20 | ||
|
|
55d66b816f | ||
|
|
1c0fce1fc9 | ||
|
|
366206868d | ||
|
|
78f0d0ee79 | ||
|
|
357adbb4b6 | ||
|
|
e79e702f4b | ||
|
|
385cc5b46a | ||
|
|
bb56abf25c | ||
|
|
374ecd3b9c | ||
|
|
f0054c977e | ||
|
|
c9b03f2a90 | ||
|
|
5ddd9aea8e | ||
|
|
ea452c97f1 | ||
|
|
7d9c4bbb67 | ||
|
|
33311c67da | ||
|
|
0aaad09bd8 | ||
|
|
416d5d3002 | ||
|
|
0184fed5fc | ||
|
|
671b02a011 | ||
|
|
f6e6b92330 | ||
|
|
45accfc973 | ||
|
|
0165c547a5 | ||
|
|
8c790c74be | ||
|
|
e750db52c2 | ||
|
|
c0a3c258da | ||
|
|
507c11e883 | ||
|
|
8b9573fe47 | ||
|
|
b4d9e4018c | ||
|
|
05d4959aea | ||
|
|
a0a10e68be | ||
|
|
8d9e37d949 | ||
|
|
5977d303bf | ||
|
|
2970cfd003 | ||
|
|
33f0d99b25 | ||
|
|
8a32e68a20 | ||
|
|
c4170e390f | ||
|
|
8bb394a05c | ||
|
|
60167df1b5 | ||
|
|
ba4dac12be | ||
|
|
3ae6806be3 | ||
|
|
d20bb062dd | ||
|
|
2d503e0fb1 | ||
|
|
8d227a6fbb | ||
|
|
dc3314220d | ||
|
|
111b681101 | ||
|
|
9a5413e9fa | ||
|
|
1ac0412403 | ||
|
|
b82ce7b0d8 | ||
|
|
42bdbbe5fc | ||
|
|
f90a6cfcfc | ||
|
|
f9e0107d8c | ||
|
|
ff6546fecc | ||
|
|
69ea5d3e76 | ||
|
|
3a4823d9a4 | ||
|
|
e139717fa0 | ||
|
|
b3464e207b | ||
|
|
d4e173764d | ||
|
|
a580b0b407 | ||
|
|
048038800f | ||
|
|
6237faf30d | ||
|
|
1b54bcb738 | ||
|
|
f6569aea67 | ||
|
|
7e02b98660 | ||
|
|
cece5d6901 | ||
|
|
56976e04c8 | ||
|
|
d9df5126de | ||
|
|
1396d339da | ||
|
|
3195473247 | ||
|
|
04296c2cff | ||
|
|
fafe37755a | ||
|
|
3f5f6163a4 | ||
|
|
009888ec9b | ||
|
|
b71d035063 | ||
|
|
723687b1e0 | ||
|
|
d2796f7568 | ||
|
|
f273a9844a | ||
|
|
40623ab505 | ||
|
|
d6cfe43b69 | ||
|
|
1b168e5b8c | ||
|
|
973d5536d3 | ||
|
|
2753300b4e | ||
|
|
ba2c386d76 | ||
|
|
5af98305bc | ||
|
|
47176bb1fa | ||
|
|
0e1c162428 | ||
|
|
bc4ef68f74 | ||
|
|
918c526413 | ||
|
|
c508b718dd | ||
|
|
42d74b5aba | ||
|
|
f00ff820f7 | ||
|
|
4055e1cac3 | ||
|
|
c3d883fb2a | ||
|
|
733af3c200 | ||
|
|
492f318ca8 | ||
|
|
a241deda10 | ||
|
|
2a5099fdb3 | ||
|
|
7b3ff6397c | ||
|
|
67057dade8 | ||
|
|
58e4c5446f | ||
|
|
8cf303ed56 | ||
|
|
72d27b6240 | ||
|
|
123ae32e8b | ||
|
|
3bbfabafa3 |
No files matched your search
+11
@@ -1706,6 +1706,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 = [
|
||||
|
||||
@@ -14,12 +14,11 @@ description:
|
||||
functionality. Along with it the user can enable the touchkey which can work
|
||||
as a basic HOME and BACK key for phones.
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stmfts
|
||||
enum:
|
||||
- st,stmfts
|
||||
- st,stmfts5
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -40,6 +39,14 @@ properties:
|
||||
vdd-supply:
|
||||
description: Power supply
|
||||
|
||||
mode-switch-gpios:
|
||||
description: Optional switch between touchscreen SLPI and AP mode.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: Reset GPIO (active-low)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -47,6 +54,17 @@ required:
|
||||
- interrupts
|
||||
- vdd-supply
|
||||
|
||||
allOf:
|
||||
- $ref: touchscreen.yaml#
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stmfts5
|
||||
then:
|
||||
properties:
|
||||
mode-switch-gpios: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
@@ -60,10 +78,9 @@ examples:
|
||||
touchscreen@49 {
|
||||
compatible = "st,stmfts";
|
||||
reg = <0x49>;
|
||||
interrupt-parent = <&gpa1>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||
touchscreen-size-x = <1599>;
|
||||
touchscreen-size-y = <2559>;
|
||||
interrupts-extended = <&gpa1 1 IRQ_TYPE_LEVEL_LOW>;
|
||||
touchscreen-size-x = <1600>;
|
||||
touchscreen-size-y = <2560>;
|
||||
touch-key-connected;
|
||||
avdd-supply = <&ldo30_reg>;
|
||||
vdd-supply = <&ldo31_reg>;
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -23335,6 +23335,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
|
||||
|
||||
@@ -2453,6 +2453,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
|
||||
|
||||
@@ -30,6 +30,13 @@ 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
|
||||
|
||||
@@ -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>;
|
||||
@@ -1295,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";
|
||||
};
|
||||
|
||||
@@ -1362,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,108 @@
|
||||
// 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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gpio@6000d000 {
|
||||
wlreg-hog {
|
||||
gpio-hog;
|
||||
gpios = <TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "wlreg_on";
|
||||
};
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
};
|
||||
@@ -26,7 +26,24 @@
|
||||
|
||||
status = "okay";
|
||||
|
||||
/* ST,FTS @ 49 */
|
||||
touchscreen@49 {
|
||||
compatible = "st,stmfts5";
|
||||
reg = <0x49>;
|
||||
|
||||
pinctrl-0 = <&touchscreen_irq_n>, <&touchscreen_reset>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
interrupts-extended = <&tlmm 125 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
mode-switch-gpios = <&tlmm 136 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>;
|
||||
|
||||
avdd-supply = <&vreg_l19a_3p3>;
|
||||
vdd-supply = <&vreg_l14a_1p8>;
|
||||
|
||||
touchscreen-size-x = <1080>;
|
||||
touchscreen-size-y = <2160>;
|
||||
};
|
||||
};
|
||||
|
||||
&mdss_dsi0 {
|
||||
|
||||
@@ -466,7 +466,7 @@
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
touchscreen_pins: ts-pins-gpio-state {
|
||||
touchscreen_irq_n: ts-irq-n-gpio-state {
|
||||
pins = "gpio125";
|
||||
function = "gpio";
|
||||
drive-strength = <2>;
|
||||
|
||||
@@ -874,6 +874,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
|
||||
@@ -50,7 +50,6 @@ 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 +69,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
|
||||
@@ -441,7 +441,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,7 +606,6 @@ 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
|
||||
@@ -766,8 +764,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<6>[ 0.505994] bm92t 0-0018: bm92t_probe
|
||||
<6>[ 0.506468] bm92t 0-0018: DP handling disabled
|
||||
<6>[ 0.508019] bm92t 0-0018: fw_type: 0x603, fw_rev: 0xD7C
|
||||
<7>[ 0.508615] bm92t 0-0018: write reg cmd = 0x06 len = 3
|
||||
<6>[ 0.509242] bm92t 0-0018: bm92t_debug_init
|
||||
<6>[ 0.519206] bm92t 0-0018: init done
|
||||
<7>[ 0.621689] bm92t 0-0018: Disabling VBUS
|
||||
<3>[ 0.623565] bm92t 0-0018: Unknown cmd rejected!
|
||||
<4>[ 0.623586] bm92t 0-0018: Invalid state, initiating SYS Reset!
|
||||
<7>[ 0.623626] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
<7>[ 0.624129] bm92t 0-0018: Sent cmd 0x0D 0x0D return value 0
|
||||
<7>[ 0.727667] bm92t 0-0018: write reg cmd = 0x06 len = 3
|
||||
<7>[ 0.728199] bm92t 0-0018: write reg cmd = 0x19 len = 3
|
||||
<6>[ 0.728696] bm92t 0-0018: extcon cable is set to init state
|
||||
<6>[ 0.840258] bm92t 0-0018: Alert= 0x0008 Status1= 0x1A80 Status2= 0x2000 DP= 0x4000 State= INIT_STATE
|
||||
<7>[ 0.840297] bm92t 0-0018: Enabling VBUS
|
||||
<6>[ 1.069745] bm92t 0-0018: extcon cable (02: USB HOST) attached
|
||||
<6>[ 1.072449] bm92t 0-0018: Alert= 0x0008 Status1= 0x0D80 Status2= 0x0000 DP= 0x4000 State= INIT_STATE
|
||||
<6>[ 1.095097] bm92t 0-0018: Alert= 0x4000 Status1= 0x0D80 Status2= 0x0000 DP= 0x4000 State= INIT_STATE
|
||||
<6>[ 1.137871] bm92t 0-0018: Alert= 0x1000 Status1= 0x4D80 Status2= 0x0000 DP= 0x4000 State= INIT_STATE
|
||||
<6>[ 1.141067] bm92t 0-0018: Supported PDOs:
|
||||
<6>[ 1.141089] bm92t 0-0018: PDO 1: 1500mA 5000mV DRD
|
||||
<6>[ 1.141104] bm92t 0-0018: Device in powered mode
|
||||
<6>[ 1.141120] bm92t 0-0018: Requesting 1: min 900mA, max 1500mA, 5000mV
|
||||
<7>[ 1.141138] bm92t 0-0018: write reg cmd = 0x30 len = 6
|
||||
<7>[ 1.141930] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
<7>[ 1.142422] bm92t 0-0018: Sent cmd 0x07 0x07 return value 0
|
||||
<7>[ 1.142438] bm92t 0-0018: state = NEW_PDO
|
||||
<6>[ 1.166166] bm92t 0-0018: Alert= 0x0004 Status1= 0x4D80 Status2= 0x0000 DP= 0x4000 State= NEW_PDO
|
||||
<7>[ 1.166200] bm92t 0-0018: cmd done in NEW_PDO state
|
||||
<6>[ 1.189414] bm92t 0-0018: Alert= 0x1000 Status1= 0x4D80 Status2= 0x0000 DP= 0x4000 State= NEW_PDO
|
||||
<6>[ 1.191193] bm92t 0-0018: New PD Contract:
|
||||
<6>[ 1.191212] bm92t 0-0018: PDO: 1: 1500mA, 5000mV
|
||||
<6>[ 1.191224] bm92t 0-0018: RDO: op 900mA, 1500mA max
|
||||
<7>[ 1.191240] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
<7>[ 1.191734] bm92t 0-0018: Sent cmd 0x05 0x05 return value 0
|
||||
<7>[ 1.191750] bm92t 0-0018: state = PS_RDY_SENT
|
||||
<6>[ 1.194256] bm92t 0-0018: Alert= 0x0004 Status1= 0x4D80 Status2= 0x0000 DP= 0x4000 State= PS_RDY_SENT
|
||||
<7>[ 1.194287] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
<7>[ 1.194804] bm92t 0-0018: Sent cmd 0x18 0x18 return value 0
|
||||
<7>[ 1.194818] bm92t 0-0018: state = DR_SWAP_SENT
|
||||
<6>[ 1.203046] bm92t 0-0018: Alert= 0x0004 Status1= 0x4DE0 Status2= 0x0000 DP= 0x4000 State= DR_SWAP_SENT
|
||||
<3>[ 1.203075] bm92t 0-0018: DR_SWAP_CMD rejected!
|
||||
<6>[ 1.203093] bm92t 0-0018: extcon cable (02: USB HOST) detached
|
||||
<6>[ 1.203168] bm92t 0-0018: extcon cable (01: USB) attached
|
||||
<7>[ 1.203195] bm92t 0-0018: state = INIT_STATE
|
||||
<6>[ 2.131526] bm92t 0-0018: Alert= 0x0800 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
<6>[ 3.216479] bm92t 0-0018: Set Charging Current Limit 900ma
|
||||
@@ -0,0 +1,72 @@
|
||||
[ 0.513067][ T1] /i2c@7000c000/bm92t@18: Fixed dependency cycle(s) with /padctl@7009f000
|
||||
[ 0.513632][ T1] /padctl@7009f000: Fixed dependency cycle(s) with /i2c@7000c000/bm92t@18
|
||||
[ 3.774932][ T1] /padctl@7009f000: Fixed dependency cycle(s) with /i2c@7000c000/bm92t@18
|
||||
[ 3.781706][ T1] /i2c@7000c000/bm92t@18: Fixed dependency cycle(s) with /padctl@7009f000
|
||||
[ 4.999891][ T1] bm92t 0-0018: DP handling disabled
|
||||
[ 5.005789][ T1] bm92t 0-0018: fw_type: 0x603, fw_rev: 0xD7C
|
||||
[ 5.010151][ T1] bm92t 0-0018: write reg cmd = 0x06 len = 3
|
||||
[ 5.029128][ T1] bm92t 0-0018: init done
|
||||
[ 5.133260][ T76] bm92t 0-0018: Disabling VBUS
|
||||
[ 5.139599][ T76] bm92t 0-0018: Unknown cmd rejected!
|
||||
[ 5.150059][ T76] bm92t 0-0018: Invalid state, initiating SYS Reset!
|
||||
[ 5.163413][ T76] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
[ 5.174663][ T76] bm92t 0-0018: Sent cmd 0x0D 0x0D return value 0
|
||||
[ 5.284905][ T76] bm92t 0-0018: write reg cmd = 0x06 len = 3
|
||||
[ 5.289002][ T76] bm92t 0-0018: write reg cmd = 0x19 len = 3
|
||||
[ 5.294828][ T76] bm92t 0-0018: extcon cable is set to init state
|
||||
[ 5.409602][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.419830][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.430023][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.440217][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.450404][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.460599][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.470791][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.480977][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.491180][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0000 Status2= 0x0000 DP= 0x0000 State= INIT_STATE
|
||||
[ 5.501370][ T14] bm92t 0-0018: Alert= 0x0000 Status1= 0x0D80 Status2= 0x0000 DP= 0x4000 State= INIT_STATE
|
||||
[ 5.601170][ T12] bm92t 0-0018: Supported PDOs:
|
||||
[ 5.603621][ T12] bm92t 0-0018: PDO 1: 1500mA 5000mV DRD
|
||||
[ 5.609164][ T12] bm92t 0-0018: Device in powered mode
|
||||
[ 5.614444][ T12] bm92t 0-0018: Requesting 1: min 900mA, max 1500mA, 5000mV
|
||||
[ 5.621646][ T12] bm92t 0-0018: write reg cmd = 0x30 len = 6
|
||||
[ 5.628227][ T12] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
[ 5.633748][ T12] bm92t 0-0018: Sent cmd 0x07 0x07 return value 0
|
||||
[ 5.639500][ T12] bm92t 0-0018: state = NEW_PDO
|
||||
[ 5.669385][ T12] bm92t 0-0018: cmd done in NEW_PDO state
|
||||
[ 5.682390][ T14] bm92t 0-0018: New PD Contract:
|
||||
[ 5.684930][ T14] bm92t 0-0018: PDO: 1: 1500mA, 5000mV
|
||||
[ 5.690203][ T14] bm92t 0-0018: RDO: op 900mA, 1500mA max
|
||||
[ 5.695750][ T14] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
[ 5.702053][ T14] bm92t 0-0018: Sent cmd 0x05 0x05 return value 0
|
||||
[ 5.707809][ T14] bm92t 0-0018: state = PS_RDY_SENT
|
||||
[ 5.715462][ T14] bm92t 0-0018: extcon cable (02: USB HOST) attached
|
||||
[ 5.719728][ T14] bm92t 0-0018: write reg cmd = 0x05 len = 3
|
||||
[ 5.726030][ T14] bm92t 0-0018: Sent cmd 0x18 0x18 return value 0
|
||||
[ 5.731775][ T14] bm92t 0-0018: state = DR_SWAP_SENT
|
||||
[ 5.739509][ T14] bm92t 0-0018: DR_SWAP_CMD rejected!
|
||||
[ 5.742450][ T14] bm92t 0-0018: extcon cable (02: USB HOST) detached
|
||||
[ 5.749002][ T14] bm92t 0-0018: extcon cable (01: USB) attached
|
||||
[ 5.755045][ T14] bm92t 0-0018: state = INIT_STATE
|
||||
[ 7.750906][ T76] bm92t 0-0018: Set Charging Current Limit 900ma
|
||||
[ 10.413696][ T12] bm92t_event_handler: 1554 callbacks suppressed
|
||||
[ 10.413707][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.430124][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.440606][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.450832][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.461080][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.471307][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.481507][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.491702][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.501887][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 10.512081][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.415942][ T55] bm92t_event_handler: 1865 callbacks suppressed
|
||||
[ 15.415949][ T55] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.432305][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.442506][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.452721][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.462926][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.473114][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.483314][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.493520][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.503715][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
[ 15.513916][ T12] bm92t 0-0018: Alert= 0x0000 Status1= 0x4DE0 Status2= 0x0001 DP= 0x4000 State= INIT_STATE
|
||||
@@ -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);
|
||||
|
||||
@@ -506,6 +506,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
|
||||
{ 0x6606, "BCM4345C5" }, /* 003.006.006 */
|
||||
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
|
||||
{ 0x2310, "BCM4343A2" }, /* 001.003.016 */
|
||||
{ 0x2409, "BCM4356A3" }, /* 001.004.009 */
|
||||
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */
|
||||
{ 0x420d, "BCM4349B1" }, /* 002.002.013 */
|
||||
{ 0x420e, "BCM4349B1" }, /* 002.002.014 */
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
+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);
|
||||
|
||||
@@ -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,7 +581,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,
|
||||
}
|
||||
},
|
||||
@@ -680,10 +680,13 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = {
|
||||
.process_id = -1,
|
||||
.max_millivolts = 1120,
|
||||
CPUB01_CVB_TABLE,
|
||||
.vmin_coefficients = { 620000, 0, 0 },
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x0000ffcf,
|
||||
.tune1 = 0x012207ff,
|
||||
.tune1_low = 0x012207ff,
|
||||
.tune1_high = 0x03FFF7FF,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -691,11 +694,13 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = {
|
||||
.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 = 0x021107ff,
|
||||
.tune1_low = 0x021107ff,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -703,11 +708,13 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = {
|
||||
.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 = 0x021107ff,
|
||||
.tune1_low = 0x021107ff,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -715,10 +722,12 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = {
|
||||
.process_id = -1,
|
||||
.max_millivolts = 1120,
|
||||
CPUB01_CVB_TABLE,
|
||||
.vmin_coefficients = { 620000, 0, 0 },
|
||||
.cpu_dfll_data = {
|
||||
.tune0_low = 0x0000ffcf,
|
||||
.tune1 = 0x012207ff,
|
||||
.tune1_low = 0x012207ff,
|
||||
.tune_high_min_millivolts = 850,
|
||||
.tune_high_margin_millivolts = 38,
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -845,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)) {
|
||||
@@ -854,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 },
|
||||
};
|
||||
|
||||
|
||||
@@ -1705,7 +1705,6 @@ static struct div_nmp pllss_nmp = {
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = {
|
||||
{ 38400000, 998400000, 52, 2, 1, 0 },
|
||||
{ 38400000, 787200000, 41, 2, 1, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
@@ -2177,9 +2176,9 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_i2s0] = { .dt_id = TEGRA210_CLK_I2S0, .present = true },
|
||||
[tegra_clk_apbdma] = { .dt_id = TEGRA210_CLK_APBDMA, .present = true },
|
||||
[tegra_clk_kfuse] = { .dt_id = TEGRA210_CLK_KFUSE, .present = true },
|
||||
[tegra_clk_sbc1_9] = { .dt_id = TEGRA210_CLK_SBC1, .present = true },
|
||||
[tegra_clk_sbc2_9] = { .dt_id = TEGRA210_CLK_SBC2, .present = true },
|
||||
[tegra_clk_sbc3_9] = { .dt_id = TEGRA210_CLK_SBC3, .present = true },
|
||||
[tegra_clk_sbc1_9] = { .dt_id = TEGRA210_CLK_SBC1, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_sbc2_9] = { .dt_id = TEGRA210_CLK_SBC2, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_sbc3_9] = { .dt_id = TEGRA210_CLK_SBC3, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_i2c5] = { .dt_id = TEGRA210_CLK_I2C5, .present = true },
|
||||
[tegra_clk_csi] = { .dt_id = TEGRA210_CLK_CSI, .present = true },
|
||||
[tegra_clk_i2c2] = { .dt_id = TEGRA210_CLK_I2C2, .present = true },
|
||||
@@ -2189,20 +2188,20 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_bsev] = { .dt_id = TEGRA210_CLK_BSEV, .present = true },
|
||||
[tegra_clk_uartd_8] = { .dt_id = TEGRA210_CLK_UARTD, .present = true },
|
||||
[tegra_clk_i2c3] = { .dt_id = TEGRA210_CLK_I2C3, .present = true },
|
||||
[tegra_clk_sbc4_9] = { .dt_id = TEGRA210_CLK_SBC4, .present = true },
|
||||
[tegra_clk_sbc4_9] = { .dt_id = TEGRA210_CLK_SBC4, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_sdmmc3_9] = { .dt_id = TEGRA210_CLK_SDMMC3, .present = true },
|
||||
[tegra_clk_pcie] = { .dt_id = TEGRA210_CLK_PCIE, .present = true },
|
||||
[tegra_clk_owr_8] = { .dt_id = TEGRA210_CLK_OWR, .present = true },
|
||||
[tegra_clk_afi] = { .dt_id = TEGRA210_CLK_AFI, .present = true },
|
||||
[tegra_clk_csite_8] = { .dt_id = TEGRA210_CLK_CSITE, .present = true },
|
||||
[tegra_clk_soc_therm_8] = { .dt_id = TEGRA210_CLK_SOC_THERM, .present = true },
|
||||
[tegra_clk_soc_therm_8] = { .dt_id = TEGRA210_CLK_SOC_THERM, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_dtv] = { .dt_id = TEGRA210_CLK_DTV, .present = true },
|
||||
[tegra_clk_i2cslow] = { .dt_id = TEGRA210_CLK_I2CSLOW, .present = true },
|
||||
[tegra_clk_i2cslow] = { .dt_id = TEGRA210_CLK_I2CSLOW, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_tsec_8] = { .dt_id = TEGRA210_CLK_TSEC, .present = true },
|
||||
[tegra_clk_xusb_host] = { .dt_id = TEGRA210_CLK_XUSB_HOST, .present = true },
|
||||
[tegra_clk_csus] = { .dt_id = TEGRA210_CLK_CSUS, .present = true },
|
||||
[tegra_clk_mselect] = { .dt_id = TEGRA210_CLK_MSELECT, .present = true },
|
||||
[tegra_clk_tsensor] = { .dt_id = TEGRA210_CLK_TSENSOR, .present = true },
|
||||
[tegra_clk_tsensor] = { .dt_id = TEGRA210_CLK_TSENSOR, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_i2s3] = { .dt_id = TEGRA210_CLK_I2S3, .present = true },
|
||||
[tegra_clk_i2s4] = { .dt_id = TEGRA210_CLK_I2S4, .present = true },
|
||||
[tegra_clk_i2c4] = { .dt_id = TEGRA210_CLK_I2C4, .present = true },
|
||||
@@ -2217,8 +2216,8 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_sata_8] = { .dt_id = TEGRA210_CLK_SATA, .present = true },
|
||||
[tegra_clk_hda_8] = { .dt_id = TEGRA210_CLK_HDA, .present = true },
|
||||
[tegra_clk_hda2hdmi] = { .dt_id = TEGRA210_CLK_HDA2HDMI, .present = true },
|
||||
[tegra_clk_cilab] = { .dt_id = TEGRA210_CLK_CILAB, .present = true },
|
||||
[tegra_clk_cilcd] = { .dt_id = TEGRA210_CLK_CILCD, .present = true },
|
||||
[tegra_clk_cilab] = { .dt_id = TEGRA210_CLK_CILAB, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_cilcd] = { .dt_id = TEGRA210_CLK_CILCD, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_cile] = { .dt_id = TEGRA210_CLK_CILE, .present = true },
|
||||
[tegra_clk_dsialp] = { .dt_id = TEGRA210_CLK_DSIALP, .present = true },
|
||||
[tegra_clk_dsiblp] = { .dt_id = TEGRA210_CLK_DSIBLP, .present = true },
|
||||
@@ -2238,7 +2237,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, },
|
||||
[tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true },
|
||||
[tegra_clk_spdif_in_8] = { .dt_id = TEGRA210_CLK_SPDIF_IN, .present = true },
|
||||
[tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .present = true },
|
||||
[tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_vi_10] = { .dt_id = TEGRA210_CLK_VI, .present = true },
|
||||
[tegra_clk_vi_sensor_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR, .present = true },
|
||||
[tegra_clk_fuse] = { .dt_id = TEGRA210_CLK_FUSE, .present = true },
|
||||
@@ -2276,7 +2275,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_pll_u_60m] = { .dt_id = TEGRA210_CLK_PLL_U_60M, .present = true },
|
||||
[tegra_clk_pll_u_48m] = { .dt_id = TEGRA210_CLK_PLL_U_48M, .present = true },
|
||||
[tegra_clk_pll_x] = { .dt_id = TEGRA210_CLK_PLL_X, .present = true },
|
||||
[tegra_clk_pll_x_out0] = { .dt_id = TEGRA210_CLK_PLL_X_OUT0, .present = true },
|
||||
[tegra_clk_pll_re_vco] = { .dt_id = TEGRA210_CLK_PLL_RE_VCO, .present = true },
|
||||
[tegra_clk_pll_re_out] = { .dt_id = TEGRA210_CLK_PLL_RE_OUT, .present = true },
|
||||
[tegra_clk_spdif_in_sync] = { .dt_id = TEGRA210_CLK_SPDIF_IN_SYNC, .present = true },
|
||||
@@ -2310,7 +2308,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_hclk] = { .dt_id = TEGRA210_CLK_HCLK, .present = true },
|
||||
[tegra_clk_pclk] = { .dt_id = TEGRA210_CLK_PCLK, .present = true },
|
||||
[tegra_clk_cclk_g] = { .dt_id = TEGRA210_CLK_CCLK_G, .present = true },
|
||||
[tegra_clk_cclk_lp] = { .dt_id = TEGRA210_CLK_CCLK_LP, .present = true },
|
||||
[tegra_clk_dfll_ref] = { .dt_id = TEGRA210_CLK_DFLL_REF, .present = true },
|
||||
[tegra_clk_dfll_soc] = { .dt_id = TEGRA210_CLK_DFLL_SOC, .present = true },
|
||||
[tegra_clk_vi_sensor2_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR2, .present = true },
|
||||
@@ -2325,8 +2322,8 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
|
||||
[tegra_clk_spdif_mux] = { .dt_id = TEGRA210_CLK_SPDIF_MUX, .present = true },
|
||||
[tegra_clk_maud] = { .dt_id = TEGRA210_CLK_MAUD, .present = true },
|
||||
[tegra_clk_mipibif] = { .dt_id = TEGRA210_CLK_MIPIBIF, .present = true },
|
||||
[tegra_clk_qspi] = { .dt_id = TEGRA210_CLK_QSPI, .present = true },
|
||||
[tegra_clk_sdmmc_legacy] = { .dt_id = TEGRA210_CLK_SDMMC_LEGACY, .present = true },
|
||||
[tegra_clk_qspi] = { .dt_id = TEGRA210_CLK_QSPI, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_sdmmc_legacy] = { .dt_id = TEGRA210_CLK_SDMMC_LEGACY, .use_integer_div = true, .present = true },
|
||||
[tegra_clk_tsecb] = { .dt_id = TEGRA210_CLK_TSECB, .present = true },
|
||||
[tegra_clk_uartape] = { .dt_id = TEGRA210_CLK_UARTAPE, .present = true },
|
||||
[tegra_clk_vi_i2c] = { .dt_id = TEGRA210_CLK_VI_I2C, .present = true },
|
||||
@@ -2535,7 +2532,7 @@ static void tegra210_utmi_hw_sequencer_enable(void)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static int tegra210_enable_utmipll(void)
|
||||
static int tegra210b01_enable_utmipll(void)
|
||||
{
|
||||
u32 reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
|
||||
bool hw_on = reg & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
|
||||
@@ -2618,7 +2615,7 @@ static int tegra210_enable_pllu(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_init_pllu(void)
|
||||
static int tegra210b01_init_pllu(void)
|
||||
{
|
||||
u32 reg;
|
||||
int err;
|
||||
@@ -2676,7 +2673,7 @@ static int tegra210_init_pllu(void)
|
||||
}
|
||||
|
||||
/* enable UTMIPLL hw control if not yet done by the bootloader */
|
||||
return tegra210_enable_utmipll();
|
||||
return tegra210b01_enable_utmipll();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2876,7 +2873,7 @@ static __init void tegra210_periph_clk_init(struct device_node *np,
|
||||
tegra210_clk_register_mc("mc", "emc");
|
||||
}
|
||||
|
||||
static void __init tegra210_pll_init(void __iomem *clk_base,
|
||||
static void __init tegra210b01_pll_init(void __iomem *clk_base,
|
||||
void __iomem *pmc)
|
||||
{
|
||||
struct clk *clk;
|
||||
@@ -2921,7 +2918,7 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
|
||||
clks[TEGRA210_CLK_PLL_C3] = clk;
|
||||
|
||||
/* PLLU_VCO */
|
||||
if (!tegra210_init_pllu()) {
|
||||
if (!tegra210b01_init_pllu()) {
|
||||
clk = clk_register_fixed_rate(NULL, "pll_u_vco", "pll_ref", 0,
|
||||
480*1000*1000);
|
||||
clk_register_clkdev(clk, "pll_u_vco", NULL);
|
||||
@@ -3030,8 +3027,8 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
|
||||
clks[TEGRA210_CLK_PLL_E] = clk;
|
||||
|
||||
/* PLLC4 */
|
||||
clk = tegra_clk_register_pllre_tegra210("pll_c4_vco", "pll_ref",
|
||||
clk_base, pmc, 0, &pll_c4_vco_params, NULL, pll_ref_freq);
|
||||
clk = tegra_clk_register_pllre("pll_c4_vco", "pll_ref", clk_base, pmc,
|
||||
0, &pll_c4_vco_params, NULL, pll_ref_freq);
|
||||
clk_register_clkdev(clk, "pll_c4_vco", NULL);
|
||||
clks[TEGRA210_CLK_PLL_C4] = clk;
|
||||
|
||||
@@ -3098,6 +3095,55 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
|
||||
clks[TEGRA210_CLK_PLL_P_UPHY_OUT] = clk;
|
||||
}
|
||||
|
||||
static char *tegra210b01_determine_pllc4_rate(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
u32 val;
|
||||
int out0_ratio, i;
|
||||
unsigned long sdmmc_max_rate = 0;
|
||||
struct clk *clk;
|
||||
char *sclk_high_clk;
|
||||
|
||||
for_each_compatible_node(node, NULL, "nvidia,tegra210-sdhci") {
|
||||
if (!of_device_is_available(node))
|
||||
continue;
|
||||
|
||||
if (!of_property_read_u32(node, "max-frequency", &val)
|
||||
&& val > sdmmc_max_rate)
|
||||
sdmmc_max_rate = val;
|
||||
}
|
||||
|
||||
switch (sdmmc_max_rate) {
|
||||
case 266000000:
|
||||
sclk_high_clk = "pll_c4_out1";
|
||||
pll_c4_vco_params.fixed_rate = 798000000;
|
||||
out0_ratio = 4;
|
||||
break;
|
||||
default:
|
||||
sclk_high_clk = "pll_c4_out3";
|
||||
pll_c4_vco_params.fixed_rate = 1000000000;
|
||||
out0_ratio = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
pll_c4_vco_params.fixed_rate /= pll_ref_freq/pll_c4_vco_params.mdiv_default;
|
||||
pll_c4_vco_params.fixed_rate *= pll_ref_freq/pll_c4_vco_params.mdiv_default;
|
||||
|
||||
val = readl(clk_base + PLLC4_BASE);
|
||||
for (i = 0; pll_vco_post_div_table[i].div; i++)
|
||||
if (pll_vco_post_div_table[i].div >= out0_ratio)
|
||||
break;
|
||||
val &= ~GENMASK(23, 19);
|
||||
val |= pll_vco_post_div_table[i].val << pll_c4_vco_params.div_nmp->divp_shift;
|
||||
writel(val, clk_base + PLLC4_BASE);
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "pll_c4_out0", "pll_c4_vco", 0,
|
||||
1, pll_vco_post_div_table[i].div);
|
||||
clks[TEGRA210_CLK_PLL_C4_OUT0] = clk;
|
||||
|
||||
return sclk_high_clk;
|
||||
}
|
||||
|
||||
/* Tegra210 CPU clock and reset control functions */
|
||||
static void tegra210_wait_cpu_in_reset(u32 cpu)
|
||||
{
|
||||
@@ -3179,7 +3225,7 @@ static void tegra210_clk_resume(void *data)
|
||||
fence_udelay(2, clk_base);
|
||||
|
||||
/* restore PLLs and all peripheral clock rates */
|
||||
tegra210_init_pllu();
|
||||
tegra210b01_init_pllu();
|
||||
clk_restore_context();
|
||||
|
||||
/* restore saved context of peripheral clocks and reset state */
|
||||
@@ -3227,12 +3273,9 @@ static const struct of_device_id pmc_match[] __initconst = {
|
||||
};
|
||||
|
||||
static struct tegra_clk_init_table t210b01_init_table[] __initdata = {
|
||||
{ TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1,
|
||||
TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
|
||||
{ TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 0, 1,
|
||||
TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
|
||||
{ TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0,
|
||||
TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
|
||||
{ TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1, TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
|
||||
//{ TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 0, 1, TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
|
||||
{ TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0, TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
|
||||
{ TEGRA210_CLK_PLL_P_UPHY_OUT, TEGRA210_CLK_CLK_MAX, 102000000, 1 },
|
||||
{ TEGRA210_CLK_SDMMC_LEGACY, TEGRA210_CLK_PLL_P, 12000000, 0 },
|
||||
{ TEGRA210_CLK_I2CSLOW, TEGRA210_CLK_CLK_32K, 32000, 0 },
|
||||
@@ -3403,48 +3446,6 @@ static int tegra210b01_reset_deassert(unsigned long id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum clk_id tegra210b01_integer_div_id[] = {
|
||||
tegra_clk_cilab,
|
||||
tegra_clk_cilcd,
|
||||
|
||||
tegra_clk_spdif_out,
|
||||
|
||||
tegra_clk_sbc1_9,
|
||||
tegra_clk_sbc2_9,
|
||||
tegra_clk_sbc3_9,
|
||||
tegra_clk_sbc4_9,
|
||||
|
||||
tegra_clk_sdmmc_legacy,
|
||||
tegra_clk_i2cslow,
|
||||
tegra_clk_qspi,
|
||||
|
||||
tegra_clk_soc_therm_8,
|
||||
tegra_clk_tsensor,
|
||||
};
|
||||
|
||||
static void tegra210b01_adjust_clks(struct tegra_clk *tegra_clks)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Remove CPU_LP claster clocks */
|
||||
tegra_clks[tegra_clk_cclk_lp].present = false;
|
||||
tegra_clks[tegra_clk_pll_x_out0].present = false;
|
||||
|
||||
/* Prevent 1:1.5 fractional divider setting */
|
||||
div1_5_not_allowed = true;
|
||||
|
||||
/* Prevent any fractional setting */
|
||||
for (i = 0; i < ARRAY_SIZE(tegra210b01_integer_div_id); i++) {
|
||||
enum clk_id cid = tegra210b01_integer_div_id[i];
|
||||
|
||||
if (cid >= tegra_clk_max || !tegra_clks[cid].present) {
|
||||
pr_warn("%s: clk %d is not present\n", __func__, cid);
|
||||
continue;
|
||||
}
|
||||
tegra_clks[cid].use_integer_div = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210b01_clock_init - Tegra210-specific clock initialization
|
||||
* @np: struct device_node * of the DT node for the SoC CAR IP block
|
||||
@@ -3457,6 +3458,7 @@ static void tegra210b01_adjust_clks(struct tegra_clk *tegra_clks)
|
||||
static void __init tegra210b01_clock_init(struct device_node *np)
|
||||
{
|
||||
struct device_node *node;
|
||||
char *sclk_high_clk;
|
||||
u32 value, clk_m_div;
|
||||
|
||||
clk_base = of_iomap(np, 0);
|
||||
@@ -3485,7 +3487,8 @@ static void __init tegra210b01_clock_init(struct device_node *np)
|
||||
if (!clks)
|
||||
return;
|
||||
|
||||
tegra210b01_adjust_clks(tegra210_clks);
|
||||
/* Prevent 1:1.5 fractional divider setting */
|
||||
div1_5_not_allowed = true;
|
||||
|
||||
value = readl(clk_base + SPARE_REG0) >> CLK_M_DIVISOR_SHIFT;
|
||||
clk_m_div = (value & CLK_M_DIVISOR_MASK) + 1;
|
||||
@@ -3496,7 +3499,8 @@ static void __init tegra210b01_clock_init(struct device_node *np)
|
||||
return;
|
||||
|
||||
tegra_fixed_clk_init(tegra210_clks);
|
||||
tegra210_pll_init(clk_base, pmc_base);
|
||||
sclk_high_clk = tegra210b01_determine_pllc4_rate();
|
||||
tegra210b01_pll_init(clk_base, pmc_base);
|
||||
tegra210_periph_clk_init(np, clk_base, pmc_base);
|
||||
tegra_audio_clk_init(clk_base, pmc_base, tegra210_clks,
|
||||
tegra210_audio_plls,
|
||||
|
||||
+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);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/pm.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/sched/clock.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <soc/tegra/bpmp.h>
|
||||
#include <soc/tegra/bpmp-abi.h>
|
||||
@@ -343,28 +344,12 @@ static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
|
||||
|
||||
static int __maybe_unused tegra_bpmp_resume(struct device *dev);
|
||||
|
||||
int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
|
||||
struct tegra_bpmp_message *msg)
|
||||
static int __tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
|
||||
struct tegra_bpmp_message *msg)
|
||||
{
|
||||
struct tegra_bpmp_channel *channel;
|
||||
struct tegra_bpmp_channel *channel = bpmp->tx_channel;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!irqs_disabled()))
|
||||
return -EPERM;
|
||||
|
||||
if (!tegra_bpmp_message_valid(msg))
|
||||
return -EINVAL;
|
||||
|
||||
if (bpmp->suspended) {
|
||||
/* Reset BPMP IPC channels during resume based on flags passed */
|
||||
if (msg->flags & TEGRA_BPMP_MESSAGE_RESET)
|
||||
tegra_bpmp_resume(bpmp->dev);
|
||||
else
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
channel = bpmp->tx_channel;
|
||||
|
||||
spin_lock(&bpmp->atomic_tx_lock);
|
||||
|
||||
err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
|
||||
@@ -387,6 +372,26 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
|
||||
return __tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size,
|
||||
&msg->rx.ret);
|
||||
}
|
||||
|
||||
int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
|
||||
struct tegra_bpmp_message *msg)
|
||||
{
|
||||
if (WARN_ON(!irqs_disabled()))
|
||||
return -EPERM;
|
||||
|
||||
if (!tegra_bpmp_message_valid(msg))
|
||||
return -EINVAL;
|
||||
|
||||
if (bpmp->suspended) {
|
||||
/* Reset BPMP IPC channels during resume based on flags passed */
|
||||
if (msg->flags & TEGRA_BPMP_MESSAGE_RESET)
|
||||
tegra_bpmp_resume(bpmp->dev);
|
||||
else
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return __tegra_bpmp_transfer_atomic(bpmp, msg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra_bpmp_transfer_atomic);
|
||||
|
||||
int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
|
||||
@@ -733,6 +738,37 @@ void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
|
||||
spin_unlock(&bpmp->lock);
|
||||
}
|
||||
|
||||
#define MRQ_T210_ENABLE_SUSPEND 17
|
||||
#define TEGRA210_BPMP_PM_SC7 23
|
||||
|
||||
static int tegra210_bpmp_syscore_suspend(void *data)
|
||||
{
|
||||
struct tegra_bpmp *bpmp = data;
|
||||
__le32 req[2] = { cpu_to_le32(TEGRA210_BPMP_PM_SC7), 0 };
|
||||
struct tegra_bpmp_message msg = {
|
||||
.mrq = MRQ_T210_ENABLE_SUSPEND,
|
||||
.tx = {
|
||||
.data = req,
|
||||
.size = sizeof(req),
|
||||
},
|
||||
};
|
||||
int err;
|
||||
|
||||
err = __tegra_bpmp_transfer_atomic(bpmp, &msg);
|
||||
if (err < 0)
|
||||
dev_err(bpmp->dev, "failed to enable SC7: %d\n", err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct syscore_ops tegra210_bpmp_syscore_ops = {
|
||||
.suspend = tegra210_bpmp_syscore_suspend,
|
||||
};
|
||||
|
||||
static struct syscore tegra210_bpmp_syscore = {
|
||||
.ops = &tegra210_bpmp_syscore_ops,
|
||||
};
|
||||
|
||||
static int tegra_bpmp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_bpmp *bpmp;
|
||||
@@ -831,6 +867,11 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
|
||||
if (err < 0)
|
||||
dev_err(&pdev->dev, "debugfs initialization failed: %d\n", err);
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "nvidia,tegra210-bpmp")) {
|
||||
tegra210_bpmp_syscore.data = bpmp;
|
||||
register_syscore(&tegra210_bpmp_syscore);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_mrq:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -192,7 +192,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;
|
||||
|
||||
|
||||
@@ -148,7 +148,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)
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -96,12 +96,18 @@ struct gm20b_clk_dvfs_params {
|
||||
u32 vco_ctrl;
|
||||
};
|
||||
|
||||
static const struct gm20b_clk_dvfs_params gm20b_dvfs_params = {
|
||||
static const struct gm20b_clk_dvfs_params gm20b_b1_dvfs_params = {
|
||||
.coeff_slope = -165230,
|
||||
.coeff_offs = 214007,
|
||||
.vco_ctrl = 0x7 << 3,
|
||||
};
|
||||
|
||||
static const struct gm20b_clk_dvfs_params gm20b_c1_dvfs_params = {
|
||||
.coeff_slope = 0,
|
||||
.coeff_offs = 0,
|
||||
.vco_ctrl = 0x7 << 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* base.n is now the *integer* part of the N factor.
|
||||
* sdm_din contains n's decimal part.
|
||||
@@ -358,7 +364,7 @@ gm20b_pllg_disable(struct gm20b_clk *clk)
|
||||
}
|
||||
|
||||
static int
|
||||
gm20b_pllg_program_mnp(struct gm20b_clk *clk, const struct gk20a_pll *pll)
|
||||
gm20b_pllg_program_mnp(struct gm20b_clk *clk, const struct gk20a_pll *pll, bool pll_c1)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &clk->base.base.subdev;
|
||||
struct nvkm_device *device = subdev->device;
|
||||
@@ -396,7 +402,7 @@ gm20b_pllg_program_mnp(struct gm20b_clk *clk, const struct gk20a_pll *pll)
|
||||
* the case, calculate and program an interim PL that will allow
|
||||
* us to respect that rule.
|
||||
*/
|
||||
if ((old & new) == 0) {
|
||||
if ((old & new) == 0 && !pll_c1) {
|
||||
cur_pll.base.pl = min(old | BIT(ffs(new) - 1),
|
||||
new | BIT(ffs(old) - 1));
|
||||
gk20a_pllg_write_mnp(&clk->base, &cur_pll.base);
|
||||
@@ -431,7 +437,7 @@ gm20b_pllg_program_mnp(struct gm20b_clk *clk, const struct gk20a_pll *pll)
|
||||
}
|
||||
|
||||
static int
|
||||
gm20b_pllg_program_mnp_slide(struct gm20b_clk *clk, const struct gk20a_pll *pll)
|
||||
gm20b_pllg_program_mnp_slide(struct gm20b_clk *clk, const struct gk20a_pll *pll, bool pll_c1)
|
||||
{
|
||||
struct gk20a_pll cur_pll;
|
||||
int ret;
|
||||
@@ -453,7 +459,7 @@ gm20b_pllg_program_mnp_slide(struct gm20b_clk *clk, const struct gk20a_pll *pll)
|
||||
/* program MNP with the new clock parameters and new NDIV_LO */
|
||||
cur_pll = *pll;
|
||||
cur_pll.n = gk20a_pllg_n_lo(&clk->base, &cur_pll);
|
||||
ret = gm20b_pllg_program_mnp(clk, &cur_pll);
|
||||
ret = gm20b_pllg_program_mnp(clk, &cur_pll, pll_c1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -611,7 +617,7 @@ gm20b_clk_prog(struct nvkm_clk *base)
|
||||
pll_safe = clk->new_pll;
|
||||
|
||||
gm20b_dvfs_calc_safe_pll(clk, &pll_safe);
|
||||
ret = gm20b_pllg_program_mnp_slide(clk, &pll_safe);
|
||||
ret = gm20b_pllg_program_mnp_slide(clk, &pll_safe, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -632,7 +638,73 @@ prog:
|
||||
clk->dvfs = clk->new_dvfs;
|
||||
clk->base.pll = clk->new_pll;
|
||||
|
||||
return gm20b_pllg_program_mnp_slide(clk, &clk->base.pll);
|
||||
return gm20b_pllg_program_mnp_slide(clk, &clk->base.pll, false);
|
||||
}
|
||||
|
||||
static int
|
||||
gm20b_b01_clk_prog(struct nvkm_clk *base)
|
||||
{
|
||||
struct gm20b_clk *clk = gm20b_clk(base);
|
||||
u32 cur_freq;
|
||||
int ret;
|
||||
|
||||
/* No change in DVFS settings? */
|
||||
if (clk->uv == clk->new_uv)
|
||||
goto prog;
|
||||
|
||||
/*
|
||||
* Interim step for changing DVFS detection settings: low enough
|
||||
* frequency to be safe at DVFS coeff = 0.
|
||||
*
|
||||
* 1. If voltage is increasing:
|
||||
* - safe frequency target matches the lowest - old - frequency
|
||||
* - DVFS settings are still old
|
||||
* - Voltage already increased to new level by volt, but maximum
|
||||
* detection limit assures PLL output remains under F/V curve
|
||||
*
|
||||
* 2. If voltage is decreasing:
|
||||
* - safe frequency target matches the lowest - new - frequency
|
||||
* - DVFS settings are still old
|
||||
* - Voltage is also old, it will be lowered by volt afterwards
|
||||
*
|
||||
* Interim step can be skipped if old frequency is below safe minimum,
|
||||
* i.e., it is low enough to be safe at any voltage in operating range
|
||||
* with zero DVFS coefficient.
|
||||
*/
|
||||
cur_freq = nvkm_clk_read(&clk->base.base, nv_clk_src_gpc);
|
||||
if (cur_freq > clk->safe_fmax_vmin) {
|
||||
struct gk20a_pll pll_safe;
|
||||
|
||||
if (clk->uv < clk->new_uv)
|
||||
/* voltage will raise: safe frequency is current one */
|
||||
pll_safe = clk->base.pll;
|
||||
else
|
||||
/* voltage will drop: safe frequency is new one */
|
||||
pll_safe = clk->new_pll;
|
||||
|
||||
gm20b_dvfs_calc_safe_pll(clk, &pll_safe);
|
||||
ret = gm20b_pllg_program_mnp_slide(clk, &pll_safe, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* DVFS detection settings transition:
|
||||
* - Set DVFS coefficient zero
|
||||
* - Set calibration level to new voltage
|
||||
* - Set DVFS coefficient to match new voltage
|
||||
*/
|
||||
gm20b_dvfs_program_coeff(clk, 0);
|
||||
gm20b_dvfs_program_ext_cal(clk, clk->new_dvfs.dfs_ext_cal);
|
||||
gm20b_dvfs_program_coeff(clk, clk->new_dvfs.dfs_coeff);
|
||||
gm20b_dvfs_program_dfs_detection(clk, &clk->new_dvfs);
|
||||
|
||||
prog:
|
||||
clk->uv = clk->new_uv;
|
||||
clk->dvfs = clk->new_dvfs;
|
||||
clk->base.pll = clk->new_pll;
|
||||
|
||||
return gm20b_pllg_program_mnp_slide(clk, &clk->base.pll, true);
|
||||
}
|
||||
|
||||
static struct nvkm_pstate
|
||||
@@ -717,6 +789,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)
|
||||
{
|
||||
@@ -805,8 +983,85 @@ calibrated:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gm20b_b01_clk_init_dvfs(struct gm20b_clk *clk)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &clk->base.base.subdev;
|
||||
struct nvkm_device *device = subdev->device;
|
||||
bool fused = clk->uvdet_offs && clk->uvdet_slope;
|
||||
static const s32 ADC_SLOPE_UV = 10000; /* default ADC detection slope */
|
||||
u32 data;
|
||||
int ret;
|
||||
|
||||
/* Enable NA DVFS */
|
||||
nvkm_mask(device, GPCPLL_DVFS1, GPCPLL_DVFS1_EN_DFS_BIT,
|
||||
GPCPLL_DVFS1_EN_DFS_BIT);
|
||||
|
||||
/* Set VCO_CTRL */
|
||||
if (clk->dvfs_params->vco_ctrl)
|
||||
nvkm_mask(device, GPCPLL_CFG3, GPCPLL_CFG3_VCO_CTRL_MASK,
|
||||
clk->dvfs_params->vco_ctrl << GPCPLL_CFG3_VCO_CTRL_SHIFT);
|
||||
|
||||
if (fused) {
|
||||
/* Start internal calibration, but ignore results */
|
||||
nvkm_mask(device, GPCPLL_DVFS1, GPCPLL_DVFS1_EN_DFS_CAL_BIT,
|
||||
GPCPLL_DVFS1_EN_DFS_CAL_BIT);
|
||||
|
||||
/* got uvdev parameters from fuse, skip calibration */
|
||||
goto calibrated;
|
||||
}
|
||||
|
||||
/*
|
||||
* If calibration parameters are not fused, start internal calibration,
|
||||
* wait for completion, and use results along with default slope to
|
||||
* calculate ADC offset during boot.
|
||||
*/
|
||||
nvkm_mask(device, GPCPLL_DVFS1, GPCPLL_DVFS1_EN_DFS_CAL_BIT,
|
||||
GPCPLL_DVFS1_EN_DFS_CAL_BIT);
|
||||
|
||||
/*
|
||||
* C1 PLL revision must be enabled to read internal calibration results.
|
||||
*/
|
||||
nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 1);
|
||||
|
||||
/* Wait for internal calibration done (spec < 2us). */
|
||||
ret = nvkm_wait_usec(device, 10, GPCPLL_DVFS1,
|
||||
GPCPLL_DVFS1_DFS_CAL_DONE_BIT,
|
||||
GPCPLL_DVFS1_DFS_CAL_DONE_BIT);
|
||||
if (ret < 0) {
|
||||
nvkm_error(subdev, "GPCPLL calibration timeout\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
data = nvkm_rd32(device, GPCPLL_CFG3) >>
|
||||
GPCPLL_CFG3_PLL_DFS_TESTOUT_SHIFT;
|
||||
data &= MASK(GPCPLL_CFG3_PLL_DFS_TESTOUT_WIDTH);
|
||||
|
||||
/*
|
||||
* Disable C1 PLL revision after reading calibration results.
|
||||
*/
|
||||
nvkm_mask(device, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0);
|
||||
|
||||
clk->uvdet_slope = ADC_SLOPE_UV;
|
||||
clk->uvdet_offs = ((s32)clk->uv) - data * ADC_SLOPE_UV;
|
||||
|
||||
nvkm_debug(subdev, "calibrated DVFS parameters: offs %d, slope %d\n",
|
||||
clk->uvdet_offs, clk->uvdet_slope);
|
||||
|
||||
calibrated:
|
||||
/* Compute and apply initial DVFS parameters */
|
||||
gm20b_dvfs_calc_det_coeff(clk, clk->uv, &clk->dvfs);
|
||||
gm20b_dvfs_program_coeff(clk, 0);
|
||||
gm20b_dvfs_program_ext_cal(clk, clk->dvfs.dfs_ext_cal);
|
||||
gm20b_dvfs_program_coeff(clk, clk->dvfs.dfs_coeff);
|
||||
gm20b_dvfs_program_dfs_detection(clk, &clk->new_dvfs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Forward declaration to detect speedo >=1 in gm20b_clk_init() */
|
||||
static const struct nvkm_clk_func gm20b_clk;
|
||||
static const struct nvkm_clk_func gm20b_b01_clk;
|
||||
|
||||
static int
|
||||
gm20b_clk_init(struct nvkm_clk *base)
|
||||
@@ -860,6 +1115,17 @@ gm20b_clk_init(struct nvkm_clk *base)
|
||||
ret = gm20b_clk_init_dvfs(_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (clk->base.func == &gm20b_b01_clk) {
|
||||
struct gm20b_clk *_clk = gm20b_clk(base);
|
||||
struct nvkm_volt *volt = device->volt;
|
||||
|
||||
/* Get current voltage */
|
||||
_clk->uv = nvkm_volt_get(volt);
|
||||
|
||||
/* Initialize DVFS */
|
||||
ret = gm20b_b01_clk_init_dvfs(_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Start with lowest frequency */
|
||||
@@ -912,6 +1178,23 @@ gm20b_clk = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct nvkm_clk_func
|
||||
gm20b_b01_clk = {
|
||||
.init = gm20b_clk_init,
|
||||
.fini = gm20b_clk_fini,
|
||||
.read = gk20a_clk_read,
|
||||
.calc = gm20b_clk_calc,
|
||||
.prog = gm20b_b01_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)
|
||||
@@ -1058,7 +1341,67 @@ gm20b_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||
clk->base.pl_to_div = pl_to_div;
|
||||
clk->base.div_to_pl = div_to_pl;
|
||||
|
||||
clk->dvfs_params = &gm20b_dvfs_params;
|
||||
clk->dvfs_params = &gm20b_b1_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;
|
||||
}
|
||||
|
||||
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_c1_dvfs_params;
|
||||
|
||||
ret = gm20b_clk_init_fused_params(clk);
|
||||
/*
|
||||
|
||||
@@ -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,877 @@
|
||||
/*
|
||||
* Copyright (C) 2018 SwtcR <swtcr0@gmail.com>
|
||||
* Copyright (C) 2023-2026 Azkali <a.ffcc7@gmail.com>
|
||||
* Copyright (C) 2026 Thomas Makin <halorocker89@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_of.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))
|
||||
|
||||
#define DCS_SM_BRIGHTNESS_MAX 2047
|
||||
#define DCS_SM_DUTY_MAX 255
|
||||
#define DCS_SM_DUTY_DEFAULT 150
|
||||
|
||||
/* 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;
|
||||
bool dcs_backlight;
|
||||
|
||||
const struct drm_display_mode *mode;
|
||||
enum drm_panel_orientation orientation;
|
||||
|
||||
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,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
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, 0, { 0x00 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
|
||||
// Set color mode to basic (natural). Stock is Saturated (0x00). (Reset value is 0x20).
|
||||
{ MIPI_DCS_PRIV_SM_SET_COLOR_MODE, 1, { DCS_SM_COLOR_MODE_BASIC } },
|
||||
|
||||
// Enable backlight and smooth PWM.
|
||||
{ MIPI_DCS_WRITE_CONTROL_DISPLAY, 1, { DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL | DCS_CONTROL_DISPLAY_DIMMING_CTRL } },
|
||||
|
||||
// Unlock Level 2 registers.
|
||||
{ MIPI_DCS_PRIV_SM_SET_REGS_LOCK, 4, { 0x5A, 0x5A, 0x5A, 0x5A } },
|
||||
|
||||
// Set registers offset and set PWM transition to 6 frames (100ms).
|
||||
{ MIPI_DCS_PRIV_SM_SET_REG_OFFSET, 1, { 0x07 } },
|
||||
{ MIPI_DCS_PRIV_SM_SET_ELVSS, 1, { 0x06 } },
|
||||
|
||||
// Relock Level 2 registers.
|
||||
{ MIPI_DCS_PRIV_SM_SET_REGS_LOCK, 4, { 0x5A, 0x5A, 0xA5, 0xA5 } },
|
||||
|
||||
// MIPI_DCS_SET_BRIGHTNESS 0000: 0%. 07FF: 100%.
|
||||
{ MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 2, { 0x00, 0x00 } },
|
||||
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_SET_DISPLAY_ON, 0, { 0x00 } },
|
||||
{
|
||||
0xFF,
|
||||
20,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
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 } },
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_AUO_A062TAN01[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
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 } },
|
||||
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_SAM_AMS699VC01[] = {
|
||||
{ MIPI_DCS_SET_DISPLAY_OFF, 0, { 0x00 } },
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 0, { 0x00 } },
|
||||
{
|
||||
0xFF,
|
||||
120,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
static inline struct nx_panel *to_nx_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct nx_panel, base);
|
||||
}
|
||||
|
||||
static u16 nx_dcs_brightness(struct backlight_device *bl)
|
||||
{
|
||||
if (backlight_is_blank(bl))
|
||||
return 0;
|
||||
|
||||
if (bl->props.brightness >= DCS_SM_DUTY_MAX)
|
||||
return DCS_SM_BRIGHTNESS_MAX;
|
||||
|
||||
return max(bl->props.brightness, 1) *
|
||||
(DCS_SM_BRIGHTNESS_MAX / DCS_SM_DUTY_MAX);
|
||||
}
|
||||
|
||||
static void nx_panel_detect(struct nx_panel *nx)
|
||||
{
|
||||
u8 id[3] = { 0 };
|
||||
int ret;
|
||||
nx->init_cmds = NULL;
|
||||
nx->suspend_cmds = NULL;
|
||||
|
||||
nx->display_id = 0;
|
||||
|
||||
ret = mipi_dsi_dcs_read(nx->dsi, MIPI_DCS_GET_DISPLAY_ID,
|
||||
id, sizeof(id));
|
||||
if (ret < 0) {
|
||||
dev_err(&nx->dsi->dev, "failed to read panel ID: %d\n", ret);
|
||||
} else {
|
||||
nx->display_id = (id[2] << 8) | id[0];
|
||||
dev_info_once(&nx->dsi->dev, "display ID[%d]: %02x %02x %02x\n",
|
||||
ret, id[0], id[1], id[2]);
|
||||
}
|
||||
|
||||
if ((nx->display_id & 0xFF) == PANEL_JDI_XXX062M)
|
||||
nx->display_id = PANEL_JDI_XXX062M;
|
||||
|
||||
if (of_machine_is_compatible("nintendo,aula"))
|
||||
nx->display_id = PANEL_SAM_AMS699VC01;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (nx->dcs_backlight) {
|
||||
u8 mode;
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_brightness_large(dsi,
|
||||
nx_dcs_brightness(nx->backlight));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set brightness: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_get_power_mode(dsi, &mode);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "failed to read power mode: %d\n", 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);
|
||||
|
||||
if (nx->dcs_backlight)
|
||||
mipi_dsi_dcs_set_display_off(nx->dsi);
|
||||
|
||||
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 + 1,
|
||||
.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 enum drm_panel_orientation nx_panel_get_orientation(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
|
||||
return nx->orientation;
|
||||
}
|
||||
|
||||
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,
|
||||
.get_orientation = nx_panel_get_orientation,
|
||||
};
|
||||
|
||||
static int nx_dcs_backlight_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct nx_panel *nx = bl_get_data(bl);
|
||||
|
||||
if (!nx->prepared)
|
||||
return 0;
|
||||
|
||||
return mipi_dsi_dcs_set_display_brightness_large(nx->dsi,
|
||||
nx_dcs_brightness(bl));
|
||||
}
|
||||
|
||||
static const struct backlight_ops nx_dcs_backlight_ops = {
|
||||
.update_status = nx_dcs_backlight_update_status,
|
||||
};
|
||||
|
||||
static int nx_panel_add(struct nx_panel *nx)
|
||||
{
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
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;
|
||||
} else {
|
||||
struct backlight_properties props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = DCS_SM_DUTY_DEFAULT,
|
||||
.max_brightness = DCS_SM_DUTY_MAX,
|
||||
};
|
||||
|
||||
nx->backlight = devm_backlight_device_register(dev, "backlight", dev, nx,
|
||||
&nx_dcs_backlight_ops,
|
||||
&props);
|
||||
if (IS_ERR(nx->backlight))
|
||||
return PTR_ERR(nx->backlight);
|
||||
|
||||
nx->dcs_backlight = true;
|
||||
}
|
||||
|
||||
ret = of_drm_get_panel_orientation(dev->of_node, &nx->orientation);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get orientation %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 && !nx->dcs_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");
|
||||
@@ -1378,6 +1378,7 @@ 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", },
|
||||
|
||||
+184
-44
@@ -25,6 +25,7 @@
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "dc.h"
|
||||
#include "drm.h"
|
||||
@@ -54,6 +55,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 +99,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 +142,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 +201,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 +219,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 +460,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 +668,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 +686,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 +694,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)
|
||||
@@ -1055,6 +1075,9 @@ static int tegra_dsi_init(struct host1x_client *client)
|
||||
&tegra_dsi_connector_helper_funcs);
|
||||
dsi->output.connector.dpms = DRM_MODE_DPMS_OFF;
|
||||
|
||||
drm_connector_set_orientation_from_panel(
|
||||
&dsi->output.connector, dsi->output.panel);
|
||||
|
||||
drm_simple_encoder_init(drm, &dsi->output.encoder,
|
||||
DRM_MODE_ENCODER_DSI);
|
||||
drm_encoder_helper_add(&dsi->output.encoder,
|
||||
@@ -1069,7 +1092,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;
|
||||
@@ -1323,6 +1346,39 @@ static void tegra_dsi_writesl(struct tegra_dsi *dsi, unsigned long offset,
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t tegra_dsi_video_transfer(struct tegra_dsi *dsi,
|
||||
const struct mipi_dsi_packet *packet)
|
||||
{
|
||||
const u8 *header = packet->header;
|
||||
u32 host_control, value;
|
||||
|
||||
host_control = tegra_dsi_readl(dsi, DSI_HOST_CONTROL);
|
||||
|
||||
value = DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_TX_TRIG_SOL |
|
||||
DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
|
||||
tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
|
||||
|
||||
value = DSI_VIDEO_MODE_CMD_PKT_ENABLE | DSI_VIDEO_MODE_LINE_TYPE(4);
|
||||
tegra_dsi_writel(dsi, value, DSI_VIDEO_MODE_CONTROL);
|
||||
|
||||
value = header[2] << 16 | header[1] << 8 | header[0];
|
||||
tegra_dsi_writel(dsi, value, DSI_WR_DATA);
|
||||
|
||||
if (packet->payload_length > 0)
|
||||
tegra_dsi_writesl(dsi, DSI_WR_DATA, packet->payload,
|
||||
packet->payload_length);
|
||||
|
||||
if (dsi->output.encoder.crtc) {
|
||||
drm_crtc_wait_one_vblank(dsi->output.encoder.crtc);
|
||||
drm_crtc_wait_one_vblank(dsi->output.encoder.crtc);
|
||||
}
|
||||
|
||||
tegra_dsi_writel(dsi, 0, DSI_VIDEO_MODE_CONTROL);
|
||||
tegra_dsi_writel(dsi, host_control, DSI_HOST_CONTROL);
|
||||
|
||||
return packet->size;
|
||||
}
|
||||
|
||||
static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host,
|
||||
const struct mipi_dsi_msg *msg)
|
||||
{
|
||||
@@ -1343,14 +1399,16 @@ static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host,
|
||||
if (packet.size > dsi->video_fifo_depth * 4)
|
||||
return -ENOSPC;
|
||||
|
||||
/* reset underflow/overflow flags */
|
||||
value = tegra_dsi_readl(dsi, DSI_STATUS);
|
||||
if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) {
|
||||
value = DSI_HOST_CONTROL_FIFO_RESET;
|
||||
tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
|
||||
usleep_range(10, 20);
|
||||
if (tegra_dsi_readl(dsi, DSI_CONTROL) & DSI_CONTROL_VIDEO_ENABLE) {
|
||||
if (msg->rx_buf && msg->rx_len > 0)
|
||||
return -EBUSY;
|
||||
|
||||
return tegra_dsi_video_transfer(dsi, &packet);
|
||||
}
|
||||
|
||||
tegra_dsi_writel(dsi, DSI_HOST_CONTROL_FIFO_RESET, DSI_HOST_CONTROL);
|
||||
usleep_range(10, 20);
|
||||
|
||||
value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
|
||||
value |= DSI_POWER_CONTROL_ENABLE;
|
||||
tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
|
||||
@@ -1633,6 +1691,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 +1752,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);
|
||||
|
||||
@@ -102,6 +102,8 @@
|
||||
#define DSI_PAD_CONTROL_CD 0x4c
|
||||
#define DSI_PAD_CD_STATUS 0x4d
|
||||
#define DSI_VIDEO_MODE_CONTROL 0x4e
|
||||
#define DSI_VIDEO_MODE_CMD_PKT_ENABLE (1 << 0)
|
||||
#define DSI_VIDEO_MODE_LINE_TYPE(x) (((x) & 0x7) << 1)
|
||||
#define DSI_PAD_CONTROL_1 0x4f
|
||||
#define DSI_PAD_CONTROL_2 0x50
|
||||
#define DSI_PAD_OUT_CLK(x) (((x) & 0x7) << 0)
|
||||
@@ -130,6 +132,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
|
||||
*/
|
||||
|
||||
@@ -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[] = {
|
||||
{
|
||||
@@ -3533,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,
|
||||
@@ -3656,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 },
|
||||
|
||||
@@ -135,6 +135,16 @@ config AS73211
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called as73211.
|
||||
|
||||
config BH1730
|
||||
tristate "ROHM BH1730 ambient light sensor"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to build support for the ROHM BH1730FVC ambient light
|
||||
sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called bh1730.
|
||||
|
||||
config BH1745
|
||||
tristate "ROHM BH1745 colour sensor"
|
||||
depends on I2C
|
||||
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_APDS9300) += apds9300.o
|
||||
obj-$(CONFIG_APDS9306) += apds9306.o
|
||||
obj-$(CONFIG_APDS9960) += apds9960.o
|
||||
obj-$(CONFIG_AS73211) += as73211.o
|
||||
obj-$(CONFIG_BH1730) += bh1730.o
|
||||
obj-$(CONFIG_BH1745) += bh1745.o
|
||||
obj-$(CONFIG_BH1750) += bh1750.o
|
||||
obj-$(CONFIG_BH1780) += bh1780.o
|
||||
|
||||
@@ -0,0 +1,575 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ROHM BH1730 ambient light sensor driver
|
||||
*
|
||||
* Copyright (c) 2021 CTCaer <ctcaer@gmail.com>
|
||||
*
|
||||
* Based on previous iio BH1730FVC drivers from:
|
||||
* Copyright (c) 2018 Google, Inc.
|
||||
* Author: Pierre Bourdon <delroth@google.com>
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics. All rights reserved.
|
||||
* Author: Won Huh <won.huh@samsung.com>
|
||||
*
|
||||
* Data sheets:
|
||||
* http://www.rohm.com/web/global/datasheet/BH1730FVC/bh1730fvc-e
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define BH1730_NAME "bh1730fvc"
|
||||
|
||||
#define BH1730_CMD_BIT BIT(7)
|
||||
|
||||
#define BH1730_REG_CONTROL 0x00
|
||||
#define BH1730_REG_TIMING 0x01
|
||||
#define BH1730_REG_GAIN 0x07
|
||||
#define BH1730_REG_DATA0LOW 0x14
|
||||
#define BH1730_REG_DATA1LOW 0x16
|
||||
|
||||
#define BH1730_CONTROL_POWER BIT(0)
|
||||
#define BH1730_CONTROL_ADC_EN BIT(1)
|
||||
|
||||
#define BH1730_ADC_CALC_DELAY_US 2000 /* BH1730_INTERNAL_CLOCK_MS * 714 */
|
||||
#define BH1730_ITIME_TO_US 2700 /* BH1730_INTERNAL_CLOCK_MS * 964 */
|
||||
|
||||
#define BH1730_DEFAULT_INTEG_CYCLE 38
|
||||
#define BH1730_DEFAULT_ITIME_MS 100
|
||||
|
||||
#define BH1730_POWER_ON_DELAY_US 10000
|
||||
|
||||
#define BH1730_MAX_MEASURED_LUX 100000
|
||||
|
||||
enum bh1730_gain {
|
||||
BH1730_GAIN_1X = 0,
|
||||
BH1730_GAIN_2X,
|
||||
BH1730_GAIN_64X,
|
||||
BH1730_GAIN_128X,
|
||||
};
|
||||
|
||||
struct gain_coeff_t {
|
||||
u32 cl;
|
||||
u32 fl;
|
||||
};
|
||||
|
||||
struct opt_win_coeff_t {
|
||||
u32 rc;
|
||||
u32 cv;
|
||||
u32 ci;
|
||||
};
|
||||
|
||||
struct lux_cal_data_t {
|
||||
const struct gain_coeff_t *gain_coeff;
|
||||
const struct opt_win_coeff_t *opt_win_coeff;
|
||||
u32 opt_win_coeff_count;
|
||||
u32 itime_cycle;
|
||||
u32 mul;
|
||||
};
|
||||
|
||||
/*
|
||||
* No optical window or optical window that has flat transmittance
|
||||
* from visible light to infrared light.
|
||||
*/
|
||||
static const struct opt_win_coeff_t def_lux_coeff[] = {
|
||||
{ 260, 1290, 2733 },
|
||||
{ 550, 795, 859 },
|
||||
{ 1090, 510, 345 },
|
||||
{ 2130, 276, 130 }
|
||||
};
|
||||
|
||||
static const struct gain_coeff_t def_gain_coeff[] = {
|
||||
{ 3000, -1 }, /* 1x */
|
||||
{ 2000, 9800 }, /* 2x */
|
||||
{ 15, 60000 }, /* 64x */
|
||||
{ 0, 1300 } /* 128x */
|
||||
};
|
||||
|
||||
static const struct lux_cal_data_t def_lux_data = {
|
||||
.gain_coeff = def_gain_coeff,
|
||||
.opt_win_coeff = def_lux_coeff,
|
||||
.opt_win_coeff_count = ARRAY_SIZE(def_lux_coeff),
|
||||
.itime_cycle = BH1730_DEFAULT_INTEG_CYCLE,
|
||||
.mul = 1000
|
||||
};
|
||||
|
||||
struct bh1730_data {
|
||||
struct i2c_client *client;
|
||||
struct lux_cal_data_t cal;
|
||||
struct regulator *reg_vdd;
|
||||
struct regulator *reg_vid;
|
||||
enum bh1730_gain gain;
|
||||
bool powered;
|
||||
u32 itime_us;
|
||||
u32 tmt_us;
|
||||
};
|
||||
|
||||
static int bh1730_read_word(struct bh1730_data *bh1730, u8 reg)
|
||||
{
|
||||
int ret = i2c_smbus_read_word_data(bh1730->client,
|
||||
BH1730_CMD_BIT | reg);
|
||||
if (ret < 0)
|
||||
dev_err(&bh1730->client->dev,
|
||||
"i2c read failed error %d, register %01x\n",
|
||||
ret, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bh1730_write(struct bh1730_data *bh1730, u8 reg, u8 val)
|
||||
{
|
||||
int ret = i2c_smbus_write_byte_data(bh1730->client,
|
||||
BH1730_CMD_BIT | reg,
|
||||
val);
|
||||
if (ret < 0)
|
||||
dev_err(&bh1730->client->dev,
|
||||
"i2c write failed error %d, register %01x\n",
|
||||
ret, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bh1730_gain_multiplier(struct bh1730_data *bh1730)
|
||||
{
|
||||
switch (bh1730->gain) {
|
||||
case BH1730_GAIN_1X:
|
||||
return 1;
|
||||
case BH1730_GAIN_2X:
|
||||
return 2;
|
||||
case BH1730_GAIN_64X:
|
||||
return 64;
|
||||
case BH1730_GAIN_128X:
|
||||
return 128;
|
||||
}
|
||||
|
||||
dev_warn(&bh1730->client->dev,
|
||||
"invalid gain multiplier settings: %d\n", bh1730->gain);
|
||||
bh1730->gain = BH1730_GAIN_1X;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bh1730_set_gain(struct bh1730_data *bh1730, enum bh1730_gain gain)
|
||||
{
|
||||
int ret = bh1730_write(bh1730, BH1730_REG_GAIN, gain);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bh1730->gain = gain;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bh1730_set_integration_time_cycle(struct bh1730_data *bh1730,
|
||||
u32 cycle)
|
||||
{
|
||||
int ret, itime;
|
||||
|
||||
itime = 256 - cycle;
|
||||
|
||||
/* ITIME == 0 is reserved for manual integration mode. */
|
||||
if (itime <= 0 || itime > 255) {
|
||||
dev_warn(&bh1730->client->dev,
|
||||
"integration time out of range: %d cycles\n", cycle);
|
||||
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
ret = bh1730_write(bh1730, BH1730_REG_TIMING, itime);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
bh1730->itime_us = BH1730_ITIME_TO_US * cycle;
|
||||
bh1730->tmt_us = bh1730->itime_us + BH1730_ADC_CALC_DELAY_US;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bh1730_adjust_gain(struct bh1730_data *bh1730)
|
||||
{
|
||||
int visible, ir, highest, gain, ret;
|
||||
|
||||
visible = bh1730_read_word(bh1730, BH1730_REG_DATA0LOW);
|
||||
if (visible < 0)
|
||||
return visible;
|
||||
|
||||
ir = bh1730_read_word(bh1730, BH1730_REG_DATA1LOW);
|
||||
if (ir < 0)
|
||||
return ir;
|
||||
|
||||
highest = max(visible, ir);
|
||||
|
||||
/* Adjust gain based on sensitivity calibration */
|
||||
gain = bh1730->gain;
|
||||
if (highest > bh1730->cal.gain_coeff[gain].fl &&
|
||||
gain != BH1730_GAIN_1X) {
|
||||
gain--; /* Decrease sensitivity */
|
||||
} else if (highest < bh1730->cal.gain_coeff[gain].cl &&
|
||||
gain != BH1730_GAIN_128X) {
|
||||
gain++; /* Increase sensitivity */
|
||||
}
|
||||
|
||||
if (gain != bh1730->gain) {
|
||||
ret = bh1730_set_gain(bh1730, gain);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
fsleep(bh1730->tmt_us);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bh1730_get_lux(struct bh1730_data *bh1730)
|
||||
{
|
||||
const struct opt_win_coeff_t *opt_win_coeff;
|
||||
int i, visible, ir;
|
||||
u64 lux = 0;
|
||||
|
||||
visible = bh1730_read_word(bh1730, BH1730_REG_DATA0LOW);
|
||||
|
||||
/* If visible is 0, skip calculations */
|
||||
if (visible <= 0)
|
||||
return visible;
|
||||
|
||||
ir = bh1730_read_word(bh1730, BH1730_REG_DATA1LOW);
|
||||
if (ir < 0)
|
||||
return ir;
|
||||
|
||||
/* Calibrate based on optical window */
|
||||
for (i = 0; i < bh1730->cal.opt_win_coeff_count; i++) {
|
||||
opt_win_coeff = &bh1730->cal.opt_win_coeff[i];
|
||||
if (1000 * ir / visible < opt_win_coeff->rc) {
|
||||
lux = ((u64)opt_win_coeff->cv * visible) -
|
||||
(opt_win_coeff->ci * ir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate lux */
|
||||
lux *= BH1730_DEFAULT_ITIME_MS;
|
||||
lux = div_u64(lux, bh1730_gain_multiplier(bh1730) * bh1730->itime_us);
|
||||
lux = div_u64(lux * bh1730->cal.mul, 1000);
|
||||
|
||||
if (lux > BH1730_MAX_MEASURED_LUX)
|
||||
lux = BH1730_MAX_MEASURED_LUX;
|
||||
|
||||
return (int)lux;
|
||||
}
|
||||
|
||||
static int bh1730_power_ctrl(struct bh1730_data *bh1730, bool enable)
|
||||
{
|
||||
struct device *dev = &bh1730->client->dev;
|
||||
int ret;
|
||||
|
||||
if (bh1730->powered == enable)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
ret = regulator_enable(bh1730->reg_vdd);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable vdd: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_enable(bh1730->reg_vid);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable vid: %d\n", ret);
|
||||
regulator_disable(bh1730->reg_vdd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fsleep(BH1730_POWER_ON_DELAY_US);
|
||||
} else {
|
||||
regulator_disable(bh1730->reg_vid);
|
||||
regulator_disable(bh1730->reg_vdd);
|
||||
}
|
||||
|
||||
bh1730->powered = enable;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bh1730_power_on(struct bh1730_data *bh1730)
|
||||
{
|
||||
int ret = bh1730_power_ctrl(bh1730, true);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return bh1730_write(bh1730, BH1730_REG_CONTROL,
|
||||
BH1730_CONTROL_POWER | BH1730_CONTROL_ADC_EN);
|
||||
}
|
||||
|
||||
static int bh1730_init_config(struct bh1730_data *bh1730)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bh1730_set_gain(bh1730, BH1730_GAIN_64X);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return bh1730_set_integration_time_cycle(bh1730,
|
||||
bh1730->cal.itime_cycle);
|
||||
}
|
||||
|
||||
static int bh1730_power_off(struct bh1730_data *bh1730)
|
||||
{
|
||||
int ret = bh1730_write(bh1730, BH1730_REG_CONTROL, 0);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return bh1730_power_ctrl(bh1730, false);
|
||||
}
|
||||
|
||||
static int bh1730_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct bh1730_data *bh1730 = iio_priv(indio_dev);
|
||||
int data_reg, ret;
|
||||
|
||||
ret = bh1730_adjust_gain(bh1730);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_PROCESSED:
|
||||
ret = bh1730_get_lux(bh1730);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
switch (chan->channel2) {
|
||||
case IIO_MOD_LIGHT_CLEAR:
|
||||
data_reg = BH1730_REG_DATA0LOW;
|
||||
break;
|
||||
case IIO_MOD_LIGHT_IR:
|
||||
data_reg = BH1730_REG_DATA1LOW;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = bh1730_read_word(bh1730, data_reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = ret * 1000 / bh1730_gain_multiplier(bh1730);
|
||||
*val = ret / 1000;
|
||||
*val2 = (ret % 1000) * 1000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_CHAN_INFO_INT_TIME:
|
||||
*val = 0;
|
||||
*val2 = bh1730->itime_us;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bh1730_parse_dt(struct bh1730_data *bh1730)
|
||||
{
|
||||
struct device *dev = &bh1730->client->dev;
|
||||
struct device_node *dn = dev->of_node;
|
||||
u32 *opt_win_coeff = NULL;
|
||||
u32 *gain_coeff = NULL;
|
||||
int opt_win_coeff_count, gain_coeff_count;
|
||||
u32 cycle = 0, mul = 0;
|
||||
|
||||
bh1730->cal = def_lux_data;
|
||||
|
||||
bh1730->reg_vdd = devm_regulator_get(dev, "als-vdd");
|
||||
if (IS_ERR(bh1730->reg_vdd))
|
||||
return dev_err_probe(dev, PTR_ERR(bh1730->reg_vdd),
|
||||
"failed to get als-vdd\n");
|
||||
|
||||
bh1730->reg_vid = devm_regulator_get(dev, "als-vid");
|
||||
if (IS_ERR(bh1730->reg_vid))
|
||||
return dev_err_probe(dev, PTR_ERR(bh1730->reg_vid),
|
||||
"failed to get als-vid\n");
|
||||
|
||||
if (!dn)
|
||||
goto out;
|
||||
|
||||
/* Get calibration */
|
||||
if (of_property_read_u32(dn, "rohm,integration-cycle", &cycle) ||
|
||||
of_property_read_u32(dn, "rohm,lux-multiplier", &mul) ||
|
||||
!cycle || !mul)
|
||||
goto out;
|
||||
|
||||
/* Get optical window coefficients */
|
||||
opt_win_coeff_count = of_property_count_u32_elems(dn, "rohm,opt-win-coeff");
|
||||
if (opt_win_coeff_count > 0 &&
|
||||
!(opt_win_coeff_count % (sizeof(struct opt_win_coeff_t) / sizeof(u32)))) {
|
||||
opt_win_coeff = devm_kcalloc(dev, opt_win_coeff_count,
|
||||
sizeof(u32), GFP_KERNEL);
|
||||
if (!opt_win_coeff)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_property_read_u32_array(dn, "rohm,opt-win-coeff",
|
||||
opt_win_coeff, opt_win_coeff_count))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get gain sensitivity coefficients, 2 for each gain supported */
|
||||
gain_coeff_count = of_property_count_u32_elems(dn, "rohm,gain-coeff");
|
||||
if (gain_coeff_count == 8) {
|
||||
gain_coeff = devm_kcalloc(dev, gain_coeff_count,
|
||||
sizeof(u32), GFP_KERNEL);
|
||||
if (!gain_coeff)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_property_read_u32_array(dn, "rohm,gain-coeff",
|
||||
gain_coeff, gain_coeff_count))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opt_win_coeff) {
|
||||
bh1730->cal.opt_win_coeff =
|
||||
(const struct opt_win_coeff_t *)opt_win_coeff;
|
||||
bh1730->cal.opt_win_coeff_count = opt_win_coeff_count /
|
||||
(sizeof(struct opt_win_coeff_t) / sizeof(u32));
|
||||
}
|
||||
|
||||
if (gain_coeff)
|
||||
bh1730->cal.gain_coeff = (const struct gain_coeff_t *)gain_coeff;
|
||||
|
||||
bh1730->cal.itime_cycle = cycle;
|
||||
bh1730->cal.mul = mul;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
dev_info(dev, "using default calibration\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_info bh1730_info = {
|
||||
.read_raw = bh1730_read_raw,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec bh1730_channels[] = {
|
||||
{
|
||||
.type = IIO_LIGHT,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
|
||||
BIT(IIO_CHAN_INFO_INT_TIME),
|
||||
},
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
.modified = 1,
|
||||
.channel2 = IIO_MOD_LIGHT_CLEAR,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
},
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
.modified = 1,
|
||||
.channel2 = IIO_MOD_LIGHT_IR,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
},
|
||||
};
|
||||
|
||||
static void bh1730_power_off_action(void *data)
|
||||
{
|
||||
bh1730_power_off(data);
|
||||
}
|
||||
|
||||
static int bh1730_probe(struct i2c_client *client)
|
||||
{
|
||||
struct bh1730_data *bh1730;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1730));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
bh1730 = iio_priv(indio_dev);
|
||||
bh1730->client = client;
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
ret = bh1730_parse_dt(bh1730);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = bh1730_power_on(bh1730);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(&client->dev, bh1730_power_off_action,
|
||||
bh1730);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bh1730_init_config(bh1730);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
indio_dev->info = &bh1730_info;
|
||||
indio_dev->name = "bh1730";
|
||||
indio_dev->channels = bh1730_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(bh1730_channels);
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
return devm_iio_device_register(&client->dev, indio_dev);
|
||||
}
|
||||
|
||||
static int bh1730_suspend(struct device *dev)
|
||||
{
|
||||
struct bh1730_data *bh1730 = iio_priv(dev_get_drvdata(dev));
|
||||
|
||||
return bh1730_power_off(bh1730);
|
||||
}
|
||||
|
||||
static int bh1730_resume(struct device *dev)
|
||||
{
|
||||
struct bh1730_data *bh1730 = iio_priv(dev_get_drvdata(dev));
|
||||
int ret;
|
||||
|
||||
ret = bh1730_power_on(bh1730);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return bh1730_init_config(bh1730);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(bh1730_pm_ops, bh1730_suspend, bh1730_resume);
|
||||
|
||||
static const struct i2c_device_id bh1730_i2c_device_id[] = {
|
||||
{ BH1730_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bh1730_i2c_device_id);
|
||||
|
||||
static const struct of_device_id of_bh1730_match[] = {
|
||||
{ .compatible = "rohm,bh1730fvc" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_bh1730_match);
|
||||
|
||||
static struct i2c_driver bh1730_driver = {
|
||||
.probe = bh1730_probe,
|
||||
.driver = {
|
||||
.name = BH1730_NAME,
|
||||
.of_match_table = of_bh1730_match,
|
||||
.pm = pm_sleep_ptr(&bh1730_pm_ops),
|
||||
},
|
||||
.id_table = bh1730_i2c_device_id,
|
||||
};
|
||||
module_i2c_driver(bh1730_driver);
|
||||
|
||||
MODULE_AUTHOR("CTCaer <ctcaer@gmail.com>");
|
||||
MODULE_DESCRIPTION("ROHM BH1730FVC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -304,7 +304,7 @@ static int seesaw_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id seesaw_id_table[] = {
|
||||
{ SEESAW_DEVICE_NAME },
|
||||
{ .name = SEESAW_DEVICE_NAME },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, seesaw_id_table);
|
||||
|
||||
@@ -337,7 +337,7 @@ static void as5011_remove(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id as5011_id[] = {
|
||||
{ MODULE_DEVICE_ALIAS },
|
||||
{ .name = MODULE_DEVICE_ALIAS },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, as5011_id);
|
||||
|
||||
@@ -126,7 +126,7 @@ MODULE_DEVICE_TABLE(of, of_qwiic_match);
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static const struct i2c_device_id qwiic_id_table[] = {
|
||||
{ KBUILD_MODNAME },
|
||||
{ .name = KBUILD_MODNAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, qwiic_id_table);
|
||||
|
||||
@@ -842,8 +842,8 @@ static int adp5588_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume);
|
||||
|
||||
static const struct i2c_device_id adp5588_id[] = {
|
||||
{ "adp5588-keys" },
|
||||
{ "adp5587-keys" },
|
||||
{ .name = "adp5588-keys" },
|
||||
{ .name = "adp5587-keys" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adp5588_id);
|
||||
|
||||
@@ -651,13 +651,13 @@ static const struct of_device_id cap11xx_dt_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, cap11xx_dt_ids);
|
||||
|
||||
static const struct i2c_device_id cap11xx_i2c_ids[] = {
|
||||
{ "cap1106", (kernel_ulong_t)&cap1106_model },
|
||||
{ "cap1126", (kernel_ulong_t)&cap1126_model },
|
||||
{ "cap1188", (kernel_ulong_t)&cap1188_model },
|
||||
{ "cap1203", (kernel_ulong_t)&cap1203_model },
|
||||
{ "cap1206", (kernel_ulong_t)&cap1206_model },
|
||||
{ "cap1293", (kernel_ulong_t)&cap1293_model },
|
||||
{ "cap1298", (kernel_ulong_t)&cap1298_model },
|
||||
{ .name = "cap1106", .driver_data = (kernel_ulong_t)&cap1106_model },
|
||||
{ .name = "cap1126", .driver_data = (kernel_ulong_t)&cap1126_model },
|
||||
{ .name = "cap1188", .driver_data = (kernel_ulong_t)&cap1188_model },
|
||||
{ .name = "cap1203", .driver_data = (kernel_ulong_t)&cap1203_model },
|
||||
{ .name = "cap1206", .driver_data = (kernel_ulong_t)&cap1206_model },
|
||||
{ .name = "cap1293", .driver_data = (kernel_ulong_t)&cap1293_model },
|
||||
{ .name = "cap1298", .driver_data = (kernel_ulong_t)&cap1298_model },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids);
|
||||
|
||||
@@ -209,7 +209,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops,
|
||||
cypress_sf_suspend, cypress_sf_resume);
|
||||
|
||||
static const struct i2c_device_id cypress_sf_id_table[] = {
|
||||
{ CYPRESS_SF_DEV_NAME },
|
||||
{ .name = CYPRESS_SF_DEV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cypress_sf_id_table);
|
||||
|
||||
@@ -128,7 +128,7 @@ static int dir685_tk_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id dir685_tk_id[] = {
|
||||
{ "dir685tk" },
|
||||
{ .name = "dir685tk" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, dir685_tk_id);
|
||||
|
||||
@@ -788,7 +788,7 @@ static int lm8323_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
|
||||
|
||||
static const struct i2c_device_id lm8323_id[] = {
|
||||
{ "lm8323" },
|
||||
{ .name = "lm8323" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ static int lm8333_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm8333_id[] = {
|
||||
{ "lm8333" },
|
||||
{ .name = "lm8333" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm8333_id);
|
||||
|
||||
@@ -270,7 +270,7 @@ static int max7359_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
|
||||
|
||||
static const struct i2c_device_id max7359_ids[] = {
|
||||
{ "max7359" },
|
||||
{ .name = "max7359" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max7359_ids);
|
||||
|
||||
@@ -322,7 +322,7 @@ static int mpr_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
|
||||
|
||||
static const struct i2c_device_id mpr121_id[] = {
|
||||
{ "mpr121_touchkey" },
|
||||
{ .name = "mpr121_touchkey" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mpr121_id);
|
||||
|
||||
@@ -233,7 +233,7 @@ static int qt1070_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume);
|
||||
|
||||
static const struct i2c_device_id qt1070_id[] = {
|
||||
{ "qt1070" },
|
||||
{ .name = "qt1070" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, qt1070_id);
|
||||
|
||||
@@ -393,7 +393,7 @@ static int qt2160_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id qt2160_idtable[] = {
|
||||
{ "qt2160" },
|
||||
{ .name = "qt2160" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -354,7 +354,7 @@ static int tca8418_keypad_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tca8418_id[] = {
|
||||
{ "tca8418", 8418, },
|
||||
{ .name = "tca8418", .driver_data = 8418 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tca8418_id);
|
||||
|
||||
@@ -326,7 +326,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops,
|
||||
tm2_touchkey_suspend, tm2_touchkey_resume);
|
||||
|
||||
static const struct i2c_device_id tm2_touchkey_id_table[] = {
|
||||
{ TM2_TOUCHKEY_DEV_NAME },
|
||||
{ .name = TM2_TOUCHKEY_DEV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table);
|
||||
|
||||
@@ -282,6 +282,13 @@ config INPUT_MAX77693_HAPTIC
|
||||
To compile this driver as module, choose M here: the
|
||||
module will be called max77693-haptic.
|
||||
|
||||
config INPUT_MAX77620_ONOFF
|
||||
tristate "MAX77620 ONOFF support"
|
||||
depends on MFD_MAX77620
|
||||
help
|
||||
Support the ONOFF block of MAX77620 PMICs as an input device
|
||||
reporting power button status.
|
||||
|
||||
config INPUT_MAX8925_ONKEY
|
||||
tristate "MAX8925 ONKEY support"
|
||||
depends on MFD_MAX8925
|
||||
|
||||
@@ -55,6 +55,7 @@ obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
|
||||
obj-$(CONFIG_INPUT_MAX7360_ROTARY) += max7360-rotary.o
|
||||
obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o
|
||||
obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
|
||||
obj-$(CONFIG_INPUT_MAX77620_ONOFF) += max77620-onoff.o
|
||||
obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o
|
||||
obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o
|
||||
obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o
|
||||
|
||||
@@ -72,11 +72,11 @@ static int ad714x_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ad714x_id[] = {
|
||||
{ "ad7142_captouch" },
|
||||
{ "ad7143_captouch" },
|
||||
{ "ad7147_captouch" },
|
||||
{ "ad7147a_captouch" },
|
||||
{ "ad7148_captouch" },
|
||||
{ .name = "ad7142_captouch" },
|
||||
{ .name = "ad7143_captouch" },
|
||||
{ .name = "ad7147_captouch" },
|
||||
{ .name = "ad7147a_captouch" },
|
||||
{ .name = "ad7148_captouch" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad714x_id);
|
||||
|
||||
@@ -96,7 +96,7 @@ static int adxl34x_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id adxl34x_id[] = {
|
||||
{ "adxl34x" },
|
||||
{ .name = "adxl34x" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ static void apanel_shutdown(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id apanel_id[] = {
|
||||
{ "fujitsu_apanel" },
|
||||
{ .name = "fujitsu_apanel" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, apanel_id);
|
||||
|
||||
@@ -257,7 +257,7 @@ static const struct of_device_id atmel_captouch_of_id[] = {
|
||||
MODULE_DEVICE_TABLE(of, atmel_captouch_of_id);
|
||||
|
||||
static const struct i2c_device_id atmel_captouch_id[] = {
|
||||
{ "atmel_captouch" },
|
||||
{ .name = "atmel_captouch" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, atmel_captouch_id);
|
||||
|
||||
@@ -536,9 +536,9 @@ static int __maybe_unused bma150_resume(struct device *dev)
|
||||
static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
|
||||
|
||||
static const struct i2c_device_id bma150_id[] = {
|
||||
{ "bma150" },
|
||||
{ "smb380" },
|
||||
{ "bma023" },
|
||||
{ .name = "bma150" },
|
||||
{ .name = "smb380" },
|
||||
{ .name = "bma023" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ static const struct dev_pm_ops cma3000_i2c_pm_ops = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id cma3000_i2c_id[] = {
|
||||
{ "cma3000_d01" },
|
||||
{ .name = "cma3000_d01" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -1305,7 +1305,7 @@ MODULE_DEVICE_TABLE(of, da7280_of_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id da7280_i2c_id[] = {
|
||||
{ "da7280", },
|
||||
{ .name = "da7280" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da7280_i2c_id);
|
||||
|
||||
@@ -630,10 +630,10 @@ static int drv260x_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume);
|
||||
|
||||
static const struct i2c_device_id drv260x_id[] = {
|
||||
{ "drv2604" },
|
||||
{ "drv2604l" },
|
||||
{ "drv2605" },
|
||||
{ "drv2605l" },
|
||||
{ .name = "drv2604" },
|
||||
{ .name = "drv2604l" },
|
||||
{ .name = "drv2605" },
|
||||
{ .name = "drv2605l" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, drv260x_id);
|
||||
|
||||
@@ -281,7 +281,7 @@ static int drv2665_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume);
|
||||
|
||||
static const struct i2c_device_id drv2665_id[] = {
|
||||
{ "drv2665" },
|
||||
{ .name = "drv2665" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, drv2665_id);
|
||||
|
||||
@@ -458,7 +458,7 @@ static int drv2667_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
|
||||
|
||||
static const struct i2c_device_id drv2667_id[] = {
|
||||
{ "drv2667" },
|
||||
{ .name = "drv2667" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, drv2667_id);
|
||||
|
||||
@@ -525,7 +525,7 @@ static int kxtj9_resume(struct device *dev)
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
|
||||
|
||||
static const struct i2c_device_id kxtj9_id[] = {
|
||||
{ NAME },
|
||||
{ .name = NAME },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 Billy Laws
|
||||
* Copyright (C) 2020-2022 CTCaer
|
||||
*
|
||||
* Author:
|
||||
* Billy Laws <blaws05@gmail.com>
|
||||
* CTCaer <ctcaer@gmail.com>
|
||||
*
|
||||
* Description:
|
||||
* ONOFF driver for MAXIM 77620 charger/power-supply.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/max77620.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define ONOFF_IRQF 2
|
||||
#define ONOFF_IRQR 3
|
||||
|
||||
/* MAX77620 IRQ ONOFF interrupts */
|
||||
#define MAX77620_IRQ_ONOFF_MRWRN 0
|
||||
#define MAX77620_IRQ_ONOFF_EN0_1SEC 1
|
||||
#define MAX77620_IRQ_ONOFF_EN0_F 2
|
||||
#define MAX77620_IRQ_ONOFF_EN0_R 3
|
||||
#define MAX77620_IRQ_ONOFF_LID_F 4
|
||||
#define MAX77620_IRQ_ONOFF_LID_R 5
|
||||
#define MAX77620_IRQ_ONOFF_ACOK_F 6
|
||||
#define MAX77620_IRQ_ONOFF_ACOK_R 7
|
||||
|
||||
struct max77620_onoff {
|
||||
struct regmap *rmap;
|
||||
struct input_dev *input;
|
||||
int irq_f, irq_r;
|
||||
unsigned int code;
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
static const struct regmap_irq max77620_onoff_irqs[] = {
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_MRWRN, 0, MAX77620_IRQ_ONOFF_MRWRN_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_EN0_1SEC, 0, MAX77620_IRQ_ONOFF_EN0_1SEC_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_EN0_F, 0, MAX77620_IRQ_ONOFF_EN0_F_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_EN0_R, 0, MAX77620_IRQ_ONOFF_EN0_R_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_LID_F, 0, MAX77620_IRQ_ONOFF_LID_F_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_LID_R, 0, MAX77620_IRQ_ONOFF_LID_R_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_ACOK_F, 0, MAX77620_IRQ_ONOFF_ACOK_F_MASK),
|
||||
REGMAP_IRQ_REG(MAX77620_IRQ_ONOFF_ACOK_R, 0, MAX77620_IRQ_ONOFF_ACOK_R_MASK),
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip max77620_onoff_irq_chip = {
|
||||
.name = "max77620-onoff",
|
||||
.irqs = max77620_onoff_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max77620_onoff_irqs),
|
||||
.num_regs = 1,
|
||||
.irq_reg_stride = 1,
|
||||
.status_base = MAX77620_REG_ONOFFIRQ,
|
||||
.mask_base = MAX77620_REG_ONOFFIRQM,
|
||||
};
|
||||
|
||||
static irqreturn_t max77620_onoff_handler(int irq, void *data)
|
||||
{
|
||||
struct max77620_onoff *onoff = data;
|
||||
bool pressed = irq == onoff->irq_r;
|
||||
|
||||
/* Skip release report in suspended state */
|
||||
if (onoff->suspended && !pressed)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
input_report_key(onoff->input, onoff->code, pressed);
|
||||
input_sync(onoff->input);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int max77620_onoff_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max77620_onoff *onoff;
|
||||
struct device *dev, *parent;
|
||||
struct max77620_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device_node *np;
|
||||
unsigned int code;
|
||||
int irq, ret;
|
||||
|
||||
dev = &pdev->dev;
|
||||
parent = dev->parent;
|
||||
|
||||
onoff = devm_kzalloc(dev, sizeof(*onoff), GFP_KERNEL);
|
||||
if (!onoff)
|
||||
return -ENOMEM;
|
||||
|
||||
onoff->rmap = chip->rmap;
|
||||
|
||||
ret = regmap_read(onoff->rmap, MAX77620_REG_ONOFFIRQ, &code);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to clear onoff irq: %d\n", ret);
|
||||
|
||||
np = of_get_child_by_name(pdev->dev.parent->of_node, "onoff");
|
||||
if (np && !of_device_is_available(np))
|
||||
np = NULL;
|
||||
|
||||
if (np)
|
||||
ret = of_property_read_u32(np, "maxim,onoff-keycode",
|
||||
&code);
|
||||
if (!np || ret < 0)
|
||||
onoff->code = KEY_POWER;
|
||||
else
|
||||
onoff->code = code;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
onoff->input = devm_input_allocate_device(dev);
|
||||
if (!onoff->input)
|
||||
return -ENOMEM;
|
||||
|
||||
onoff->input->name = "max77620_onoff";
|
||||
onoff->input->phys = "max77620_onoff/input0";
|
||||
onoff->input->id.bustype = BUS_I2C;
|
||||
input_set_capability(onoff->input, EV_KEY, onoff->code);
|
||||
|
||||
ret = devm_regmap_add_irq_chip(&pdev->dev, onoff->rmap, irq,
|
||||
IRQF_ONESHOT, -1,
|
||||
&max77620_onoff_irq_chip,
|
||||
&chip->onoff_irq_data);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to add onoff irq_chip %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
onoff->irq_r = regmap_irq_get_virq(chip->onoff_irq_data,
|
||||
MAX77620_IRQ_ONOFF_EN0_R);
|
||||
onoff->irq_f = regmap_irq_get_virq(chip->onoff_irq_data,
|
||||
MAX77620_IRQ_ONOFF_EN0_F);
|
||||
|
||||
ret = devm_request_any_context_irq(dev, onoff->irq_r,
|
||||
max77620_onoff_handler,
|
||||
IRQF_ONESHOT, "en0-down", onoff);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = devm_request_any_context_irq(dev, onoff->irq_f,
|
||||
max77620_onoff_handler,
|
||||
IRQF_ONESHOT, "en0-up", onoff);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
platform_set_drvdata(pdev, onoff);
|
||||
input_set_drvdata(onoff->input, onoff);
|
||||
device_init_wakeup(dev, 1);
|
||||
|
||||
ret = input_register_device(onoff->input);
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static int max77620_onoff_suspend(struct device *dev)
|
||||
{
|
||||
struct max77620_onoff *onoff = dev_get_drvdata(dev);
|
||||
|
||||
onoff->suspended = true;
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
return enable_irq_wake(onoff->irq_f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max77620_onoff_resume(struct device *dev)
|
||||
{
|
||||
struct max77620_onoff *onoff = dev_get_drvdata(dev);
|
||||
unsigned int val, ret;
|
||||
|
||||
/* Clear ON/OFF interrupts */
|
||||
ret = regmap_read(onoff->rmap, MAX77620_REG_ONOFFIRQ, &val);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to clear onoff irq: %d\n", ret);
|
||||
|
||||
onoff->suspended = false;
|
||||
|
||||
/* If ON/OFF was pressed, report it */
|
||||
if (val & MAX77620_IRQ_ONOFF_EN0_R_MASK) {
|
||||
input_report_key(onoff->input, onoff->code, 1);
|
||||
input_sync(onoff->input);
|
||||
}
|
||||
|
||||
/* Unconditionally release after resume */
|
||||
input_report_key(onoff->input, onoff->code, 0);
|
||||
input_sync(onoff->input);
|
||||
|
||||
if (device_may_wakeup(dev))
|
||||
return disable_irq_wake(onoff->irq_f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops max77620_onoff_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(max77620_onoff_suspend,
|
||||
max77620_onoff_resume)
|
||||
};
|
||||
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static struct platform_driver max77620_onoff_driver = {
|
||||
.driver = {
|
||||
.name = "max77620-onoff",
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.pm = &max77620_onoff_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.probe = max77620_onoff_probe,
|
||||
};
|
||||
|
||||
static int __init max77620_onoff_init(void)
|
||||
{
|
||||
return platform_driver_register(&max77620_onoff_driver);
|
||||
}
|
||||
subsys_initcall(max77620_onoff_init);
|
||||
|
||||
static void __exit max77620_onoff_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&max77620_onoff_driver);
|
||||
}
|
||||
module_exit(max77620_onoff_exit);
|
||||
|
||||
MODULE_DESCRIPTION("MAXIM 77620 ONOFF driver");
|
||||
MODULE_AUTHOR("Billy Laws <blaws05@gmail.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
@@ -200,7 +200,7 @@ static int mma8450_probe(struct i2c_client *c)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mma8450_id[] = {
|
||||
{ MMA8450_DRV_NAME },
|
||||
{ .name = MMA8450_DRV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mma8450_id);
|
||||
|
||||
@@ -189,7 +189,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(pcf8574_kp_pm_ops,
|
||||
pcf8574_kp_suspend, pcf8574_kp_resume);
|
||||
|
||||
static const struct i2c_device_id pcf8574_kp_id[] = {
|
||||
{ DRV_NAME },
|
||||
{ .name = DRV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id);
|
||||
|
||||
@@ -1456,7 +1456,7 @@ static const struct dev_pm_ops cyapa_pm_ops = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id cyapa_id_table[] = {
|
||||
{ "cyapa" },
|
||||
{ .name = "cyapa" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cyapa_id_table);
|
||||
|
||||
@@ -1407,7 +1407,7 @@ err:
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume);
|
||||
|
||||
static const struct i2c_device_id elan_id[] = {
|
||||
{ DRIVER_NAME },
|
||||
{ .name = DRIVER_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, elan_id);
|
||||
|
||||
@@ -607,7 +607,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
|
||||
synaptics_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id synaptics_i2c_id_table[] = {
|
||||
{ "synaptics_i2c" },
|
||||
{ .name = "synaptics_i2c" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table);
|
||||
|
||||
@@ -365,7 +365,7 @@ static const struct dev_pm_ops rmi_i2c_pm = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id rmi_id[] = {
|
||||
{ "rmi4_i2c" },
|
||||
{ .name = "rmi4_i2c" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rmi_id);
|
||||
|
||||
@@ -413,7 +413,7 @@ static const struct dev_pm_ops rmi_smb_pm = {
|
||||
};
|
||||
|
||||
static const struct i2c_device_id rmi_id[] = {
|
||||
{ "rmi4_smbus" },
|
||||
{ .name = "rmi4_smbus" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rmi_id);
|
||||
|
||||
@@ -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/
|
||||
@@ -42,8 +42,8 @@ static int ad7879_i2c_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ad7879_id[] = {
|
||||
{ "ad7879" },
|
||||
{ "ad7889" },
|
||||
{ .name = "ad7879" },
|
||||
{ .name = "ad7889" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad7879_id);
|
||||
|
||||
@@ -164,7 +164,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ar1021_i2c_pm,
|
||||
ar1021_i2c_suspend, ar1021_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id ar1021_i2c_id[] = {
|
||||
{ "ar1021" },
|
||||
{ .name = "ar1021" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id);
|
||||
|
||||
@@ -3420,11 +3420,11 @@ MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id mxt_id[] = {
|
||||
{ "qt602240_ts" },
|
||||
{ "atmel_mxt_ts" },
|
||||
{ "atmel_mxt_tp" },
|
||||
{ "maxtouch" },
|
||||
{ "mXT224" },
|
||||
{ .name = "qt602240_ts" },
|
||||
{ .name = "atmel_mxt_ts" },
|
||||
{ .name = "atmel_mxt_tp" },
|
||||
{ .name = "maxtouch" },
|
||||
{ .name = "mXT224" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mxt_id);
|
||||
|
||||
Loaded 100 of 174 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user