Compare commits
51
Commits
bd7511b3e8
...
3dd376955a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dd376955a | ||
|
|
ed97c6be0c | ||
|
|
972c9d08df | ||
|
|
7046ddc190 | ||
|
|
9feaff3ae1 | ||
|
|
eef0d09399 | ||
|
|
e8b51f1fa0 | ||
|
|
d48bcafa7b | ||
|
|
5b576b78c1 | ||
|
|
25fff59c03 | ||
|
|
bb090bddd9 | ||
|
|
7cbf47a99c | ||
|
|
32493862c1 | ||
|
|
86ed2aca6a | ||
|
|
67b1c0160c | ||
|
|
8bfe2b6101 | ||
|
|
8933091ce0 | ||
|
|
a4b09321ce | ||
|
|
8b96bea2e5 | ||
|
|
a304332401 | ||
|
|
3a0c4610bf | ||
|
|
1863ffe37c | ||
|
|
7318a9019f | ||
|
|
be4132c76c | ||
|
|
ddda24d22c | ||
|
|
84f79459e2 | ||
|
|
7eeb7c0b80 | ||
|
|
08a23556d1 | ||
|
|
3f4f9da841 | ||
|
|
887e25e2a4 | ||
|
|
0dae43de41 | ||
|
|
bd40421261 | ||
|
|
63b8c70722 | ||
|
|
2893c7e85d | ||
|
|
54dc3c657c | ||
|
|
24efa3a31f | ||
|
|
56e643bf1e | ||
|
|
a45f389a30 | ||
|
|
41b487ca6f | ||
|
|
a4aac0fbf5 | ||
|
|
aac9a62d26 | ||
|
|
e0c4f196a3 | ||
|
|
fa29ee0a51 | ||
|
|
7f5782c8a1 | ||
|
|
b6c7c242b0 | ||
|
|
ea33c54a81 | ||
|
|
639d4b9b13 | ||
|
|
b28a89fa67 | ||
|
|
b53d60cd00 | ||
|
|
95a36c4eb8 | ||
|
|
7fc23c1224 |
No files matched your search
@@ -0,0 +1,128 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/usb/rohm,bm92t.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rohm BM92TXX USB Type-C and Power Delivery controller
|
||||
|
||||
maintainers:
|
||||
- CTCaer <ctcaer@gmail.com>
|
||||
- Alexandre Hamamdjian <azkali.limited@gmail.com>
|
||||
|
||||
description:
|
||||
The Rohm BM92TXX is a family of USB Type-C and Power Delivery
|
||||
controllers with an integrated MCU. The host communicates with the
|
||||
device over I2C and is notified of state changes through a dedicated
|
||||
interrupt line.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bm92t
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vbus-supply:
|
||||
description: VBUS sink regulator.
|
||||
|
||||
vbus-source-supply:
|
||||
description: VBUS source (provider) regulator.
|
||||
|
||||
pd_bat_chg-supply:
|
||||
description: Battery charger regulator gated by Power Delivery state.
|
||||
|
||||
rohm,vconn-en-gpio:
|
||||
maxItems: 1
|
||||
description: GPIO controlling the external VCONN switch.
|
||||
|
||||
rohm,dp-disable:
|
||||
type: boolean
|
||||
description: Disable DisplayPort alternate-mode handling.
|
||||
|
||||
rohm,dp-alerts-enable:
|
||||
type: boolean
|
||||
description: Enable DisplayPort status alerts.
|
||||
|
||||
rohm,dp-signal-toggle-on-resume:
|
||||
type: boolean
|
||||
description:
|
||||
Toggle the DisplayPort signal on resume to work around sinks that
|
||||
do not re-train after system resume.
|
||||
|
||||
rohm,dp-lanes:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [2, 4]
|
||||
default: 2
|
||||
description: Number of DisplayPort lanes to negotiate.
|
||||
|
||||
rohm,led-static-on-suspend:
|
||||
type: boolean
|
||||
description:
|
||||
Keep the charge LED in a static state during system suspend
|
||||
instead of letting the controller animate it.
|
||||
|
||||
rohm,dock-power-limit-disable:
|
||||
type: boolean
|
||||
description:
|
||||
Disable the lower power limit applied when a dock is detected.
|
||||
|
||||
rohm,pd-5v-current-limit-ma:
|
||||
description: Charging current limit in mA when 5V PD contract is active.
|
||||
|
||||
rohm,pd-9v-current-limit-ma:
|
||||
description: Charging current limit in mA when 9V PD contract is active.
|
||||
|
||||
rohm,pd-12v-current-limit-ma:
|
||||
description: Charging current limit in mA when 12V PD contract is active.
|
||||
|
||||
rohm,pd-15v-current-limit-ma:
|
||||
description: Charging current limit in mA when 15V PD contract is active.
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output port linking to a USB role switch consumer endpoint.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
typec@18 {
|
||||
compatible = "rohm,bm92t";
|
||||
reg = <0x18>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
vbus-supply = <&vbus_reg>;
|
||||
vbus-source-supply = <&vbus_src_reg>;
|
||||
pd_bat_chg-supply = <&pd_bat_chg_reg>;
|
||||
|
||||
rohm,dp-lanes = <4>;
|
||||
rohm,pd-5v-current-limit-ma = <2000>;
|
||||
rohm,pd-9v-current-limit-ma = <2000>;
|
||||
rohm,pd-12v-current-limit-ma = <1500>;
|
||||
rohm,pd-15v-current-limit-ma = <1200>;
|
||||
|
||||
port {
|
||||
bm92t_ep: endpoint {
|
||||
remote-endpoint = <&usb_role_sw>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -23259,6 +23259,14 @@ L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/iio/pressure/rohm-bm1390.c
|
||||
|
||||
ROHM BM92TXX USB TYPE-C CONTROLLER DRIVER
|
||||
M: CTCaer <ctcaer@gmail.com>
|
||||
M: Alexandre Hamamdjian <azkali.limited@gmail.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/usb/rohm,bm92t.yaml
|
||||
F: drivers/usb/typec/bm92txx.c
|
||||
|
||||
ROHM BU270xx LIGHT SENSOR DRIVERs
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
||||
@@ -1,944 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/mfd/max77620.h>
|
||||
#include <dt-bindings/gpio/tegra-gpio.h>
|
||||
#include <dt-bindings/thermal/thermal.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/soc/tegra-pmc.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/pwm/pwm.h>
|
||||
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
|
||||
|
||||
#include "tegra210.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
i2c1 = "/i2c@7000c000";
|
||||
i2c2 = "/i2c@7000c400";
|
||||
i2c3 = "/i2c@7000c500";
|
||||
i2c5 = "/i2c@7000d000";
|
||||
rtc0 = "/i2c@7000d000/max77620@3c";
|
||||
rtc1 = "/rtc@7000e000";
|
||||
serial0 = &uarta;
|
||||
serial1 = &uartb;
|
||||
serial2 = &uartc;
|
||||
serial3 = &uartd;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "root=/dev/mmcblk0p2 rw rootwait fbcon=rotate:3 printk.synchronous=1 loglevel=4 console=fb0 console=ttyGS0 earlycon";
|
||||
stdout-path = "serial1:115200n8";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
vdd-cpu-supply = <&cpu_max_reg>;
|
||||
};
|
||||
|
||||
idle-states {
|
||||
cpu-sleep {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gpu@57000000 {
|
||||
status = "okay";
|
||||
vdd-supply = <&gpu_max_reg>;
|
||||
};
|
||||
|
||||
host1x@50000000 {
|
||||
dsia: dsi@54300000 {
|
||||
status = "okay";
|
||||
|
||||
panel@0 {
|
||||
compatible = "jdi,lpm062m326a";
|
||||
reset-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
|
||||
backlight = <&backlight>;
|
||||
vdd1-supply = <&v_pavdd_5v0>;
|
||||
vdd2-supply = <&v_navdd_5v0>;
|
||||
};
|
||||
};
|
||||
|
||||
/* tegradc.0: DSI */
|
||||
dc@54200000 {
|
||||
status = "okay";
|
||||
pavdd_lcd-supply = <&v_pavdd_5v0>;
|
||||
navdd_lcd-supply = <&v_navdd_5v0>;
|
||||
dvdd_lcd-supply = <&max77620_sd3>;
|
||||
vdd_lcd_bl_en-supply = <&lcd_bl_en>;
|
||||
nvidia,outputs = <&dsia>;
|
||||
};
|
||||
|
||||
/* tegradc.1: DP */
|
||||
dc@54240000 {
|
||||
status = "okay";
|
||||
avdd_hdmi-supply = <&max77620_ldo8>; /* 1V05 */
|
||||
avdd_hdmi_pll-supply = <&max77620_sd3>; /* 1V8 */
|
||||
// vdd_hdmi_5v0-supply = <&vdd_hdmi>; /* 5V0 GPIO_PCC7 fixed reg */
|
||||
|
||||
vdd-dp-pwr-supply = <&vdd_3v3>;
|
||||
avdd-dp-pll-supply = <&max77620_sd3>;
|
||||
vdd-dp-pad-supply = <&max77620_ldo8>;
|
||||
|
||||
extcon-cables = <&bm92t 3>;
|
||||
extcon-cable-names = "typec1";
|
||||
|
||||
nvidia,outputs = <&sor1>;
|
||||
};
|
||||
|
||||
dpaux1: dpaux@54040000 {
|
||||
status = "okay";
|
||||
vdd-supply = <&v_pavdd_5v0>;
|
||||
};
|
||||
|
||||
sor1: sor@54580000 {
|
||||
status = "okay";
|
||||
nvidia,dpaux = <&dpaux1>;
|
||||
|
||||
avdd-io-hdmi-dp-supply = <&max77620_ldo8>;
|
||||
vdd-hdmi-dp-pll-supply = <&max77620_sd3>;
|
||||
|
||||
nvidia,hpd-gpio = <&gpio TEGRA_GPIO(CC, 1) GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
vi: i2c@546c0000 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
clock@70110000 {
|
||||
status = "okay";
|
||||
nvidia,cf = <6>;
|
||||
nvidia,ci = <0>;
|
||||
nvidia,cg = <2>;
|
||||
nvidia,droop-ctrl = <0x00000f00>;
|
||||
nvidia,force-mode = <1>;
|
||||
nvidia,i2c-fs-rate = <400000>;
|
||||
nvidia,sample-rate = <12500>;
|
||||
vdd-cpu-supply = <&cpu_max_reg>;
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x80000000 0x0 0x80000000>;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
/delete-node/ vpr-carveout;
|
||||
/delete-node/ iram-carveout;
|
||||
};
|
||||
|
||||
r2p {
|
||||
compatible = "tegra-r2p";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* debug port */
|
||||
serial@70006000 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
/* joycon ports:
|
||||
invert TXD and RTS via IRDA_CSR
|
||||
start @ 1000000 baud, switch to 3000000
|
||||
when they are >= 3000000 baud, use 2 stop bits
|
||||
use flow control
|
||||
Note: hsuart driver is required for flow control
|
||||
*/
|
||||
/* right joycon */
|
||||
serial@70006040 {
|
||||
status = "okay";
|
||||
compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
|
||||
nvidia,invert-txd;
|
||||
nvidia,invert-rts;
|
||||
reset-names = "serial";
|
||||
|
||||
joyconr {
|
||||
status = "okay";
|
||||
compatible = "nintendo,joycon-serdev";
|
||||
charger-supply = <&en_vdd_jcr_chgr>;
|
||||
detect-en-gpios = <&gpio TEGRA_GPIO(G, 0) GPIO_ACTIVE_HIGH>;
|
||||
detect-gpios = <&gpio TEGRA_GPIO(H, 6) GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
/* left joycon */
|
||||
serial@70006200 {
|
||||
status = "okay";
|
||||
compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
|
||||
nvidia,invert-txd;
|
||||
nvidia,invert-rts;
|
||||
reset-names = "serial";
|
||||
|
||||
joyconl {
|
||||
status = "okay";
|
||||
compatible = "nintendo,joycon-serdev";
|
||||
charger-supply = <&en_vdd_jcl_chgr>;
|
||||
detect-en-gpios = <&gpio TEGRA_GPIO(D, 1) GPIO_ACTIVE_HIGH>;
|
||||
detect-gpios = <&gpio TEGRA_GPIO(E, 6) GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
/* bluetooth */
|
||||
serial@70006300 {
|
||||
dma-names = "tx";
|
||||
status = "okay";
|
||||
compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
|
||||
reset-names = "serial";
|
||||
|
||||
bluetooth {
|
||||
compatible = "brcm,bcm43438-bt";
|
||||
vbat-supply = <&battery_reg>;
|
||||
vddio-supply = <&battery_reg>;
|
||||
shutdown-gpios = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
|
||||
device-wakeup-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_LOW>;
|
||||
max-speed = <3000000>; /* Max supported 4 MBaud */
|
||||
sco-routing = <1>; /* Over HCI */
|
||||
};
|
||||
};
|
||||
|
||||
clk32k_in: clock-32k {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <32768>;
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
backlight: backlight {
|
||||
compatible = "pwm-backlight";
|
||||
pwms = <&pwm 0 33898>;
|
||||
pwm-names = "backlight";
|
||||
brightness-levels = <
|
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||
17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
||||
31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
||||
45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
||||
59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
||||
73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
||||
87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
||||
>;
|
||||
default-brightness-level = <50>;
|
||||
enable-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
|
||||
power-supply = <&max77620_sd3>;
|
||||
};
|
||||
|
||||
/* Fixed regulators */
|
||||
battery_reg: vdd-ac-bat {
|
||||
compatible = "regulator-fixed";
|
||||
status = "okay";
|
||||
regulator-name = "vdd-ac-bat";
|
||||
regulator-min-microvolt = <4800000>;
|
||||
regulator-max-microvolt = <4800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
vdd_3v3: vdd-3v3 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vdd-3v3";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
gpio = <&max77620 3 0>;
|
||||
enable-active-high;
|
||||
regulator-enable-ramp-delay = <160>;
|
||||
regulator-disable-ramp-delay = <10000>;
|
||||
};
|
||||
|
||||
max77620_gpio7: avdd-dsi-csi-1v2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "max77620-gpio7";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-boot-on; /* Must be set for seamless display */
|
||||
gpio = <&max77620 7 0>;
|
||||
enable-active-high;
|
||||
regulator-enable-ramp-delay = <240>;
|
||||
regulator-disable-ramp-delay = <11340>;
|
||||
vin-supply = <&max77620_ldo0>;
|
||||
};
|
||||
|
||||
lcd_bl_en: lcd-bl-en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "lcd-bl-en";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
gpio = <&gpio TEGRA_GPIO(V, 1) 0>;
|
||||
regulator-boot-on; /* Must be set for seamless display */
|
||||
enable-active-high;
|
||||
regulator-always-on;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
en_vdd_sd: en-vdd-sd {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "en-vdd-sd";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpio = <&gpio TEGRA_GPIO(E, 4) 0>;
|
||||
enable-active-high;
|
||||
regulator-enable-ramp-delay = <472>;
|
||||
regulator-disable-ramp-delay = <4880>;
|
||||
vin-supply = <&vdd_3v3>;
|
||||
};
|
||||
|
||||
/* LCD Power Enable +5V. Rohm BD8316GWL. */
|
||||
v_pavdd_5v0: v-pavdd-5v0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "v_pavdd_5v0";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
gpio = <&gpio TEGRA_GPIO(I, 0) 0>;
|
||||
enable-active-high;
|
||||
regulator-boot-on; /* Must be set for seamless display */
|
||||
regulator-enable-ramp-delay = <232>;
|
||||
};
|
||||
|
||||
/* LCD Power Enable -5V. Rohm BD8316GWL. */
|
||||
v_navdd_5v0: v-navdd-5v0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "v_navdd_5v0";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
gpio = <&gpio TEGRA_GPIO(I, 1) 0>;
|
||||
enable-active-high;
|
||||
regulator-boot-on; /* Must be set for seamless display */
|
||||
regulator-enable-ramp-delay = <232>;
|
||||
};
|
||||
|
||||
/* Joycon/Fan power (battery). Maxim MAX8969EWL53+. */
|
||||
v_vdd50_a: v-vdd50-a {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "v_vdd50_a";
|
||||
regulator-min-microvolt = <5300000>;
|
||||
regulator-max-microvolt = <5300000>;
|
||||
gpio = <&gpio TEGRA_GPIO(A, 5) 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
/* Joycon/Fan power (usb). DC0 on Odin. Maxim MAX8969EWL53+ on Modin. */
|
||||
v_vdd50_b: v-vdd50-b {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "v_vdd50_b";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
gpio = <&gpio TEGRA_GPIO(CC, 4) 0>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
v_vdd5v3: v-vdd5v3 {
|
||||
compatible = "regulator-fixed";
|
||||
status = "okay"; /* Only enabled on Modin/Vali/Fric */
|
||||
regulator-name = "v_vdd5v3";
|
||||
regulator-min-microvolt = <5300000>;
|
||||
regulator-max-microvolt = <5300000>;
|
||||
gpio = <&gpio TEGRA_GPIO(X, 3) 0>;
|
||||
enable-active-high;
|
||||
regulator-enable-ramp-delay = <10000>;
|
||||
};
|
||||
|
||||
vdd3v3_gc: vdd3v3-gc {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vdd3v3_gc";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpio = <&gpio TEGRA_GPIO(E, 5) 0>;
|
||||
enable-active-high;
|
||||
regulator-enable-ramp-delay = <472>;
|
||||
regulator-disable-ramp-delay = <4880>;
|
||||
vin-supply = <&vdd_3v3>;
|
||||
};
|
||||
|
||||
/* TI TCR2EE48 4.8V */
|
||||
en_vdd_jcl_chgr: left-joycon-charger {
|
||||
compatible = "regulator-fixed";
|
||||
status = "okay";
|
||||
regulator-name = "left-joycon-charger";
|
||||
regulator-min-microvolt = <4800000>;
|
||||
regulator-max-microvolt = <4800000>;
|
||||
gpio = <&gpio TEGRA_GPIO(CC, 3) GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
vin-supply = <&v_vdd50_a>;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
/* TI TCR2EE48 4.8V */
|
||||
en_vdd_jcr_chgr: right-joycon-charger {
|
||||
compatible = "regulator-fixed";
|
||||
status = "okay";
|
||||
regulator-name = "right-joycon-charger";
|
||||
regulator-min-microvolt = <4800000>;
|
||||
regulator-max-microvolt = <4800000>;
|
||||
gpio = <&gpio TEGRA_GPIO(K, 3) GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
vin-supply = <&v_vdd50_a>;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
/* SDMMC4 for EMMC */
|
||||
mmc@700b0600 {
|
||||
status = "disabled";
|
||||
bus-width = <8>;
|
||||
max-frequency = <200000000>;
|
||||
|
||||
cap-mmc-highspeed;
|
||||
mmc-ddr-1_8v;
|
||||
mmc-hs200-1_8v;
|
||||
mmc-hs400-1_8v;
|
||||
non-removable;
|
||||
|
||||
vqmmc-supply = <&max77620_sd3>;
|
||||
vmmc-supply = <&vdd_3v3>;
|
||||
};
|
||||
|
||||
/* SDMMC3 Not Used */
|
||||
mmc@700b0400 {
|
||||
status = "disabled";
|
||||
|
||||
vqmmc-supply = <&max77620_sd3>;
|
||||
vmmc-supply = <&vdd_3v3>;
|
||||
};
|
||||
|
||||
/* SDMMC2 for Gamecard */
|
||||
mmc@700b0200 {
|
||||
status = "disabled";
|
||||
bus-width = <8>;
|
||||
max-frequency = <200000000>;
|
||||
|
||||
mmc-ddr-1_8v;
|
||||
mmc-hs400-1_8v;
|
||||
mmc-hs200-1_8v;
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
non-removable;
|
||||
|
||||
vqmmc-supply = <&max77620_sd3>;
|
||||
vmmc-supply = <&vdd_3v3>;
|
||||
};
|
||||
|
||||
/* SDMMC1 for SD Card */
|
||||
mmc@700b0000 {
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
max-frequency = <200000000>;
|
||||
|
||||
cap-sd-highspeed;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
|
||||
cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
|
||||
|
||||
vmmc-supply = <&en_vdd_sd>;
|
||||
vqmmc-supply = <&max77620_ldo2>;
|
||||
};
|
||||
|
||||
hda@70030000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* i2c1 @ 100000hz
|
||||
1c: realtek 5639
|
||||
18: rohm usb-pd
|
||||
4c: ti temperature sensor
|
||||
6b: ti charger
|
||||
36: maxim fuel gauge
|
||||
*/
|
||||
i2c@7000c000 {
|
||||
status = "okay";
|
||||
clock-frequency = <100000>;
|
||||
|
||||
bq24193@6b {
|
||||
compatible = "ti,bq24193";
|
||||
reg = <0x6b>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(Z, 0) IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
monitored-battery = <&fuel_gauge>;
|
||||
#extcon-cells = <1>;
|
||||
|
||||
omit-battery-class;
|
||||
|
||||
battery_charger: charger {
|
||||
regulator-name = "batt_regulator";
|
||||
regulator-max-microamp = <4500000>;
|
||||
};
|
||||
|
||||
usb0_vbus: usb-otg-vbus {
|
||||
regulator-name = "vbus_regulator";
|
||||
};
|
||||
};
|
||||
|
||||
fuel_gauge: fuel-gauge@36 {
|
||||
compatible = "maxim,max17050";
|
||||
status = "okay";
|
||||
reg = <0x36>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(Y, 0) IRQ_TYPE_NONE>;
|
||||
|
||||
/* Actual is 5000 but driver does not account for CGAIN */
|
||||
/* And does not take into account Rsense and CGAIN for capacity */
|
||||
maxim,rsns-microohm = <10000>;
|
||||
maxim,over-heat-temp = <600>;
|
||||
maxim,dead-volt = <3000>;
|
||||
maxim,over-volt = <4208>; /* Actual: 4258 mV */
|
||||
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
rt5639: audio-codec@1c {
|
||||
status = "okay";
|
||||
compatible = "realtek,rt5639";
|
||||
reg = <0x1c>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(BB, 4) IRQ_TYPE_EDGE_RISING>;
|
||||
realtek,ldo1-en-gpios = <&gpio TEGRA_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
|
||||
realtek,over-current-threshold-microamp = <600>;
|
||||
realtek,over-current-scale-factor = <2>;
|
||||
realtek,jack-detect-is-jd1;
|
||||
};
|
||||
|
||||
/* PD Chip */
|
||||
bm92t: bm92t@18 {
|
||||
compatible = "rohm,bm92t";
|
||||
reg = <0x18>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(K, 4) IRQ_TYPE_EDGE_RISING>;
|
||||
#extcon-cells = <1>;
|
||||
pd_bat_chg-supply = <&battery_charger>;
|
||||
vbus-source-supply = <&v_vdd5v3>;
|
||||
vbus-supply = <&usb0_vbus>;
|
||||
|
||||
rohm,dp-lanes = <2>;
|
||||
rohm,dp-signal-toggle-on-resume;
|
||||
|
||||
/* Absolute max is 2.4A, constrained by BQ24193 ILIM */
|
||||
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 {
|
||||
usb_con_ep: endpoint {
|
||||
remote-endpoint = <&usb_port_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
tmp451: temperature-sensor@4c {
|
||||
compatible = "ti,tmp451";
|
||||
status = "okay";
|
||||
reg = <0x4c>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(X, 4) IRQ_TYPE_EDGE_FALLING>;
|
||||
vcc-supply = <&battery_reg>;
|
||||
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
/* i2c3 @ 400000hz
|
||||
49: stm touchscreen controller
|
||||
*/
|
||||
i2c@7000c500 {
|
||||
status = "okay";
|
||||
clock-frequency = <400000>;
|
||||
|
||||
touchscreen@49 {
|
||||
compatible = "stm,ftm4_fts";
|
||||
status = "okay";
|
||||
reg = <0x49>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(X, 1) IRQ_TYPE_LEVEL_LOW>;
|
||||
vdd-tp-2v9-supply = <&max77620_ldo6>;
|
||||
stm,vio-gpio = <&gpio TEGRA_GPIO(J, 7) GPIO_ACTIVE_HIGH>;
|
||||
stm,irq_type = <0x2000>; /* IRQF_ONESHOT */
|
||||
stm,regulator_avdd = "vdd-tp-2v9";
|
||||
stm,max_coords = <1280 720>;
|
||||
stm,max-real-coords = <1264 704>;
|
||||
stm,edge-offset = <15 15>;
|
||||
stm,delayed-open;
|
||||
stm,delayed-open-time = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* i2c2 @ 400000hz
|
||||
29: rohm ambient light sensor
|
||||
*/
|
||||
i2c@7000c400 {
|
||||
status = "okay";
|
||||
clock-frequency = <400000>;
|
||||
|
||||
bh1730fvc: bh1730fvc@29 {
|
||||
status = "disabled";
|
||||
compatible = "rohm,bh1730fvc";
|
||||
reg = <0x29>;
|
||||
als-vid-supply = <&max77620_ldo6>;
|
||||
als-vdd-supply = <&vdd_3v3>;
|
||||
rohm,integration-cycle = <38>;
|
||||
rohm,lux-multiplier = <3600>;
|
||||
|
||||
rohm,opt-win-coeff = < 500 5002 7502
|
||||
754 2250 2000
|
||||
1029 1999 1667
|
||||
1373 884 583
|
||||
1879 309 165>;
|
||||
|
||||
rohm,gain-coeff = < 2500 0
|
||||
1600 7800
|
||||
10 50000
|
||||
0 1000>;
|
||||
};
|
||||
};
|
||||
|
||||
spi@7000da00 {
|
||||
status = "disabled"; /* Disabled for Vali */
|
||||
num-cs = <1>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
// spi-cs-setup-delay-ns = <2>;
|
||||
// spi-cs-hold-delay-ns = <2>;
|
||||
// spi-cs-inactive-delay-ns = <2>;
|
||||
|
||||
/*
|
||||
* Model WHOAMI:
|
||||
* LSM6DS3H 0x69, LSM6DSE 0x6A, LSM6DSO 0x6C, ICM40607 0x38.
|
||||
*/
|
||||
gyroscope: imu@0 {
|
||||
reg = <0>;
|
||||
status = "disabled";
|
||||
compatible = "st,lsm6ds3h";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
spi-max-frequency = <8000000>;
|
||||
|
||||
/* SPI Mode-3 */
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(X, 2) IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
vdd-supply = <&battery_reg>;
|
||||
vddio-supply = <&battery_reg>;
|
||||
|
||||
st,drdy-int-pin = <2>;
|
||||
|
||||
nvidia,rx-clk-tap-delay = <0x1f>;
|
||||
nvidia,tx-clk-tap-delay = <0x0>;
|
||||
|
||||
|
||||
mount-matrix =
|
||||
"1", "0", "0", /* X: x */
|
||||
"0", "1", "0", /* Y: y */
|
||||
"0", "0", "1"; /* Z: z */
|
||||
};
|
||||
};
|
||||
|
||||
gpio-keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
key-volume-down {
|
||||
label = "Volume Down";
|
||||
gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <EV_KEY>;
|
||||
linux,code = <KEY_VOLUMEDOWN>;
|
||||
debounce-interval = <10>;
|
||||
};
|
||||
|
||||
key-volume-up {
|
||||
label = "Volume Up";
|
||||
gpios = <&gpio TEGRA_GPIO(X, 6) GPIO_ACTIVE_LOW>;
|
||||
linux,input-type = <EV_KEY>;
|
||||
linux,code = <KEY_VOLUMEUP>;
|
||||
debounce-interval = <10>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio@6000d000 {
|
||||
boot-default-output-high {
|
||||
gpio-hog;
|
||||
output-high;
|
||||
gpios = <TEGRA_GPIO(H, 1) GPIO_ACTIVE_HIGH>; /* Wi-Fi Reset. Powered on by default. */
|
||||
line-name = "boot-default-output-high";
|
||||
};
|
||||
};
|
||||
|
||||
pwm@7000a000 {
|
||||
status = "okay";
|
||||
#pwm-cells = <2>;
|
||||
};
|
||||
|
||||
fan: pwm-fan {
|
||||
compatible = "pwm-fan";
|
||||
cooling-min-state = <0>;
|
||||
cooling-max-state = <5>;
|
||||
#cooling-cells = <2>;
|
||||
pwms = <&pwm 1 33333>;
|
||||
fan-supply = <&v_vdd50_a>;
|
||||
enable-gpios = <&gpio TEGRA_GPIO(A, 5) GPIO_ACTIVE_HIGH>;
|
||||
/* cooling level (0, 1, 2, 3, 4, 5) - pwm inverted */
|
||||
cooling-levels = <255 204 153 102 51 0>;
|
||||
};
|
||||
|
||||
sound {
|
||||
status = "okay";
|
||||
compatible = "nvidia,tegra-audio-rt5640-tx1",
|
||||
"nvidia,tegra-audio-rt5640";
|
||||
nvidia,model = "Nintendo Switch";
|
||||
|
||||
nvidia,audio-codec = <&rt5639>;
|
||||
nvidia,i2s-controller = <&tegra_i2s1>;
|
||||
// nvidia,hp-det-gpios = <&gpio 143 0>;
|
||||
|
||||
clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
|
||||
<&tegra_car TEGRA210_CLK_CLK_M>;
|
||||
clock-names = "pll_a", "plla_out0", "mclk";
|
||||
|
||||
assigned-clocks = <&tegra_car TEGRA210_CLK_PLL_A>,
|
||||
<&tegra_car TEGRA210_CLK_PLL_A_OUT0>,
|
||||
<&tegra_car TEGRA210_CLK_D_AUDIO>,
|
||||
<&tegra_car TEGRA210_CLK_EXTERN1>;
|
||||
assigned-clock-rates = <368640000>, <36864000>,
|
||||
<36864000>, <12288000>;
|
||||
|
||||
nvidia,audio-routing =
|
||||
"Headphones", "HPOL",
|
||||
"Headphones", "HPOR",
|
||||
"Speakers", "SPORP",
|
||||
"Speakers", "SPORN",
|
||||
"Speakers", "SPOLP",
|
||||
"Speakers", "SPOLN",
|
||||
"IN1P", "Mic Jack",
|
||||
"IN1P", "Mic Jack";
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu {
|
||||
polling-delay-passive = <250>;
|
||||
polling-delay = <500>;
|
||||
status = "okay";
|
||||
|
||||
/* Based on Console profile SoC: 95% (100% at Handheld) */
|
||||
coefficients = <95 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>;
|
||||
thermal-sensors = <&tmp451 1>;
|
||||
|
||||
trips {
|
||||
cpu_critical: cpu-critical {
|
||||
temperature = <102500>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
|
||||
cpu_heavy: cpu-heavy {
|
||||
temperature = <98500>;
|
||||
hysteresis = <1000>;
|
||||
type = "hot";
|
||||
};
|
||||
|
||||
cpu_throttle: cpu-throttle {
|
||||
temperature = <89000>;
|
||||
hysteresis = <2000>;
|
||||
type = "passive";
|
||||
};
|
||||
|
||||
cpu_cap_trip1: cpu-cap-trip1 {
|
||||
temperature = <58000>;
|
||||
hysteresis = <2000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
cpu_floor_trip1: cpu-floor-trip1 {
|
||||
temperature = <53000>;
|
||||
hysteresis = <2000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
cpu_cap_trip0: cpu-cap-trip0 {
|
||||
temperature = <48000>;
|
||||
hysteresis = <2000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
cpu_floor_trip0: cpu-floor-trip0 {
|
||||
temperature = <43000>;
|
||||
hysteresis = <2000>;
|
||||
type = "active";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
||||
trip = <&cpu_critical>;
|
||||
};
|
||||
|
||||
map1 {
|
||||
cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
||||
trip = <&cpu_heavy>;
|
||||
};
|
||||
|
||||
map2 {
|
||||
cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
||||
trip = <&cpu_throttle>;
|
||||
};
|
||||
|
||||
map3 {
|
||||
cooling-device = <&fan 1 1>;
|
||||
trip = <&cpu_cap_trip1>;
|
||||
};
|
||||
|
||||
map4 {
|
||||
cooling-device = <&fan 2 2>;
|
||||
trip = <&cpu_floor_trip1>;
|
||||
};
|
||||
|
||||
map5 {
|
||||
cooling-device = <&fan 3 3>;
|
||||
trip = <&cpu_cap_trip0>;
|
||||
};
|
||||
|
||||
map6 {
|
||||
cooling-device = <&fan 4 4>;
|
||||
trip = <&cpu_floor_trip0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gpu {
|
||||
polling-delay-passive = <250>;
|
||||
polling-delay = <500>;
|
||||
status = "okay";
|
||||
thermal-sensors = <&tmp451 1>;
|
||||
|
||||
trips {
|
||||
gpu_critical: gpu-critical {
|
||||
temperature = <103000>;
|
||||
hysteresis = <0>;
|
||||
type = "critical";
|
||||
};
|
||||
|
||||
gpu_heavy: gpu-heavy {
|
||||
temperature = <100000>;
|
||||
hysteresis = <1000>;
|
||||
type = "hot";
|
||||
};
|
||||
|
||||
gpu_throttle: gpu-throttle {
|
||||
temperature = <90500>;
|
||||
hysteresis = <0>;
|
||||
type = "passive";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
trip = <&gpu_critical>;
|
||||
cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
||||
};
|
||||
map1 {
|
||||
trip = <&gpu_heavy>;
|
||||
cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
||||
};
|
||||
map2 {
|
||||
trip = <&gpu_throttle>;
|
||||
cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pmic {
|
||||
status = "okay";
|
||||
polling-delay-passive = <250>;
|
||||
polling-delay = <500>;
|
||||
thermal-sensors = <&max77620>;
|
||||
|
||||
trips {
|
||||
pmic_die_warn_temp_thresh: hot-die {
|
||||
temperature = <120000>;
|
||||
type = "hot";
|
||||
hysteresis = <0>;
|
||||
};
|
||||
|
||||
pmic_die_cirt_temp_thresh: critical-die {
|
||||
temperature = <140000>;
|
||||
type = "critical";
|
||||
hysteresis = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
trip = <&pmic_die_warn_temp_thresh>;
|
||||
cooling-device = <&throttle_heavy 1 1>;
|
||||
contribution = <100>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
cpu_vreg {
|
||||
status = "okay";
|
||||
polling-delay-passive = <250>;
|
||||
polling-delay = <500>;
|
||||
thermal-sensors = <&cpu_max_reg>;
|
||||
|
||||
trips {
|
||||
cpu_vreg_die_warn_temp_thresh: hot-die {
|
||||
temperature = <120000>;
|
||||
type = "hot";
|
||||
hysteresis = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
trip = <&cpu_vreg_die_warn_temp_thresh>;
|
||||
cooling-device = <&throttle_heavy 1 1>;
|
||||
contribution = <100>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gpu_vreg {
|
||||
status = "okay";
|
||||
polling-delay-passive = <250>;
|
||||
polling-delay = <500>;
|
||||
thermal-sensors = <&gpu_max_reg>;
|
||||
|
||||
trips {
|
||||
gpu_vreg_die_warn_temp_thresh: hot-die {
|
||||
temperature = <120000>;
|
||||
type = "hot";
|
||||
hysteresis = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
/*
|
||||
* There are currently no cooling maps,
|
||||
* because there are no cooling devices.
|
||||
*/
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1310,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";
|
||||
};
|
||||
|
||||
@@ -1377,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";
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "tegra210b01-nx.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Nintendo Switch (OLED model)";
|
||||
compatible = "nvidia,fric", "nintendo,aula", "nintendo,nx", "nvidia,tegra210b01";
|
||||
};
|
||||
@@ -1,432 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <dt-bindings/mfd/max77620.h>
|
||||
|
||||
#include "tegra210b01.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
serial0 = &uarta;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x80000000 0x0 0xc0000000>;
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
/delete-property/ dmas;
|
||||
/delete-property/ dma-names;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pmc@7000e400 {
|
||||
nvidia,invert-interrupt;
|
||||
nvidia,suspend-mode = <0>;
|
||||
nvidia,cpu-pwr-good-time = <0>;
|
||||
nvidia,cpu-pwr-off-time = <0>;
|
||||
nvidia,core-pwr-good-time = <13100 7800>;
|
||||
nvidia,core-pwr-off-time = <44160>;
|
||||
nvidia,core-power-req-active-high;
|
||||
nvidia,sys-clock-req-active-high;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
mmc@700b0600 {
|
||||
bus-width = <8>;
|
||||
non-removable;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
clk32k_in: clock-32k {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <32768>;
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
cpu@0 {
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
cpu@2 {
|
||||
enable-method = "psci";
|
||||
};
|
||||
|
||||
cpu@3 {
|
||||
enable-method = "psci";
|
||||
};
|
||||
};
|
||||
|
||||
psci {
|
||||
compatible = "arm,psci-1.0";
|
||||
method = "smc";
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
status = "okay";
|
||||
clock-frequency = <400000>;
|
||||
|
||||
pmic_a: pmic@33 {
|
||||
compatible = "maxim,max77812-regulator";
|
||||
reg = <0x33>;
|
||||
maxim,soft-start-slew-rate = <5000>;
|
||||
maxim,shutdown-slew-rate = <5000>;
|
||||
maxim,ramp-up-slew-rate = <5000>;
|
||||
maxim,ramp-down-slew-rate = <5000>;
|
||||
status = "okay";
|
||||
|
||||
/* interrupt-parent = <&gpio>; */
|
||||
/* interrupts = <TEGRA_GPIO(K, 6) IRQ_TYPE_NONE>; */
|
||||
|
||||
regulators {
|
||||
gpu_max_reg: m1vout {
|
||||
regulator-name = "vdd-gpu";
|
||||
regulator-min-microvolt = <250000>;
|
||||
regulator-max-microvolt = <1525000>;
|
||||
/* regulator-max-microamp = <10000000>; */ /* 0x33 cfg */
|
||||
/* regulator-max-microamp = <15000000>; */ /* 0x31 cfg */
|
||||
regulator-init-microvolt = <800000>;
|
||||
regulator-ramp-delay = <5000>;
|
||||
regulator-enable-ramp-delay = <5000>;
|
||||
regulator-disable-ramp-delay = <5000>;
|
||||
maxim,peak-current-limit-ua = <7200000>;
|
||||
};
|
||||
|
||||
m2vout {
|
||||
regulator-name = "vdd-mvout2";
|
||||
regulator-min-microvolt = <250000>;
|
||||
regulator-max-microvolt = <1525000>;
|
||||
regulator-ramp-delay = <5000>;
|
||||
regulator-enable-ramp-delay = <5000>;
|
||||
regulator-disable-ramp-delay = <5000>;
|
||||
maxim,peak-current-limit-ua = <7200000>;
|
||||
};
|
||||
|
||||
ram_max_reg: m3vout {
|
||||
status = "okay";
|
||||
regulator-name = "vddio-ddr";
|
||||
regulator-min-microvolt = <550000>; /* Set min lpddr4x normally allowed */
|
||||
regulator-max-microvolt = <650000>; /* Set max lpddr4x normally allowed */
|
||||
/* regulator-max-microamp = <5000000>; */
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
/* regulator-init-microvolt = <600000>; */ /* Controlled by bootloader */
|
||||
regulator-ramp-delay = <5000>;
|
||||
regulator-enable-ramp-delay = <5000>;
|
||||
regulator-disable-ramp-delay = <5000>;
|
||||
maxim,peak-current-limit-ua = <7200000>;
|
||||
};
|
||||
|
||||
cpu_max_reg: m4vout {
|
||||
regulator-name = "vdd-cpu";
|
||||
regulator-min-microvolt = <250000>;
|
||||
regulator-max-microvolt = <1525000>;
|
||||
/* regulator-max-microamp = <5000000>; */
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-init-microvolt = <1000000>;
|
||||
regulator-ramp-delay = <5000>;
|
||||
regulator-enable-ramp-delay = <5000>;
|
||||
regulator-disable-ramp-delay = <5000>;
|
||||
maxim,peak-current-limit-ua = <7200000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pmic_b: pmic@3c {
|
||||
compatible = "maxim,max77620";
|
||||
reg = <0x3c>;
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&max77620_default>;
|
||||
|
||||
fps {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
fps0 {
|
||||
reg = <0>;
|
||||
maxim,shutdown-fps-time-period-us = <5120>;
|
||||
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
|
||||
};
|
||||
|
||||
fps1 {
|
||||
reg = <1>;
|
||||
maxim,shutdown-fps-time-period-us = <5120>;
|
||||
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
|
||||
maxim,device-state-on-disabled-event = <MAX77620_FPS_INACTIVE_STATE_SLEEP>;
|
||||
};
|
||||
|
||||
fps2 {
|
||||
reg = <2>;
|
||||
maxim,shutdown-fps-time-period-us = <5120>;
|
||||
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
|
||||
};
|
||||
};
|
||||
|
||||
// hog-0 {
|
||||
// gpio-hog;
|
||||
// output-high;
|
||||
// gpios = <2 GPIO_ACTIVE_HIGH>,
|
||||
// <7 GPIO_ACTIVE_HIGH>;
|
||||
// };
|
||||
|
||||
max77620_default: pinmux {
|
||||
gpio0 {
|
||||
pins = "gpio0";
|
||||
function = "gpio";
|
||||
};
|
||||
|
||||
gpio1 {
|
||||
pins = "gpio1";
|
||||
function = "fps-out";
|
||||
drive-open-drain = <1>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
maxim,active-fps-power-up-slot = <5>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
};
|
||||
|
||||
gpio2 {
|
||||
pins = "gpio2";
|
||||
function = "fps-out";
|
||||
drive-open-drain = <1>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
maxim,active-fps-power-up-slot = <6>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
};
|
||||
|
||||
gpio3 {
|
||||
pins = "gpio3";
|
||||
function = "fps-out";
|
||||
drive-open-drain = <1>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
maxim,active-fps-power-up-slot = <3>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
};
|
||||
|
||||
gpio4 {
|
||||
pins = "gpio4";
|
||||
function = "32k-out1";
|
||||
};
|
||||
|
||||
gpio5_6_7 {
|
||||
pins = "gpio5", "gpio6", "gpio7";
|
||||
function = "gpio";
|
||||
drive-open-drain = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
regulators {
|
||||
in-ldo0-1-supply = <&max77620_sd2>;
|
||||
in-ldo7-8-supply = <&max77620_sd2>;
|
||||
|
||||
max77620_sd0: sd0 {
|
||||
regulator-name = "vdd-core";
|
||||
regulator-min-microvolt = <625000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
|
||||
maxim,active-fps-power-up-slot = <1>;
|
||||
maxim,active-fps-power-down-slot = <7>;
|
||||
// regulator-initial-mode = <REGULATOR_MODE_NORMAL>;
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-disable-ramp-delay = <4080>;
|
||||
maxim,ramp-rate-setting = <27500>;
|
||||
regulator-ramp-delay = <27500>;
|
||||
};
|
||||
|
||||
max77620_sd1: sd1 {
|
||||
regulator-name = "vdd-ddr";
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1175000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
/* regulator-init-microvolt = <1100000>; */ /* Controlled by bootloader */
|
||||
// regulator-initial-mode = <REGULATOR_MODE_NORMAL>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
maxim,active-fps-power-up-slot = <5>;
|
||||
maxim,active-fps-power-down-slot = <2>;
|
||||
regulator-enable-ramp-delay = <60>;
|
||||
regulator-disable-ramp-delay = <145800>;
|
||||
maxim,ramp-rate-setting = <27500>;
|
||||
regulator-ramp-delay = <27500>;
|
||||
};
|
||||
|
||||
max77620_sd2: sd2 {
|
||||
regulator-name = "vdd-pre-reg";
|
||||
regulator-min-microvolt = <1325000>;
|
||||
regulator-max-microvolt = <1325000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <40>;
|
||||
regulator-disable-ramp-delay = <20000>;
|
||||
maxim,ramp-rate-setting = <27500>;
|
||||
regulator-ramp-delay = <27500>;
|
||||
};
|
||||
|
||||
max77620_sd3: sd3 {
|
||||
regulator-name = "vdd-1v8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
maxim,active-fps-power-up-slot = <2>;
|
||||
maxim,active-fps-power-down-slot = <4>;
|
||||
// regulator-initial-mode = <REGULATOR_MODE_NORMAL>;
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-disable-ramp-delay = <118000>;
|
||||
maxim,ramp-rate-setting = <27500>;
|
||||
regulator-ramp-delay = <27500>;
|
||||
};
|
||||
|
||||
max77620_ldo0: ldo0 {
|
||||
regulator-name = "avdd-sys";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-boot-on; /* Must be set for seamless display */
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-disable-ramp-delay = <4000>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
max77620_ldo1: ldo1 {
|
||||
regulator-name = "vdd-pex";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-disable-ramp-delay = <7000>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
max77620_ldo2: ldo2 {
|
||||
regulator-name = "vddio-sdmmc1";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <100>;
|
||||
regulator-disable-ramp-delay = <6000>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
max77620_ldo3: ldo3 {
|
||||
regulator-name = "vdd-gc-3v1";
|
||||
regulator-min-microvolt = <3100000>;
|
||||
regulator-max-microvolt = <3100000>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <100>;
|
||||
regulator-disable-ramp-delay = <3000>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
max77620_ldo4: ldo4 {
|
||||
regulator-name = "vdd-rtc";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <800000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <7>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-disable-ramp-delay = <610>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
/* GC Card Vddio */
|
||||
max77620_ldo5: ldo5 {
|
||||
regulator-name = "vdd-gc-1v8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <70>;
|
||||
regulator-disable-ramp-delay = <3000>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
/* Touch Panel, ALS. Powers LDO 1V8. */
|
||||
max77620_ldo6: ldo6 {
|
||||
regulator-name = "vdd-tp-2v9";
|
||||
regulator-min-microvolt = <2900000>;
|
||||
regulator-max-microvolt = <2900000>;
|
||||
regulator-boot-on; /* Decrease por time for Touch Panel. */
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <100>;
|
||||
regulator-disable-ramp-delay = <3000>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
/* Not used on T210B01 */
|
||||
max77620_ldo7: ldo7 {
|
||||
regulator-name = "vdd-gen-pll-edp";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1000000>; /* 3100000 */
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-disable-ramp-delay = <2768>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
|
||||
/* Odin/Modin/Fric: DP. */
|
||||
/* Vali: Powers LDO 2V8 for Sio VDD
|
||||
* Powers LDO 1V8 for I2C1 VDDQ and ALC5639.
|
||||
*/
|
||||
max77620_ldo8: ldo8 {
|
||||
regulator-name = "vdd-hdmi-dp";
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
|
||||
maxim,active-fps-power-up-slot = <0>;
|
||||
maxim,active-fps-power-down-slot = <0>;
|
||||
regulator-enable-ramp-delay = <50>;
|
||||
regulator-disable-ramp-delay = <4000>;
|
||||
maxim,ramp-rate-setting = <50000>;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "tegra210b01-nx.dtsi"
|
||||
|
||||
/ {
|
||||
|
||||
model = "Nintendo Switch (2019)";
|
||||
compatible = "nvidia,modin", "nvidia,odin", "nintendo,iowa", "nintendo,nx", "nvidia,tegra210b01";
|
||||
};
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
/ {
|
||||
model = "Nintendo Switch Lite";
|
||||
compatible = "nvidia,vali", "nintendo,hoag", "nintendo,nx", "nvidia,tegra210b01";
|
||||
compatible = "nvidia,vali", "nintendo,hoag", "nintendo,nx", "nvidia,tegra210b01", "nvidia,tegra210";
|
||||
|
||||
/* Joycon/Fan power (usb) */
|
||||
v_vdd50_b: v-vdd50-b {
|
||||
@@ -48,6 +48,33 @@
|
||||
};
|
||||
};
|
||||
|
||||
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 {
|
||||
@@ -64,4 +91,52 @@
|
||||
};
|
||||
};
|
||||
|
||||
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>;
|
||||
};
|
||||
};
|
||||
@@ -48,6 +48,8 @@
|
||||
};
|
||||
|
||||
pinmux@700008d4 {
|
||||
compatible = "nvidia,tegra210b01-pinmux";
|
||||
|
||||
pinmux-sdmmc1-1v8-drv {
|
||||
sdmmc1 {
|
||||
nvidia,pull-down-strength = <0x8>;
|
||||
@@ -132,6 +134,7 @@
|
||||
assigned-clock-rates = <199680000>, <199680000>;
|
||||
};
|
||||
|
||||
/* Tegra210B01 has MBIST patched and is missing VI unit */
|
||||
pmc@7000e400 {
|
||||
compatible = "nvidia,tegra210b01-pmc";
|
||||
|
||||
|
||||
@@ -872,6 +872,7 @@ CONFIG_REGULATOR_HI6421V530=y
|
||||
CONFIG_REGULATOR_HI655X=y
|
||||
CONFIG_REGULATOR_LP873X=m
|
||||
CONFIG_REGULATOR_MAX77620=y
|
||||
CONFIG_REGULATOR_MAX77812=y
|
||||
CONFIG_REGULATOR_MAX8973=y
|
||||
CONFIG_REGULATOR_MAX20411=m
|
||||
CONFIG_REGULATOR_MP8859=y
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -2057,12 +2358,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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -285,9 +285,9 @@ static void gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
gpiochip_enable_irq(&chips->chip, hwirq);
|
||||
|
||||
status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
|
||||
status &= IRQ_TYPE_EDGE_BOTH;
|
||||
if (!status)
|
||||
status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
|
||||
status = IRQ_TYPE_EDGE_BOTH;
|
||||
|
||||
if (status & IRQ_TYPE_EDGE_FALLING)
|
||||
writel_relaxed(mask, &g->set_falling);
|
||||
@@ -297,7 +297,7 @@ static void gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
static int gpio_irq_type(struct irq_data *d, unsigned trigger)
|
||||
{
|
||||
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
if (trigger & ~IRQ_TYPE_EDGE_BOTH)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -400,7 +400,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
|
||||
|
||||
mask = __gpio_mask(i);
|
||||
|
||||
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
if (trigger & ~IRQ_TYPE_EDGE_BOTH)
|
||||
return -EINVAL;
|
||||
|
||||
writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||
|
||||
@@ -160,7 +160,7 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
|
||||
rg->hlevel | rg->llevel) & mask)
|
||||
return 0;
|
||||
|
||||
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
type = IRQ_TYPE_EDGE_BOTH;
|
||||
}
|
||||
|
||||
rg->rising &= ~mask;
|
||||
|
||||
@@ -1263,14 +1263,14 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||
gc = irq_get_domain_generic_chip(mvchip->domain, 0);
|
||||
gc->private = mvchip;
|
||||
ct = &gc->chip_types[0];
|
||||
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
|
||||
ct->type = IRQ_TYPE_LEVEL_MASK;
|
||||
ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
|
||||
ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
|
||||
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
|
||||
ct->chip.name = mvchip->chip.label;
|
||||
|
||||
ct = &gc->chip_types[1];
|
||||
ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
ct->type = IRQ_TYPE_EDGE_BOTH;
|
||||
ct->chip.irq_ack = mvebu_gpio_irq_ack;
|
||||
ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
|
||||
ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
|
||||
|
||||
@@ -198,7 +198,7 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
|
||||
gc->private = port;
|
||||
|
||||
ct = &gc->chip_types[0];
|
||||
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
|
||||
ct->type = IRQ_TYPE_LEVEL_MASK;
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_disable_reg;
|
||||
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
|
||||
@@ -210,7 +210,7 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
|
||||
ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR;
|
||||
|
||||
ct = &gc->chip_types[1];
|
||||
ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
ct->type = IRQ_TYPE_EDGE_BOTH;
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_disable_reg;
|
||||
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
|
||||
|
||||
@@ -432,8 +432,7 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
if (type & ~IRQ_TYPE_SENSE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if (!bank->regs->leveldetect0 &&
|
||||
(type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
|
||||
if (!bank->regs->leveldetect0 && (type & IRQ_TYPE_LEVEL_MASK))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock_irqsave(&bank->lock, flags);
|
||||
@@ -450,9 +449,9 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
/*
|
||||
* Edge IRQs are already cleared/acked in irq_handler and
|
||||
* not need to be masked, as result handle_edge_irq()
|
||||
@@ -702,7 +701,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
|
||||
* after enabing the interrupt to clear the wakeup status.
|
||||
*/
|
||||
if (bank->regs->leveldetect0 && bank->regs->wkup_en &&
|
||||
trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
|
||||
trigger & IRQ_TYPE_LEVEL_MASK)
|
||||
omap_clear_gpio_irqstatus(bank, offset);
|
||||
|
||||
if (trigger)
|
||||
|
||||
@@ -132,8 +132,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
if (offset < 0 || offset >= PL061_GPIO_NR)
|
||||
return -EINVAL;
|
||||
|
||||
if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
|
||||
(trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))
|
||||
if ((trigger & IRQ_TYPE_LEVEL_MASK) && (trigger & IRQ_TYPE_EDGE_BOTH))
|
||||
{
|
||||
dev_err(gc->parent,
|
||||
"trying to configure line %d for both level and edge "
|
||||
@@ -149,7 +148,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
gpiois = readb(pl061->base + GPIOIS);
|
||||
gpioibe = readb(pl061->base + GPIOIBE);
|
||||
|
||||
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
|
||||
if (trigger & IRQ_TYPE_LEVEL_MASK) {
|
||||
bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
|
||||
|
||||
/* Disable edge detection */
|
||||
|
||||
@@ -406,7 +406,7 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
|
||||
if (__gpio_is_occupied(pchip, gpio))
|
||||
return 0;
|
||||
|
||||
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
type = IRQ_TYPE_EDGE_BOTH;
|
||||
}
|
||||
|
||||
gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
|
||||
|
||||
@@ -169,9 +169,9 @@ static int rda_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
if (flow_type & IRQ_TYPE_LEVEL_MASK)
|
||||
irq_set_handler_locked(data, handle_level_irq);
|
||||
else if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
else if (flow_type & IRQ_TYPE_EDGE_BOTH)
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -134,7 +134,7 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
|
||||
if (type == IRQ_TYPE_PROBE) {
|
||||
if ((sgc->irqrising | sgc->irqfalling) & mask)
|
||||
return 0;
|
||||
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
type = IRQ_TYPE_EDGE_BOTH;
|
||||
}
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
|
||||
@@ -158,7 +158,7 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
|
||||
|
||||
sd->gc->private = sd;
|
||||
ct = sd->gc->chip_types;
|
||||
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
|
||||
ct->type = IRQ_TYPE_LEVEL_MASK;
|
||||
ct->regs.eoi = GPSTR;
|
||||
ct->regs.mask = GPIO_INT;
|
||||
ct->chip.irq_mask = irq_gc_mask_clr_bit;
|
||||
|
||||
@@ -149,7 +149,7 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
int regoffset = offset / 8;
|
||||
int mask = BIT(offset % 8);
|
||||
|
||||
if (type & IRQ_TYPE_LEVEL_LOW || type & IRQ_TYPE_LEVEL_HIGH)
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
/* STMPE801 and STMPE 1600 don't have RE and FE registers */
|
||||
|
||||
@@ -172,18 +172,11 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
|
||||
tegra_gpio_enable(tgi, offset);
|
||||
|
||||
ret = pinctrl_gpio_direction_input(chip, offset);
|
||||
if (ret < 0)
|
||||
dev_err(tgi->dev,
|
||||
"Failed to set pinctrl input direction of GPIO %d: %d",
|
||||
chip->base + offset, ret);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gpio_direction_output(struct gpio_chip *chip,
|
||||
@@ -191,19 +184,12 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip,
|
||||
int value)
|
||||
{
|
||||
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
tegra_gpio_set(chip, offset, value);
|
||||
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
|
||||
tegra_gpio_enable(tgi, offset);
|
||||
|
||||
ret = pinctrl_gpio_direction_output(chip, offset);
|
||||
if (ret < 0)
|
||||
dev_err(tgi->dev,
|
||||
"Failed to set pinctrl output direction of GPIO %d: %d",
|
||||
chip->base + offset, ret);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gpio_get_direction(struct gpio_chip *chip,
|
||||
@@ -356,9 +342,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
irq_set_handler_locked(d, handle_level_irq);
|
||||
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
|
||||
if (d->parent_data)
|
||||
@@ -722,7 +708,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)
|
||||
tgi->gc.direction_output = tegra_gpio_direction_output;
|
||||
tgi->gc.set = tegra_gpio_set;
|
||||
tgi->gc.get_direction = tegra_gpio_get_direction;
|
||||
tgi->gc.base = 0;
|
||||
tgi->gc.ngpio = tgi->bank_count * 32;
|
||||
tgi->gc.parent = &pdev->dev;
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
|
||||
if (ver > 2)
|
||||
bflr = ioread32(tgpio->membase + TGPIO_BFLR);
|
||||
|
||||
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
|
||||
if (trigger & IRQ_TYPE_LEVEL_MASK) {
|
||||
bflr &= ~(1 << offset);
|
||||
flr &= ~(1 << offset);
|
||||
if (trigger & IRQ_TYPE_LEVEL_HIGH)
|
||||
|
||||
@@ -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,797 @@
|
||||
/*
|
||||
* Copyright (C) 2018 SwtcR <swtcr0@gmail.com>
|
||||
* Copyright (C) 2023-2024 Azkali <a.ffcc7@gmail.com>
|
||||
*
|
||||
* Based on Sharp ls043t1le01 panel driver by Werner Johansson <werner.johansson@sonymobile.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_modes.h>
|
||||
|
||||
/*! MIPI DCS Panel Private CMDs. */
|
||||
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE ((u8)0xA0)
|
||||
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET ((u8)0xB0)
|
||||
#define MIPI_DCS_PRIV_SM_SET_ELVSS ((u8)0xB1) /* OLED backlight tuning. Byte7: PWM transition time in frames. */
|
||||
#define MIPI_DCS_PRIV_SET_POWER_CONTROL ((u8)0xB1)
|
||||
#define MIPI_DCS_PRIV_SET_EXTC ((u8)0xB9) /* Enable extended commands. */
|
||||
#define MIPI_DCS_PRIV_UNK_BD ((u8)0xBD)
|
||||
#define MIPI_DCS_PRIV_UNK_D5 ((u8)0xD5)
|
||||
#define MIPI_DCS_PRIV_UNK_D6 ((u8)0xD6)
|
||||
#define MIPI_DCS_PRIV_UNK_D8 ((u8)0xD8)
|
||||
#define MIPI_DCS_PRIV_UNK_D9 ((u8)0xD9)
|
||||
|
||||
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK ((u8)0xE2)
|
||||
|
||||
/* BL Control */
|
||||
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT ((u8)BIT(2))
|
||||
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL ((u8)BIT(2))
|
||||
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL ((u8)BIT(3))
|
||||
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL ((u8)BIT(5))
|
||||
|
||||
/* OLED Panels color mode */
|
||||
#define DCS_SM_COLOR_MODE_SATURATED ((u8)0x00) /* Disabled. Similar to vivid but over-saturated. Wide gamut? */
|
||||
#define DCS_SM_COLOR_MODE_WASHED ((u8)0x45)
|
||||
#define DCS_SM_COLOR_MODE_BASIC ((u8)0x03)
|
||||
#define DCS_SM_COLOR_MODE_POR_RESET ((u8)0x20) /* Reset value on power on. */
|
||||
#define DCS_SM_COLOR_MODE_NATURAL ((u8)0x23) /* Not actually natural.. */
|
||||
#define DCS_SM_COLOR_MODE_VIVID ((u8)0x65)
|
||||
#define DCS_SM_COLOR_MODE_NIGHT0 ((u8)0x43) /* Based on washed out. */
|
||||
#define DCS_SM_COLOR_MODE_NIGHT1 ((u8)0x15) /* Based on basic. */
|
||||
#define DCS_SM_COLOR_MODE_NIGHT2 ((u8)0x35) /* Based on natural. */
|
||||
#define DCS_SM_COLOR_MODE_NIGHT3 ((u8)0x75) /* Based on vivid. */
|
||||
|
||||
#define DCS_SM_COLOR_MODE_ENABLE ((u8)BIT(0))
|
||||
|
||||
enum
|
||||
{
|
||||
PANEL_JDI_XXX062M = 0x10,
|
||||
PANEL_JDI_LAM062M109A = 0x0910,
|
||||
PANEL_JDI_LPM062M326A = 0x2610,
|
||||
PANEL_INL_P062CCA_AZ1 = 0x0F20,
|
||||
PANEL_AUO_A062TAN01 = 0x0F30,
|
||||
PANEL_INL_2J055IA_27A = 0x1020,
|
||||
PANEL_AUO_A055TAN01 = 0x1030,
|
||||
PANEL_SHP_LQ055T1SW10 = 0x1040,
|
||||
PANEL_SAM_AMS699VC01 = 0x2050,
|
||||
PANEL_RR_SUPER5_OLED_V1 = 0x10E0,
|
||||
PANEL_RR_SUPER5_OLED_HD_V1 = 0x10E1,
|
||||
PANEL_RR_SUPER7_IPS_V1 = 0x0FE0,
|
||||
PANEL_RR_SUPER7_IPS_HD_V1 = 0x0FE1,
|
||||
PANEL_RR_SUPER7_OLED_7_V1 = 0x20E0,
|
||||
PANEL_RR_SUPER7_OLED_HD_7_V1 = 0x20E1,
|
||||
|
||||
// Found on 6/2" clones. Unknown markings. Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F].
|
||||
PANEL_OEM_CLONE_6_2 = 0x0F83,
|
||||
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
|
||||
PANEL_OEM_CLONE_5_5 = 0x00B3,
|
||||
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
|
||||
PANEL_OEM_CLONE = 0x0000
|
||||
};
|
||||
|
||||
struct init_cmd {
|
||||
u8 cmd;
|
||||
int length;
|
||||
u8 data[64];
|
||||
};
|
||||
|
||||
struct nx_panel {
|
||||
struct drm_panel base;
|
||||
struct mipi_dsi_device *dsi;
|
||||
|
||||
struct backlight_device *backlight;
|
||||
struct regulator *supply1;
|
||||
struct regulator *supply2;
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
bool prepared;
|
||||
bool enabled;
|
||||
|
||||
const struct drm_display_mode *mode;
|
||||
|
||||
struct init_cmd *init_cmds;
|
||||
struct init_cmd *suspend_cmds;
|
||||
|
||||
u16 display_id;
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_default[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
120,
|
||||
},
|
||||
{ MIPI_DCS_SET_DISPLAY_ON, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
20,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_JDI_XXX062M[] = {
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x00, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D8, 24, { 0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
|
||||
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x01, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D8,
|
||||
38,
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x02, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D8,
|
||||
14,
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF } },
|
||||
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x00, 0x00 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D9, 2, { 0x06, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0x00, 0x00, 0x00 } },
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
{ MIPI_DCS_SET_DISPLAY_ON, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
20,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_JDI_XXX062M[] = {
|
||||
{ MIPI_DCS_SET_DISPLAY_OFF, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{ MIPI_DCS_PRIV_UNK_D5,
|
||||
32,
|
||||
{ 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
|
||||
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
|
||||
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 } },
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL,
|
||||
10,
|
||||
{ 0x41, 0x0F, 0x4F, 0x33, 0xA4, 0x79, 0xF1, 0x81, 0x2D, 0x00 } },
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0x00, 0x00, 0x00 } },
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
{ MIPI_DCS_NOP, -1, { 0x00 } },
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_SAM_AMS699VC01[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
|
||||
// Set color mode to basic (natural). Stock is Saturated (0x00). (Reset value is 0x20).
|
||||
{ MIPI_DCS_PRIV_SM_SET_COLOR_MODE, 2, { 0x23, 0x0 } },
|
||||
|
||||
// Enable backlight and smooth PWM.
|
||||
{ MIPI_DCS_WRITE_CONTROL_DISPLAY, 2, { 0x28, 0x0 } },
|
||||
|
||||
// Unlock Level 2 registers.
|
||||
{ 0x05, 9, { 0x0, 0x0, 0xE2, 0x5A, 0x5A, 0x5A, 0x5A, 0x0, 0x0 } },
|
||||
|
||||
// Set registers offset and set PWM transition to 6 frames (100ms).
|
||||
{ MIPI_DCS_PRIV_SM_SET_REG_OFFSET, 2, { 0x07, 0x0 } },
|
||||
{ MIPI_DCS_PRIV_SM_SET_ELVSS, 2, { 0x06, 0x0 } },
|
||||
|
||||
// Relock Level 2 registers.
|
||||
{ 0x05, 9, { 0x0, 0x0, 0xE2, 0x5A, 0x5A, 0xA5, 0xA5, 0x0, 0x0 } },
|
||||
|
||||
// MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%.
|
||||
{ 0x03, 7, { 0x00, 0x00, 0x51, 0x0, 0x0, 0x0, 0x0 } },
|
||||
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_AUO_A062TAN01[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 6, { 0x48, 0x11, 0x71, 0x09, 0x32, 0x14 } },
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_AUO_A062TAN01[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_AUO_A055TAN01[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x11, 0x71, 0x09, 0x32, 0x14, 0x71, 0x31, 0x4D, 0x11 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd init_cmds_PANEL_INL_P062CCA_AZ1[] = {
|
||||
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
180,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 6, { 0x48, 0x15, 0x75, 0x09, 0x32, 0x14 } },
|
||||
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_INL_2J055IA_27A[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x15, 0x75, 0x09, 0x32, 0x14, 0x71, 0x31, 0x4D, 0x11 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_SHP_LQ055T1SW10[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x13, 0x73, 0x09, 0x32, 0x24, 0x71, 0x31, 0x4C, 0x00 } },
|
||||
{
|
||||
0xFF,
|
||||
5,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
50,
|
||||
},
|
||||
};
|
||||
|
||||
struct init_cmd suspend_cmds_PANEL_SAM_AMS699VC01[] = {
|
||||
{
|
||||
0xFF,
|
||||
100,
|
||||
},
|
||||
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
|
||||
{
|
||||
0xFF,
|
||||
120,
|
||||
},
|
||||
};
|
||||
|
||||
static inline struct nx_panel *to_nx_panel(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct nx_panel, base);
|
||||
}
|
||||
|
||||
static void nx_panel_detect(struct nx_panel *nx)
|
||||
{
|
||||
int ret;
|
||||
nx->init_cmds = NULL;
|
||||
nx->suspend_cmds = NULL;
|
||||
|
||||
printk("nx_panel_detect");
|
||||
|
||||
memset(&(nx->display_id), 0, sizeof(nx->display_id));
|
||||
|
||||
ret = mipi_dsi_dcs_read(nx->dsi, MIPI_DCS_GET_DISPLAY_ID,
|
||||
&(nx->display_id), sizeof(nx->display_id));
|
||||
if (ret < 0) {
|
||||
dev_err(&nx->dsi->dev, "failed to read panel ID: %d\n", ret);
|
||||
} else {
|
||||
dev_info(&nx->dsi->dev, "display ID[%d]: %04x\n",
|
||||
ret, nx->display_id);
|
||||
}
|
||||
|
||||
dev_info(&nx->dsi->dev,
|
||||
"setting init sequence for ID %04x\n", nx->display_id);
|
||||
|
||||
switch (nx->display_id) {
|
||||
case PANEL_JDI_XXX062M:
|
||||
nx->init_cmds = init_cmds_PANEL_JDI_XXX062M;
|
||||
break;
|
||||
case PANEL_SAM_AMS699VC01:
|
||||
nx->init_cmds = init_cmds_PANEL_SAM_AMS699VC01;
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
nx->init_cmds = init_cmds_PANEL_INL_P062CCA_AZ1;
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
nx->init_cmds = init_cmds_PANEL_AUO_A062TAN01;
|
||||
break;
|
||||
case PANEL_INL_2J055IA_27A:
|
||||
case PANEL_AUO_A055TAN01:
|
||||
case PANEL_SHP_LQ055T1SW10:
|
||||
default:
|
||||
dev_info(&nx->dsi->dev, "using default init sequence\n");
|
||||
nx->init_cmds = init_cmds_default;
|
||||
break;
|
||||
}
|
||||
|
||||
dev_info(&nx->dsi->dev,
|
||||
"setting suspend sequence for ID %04x\n", nx->display_id);
|
||||
|
||||
switch (nx->display_id) {
|
||||
case PANEL_JDI_XXX062M:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_JDI_XXX062M;
|
||||
break;
|
||||
case PANEL_AUO_A062TAN01:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_AUO_A062TAN01;
|
||||
break;
|
||||
case PANEL_INL_2J055IA_27A:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_INL_2J055IA_27A;
|
||||
break;
|
||||
case PANEL_AUO_A055TAN01:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_AUO_A055TAN01;
|
||||
break;
|
||||
case PANEL_SHP_LQ055T1SW10:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_SHP_LQ055T1SW10;
|
||||
break;
|
||||
case PANEL_SAM_AMS699VC01:
|
||||
nx->suspend_cmds = suspend_cmds_PANEL_SAM_AMS699VC01;
|
||||
break;
|
||||
case PANEL_INL_P062CCA_AZ1:
|
||||
default:
|
||||
dev_info(&nx->dsi->dev, "using default suspend sequence\n");
|
||||
break;
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
static int nx_mipi_dsi_dcs_cmds(struct init_cmd *cmds, struct nx_panel *nx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (cmds && cmds->length != -1) {
|
||||
if (cmds->cmd == 0xFF)
|
||||
msleep(cmds->length);
|
||||
else {
|
||||
ret = mipi_dsi_dcs_write(nx->dsi, cmds->cmd,
|
||||
cmds->data, cmds->length);
|
||||
if (ret < 0) {
|
||||
dev_err(&nx->dsi->dev,
|
||||
"failed to write dsi_cmd: %d error: %d\n",
|
||||
cmds->cmd, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
cmds++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nx_panel_init(struct nx_panel *nx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = nx->dsi;
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
printk("nx_panel_init");
|
||||
|
||||
ret = mipi_dsi_set_maximum_return_packet_size(dsi, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set maximum return packet size: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nx_panel_detect(nx);
|
||||
|
||||
ret = nx_mipi_dsi_dcs_cmds(nx->init_cmds, nx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mipi_dsi_dcs_set_column_address(dsi, 0, nx->mode->hdisplay - 1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set page address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_page_address(dsi, 0, nx->mode->vdisplay - 1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set column address: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set vblank tear on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to set pixel format: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
|
||||
if (nx->enabled)
|
||||
return 0;
|
||||
|
||||
backlight_enable(nx->backlight);
|
||||
|
||||
nx->enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
|
||||
if (!nx->enabled)
|
||||
return 0;
|
||||
|
||||
backlight_disable(nx->backlight);
|
||||
|
||||
nx->enabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
int ret;
|
||||
|
||||
if (!nx->prepared)
|
||||
return 0;
|
||||
|
||||
nx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = nx_mipi_dsi_dcs_cmds(nx->suspend_cmds, nx);
|
||||
if (ret < 0)
|
||||
dev_err(&nx->dsi->dev, "failed to write suspend cmds: %d\n",
|
||||
ret);
|
||||
|
||||
if (nx->reset_gpio)
|
||||
gpiod_set_value(nx->reset_gpio, 0);
|
||||
|
||||
msleep(10);
|
||||
regulator_disable(nx->supply2);
|
||||
msleep(10);
|
||||
regulator_disable(nx->supply1);
|
||||
|
||||
nx->prepared = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nx_panel_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
printk("nx panel prepare");
|
||||
|
||||
if (nx->prepared)
|
||||
return 0;
|
||||
|
||||
ret = regulator_enable(nx->supply1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(10);
|
||||
|
||||
ret = regulator_enable(nx->supply2);
|
||||
if (ret < 0)
|
||||
goto poweroff;
|
||||
msleep(10);
|
||||
|
||||
if (nx->reset_gpio) {
|
||||
gpiod_set_value(nx->reset_gpio, 0);
|
||||
msleep(10);
|
||||
gpiod_set_value(nx->reset_gpio, 1);
|
||||
msleep(60);
|
||||
}
|
||||
nx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
ret = nx_panel_init(nx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to init panel: %d\n", ret);
|
||||
goto reset;
|
||||
}
|
||||
|
||||
nx->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
||||
reset:
|
||||
if (nx->reset_gpio)
|
||||
gpiod_set_value(nx->reset_gpio, 0);
|
||||
regulator_disable(nx->supply2);
|
||||
|
||||
poweroff:
|
||||
regulator_disable(nx->supply1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode default_mode = {
|
||||
.clock = 78000,
|
||||
.hdisplay = 720,
|
||||
.hsync_start = 720 + 136,
|
||||
.hsync_end = 720 + 136 + 72,
|
||||
.htotal = 720 + 136 + 72 + 72,
|
||||
.vdisplay = 1280,
|
||||
.vsync_start = 1280 + 10,
|
||||
.vsync_end = 1280 + 10 + 2,
|
||||
.vtotal = 1280 + 10 + 1 + 9,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static int nx_panel_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct nx_panel *nx = to_nx_panel(panel);
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
|
||||
printk("nx panel get_modes");
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, &default_mode);
|
||||
if (!mode) {
|
||||
dev_err(dev, "failed to add mode %ux%ux@%u\n",
|
||||
default_mode.hdisplay, default_mode.vdisplay,
|
||||
drm_mode_vrefresh(&default_mode));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
connector->display_info.width_mm = 77;
|
||||
connector->display_info.height_mm = 137;
|
||||
connector->display_info.bpc = 8;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs nx_panel_funcs = {
|
||||
.prepare = nx_panel_prepare,
|
||||
.unprepare = nx_panel_unprepare,
|
||||
.enable = nx_panel_enable,
|
||||
.disable = nx_panel_disable,
|
||||
.get_modes = nx_panel_get_modes,
|
||||
};
|
||||
|
||||
static int nx_panel_add(struct nx_panel *nx)
|
||||
{
|
||||
struct device *dev = &nx->dsi->dev;
|
||||
struct device_node *np;
|
||||
|
||||
printk("nx_panel_add");
|
||||
|
||||
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);
|
||||
|
||||
printk("backlight");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
printk("panel init");
|
||||
|
||||
drm_panel_init(&nx->base, &nx->dsi->dev, &nx_panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
printk("drm panel add");
|
||||
|
||||
drm_panel_add(&nx->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nx_panel_del(struct nx_panel *nx)
|
||||
{
|
||||
if (nx->base.dev)
|
||||
drm_panel_remove(&nx->base);
|
||||
|
||||
if (nx->backlight)
|
||||
put_device(&nx->backlight->dev);
|
||||
}
|
||||
|
||||
static int nx_panel_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct nx_panel *nx;
|
||||
int ret;
|
||||
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS |
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
printk("nx_panel_probe");
|
||||
|
||||
nx = devm_kzalloc(&dsi->dev, sizeof(*nx), GFP_KERNEL);
|
||||
if (!nx)
|
||||
return -ENOMEM;
|
||||
|
||||
printk("set drvdata");
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, nx);
|
||||
|
||||
nx->dsi = dsi;
|
||||
|
||||
printk("add panel");
|
||||
|
||||
ret = nx_panel_add(nx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
printk("dsi attach");
|
||||
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;
|
||||
|
||||
printk("nx_panel_remove");
|
||||
|
||||
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", },
|
||||
|
||||
+139
-38
@@ -54,6 +54,21 @@ to_dsi_state(struct drm_connector_state *state)
|
||||
return container_of(state, struct tegra_dsi_state, base);
|
||||
}
|
||||
|
||||
/*
|
||||
* remap of registers revised in Tegra210B01
|
||||
*/
|
||||
struct dsi_regmap {
|
||||
int init_seq_data_15;
|
||||
int slew_impedance[4];
|
||||
int preemphasis;
|
||||
int bias;
|
||||
int ganged_mode_control;
|
||||
int ganged_mode_start;
|
||||
int ganged_mode_size;
|
||||
int dbg_regs_cnt;
|
||||
struct debugfs_reg32 dbg_regs_ext[16];
|
||||
};
|
||||
|
||||
struct tegra_dsi {
|
||||
struct host1x_client client;
|
||||
struct tegra_output output;
|
||||
@@ -83,6 +98,8 @@ struct tegra_dsi {
|
||||
/* for ganged-mode support */
|
||||
struct tegra_dsi *master;
|
||||
struct tegra_dsi *slave;
|
||||
|
||||
const struct dsi_regmap *regmap;
|
||||
};
|
||||
|
||||
static inline struct tegra_dsi *
|
||||
@@ -124,7 +141,7 @@ static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value,
|
||||
|
||||
#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
|
||||
|
||||
static const struct debugfs_reg32 tegra_dsi_regs[] = {
|
||||
static const struct debugfs_reg32 tegra_dsi_regs_common[] = {
|
||||
DEBUGFS_REG32(DSI_INCR_SYNCPT),
|
||||
DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL),
|
||||
DEBUGFS_REG32(DSI_INCR_SYNCPT_ERROR),
|
||||
@@ -183,19 +200,6 @@ static const struct debugfs_reg32 tegra_dsi_regs[] = {
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_2),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_3),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_4),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_START),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE),
|
||||
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT),
|
||||
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15),
|
||||
};
|
||||
|
||||
static int tegra_dsi_show_regs(struct seq_file *s, void *data)
|
||||
@@ -214,10 +218,17 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs); i++) {
|
||||
unsigned int offset = tegra_dsi_regs[i].offset;
|
||||
for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs_common); i++) {
|
||||
unsigned int offset = tegra_dsi_regs_common[i].offset;
|
||||
|
||||
seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs[i].name,
|
||||
seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs_common[i].name,
|
||||
offset, tegra_dsi_readl(dsi, offset));
|
||||
}
|
||||
|
||||
for (i = 0; i < dsi->regmap->dbg_regs_cnt; i++) {
|
||||
unsigned int offset = dsi->regmap->dbg_regs_ext[i].offset;
|
||||
|
||||
seq_printf(s, "%-32s %#05x %08x\n", dsi->regmap->dbg_regs_ext[i].name,
|
||||
offset, tegra_dsi_readl(dsi, offset));
|
||||
}
|
||||
|
||||
@@ -448,11 +459,11 @@ static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start,
|
||||
{
|
||||
u32 value;
|
||||
|
||||
tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START);
|
||||
tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE);
|
||||
tegra_dsi_writel(dsi, start, dsi->regmap->ganged_mode_start);
|
||||
tegra_dsi_writel(dsi, size << 16 | size, dsi->regmap->ganged_mode_size);
|
||||
|
||||
value = DSI_GANGED_MODE_CONTROL_ENABLE;
|
||||
tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL);
|
||||
tegra_dsi_writel(dsi, value, dsi->regmap->ganged_mode_control);
|
||||
}
|
||||
|
||||
static void tegra_dsi_enable(struct tegra_dsi *dsi)
|
||||
@@ -656,9 +667,9 @@ static void tegra_dsi_video_disable(struct tegra_dsi *dsi)
|
||||
|
||||
static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
|
||||
{
|
||||
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
|
||||
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
|
||||
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_start);
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_size);
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_control);
|
||||
}
|
||||
|
||||
static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
|
||||
@@ -674,7 +685,7 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
|
||||
static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
|
||||
{
|
||||
u32 value;
|
||||
int err;
|
||||
int err, i;
|
||||
|
||||
/*
|
||||
* XXX Is this still needed? The module reset is deasserted right
|
||||
@@ -682,21 +693,29 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
|
||||
*/
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
|
||||
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
|
||||
for (i = 0; i < ARRAY_SIZE(dsi->regmap->slew_impedance); i++) {
|
||||
if (dsi->regmap->slew_impedance[i])
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->slew_impedance[i]);
|
||||
}
|
||||
|
||||
/* start calibration */
|
||||
tegra_dsi_pad_enable(dsi);
|
||||
|
||||
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
|
||||
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
|
||||
DSI_PAD_OUT_CLK(0x0);
|
||||
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
|
||||
/* do not set padctl 2 slew by default */
|
||||
if (of_property_read_bool(dsi->dev->of_node, "nvidia,slew-enable")) {
|
||||
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
|
||||
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
|
||||
DSI_PAD_OUT_CLK(0x0);
|
||||
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
|
||||
}
|
||||
|
||||
value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
|
||||
value = tegra_dsi_readl(dsi, dsi->regmap->preemphasis);
|
||||
|
||||
value |= DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
|
||||
DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
|
||||
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
|
||||
tegra_dsi_writel(dsi, value, dsi->regmap->preemphasis);
|
||||
|
||||
tegra_dsi_writel(dsi, 0, dsi->regmap->bias);
|
||||
|
||||
err = tegra_mipi_start_calibration(dsi->mipi);
|
||||
if (err < 0)
|
||||
@@ -1069,7 +1088,7 @@ static int tegra_dsi_init(struct host1x_client *client)
|
||||
dev_err(dsi->dev, "failed to initialize output: %d\n",
|
||||
err);
|
||||
|
||||
dsi->output.encoder.possible_crtcs = 0x3;
|
||||
tegra_output_find_possible_crtcs(&dsi->output, drm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1633,6 +1652,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
|
||||
goto remove;
|
||||
}
|
||||
|
||||
dsi->regmap = of_device_get_match_data(&pdev->dev);
|
||||
if (IS_ERR(dsi->regmap)) {
|
||||
err = PTR_ERR(dsi->regmap);
|
||||
goto remove;
|
||||
}
|
||||
|
||||
dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
|
||||
if (IS_ERR(dsi->mipi)) {
|
||||
err = PTR_ERR(dsi->mipi);
|
||||
@@ -1688,11 +1713,87 @@ static void tegra_dsi_remove(struct platform_device *pdev)
|
||||
tegra_mipi_free(dsi->mipi);
|
||||
}
|
||||
|
||||
static const struct dsi_regmap tegra_dsi_regmap = {
|
||||
.init_seq_data_15 = DSI_INIT_SEQ_DATA_15,
|
||||
.slew_impedance = { DSI_PAD_CONTROL_2 },
|
||||
.preemphasis = DSI_PAD_CONTROL_3,
|
||||
.bias = DSI_PAD_CONTROL_4,
|
||||
.ganged_mode_control = DSI_GANGED_MODE_CONTROL,
|
||||
.ganged_mode_start = DSI_GANGED_MODE_START,
|
||||
.ganged_mode_size = DSI_GANGED_MODE_SIZE,
|
||||
.dbg_regs_cnt = 13,
|
||||
.dbg_regs_ext = {
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_START),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE),
|
||||
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT),
|
||||
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct dsi_regmap tegra_dsi_regmap_b01 = {
|
||||
.init_seq_data_15 = DSI_INIT_SEQ_DATA_15_B01,
|
||||
.slew_impedance = {
|
||||
DSI_PAD_CONTROL_2,
|
||||
DSI_PAD_CONTROL_3,
|
||||
DSI_PAD_CONTROL_4,
|
||||
DSI_PAD_CONTROL_5_B01,
|
||||
},
|
||||
.preemphasis = DSI_PAD_CONTROL_6_B01,
|
||||
.bias = DSI_PAD_CONTROL_7_B01,
|
||||
.ganged_mode_control = DSI_GANGED_MODE_CONTROL_B01,
|
||||
.ganged_mode_start = DSI_GANGED_MODE_START_B01,
|
||||
.ganged_mode_size = DSI_GANGED_MODE_SIZE_B01,
|
||||
.dbg_regs_cnt = 16,
|
||||
.dbg_regs_ext = {
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_5_B01),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_6_B01),
|
||||
DEBUGFS_REG32(DSI_PAD_CONTROL_7_B01),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL_B01),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_START_B01),
|
||||
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE_B01),
|
||||
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT_B01),
|
||||
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14_B01),
|
||||
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15_B01),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_dsi_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra210-dsi", },
|
||||
{ .compatible = "nvidia,tegra132-dsi", },
|
||||
{ .compatible = "nvidia,tegra124-dsi", },
|
||||
{ .compatible = "nvidia,tegra114-dsi", },
|
||||
{
|
||||
.compatible = "nvidia,tegra210b01-dsi",
|
||||
.data = &tegra_dsi_regmap_b01
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra210-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra132-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra124-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{
|
||||
.compatible = "nvidia,tegra114-dsi",
|
||||
.data = &tegra_dsi_regmap
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
|
||||
|
||||
@@ -130,6 +130,24 @@
|
||||
#define DSI_INIT_SEQ_DATA_14 0x5e
|
||||
#define DSI_INIT_SEQ_DATA_15 0x5f
|
||||
|
||||
// Tegra210B01 has a revised set of regs
|
||||
#define DSI_PAD_CONTROL_5_B01 0x53
|
||||
#define DSI_PAD_CONTROL_6_B01 0x54
|
||||
#define DSI_PAD_CONTROL_7_B01 0x55
|
||||
#define DSI_GANGED_MODE_CONTROL_B01 0x56
|
||||
#define DSI_GANGED_MODE_START_B01 0x57
|
||||
#define DSI_GANGED_MODE_SIZE_B01 0x58
|
||||
#define DSI_RAW_DATA_BYTE_COUNT_B01 0x59
|
||||
#define DSI_ULTRA_LOW_POWER_CONTROL_B01 0x5a
|
||||
#define DSI_INIT_SEQ_DATA_8_B01 0x5b
|
||||
#define DSI_INIT_SEQ_DATA_9_B01 0x5c
|
||||
#define DSI_INIT_SEQ_DATA_10_B01 0x5d
|
||||
#define DSI_INIT_SEQ_DATA_11_B01 0x5e
|
||||
#define DSI_INIT_SEQ_DATA_12_B01 0x5f
|
||||
#define DSI_INIT_SEQ_DATA_13_B01 0x60
|
||||
#define DSI_INIT_SEQ_DATA_14_B01 0x61
|
||||
#define DSI_INIT_SEQ_DATA_15_B01 0x62
|
||||
|
||||
/*
|
||||
* pixel format as used in the DSI_CONTROL_FORMAT field
|
||||
*/
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -11,6 +11,7 @@ menuconfig INPUT_TOUCHSCREEN
|
||||
If unsure, say Y.
|
||||
|
||||
if INPUT_TOUCHSCREEN
|
||||
source "drivers/input/touchscreen/stm/Kconfig"
|
||||
|
||||
config TOUCHSCREEN_88PM860X
|
||||
tristate "Marvell 88PM860x touchscreen"
|
||||
|
||||
@@ -119,3 +119,4 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_IQS7211) += iqs7211.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_FTM4) += stm/
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# STMicroelectronics TOUCH driver configuration
|
||||
#
|
||||
|
||||
config TOUCHSCREEN_FTM4
|
||||
tristate "STMicroelectronics i2c multitouch touchscreen - FTM4 with FingerTipS"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to enable STMicroelectronics touchscreen support.
|
||||
If unsure, say N.
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called fts_touch.
|
||||
|
||||
config TOUCHSCREEN_FTM4_SHOW_EVENTS
|
||||
bool "Enable debug of FTM4 events"
|
||||
depends on TOUCHSCREEN_FTM4
|
||||
help
|
||||
Say Y here to enable dumping of touch driver events. This should
|
||||
only be enabled for debugging and not for shipping code.
|
||||
@@ -0,0 +1,3 @@
|
||||
# FTM4 driver
|
||||
obj-$(CONFIG_TOUCHSCREEN_FTM4) += ftm4.o
|
||||
ftm4-objs += ftm4_ts.o
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,374 @@
|
||||
/******************************** FingerTipS 4CD60D ****************************
|
||||
*
|
||||
* File Name : fts.c
|
||||
* Authors : Copyright (c) 2012 STMicroelectronics, Analog Mems Sensor Team
|
||||
* Copyright (c) 2019-2020 Billy Laws <blaws05@gmail.com>
|
||||
* Copyright (c) 2019-2021 Kostas Missos <ctcaer@gmail.com>
|
||||
* Description : FTS Capacitive touch screen controller (FingerTipS)
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
|
||||
* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
|
||||
* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
|
||||
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
|
||||
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
|
||||
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LINUX_FTM4_TS_H_
|
||||
#define _LINUX_FTM4_TS_H_
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
#include <linux/printk.h>
|
||||
#define tsp_debug_dbg(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
|
||||
#define tsp_debug_info(dev, fmt, ...) dev_info(dev, fmt, ## __VA_ARGS__)
|
||||
#define tsp_debug_err(dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__)
|
||||
#ifdef CONFIG_TOUCHSCREEN_FTM4_SHOW_EVENTS
|
||||
#define tsp_debug_event(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define tsp_debug_event(dev, fmt, ...)
|
||||
#endif
|
||||
|
||||
#define FTS_INPUT_OPEN_DWORK_TIME 10
|
||||
|
||||
#define FTS_TS_DRV_NAME "fts_touch"
|
||||
#define FTS_TS_DRV_VERSION "4CD60D"
|
||||
|
||||
#define STM_DEVICE_NAME "STM"
|
||||
|
||||
#define FTS_ID0 0x36
|
||||
#define FTS_ID1 0x70
|
||||
|
||||
#define FTS_DIGITAL_REV_1 0x01
|
||||
#define FTS_DIGITAL_REV_2 0x02
|
||||
#define FTS_FIFO_MAX 32
|
||||
#define FTS_EVENT_SIZE 8
|
||||
#define FTS_FW_UPDATE_RETRY 3
|
||||
#define FTS_LOCKDOWNCODE_SIZE 13
|
||||
|
||||
#define PRESSURE_MIN 0
|
||||
#define PRESSURE_MAX 500
|
||||
#define FINGER_MAX 10
|
||||
|
||||
#define EVENTID_NO_EVENT 0x00
|
||||
#define EVENTID_ENTER_POINTER 0x03
|
||||
#define EVENTID_LEAVE_POINTER 0x04
|
||||
#define EVENTID_HOS_EVENT 0x04
|
||||
#define EVENTID_MOTION_POINTER 0x05
|
||||
#define EVENTID_HOVER_ENTER_POINTER 0x07
|
||||
#define EVENTID_HOVER_LEAVE_POINTER 0x08
|
||||
#define EVENTID_MOTION_POINTER 0x05
|
||||
#define EVENTID_HOVER_MOTION_POINTER 0x09
|
||||
#define EVENTID_PROXIMITY_IN 0x0B
|
||||
#define EVENTID_PROXIMITY_OUT 0x0C
|
||||
#define EVENTID_MSKEY 0x0E
|
||||
#define EVENTID_ERROR 0x0F
|
||||
#define EVENTID_CONTROLLER_READY 0x10
|
||||
#define EVENTID_SLEEPOUT_CONTROLLER_READY 0x11
|
||||
#define EVENTID_RESULT_READ_REGISTER 0x12
|
||||
#define EVENTID_STATUS_REQUEST_COMP 0x13
|
||||
|
||||
#define EVENTID_STATUS_EVENT 0x16
|
||||
#define EVENTID_INTERNAL_RELEASE_INFO 0x14
|
||||
#define EVENTID_EXTERNAL_RELEASE_INFO 0x15
|
||||
|
||||
#define EVENTID_FROM_STRING 0x80
|
||||
#define EVENTID_GESTURE 0x20
|
||||
|
||||
#define EVENTID_SIDE_SCROLL 0x40
|
||||
/* side touch event-id for debug, remove after f/w fixed */
|
||||
#define EVENTID_SIDE_TOUCH_DEBUG 0xDB
|
||||
#define EVENTID_SIDE_TOUCH 0x0B
|
||||
|
||||
#define EVENTID_ERROR_FLASH_CORRUPTION 0x03
|
||||
|
||||
/* define flash corruption type */
|
||||
#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_1 0x01
|
||||
#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_2 0x02
|
||||
#define EVENTID_ERROR_CX_FLASH_CORRUPTION 0x03
|
||||
|
||||
#define EVENTID_LOCKDOWN_CODE 0x1E
|
||||
#define EVENTID_ERROR_LOCKDOWN 0x0B
|
||||
|
||||
#define STATUS_EVENT_MS_CX_TUNING_DONE 0x01
|
||||
#define STATUS_EVENT_SS_CX_TUNING_DONE 0x02
|
||||
#define STATUS_EVENT_FLASH_WRITE_CONFIG 0x03
|
||||
#define STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE 0x04
|
||||
#define STATUS_EVENT_FORCE_CAL_MUTUAL_SELF 0x05
|
||||
#define STATUS_EVENT_FORCE_CAL_DONE 0x06
|
||||
|
||||
#define STATUS_EVENT_FORCE_CAL_MUTUAL 0x15
|
||||
#define STATUS_EVENT_FORCE_CAL_SELF 0x06
|
||||
#define STATUS_EVENT_PARAM1_FCAL_MS_SS_DONE 0x23
|
||||
#define STATUS_EVENT_WATERMODE_ON 0x07
|
||||
#define STATUS_EVENT_WATERMODE_OFF 0x08
|
||||
#define STATUS_EVENT_RTUNE_MUTUAL 0x09
|
||||
#define STATUS_EVENT_RTUNE_SELF 0x0A
|
||||
#define STATUS_EVENT_PANEL_TEST_RESULT 0x0B
|
||||
#define STATUS_EVENT_GLOVE_MODE 0x0C
|
||||
#define STATUS_EVENT_RAW_DATA_READY 0x0D
|
||||
#define STATUS_EVENT_MUTUAL_CAL_FRAME_CHECK 0xC1
|
||||
#define STATUS_EVENT_SELF_CAL_FRAME_CHECK 0xC2
|
||||
#define STATUS_EVENT_CHARGER_CONNECTED 0xCC
|
||||
#define STATUS_EVENT_CHARGER_DISCONNECTED 0xCD
|
||||
#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_WRITE_FINISH 0x10
|
||||
#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_CLEAR_FINISH 0x11
|
||||
|
||||
#define INT_ENABLE 0x48
|
||||
#define INT_DISABLE 0x08
|
||||
|
||||
#define FTS_READ_STATUS 0x84
|
||||
#define FTS_READ_ONE_EVENT 0x85
|
||||
#define FTS_READ_ALL_EVENT 0x86
|
||||
|
||||
#define FTS_CMD_SENSEOFF 0x92
|
||||
#define FTS_CMD_SENSEON 0x93
|
||||
#define FTS_CMD_HOVER_OFF 0x94
|
||||
#define FTS_CMD_HOVER_ON 0x95
|
||||
|
||||
#define FTS_CMD_MSKEY_AUTOTUNE 0x96
|
||||
#define FTS_CMD_TRIM_LOW_POWER_OSCILLATOR 0x97
|
||||
|
||||
#define FTS_CMD_KEY_SENSE_OFF 0x9A
|
||||
#define FTS_CMD_KEY_SENSE_ON 0x9B
|
||||
#define FTS_CMD_SET_FAST_GLOVE_MODE 0x9D
|
||||
|
||||
#define FTS_CMD_MSHOVER_OFF 0x9E
|
||||
#define FTS_CMD_MSHOVER_ON 0x9F
|
||||
#define FTS_CMD_SET_NOR_GLOVE_MODE 0x9F
|
||||
|
||||
#define FTS_CMD_FLUSHBUFFER 0xA1
|
||||
#define FTS_CMD_FORCECALIBRATION 0xA2
|
||||
#define FTS_CMD_MS_CX_TUNING 0xA3
|
||||
#define FTS_CMD_SS_CX_TUNING 0xA4
|
||||
|
||||
#define FTS_CMD_ITO_CHECK 0xA7
|
||||
|
||||
#define FTS_CMD_CHARGER_PLUGGED 0xA8
|
||||
#define FTS_CMD_CHARGER_UNPLUGGED 0xAB
|
||||
|
||||
#define FTS_CMD_RELEASEINFO 0xAA
|
||||
#define FTS_CMD_STYLUS_OFF 0xAB
|
||||
#define FTS_CMD_STYLUS_ON 0xAC
|
||||
#define FTS_CMD_LOWPOWER_MODE 0xAD
|
||||
|
||||
#define FTS_CMD_WRITE_REG 0xB6
|
||||
|
||||
#define FTS_CMS_ENABLE_FEATURE 0xC1
|
||||
#define FTS_CMS_DISABLE_FEATURE 0xC2
|
||||
#define FTS_CMD_SWITCH_SENSE_MODE 0xC3
|
||||
#define FTS_CMD_LOCKDOWN_READ 0xC4
|
||||
|
||||
#define FTS_CMD_WRITE_PRAM 0xF0
|
||||
#define FTS_CMD_BURN_PROG_FLASH 0xF2
|
||||
#define FTS_CMD_ERASE_PROG_FLASH 0xF3
|
||||
#define FTS_CMD_READ_FLASH_STAT 0xF4
|
||||
#define FTS_CMD_UNLOCK_FLASH 0xF7
|
||||
#define FTS_CMD_SAVE_FWCONFIG 0xFB
|
||||
#define FTS_CMD_SAVE_CX_TUNING 0xFC
|
||||
|
||||
#define FTS_CMD_FAST_SCAN 0x01
|
||||
#define FTS_CMD_SLOW_SCAN 0x02
|
||||
#define FTS_CMD_USLOW_SCAN 0x03
|
||||
|
||||
#define FTS_STYLUS_MODE 0x00
|
||||
#define FTS_FINGER_MODE 0x01
|
||||
#define FTS_HOVER_MODE 0x02
|
||||
|
||||
#define FTS_REPORT_RATE_90HZ 0
|
||||
#define FTS_REPORT_RATE_60HZ 1
|
||||
#define FTS_REPORT_RATE_30HZ 2
|
||||
|
||||
#define FTS_CMD_STRING_ACCESS 0xEC00
|
||||
#define FTS_CMD_NOTIFY 0xC0
|
||||
|
||||
#define FTS_RETRY_COUNT 10
|
||||
|
||||
/* QUICK SHOT : Quick Camera Launching */
|
||||
#define FTS_STRING_EVENT_REAR_CAM (1 << 0)
|
||||
#define FTS_STRING_EVENT_FRONT_CAM (1 << 1)
|
||||
|
||||
/* SCRUB : Display Watch, Event Status / Fast Access Event */
|
||||
#define FTS_STRING_EVENT_WATCH_STATUS (1 << 2)
|
||||
#define FTS_STRING_EVENT_FAST_ACCESS (1 << 3)
|
||||
#define FTS_STRING_EVENT_DIRECT_INDICATOR ((1 << 3) | (1 << 2))
|
||||
#define FTS_STRING_EVENT_SPAY (1 << 4)
|
||||
#define FTS_STRING_EVENT_SPAY1 (1 << 5)
|
||||
#define FTS_STRING_EVENT_SPAY2 ((1 << 4) | (1 << 5))
|
||||
|
||||
#define FTS_SIDEGESTURE_EVENT_SINGLE_STROKE 0xE0
|
||||
#define FTS_SIDEGESTURE_EVENT_DOUBLE_STROKE 0xE1
|
||||
#define FTS_SIDEGESTURE_EVENT_INNER_STROKE 0xE3
|
||||
|
||||
#define FTS_SIDETOUCH_EVENT_LONG_PRESS 0xBB
|
||||
#define FTS_SIDETOUCH_EVENT_REBOOT_BY_ESD 0xED
|
||||
|
||||
#define FTS_ENABLE 1
|
||||
#define FTS_DISABLE 0
|
||||
|
||||
#define FTS_MODE_QUICK_SHOT (1 << 0)
|
||||
#define FTS_MODE_SCRUB (1 << 1)
|
||||
#define FTS_MODE_SPAY (1 << 1)
|
||||
#define FTS_MODE_QUICK_APP_ACCESS (1 << 2)
|
||||
#define FTS_MODE_DIRECT_INDICATOR (1 << 3)
|
||||
|
||||
#define TSP_BUF_SIZE 2048
|
||||
#define CMD_STR_LEN 32
|
||||
#define CMD_RESULT_STR_LEN 2048
|
||||
#define CMD_PARAM_NUM 8
|
||||
|
||||
#define FTS_LOWP_FLAG_QUICK_CAM (1 << 0)
|
||||
#define FTS_LOWP_FLAG_2ND_SCREEN (1 << 1)
|
||||
#define FTS_LOWP_FLAG_BLACK_UI (1 << 2)
|
||||
#define FTS_LOWP_FLAG_QUICK_APP_ACCESS (1 << 3)
|
||||
#define FTS_LOWP_FLAG_DIRECT_INDICATOR (1 << 4)
|
||||
#define FTS_LOWP_FLAG_SPAY (1 << 5)
|
||||
#define FTS_LOWP_FLAG_TEMP_CMD (1 << 6)
|
||||
|
||||
enum fts_error_return {
|
||||
FTS_NOT_ERROR = 0,
|
||||
FTS_ERROR_INVALID_CHIP_ID,
|
||||
FTS_ERROR_INVALID_CHIP_VERSION_ID,
|
||||
FTS_ERROR_INVALID_SW_VERSION,
|
||||
FTS_ERROR_EVENT_ID,
|
||||
FTS_ERROR_TIMEOUT,
|
||||
FTS_ERROR_FW_UPDATE_FAIL,
|
||||
};
|
||||
#define RAW_MAX 3750
|
||||
/**
|
||||
* struct fts_finger - Represents fingers.
|
||||
* @ state: finger status (Event ID).
|
||||
* @ mcount: moving counter for debug.
|
||||
*/
|
||||
struct fts_finger {
|
||||
unsigned char state;
|
||||
int lx;
|
||||
int ly;
|
||||
};
|
||||
|
||||
enum tsp_power_mode {
|
||||
FTS_POWER_STATE_ACTIVE = 0,
|
||||
FTS_POWER_STATE_POWERDOWN,
|
||||
};
|
||||
|
||||
enum fts_customer_feature {
|
||||
FTS_FEATURE_ORIENTATION_GESTURE = 1,
|
||||
FTS_FEATURE_STYLUS,
|
||||
FTS_FEATURE_QUICK_SHORT_CAMERA_ACCESS,
|
||||
FTS_FEATURE_SIDE_GUSTURE,
|
||||
FTS_FEATURE_COVER_GLASS,
|
||||
FTS_FEATURE_COVER_WALLET,
|
||||
FTS_FEATURE_COVER_LED,
|
||||
FTS_FEATURE_COVER_CLEAR_FLIP,
|
||||
FTS_FEATURE_DUAL_SIDE_GUSTURE,
|
||||
FTS_FEATURE_CUSTOM_COVER_GLASS_ON,
|
||||
};
|
||||
|
||||
struct fts_flash_corruption_info {
|
||||
bool fw_broken;
|
||||
bool cfg_broken;
|
||||
bool cx_broken;
|
||||
};
|
||||
|
||||
struct fts_i2c_platform_data {
|
||||
bool disable_tuning;
|
||||
bool delayed_open;
|
||||
unsigned int delayed_open_time;
|
||||
int max_x;
|
||||
int max_y;
|
||||
|
||||
struct regulator *regulator_dvdd;
|
||||
struct regulator *regulator_avdd;
|
||||
|
||||
int (*power)(void *data, bool on);
|
||||
|
||||
unsigned gpio;
|
||||
int vdd_gpio;
|
||||
int vio_gpio;
|
||||
int irq_type;
|
||||
|
||||
int coord_factor;
|
||||
int x_axis_real_max;
|
||||
int y_axis_real_max;
|
||||
int x_axis_edge_offset;
|
||||
int y_axis_edge_offset;
|
||||
};
|
||||
|
||||
struct fts_ts_info {
|
||||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
struct work_struct work;
|
||||
|
||||
int irq;
|
||||
int irq_type;
|
||||
atomic_t irq_enabled;
|
||||
struct fts_i2c_platform_data *board;
|
||||
|
||||
bool run_autotune;
|
||||
|
||||
int power_state;
|
||||
int touch_count;
|
||||
struct fts_finger finger[FINGER_MAX];
|
||||
bool palm_pressed;
|
||||
int palm_touch_id;
|
||||
|
||||
int touch_mode;
|
||||
|
||||
struct delayed_work open_work;
|
||||
|
||||
struct mutex i2c_mutex;
|
||||
struct mutex device_mutex;
|
||||
spinlock_t lock;
|
||||
|
||||
unsigned char data[FTS_EVENT_SIZE * FTS_FIFO_MAX];
|
||||
|
||||
struct fts_flash_corruption_info flash_corruption_info;
|
||||
};
|
||||
|
||||
#define WRITE_CHUNK_SIZE 32
|
||||
#define FLASH_CHUNK (64 * 1024)
|
||||
#define DMA_CHUNK 32
|
||||
|
||||
#define FW_HEADER_SIZE 64
|
||||
#define FW_HEADER_FTB_SIGNATURE 0xAA55AA55
|
||||
#define FW_FTB_VER 0x00000001
|
||||
#define FW_BYTES_ALLIGN 4
|
||||
#define FW_BIN_VER_OFFSET 16
|
||||
#define FW_BIN_CONFIG_VER_OFFSET 20
|
||||
|
||||
/* Command for flash */
|
||||
#define FLASH_CMD_UNLOCK 0xF7
|
||||
#define FLASH_CMD_WRITE_64K 0xF8
|
||||
#define FLASH_CMD_READ_REGISTER 0xF9
|
||||
#define FLASH_CMD_WRITE_REGISTER 0xFA
|
||||
|
||||
/* Parameters for commands */
|
||||
#define ADDR_WARM_BOOT 0x001E
|
||||
#define WARM_BOOT_VALUE 0x38
|
||||
#define FLASH_ADDR_CODE 0x00000000
|
||||
#define FLASH_ADDR_CONFIG 0x0000FC00
|
||||
|
||||
#define FLASH_UNLOCK_CODE0 0x74
|
||||
#define FLASH_UNLOCK_CODE1 0x45
|
||||
|
||||
#define FLASH_ERASE_UNLOCK_CODE0 0x72
|
||||
#define FLASH_ERASE_UNLOCK_CODE1 0x03
|
||||
#define FLASH_ERASE_UNLOCK_CODE2 0x02
|
||||
#define FLASH_ERASE_CODE0 0x02
|
||||
#define FLASH_ERASE_CODE1 0xC0
|
||||
#define FLASH_DMA_CODE0 0x05
|
||||
#define FLASH_DMA_CODE1 0xC0
|
||||
#define FLASH_DMA_CONFIG 0x06
|
||||
|
||||
#endif /* _LINUX_FTM4_TS_H_ */
|
||||
@@ -545,6 +545,10 @@ int tegra30_mc_probe(struct tegra_mc *mc)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -443,6 +443,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
|
||||
if (!emc)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&emc->rate_lock);
|
||||
|
||||
emc->bpmp = tegra_bpmp_get(&pdev->dev);
|
||||
if (IS_ERR(emc->bpmp))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp),
|
||||
@@ -521,6 +523,9 @@ static const struct of_device_id tegra186_emc_of_match[] = {
|
||||
#if defined(CONFIG_ARCH_TEGRA_186_SOC)
|
||||
{ .compatible = "nvidia,tegra186-emc" },
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
{ .compatible = "nvidia,tegra210b01-emc" },
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_TEGRA_194_SOC)
|
||||
{ .compatible = "nvidia,tegra194-emc" },
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Author: Mike Rapoport <mike@compulab.co.il>
|
||||
*
|
||||
* Based on NVIDIA PCIe driver
|
||||
* Copyright (c) 2008-2009, NVIDIA Corporation.
|
||||
* Copyright (c) 2008-2020, NVIDIA Corporation.
|
||||
*
|
||||
* Bits taken from arch/arm/mach-dove/pcie.c
|
||||
*
|
||||
@@ -165,10 +165,61 @@
|
||||
|
||||
#define AFI_PLLE_CONTROL 0x160
|
||||
#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
|
||||
#define AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL (1 << 8)
|
||||
#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
|
||||
#define AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN (1 << 0)
|
||||
|
||||
#define AFI_PEXBIAS_CTRL_0 0x168
|
||||
|
||||
|
||||
#define RP_PRIV_XP_DL 0x00000494
|
||||
#define RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD (0x1ff << 1)
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_CTL 0xc00
|
||||
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2 (0x1 << 0)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1 (0x1 << 1)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2 (0x1 << 2)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1 (0x1 << 3)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK (0xff << 8)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT 8
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK (0x3 << 16)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT 16
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK (0x1f << 19)
|
||||
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT 19
|
||||
#define RP_L1_PM_SUBSTATES_CTL_HIDE_CAP (0x1 << 24)
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_1_CTL 0xc04
|
||||
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK 0x1fff
|
||||
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY 0x26
|
||||
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK (0x1ff << 13)
|
||||
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY (0x27 << 13)
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL 0xc08
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK 0x1fff
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY 0x4d
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK (0xff << 13)
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND (0x13 << 13)
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK (0xf << 21)
|
||||
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP (0x2 << 21)
|
||||
|
||||
#define RP_RX_HDR_LIMIT 0x00000e00
|
||||
#define RP_RX_HDR_LIMIT_PW_MASK (0xff << 8)
|
||||
#define RP_RX_HDR_LIMIT_PW (0x0e << 8)
|
||||
|
||||
#define RP_TIMEOUT0 0xe24
|
||||
#define RP_TIMEOUT0_PAD_PWRUP_MASK 0xff
|
||||
#define RP_TIMEOUT0_PAD_PWRUP 0xa
|
||||
#define RP_TIMEOUT0_PAD_PWRUP_CM_MASK 0xffff00
|
||||
#define RP_TIMEOUT0_PAD_PWRUP_CM (0x180 << 8)
|
||||
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK (0xff << 24)
|
||||
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2 (0xa << 24)
|
||||
|
||||
#define RP_TIMEOUT1 0xe28
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK (0xff << 16)
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE (0x10 << 16)
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK (0xff << 24)
|
||||
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE (0x74 << 24)
|
||||
|
||||
#define RP_ECTL_1_R1 0x00000e80
|
||||
#define RP_ECTL_1_R1_TX_DRV_AMP_1C_MASK 0x3f
|
||||
|
||||
@@ -207,6 +258,19 @@
|
||||
#define RP_VEND_XP_OPPORTUNISTIC_UPDATEFC (1 << 28)
|
||||
#define RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK (0xff << 18)
|
||||
|
||||
#define RP_VEND_XP1 0xf04
|
||||
#define RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S (1 << 23)
|
||||
#define RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT (1 << 21)
|
||||
|
||||
|
||||
#define RP_XP_REF 0xf30
|
||||
#define RP_XP_REF_MICROSECOND_LIMIT_MASK 0xff
|
||||
#define RP_XP_REF_MICROSECOND_LIMIT 0x14
|
||||
#define RP_XP_REF_MICROSECOND_ENABLE (1 << 8)
|
||||
#define RP_XP_REF_CPL_TO_OVERRIDE (1 << 13)
|
||||
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK (0x1ffff << 14)
|
||||
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE (0x1770 << 14)
|
||||
|
||||
#define RP_VEND_CTL0 0x00000f44
|
||||
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH_MASK (0xf << 12)
|
||||
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH (0x9 << 12)
|
||||
@@ -230,12 +294,23 @@
|
||||
#define RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD (0xf << 24)
|
||||
#define RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE (1 << 31)
|
||||
|
||||
#define RP_VEND_XP_PAD_PWRDN 0x00000f50
|
||||
#define RP_VEND_XP_PAD_PWRDN_L1_EN (1 << 0)
|
||||
#define RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN (1 << 1)
|
||||
#define RP_VEND_XP_PAD_PWRDN_DISABLED_EN (1 << 2)
|
||||
#define RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN (1 << 15)
|
||||
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP (3 << 5)
|
||||
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP (3 << 3)
|
||||
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP (3 << 16)
|
||||
|
||||
#define RP_LINK_CONTROL_STATUS 0x00000090
|
||||
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
|
||||
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
|
||||
|
||||
#define RP_LINK_CONTROL_STATUS_2 0x000000b0
|
||||
|
||||
#define RP_L1_PM_SUBSTATES_CAP 0x144
|
||||
|
||||
#define PADS_CTL_SEL 0x0000009c
|
||||
|
||||
#define PADS_CTL 0x000000a0
|
||||
@@ -312,6 +387,10 @@ struct tegra_pcie_soc {
|
||||
bool program_deskew_time;
|
||||
bool update_fc_timer;
|
||||
bool has_cache_bars;
|
||||
bool enable_wrap;
|
||||
bool has_aspm_l1;
|
||||
bool has_aspm_l1ss;
|
||||
bool l1ss_rp_wake_fixup;
|
||||
struct {
|
||||
struct {
|
||||
u32 rp_ectl_1_r1;
|
||||
@@ -376,6 +455,8 @@ struct tegra_pcie_port {
|
||||
void __iomem *base;
|
||||
unsigned int index;
|
||||
unsigned int lanes;
|
||||
unsigned int aspm_state;
|
||||
bool supports_clkreq;
|
||||
|
||||
struct phy **phys;
|
||||
|
||||
@@ -404,6 +485,14 @@ static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset)
|
||||
return readl(pcie->pads + offset);
|
||||
}
|
||||
|
||||
static bool tegra_pcie_link_up(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = readl(port->base + RP_LINK_CONTROL_STATUS);
|
||||
return !!(value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The configuration space mapping on Tegra is somewhat similar to the ECAM
|
||||
* defined by PCIe. However it deviates a bit in how the 4 bits for extended
|
||||
@@ -469,20 +558,50 @@ static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus,
|
||||
static int tegra_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 *value)
|
||||
{
|
||||
struct tegra_pcie *pcie = bus->sysdata;
|
||||
struct pci_dev *bridge;
|
||||
struct tegra_pcie_port *port;
|
||||
|
||||
if (bus->number == 0)
|
||||
return pci_generic_config_read32(bus, devfn, where, size,
|
||||
value);
|
||||
|
||||
bridge = pcie_find_root_port(bus->self);
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list)
|
||||
if (port->index + 1 == PCI_SLOT(bridge->devfn))
|
||||
break;
|
||||
|
||||
/* If there is no link, then there is no device */
|
||||
if (!tegra_pcie_link_up(port)) {
|
||||
*value = 0xffffffff;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return pci_generic_config_read(bus, devfn, where, size, value);
|
||||
}
|
||||
|
||||
static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
|
||||
int where, int size, u32 value)
|
||||
{
|
||||
struct tegra_pcie *pcie = bus->sysdata;
|
||||
struct tegra_pcie_port *port;
|
||||
struct pci_dev *bridge;
|
||||
|
||||
if (bus->number == 0)
|
||||
return pci_generic_config_write32(bus, devfn, where, size,
|
||||
value);
|
||||
|
||||
bridge = pcie_find_root_port(bus->self);
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list)
|
||||
if (port->index + 1 == PCI_SLOT(bridge->devfn))
|
||||
break;
|
||||
|
||||
/* If there is no link, then there is no device */
|
||||
if (!tegra_pcie_link_up(port))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
return pci_generic_config_write(bus, devfn, where, size, value);
|
||||
}
|
||||
|
||||
@@ -539,6 +658,44 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
|
||||
}
|
||||
}
|
||||
|
||||
static void disable_aspm_l0s(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_VEND_XP1);
|
||||
val |= RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S;
|
||||
writel(val, port->base + RP_VEND_XP1);
|
||||
}
|
||||
|
||||
static void disable_aspm_l10(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_VEND_XP1);
|
||||
val &= ~RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
|
||||
writel(val, port->base + RP_VEND_XP1);
|
||||
}
|
||||
|
||||
static void disable_aspm_l11(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1;
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1;
|
||||
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
}
|
||||
|
||||
static void disable_aspm_l12(struct tegra_pcie_port *port)
|
||||
{
|
||||
u32 val = 0;
|
||||
|
||||
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2;
|
||||
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2;
|
||||
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
}
|
||||
|
||||
static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
|
||||
{
|
||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||
@@ -575,6 +732,47 @@ static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
|
||||
}
|
||||
|
||||
writel(value, port->base + RP_PRIV_MISC);
|
||||
|
||||
if (soc->has_aspm_l1) {
|
||||
/* Advertise ASPM-L1 state capability*/
|
||||
value = readl(port->base + RP_VEND_XP1);
|
||||
value |= RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
|
||||
writel(value, port->base + RP_VEND_XP1);
|
||||
|
||||
/* Power saving configuration for L1 sleep/idle */
|
||||
value = readl(port->base + RP_VEND_XP_PAD_PWRDN);
|
||||
value |= RP_VEND_XP_PAD_PWRDN_DISABLED_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_L1_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP;
|
||||
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP;
|
||||
writel(value, port->base + RP_VEND_XP_PAD_PWRDN);
|
||||
|
||||
if (port->aspm_state & 0x1)
|
||||
disable_aspm_l0s(port);
|
||||
if (port->aspm_state & 0x2)
|
||||
disable_aspm_l10(port);
|
||||
}
|
||||
|
||||
if (soc->has_aspm_l1ss) {
|
||||
if (port->aspm_state & 0x2) {
|
||||
disable_aspm_l11(port);
|
||||
disable_aspm_l12(port);
|
||||
}
|
||||
if (port->aspm_state & 0x4)
|
||||
disable_aspm_l11(port);
|
||||
if (port->aspm_state & 0x8)
|
||||
disable_aspm_l12(port);
|
||||
|
||||
/* Disable L1SS capability if CLKREQ# is not present */
|
||||
if (!port->supports_clkreq) {
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
value |= RP_L1_PM_SUBSTATES_CTL_HIDE_CAP;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
||||
@@ -635,6 +833,26 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
|
||||
writel(value, port->base + RP_ECTL_6_R2);
|
||||
}
|
||||
|
||||
static void tegra_pcie_enable_wrap(void)
|
||||
{
|
||||
u32 val;
|
||||
void __iomem *msel_base;
|
||||
|
||||
#define MSELECT_CONFIG_BASE 0x50060000
|
||||
#define MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1 BIT(28)
|
||||
#define MSELECT_CONFIG_ERR_RESP_EN_SLAVE1 BIT(24)
|
||||
|
||||
/* Config MSELECT to support wrap trans for normal NC & GRE mapping */
|
||||
msel_base = ioremap(MSELECT_CONFIG_BASE, 4);
|
||||
val = readl(msel_base);
|
||||
/* Enable WRAP_TO_INCR_SLAVE1 */
|
||||
val |= MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1;
|
||||
/* Disable ERR_RESP_EN_SLAVE1 */
|
||||
val &= ~MSELECT_CONFIG_ERR_RESP_EN_SLAVE1;
|
||||
writel(val, msel_base);
|
||||
iounmap(msel_base);
|
||||
}
|
||||
|
||||
static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
|
||||
{
|
||||
const struct tegra_pcie_soc *soc = port->pcie->soc;
|
||||
@@ -669,6 +887,76 @@ static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
|
||||
value &= ~PCI_EXP_LNKSTA_CLS;
|
||||
value |= PCI_EXP_LNKSTA_CLS_2_5GB;
|
||||
writel(value, port->base + RP_LINK_CONTROL_STATUS_2);
|
||||
|
||||
if (soc->enable_wrap)
|
||||
tegra_pcie_enable_wrap();
|
||||
|
||||
if (soc->has_aspm_l1ss) {
|
||||
/* Set port Common_Mode_Restore_Time to 30us */
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
value &= ~RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK;
|
||||
value |= (0x1E << RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT);
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
|
||||
/* set port T_POWER_ON to 70us */
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
value &= ~(RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK |
|
||||
RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK);
|
||||
value |= (1 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT) |
|
||||
(7 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT);
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
|
||||
|
||||
/* Following is based on clk_m being 19.2 MHz */
|
||||
value = readl(port->base + RP_TIMEOUT0);
|
||||
value &= ~RP_TIMEOUT0_PAD_PWRUP_MASK;
|
||||
value |= RP_TIMEOUT0_PAD_PWRUP;
|
||||
value &= ~RP_TIMEOUT0_PAD_PWRUP_CM_MASK;
|
||||
value |= RP_TIMEOUT0_PAD_PWRUP_CM;
|
||||
value &= ~RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK;
|
||||
value |= RP_TIMEOUT0_PAD_SPDCHNG_GEN2;
|
||||
writel(value, port->base + RP_TIMEOUT0);
|
||||
|
||||
value = readl(port->base + RP_TIMEOUT1);
|
||||
value &= ~RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK;
|
||||
value |= RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE;
|
||||
value &= ~RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK;
|
||||
value |= RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE;
|
||||
writel(value, port->base + RP_TIMEOUT1);
|
||||
|
||||
value = readl(port->base + RP_XP_REF);
|
||||
value &= ~RP_XP_REF_MICROSECOND_LIMIT_MASK;
|
||||
value |= RP_XP_REF_MICROSECOND_LIMIT;
|
||||
value |= RP_XP_REF_MICROSECOND_ENABLE;
|
||||
value |= RP_XP_REF_CPL_TO_OVERRIDE;
|
||||
value &= ~RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK;
|
||||
value |= RP_XP_REF_CPL_TO_CUSTOM_VALUE;
|
||||
writel(value, port->base + RP_XP_REF);
|
||||
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
value &= ~RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_2_CTL);
|
||||
value &= ~RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY;
|
||||
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND;
|
||||
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK;
|
||||
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_2_CTL);
|
||||
}
|
||||
|
||||
if (soc->l1ss_rp_wake_fixup) {
|
||||
/*
|
||||
* Set CLKREQ asserted delay greater than Power_Off
|
||||
* time (2us) to avoid RP wakeup in L1.2.ENTRY
|
||||
*/
|
||||
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
value &= ~RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK;
|
||||
value |= RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY;
|
||||
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
|
||||
@@ -681,8 +969,12 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
|
||||
value = afi_readl(port->pcie, ctrl);
|
||||
value |= AFI_PEX_CTRL_REFCLK_EN;
|
||||
|
||||
if (soc->has_pex_clkreq_en)
|
||||
value |= AFI_PEX_CTRL_CLKREQ_EN;
|
||||
if (soc->has_pex_clkreq_en) {
|
||||
if (port->supports_clkreq)
|
||||
value &= ~AFI_PEX_CTRL_CLKREQ_EN;
|
||||
else
|
||||
value |= AFI_PEX_CTRL_CLKREQ_EN;
|
||||
}
|
||||
|
||||
value |= AFI_PEX_CTRL_OVERRIDE_EN;
|
||||
|
||||
@@ -1112,10 +1404,20 @@ static void tegra_pcie_enable_controller(struct tegra_pcie *pcie)
|
||||
unsigned long value;
|
||||
|
||||
/* enable PLL power down */
|
||||
if (pcie->phy) {
|
||||
if (soc->has_aspm_l1ss) {
|
||||
value = afi_readl(pcie, AFI_PLLE_CONTROL);
|
||||
value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
||||
value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
|
||||
|
||||
list_for_each_entry(port, &pcie->ports, list) {
|
||||
if (!port->supports_clkreq) {
|
||||
value &= ~AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
value &= ~AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL;
|
||||
value |= AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN;
|
||||
afi_writel(pcie, value, AFI_PLLE_CONTROL);
|
||||
}
|
||||
|
||||
@@ -1547,6 +1849,11 @@ static void tegra_pcie_pme_turnoff(struct tegra_pcie_port *port)
|
||||
val = afi_readl(pcie, AFI_PCIE_PME);
|
||||
val &= ~(0x1 << soc->ports[port->index].pme.turnoff_bit);
|
||||
afi_writel(pcie, val, AFI_PCIE_PME);
|
||||
|
||||
/* PCIe link is in L2, bypass CLKREQ# control over PLLE power down */
|
||||
val = afi_readl(pcie, AFI_PLLE_CONTROL);
|
||||
val |= AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
|
||||
afi_writel(pcie, val, AFI_PLLE_CONTROL);
|
||||
}
|
||||
|
||||
static void tegra_pcie_msi_irq(struct irq_desc *desc)
|
||||
@@ -1838,6 +2145,13 @@ static void tegra_pcie_disable_interrupts(struct tegra_pcie *pcie)
|
||||
afi_writel(pcie, value, AFI_INTR_MASK);
|
||||
}
|
||||
|
||||
static void update_rp_lanes(struct tegra_pcie *pcie, u32 lanes)
|
||||
{
|
||||
struct tegra_pcie_port *port = NULL;
|
||||
list_for_each_entry(port, &pcie->ports, list)
|
||||
port->lanes = (lanes >> (port->index << 3)) & 0xFF;
|
||||
}
|
||||
|
||||
static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
|
||||
u32 *xbar)
|
||||
{
|
||||
@@ -1866,14 +2180,21 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
|
||||
"switching to default 2x1, 1x1, 1x1 "
|
||||
"configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211;
|
||||
update_rp_lanes(pcie, 0x010102);
|
||||
return 0;
|
||||
}
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra210b01-pcie")) {
|
||||
switch (lanes) {
|
||||
case 0x0104:
|
||||
dev_info(pcie->dev, "4x1, 1x1 configuration\n");
|
||||
dev_info(dev, "4x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
|
||||
return 0;
|
||||
default:
|
||||
dev_info(dev, "wrong configuration updated in DT, "
|
||||
"switching to default 4x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
|
||||
update_rp_lanes(pcie, 0x0104);
|
||||
return 0;
|
||||
}
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") ||
|
||||
of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
|
||||
@@ -1887,6 +2208,13 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
|
||||
dev_info(dev, "2x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
dev_info(dev, "wrong configuration updated in DT, "
|
||||
"switching to default 4x1, 1x1 configuration\n");
|
||||
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
|
||||
update_rp_lanes(pcie, 0x0104);
|
||||
return 0;
|
||||
}
|
||||
} else if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
|
||||
switch (lanes) {
|
||||
@@ -2190,6 +2518,14 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
|
||||
"failed to get reset GPIO\n");
|
||||
}
|
||||
|
||||
err = of_property_read_u32(port, "nvidia,disable-aspm-states",
|
||||
&rp->aspm_state);
|
||||
if (err < 0)
|
||||
rp->aspm_state = 0;
|
||||
|
||||
rp->supports_clkreq = of_property_read_bool(port,
|
||||
"supports-clkreq");
|
||||
|
||||
list_add_tail(&rp->list, &pcie->ports);
|
||||
}
|
||||
|
||||
@@ -2378,6 +2714,10 @@ static const struct tegra_pcie_soc tegra20_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = true,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = false,
|
||||
.has_aspm_l1ss = false,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
@@ -2407,6 +2747,10 @@ static const struct tegra_pcie_soc tegra30_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = false,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
@@ -2428,6 +2772,10 @@ static const struct tegra_pcie_soc tegra124_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = false,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
@@ -2451,6 +2799,10 @@ static const struct tegra_pcie_soc tegra210_pcie = {
|
||||
.program_deskew_time = true,
|
||||
.update_fc_timer = true,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = true,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = true,
|
||||
.l1ss_rp_wake_fixup = true,
|
||||
.ectl = {
|
||||
.regs = {
|
||||
.rp_ectl_1_r1 = 0x0000001f,
|
||||
@@ -2530,6 +2882,10 @@ static const struct tegra_pcie_soc tegra186_pcie = {
|
||||
.program_deskew_time = false,
|
||||
.update_fc_timer = false,
|
||||
.has_cache_bars = false,
|
||||
.enable_wrap = false,
|
||||
.has_aspm_l1 = true,
|
||||
.has_aspm_l1ss = true,
|
||||
.l1ss_rp_wake_fixup = false,
|
||||
.ectl.enable = false,
|
||||
};
|
||||
|
||||
@@ -2660,6 +3016,8 @@ static int tegra_pcie_probe(struct platform_device *pdev)
|
||||
goto pm_runtime_put;
|
||||
}
|
||||
|
||||
pci_add_flags(PCI_REASSIGN_ALL_BUS);
|
||||
|
||||
host->ops = &tegra_pcie_ops;
|
||||
host->map_irq = tegra_pcie_map_irq;
|
||||
|
||||
|
||||
@@ -7,12 +7,17 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
||||
#include "pinctrl-tegra.h"
|
||||
|
||||
struct tegra210_pinctrl_soc {
|
||||
bool lpdr_support;
|
||||
};
|
||||
|
||||
/*
|
||||
* Most pins affected by the pinmux can also be GPIOs. Define these first.
|
||||
* These must match how the GPIO driver names/numbers its pins.
|
||||
@@ -1349,7 +1354,7 @@ static const char * const tegra210_functions[] = {
|
||||
.parked_bitmask = prk_mask, \
|
||||
}
|
||||
|
||||
static const struct tegra_pingroup tegra210_groups[] = {
|
||||
static struct tegra_pingroup tegra210_groups[] = {
|
||||
/* pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, lpdr, rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
|
||||
PINGROUP(sdmmc1_clk_pm0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3000, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
|
||||
PINGROUP(sdmmc1_cmd_pm1, SDMMC1, SPI3, RSVD2, RSVD3, 0x3004, Y, Y, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1),
|
||||
@@ -1558,12 +1563,39 @@ static const struct tegra_pinctrl_soc_data tegra210_pinctrl = {
|
||||
|
||||
static int tegra210_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct tegra210_pinctrl_soc *soc;
|
||||
struct tegra_pingroup *g;
|
||||
int i;
|
||||
|
||||
soc = of_device_get_match_data(&pdev->dev);
|
||||
if (soc->lpdr_support) {
|
||||
for (i = 0; i < tegra210_pinctrl.ngroups; ++i) {
|
||||
g = &tegra210_groups[i];
|
||||
if (g->mux_reg >= 0)
|
||||
g->lpdr_bit = 8;
|
||||
}
|
||||
}
|
||||
|
||||
return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
|
||||
}
|
||||
|
||||
static const struct tegra210_pinctrl_soc tegra210_pinctrl_soc_data = {
|
||||
.lpdr_support = false,
|
||||
};
|
||||
|
||||
static const struct tegra210_pinctrl_soc tegra210b01_pinctrl_soc_data = {
|
||||
.lpdr_support = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra210_pinctrl_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra210-pinmux", },
|
||||
{ },
|
||||
{
|
||||
.compatible = "nvidia,tegra210-pinmux",
|
||||
.data = &tegra210_pinctrl_soc_data,
|
||||
}, {
|
||||
.compatible = "nvidia,tegra210b01-pinmux",
|
||||
.data = &tegra210b01_pinctrl_soc_data,
|
||||
}, {
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_driver tegra210_pinctrl_driver = {
|
||||
|
||||
@@ -12,6 +12,7 @@ obj-$(CONFIG_GOLDFISH) += goldfish/
|
||||
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
|
||||
obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
|
||||
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += arm64/
|
||||
obj-$(CONFIG_BCM2835_VCHIQ) += raspberrypi/
|
||||
obj-$(CONFIG_ACPI_WMI) += wmi/
|
||||
@@ -0,0 +1,24 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Tegra Platform Specific Drivers
|
||||
#
|
||||
|
||||
menuconfig TEGRA_PLATFORM_DEVICES
|
||||
bool "Tegra Platform Specific Device Drivers"
|
||||
default y
|
||||
help
|
||||
Say Y here to get to see options for device drivers of various
|
||||
Tegra platforms. This option itself does not add any kernel code.
|
||||
|
||||
If you say N, all options in this submenu will be skipped and
|
||||
disabled.
|
||||
|
||||
if TEGRA_PLATFORM_DEVICES
|
||||
|
||||
config TEGRA_PROD_LEGACY
|
||||
def_bool y
|
||||
help
|
||||
This config helps client driver to identify whether prod
|
||||
framework is implemented as legacy method or not.
|
||||
|
||||
endif # TEGRA_PLATFORM_DEVICES
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_TEGRA_PROD_LEGACY) += tegra_prod.o
|
||||
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/tegra_prod.h>
|
||||
|
||||
#define PROD_TUPLE_NUM (sizeof(struct prod_tuple)/sizeof(u32))
|
||||
|
||||
/* tegra_prod: Tegra Prod list for the given submodule
|
||||
* @n_prod_cells: Number of prod setting cells.
|
||||
*/
|
||||
struct tegra_prod {
|
||||
struct tegra_prod_config *prod_config;
|
||||
int num; /* number of tegra_prod*/
|
||||
int n_prod_cells;
|
||||
};
|
||||
|
||||
struct prod_tuple {
|
||||
u32 index; /* Address base index */
|
||||
u32 addr; /* offset address*/
|
||||
u32 mask; /* mask */
|
||||
u32 val; /* value */
|
||||
};
|
||||
|
||||
struct tegra_prod_config {
|
||||
const char *name;
|
||||
struct prod_tuple *prod_tuple;
|
||||
int count; /* number of prod_tuple*/
|
||||
bool boot_init;
|
||||
};
|
||||
|
||||
static int tegra_prod_get_child_tupple_count(struct device *dev,
|
||||
struct device_node *np,
|
||||
int n_tupple)
|
||||
{
|
||||
struct device_node *child;
|
||||
int count;
|
||||
int total_tupple = 0;
|
||||
|
||||
count = of_property_count_u32_elems(np, "prod");
|
||||
if (count > 0) {
|
||||
if ((count < n_tupple) || (count % n_tupple != 0)) {
|
||||
dev_err(dev, "Node %s has invalid entries\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
total_tupple = count / n_tupple;
|
||||
}
|
||||
|
||||
for_each_available_child_of_node(np, child) {
|
||||
count = tegra_prod_get_child_tupple_count(dev, child, n_tupple);
|
||||
if (count < 0)
|
||||
return count;
|
||||
|
||||
total_tupple += count;
|
||||
}
|
||||
|
||||
return total_tupple;
|
||||
}
|
||||
|
||||
static int tegra_prod_read_prod_data(struct device *dev,
|
||||
struct device_node *np,
|
||||
struct prod_tuple *p_tuple,
|
||||
int n_tupple)
|
||||
{
|
||||
u32 pval;
|
||||
int count;
|
||||
int t_count;
|
||||
int cnt;
|
||||
int index;
|
||||
int ret;
|
||||
|
||||
count = of_property_count_u32_elems(np, "prod");
|
||||
if (count <= 0) {
|
||||
dev_dbg(dev, "Node %s: prod prop not found\n", np->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
t_count = count / n_tupple;
|
||||
for (cnt = 0; cnt < t_count; cnt++, p_tuple++) {
|
||||
index = cnt * n_tupple;
|
||||
|
||||
if (n_tupple == 4) {
|
||||
ret = of_property_read_u32_index(np, "prod", index,
|
||||
&pval);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to parse prod of node %s\n",
|
||||
np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p_tuple->index = pval;
|
||||
index++;
|
||||
} else {
|
||||
p_tuple->index = 0;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32_index(np, "prod", index, &pval);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to parse address of node %s\n",
|
||||
np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
p_tuple->addr = pval;
|
||||
index++;
|
||||
|
||||
ret = of_property_read_u32_index(np, "prod", index, &pval);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to parse mask of node %s\n",
|
||||
np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
p_tuple->mask = pval;
|
||||
index++;
|
||||
|
||||
ret = of_property_read_u32_index(np, "prod", index, &pval);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to parse value of node %s\n",
|
||||
np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
p_tuple->val = pval;
|
||||
}
|
||||
|
||||
return t_count;
|
||||
}
|
||||
|
||||
static int tegra_prod_read_node_tupple(struct device *dev,
|
||||
struct device_node *np,
|
||||
struct prod_tuple *p_tuple,
|
||||
int n_tupple)
|
||||
{
|
||||
int ret = 0;
|
||||
int sindex;
|
||||
struct device_node *child;
|
||||
|
||||
ret = tegra_prod_read_prod_data(dev, np, p_tuple, n_tupple);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
sindex = ret;
|
||||
p_tuple += ret;
|
||||
|
||||
for_each_available_child_of_node(np, child) {
|
||||
ret = tegra_prod_read_node_tupple(dev, child,
|
||||
p_tuple, n_tupple);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
sindex += ret;
|
||||
p_tuple += ret;
|
||||
}
|
||||
|
||||
return sindex;
|
||||
}
|
||||
|
||||
/* Process the tupples and optimise for the register configuration for
|
||||
* Same location.
|
||||
*/
|
||||
static void tegra_prod_optimise_tupple(struct prod_tuple *p_tuple,
|
||||
int n_tupple)
|
||||
{
|
||||
struct prod_tuple *ti, *tj;
|
||||
u32 mask;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < n_tupple; ++i) {
|
||||
ti = p_tuple + i;
|
||||
for (j = i + 1; j < n_tupple; ++j) {
|
||||
tj = p_tuple + j;
|
||||
if (ti->index != tj->index)
|
||||
continue;
|
||||
|
||||
if (ti->addr != tj->addr)
|
||||
continue;
|
||||
|
||||
mask = ti->mask & tj->mask;
|
||||
if (!mask)
|
||||
continue;
|
||||
|
||||
ti->val &= ~mask;
|
||||
ti->mask &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_prod_parse_dt - Read the prod setting form Device tree.
|
||||
* @np: device node from which the property value is to be read.
|
||||
* @np_prod: Prod setting node.
|
||||
* @tegra_prod: The list of tegra prods.
|
||||
*
|
||||
* Read the prod setting form DT according the prod name in tegra prod list.
|
||||
* prod tuple will be allocated dynamically according to the tuple number of
|
||||
* each prod in DT.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
|
||||
static int tegra_prod_parse_dt(struct device *dev,
|
||||
const struct device_node *np,
|
||||
const struct device_node *np_prod,
|
||||
struct tegra_prod *tegra_prod)
|
||||
{
|
||||
struct device_node *child;
|
||||
struct tegra_prod_config *t_prod;
|
||||
struct prod_tuple *p_tuple;
|
||||
int n_child;
|
||||
int n_tupple = 3;
|
||||
int ret;
|
||||
int count;
|
||||
u32 pval;
|
||||
bool mask_opt;
|
||||
|
||||
if (!tegra_prod || !tegra_prod->prod_config) {
|
||||
dev_err(dev, "Node %s: Invalid tegra prods list.\n", np->name);
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
mask_opt = of_property_read_bool(np_prod, "enable-mask-optimisation");
|
||||
|
||||
ret = of_property_read_u32(np_prod, "#prod-cells", &pval);
|
||||
if (!ret)
|
||||
n_tupple = pval;
|
||||
if ((n_tupple != 3) && (n_tupple != 4)) {
|
||||
dev_err(dev, "Node %s: Prod cells not supported\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
tegra_prod->n_prod_cells = n_tupple;
|
||||
|
||||
n_child = 0;
|
||||
for_each_available_child_of_node(np_prod, child) {
|
||||
t_prod = &tegra_prod->prod_config[n_child];
|
||||
t_prod->name = child->name;
|
||||
|
||||
count = tegra_prod_get_child_tupple_count(dev, child, n_tupple);
|
||||
if (count < 0) {
|
||||
dev_err(dev, "Node %s: Child has not proper setting\n",
|
||||
child->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
dev_err(dev, "Node %s: prod prop not found\n",
|
||||
child->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t_prod->count = count;
|
||||
|
||||
t_prod->prod_tuple = devm_kcalloc(dev, t_prod->count,
|
||||
sizeof(*p_tuple), GFP_KERNEL);
|
||||
if (!t_prod->prod_tuple)
|
||||
return -ENOMEM;
|
||||
|
||||
t_prod->boot_init = of_property_read_bool(child,
|
||||
"nvidia,prod-boot-init");
|
||||
|
||||
ret = tegra_prod_read_node_tupple(dev, child,
|
||||
t_prod->prod_tuple, n_tupple);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Node %s: Reading prod setting failed: %d\n",
|
||||
child->name, ret);
|
||||
return ret;
|
||||
}
|
||||
if (t_prod->count != ret) {
|
||||
dev_err(dev, "Node %s: prod read failed: exp %d read %d\n",
|
||||
child->name, t_prod->count, ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Optimise the prod configuration */
|
||||
if (mask_opt)
|
||||
tegra_prod_optimise_tupple(t_prod->prod_tuple,
|
||||
t_prod->count);
|
||||
|
||||
|
||||
n_child++;
|
||||
}
|
||||
|
||||
tegra_prod->num = n_child;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_prod_set_tuple - Only set a tuple.
|
||||
* @base: base address of the register.
|
||||
* @prod_tuple: the tuple to set.
|
||||
* @new_mask: Mask override value, 0 means use from tupple.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static int tegra_prod_set_tuple(void __iomem **base,
|
||||
struct prod_tuple *prod_tuple,
|
||||
u32 new_mask)
|
||||
{
|
||||
u32 reg;
|
||||
u32 mask = (new_mask) ? new_mask : prod_tuple->mask;
|
||||
|
||||
if (!prod_tuple)
|
||||
return -EINVAL;
|
||||
|
||||
reg = readl(base[prod_tuple->index] + prod_tuple->addr);
|
||||
reg = ((reg & ~mask) | (prod_tuple->val & mask));
|
||||
|
||||
writel(reg, base[prod_tuple->index] + prod_tuple->addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_prod_set - Set one prod setting.
|
||||
* @base: base address of the register.
|
||||
* @tegra_prod: the prod setting to set.
|
||||
*
|
||||
* Set all the tuples in one tegra_prod.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static int tegra_prod_set(void __iomem **base,
|
||||
struct tegra_prod_config *tegra_prod)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (!tegra_prod)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < tegra_prod->count; i++) {
|
||||
ret = tegra_prod_set_tuple(base, &tegra_prod->prod_tuple[i], 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra_prod_set_list - Set all the prod settings of the list in sequence.
|
||||
* @base: base address of the register.
|
||||
* @tegra_prod: the list of tegra prods.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int tegra_prod_set_list(void __iomem **base,
|
||||
struct tegra_prod *tegra_prod)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (!tegra_prod)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < tegra_prod->num; i++) {
|
||||
ret = tegra_prod_set(base, &tegra_prod->prod_config[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_prod_set_list);
|
||||
|
||||
/**
|
||||
* tegra_prod_set_boot_init - Set all the prod settings of the list in sequence
|
||||
* Which are needed for boot initialisation.
|
||||
* @base: base address of the register.
|
||||
* @tegra_prod: the list of tegra prods.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int tegra_prod_set_boot_init(void __iomem **base,
|
||||
struct tegra_prod *tegra_prod)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (!tegra_prod)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < tegra_prod->num; i++) {
|
||||
if (!tegra_prod->prod_config[i].boot_init)
|
||||
continue;
|
||||
ret = tegra_prod_set(base, &tegra_prod->prod_config[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_prod_set_boot_init);
|
||||
|
||||
/**
|
||||
* tegra_prod_set_by_name - Set the prod setting according the name.
|
||||
* @base: base address of the register.
|
||||
* @name: the name of tegra prod need to set.
|
||||
* @tegra_prod: the list of tegra prods.
|
||||
*
|
||||
* Find the tegra prod in the list according to the name. Then set
|
||||
* that tegra prod.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int tegra_prod_set_by_name(void __iomem **base, const char *name,
|
||||
struct tegra_prod *tegra_prod)
|
||||
{
|
||||
int i;
|
||||
struct tegra_prod_config *t_prod;
|
||||
|
||||
if (!tegra_prod)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < tegra_prod->num; i++) {
|
||||
t_prod = &tegra_prod->prod_config[i];
|
||||
if (!strcasecmp(t_prod->name, name))
|
||||
return tegra_prod_set(base, t_prod);
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_prod_set_by_name);
|
||||
|
||||
/**
|
||||
* tegra_prod_set_by_name_partially - Set the prod setting from list partially
|
||||
* under given prod name. The matching is done
|
||||
* qith index, offset and mask.
|
||||
* @base: base address of the register.
|
||||
* @name: the name of tegra prod need to set.
|
||||
* @tegra_prod: the list of tegra prods.
|
||||
* @index: Index of base address.
|
||||
* @offset: Offset of the register.
|
||||
* @mask: Mask field on given register.
|
||||
*
|
||||
* Find the tegra prod in the list according to the name. Then set
|
||||
* that tegra prod which has matching of index, offset and mask.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int tegra_prod_set_by_name_partially(void __iomem **base, const char *name,
|
||||
struct tegra_prod *tegra_prod, u32 index,
|
||||
u32 offset, u32 mask)
|
||||
{
|
||||
struct tegra_prod_config *t_prod;
|
||||
int ret;
|
||||
int i;
|
||||
bool found = false;
|
||||
|
||||
if (!tegra_prod)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < tegra_prod->num; i++) {
|
||||
t_prod = &tegra_prod->prod_config[i];
|
||||
if (!strcasecmp(t_prod->name, name)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < t_prod->count; i++) {
|
||||
struct prod_tuple *ptuple = &t_prod->prod_tuple[i];;
|
||||
|
||||
if ((ptuple->index != index) || (ptuple->addr != offset) ||
|
||||
((ptuple->mask & mask) != mask))
|
||||
continue;
|
||||
|
||||
ret = tegra_prod_set_tuple(base, ptuple, mask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_prod_set_by_name_partially);
|
||||
|
||||
bool tegra_prod_by_name_supported(struct tegra_prod *tegra_prod,
|
||||
const char *name)
|
||||
{
|
||||
int i;
|
||||
struct tegra_prod_config *t_prod;
|
||||
|
||||
if (!tegra_prod)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < tegra_prod->num; i++) {
|
||||
t_prod = &tegra_prod->prod_config[i];
|
||||
if (!t_prod)
|
||||
break;
|
||||
|
||||
if (!strcasecmp(t_prod->name, name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(tegra_prod_by_name_supported);
|
||||
|
||||
/**
|
||||
* tegra_prod_init - Init tegra prod list.
|
||||
# @dev: Device handle.
|
||||
* @np: device node from which the property value is to be read.
|
||||
*
|
||||
* Query all the prod settings under DT node & Init the tegra prod list
|
||||
* automatically.
|
||||
*
|
||||
* Returns 0 on success, -EINVAL for wrong prod number, -ENOMEM if failed
|
||||
* to allocate memory for tegra prod list.
|
||||
*/
|
||||
static struct tegra_prod *tegra_prod_init(struct device *dev,
|
||||
const struct device_node *np)
|
||||
{
|
||||
struct tegra_prod *tegra_prod;
|
||||
struct device_node *np_prod;
|
||||
int prod_num = 0;
|
||||
int ret;
|
||||
|
||||
np_prod = of_get_child_by_name(np, "prod-settings");
|
||||
if (!np_prod)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
/* Check whether child is enabled or not */
|
||||
if (!of_device_is_available(np_prod)) {
|
||||
dev_err(dev, "Node %s: Node is not enabled\n", np_prod->name);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
prod_num = of_get_child_count(np_prod);
|
||||
if (prod_num <= 0) {
|
||||
dev_err(dev, "Node %s: No child node for prod settings\n",
|
||||
np_prod->name);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
tegra_prod = devm_kzalloc(dev, sizeof(*tegra_prod), GFP_KERNEL);
|
||||
if (!tegra_prod)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
tegra_prod->prod_config = devm_kcalloc(dev, prod_num,
|
||||
sizeof(*tegra_prod->prod_config),
|
||||
GFP_KERNEL);
|
||||
if (!tegra_prod->prod_config)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
tegra_prod->num = prod_num;
|
||||
|
||||
ret = tegra_prod_parse_dt(dev, np, np_prod, tegra_prod);
|
||||
if (ret) {
|
||||
dev_err(dev, "Node %s: Failed to read the Prod Setting.\n",
|
||||
np->name);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return tegra_prod;
|
||||
}
|
||||
|
||||
static void devm_tegra_prod_release(struct device *dev, void *res)
|
||||
{
|
||||
}
|
||||
|
||||
struct tegra_prod *devm_tegra_prod_get(struct device *dev)
|
||||
{
|
||||
struct tegra_prod **ptr, *prod_list;
|
||||
|
||||
ptr = devres_alloc(devm_tegra_prod_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
prod_list = tegra_prod_init(dev, dev->of_node);
|
||||
if (IS_ERR(prod_list)) {
|
||||
devres_free(ptr);
|
||||
return prod_list;
|
||||
}
|
||||
|
||||
*ptr = prod_list;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
return prod_list;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_tegra_prod_get);
|
||||
|
||||
struct tegra_prod *devm_tegra_prod_get_from_node(struct device *dev,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct tegra_prod **ptr, *prod_list;
|
||||
|
||||
ptr = devres_alloc(devm_tegra_prod_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
prod_list = tegra_prod_init(dev, np);
|
||||
if (IS_ERR(prod_list)) {
|
||||
devres_free(ptr);
|
||||
return prod_list;
|
||||
}
|
||||
|
||||
*ptr = prod_list;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
return prod_list;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_tegra_prod_get_from_node);
|
||||
@@ -611,6 +611,29 @@ out:
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REGULATOR
|
||||
static int bq24190_get_charging_current(struct regulator_dev *dev)
|
||||
{
|
||||
struct bq24190_dev_info *bdi = rdev_get_drvdata(dev);
|
||||
int in_current_limit;
|
||||
int ret;
|
||||
|
||||
dev_info(bdi->dev, "Getting charging current\n");
|
||||
|
||||
ret = bq24190_get_field_val(bdi, BQ24190_REG_ISC,
|
||||
BQ24190_REG_ISC_IINLIM_MASK,
|
||||
BQ24190_REG_ISC_IINLIM_SHIFT,
|
||||
bq24190_isc_iinlim_values,
|
||||
ARRAY_SIZE(bq24190_isc_iinlim_values),
|
||||
&in_current_limit);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
return in_current_limit;
|
||||
error:
|
||||
dev_err(bdi->dev, "Charger enable failed, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bq24190_set_charging_current(struct regulator_dev *dev,
|
||||
int min_uA, int max_uA)
|
||||
{
|
||||
@@ -645,6 +668,7 @@ error:
|
||||
}
|
||||
|
||||
static const struct regulator_ops bq24190_chrg_ops = {
|
||||
.get_current_limit = bq24190_get_charging_current,
|
||||
.set_current_limit = bq24190_set_charging_current,
|
||||
};
|
||||
|
||||
|
||||
@@ -56,6 +56,11 @@
|
||||
#define CTL_MODE_VSEL0_MODE BIT(0)
|
||||
#define CTL_MODE_VSEL1_MODE BIT(1)
|
||||
|
||||
#define FAN53528_CTL_MODE_MASK 0x3
|
||||
#define FAN53528_CTL_MODE_FPWM (BIT(1) | BIT(0))
|
||||
#define FAN53528_CTL_MODE_AUTFPWM 0x0
|
||||
#define FAN53528_VOLTAGE_MASK 0x7F
|
||||
|
||||
#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */
|
||||
#define FAN53526_NVOLTAGES 128
|
||||
#define RK8602_NVOLTAGES 160
|
||||
@@ -67,6 +72,7 @@
|
||||
|
||||
enum fan53555_vendor {
|
||||
FAN53526_VENDOR_FAIRCHILD = 0,
|
||||
FAN53528_VENDOR_FAIRCHILD,
|
||||
FAN53555_VENDOR_FAIRCHILD,
|
||||
FAN53555_VENDOR_ROCKCHIP, /* RK8600, RK8601 */
|
||||
RK8602_VENDOR_ROCKCHIP, /* RK8602, RK8603 */
|
||||
@@ -161,8 +167,12 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
ret = regulator_map_voltage_linear(rdev, uV, uV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = regmap_update_bits(rdev->regmap, di->sleep_reg,
|
||||
di->desc.vsel_mask, ret);
|
||||
if (di->vendor == FAN53528_VENDOR_FAIRCHILD)
|
||||
ret = regmap_update_bits(rdev->regmap, di->sleep_reg,
|
||||
FAN53528_VOLTAGE_MASK, ret);
|
||||
else
|
||||
ret = regmap_update_bits(rdev->regmap, di->sleep_reg,
|
||||
di->desc.vsel_mask, ret);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Cache the sleep voltage setting.
|
||||
@@ -194,11 +204,21 @@ static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
regmap_update_bits(rdev->regmap, di->mode_reg,
|
||||
di->mode_mask, di->mode_mask);
|
||||
if (di->vendor == FAN53528_VENDOR_FAIRCHILD)
|
||||
regmap_update_bits(rdev->regmap, FAN53555_CONTROL,
|
||||
FAN53528_CTL_MODE_MASK,
|
||||
FAN53528_CTL_MODE_FPWM);
|
||||
else
|
||||
regmap_update_bits(rdev->regmap, di->mode_reg,
|
||||
di->mode_mask, di->mode_mask);
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
regmap_update_bits(rdev->regmap, di->vol_reg, di->mode_mask, 0);
|
||||
if (di->vendor == FAN53528_VENDOR_FAIRCHILD)
|
||||
regmap_update_bits(di->regmap, FAN53555_CONTROL,
|
||||
FAN53528_CTL_MODE_MASK,
|
||||
FAN53528_CTL_MODE_AUTFPWM);
|
||||
else
|
||||
regmap_update_bits(rdev->regmap, di->vol_reg, di->mode_mask, 0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -212,6 +232,17 @@ static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
|
||||
unsigned int val;
|
||||
int ret = 0;
|
||||
|
||||
if (di->vendor == FAN53528_VENDOR_FAIRCHILD) {
|
||||
ret = regmap_read(di->regmap, FAN53555_CONTROL, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if ((val & FAN53528_CTL_MODE_MASK) == FAN53528_CTL_MODE_FPWM)
|
||||
return REGULATOR_MODE_FAST;
|
||||
else
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = regmap_read(rdev->regmap, di->mode_reg, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -610,6 +641,13 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
|
||||
rdesc->enable_time = di->enable_time;
|
||||
rdesc->owner = THIS_MODULE;
|
||||
|
||||
if (di->vendor == FAN53528_VENDOR_FAIRCHILD) {
|
||||
rdesc->name = "fan53528-reg";
|
||||
rdesc->n_voltages = FAN53526_NVOLTAGES;
|
||||
rdesc->vsel_mask = FAN53528_VOLTAGE_MASK;
|
||||
};
|
||||
|
||||
|
||||
rdev = devm_regulator_register(di->dev, &di->desc, config);
|
||||
return PTR_ERR_OR_ZERO(rdev);
|
||||
}
|
||||
@@ -645,6 +683,9 @@ static const struct of_device_id __maybe_unused fan53555_dt_ids[] = {
|
||||
{
|
||||
.compatible = "fcs,fan53526",
|
||||
.data = (void *)FAN53526_VENDOR_FAIRCHILD,
|
||||
}, {
|
||||
.compatible = "fcs,fan53528",
|
||||
.data = (void *)FAN53528_VENDOR_FAIRCHILD,
|
||||
}, {
|
||||
.compatible = "fcs,fan53555",
|
||||
.data = (void *)FAN53555_VENDOR_FAIRCHILD
|
||||
@@ -752,6 +793,9 @@ static const struct i2c_device_id fan53555_id[] = {
|
||||
{
|
||||
.name = "fan53526",
|
||||
.driver_data = FAN53526_VENDOR_FAIRCHILD
|
||||
}, {
|
||||
.name = "fan53528",
|
||||
.driver_data = FAN53528_VENDOR_FAIRCHILD
|
||||
}, {
|
||||
.name = "fan53555",
|
||||
.driver_data = FAN53555_VENDOR_FAIRCHILD
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* High-speed serial driver for NVIDIA Tegra SoCs
|
||||
*
|
||||
* Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2012-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
*/
|
||||
@@ -1260,8 +1260,10 @@ static void tegra_uart_flush_buffer(struct uart_port *u)
|
||||
struct tegra_uart_port *tup = to_tegra_uport(u);
|
||||
|
||||
tup->tx_bytes = 0;
|
||||
if (tup->tx_dma_chan)
|
||||
if (tup->tx_dma_chan) {
|
||||
dmaengine_terminate_all(tup->tx_dma_chan);
|
||||
tup->tx_in_progress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra_uart_shutdown(struct uart_port *u)
|
||||
|
||||
@@ -64,6 +64,18 @@ config TYPEC_ANX7411
|
||||
If you choose to build this driver as a dynamically linked module, the
|
||||
module will be called anx7411.ko.
|
||||
|
||||
config TYPEC_BM92TXX
|
||||
tristate "Rohm Semiconductor BM92TXX USB Type-C Support"
|
||||
depends on I2C
|
||||
depends on USB_ROLE_SWITCH
|
||||
depends on DRM
|
||||
help
|
||||
Say Y or M here if your system has Rohm BM92TXX USB Type-C and
|
||||
Power Delivery controller.
|
||||
|
||||
If you choose to build this driver as a dynamically linked module, the
|
||||
module will be called bm92txx.ko
|
||||
|
||||
config TYPEC_RT1719
|
||||
tristate "Richtek RT1719 Sink Only Type-C controller driver"
|
||||
depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
|
||||
|
||||
@@ -7,6 +7,7 @@ obj-$(CONFIG_TYPEC_TCPM) += tcpm/
|
||||
obj-$(CONFIG_TYPEC_UCSI) += ucsi/
|
||||
obj-$(CONFIG_TYPEC_TPS6598X) += tipd/
|
||||
obj-$(CONFIG_TYPEC_ANX7411) += anx7411.o
|
||||
obj-$(CONFIG_TYPEC_BM92TXX) += bm92txx.o
|
||||
obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o
|
||||
obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
|
||||
obj-$(CONFIG_TYPEC_RT1719) += rt1719.o
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _TEGRA_PRODS_H
|
||||
#define _TEGRA_PRODS_H
|
||||
|
||||
struct tegra_prod;
|
||||
|
||||
/**
|
||||
* tegra_prod_set_list(): Set all prods configurations
|
||||
* @base: List of IO mapped registers.
|
||||
* @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get()
|
||||
* or tegra_prod_get_from_node();
|
||||
*
|
||||
* Configure all the prod configuration listed on prod-setting nodes.
|
||||
*
|
||||
* Returns 0 on success otherwise negive error number for failed case.
|
||||
*/
|
||||
int tegra_prod_set_list(void __iomem **base, struct tegra_prod *tegra_prod);
|
||||
|
||||
/**
|
||||
* tegra_prod_set_boot_init(): Set all prods configurations which has boot init
|
||||
* flag on the prod setting nodes.
|
||||
* @base: List of IO mapped registers.
|
||||
* @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get()
|
||||
* or tegra_prod_get_from_node();
|
||||
*
|
||||
* Configure all the prod configuration listed on prod-setting nodes.
|
||||
*
|
||||
* Returns 0 on success otherwise negive error number for failed case.
|
||||
*/
|
||||
int tegra_prod_set_boot_init(void __iomem **base,
|
||||
struct tegra_prod *tegra_prod);
|
||||
|
||||
/**
|
||||
* tegra_prod_set_by_name(): Set prod configuration with specific prod name.
|
||||
* This is used for conditional prod configurations.
|
||||
* @base: List of IO mapped registers.
|
||||
* @name: Name of conditional prod which need to be configure.
|
||||
* @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get()
|
||||
* or tegra_prod_get_from_node();
|
||||
*
|
||||
* Configure prod configuration with specific prod name for conditional
|
||||
* prod configurations.
|
||||
*
|
||||
* Returns 0 on success otherwise negive error number for failed case.
|
||||
*/
|
||||
int tegra_prod_set_by_name(void __iomem **base, const char *name,
|
||||
struct tegra_prod *tegra_prod);
|
||||
|
||||
/**
|
||||
* tegra_prod_set_by_name_partially - Set the prod setting from list partially
|
||||
* under given prod name. The matching is done
|
||||
* qith index, offset and mask.
|
||||
* @base: base address of the register.
|
||||
* @name: the name of tegra prod need to set.
|
||||
* @tegra_prod: the list of tegra prods.
|
||||
* @index: Index of base address.
|
||||
* @offset: Offset of the register.
|
||||
* @mask: Mask field on given register.
|
||||
*
|
||||
* Find the tegra prod in the list according to the name. Then set
|
||||
* that tegra prod which has matching of index, offset and mask.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int tegra_prod_set_by_name_partially(void __iomem **base, const char *name,
|
||||
struct tegra_prod *tegra_prod, u32 index,
|
||||
u32 offset, u32 mask);
|
||||
|
||||
/**
|
||||
* tegra_prod_by_name_supported - Tell whether tegra prod will be supported by
|
||||
* given name or not.
|
||||
* @tegra_prod: the list of tegra prods.
|
||||
* @name: the name of tegra prod need to set.
|
||||
*
|
||||
* Find the tegra prod in the list according to the name. If it exist then
|
||||
* return true else false.
|
||||
*/
|
||||
bool tegra_prod_by_name_supported(struct tegra_prod *tegra_prod,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* devm_tegra_prod_get(): Get the prod handle from the device.
|
||||
* @dev: Device handle on which prod setting nodes are available.
|
||||
*
|
||||
* Parse the prod-setting node of the dev->of_node and keep all prod
|
||||
* setting data in prod handle.
|
||||
* This handle is used for setting prod configurations.
|
||||
*
|
||||
* Returns valid prod_list handle on success or pointer to the error
|
||||
* when it failed.
|
||||
*/
|
||||
struct tegra_prod *devm_tegra_prod_get(struct device *dev);
|
||||
|
||||
/**
|
||||
* devm_tegra_prod_get_from_node(): Get the prod handle from the node.
|
||||
* @dev: Device handle.
|
||||
* @np: Node pointer on which prod setting nodes are available.
|
||||
*
|
||||
* Parse the prod-setting node of the node pointer "np" and keep all prod
|
||||
* setting data in prod handle.
|
||||
* This handle is used for setting prod configurations.
|
||||
*
|
||||
* Returns valid prod_list handle on success or pointer to the error
|
||||
* when it failed.
|
||||
* The allocated resource is released by driver core framework when device
|
||||
* is unbinded and so no need to call any release APIs for the tegra_prod
|
||||
* handle.
|
||||
*/
|
||||
struct tegra_prod *devm_tegra_prod_get_from_node(struct device *dev,
|
||||
struct device_node *np);
|
||||
#endif
|
||||
Reference in new issue
Block a user