Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
- index dff236f..a4903f7 100644
- --- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
- +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
- @@ -23,7 +23,8 @@ Required properties:
- - clock-names: Must include the following entries:
- - soc: Clock source for the DFLL control logic.
- - ref: The closed loop reference clock
- - - i2c: Clock source for the integrated I2C master.
- + - i2c: Clock source for the integrated I2C master (only required when
- + using I2C mode).
- - resets: Must contain an entry for each entry in reset-names.
- See ../reset/reset.txt for details.
- - reset-names: Must include the following entries:
- @@ -45,10 +46,28 @@ Required properties for the control loop parameters:
- Optional properties for the control loop parameters:
- - nvidia,cg-scale: Boolean value, see the field DFLL_PARAMS_CG_SCALE in the TRM.
- +Optional properties for mode selection:
- +- nvidia,pwm-to-pmic: Use PWM to control regulator rather then I2C.
- +
- Required properties for I2C mode:
- - nvidia,i2c-fs-rate: I2C transfer rate, if using full speed mode.
- -Example:
- +Required properties for PWM mode:
- +- nvidia,pwm-period: period of PWM square wave in us.
- +- nvidia,init-uv: Regulator voltage in uV when PWM control is disabled.
- +- nvidia,align-offset-uv: Regulator voltage in uV when PWM control is enabled
- + and PWM output is low.
- +- nvidia,align-step-uv: Voltage increase in uV corresponding to a 1/33th
- + increase in duty cycle. Eg the voltage for 2/33th duty
- + cycle would be:
- + nvidia,align-offset-uv + nvidia,align-step-uv * 2.
- +- pinctrl-0: I/O pad configuration when PWM control is enabled.
- +- pinctrl-1: I/O pad configuration when PWM control is disabled.
- +- pinctrl-names: must include the following entries:
- + - dvfs_pwm_enable: I/O pad configuration when PWM control is enabled.
- + - dvfs_pwm_disable: I/O pad configuration when PWM control is disabled.
- +
- +Example for I2C:
- clock@70110000 {
- compatible = "nvidia,tegra124-dfll";
- @@ -76,3 +95,56 @@ clock@70110000 {
- nvidia,i2c-fs-rate = <400000>;
- };
- +
- +Example for PWM:
- +
- +clock@70110000 {
- + compatible = "nvidia,tegra124-dfll";
- + reg = <0 0x70110000 0 0x100>, /* DFLL control */
- + <0 0x70110000 0 0x100>, /* I2C output control */
- + <0 0x70110100 0 0x100>, /* Integrated I2C controller */
- + <0 0x70110200 0 0x100>; /* Look-up table RAM */
- + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&tegra_car TEGRA210_CLK_DFLL_SOC>,
- + <&tegra_car TEGRA210_CLK_DFLL_REF>;
- + clock-names = "soc", "ref";
- + resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>;
- + reset-names = "dvco";
- + #clock-cells = <0>;
- + clock-output-names = "dfllCPU_out";
- + nvidia,pwm-to-pmic;
- + nvidia,init-uv = <1000000>;
- + nvidia,align-step-uv = <19200>; /* 19.2mV */
- + nvidia,align-offset-uv = <708000>; /* 708mV */
- + nvidia,sample-rate = <25000>;
- + nvidia,droop-ctrl = <0x00000f00>;
- + nvidia,force-mode = <1>;
- + nvidia,cf = <6>;
- + nvidia,ci = <0>;
- + nvidia,cg = <2>;
- + nvidia,idle-override;
- + nvidia,one-shot-calibrate;
- + nvidia,pwm-period = <2500>; /* 2.5us */
- + pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
- + pinctrl-0 = <&dvfs_pwm_active_state>;
- + pinctrl-1 = <&dvfs_pwm_inactive_state>;
- +};
- +
- +/* pinmux nodes added for completeness. Binding doc can be found in:
- + * Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt
- + */
- +
- +pinmux: pinmux@700008d4 {
- + dvfs_pwm_active_state: dvfs_pwm_active {
- + dvfs_pwm_pbb1 {
- + nvidia,pins = "dvfs_pwm_pbb1";
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + };
- + };
- + dvfs_pwm_inactive_state: dvfs_pwm_inactive {
- + dvfs_pwm_pbb1 {
- + nvidia,pins = "dvfs_pwm_pbb1";
- + nvidia,tristate = <TEGRA_PIN_ENABLE>;
- + };
- + };
- +};
- diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
- index 9bce578..cda29fd 100644
- --- a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
- +++ b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
- @@ -23,6 +23,8 @@ Required properties:
- Optional properties:
- - power-gpios : Specify GPIOs for power control
- +- nvidia,pad : Specify the pad ID for controlling the I/O voltage level.
- + Required for 1.8V mode support on Tegra210.
- Example:
- diff --git a/arch/arm64/boot/dts/nvidia/Makefile b/arch/arm64/boot/dts/nvidia/Makefile
- index 7c13d7d..17ab6c4 100644
- --- a/arch/arm64/boot/dts/nvidia/Makefile
- +++ b/arch/arm64/boot/dts/nvidia/Makefile
- @@ -1,5 +1,6 @@
- # SPDX-License-Identifier: GPL-2.0
- dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb
- +dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-nintendo-switch.dtb
- dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb
- dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
- dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
- diff --git a/arch/arm64/boot/dts/nvidia/tegra210-nintendo-switch.dts b/arch/arm64/boot/dts/nvidia/tegra210-nintendo-switch.dts
- new file mode 100644
- index 0000000..44de6b5
- --- /dev/null
- +++ b/arch/arm64/boot/dts/nvidia/tegra210-nintendo-switch.dts
- @@ -0,0 +1,1325 @@
- +// SPDX-License-Identifier: GPL-2.0
- +/dts-v1/;
- +
- +#include <dt-bindings/input/input.h>
- +#include <dt-bindings/mfd/max77620.h>
- +#include <dt-bindings/pwm/pwm.h>
- +#include <dt-bindings/thermal/thermal.h>
- +
- +#include "tegra210.dtsi"
- +
- +/ {
- + model = "Nintendo Switch";
- + compatible = "nintendo,switch", "nvidia,tegra210";
- +
- + 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 = "earlycon drm.debug=0x3f";
- + stdout-path = "serial1:115200n8";
- + };
- +
- + memory {
- + device_type = "memory";
- + reg = <0x0 0x80000000 0x1 0x0>;
- + };
- +
- + cpus {
- + cpu@0 {
- + vdd-cpu-supply = <&max77621_cpu>;
- + };
- + };
- +
- + clock@70110000 {
- + status = "okay";
- +
- + vdd-cpu-supply = <&max77621_cpu>;
- + nvidia,sample-rate = <12500>;
- + nvidia,droop-ctrl = <0x00000f00>;
- + nvidia,force-mode = <1>;
- + nvidia,cf = <10>;
- + nvidia,ci = <0>;
- + nvidia,cg = <2>;
- + nvidia,i2c-fs-rate = <400000>;
- + };
- +
- + pcie@1003000 {
- + status = "okay";
- +
- + avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
- + hvddio-pex-supply = <&vdd_1v8>;
- + dvddio-pex-supply = <&vdd_pex_1v05>;
- + dvdd-pex-pll-supply = <&vdd_pex_1v05>;
- + hvdd-pex-pll-e-supply = <&vdd_1v8>;
- + vddio-pex-ctl-supply = <&vdd_1v8>;
- +
- + pci@1,0 {
- + phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
- + <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>,
- + <&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>,
- + <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
- + phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3";
- + status = "okay";
- + };
- +
- + pci@2,0 {
- + phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
- + phy-names = "pcie-0";
- + status = "okay";
- + };
- + };
- +
- + host1x@50000000 {
- + dsi@54300000 {
- + status = "okay";
- +
- + avdd-dsi-csi-supply = <&vdd_dsi_csi>;
- +
- + panel@0 {
- + compatible = "jdi,lpm062m326a";
- + reg = <0>;
- +
- + reset-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
- + vdd1-supply = <&vdd_lcd_1>;
- + vdd2-supply = <&vdd_lcd_2>;
- + backlight = <&backlight>;
- + };
- + };
- +
- + dpaux@54040000 {
- + //status = "okay";
- + };
- +
- + };
- +
- + backlight: backlight {
- + compatible = "pwm-backlight";
- + pwms = <&pwm 0 1666666 0>;
- + 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 = <80>;
- +
- + enable-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
- + };
- +
- + gpu@57000000 {
- + vdd-supply = <&max77621_gpu>;
- + };
- +
- + pinmux: pinmux@700008d4 {
- + pinctrl-names = "default";
- + pinctrl-0 = <&state_default>;
- +
- + state_default: pinmux {
- + // I2C
- + i2c1 {
- + nvidia,pins = "gen1_i2c_sda_pj0", "gen1_i2c_scl_pj1";
- + nvidia,function = "i2c1";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + nvidia,io-hv = <TEGRA_PIN_DISABLE>;
- + };
- + i2c2 {
- + nvidia,pins = "gen2_i2c_scl_pj2", "gen2_i2c_sda_pj3";
- + nvidia,function = "i2c2";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + nvidia,io-hv = <TEGRA_PIN_DISABLE>;
- + };
- + i2c3 {
- + nvidia,pins = "gen3_i2c_scl_pf0", "gen3_i2c_sda_pf1";
- + nvidia,function = "i2c3";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + nvidia,io-hv = <TEGRA_PIN_DISABLE>;
- + };
- + i2c5 {
- + nvidia,pins = "pwr_i2c_scl_py3", "pwr_i2c_sda_py4";
- + nvidia,function = "i2cpmu";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + nvidia,io-hv = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Right side Joy-Con
- + uart2_tx {
- + nvidia,pins = "uart2_tx_pg0", "uart2_rts_pg2";
- + nvidia,function = "uartb";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + uart2_rx {
- + nvidia,pins = "uart2_rx_pg1", "uart2_cts_pg3";
- + nvidia,function = "uartb";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + joycon_right_insert_tx {
- + nvidia,pins = "ph6";
- + nvidia,function = "rsvd0";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + joycon_right_charge {
- + nvidia,pins = "pk3";
- + nvidia,function = "rsvd2";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Left side Joy-Con
- + uart3_tx {
- + nvidia,pins = "uart3_tx_pd1", "uart3_rts_pd3";
- + nvidia,function = "uartc";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + uart3_rx {
- + nvidia,pins = "uart3_rx_pd2", "uart3_cts_pd4";
- + nvidia,function = "uartc";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + joycon_left_insert_tx {
- + nvidia,pins = "pe6";
- + nvidia,function = "rsvd0";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + joycon_left_charge {
- + nvidia,pins = "spdif_in_pcc3";
- + nvidia,function = "rsvd1";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // SD card
- + sdmmc1_clk {
- + nvidia,pins = "sdmmc1_clk_pm0";
- + nvidia,function = "sdmmc1";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + sdmmc1_io {
- + nvidia,pins = "sdmmc1_cmd_pm1", "sdmmc1_dat3_pm2", "sdmmc1_dat2_pm3", "sdmmc1_dat1_pm4", "sdmmc1_dat0_pm5";
- + nvidia,function = "sdmmc1";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + sdmmc1_cd {
- + nvidia,pins = "pz1";
- + nvidia,function = "sdmmc1";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + sdmmc1_pwr {
- + nvidia,pins = "dmic3_clk_pe4";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // LCD control
- + lcd_bl_pwm {
- + nvidia,pins = "lcd_bl_pwm_pv0";
- + nvidia,function = "pwm0";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + lcd_gpio {
- + // bl_en, rst, pwr1, pwr2
- + nvidia,pins = "lcd_bl_en_pv1", "lcd_rst_pv2", "nfc_en_pi0", "nfc_int_pi1";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Buttons
- + buttons {
- + nvidia,pins = "button_vol_up_px6", "button_vol_down_px7";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Audio codec
- + rt5639_pwr { // or reset?
- + nvidia,pins = "pz4";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + rt5639_irq { // guess, could be bb4
- + nvidia,pins = "touch_rst_pv6";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_ENABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Fan
- + fan_pwr {
- + nvidia,pins = "sata_led_active_pa5", "usb_vbus_en0_pcc4";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + fan_pwm {
- + nvidia,pins = "lcd_gpio2_pv4";
- + nvidia,function = "pwm1";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Touchscreen
- + touch_enable {
- + nvidia,pins = "dap4_sclk_pj7";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Bluetooth
- + bt_rst {
- + nvidia,pins = "bt_rst_ph4";
- + nvidia,function = "rsvd0";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + bt_wake {
- + nvidia,pins = "ap_wake_bt_ph3";
- + nvidia,function = "rsvd0";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + bt_uart_tx {
- + nvidia,pins = "uart4_tx_pi4", "uart4_rts_pi6";
- + nvidia,function = "uartd";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + bt_uart_rx {
- + nvidia,pins = "uart4_rx_pi5", "uart4_cts_pi7";
- + nvidia,function = "uartd";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_ENABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- +
- + // Misc unknown GPIOs
- + in_none {
- + // p5,p4,p3,p2,s1,h5,x5,y1,e6,h6,k2
- + nvidia,pins = "sdmmc3_dat0_pp5", "sdmmc3_dat1_pp4", "sdmmc3_dat2_pp3", "sdmmc3_dat3_pp2", "cam2_mclk_ps1", "bt_wake_ap_ph5", "button_power_on_px5", "button_home_py1", "pe6", "ph6", "pk2";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_ENABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + in_up {
- + // s3,bb2,cc2,s7,x1,x4,y0,k4,k6,k7,z0,z3
- + nvidia,pins = "cam_i2c_sda_ps3", "dvfs_clk_pbb2", "spdif_out_pcc2", "cam1_pwdn_ps7", "touch_int_px1", "temp_alert_px4", "button_slide_sw_py0", "pk4", "pk6", "pk7", "pz0", "pz3";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_UP>;
- + nvidia,tristate = <TEGRA_PIN_ENABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + in_down {
- + // p0,s0,h2,x2,k0,k1,z2,bb4
- + nvidia,pins = "sdmmc3_clk_pp0", "cam1_mclk_ps0", "wifi_wake_ap_ph2", "motion_int_px2", "pk0", "pk1", "pz2", "gpio_x3_aud_pbb4";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_ENABLE>;
- + nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + out_none {
- + // h7
- + nvidia,pins = "ap_wake_nfc_ph7";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + out_down {
- + // e5,j5,bb3,cc3,h0,h1,s6,v5,k3,k5,l0
- + nvidia,pins = "dmic3_dat_pe5", "dap4_din_pj5", "gpio_x1_aud_pbb3", "spdif_in_pcc3", "wifi_en_ph0", "wifi_rst_ph1", "cam_flash_en_ps6", "ap_ready_pv5", "pk3", "pk5", "pl0";
- + nvidia,function = "rsvd3";
- + nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- + nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- + };
- + };
- + };
- +
- + /* debug port */
- + serial@70006000 {
- + status = "okay";
- + };
- +
- + /* 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;
- +
- + joycon {
- + compatible = "nintendo,joycon-uart";
- + charge-gpios = <&gpio TEGRA_GPIO(K, 3) GPIO_ACTIVE_HIGH>;
- + };
- + };
- +
- + /* left joycon */
- + serial@70006200 {
- + status = "okay";
- + compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
- + nvidia,invert-txd;
- + nvidia,invert-rts;
- +
- + joycon {
- + compatible = "nintendo,joycon-uart";
- + charge-gpios = <&gpio TEGRA_GPIO(CC, 3) GPIO_ACTIVE_HIGH>;
- + };
- + };
- +
- + /* bluetooth */
- + serial@70006300 {
- + status = "okay";
- + // starts @ 115200, switches to 3000000
- + // flow control, 1 stop bit
- + compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
- +
- + bluetooth {
- + compatible = "brcm,bcm43438-bt";
- + shutdown-gpios = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
- + // level correct?
- + device-wakeup-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_LOW>;
- + };
- + };
- +
- + pwm@7000a000 {
- + status = "okay";
- + #pwm-cells = <3>;
- + };
- +
- + fan: pwm-fan {
- + compatible = "pwm-fan";
- + cooling-min-state = <0>;
- + cooling-max-state = <7>;
- + #cooling-cells = <2>;
- + pwms = <&pwm 1 40000 PWM_POLARITY_INVERTED>;
- + enable-gpios = <&gpio TEGRA_GPIO(A, 5) GPIO_ACTIVE_HIGH>;
- + cooling-levels = <0 64 80 96 128 160 192 255>;
- + };
- +
- + bat: battery {
- + compatible = "simple-battery";
- + precharge-current-microamp = <512000>;
- + charge-term-current-microamp = <256000>;
- + };
- +
- + /* i2c1 @ 100000hz
- + 18: rohm usb-pd
- + 1c: realtek 5639
- + 36: maxim fuel gauge
- + 4c: ti temperature sensor
- + 6b: ti charger
- + */
- + i2c@7000c000 {
- + status = "okay";
- + clock-frequency = <100000>;
- +
- + audio-codec@1c {
- + compatible = "realtek,rt5639";
- + reg = <0x1c>;
- + interrupt-parent = <&gpio>;
- + interrupts = <TEGRA_GPIO(V, 6) IRQ_TYPE_LEVEL_HIGH>;
- + realtek,ldo1-en-gpios = <&gpio TEGRA_GPIO(Z, 4) GPIO_ACTIVE_LOW>;
- + status = "okay";
- + };
- +
- + temperature-sensor@4c {
- + compatible = "ti,tmp451";
- + reg = <0x4c>;
- + };
- +
- + bq24190: charger@6b {
- + compatible = "ti,bq24190";
- + reg = <0x6b>;
- + interrupt-parent = <&gpio>;
- + interrupts = <TEGRA_GPIO(Z, 0) IRQ_TYPE_EDGE_FALLING>;
- + ti,system-minimum-microvolt = <3200000>;
- + monitored-battery = <&bat>;
- + status = "okay";
- + omit-battery-class;
- + };
- +
- + battery-charger@36 {
- + compatible = "maxim,max17050";
- + reg = <0x36>;
- + interrupt-parent = <&gpio>;
- + interrupts = <TEGRA_GPIO(Y, 0) IRQ_TYPE_LEVEL_LOW>;
- + maxim,rsns-microohm = <10000>;
- + maxim,over-heat-temp = <600>;
- + maxim,over-volt = <4300>;
- + monitored-battery = <&bat>;
- + power-supplies = <&bq24190>;
- + status = "okay";
- + };
- + };
- +
- + /* i2c2 @ 400000hz
- + 29: rohm ambient light sensor
- + */
- + i2c@7000c400 {
- + status = "okay";
- + clock-frequency = <400000>;
- +
- + light-sensor@29 {
- + compatible = "rohm,bh1730fvc";
- + reg = <0x29>;
- + };
- + };
- +
- + /* i2c3 @ 400000hz
- + 49: stm touchscreen controller
- + */
- + i2c@7000c500 {
- + status = "okay";
- + clock-frequency = <400000>;
- +
- + stmfts: touchscreen@49 {
- + compatible = "st,stmfts";
- + reg = <0x49>;
- + interrupt-parent = <&gpio>;
- + interrupts = <TEGRA_GPIO(X, 1) IRQ_TYPE_LEVEL_LOW>;
- + interrupt-enable-reg = <0x2c 0x48>;
- + avdd-supply = <&avdd_touchscreen>;
- + vdd-supply = <&vdd_touchscreen>;
- + touchscreen-size-x = <1280>;
- + touchscreen-size-y = <720>;
- + };
- + };
- +
- + /* i2c5 @ 400000hz
- + 1b: max77621_cpu
- + 1c: max77621_gpu
- + 3c: max77620
- + 68: max77620_rtc
- + */
- + i2c@7000d000 {
- + status = "okay";
- + clock-frequency = <400000>;
- +
- + max77620: max77620@3c {
- + compatible = "maxim,max77620";
- + reg = <0x3c>;
- + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
- +
- + #interrupt-cells = <2>;
- + interrupt-controller;
- +
- + #gpio-cells = <2>;
- + gpio-controller;
- +
- + #thermal-sensor-cells = <0>;
- +
- +
- + pinctrl-names = "default";
- + pinctrl-0 = <&max77620_default>;
- +
- + max77620_default: pinmux {
- + gpio2 {
- + pins = "gpio2";
- + function = "fps-out";
- + maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + gpio3 {
- + pins = "gpio3";
- + function = "fps-out";
- + maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
- + maxim,active-fps-power-up-slot = <4>;
- + maxim,active-fps-power-down-slot = <2>;
- + };
- +
- + pin_32k {
- + pins = "gpio4";
- + function = "32k-out1";
- + };
- +
- + gpio5_6_7 {
- + pins = "gpio5", "gpio6", "gpio7";
- + function = "gpio";
- + drive-push-pull = <1>;
- + };
- + };
- +
- + fps {
- + fps0 {
- + maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
- + maxim,suspend-fps-time-period-us = <5120>;
- + };
- +
- + fps1 {
- + maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
- + maxim,suspend-fps-time-period-us = <5120>;
- + };
- +
- + fps2 {
- + maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
- + maxim,suspend-fps-time-period-us = <5120>;
- + };
- + };
- +
- + regulators {
- + in-ldo0-1-supply = <&vdd_pre>;
- + in-ldo7-8-supply = <&vdd_pre>;
- +
- + vdd_soc: sd0 {
- + regulator-name = "VDD_SOC";
- + regulator-min-microvolt = <825000>;
- + regulator-max-microvolt = <1125000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <146>;
- + regulator-disable-ramp-delay = <4080>;
- + regulator-ramp-delay = <27500>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
- + maxim,active-fps-power-up-slot = <1>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + vdd_ddr: sd1 {
- + regulator-name = "VDD_DDR_1V1_PMIC";
- + regulator-min-microvolt = <1125000>;
- + regulator-max-microvolt = <1125000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <130>;
- + regulator-disable-ramp-delay = <145800>;
- + regulator-ramp-delay = <27500>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
- + maxim,active-fps-power-up-slot = <5>;
- + maxim,active-fps-power-down-slot = <1>;
- + };
- +
- + vdd_pre: sd2 {
- + regulator-name = "VDD_PRE_REG_1V35";
- + regulator-min-microvolt = <1325000>;
- + regulator-max-microvolt = <1350000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <176>;
- + regulator-disable-ramp-delay = <32000>;
- + regulator-ramp-delay = <27500>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
- + maxim,active-fps-power-up-slot = <2>;
- + maxim,active-fps-power-down-slot = <5>;
- + };
- +
- + vdd_1v8: sd3 {
- + regulator-name = "VDD_1V8";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <242>;
- + regulator-disable-ramp-delay = <118000>;
- + regulator-ramp-delay = <27500>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
- + maxim,active-fps-power-up-slot = <3>;
- + maxim,active-fps-power-down-slot = <3>;
- + };
- +
- + vdd_sys_1v2: ldo0 {
- + regulator-name = "AVDD_SYS_1V2";
- + regulator-min-microvolt = <1200000>;
- + regulator-max-microvolt = <1200000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <26>;
- + regulator-disable-ramp-delay = <626>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + vdd_pex_1v05: ldo1 {
- + regulator-name = "VDD_PEX_1V05";
- + regulator-min-microvolt = <1050000>;
- + regulator-max-microvolt = <1050000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <22>;
- + regulator-disable-ramp-delay = <630>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + vddio_sdmmc: ldo2 {
- + regulator-name = "VDDIO_SDMMC";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <62>;
- + regulator-disable-ramp-delay = <650>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + vdd_unk_ldo3: ldo3 {
- + regulator-name = "VDD_UNK_LDO3";
- + regulator-min-microvolt = <3100000>;
- + regulator-max-microvolt = <3100000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <50>;
- + regulator-disable-ramp-delay = <1110>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + vdd_rtc: ldo4 {
- + regulator-name = "VDD_RTC";
- + regulator-min-microvolt = <850000>;
- + regulator-max-microvolt = <850000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <22>;
- + regulator-disable-ramp-delay = <610>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
- + maxim,active-fps-power-up-slot = <1>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + vdd_unk_ldo5: ldo5 {
- + regulator-name = "VDD_UNK_LDO5";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <62>;
- + regulator-disable-ramp-delay = <640>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + avdd_touchscreen: ldo6 {
- + regulator-name = "AVDD_TOUCHSCREEN";
- + regulator-min-microvolt = <2900000>;
- + regulator-max-microvolt = <2900000>;
- +
- + regulator-enable-ramp-delay = <36>;
- + regulator-disable-ramp-delay = <674>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- +
- + avdd_1v05_pll: ldo7 {
- + regulator-name = "AVDD_1V05_PLL";
- + regulator-min-microvolt = <1050000>;
- + regulator-max-microvolt = <1050000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <24>;
- + regulator-disable-ramp-delay = <2768>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
- + maxim,active-fps-power-up-slot = <3>;
- + maxim,active-fps-power-down-slot = <4>;
- + };
- +
- + avdd_1v05: ldo8 {
- + regulator-name = "AVDD_SATA_HDMI_DP_1V05";
- + regulator-min-microvolt = <1050000>;
- + regulator-max-microvolt = <1050000>;
- + regulator-always-on;
- + regulator-boot-on;
- +
- + regulator-enable-ramp-delay = <22>;
- + regulator-disable-ramp-delay = <1160>;
- + regulator-ramp-delay = <100000>;
- +
- + maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
- + maxim,active-fps-power-up-slot = <0>;
- + maxim,active-fps-power-down-slot = <7>;
- + };
- + };
- + };
- +
- + max77621_cpu: pmic@1b {
- + compatible = "maxim,max77621";
- + reg = <0x1b>;
- +// interrupt-parent = <&gpio>;
- +// interrupts = <TEGRA_GPIO(Y, 1) IRQ_TYPE_LEVEL_LOW>;
- + regulator-name = "PPVAR_CPU";
- + // smaug: 800000..1231250
- + regulator-min-microvolt = <800000>;
- + regulator-max-microvolt = <1231250>;
- + regulator-ramp-delay = <12000>;
- + maxim,externally-enable;
- + maxim,enable-gpio = <&max77620 5 0>;
- + maxim,dvs-default-state = <1>;
- + regulator-always-on;
- + maxim,enable-remote-sense;
- + maxim,enable-active-discharge;
- + junction-warn-millicelsius = <120>;
- +
- + // not supported in mainline yet
- + //maxim,inductor-value = <MAX8973_INDUCTOR_VAL_PLUS_30_PER>;
- +
- + #thermal-sensor-cells = <0>;
- + };
- +
- + max77621_gpu: pmic@1c {
- + compatible = "maxim,max77621";
- + reg = <0x1c>;
- +// interrupt-parent = <&gpio>;
- +// interrupts = <TEGRA_GPIO(A, 6) IRQ_TYPE_LEVEL_LOW>;
- + regulator-name = "PPVAR_GPU";
- + regulator-min-microvolt = <840000>;
- + regulator-max-microvolt = <1150000>;
- + regulator-ramp-delay = <12000>;
- + maxim,externally-enable;
- + maxim,enable-gpio = <&max77620 6 0>;
- + maxim,dvs-default-state = <1>;
- + maxim,enable-remote-sense;
- + maxim,enable-active-discharge;
- + junction-warn-millicelsius = <120>;
- +
- + // not supported in mainline yet
- + //maxim,inductor-value = <MAX8973_INDUCTOR_VAL_PLUS_30_PER>;
- +
- + #thermal-sensor-cells = <0>;
- + };
- + };
- +
- + pmc@7000e400 {
- + nvidia,invert-interrupt;
- + };
- +
- + usb@70090000 {
- + phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
- + <&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>;
- + phy-names = "usb2-0", "usb3-0";
- +
- + dvddio-pex-supply = <&vdd_pex_1v05>;
- + hvddio-pex-supply = <&vdd_1v8>;
- + avdd-usb-supply = <&vdd_3v3_sys>;
- + avdd-pll-utmip-supply = <&vdd_1v8>;
- + avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
- + dvdd-usb-ss-pll-supply = <&vdd_pex_1v05>;
- + hvdd-usb-ss-pll-e-supply = <&vdd_1v8>;
- +
- + status = "okay";
- + };
- +
- + padctl@7009f000 {
- + status = "okay";
- +
- + pads {
- + usb2 {
- + status = "okay";
- +
- + lanes {
- + usb2-0 {
- + nvidia,function = "xusb";
- + status = "okay";
- + };
- + };
- + };
- +
- + pcie {
- + status = "okay";
- +
- + lanes {
- + pcie-0 {
- + nvidia,function = "pcie-x1";
- + status = "okay";
- + };
- + pcie-1 {
- + nvidia,function = "pcie-x4";
- + status = "okay";
- + };
- + pcie-2 {
- + nvidia,function = "pcie-x4";
- + status = "okay";
- + };
- + pcie-3 {
- + nvidia,function = "pcie-x4";
- + status = "okay";
- + };
- + pcie-4 {
- + nvidia,function = "pcie-x4";
- + status = "okay";
- + };
- + pcie-5 {
- + nvidia,function = "usb3-ss";
- + status = "okay";
- + };
- + pcie-6 {
- + nvidia,function = "usb3-ss";
- + status = "okay";
- + };
- + };
- + };
- + };
- +
- + ports {
- + usb2-0 {
- + status = "okay";
- + vbus-supply = <&usbc_vbus>;
- + mode = "otg";
- + };
- +
- + usb3-0 {
- + nvidia,usb2-companion = <0>;
- + vbus-supply = <&usbc_vbus>;
- + status = "okay";
- + };
- + };
- + };
- +
- + /* MMC/SD */
- + sdhci@700b0000 {
- + status = "okay";
- + bus-width = <4>;
- +
- + cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
- + power-gpios = <&gpio TEGRA_GPIO(E, 4) GPIO_ACTIVE_HIGH>;
- + vqmmc-supply = <&vddio_sdmmc>;
- + };
- +
- + /* eMMC */
- + sdhci@700b0600 {
- + status = "okay";
- + bus-width = <8>;
- + non-removable;
- + };
- +
- + aconnect@702c0000 {
- + status = "okay";
- +
- + dma@702e2000 {
- + status = "okay";
- + };
- +
- + agic@702f9000 {
- + status = "okay";
- + };
- + };
- +
- + clocks {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + clk32k_in: clock@0 {
- + compatible = "fixed-clock";
- + reg = <0>;
- + #clock-cells = <0>;
- + clock-frequency = <32768>;
- + };
- + };
- +
- + gpio-keys {
- + compatible = "gpio-keys";
- + label = "gpio-keys";
- +
- + volume_down {
- + label = "Volume Down";
- + gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_VOLUMEDOWN>;
- + };
- +
- + volume_up {
- + label = "Volume Up";
- + gpios = <&gpio TEGRA_GPIO(X, 6) GPIO_ACTIVE_LOW>;
- + linux,code = <KEY_VOLUMEUP>;
- + };
- + };
- +
- + regulators {
- + compatible = "simple-bus";
- + #address-cells = <1>;
- + #size-cells = <0>;
- +
- + vdd_3v3_sys: regulator@0 {
- + compatible = "regulator-fixed";
- + reg = <0>;
- + regulator-name = "PP3300";
- + regulator-min-microvolt = <3300000>;
- + regulator-max-microvolt = <3300000>;
- + regulator-boot-on;
- + regulator-always-on;
- + };
- +
- + vdd_lcd_1: regulator@1 {
- + compatible = "regulator-fixed";
- + reg = <1>;
- + regulator-name = "vcc_lcd_1";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + gpio = <&gpio TEGRA_GPIO(I, 0) GPIO_ACTIVE_HIGH>;
- + enable-active-high;
- + };
- +
- + vdd_lcd_2: regulator@2 {
- + compatible = "regulator-fixed";
- + reg = <2>;
- + regulator-name = "vcc_lcd_2";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + gpio = <&gpio TEGRA_GPIO(I, 1) GPIO_ACTIVE_HIGH>;
- + enable-active-high;
- + };
- +
- + vdd_dsi_csi: regulator@3 {
- + compatible = "regulator-fixed";
- + reg = <3>;
- + regulator-name = "AVDD_DSI_CSI_1V2";
- + gpio = <&max77620 7 0>;
- + enable-active-high;
- + regulator-min-microvolt = <1200000>;
- + regulator-max-microvolt = <1200000>;
- + vin-supply = <&vdd_sys_1v2>;
- + regulator-always-on;
- + regulator-boot-on;
- + };
- +
- + usbc_vbus: regulator@4 {
- + compatible = "regulator-fixed";
- + reg = <4>;
- + regulator-name = "USBC_VBUS";
- + regulator-min-microvolt = <5000000>;
- + regulator-max-microvolt = <5000000>;
- + };
- +
- + vdd_touchscreen: regulator@5 {
- + compatible = "regulator-fixed";
- + reg = <5>;
- + regulator-name = "vdd_touchscreen";
- + regulator-min-microvolt = <1800000>;
- + regulator-max-microvolt = <1800000>;
- + gpio = <&gpio TEGRA_GPIO(J, 7) GPIO_ACTIVE_HIGH>;
- + enable-active-high;
- + };
- + };
- +
- + thermal-zones {
- + cpu {
- + polling-delay-passive = <250>;
- + polling-delay = <500>;
- + hwmon;
- +
- + trips {
- + cpu_alert0: cpu-alert-0 {
- + temperature = <40000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + cpu_alert1: cpu-alert-1 {
- + temperature = <50000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + cpu_alert2: cpu-alert-2 {
- + temperature = <60000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + cpu_alert3: cpu-alert-3 {
- + temperature = <70000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + cpu_alert4: cpu-alert-4 {
- + temperature = <80000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + };
- +
- + cooling-maps {
- + map1 {
- + trip = <&cpu_alert0>;
- + cooling-device = <&fan 1 2>;
- + };
- + map2 {
- + trip = <&cpu_alert1>;
- + cooling-device = <&fan 2 3>;
- + };
- + map3 {
- + trip = <&cpu_alert2>;
- + cooling-device = <&fan 3 5>;
- + };
- + map4 {
- + trip = <&cpu_alert3>;
- + cooling-device = <&fan 5 6>;
- + };
- + map5 {
- + trip = <&cpu_alert4>;
- + cooling-device = <&fan 6 THERMAL_NO_LIMIT>;
- + };
- + };
- + };
- +
- + gpu {
- + polling-delay-passive = <250>;
- + polling-delay = <500>;
- + hwmon;
- +
- + trips {
- + gpu_alert0: gpu-alert-0 {
- + temperature = <40000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + gpu_alert1: gpu-alert-1 {
- + temperature = <50000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + gpu_alert2: gpu-alert-2 {
- + temperature = <60000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + gpu_alert3: gpu-alert-3 {
- + temperature = <70000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + gpu_alert4: gpu-alert-4 {
- + temperature = <80000>;
- + hysteresis = <5000>;
- + type = "active";
- + };
- + };
- +
- + cooling-maps {
- + map1 {
- + trip = <&gpu_alert0>;
- + cooling-device = <&fan 1 2>;
- + };
- + map2 {
- + trip = <&gpu_alert1>;
- + cooling-device = <&fan 2 3>;
- + };
- + map3 {
- + trip = <&gpu_alert2>;
- + cooling-device = <&fan 3 5>;
- + };
- + map4 {
- + trip = <&gpu_alert3>;
- + cooling-device = <&fan 5 6>;
- + };
- + map5 {
- + trip = <&gpu_alert4>;
- + cooling-device = <&fan 6 THERMAL_NO_LIMIT>;
- + };
- + };
- + };
- +
- + mem {
- + hwmon;
- + };
- +
- + pllx {
- + hwmon;
- + };
- +
- + pmic {
- + 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 {
- + polling-delay-passive = <250>;
- + polling-delay = <500>;
- + thermal-sensors = <&max77621_cpu>;
- +
- + 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 {
- + polling-delay-passive = <250>;
- + polling-delay = <500>;
- + thermal-sensors = <&max77621_gpu>;
- +
- + 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.
- + */
- + };
- + };
- +
- + };
- +};
- diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
- index 212e663..19720b5 100644
- --- a/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
- +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
- @@ -284,6 +284,24 @@
- non-removable;
- };
- + clock@70110000 {
- + status = "okay";
- + nvidia,pwm-to-pmic;
- + nvidia,init-uv = <1000000>;
- + nvidia,align-step-uv = <19200>; /* 19.2mV */
- + nvidia,align-offset-uv = <708000>; /* 708mV */
- + nvidia,sample-rate = <25000>;
- + nvidia,droop-ctrl = <0x00000f00>;
- + nvidia,force-mode = <1>;
- + nvidia,cf = <6>;
- + nvidia,ci = <0>;
- + nvidia,cg = <2>;
- + nvidia,pwm-period = <2500>; /* 2.5us */
- + pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
- + pinctrl-0 = <&dvfs_pwm_active_state>;
- + pinctrl-1 = <&dvfs_pwm_inactive_state>;
- + };
- +
- clocks {
- compatible = "simple-bus";
- #address-cells = <1>;
- diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
- index 9d5a0e6..54b5235 100644
- --- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
- +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
- @@ -1278,6 +1278,18 @@
- nvidia,open-drain = <TEGRA_PIN_DISABLE>;
- };
- };
- + dvfs_pwm_active_state: dvfs_pwm_active {
- + dvfs_pwm_pbb1 {
- + nvidia,pins = "dvfs_pwm_pbb1";
- + nvidia,tristate = <TEGRA_PIN_DISABLE>;
- + };
- + };
- + dvfs_pwm_inactive_state: dvfs_pwm_inactive {
- + dvfs_pwm_pbb1 {
- + nvidia,pins = "dvfs_pwm_pbb1";
- + nvidia,tristate = <TEGRA_PIN_ENABLE>;
- + };
- + };
- };
- pwm@7000a000 {
- diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
- index 3be920e..1dc51aa 100644
- --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
- +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
- @@ -3,8 +3,10 @@
- #include <dt-bindings/gpio/tegra-gpio.h>
- #include <dt-bindings/memory/tegra210-mc.h>
- #include <dt-bindings/pinctrl/pinctrl-tegra.h>
- +#include <dt-bindings/reset/tegra210-car.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/thermal/tegra124-soctherm.h>
- +#include <dt-bindings/soc/tegra/pmc.h>
- / {
- compatible = "nvidia,tegra210";
- @@ -1027,6 +1029,7 @@
- clock-names = "sdhci";
- resets = <&tegra_car 14>;
- reset-names = "sdhci";
- + nvidia,pad = <TEGRA_IO_PAD_SDMMC1>;
- status = "disabled";
- };
- @@ -1049,6 +1052,7 @@
- clock-names = "sdhci";
- resets = <&tegra_car 69>;
- reset-names = "sdhci";
- + nvidia,pad = <TEGRA_IO_PAD_SDMMC3>;
- status = "disabled";
- };
- @@ -1072,6 +1076,25 @@
- #nvidia,mipi-calibrate-cells = <1>;
- };
- + dfll: clock@70110000 {
- + compatible = "nvidia,tegra210-dfll";
- + reg = <0 0x70110000 0 0x100>, /* DFLL control */
- + <0 0x70110000 0 0x100>, /* I2C output control */
- + <0 0x70110100 0 0x100>, /* Integrated I2C controller */
- + <0 0x70110200 0 0x100>; /* Look-up table RAM */
- + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
- + clocks = <&tegra_car TEGRA210_CLK_DFLL_SOC>,
- + <&tegra_car TEGRA210_CLK_DFLL_REF>,
- + <&tegra_car TEGRA210_CLK_I2C5>;
- + clock-names = "soc", "ref", "i2c";
- + resets = <&tegra_car TEGRA210_RST_DFLL_DVCO>;
- + reset-names = "dvco";
- + #clock-cells = <0>;
- + clock-output-names = "dfllCPU_out";
- + out-clock-name="dfll_cpu";
- + status = "disabled";
- + };
- +
- aconnect@702c0000 {
- compatible = "nvidia,tegra210-aconnect";
- clocks = <&tegra_car TEGRA210_CLK_APE>,
- @@ -1226,6 +1249,13 @@
- device_type = "cpu";
- compatible = "arm,cortex-a57";
- reg = <0>;
- + clocks = <&tegra_car TEGRA210_CLK_CCLK_G>,
- + <&tegra_car TEGRA210_CLK_PLL_X>,
- + <&tegra_car TEGRA210_CLK_PLL_P_OUT_CPU>,
- + <&dfll>;
- + clock-names = "cpu_g", "pll_x", "pll_p", "dfll";
- + /* FIXME: what's the actual transition time? */
- + clock-latency = <300000>;
- };
- cpu@1 {
- diff --git a/arch/arm64/configs/nintendo-switch_defconfig b/arch/arm64/configs/nintendo-switch_defconfig
- new file mode 100644
- index 0000000..653df8c
- --- /dev/null
- +++ b/arch/arm64/configs/nintendo-switch_defconfig
- @@ -0,0 +1,602 @@
- +CONFIG_CROSS_COMPILE="aarch64-linux-gnu-"
- +CONFIG_SYSVIPC=y
- +CONFIG_POSIX_MQUEUE=y
- +CONFIG_NO_HZ=y
- +CONFIG_HIGH_RES_TIMERS=y
- +CONFIG_BSD_PROCESS_ACCT=y
- +CONFIG_BSD_PROCESS_ACCT_V3=y
- +CONFIG_TASKSTATS=y
- +CONFIG_TASK_DELAY_ACCT=y
- +CONFIG_TASK_XACCT=y
- +CONFIG_TASK_IO_ACCOUNTING=y
- +CONFIG_IKCONFIG=y
- +CONFIG_IKCONFIG_PROC=y
- +CONFIG_LOG_BUF_SHIFT=18
- +CONFIG_LOG_CPU_MAX_BUF_SHIFT=14
- +CONFIG_MEMCG=y
- +CONFIG_MEMCG_SWAP=y
- +CONFIG_BLK_CGROUP=y
- +CONFIG_CFS_BANDWIDTH=y
- +CONFIG_CGROUP_PIDS=y
- +CONFIG_CGROUP_FREEZER=y
- +CONFIG_CGROUP_HUGETLB=y
- +CONFIG_CPUSETS=y
- +CONFIG_CGROUP_DEVICE=y
- +CONFIG_CGROUP_CPUACCT=y
- +CONFIG_CGROUP_PERF=y
- +CONFIG_CGROUP_BPF=y
- +CONFIG_USER_NS=y
- +CONFIG_SCHED_AUTOGROUP=y
- +CONFIG_RELAY=y
- +CONFIG_BLK_DEV_INITRD=y
- +CONFIG_BPF_SYSCALL=y
- +CONFIG_USERFAULTFD=y
- +# CONFIG_COMPAT_BRK is not set
- +CONFIG_SLAB=y
- +CONFIG_SLAB_FREELIST_RANDOM=y
- +CONFIG_PROFILING=y
- +CONFIG_JUMP_LABEL=y
- +CONFIG_CC_STACKPROTECTOR_STRONG=y
- +CONFIG_BLK_DEV_BSGLIB=y
- +CONFIG_BLK_DEV_INTEGRITY=y
- +CONFIG_BLK_DEV_THROTTLING=y
- +CONFIG_BLK_WBT=y
- +CONFIG_BLK_WBT_SQ=y
- +CONFIG_PARTITION_ADVANCED=y
- +CONFIG_MAC_PARTITION=y
- +CONFIG_CFQ_GROUP_IOSCHED=y
- +CONFIG_IOSCHED_BFQ=y
- +CONFIG_BFQ_GROUP_IOSCHED=y
- +CONFIG_ARCH_TEGRA=y
- +CONFIG_PCI=y
- +CONFIG_PCIEPORTBUS=y
- +CONFIG_PCI_PASID=y
- +CONFIG_PCI_TEGRA=y
- +# CONFIG_CAVIUM_ERRATUM_22375 is not set
- +# CONFIG_CAVIUM_ERRATUM_23154 is not set
- +# CONFIG_CAVIUM_ERRATUM_27456 is not set
- +# CONFIG_CAVIUM_ERRATUM_30115 is not set
- +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set
- +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set
- +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set
- +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set
- +# CONFIG_HISILICON_ERRATUM_161600802 is not set
- +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set
- +CONFIG_ARM64_VA_BITS_48=y
- +CONFIG_SCHED_MC=y
- +CONFIG_SCHED_SMT=y
- +CONFIG_NR_CPUS=16
- +CONFIG_PREEMPT=y
- +CONFIG_HZ_1000=y
- +CONFIG_KSM=y
- +CONFIG_TRANSPARENT_HUGEPAGE=y
- +CONFIG_CLEANCACHE=y
- +CONFIG_FRONTSWAP=y
- +CONFIG_CMA=y
- +CONFIG_ZPOOL=y
- +CONFIG_ZBUD=y
- +CONFIG_Z3FOLD=y
- +CONFIG_ZSMALLOC=y
- +CONFIG_SECCOMP=y
- +CONFIG_KEXEC=y
- +# CONFIG_EFI is not set
- +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
- +CONFIG_COMPAT=y
- +CONFIG_PM_DEBUG=y
- +CONFIG_PM_ADVANCED_DEBUG=y
- +CONFIG_CPU_IDLE=y
- +CONFIG_CPU_IDLE_GOV_LADDER=y
- +CONFIG_ARM_CPUIDLE=y
- +CONFIG_CPU_FREQ=y
- +CONFIG_CPU_FREQ_STAT=y
- +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
- +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
- +CONFIG_CPU_FREQ_GOV_USERSPACE=y
- +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
- +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
- +CONFIG_CPUFREQ_DT=y
- +CONFIG_ARM_BIG_LITTLE_CPUFREQ=y
- +CONFIG_ARM_DT_BL_CPUFREQ=y
- +# CONFIG_ARM_TEGRA20_CPUFREQ is not set
- +CONFIG_NET=y
- +CONFIG_PACKET=y
- +CONFIG_PACKET_DIAG=y
- +CONFIG_UNIX=y
- +CONFIG_UNIX_DIAG=y
- +CONFIG_XFRM_USER=y
- +CONFIG_NET_KEY=y
- +CONFIG_INET=y
- +CONFIG_IP_MULTICAST=y
- +CONFIG_NET_IPIP=y
- +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
- +# CONFIG_INET_XFRM_MODE_TUNNEL is not set
- +# CONFIG_INET_XFRM_MODE_BEET is not set
- +# CONFIG_INET_DIAG is not set
- +CONFIG_INET6_AH=y
- +CONFIG_INET6_ESP=y
- +CONFIG_INET6_IPCOMP=y
- +CONFIG_IPV6_MIP6=y
- +CONFIG_IPV6_TUNNEL=y
- +CONFIG_IPV6_MULTIPLE_TABLES=y
- +CONFIG_IPV6_SUBTREES=y
- +CONFIG_IPV6_MROUTE=y
- +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
- +CONFIG_IPV6_PIMSM_V2=y
- +CONFIG_SCTP_COOKIE_HMAC_SHA1=y
- +CONFIG_NETLINK_DIAG=y
- +CONFIG_CGROUP_NET_PRIO=y
- +CONFIG_CGROUP_NET_CLASSID=y
- +CONFIG_BT=y
- +CONFIG_BT_RFCOMM=y
- +CONFIG_BT_RFCOMM_TTY=y
- +CONFIG_BT_BNEP=y
- +CONFIG_BT_BNEP_MC_FILTER=y
- +CONFIG_BT_BNEP_PROTO_FILTER=y
- +CONFIG_BT_HIDP=y
- +CONFIG_BT_HCIUART=y
- +CONFIG_BT_HCIUART_BCSP=y
- +CONFIG_BT_HCIUART_BCM=y
- +CONFIG_BT_HCIBCM203X=y
- +CONFIG_CFG80211=y
- +CONFIG_CFG80211_DEVELOPER_WARNINGS=y
- +CONFIG_CFG80211_WEXT=y
- +CONFIG_MAC80211=y
- +CONFIG_MAC80211_LEDS=y
- +CONFIG_RFKILL=y
- +CONFIG_RFKILL_GPIO=y
- +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
- +CONFIG_DEVTMPFS=y
- +CONFIG_EXTRA_FIRMWARE="nvidia/gm20b/pmu/desc.bin nvidia/gm20b/pmu/sig.bin nvidia/gm20b/pmu/image.bin nvidia/gm20b/acr/bl.bin nvidia/gm20b/acr/ucode_load.bin nvidia/gm20b/gr/sw_method_init.bin nvidia/gm20b/gr/gpccs_inst.bin nvidia/gm20b/gr/fecs_bl.bin nvidia/gm20b/gr/sw_bundle_init.bin nvidia/gm20b/gr/fecs_inst.bin nvidia/gm20b/gr/sw_ctx.bin nvidia/gm20b/gr/fecs_data.bin nvidia/gm20b/gr/gpccs_data.bin nvidia/gm20b/gr/sw_nonctx.bin nvidia/gm20b/gr/fecs_sig.bin nvidia/tegra210/xusb.bin nvidia/tegra210/vic04_ucode.bin brcm/brcmfmac4356-pcie.bin brcm/brcmfmac4356-pcie.txt"
- +CONFIG_TEGRA_ACONNECT=y
- +CONFIG_TEGRA_GMI=y
- +CONFIG_CONNECTOR=y
- +CONFIG_BLK_DEV_LOOP=y
- +CONFIG_BLK_DEV_RAM=y
- +CONFIG_EEPROM_AT24=y
- +CONFIG_EEPROM_LEGACY=y
- +CONFIG_EEPROM_93CX6=y
- +CONFIG_SCSI=y
- +CONFIG_SCSI_MQ_DEFAULT=y
- +CONFIG_BLK_DEV_SD=y
- +CONFIG_CHR_DEV_SG=y
- +# CONFIG_SCSI_LOWLEVEL is not set
- +CONFIG_NETDEVICES=y
- +CONFIG_TUN=y
- +CONFIG_VETH=y
- +# CONFIG_NET_VENDOR_3COM is not set
- +# CONFIG_NET_VENDOR_ADAPTEC is not set
- +# CONFIG_NET_VENDOR_AGERE is not set
- +# CONFIG_NET_VENDOR_ALACRITECH is not set
- +# CONFIG_NET_VENDOR_ALTEON is not set
- +# CONFIG_NET_VENDOR_AMAZON is not set
- +# CONFIG_NET_VENDOR_AMD is not set
- +# CONFIG_NET_VENDOR_AQUANTIA is not set
- +# CONFIG_NET_VENDOR_ARC is not set
- +# CONFIG_NET_VENDOR_ATHEROS is not set
- +# CONFIG_NET_CADENCE is not set
- +# CONFIG_NET_VENDOR_BROADCOM is not set
- +# CONFIG_NET_VENDOR_BROCADE is not set
- +# CONFIG_NET_VENDOR_CAVIUM is not set
- +# CONFIG_NET_VENDOR_CHELSIO is not set
- +# CONFIG_NET_VENDOR_CISCO is not set
- +# CONFIG_NET_VENDOR_CORTINA is not set
- +# CONFIG_NET_VENDOR_DEC is not set
- +# CONFIG_NET_VENDOR_DLINK is not set
- +# CONFIG_NET_VENDOR_EMULEX is not set
- +# CONFIG_NET_VENDOR_EZCHIP is not set
- +# CONFIG_NET_VENDOR_EXAR is not set
- +# CONFIG_NET_VENDOR_HISILICON is not set
- +# CONFIG_NET_VENDOR_HP is not set
- +# CONFIG_NET_VENDOR_HUAWEI is not set
- +# CONFIG_NET_VENDOR_INTEL is not set
- +# CONFIG_NET_VENDOR_MARVELL is not set
- +# CONFIG_NET_VENDOR_MELLANOX is not set
- +# CONFIG_NET_VENDOR_MICREL is not set
- +# CONFIG_NET_VENDOR_MYRI is not set
- +# CONFIG_NET_VENDOR_NATSEMI is not set
- +# CONFIG_NET_VENDOR_NETRONOME is not set
- +# CONFIG_NET_VENDOR_NVIDIA is not set
- +# CONFIG_NET_VENDOR_OKI is not set
- +# CONFIG_NET_PACKET_ENGINE is not set
- +# CONFIG_NET_VENDOR_QLOGIC is not set
- +# CONFIG_NET_VENDOR_QUALCOMM is not set
- +# CONFIG_NET_VENDOR_REALTEK is not set
- +# CONFIG_NET_VENDOR_RENESAS is not set
- +# CONFIG_NET_VENDOR_RDC is not set
- +# CONFIG_NET_VENDOR_ROCKER is not set
- +# CONFIG_NET_VENDOR_SAMSUNG is not set
- +# CONFIG_NET_VENDOR_SEEQ is not set
- +# CONFIG_NET_VENDOR_SILAN is not set
- +# CONFIG_NET_VENDOR_SIS is not set
- +# CONFIG_NET_VENDOR_SOLARFLARE is not set
- +# CONFIG_NET_VENDOR_SMSC is not set
- +# CONFIG_NET_VENDOR_SOCIONEXT is not set
- +# CONFIG_NET_VENDOR_STMICRO is not set
- +# CONFIG_NET_VENDOR_SUN is not set
- +# CONFIG_NET_VENDOR_TEHUTI is not set
- +# CONFIG_NET_VENDOR_TI is not set
- +# CONFIG_NET_VENDOR_VIA is not set
- +# CONFIG_NET_VENDOR_WIZNET is not set
- +# CONFIG_NET_VENDOR_SYNOPSYS is not set
- +CONFIG_PHYLIB=y
- +# CONFIG_USB_NET_DRIVERS is not set
- +# CONFIG_WLAN_VENDOR_ADMTEK is not set
- +# CONFIG_WLAN_VENDOR_ATH is not set
- +# CONFIG_WLAN_VENDOR_ATMEL is not set
- +CONFIG_BRCMFMAC=y
- +# CONFIG_BRCMFMAC_SDIO is not set
- +CONFIG_BRCMFMAC_PCIE=y
- +# CONFIG_WLAN_VENDOR_CISCO is not set
- +# CONFIG_WLAN_VENDOR_INTEL is not set
- +# CONFIG_WLAN_VENDOR_INTERSIL is not set
- +# CONFIG_WLAN_VENDOR_MARVELL is not set
- +# CONFIG_WLAN_VENDOR_MEDIATEK is not set
- +# CONFIG_WLAN_VENDOR_RALINK is not set
- +# CONFIG_WLAN_VENDOR_REALTEK is not set
- +# CONFIG_WLAN_VENDOR_RSI is not set
- +# CONFIG_WLAN_VENDOR_ST is not set
- +# CONFIG_WLAN_VENDOR_TI is not set
- +# CONFIG_WLAN_VENDOR_ZYDAS is not set
- +# CONFIG_WLAN_VENDOR_QUANTENNA is not set
- +CONFIG_INPUT_POLLDEV=y
- +CONFIG_INPUT_SPARSEKMAP=y
- +CONFIG_INPUT_MOUSEDEV=y
- +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
- +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=720
- +CONFIG_INPUT_JOYDEV=y
- +CONFIG_INPUT_EVDEV=y
- +CONFIG_KEYBOARD_GPIO=y
- +# CONFIG_INPUT_MOUSE is not set
- +CONFIG_INPUT_TOUCHSCREEN=y
- +CONFIG_TOUCHSCREEN_STMFTS=y
- +CONFIG_INPUT_MISC=y
- +CONFIG_INPUT_UINPUT=y
- +# CONFIG_LEGACY_PTYS is not set
- +CONFIG_SERIAL_8250=y
- +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
- +CONFIG_SERIAL_8250_CONSOLE=y
- +# CONFIG_SERIAL_8250_PCI is not set
- +CONFIG_SERIAL_8250_EXTENDED=y
- +CONFIG_SERIAL_8250_SHARE_IRQ=y
- +CONFIG_SERIAL_OF_PLATFORM=y
- +CONFIG_SERIAL_TEGRA=y
- +CONFIG_SERIAL_DEV_BUS=y
- +# CONFIG_HW_RANDOM_CAVIUM is not set
- +# CONFIG_DEVPORT is not set
- +CONFIG_I2C_CHARDEV=y
- +CONFIG_I2C_MUX=y
- +# CONFIG_I2C_HELPER_AUTO is not set
- +CONFIG_I2C_SMBUS=y
- +CONFIG_I2C_TEGRA=y
- +CONFIG_DEBUG_PINCTRL=y
- +CONFIG_PINCTRL_SINGLE=y
- +CONFIG_PINCTRL_MAX77620=y
- +CONFIG_GPIO_SYSFS=y
- +CONFIG_GPIO_MAX77620=y
- +CONFIG_POWER_RESET_GPIO=y
- +CONFIG_POWER_RESET_GPIO_RESTART=y
- +CONFIG_BATTERY_MAX17042=y
- +CONFIG_CHARGER_BQ24190=y
- +CONFIG_SENSORS_LM90=y
- +CONFIG_SENSORS_PWM_FAN=y
- +CONFIG_THERMAL=y
- +CONFIG_THERMAL_WRITABLE_TRIPS=y
- +CONFIG_THERMAL_GOV_USER_SPACE=y
- +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
- +CONFIG_CPU_THERMAL=y
- +CONFIG_CLOCK_THERMAL=y
- +CONFIG_MAX77620_THERMAL=y
- +CONFIG_TEGRA_SOCTHERM=y
- +CONFIG_MFD_MAX77620=y
- +CONFIG_REGULATOR=y
- +CONFIG_REGULATOR_DEBUG=y
- +CONFIG_REGULATOR_FIXED_VOLTAGE=y
- +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
- +CONFIG_REGULATOR_USERSPACE_CONSUMER=y
- +CONFIG_REGULATOR_MAX77620=y
- +CONFIG_REGULATOR_MAX8973=y
- +CONFIG_MEDIA_SUPPORT=y
- +CONFIG_MEDIA_CEC_SUPPORT=y
- +CONFIG_CEC_PLATFORM_DRIVERS=y
- +CONFIG_CEC_GPIO=y
- +CONFIG_VIDEO_TEGRA_HDMI_CEC=y
- +# CONFIG_TEGRA_HOST1X_FIREWALL is not set
- +CONFIG_DRM=y
- +CONFIG_DRM_DP_AUX_CHARDEV=y
- +CONFIG_DRM_I2C_NXP_TDA998X=y
- +CONFIG_DRM_NOUVEAU=y
- +CONFIG_DRM_TEGRA=y
- +CONFIG_DRM_TEGRA_DEBUG=y
- +CONFIG_DRM_TEGRA_STAGING=y
- +CONFIG_DRM_PANEL_SIMPLE=y
- +CONFIG_DRM_PANEL_JDI_LPM062M326A=y
- +CONFIG_DRM_TINYDRM=y
- +CONFIG_FB_MODE_HELPERS=y
- +CONFIG_FB_SIMPLE=y
- +CONFIG_LCD_PLATFORM=y
- +# CONFIG_BACKLIGHT_GENERIC is not set
- +CONFIG_BACKLIGHT_PWM=y
- +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
- +CONFIG_LOGO=y
- +# CONFIG_LOGO_LINUX_MONO is not set
- +# CONFIG_LOGO_LINUX_VGA16 is not set
- +CONFIG_SOUND=y
- +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
- +CONFIG_SND=y
- +CONFIG_SND_OSSEMUL=y
- +CONFIG_SND_MIXER_OSS=y
- +CONFIG_SND_PCM_OSS=y
- +CONFIG_SND_HRTIMER=y
- +CONFIG_SND_DYNAMIC_MINORS=y
- +CONFIG_SND_VERBOSE_PRINTK=y
- +CONFIG_SND_DEBUG=y
- +CONFIG_SND_SEQUENCER=y
- +CONFIG_SND_SEQ_DUMMY=y
- +CONFIG_SND_SEQUENCER_OSS=y
- +# CONFIG_SND_DRIVERS is not set
- +# CONFIG_SND_PCI is not set
- +CONFIG_SND_HDA_TEGRA=y
- +CONFIG_SND_HDA_HWDEP=y
- +CONFIG_SND_HDA_RECONFIG=y
- +CONFIG_SND_HDA_INPUT_BEEP=y
- +CONFIG_SND_HDA_CODEC_REALTEK=y
- +CONFIG_SND_HDA_CODEC_HDMI=y
- +CONFIG_SND_HDA_PREALLOC_SIZE=2048
- +# CONFIG_SND_USB is not set
- +CONFIG_SND_SOC=y
- +CONFIG_SND_SOC_TEGRA=y
- +CONFIG_SND_SOC_TEGRA20_AC97=y
- +CONFIG_SND_SOC_TEGRA20_I2S=y
- +CONFIG_SND_SOC_TEGRA30_I2S=y
- +CONFIG_SND_SOC_TEGRA_RT5640=y
- +CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
- +CONFIG_SND_SOC_TEGRA_ALC5632=y
- +CONFIG_SND_SOC_TEGRA_RT5677=y
- +CONFIG_SND_SOC_ALC5623=y
- +CONFIG_SND_SOC_RT5616=y
- +CONFIG_SND_SOC_RT5631=y
- +CONFIG_SND_SIMPLE_CARD=y
- +CONFIG_SND_SIMPLE_SCU_CARD=y
- +CONFIG_SND_AUDIO_GRAPH_CARD=y
- +CONFIG_SND_AUDIO_GRAPH_SCU_CARD=y
- +CONFIG_HID_BATTERY_STRENGTH=y
- +CONFIG_HIDRAW=y
- +CONFIG_UHID=y
- +# CONFIG_HID_A4TECH is not set
- +# CONFIG_HID_APPLE is not set
- +# CONFIG_HID_BELKIN is not set
- +# CONFIG_HID_CHERRY is not set
- +# CONFIG_HID_CHICONY is not set
- +# CONFIG_HID_CYPRESS is not set
- +# CONFIG_HID_EZKEY is not set
- +# CONFIG_HID_ITE is not set
- +# CONFIG_HID_KENSINGTON is not set
- +# CONFIG_HID_LOGITECH is not set
- +# CONFIG_HID_MICROSOFT is not set
- +# CONFIG_HID_MONTEREY is not set
- +CONFIG_HID_SONY=y
- +CONFIG_SONY_FF=y
- +CONFIG_HID_WIIMOTE=y
- +CONFIG_USB_HIDDEV=y
- +CONFIG_USB=y
- +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
- +CONFIG_USB_OTG=y
- +CONFIG_USB_OTG_FSM=y
- +CONFIG_USB_MON=y
- +CONFIG_USB_XHCI_HCD=y
- +CONFIG_USB_XHCI_PLATFORM=y
- +CONFIG_USB_XHCI_TEGRA=y
- +CONFIG_USB_EHCI_HCD=y
- +CONFIG_USB_EHCI_TEGRA=y
- +CONFIG_USB_EHCI_HCD_PLATFORM=y
- +CONFIG_USB_STORAGE=y
- +CONFIG_USB_STORAGE_CYPRESS_ATACB=y
- +CONFIG_USB_UAS=y
- +CONFIG_USB_MUSB_HDRC=y
- +CONFIG_USB_SERIAL=y
- +CONFIG_USB_SERIAL_GENERIC=y
- +CONFIG_USB_SERIAL_SIMPLE=y
- +CONFIG_USB_SERIAL_CH341=y
- +CONFIG_USB_SERIAL_CP210X=y
- +CONFIG_USB_SERIAL_FTDI_SIO=y
- +CONFIG_USB_SERIAL_PL2303=y
- +CONFIG_USB_GADGET=y
- +CONFIG_U_SERIAL_CONSOLE=y
- +CONFIG_USB_CONFIGFS=y
- +CONFIG_USB_CONFIGFS_SERIAL=y
- +CONFIG_USB_CONFIGFS_ECM=y
- +CONFIG_USB_CONFIGFS_ECM_SUBSET=y
- +CONFIG_USB_CONFIGFS_EEM=y
- +CONFIG_USB_CONFIGFS_MASS_STORAGE=y
- +CONFIG_TYPEC=y
- +CONFIG_USB_ULPI_BUS=y
- +CONFIG_MMC=y
- +CONFIG_MMC_SDHCI=y
- +CONFIG_MMC_SDHCI_PLTFM=y
- +CONFIG_MMC_SDHCI_TEGRA=y
- +CONFIG_NEW_LEDS=y
- +CONFIG_LEDS_CLASS=y
- +CONFIG_LEDS_TRIGGER_TIMER=y
- +CONFIG_LEDS_TRIGGER_HEARTBEAT=y
- +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
- +CONFIG_LEDS_TRIGGER_TRANSIENT=y
- +CONFIG_RTC_CLASS=y
- +# CONFIG_RTC_NVMEM is not set
- +CONFIG_RTC_DRV_MAX77686=y
- +CONFIG_RTC_DRV_TEGRA=y
- +CONFIG_DMADEVICES=y
- +CONFIG_TEGRA20_APB_DMA=y
- +CONFIG_TEGRA210_ADMA=y
- +CONFIG_UIO=y
- +CONFIG_UIO_PDRV_GENIRQ=y
- +# CONFIG_VIRTIO_MENU is not set
- +CONFIG_STAGING=y
- +# CONFIG_COMMON_CLK_XGENE is not set
- +CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y
- +CONFIG_TEGRA_IOMMU_SMMU=y
- +CONFIG_ARM_SMMU=y
- +CONFIG_ARM_SMMU_V3=y
- +CONFIG_ARCH_TEGRA_210_SOC=y
- +CONFIG_PM_DEVFREQ=y
- +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
- +CONFIG_DEVFREQ_GOV_PERFORMANCE=y
- +CONFIG_DEVFREQ_GOV_POWERSAVE=y
- +CONFIG_DEVFREQ_GOV_USERSPACE=y
- +CONFIG_DEVFREQ_GOV_PASSIVE=y
- +CONFIG_MEMORY=y
- +CONFIG_IIO=y
- +CONFIG_BH1730=y
- +CONFIG_PWM=y
- +CONFIG_PWM_TEGRA=y
- +CONFIG_PHY_TEGRA_XUSB=y
- +CONFIG_POWERCAP=y
- +CONFIG_EXT4_FS=y
- +CONFIG_EXT4_FS_POSIX_ACL=y
- +CONFIG_EXT4_FS_SECURITY=y
- +CONFIG_EXT4_ENCRYPTION=y
- +CONFIG_FANOTIFY=y
- +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
- +CONFIG_AUTOFS4_FS=y
- +CONFIG_FUSE_FS=y
- +CONFIG_CUSE=y
- +CONFIG_OVERLAY_FS=y
- +CONFIG_OVERLAY_FS_INDEX=y
- +CONFIG_FSCACHE=y
- +CONFIG_CACHEFILES=y
- +CONFIG_ISO9660_FS=y
- +CONFIG_JOLIET=y
- +CONFIG_ZISOFS=y
- +CONFIG_UDF_FS=y
- +CONFIG_MSDOS_FS=y
- +CONFIG_VFAT_FS=y
- +CONFIG_FAT_DEFAULT_CODEPAGE=850
- +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15"
- +CONFIG_FAT_DEFAULT_UTF8=y
- +CONFIG_NTFS_FS=y
- +CONFIG_TMPFS=y
- +CONFIG_TMPFS_POSIX_ACL=y
- +CONFIG_HUGETLBFS=y
- +CONFIG_SQUASHFS=y
- +CONFIG_SQUASHFS_XATTR=y
- +CONFIG_SQUASHFS_LZ4=y
- +CONFIG_SQUASHFS_LZO=y
- +CONFIG_SQUASHFS_XZ=y
- +CONFIG_SQUASHFS_ZSTD=y
- +CONFIG_NFS_FS=y
- +CONFIG_NFS_V4=y
- +# CONFIG_RPCSEC_GSS_KRB5 is not set
- +CONFIG_CIFS=y
- +CONFIG_CIFS_XATTR=y
- +# CONFIG_CIFS_DEBUG is not set
- +CONFIG_NLS_DEFAULT="iso8859-15"
- +CONFIG_NLS_CODEPAGE_437=y
- +CONFIG_NLS_CODEPAGE_737=y
- +CONFIG_NLS_CODEPAGE_775=y
- +CONFIG_NLS_CODEPAGE_850=y
- +CONFIG_NLS_CODEPAGE_852=y
- +CONFIG_NLS_CODEPAGE_855=y
- +CONFIG_NLS_CODEPAGE_857=y
- +CONFIG_NLS_CODEPAGE_860=y
- +CONFIG_NLS_CODEPAGE_861=y
- +CONFIG_NLS_CODEPAGE_862=y
- +CONFIG_NLS_CODEPAGE_863=y
- +CONFIG_NLS_CODEPAGE_864=y
- +CONFIG_NLS_CODEPAGE_865=y
- +CONFIG_NLS_CODEPAGE_866=y
- +CONFIG_NLS_CODEPAGE_869=y
- +CONFIG_NLS_CODEPAGE_936=y
- +CONFIG_NLS_CODEPAGE_950=y
- +CONFIG_NLS_CODEPAGE_932=y
- +CONFIG_NLS_CODEPAGE_949=y
- +CONFIG_NLS_CODEPAGE_874=y
- +CONFIG_NLS_ISO8859_8=y
- +CONFIG_NLS_CODEPAGE_1250=y
- +CONFIG_NLS_CODEPAGE_1251=y
- +CONFIG_NLS_ASCII=y
- +CONFIG_NLS_ISO8859_1=y
- +CONFIG_NLS_ISO8859_2=y
- +CONFIG_NLS_ISO8859_3=y
- +CONFIG_NLS_ISO8859_4=y
- +CONFIG_NLS_ISO8859_5=y
- +CONFIG_NLS_ISO8859_6=y
- +CONFIG_NLS_ISO8859_7=y
- +CONFIG_NLS_ISO8859_9=y
- +CONFIG_NLS_ISO8859_13=y
- +CONFIG_NLS_ISO8859_14=y
- +CONFIG_NLS_ISO8859_15=y
- +CONFIG_NLS_KOI8_R=y
- +CONFIG_NLS_KOI8_U=y
- +CONFIG_NLS_UTF8=y
- +CONFIG_DLM=y
- +CONFIG_VIRTUALIZATION=y
- +CONFIG_KVM=y
- +CONFIG_VHOST_NET=y
- +CONFIG_PRINTK_TIME=y
- +CONFIG_DYNAMIC_DEBUG=y
- +CONFIG_UNUSED_SYMBOLS=y
- +CONFIG_DEBUG_FS=y
- +CONFIG_MAGIC_SYSRQ=y
- +CONFIG_DEBUG_KERNEL=y
- +CONFIG_PAGE_POISONING=y
- +CONFIG_PAGE_POISONING_NO_SANITY=y
- +CONFIG_PAGE_POISONING_ZERO=y
- +CONFIG_DEBUG_RODATA_TEST=y
- +CONFIG_SOFTLOCKUP_DETECTOR=y
- +CONFIG_PANIC_TIMEOUT=-1
- +# CONFIG_SCHED_DEBUG is not set
- +CONFIG_SCHED_STACK_END_CHECK=y
- +# CONFIG_DEBUG_PREEMPT is not set
- +CONFIG_STACKTRACE=y
- +CONFIG_DEBUG_SG=y
- +CONFIG_DEBUG_NOTIFIERS=y
- +CONFIG_DEBUG_CREDENTIALS=y
- +CONFIG_RCU_CPU_STALL_TIMEOUT=60
- +# CONFIG_FTRACE is not set
- +CONFIG_BUG_ON_DATA_CORRUPTION=y
- +# CONFIG_STRICT_DEVMEM is not set
- +CONFIG_DEBUG_WX=y
- +CONFIG_SECURITY=y
- +CONFIG_HARDENED_USERCOPY=y
- +CONFIG_FORTIFY_SOURCE=y
- +CONFIG_SECURITY_YAMA=y
- +CONFIG_INTEGRITY_SIGNATURE=y
- +CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
- +CONFIG_CRYPTO_PCRYPT=y
- +CONFIG_CRYPTO_MCRYPTD=y
- +CONFIG_CRYPTO_CHACHA20POLY1305=y
- +CONFIG_CRYPTO_LRW=y
- +CONFIG_CRYPTO_PCBC=y
- +CONFIG_CRYPTO_CRC32=y
- +CONFIG_CRYPTO_SHA512=y
- +CONFIG_CRYPTO_AES_TI=y
- +CONFIG_CRYPTO_BLOWFISH=y
- +CONFIG_CRYPTO_CAMELLIA=y
- +CONFIG_CRYPTO_CAST5=y
- +CONFIG_CRYPTO_CAST6=y
- +CONFIG_CRYPTO_SERPENT=y
- +CONFIG_CRYPTO_TEA=y
- +CONFIG_CRYPTO_LZO=y
- +CONFIG_CRYPTO_ANSI_CPRNG=y
- +CONFIG_CRYPTO_DRBG_HASH=y
- +CONFIG_CRYPTO_DRBG_CTR=y
- +CONFIG_CRYPTO_USER_API_HASH=y
- +CONFIG_CRYPTO_USER_API_SKCIPHER=y
- +CONFIG_CRYPTO_USER_API_AEAD=y
- +# CONFIG_CRYPTO_HW is not set
- +CONFIG_ARM64_CRYPTO=y
- +CONFIG_CRYPTO_SHA512_ARM64=y
- +CONFIG_CRYPTO_SHA1_ARM64_CE=y
- +CONFIG_CRYPTO_SHA2_ARM64_CE=y
- +CONFIG_CRYPTO_GHASH_ARM64_CE=y
- +CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y
- +CONFIG_CRYPTO_CRC32_ARM64_CE=y
- +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
- +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
- +CONFIG_CRYPTO_CHACHA20_NEON=y
- +CONFIG_CRYPTO_AES_ARM64_BS=y
- +CONFIG_CRC_CCITT=y
- +CONFIG_CRC7=y
- +CONFIG_FONTS=y
- +CONFIG_CRC8=y
- +CONFIG_INPUT_JOYSTICK=y
- +CONFIG_JOYSTICK_JOYCON=y
- diff --git a/arch/arm64/kernel/smccc-call.S b/arch/arm64/kernel/smccc-call.S
- index 6252234..6510c70 100644
- --- a/arch/arm64/kernel/smccc-call.S
- +++ b/arch/arm64/kernel/smccc-call.S
- @@ -17,7 +17,7 @@
- .macro SMCCC instr
- .cfi_startproc
- - \instr #0
- + \instr #1
- ldr x4, [sp]
- stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
- stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
- diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
- index 7ddacae..57902ab 100644
- --- a/drivers/clk/tegra/Kconfig
- +++ b/drivers/clk/tegra/Kconfig
- @@ -5,3 +5,8 @@ config TEGRA_CLK_EMC
- config CLK_TEGRA_BPMP
- def_bool y
- depends on TEGRA_BPMP
- +
- +config TEGRA_CLK_DFLL
- + depends on (ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC)
- + select PM_OPP
- + def_bool y
- diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
- index b716923..fc7f4b4 100644
- --- a/drivers/clk/tegra/Makefile
- +++ b/drivers/clk/tegra/Makefile
- @@ -19,7 +19,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
- obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
- obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
- obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
- -obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124-dfll-fcpu.o
- +obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
- obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
- obj-y += cvb.o
- obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
- diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
- index 0a7deee..890829c 100644
- --- a/drivers/clk/tegra/clk-dfll.c
- +++ b/drivers/clk/tegra/clk-dfll.c
- @@ -51,6 +51,7 @@
- #include <linux/pm_runtime.h>
- #include <linux/regmap.h>
- #include <linux/regulator/consumer.h>
- +#include <linux/pinctrl/consumer.h>
- #include <linux/reset.h>
- #include <linux/seq_file.h>
- @@ -243,6 +244,12 @@ enum dfll_tune_range {
- DFLL_TUNE_LOW = 1,
- };
- +
- +enum tegra_dfll_pmu_if {
- + TEGRA_DFLL_PMU_I2C = 0,
- + TEGRA_DFLL_PMU_PWM = 1,
- +};
- +
- /**
- * struct dfll_rate_req - target DFLL rate request data
- * @rate: target frequency, after the postscaling
- @@ -294,16 +301,25 @@ struct tegra_dfll {
- u32 ci;
- u32 cg;
- bool cg_scale;
- + u32 reg_init_uV;
- /* I2C interface parameters */
- u32 i2c_fs_rate;
- u32 i2c_reg;
- u32 i2c_slave_addr;
- - /* i2c_lut array entries are regulator framework selectors */
- - unsigned i2c_lut[MAX_DFLL_VOLTAGES];
- - int i2c_lut_size;
- - u8 lut_min, lut_max, lut_safe;
- + /* lut array entries are regulator framework selectors or PWM values*/
- + unsigned int i2c_lut[MAX_DFLL_VOLTAGES];
- + unsigned int lut_uv[MAX_DFLL_VOLTAGES];
- + int lut_size;
- + u8 lut_bottom, lut_min, lut_max, lut_safe;
- +
- + /* PWM interface */
- + enum tegra_dfll_pmu_if pmu_if;
- + unsigned long pwm_rate;
- + struct pinctrl *pwm_pin;
- + struct pinctrl_state *pwm_enable_state;
- + struct pinctrl_state *pwm_disable_state;
- };
- #define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
- @@ -489,6 +505,36 @@ static void dfll_set_mode(struct tegra_dfll *td,
- dfll_wmb(td);
- }
- +/*
- + * DVCO rate control
- + */
- +
- +static unsigned long get_dvco_rate_below(struct tegra_dfll *td, u8 out_min)
- +{
- + struct dev_pm_opp *opp;
- + unsigned long rate, prev_rate;
- + int uv, min_uv;
- +
- + min_uv = td->lut_uv[out_min];
- + for (rate = 0, prev_rate = 0; ; rate++) {
- + rcu_read_lock();
- + opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
- + if (IS_ERR(opp)) {
- + rcu_read_unlock();
- + break;
- + }
- + uv = dev_pm_opp_get_voltage(opp);
- + rcu_read_unlock();
- +
- + if (uv && uv > min_uv)
- + return prev_rate;
- +
- + prev_rate = rate;
- + }
- +
- + return prev_rate;
- +}
- +
- /*
- * DFLL-to-I2C controller interface
- */
- @@ -518,6 +564,119 @@ static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
- return 0;
- }
- +
- +/*
- + * DFLL-to-PWM controller interface
- + */
- +
- +/**
- + * dfll_pwm_set_output_enabled - enable/disable PWM voltage requests
- + * @td: DFLL instance
- + * @enable: whether to enable or disable the PWM voltage requests
- + *
- + * Set the master enable control for PWM control value updates. If disabled,
- + * then the PWM signal is not driven. Also configure the PWM output pad
- + * to the appropriate state.
- + */
- +static int dfll_pwm_set_output_enabled(struct tegra_dfll *td, bool enable)
- +{
- + int ret;
- + u32 val, div;
- +
- + if (enable) {
- + ret = pinctrl_select_state(td->pwm_pin, td->pwm_enable_state);
- + if (ret < 0) {
- + dev_err(td->dev, "setting enable state failed\n");
- + return ret;
- + }
- + val = dfll_readl(td, DFLL_OUTPUT_CFG);
- + val &= ~DFLL_OUTPUT_CFG_PWM_DIV_MASK;
- + div = DIV_ROUND_UP(td->ref_rate, td->pwm_rate);
- + val |= (div << DFLL_OUTPUT_CFG_PWM_DIV_SHIFT)
- + & DFLL_OUTPUT_CFG_PWM_DIV_MASK;
- + dfll_writel(td, val, DFLL_OUTPUT_CFG);
- + dfll_wmb(td);
- +
- + val |= DFLL_OUTPUT_CFG_PWM_ENABLE;
- + dfll_writel(td, val, DFLL_OUTPUT_CFG);
- + dfll_wmb(td);
- + } else {
- + ret = pinctrl_select_state(td->pwm_pin, td->pwm_disable_state);
- + if (ret < 0)
- + dev_warn(td->dev, "setting disable state failed\n");
- +
- + val = dfll_readl(td, DFLL_OUTPUT_CFG);
- + val &= ~DFLL_OUTPUT_CFG_PWM_ENABLE;
- + dfll_writel(td, val, DFLL_OUTPUT_CFG);
- + dfll_wmb(td);
- + }
- +
- + return 0;
- +}
- +/**
- + * dfll_set_force_output_value - set fixed value for force output
- + * @td: DFLL instance
- + * @out_val: value to force output
- + *
- + * Set the fixed value for force output, DFLL will output this value when
- + * force output is enabled.
- + */
- +static u32 dfll_set_force_output_value(struct tegra_dfll *td, u8 out_val)
- +{
- + u32 val = dfll_readl(td, DFLL_OUTPUT_FORCE);
- +
- + val &= ~OUT_MASK;
- + val = (val & DFLL_OUTPUT_FORCE_ENABLE) | (out_val & OUT_MASK);
- + dfll_writel(td, val, DFLL_OUTPUT_FORCE);
- + dfll_wmb(td);
- +
- + return dfll_readl(td, DFLL_OUTPUT_FORCE);
- +}
- +
- +/**
- + * dfll_set_force_output_enabled - enable/disable force output
- + * @td: DFLL instance
- + * @enable: whether to enable or disable the force output
- + *
- + * Set the enable control for fouce output with fixed value.
- + */
- +static void dfll_set_force_output_enabled(struct tegra_dfll *td, bool enable)
- +{
- + u32 val = dfll_readl(td, DFLL_OUTPUT_FORCE);
- +
- + if (enable)
- + val |= DFLL_OUTPUT_FORCE_ENABLE;
- + else
- + val &= ~DFLL_OUTPUT_FORCE_ENABLE;
- +
- + dfll_writel(td, val, DFLL_OUTPUT_FORCE);
- + dfll_wmb(td);
- +}
- +
- +/**
- + * dfll_i2c_set_output_enabled - enable/disable I2C PMIC voltage requests
- + * @td: DFLL instance
- + * @enable: whether to enable or disable the I2C voltage requests
- + *
- + * Set the master enable control for I2C control value updates. If disabled,
- + * then I2C control messages are inhibited, regardless of the DFLL mode.
- + */
- +static int dfll_force_output(struct tegra_dfll *td, unsigned int out_sel)
- +{
- + u32 val;
- +
- + if (out_sel > OUT_MASK)
- + return -EINVAL;
- +
- + val = dfll_set_force_output_value(td, out_sel);
- + if ((td->mode < DFLL_CLOSED_LOOP) &&
- + !(val & DFLL_OUTPUT_FORCE_ENABLE)) {
- + dfll_set_force_output_enabled(td, true);
- + }
- +
- + return 0;
- +}
- +
- /**
- * dfll_load_lut - load the voltage lookup table
- * @td: struct tegra_dfll *
- @@ -531,10 +690,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;
- @@ -594,24 +753,54 @@ static void dfll_init_out_if(struct tegra_dfll *td)
- {
- u32 val;
- - td->lut_min = 0;
- - td->lut_max = td->i2c_lut_size - 1;
- - td->lut_safe = td->lut_min + 1;
- -
- - dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG);
- - val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
- - (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
- - (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
- - dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
- - dfll_i2c_wmb(td);
- -
- - dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
- - dfll_i2c_writel(td, 0, DFLL_INTR_EN);
- - dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
- - DFLL_INTR_STS);
- -
- - dfll_load_i2c_lut(td);
- - dfll_init_i2c_if(td);
- + td->lut_min = td->lut_bottom;
- + td->lut_max = td->lut_size - 1;
- + td->lut_safe = td->lut_min + (td->lut_min < td->lut_max ? 1 : 0);
- +
- + if (td->pmu_if == TEGRA_DFLL_PMU_PWM) {
- + int vinit = td->reg_init_uV;
- + int vstep = td->soc->alignment.step_uv;
- + int vmin = td->lut_uv[0];
- +
- + /* clear DFLL_OUTPUT_CFG before setting new value */
- + dfll_writel(td, 0, DFLL_OUTPUT_CFG);
- + dfll_wmb(td);
- +
- + val = dfll_readl(td, DFLL_OUTPUT_CFG);
- + val |= (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
- + (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
- + (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
- + dfll_writel(td, val, DFLL_OUTPUT_CFG);
- + dfll_wmb(td);
- +
- + dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
- + dfll_i2c_writel(td, 0, DFLL_INTR_EN);
- + dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
- + DFLL_INTR_STS);
- +
- + /* set initial voltage */
- + if ((vinit >= vmin) && vstep) {
- + unsigned int vsel;
- +
- + vsel = DIV_ROUND_UP((vinit - vmin), vstep);
- + dfll_force_output(td, vsel);
- + }
- + } else {
- + dfll_i2c_writel(td, 0, DFLL_OUTPUT_CFG);
- + val = (td->lut_safe << DFLL_OUTPUT_CFG_SAFE_SHIFT) |
- + (td->lut_max << DFLL_OUTPUT_CFG_MAX_SHIFT) |
- + (td->lut_min << DFLL_OUTPUT_CFG_MIN_SHIFT);
- + dfll_i2c_writel(td, val, DFLL_OUTPUT_CFG);
- + dfll_i2c_wmb(td);
- +
- + dfll_writel(td, 0, DFLL_OUTPUT_FORCE);
- + dfll_i2c_writel(td, 0, DFLL_INTR_EN);
- + dfll_i2c_writel(td, DFLL_INTR_MAX_MASK | DFLL_INTR_MIN_MASK,
- + DFLL_INTR_STS);
- +
- + dfll_load_i2c_lut(td);
- + dfll_init_i2c_if(td);
- + }
- }
- /*
- @@ -619,11 +808,11 @@ static void dfll_init_out_if(struct tegra_dfll *td)
- */
- /**
- - * find_lut_index_for_rate - determine I2C LUT index for given DFLL rate
- + * find_lut_index_for_rate - determine LUT index for given DFLL rate
- * @td: DFLL instance
- * @rate: clock rate
- *
- - * Determines the index of a I2C LUT entry for a voltage that approximately
- + * Determines the index of a LUT entry for a voltage that approximately
- * produces the given DFLL clock rate. This is used when forcing a value
- * to the integrator during rate changes. Returns -ENOENT if a suitable
- * LUT index is not found.
- @@ -637,11 +826,11 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
- if (IS_ERR(opp))
- return PTR_ERR(opp);
- - uv = dev_pm_opp_get_voltage(opp);
- + uv = dev_pm_opp_get_voltage(opp) / td->soc->alignment.step_uv;
- dev_pm_opp_put(opp);
- - for (i = 0; i < td->i2c_lut_size; i++) {
- - if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv)
- + for (i = td->lut_bottom; i < td->lut_size; i++) {
- + if ((td->lut_uv[i] / td->soc->alignment.step_uv) >= uv)
- return i;
- }
- @@ -863,9 +1052,14 @@ static int dfll_lock(struct tegra_dfll *td)
- return -EINVAL;
- }
- - dfll_i2c_set_output_enabled(td, true);
- + if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
- + dfll_pwm_set_output_enabled(td, true);
- + else
- + dfll_i2c_set_output_enabled(td, true);
- +
- dfll_set_mode(td, DFLL_CLOSED_LOOP);
- dfll_set_frequency_request(td, req);
- + dfll_set_force_output_enabled(td, false);
- return 0;
- default:
- @@ -889,7 +1083,10 @@ static int dfll_unlock(struct tegra_dfll *td)
- case DFLL_CLOSED_LOOP:
- dfll_set_open_loop_config(td);
- dfll_set_mode(td, DFLL_OPEN_LOOP);
- - dfll_i2c_set_output_enabled(td, false);
- + if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
- + dfll_pwm_set_output_enabled(td, false);
- + else
- + dfll_i2c_set_output_enabled(td, false);
- return 0;
- case DFLL_OPEN_LOOP:
- @@ -1171,15 +1368,17 @@ static int attr_registers_show(struct seq_file *s, void *data)
- seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
- dfll_i2c_readl(td, offs));
- - seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
- - offs = DFLL_I2C_CLK_DIVISOR;
- - seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
- - __raw_readl(td->i2c_controller_base + offs));
- -
- - seq_puts(s, "\nLUT:\n");
- - for (offs = 0; offs < 4 * MAX_DFLL_VOLTAGES; offs += 4)
- + if (td->pmu_if == TEGRA_DFLL_PMU_I2C) {
- + seq_puts(s, "\nINTEGRATED I2C CONTROLLER REGISTERS:\n");
- + offs = DFLL_I2C_CLK_DIVISOR;
- seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
- - __raw_readl(td->lut_base + offs));
- + __raw_readl(td->i2c_controller_base + offs));
- +
- + seq_puts(s, "\nLUT:\n");
- + for (offs = 0; offs < 4 * MAX_DFLL_VOLTAGES; offs += 4)
- + seq_printf(s, "[0x%02x] = 0x%08x\n", offs,
- + __raw_readl(td->lut_base + offs));
- + }
- return 0;
- }
- @@ -1288,6 +1487,9 @@ static int dfll_init_clks(struct tegra_dfll *td)
- return PTR_ERR(td->soc_clk);
- }
- + if (td->pmu_if != TEGRA_DFLL_PMU_I2C)
- + return 0;
- +
- td->i2c_clk = devm_clk_get(td->dev, "i2c");
- if (IS_ERR(td->i2c_clk)) {
- dev_err(td->dev, "missing i2c clock\n");
- @@ -1377,15 +1579,17 @@ di_err1:
- */
- static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
- {
- - int i, n_voltages, reg_uV;
- + int i, n_voltages, reg_mult, align_mult;
- + align_mult = uV / td->soc->alignment.step_uv;
- n_voltages = regulator_count_voltages(td->vdd_reg);
- for (i = 0; i < n_voltages; i++) {
- - reg_uV = regulator_list_voltage(td->vdd_reg, i);
- - if (reg_uV < 0)
- + reg_mult = regulator_list_voltage(td->vdd_reg, i) /
- + td->soc->alignment.step_uv;
- + if (reg_mult < 0)
- break;
- - if (uV == reg_uV)
- + if (align_mult == reg_mult)
- return i;
- }
- @@ -1399,15 +1603,17 @@ static int find_vdd_map_entry_exact(struct tegra_dfll *td, int uV)
- * */
- static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
- {
- - int i, n_voltages, reg_uV;
- + int i, n_voltages, reg_mult, align_mult;
- + align_mult = uV / td->soc->alignment.step_uv;
- n_voltages = regulator_count_voltages(td->vdd_reg);
- for (i = 0; i < n_voltages; i++) {
- - reg_uV = regulator_list_voltage(td->vdd_reg, i);
- - if (reg_uV < 0)
- + reg_mult = regulator_list_voltage(td->vdd_reg, i) /
- + td->soc->alignment.step_uv;
- + if (reg_mult < 0)
- break;
- - if (uV <= reg_uV)
- + if (align_mult <= reg_mult)
- return i;
- }
- @@ -1415,6 +1621,52 @@ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
- return -EINVAL;
- }
- +/*
- + * Look-up table in h/w is ignored when PWM is used as DFLL interface to PMIC.
- + * In this case closed loop output is controlling duty cycle directly. The s/w
- + * look-up that maps PWM duty cycle to voltage is still built by this function.
- + */
- +static int dfll_build_lut_pwm(struct tegra_dfll *td, int v_max)
- +{
- + int i, reg_volt;
- + unsigned long rate;
- + u8 lut_bottom = MAX_DFLL_VOLTAGES;
- + int v_min = td->soc->cvb->min_millivolts * 1000;
- +
- + for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
- + reg_volt = td->lut_uv[i];
- +
- + /* since opp voltage is exact mv */
- + reg_volt = (reg_volt / 1000) * 1000;
- + if (reg_volt > v_max)
- + break;
- +
- + if ((lut_bottom == MAX_DFLL_VOLTAGES) && (reg_volt >= v_min))
- + lut_bottom = i;
- + }
- +
- + /* determine voltage boundaries */
- + td->lut_size = i;
- + if ((lut_bottom == MAX_DFLL_VOLTAGES) ||
- + (lut_bottom + 1 >= td->lut_size)) {
- + dev_err(td->dev, "no voltage above DFLL minimum %d mV\n",
- + td->soc->cvb->min_millivolts);
- + return -EINVAL;
- + }
- + td->lut_bottom = lut_bottom;
- +
- + /* determine rate boundaries */
- + rate = get_dvco_rate_below(td, td->lut_bottom);
- + if (!rate) {
- + dev_err(td->dev, "no opp below DFLL minimum voltage %d mV\n",
- + td->soc->cvb->min_millivolts);
- + return -EINVAL;
- + }
- + td->dvco_rate_min = rate;
- +
- + return 0;
- +}
- +
- /**
- * dfll_build_i2c_lut - build the I2C voltage register lookup table
- * @td: DFLL instance
- @@ -1427,10 +1679,10 @@ static int find_vdd_map_entry_min(struct tegra_dfll *td, int uV)
- *
- * On success, fills in td->i2c_lut and returns 0, or -err on failure.
- */
- -static int dfll_build_i2c_lut(struct tegra_dfll *td)
- +static int dfll_build_i2c_lut(struct tegra_dfll *td, int v_max)
- {
- int ret = -EINVAL;
- - int j, v, v_max, v_opp;
- + int j, v, v_opp;
- int selector;
- unsigned long rate;
- struct dev_pm_opp *opp;
- @@ -1450,8 +1702,10 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
- if (lut < 0)
- goto out;
- td->i2c_lut[0] = lut;
- + td->lut_bottom = 0;
- for (j = 1, rate = 0; ; rate++) {
- +
- opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
- if (IS_ERR(opp))
- break;
- @@ -1484,18 +1738,47 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
- if (v >= v_max)
- break;
- }
- - td->i2c_lut_size = j;
- + td->lut_size = j;
- if (!td->dvco_rate_min)
- dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
- td->soc->cvb->min_millivolts);
- - else
- + else {
- ret = 0;
- + for (j = 0; j < td->lut_size; j++)
- + td->lut_uv[j] =
- + regulator_list_voltage(td->vdd_reg,
- + td->i2c_lut[j]);
- + }
- out:
- return ret;
- }
- +static int dfll_build_lut(struct tegra_dfll *td)
- +{
- + unsigned long rate;
- + struct dev_pm_opp *opp;
- + int v_max;
- +
- + rcu_read_lock();
- +
- + rate = ULONG_MAX;
- + opp = dev_pm_opp_find_freq_floor(td->soc->dev, &rate);
- + if (IS_ERR(opp)) {
- + dev_err(td->dev, "couldn't get vmax opp, empty opp table?\n");
- + return -EINVAL;
- + }
- + v_max = dev_pm_opp_get_voltage(opp);
- +
- + rcu_read_unlock();
- +
- + if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
- + return dfll_build_lut_pwm(td, v_max);
- + else
- + return dfll_build_i2c_lut(td, v_max);
- +}
- +
- /**
- * read_dt_param - helper function for reading required parameters from the DT
- * @td: DFLL instance
- @@ -1554,11 +1837,54 @@ static int dfll_fetch_i2c_params(struct tegra_dfll *td)
- }
- td->i2c_reg = vsel_reg;
- - ret = dfll_build_i2c_lut(td);
- - if (ret) {
- - dev_err(td->dev, "couldn't build I2C LUT\n");
- + return 0;
- +}
- +
- +static int dfll_fetch_pwm_params(struct tegra_dfll *td)
- +{
- + int ret, i;
- + u32 pwm_period;
- +
- + if (!td->soc->alignment.step_uv || !td->soc->alignment.offset_uv) {
- + dev_err(td->dev, "Missing step or alignment info for PWM regulator");
- + return -EINVAL;
- + }
- + for (i = 0; i < MAX_DFLL_VOLTAGES; i++)
- + td->lut_uv[i] = td->soc->alignment.offset_uv +
- + i * td->soc->alignment.step_uv;
- +
- + ret = read_dt_param(td, "nvidia,init-uv", &td->reg_init_uV);
- + if (!ret) {
- + dev_err(td->dev, "couldn't get initialized voltage\n");
- + return ret;
- + }
- +
- + ret = read_dt_param(td, "nvidia,pwm-period", &pwm_period);
- + if (!ret) {
- + dev_err(td->dev, "couldn't get PWM period\n");
- return ret;
- }
- + td->pwm_rate = (NSEC_PER_SEC / pwm_period) * (MAX_DFLL_VOLTAGES - 1);
- +
- + td->pwm_pin = devm_pinctrl_get(td->dev);
- + if (IS_ERR(td->pwm_pin)) {
- + dev_err(td->dev, "DT: missing pinctrl device\n");
- + return PTR_ERR(td->pwm_pin);
- + }
- +
- + td->pwm_enable_state = pinctrl_lookup_state(td->pwm_pin,
- + "dvfs_pwm_enable");
- + if (IS_ERR(td->pwm_enable_state)) {
- + dev_err(td->dev, "DT: missing pwm enabled state\n");
- + return PTR_ERR(td->pwm_enable_state);
- + }
- +
- + td->pwm_disable_state = pinctrl_lookup_state(td->pwm_pin,
- + "dvfs_pwm_disable");
- + if (IS_ERR(td->pwm_disable_state)) {
- + dev_err(td->dev, "DT: missing pwm disabled state\n");
- + return PTR_ERR(td->pwm_disable_state);
- + }
- return 0;
- }
- @@ -1625,12 +1951,6 @@ int tegra_dfll_register(struct platform_device *pdev,
- td->soc = soc;
- - td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
- - if (IS_ERR(td->vdd_reg)) {
- - dev_err(td->dev, "couldn't get vdd_cpu regulator\n");
- - return PTR_ERR(td->vdd_reg);
- - }
- -
- td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
- if (IS_ERR(td->dvco_rst)) {
- dev_err(td->dev, "couldn't get dvco reset\n");
- @@ -1643,10 +1963,27 @@ int tegra_dfll_register(struct platform_device *pdev,
- return ret;
- }
- - ret = dfll_fetch_i2c_params(td);
- + if (of_property_read_bool(td->dev->of_node, "nvidia,pwm-to-pmic")) {
- + td->pmu_if = TEGRA_DFLL_PMU_PWM;
- + ret = dfll_fetch_pwm_params(td);
- + } else {
- + td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
- + if (IS_ERR(td->vdd_reg)) {
- + dev_err(td->dev, "couldn't get vdd_cpu regulator\n");
- + return PTR_ERR(td->vdd_reg);
- + }
- + td->pmu_if = TEGRA_DFLL_PMU_I2C;
- + ret = dfll_fetch_i2c_params(td);
- + }
- if (ret)
- return ret;
- + ret = dfll_build_lut(td);
- + if (ret) {
- + dev_err(td->dev, "couldn't build LUT\n");
- + return ret;
- + }
- +
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(td->dev, "no control register resource\n");
- diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
- index 83352c8..e7cbc5b 100644
- --- a/drivers/clk/tegra/clk-dfll.h
- +++ b/drivers/clk/tegra/clk-dfll.h
- @@ -21,6 +21,7 @@
- #include <linux/platform_device.h>
- #include <linux/reset.h>
- #include <linux/types.h>
- +#include "cvb.h"
- /**
- * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
- @@ -35,6 +36,7 @@ struct tegra_dfll_soc_data {
- struct device *dev;
- unsigned long max_freq;
- const struct cvb_table *cvb;
- + struct rail_alignment alignment;
- void (*init_clock_trimmers)(void);
- void (*set_clock_trimmers_high)(void);
- diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
- index 269d359..9d413e4 100644
- --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
- +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
- @@ -21,15 +21,24 @@
- #include <linux/err.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- +#include <linux/of_device.h>
- #include <linux/platform_device.h>
- +#include <linux/regulator/consumer.h>
- #include <soc/tegra/fuse.h>
- #include "clk.h"
- #include "clk-dfll.h"
- #include "cvb.h"
- +struct dfll_fcpu_data {
- + const unsigned long *cpu_max_freq_table;
- + unsigned int cpu_max_freq_table_size;
- + const struct cvb_table *cpu_cvb_tables;
- + unsigned int cpu_cvb_tables_size;
- +};
- +
- /* Maximum CPU frequency, indexed by CPU speedo id */
- -static const unsigned long cpu_max_freq_table[] = {
- +static const unsigned long tegra124_cpu_max_freq_table[] = {
- [0] = 2014500000UL,
- [1] = 2320500000UL,
- [2] = 2116500000UL,
- @@ -42,9 +51,6 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
- .process_id = -1,
- .min_millivolts = 900,
- .max_millivolts = 1260,
- - .alignment = {
- - .step_uv = 10000, /* 10mV */
- - },
- .speedo_scale = 100,
- .voltage_scale = 1000,
- .entries = {
- @@ -82,16 +88,505 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
- },
- };
- +static const unsigned long tegra210_cpu_max_freq_table[] = {
- + [0] = 1912500000UL,
- + [1] = 1912500000UL,
- + [2] = 2218500000UL,
- + [3] = 1785000000UL,
- + [4] = 1632000000UL,
- + [5] = 1912500000UL,
- + [6] = 2014500000UL,
- + [7] = 1734000000UL,
- + [8] = 1683000000UL,
- + [9] = 1555500000UL,
- + [10] = 1504500000UL,
- +};
- +
- +#define CPU_CVB_TABLE \
- + .speedo_scale = 100, \
- + .voltage_scale = 1000, \
- + .entries = { \
- + {204000000UL, {1007452, -23865, 370} }, \
- + {306000000UL, {1052709, -24875, 370} }, \
- + {408000000UL, {1099069, -25895, 370} }, \
- + {510000000UL, {1146534, -26905, 370} }, \
- + {612000000UL, {1195102, -27915, 370} }, \
- + {714000000UL, {1244773, -28925, 370} }, \
- + {816000000UL, {1295549, -29935, 370} }, \
- + {918000000UL, {1347428, -30955, 370} }, \
- + {1020000000UL, {1400411, -31965, 370} }, \
- + {1122000000UL, {1454497, -32975, 370} }, \
- + {1224000000UL, {1509687, -33985, 370} }, \
- + {1326000000UL, {1565981, -35005, 370} }, \
- + {1428000000UL, {1623379, -36015, 370} }, \
- + {1530000000UL, {1681880, -37025, 370} }, \
- + {1632000000UL, {1741485, -38035, 370} }, \
- + {1734000000UL, {1802194, -39055, 370} }, \
- + {1836000000UL, {1864006, -40065, 370} }, \
- + {1912500000UL, {1910780, -40815, 370} }, \
- + {2014500000UL, {1227000, 0, 0} }, \
- + {2218500000UL, {1227000, 0, 0} }, \
- + {0, { 0, 0, 0} }, \
- + }
- +
- +#define CPU_CVB_TABLE_XA \
- + .speedo_scale = 100, \
- + .voltage_scale = 1000, \
- + .entries = { \
- + {204000000UL, {1250024, -39785, 565} }, \
- + {306000000UL, {1297556, -41145, 565} }, \
- + {408000000UL, {1346718, -42505, 565} }, \
- + {510000000UL, {1397511, -43855, 565} }, \
- + {612000000UL, {1449933, -45215, 565} }, \
- + {714000000UL, {1503986, -46575, 565} }, \
- + {816000000UL, {1559669, -47935, 565} }, \
- + {918000000UL, {1616982, -49295, 565} }, \
- + {1020000000UL, {1675926, -50645, 565} }, \
- + {1122000000UL, {1736500, -52005, 565} }, \
- + {1224000000UL, {1798704, -53365, 565} }, \
- + {1326000000UL, {1862538, -54725, 565} }, \
- + {1428000000UL, {1928003, -56085, 565} }, \
- + {1530000000UL, {1995097, -57435, 565} }, \
- + {1606500000UL, {2046149, -58445, 565} }, \
- + {1632000000UL, {2063822, -58795, 565} }, \
- + {0, { 0, 0, 0} }, \
- + }
- +
- +#define CPU_CVB_TABLE_EUCM1 \
- + .speedo_scale = 100, \
- + .voltage_scale = 1000, \
- + .entries = { \
- + {204000000UL, {734429, 0, 0} }, \
- + {306000000UL, {768191, 0, 0} }, \
- + {408000000UL, {801953, 0, 0} }, \
- + {510000000UL, {835715, 0, 0} }, \
- + {612000000UL, {869477, 0, 0} }, \
- + {714000000UL, {903239, 0, 0} }, \
- + {816000000UL, {937001, 0, 0} }, \
- + {918000000UL, {970763, 0, 0} }, \
- + {1020000000UL, {1004525, 0, 0} }, \
- + {1122000000UL, {1038287, 0, 0} }, \
- + {1224000000UL, {1072049, 0, 0} }, \
- + {1326000000UL, {1105811, 0, 0} }, \
- + {1428000000UL, {1130000, 0, 0} }, \
- + {1555500000UL, {1130000, 0, 0} }, \
- + {1632000000UL, {1170000, 0, 0} }, \
- + {1734000000UL, {1227500, 0, 0} }, \
- + {0, { 0, 0, 0} }, \
- + }
- +
- +#define CPU_CVB_TABLE_EUCM2 \
- + .speedo_scale = 100, \
- + .voltage_scale = 1000, \
- + .entries = { \
- + {204000000UL, {742283, 0, 0} }, \
- + {306000000UL, {776249, 0, 0} }, \
- + {408000000UL, {810215, 0, 0} }, \
- + {510000000UL, {844181, 0, 0} }, \
- + {612000000UL, {878147, 0, 0} }, \
- + {714000000UL, {912113, 0, 0} }, \
- + {816000000UL, {946079, 0, 0} }, \
- + {918000000UL, {980045, 0, 0} }, \
- + {1020000000UL, {1014011, 0, 0} }, \
- + {1122000000UL, {1047977, 0, 0} }, \
- + {1224000000UL, {1081943, 0, 0} }, \
- + {1326000000UL, {1090000, 0, 0} }, \
- + {1479000000UL, {1090000, 0, 0} }, \
- + {1555500000UL, {1162000, 0, 0} }, \
- + {1683000000UL, {1195000, 0, 0} }, \
- + {0, { 0, 0, 0} }, \
- + }
- +
- +#define CPU_CVB_TABLE_EUCM2_JOINT_RAIL \
- + .speedo_scale = 100, \
- + .voltage_scale = 1000, \
- + .entries = { \
- + {204000000UL, {742283, 0, 0} }, \
- + {306000000UL, {776249, 0, 0} }, \
- + {408000000UL, {810215, 0, 0} }, \
- + {510000000UL, {844181, 0, 0} }, \
- + {612000000UL, {878147, 0, 0} }, \
- + {714000000UL, {912113, 0, 0} }, \
- + {816000000UL, {946079, 0, 0} }, \
- + {918000000UL, {980045, 0, 0} }, \
- + {1020000000UL, {1014011, 0, 0} }, \
- + {1122000000UL, {1047977, 0, 0} }, \
- + {1224000000UL, {1081943, 0, 0} }, \
- + {1326000000UL, {1090000, 0, 0} }, \
- + {1479000000UL, {1090000, 0, 0} }, \
- + {1504500000UL, {1120000, 0, 0} }, \
- + {0, { 0, 0, 0} }, \
- + }
- +
- +#define CPU_CVB_TABLE_ODN \
- + .speedo_scale = 100, \
- + .voltage_scale = 1000, \
- + .entries = { \
- + {204000000UL, {721094, 0, 0} }, \
- + {306000000UL, {754040, 0, 0} }, \
- + {408000000UL, {786986, 0, 0} }, \
- + {510000000UL, {819932, 0, 0} }, \
- + {612000000UL, {852878, 0, 0} }, \
- + {714000000UL, {885824, 0, 0} }, \
- + {816000000UL, {918770, 0, 0} }, \
- + {918000000UL, {915716, 0, 0} }, \
- + {1020000000UL, {984662, 0, 0} }, \
- + {1122000000UL, {1017608, 0, 0} }, \
- + {1224000000UL, {1050554, 0, 0} }, \
- + {1326000000UL, {1083500, 0, 0} }, \
- + {1428000000UL, {1116446, 0, 0} }, \
- + {1581000000UL, {1130000, 0, 0} }, \
- + {1683000000UL, {1168000, 0, 0} }, \
- + {1785000000UL, {1227500, 0, 0} }, \
- + {0, { 0, 0, 0} }, \
- + }
- +
- +struct cvb_table tegra210_cpu_cvb_tables[] = {
- + {
- + .speedo_id = 10,
- + .process_id = 0,
- + .min_millivolts = 840,
- + .max_millivolts = 1120,
- + CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 10,
- + .process_id = 1,
- + .min_millivolts = 840,
- + .max_millivolts = 1120,
- + CPU_CVB_TABLE_EUCM2_JOINT_RAIL,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 9,
- + .process_id = 0,
- + .min_millivolts = 900,
- + .max_millivolts = 1162,
- + CPU_CVB_TABLE_EUCM2,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + }
- + },
- + {
- + .speedo_id = 9,
- + .process_id = 1,
- + .min_millivolts = 900,
- + .max_millivolts = 1162,
- + CPU_CVB_TABLE_EUCM2,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + }
- + },
- + {
- + .speedo_id = 8,
- + .process_id = 0,
- + .min_millivolts = 900,
- + .max_millivolts = 1195,
- + CPU_CVB_TABLE_EUCM2,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + }
- + },
- + {
- + .speedo_id = 8,
- + .process_id = 1,
- + .min_millivolts = 900,
- + .max_millivolts = 1195,
- + CPU_CVB_TABLE_EUCM2,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + }
- + },
- + {
- + .speedo_id = 7,
- + .process_id = 0,
- + .min_millivolts = 841,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE_EUCM1,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 7,
- + .process_id = 1,
- + .min_millivolts = 841,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE_EUCM1,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 6,
- + .process_id = 0,
- + .min_millivolts = 870,
- + .max_millivolts = 1150,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + }
- + },
- + {
- + .speedo_id = 6,
- + .process_id = 1,
- + .min_millivolts = 870,
- + .max_millivolts = 1150,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune1 = 0x25501d0,
- + }
- + },
- + {
- + .speedo_id = 5,
- + .process_id = 0,
- + .min_millivolts = 818,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 5,
- + .process_id = 1,
- + .min_millivolts = 818,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x25501d0,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 4,
- + .process_id = -1,
- + .min_millivolts = 918,
- + .max_millivolts = 1113,
- + CPU_CVB_TABLE_XA,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune1 = 0x17711BD,
- + }
- + },
- + {
- + .speedo_id = 3,
- + .process_id = 0,
- + .min_millivolts = 825,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE_ODN,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 3,
- + .process_id = 1,
- + .min_millivolts = 825,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE_ODN,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x25501d0,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 2,
- + .process_id = 0,
- + .min_millivolts = 870,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + }
- + },
- + {
- + .speedo_id = 2,
- + .process_id = 1,
- + .min_millivolts = 870,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune1 = 0x25501d0,
- + }
- + },
- + {
- + .speedo_id = 1,
- + .process_id = 0,
- + .min_millivolts = 837,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 1,
- + .process_id = 1,
- + .min_millivolts = 837,
- + .max_millivolts = 1227,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x25501d0,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 0,
- + .process_id = 0,
- + .min_millivolts = 850,
- + .max_millivolts = 1170,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x20091d9,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- + {
- + .speedo_id = 0,
- + .process_id = 1,
- + .min_millivolts = 850,
- + .max_millivolts = 1170,
- + CPU_CVB_TABLE,
- + .cpu_dfll_data = {
- + .tune0_low = 0xffead0ff,
- + .tune0_high = 0xffead0ff,
- + .tune1 = 0x25501d0,
- + .tune_high_min_millivolts = 864,
- + }
- + },
- +};
- +
- +static const struct dfll_fcpu_data tegra124_dfll_fcpu_data = {
- + .cpu_max_freq_table = tegra124_cpu_max_freq_table,
- + .cpu_max_freq_table_size = ARRAY_SIZE(tegra124_cpu_max_freq_table),
- + .cpu_cvb_tables = tegra124_cpu_cvb_tables,
- + .cpu_cvb_tables_size = ARRAY_SIZE(tegra124_cpu_cvb_tables)
- +};
- +
- +static const struct dfll_fcpu_data tegra210_dfll_fcpu_data = {
- + .cpu_max_freq_table = tegra210_cpu_max_freq_table,
- + .cpu_max_freq_table_size = ARRAY_SIZE(tegra210_cpu_max_freq_table),
- + .cpu_cvb_tables = tegra210_cpu_cvb_tables,
- + .cpu_cvb_tables_size = ARRAY_SIZE(tegra210_cpu_cvb_tables),
- +};
- +
- +static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
- + {
- + .compatible = "nvidia,tegra124-dfll",
- + .data = &tegra124_dfll_fcpu_data,
- + },
- + {
- + .compatible = "nvidia,tegra210-dfll",
- + .data = &tegra210_dfll_fcpu_data
- + },
- + { },
- +};
- +
- +static int get_alignment_from_regulator(struct device *dev,
- + struct rail_alignment *align)
- +{
- + int min_uV, max_uV, n_voltages, ret;
- + struct regulator *reg;
- +
- + reg = devm_regulator_get(dev, "vdd-cpu");
- + if (IS_ERR(reg))
- + return PTR_ERR(reg);
- +
- + ret = regulator_get_constraint_voltages(reg, &min_uV, &max_uV);
- + if (!ret)
- + align->offset_uv = min_uV;
- + else
- + return ret;
- +
- + align->step_uv = regulator_get_linear_step(reg);
- + if (!align->step_uv && !ret) {
- + n_voltages = regulator_count_voltages(reg);
- + if (n_voltages > 1)
- + align->step_uv = (max_uV - min_uV) / (n_voltages - 1);
- + }
- +
- + devm_regulator_put(reg);
- +
- + return 0;
- +}
- +
- +static int get_alignment_from_dt(struct device *dev,
- + struct rail_alignment *align)
- +{
- + int err;
- +
- + err = of_property_read_u32(dev->of_node, "nvidia,align-step-uv",
- + &align->step_uv);
- + if (err < 0)
- + return err;
- +
- + err = of_property_read_u32(dev->of_node,
- + "nvidia,align-offset-uv", &align->offset_uv);
- + return err;
- +}
- +
- static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
- {
- int process_id, speedo_id, speedo_value, err;
- struct tegra_dfll_soc_data *soc;
- + const struct of_device_id *of_id;
- + const struct dfll_fcpu_data *fcpu_data;
- +
- + of_id = of_match_device(tegra124_dfll_fcpu_of_match, &pdev->dev);
- + fcpu_data = of_id->data;
- process_id = tegra_sku_info.cpu_process_id;
- speedo_id = tegra_sku_info.cpu_speedo_id;
- speedo_value = tegra_sku_info.cpu_speedo_value;
- - if (speedo_id >= ARRAY_SIZE(cpu_max_freq_table)) {
- + if (speedo_id >= fcpu_data->cpu_max_freq_table_size) {
- dev_err(&pdev->dev, "unknown max CPU freq for speedo_id=%d\n",
- speedo_id);
- return -ENODEV;
- @@ -107,11 +602,19 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
- return -ENODEV;
- }
- - soc->max_freq = cpu_max_freq_table[speedo_id];
- + soc->max_freq = fcpu_data->cpu_max_freq_table[speedo_id];
- + if (of_property_read_bool(pdev->dev.of_node, "nvidia,pwm-to-pmic"))
- + err = get_alignment_from_dt(&pdev->dev, &soc->alignment);
- + else
- + err = get_alignment_from_regulator(&pdev->dev,
- + &soc->alignment);
- + if (err < 0)
- + return err;
- - soc->cvb = tegra_cvb_add_opp_table(soc->dev, tegra124_cpu_cvb_tables,
- - ARRAY_SIZE(tegra124_cpu_cvb_tables),
- - process_id, speedo_id, speedo_value,
- + soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables,
- + fcpu_data->cpu_cvb_tables_size,
- + &soc->alignment, process_id,
- + speedo_id, speedo_value,
- soc->max_freq);
- if (IS_ERR(soc->cvb)) {
- dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
- @@ -142,11 +645,6 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
- return 0;
- }
- -static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
- - { .compatible = "nvidia,tegra124-dfll", },
- - { },
- -};
- -
- static const struct dev_pm_ops tegra124_dfll_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
- tegra_dfll_runtime_resume, NULL)
- diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
- index 9fb5d51..5484e46 100644
- --- a/drivers/clk/tegra/clk-tegra210.c
- +++ b/drivers/clk/tegra/clk-tegra210.c
- @@ -3359,6 +3359,14 @@ static struct tegra_clk_init_table init_table[] __initdata = {
- { TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 },
- { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
- { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 },
- + { TEGRA210_CLK_CLK72MHZ, TEGRA210_CLK_PLL_P_OUT3, 68000000, 0 },
- +// { TEGRA210_CLK_DSIA, TEGRA210_CLK_PLL_D, 68000000, 0 },
- +// { TEGRA210_CLK_DSIB, TEGRA210_CLK_PLL_D, 68000000, 0 },
- + { TEGRA210_CLK_DSIALP, TEGRA210_CLK_PLL_P, 68000000, 0 },
- + { TEGRA210_CLK_DSIBLP, TEGRA210_CLK_PLL_P, 68000000, 0 },
- + { TEGRA210_CLK_DISP1, TEGRA210_CLK_PLL_D_OUT0, 0, 0 },
- + { TEGRA210_CLK_DISP2, TEGRA210_CLK_PLL_D_OUT0, 0, 0 },
- + { TEGRA210_CLK_PWM, TEGRA210_CLK_PLL_P, 48000000, 0 },
- /* This MUST be the last entry. */
- { TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 },
- };
- @@ -3534,6 +3542,25 @@ static void __init tegra210_clock_init(struct device_node *np)
- return;
- }
- + ahub_base = ioremap(TEGRA210_AHUB_BASE, 64*1024);
- + if (!ahub_base) {
- + pr_err("ioremap tegra210 APE failed\n");
- + return;
- + }
- +
- + dispa_base = ioremap(TEGRA210_DISPA_BASE, 256*1024);
- + if (!dispa_base) {
- + pr_err("ioremap tegra210 DISPA failed\n");
- + return;
- + }
- +
- + vic_base = ioremap(TEGRA210_VIC_BASE, 256*1024);
- + if (!vic_base) {
- + pr_err("ioremap tegra210 VIC failed\n");
- + return;
- + }
- +
- +
- clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX,
- TEGRA210_CAR_BANK_COUNT);
- if (!clks)
- diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
- index da9e8e7..2aa9639 100644
- --- a/drivers/clk/tegra/cvb.c
- +++ b/drivers/clk/tegra/cvb.c
- @@ -62,11 +62,17 @@ 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)
- {
- - const struct rail_alignment *align = &table->alignment;
- int i, ret, dfll_mv, min_mv, max_mv;
- + if (!align->step_uv)
- + return -EINVAL;
- +
- + if (!align->offset_uv)
- + return -EINVAL;
- +
- min_mv = round_voltage(table->min_millivolts, align, UP);
- max_mv = round_voltage(table->max_millivolts, align, DOWN);
- @@ -109,8 +115,9 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
- */
- const struct cvb_table *
- tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
- - size_t count, int process_id, int speedo_id,
- - int speedo_value, unsigned long max_freq)
- + size_t count, struct rail_alignment *align,
- + int process_id, int speedo_id, int speedo_value,
- + unsigned long max_freq)
- {
- size_t i;
- int ret;
- @@ -124,7 +131,8 @@ tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
- if (table->process_id != -1 && table->process_id != process_id)
- continue;
- - ret = build_opp_table(dev, table, speedo_value, max_freq);
- + ret = build_opp_table(dev, table, align, speedo_value,
- + max_freq);
- return ret ? ERR_PTR(ret) : table;
- }
- diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h
- index c1f0779..91a1941 100644
- --- a/drivers/clk/tegra/cvb.h
- +++ b/drivers/clk/tegra/cvb.h
- @@ -41,6 +41,7 @@ struct cvb_cpu_dfll_data {
- u32 tune0_low;
- u32 tune0_high;
- u32 tune1;
- + unsigned int tune_high_min_millivolts;
- };
- struct cvb_table {
- @@ -49,7 +50,6 @@ struct cvb_table {
- int min_millivolts;
- int max_millivolts;
- - struct rail_alignment alignment;
- int speedo_scale;
- int voltage_scale;
- @@ -59,8 +59,9 @@ struct cvb_table {
- const struct cvb_table *
- tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
- - size_t count, int process_id, int speedo_id,
- - int speedo_value, unsigned long max_freq);
- + size_t count, struct rail_alignment *align,
- + int process_id, int speedo_id, int speedo_value,
- + unsigned long max_freq);
- void tegra_cvb_remove_opp_table(struct device *dev,
- const struct cvb_table *table,
- unsigned long max_freq);
- diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c
- index 4353025..f8e01a8 100644
- --- a/drivers/cpufreq/tegra124-cpufreq.c
- +++ b/drivers/cpufreq/tegra124-cpufreq.c
- @@ -64,7 +64,8 @@ static void tegra124_cpu_switch_to_pllx(struct tegra124_cpufreq_priv *priv)
- {
- clk_set_parent(priv->cpu_clk, priv->pllp_clk);
- clk_disable_unprepare(priv->dfll_clk);
- - regulator_sync_voltage(priv->vdd_cpu_reg);
- + if (priv->vdd_cpu_reg)
- + regulator_sync_voltage(priv->vdd_cpu_reg);
- clk_set_parent(priv->cpu_clk, priv->pllx_clk);
- }
- @@ -89,10 +90,10 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
- return -ENODEV;
- priv->vdd_cpu_reg = regulator_get(cpu_dev, "vdd-cpu");
- - if (IS_ERR(priv->vdd_cpu_reg)) {
- - ret = PTR_ERR(priv->vdd_cpu_reg);
- - goto out_put_np;
- - }
- + if (IS_ERR(priv->vdd_cpu_reg) != -EPROBE_DEFER)
- + priv->vdd_cpu_reg = NULL;
- + else
- + return -EPROBE_DEFER;
- priv->cpu_clk = of_clk_get_by_name(np, "cpu_g");
- if (IS_ERR(priv->cpu_clk)) {
- @@ -148,7 +149,6 @@ out_put_cpu_clk:
- clk_put(priv->cpu_clk);
- out_put_vdd_cpu_reg:
- regulator_put(priv->vdd_cpu_reg);
- -out_put_np:
- of_node_put(np);
- return ret;
- @@ -181,7 +181,8 @@ static int __init tegra_cpufreq_init(void)
- int ret;
- struct platform_device *pdev;
- - if (!of_machine_is_compatible("nvidia,tegra124"))
- + if (!(of_machine_is_compatible("nvidia,tegra124")
- + || of_machine_is_compatible("nvidia,tegra210")))
- return -ENODEV;
- /*
- diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
- index 94396ca..a3694f0 100644
- --- a/drivers/gpio/gpio-tegra.c
- +++ b/drivers/gpio/gpio-tegra.c
- @@ -356,6 +356,8 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d)
- struct tegra_gpio_info *tgi = bank->tgi;
- unsigned int gpio = d->hwirq;
- + tegra_gpio_irq_mask(d);
- +
- gpiochip_unlock_as_irq(&tgi->gc, gpio);
- }
- diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
- index 7856a9b..082f653 100644
- --- a/drivers/gpu/drm/drm_prime.c
- +++ b/drivers/gpu/drm/drm_prime.c
- @@ -182,6 +182,7 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
- return -ENOENT;
- }
- +EXPORT_SYMBOL(drm_gem_map_detach);
- /**
- * drm_gem_map_attach - dma_buf attach implementation for GEM
- diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
- index ab61c03..1060ce4 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
- +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
- @@ -544,6 +544,42 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)
- PAGE_SIZE, DMA_FROM_DEVICE);
- }
- +int
- +nouveau_bo_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan,
- + bool exclusive, bool intr)
- +{
- + struct reservation_object *resv = nvbo->bo.resv;
- + struct reservation_object_list *fobj;
- + struct dma_fence *fence;
- + int ret = 0, i;
- +
- + if (!exclusive) {
- + ret = reservation_object_reserve_shared(resv);
- + if (ret < 0)
- + return ret;
- + }
- +
- + fobj = reservation_object_get_list(resv);
- + fence = reservation_object_get_excl(resv);
- +
- + if (fence && (!exclusive || !fobj || !fobj->shared_count))
- + return nouveau_fence_sync(fence, chan, intr);
- +
- + if (!exclusive || !fobj)
- + return ret;
- +
- + for (i = 0; i < fobj->shared_count && !ret; ++i) {
- + fence = rcu_dereference_protected(fobj->shared[i],
- + reservation_object_held(resv));
- +
- + ret = nouveau_fence_sync(fence, chan, intr);
- + if (ret < 0)
- + break;
- + }
- +
- + return ret;
- +}
- +
- int
- nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
- bool no_wait_gpu)
- @@ -1111,7 +1147,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
- }
- mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
- - ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, intr);
- + ret = nouveau_bo_sync(nouveau_bo(bo), chan, true, intr);
- if (ret == 0) {
- ret = drm->ttm.move(chan, bo, &bo->mem, new_reg);
- if (ret == 0) {
- diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h
- index 73c4844..9a79502 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_bo.h
- +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h
- @@ -91,6 +91,8 @@ int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
- bool no_wait_gpu);
- void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo);
- void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo);
- +int nouveau_bo_sync(struct nouveau_bo *nvbo, struct nouveau_channel *channel,
- + bool exclusive, bool intr);
- /* TODO: submit equivalent to TTM generic API upstream? */
- static inline void __iomem *
- diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
- index 4cba117..014a50f 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_display.c
- +++ b/drivers/gpu/drm/nouveau/nouveau_display.c
- @@ -761,7 +761,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
- spin_unlock_irqrestore(&dev->event_lock, flags);
- /* Synchronize with the old framebuffer */
- - ret = nouveau_fence_sync(old_bo, chan, false, false);
- + ret = nouveau_bo_sync(old_bo, chan, false, false);
- if (ret)
- goto fail;
- @@ -825,7 +825,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
- goto fail_unpin;
- /* synchronise rendering channel with the kernel's channel */
- - ret = nouveau_fence_sync(new_bo, chan, false, true);
- + ret = nouveau_bo_sync(new_bo, chan, false, true);
- if (ret) {
- ttm_bo_unreserve(&new_bo->bo);
- goto fail_unpin;
- diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
- index f8e67ab..acfa5b5 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_drm.c
- +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
- @@ -961,6 +961,7 @@ nouveau_ioctls[] = {
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW),
- DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW),
- + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF2, nouveau_gem_ioctl_pushbuf2, DRM_AUTH|DRM_RENDER_ALLOW),
- };
- long
- @@ -1030,15 +1031,12 @@ driver_stub = {
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
- - .gem_prime_export = drm_gem_prime_export,
- - .gem_prime_import = drm_gem_prime_import,
- + .gem_prime_export = nouveau_gem_prime_export,
- + .gem_prime_import = nouveau_gem_prime_import,
- .gem_prime_pin = nouveau_gem_prime_pin,
- - .gem_prime_res_obj = nouveau_gem_prime_res_obj,
- .gem_prime_unpin = nouveau_gem_prime_unpin,
- + .gem_prime_res_obj = nouveau_gem_prime_res_obj,
- .gem_prime_get_sg_table = nouveau_gem_prime_get_sg_table,
- - .gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table,
- - .gem_prime_vmap = nouveau_gem_prime_vmap,
- - .gem_prime_vunmap = nouveau_gem_prime_vunmap,
- .gem_free_object_unlocked = nouveau_gem_object_del,
- .gem_open_object = nouveau_gem_object_open,
- diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
- index 503fa94..63022bc 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_fence.c
- +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
- @@ -28,6 +28,7 @@
- #include <linux/ktime.h>
- #include <linux/hrtimer.h>
- +#include <linux/dma-fence-array.h>
- #include <trace/events/dma_fence.h>
- #include <nvif/cl826e.h>
- @@ -331,66 +332,50 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
- return 0;
- }
- -int
- -nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive, bool intr)
- +static int
- +__nouveau_fence_sync(struct dma_fence *fence, struct nouveau_channel *chan,
- + bool intr)
- {
- struct nouveau_fence_chan *fctx = chan->fence;
- - struct dma_fence *fence;
- - struct reservation_object *resv = nvbo->bo.resv;
- - struct reservation_object_list *fobj;
- + struct nouveau_channel *prev = NULL;
- struct nouveau_fence *f;
- - int ret = 0, i;
- -
- - if (!exclusive) {
- - ret = reservation_object_reserve_shared(resv);
- + bool must_wait = true;
- + int ret = 0;
- - if (ret)
- - return ret;
- + f = nouveau_local_fence(fence, chan->drm);
- + if (f) {
- + rcu_read_lock();
- + prev = rcu_dereference(f->channel);
- + if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0))
- + must_wait = false;
- + rcu_read_unlock();
- }
- - fobj = reservation_object_get_list(resv);
- - fence = reservation_object_get_excl(resv);
- -
- - if (fence && (!exclusive || !fobj || !fobj->shared_count)) {
- - struct nouveau_channel *prev = NULL;
- - bool must_wait = true;
- + if (must_wait)
- + ret = dma_fence_wait(fence, intr);
- - f = nouveau_local_fence(fence, chan->drm);
- - if (f) {
- - rcu_read_lock();
- - prev = rcu_dereference(f->channel);
- - if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0))
- - must_wait = false;
- - rcu_read_unlock();
- - }
- -
- - if (must_wait)
- - ret = dma_fence_wait(fence, intr);
- -
- - return ret;
- - }
- + return ret;
- +}
- - if (!exclusive || !fobj)
- - return ret;
- +int
- +nouveau_fence_sync(struct dma_fence *fence, struct nouveau_channel *chan,
- + bool intr)
- +{
- + int ret = 0;
- - for (i = 0; i < fobj->shared_count && !ret; ++i) {
- - struct nouveau_channel *prev = NULL;
- - bool must_wait = true;
- + if (dma_fence_is_array(fence)) {
- + struct dma_fence_array *array = to_dma_fence_array(fence);
- + unsigned int i;
- - fence = rcu_dereference_protected(fobj->shared[i],
- - reservation_object_held(resv));
- + for (i = 0; i < array->num_fences; i++) {
- + struct dma_fence *f = array->fences[i];
- - f = nouveau_local_fence(fence, chan->drm);
- - if (f) {
- - rcu_read_lock();
- - prev = rcu_dereference(f->channel);
- - if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0))
- - must_wait = false;
- - rcu_read_unlock();
- + ret = __nouveau_fence_sync(f, chan, intr);
- + if (ret < 0)
- + break;
- }
- -
- - if (must_wait)
- - ret = dma_fence_wait(fence, intr);
- + } else {
- + ret = __nouveau_fence_sync(fence, chan, intr);
- }
- return ret;
- diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
- index 5bd8d30..2c46d9e 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_fence.h
- +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
- @@ -24,7 +24,7 @@ void nouveau_fence_unref(struct nouveau_fence **);
- int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *);
- bool nouveau_fence_done(struct nouveau_fence *);
- int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
- -int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr);
- +int nouveau_fence_sync(struct dma_fence *, struct nouveau_channel *, bool intr);
- struct nouveau_fence_chan {
- spinlock_t lock;
- diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
- index 707e02c..d690f11 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
- +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
- @@ -24,6 +24,8 @@
- *
- */
- +#include <linux/sync_file.h>
- +
- #include "nouveau_drv.h"
- #include "nouveau_dma.h"
- #include "nouveau_fence.h"
- @@ -507,7 +509,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
- return ret;
- }
- - ret = nouveau_fence_sync(nvbo, chan, !!b->write_domains, true);
- + ret = nouveau_bo_sync(nvbo, chan, !!b->write_domains, true);
- if (unlikely(ret)) {
- if (ret != -ERESTARTSYS)
- NV_PRINTK(err, cli, "fail post-validate sync\n");
- @@ -679,22 +681,28 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
- return ret;
- }
- -int
- -nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
- - struct drm_file *file_priv)
- +static int
- +__nouveau_gem_ioctl_pushbuf(struct drm_device *dev,
- + struct drm_nouveau_gem_pushbuf2 *request,
- + struct drm_file *file_priv)
- {
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
- struct nouveau_cli *cli = nouveau_cli(file_priv);
- struct nouveau_abi16_chan *temp;
- struct nouveau_drm *drm = nouveau_drm(dev);
- - struct drm_nouveau_gem_pushbuf *req = data;
- + struct drm_nouveau_gem_pushbuf *req = &request->base;
- struct drm_nouveau_gem_pushbuf_push *push;
- struct drm_nouveau_gem_pushbuf_bo *bo;
- struct nouveau_channel *chan = NULL;
- struct validate_op op;
- struct nouveau_fence *fence = NULL;
- + struct dma_fence *prefence = NULL;
- int i, j, ret = 0, do_reloc = 0;
- + /* check for unrecognized flags */
- + if (request->flags & ~NOUVEAU_GEM_PUSHBUF_FLAGS)
- + return -EINVAL;
- +
- if (unlikely(!abi16))
- return -ENOMEM;
- @@ -759,6 +767,15 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
- goto out_prevalid;
- }
- + if (request->flags & NOUVEAU_GEM_PUSHBUF_FENCE_WAIT) {
- + prefence = sync_file_get_fence(request->fence);
- + if (prefence) {
- + ret = nouveau_fence_sync(prefence, chan, true);
- + if (ret < 0)
- + goto out;
- + }
- + }
- +
- /* Apply any relocations that are required */
- if (do_reloc) {
- ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo);
- @@ -843,7 +860,30 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
- goto out;
- }
- + if (request->flags & NOUVEAU_GEM_PUSHBUF_FENCE_EMIT) {
- + struct sync_file *file;
- + int fd;
- +
- + fd = get_unused_fd_flags(O_CLOEXEC);
- + if (fd < 0) {
- + ret = fd;
- + goto out;
- + }
- +
- + file = sync_file_create(&fence->base);
- + if (!file) {
- + put_unused_fd(fd);
- + goto out;
- + }
- +
- + fd_install(fd, file->file);
- + request->fence = fd;
- + }
- +
- out:
- + if (prefence)
- + dma_fence_put(prefence);
- +
- validate_fini(&op, fence, bo);
- nouveau_fence_unref(&fence);
- @@ -868,6 +908,27 @@ out_next:
- return nouveau_abi16_put(abi16, ret);
- }
- +int
- +nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
- + struct drm_file *file_priv)
- +{
- + struct drm_nouveau_gem_pushbuf *request = data;
- + struct drm_nouveau_gem_pushbuf2 req;
- + int ret;
- +
- + memset(&req, 0, sizeof(req));
- + memcpy(&req.base, request, sizeof(*request));
- +
- + ret = __nouveau_gem_ioctl_pushbuf(dev, &req, file_priv);
- +
- + request->gart_available = req.base.gart_available;
- + request->vram_available = req.base.vram_available;
- + request->suffix1 = req.base.suffix1;
- + request->suffix0 = req.base.suffix0;
- +
- + return ret;
- +}
- +
- int
- nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
- @@ -935,3 +996,12 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
- return ret;
- }
- +int
- +nouveau_gem_ioctl_pushbuf2(struct drm_device *dev, void *data,
- + struct drm_file *file_priv)
- +{
- + struct drm_nouveau_gem_pushbuf2 *req = data;
- +
- + return __nouveau_gem_ioctl_pushbuf(dev, req, file_priv);
- +}
- +
- diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h
- index fe39998..3c98b0f 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_gem.h
- +++ b/drivers/gpu/drm/nouveau/nouveau_gem.h
- @@ -31,14 +31,17 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
- struct drm_file *);
- extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
- struct drm_file *);
- +extern int nouveau_gem_ioctl_pushbuf2(struct drm_device *, void *,
- + struct drm_file *);
- -extern int nouveau_gem_prime_pin(struct drm_gem_object *);
- +struct dma_buf *nouveau_gem_prime_export(struct drm_device *dev,
- + struct drm_gem_object *obj,
- + int flags);
- +struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *drm,
- + struct dma_buf *buf);
- +int nouveau_gem_prime_pin(struct drm_gem_object *obj);
- +void nouveau_gem_prime_unpin(struct drm_gem_object *obj);
- struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *);
- -extern void nouveau_gem_prime_unpin(struct drm_gem_object *);
- -extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *);
- -extern struct drm_gem_object *nouveau_gem_prime_import_sg_table(
- - struct drm_device *, struct dma_buf_attachment *, struct sg_table *);
- -extern void *nouveau_gem_prime_vmap(struct drm_gem_object *);
- -extern void nouveau_gem_prime_vunmap(struct drm_gem_object *, void *);
- +struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *obj);
- #endif
- diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c
- index 1fefc93..a3a586c 100644
- --- a/drivers/gpu/drm/nouveau/nouveau_prime.c
- +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
- @@ -23,69 +23,206 @@
- */
- #include <drm/drmP.h>
- +#include <drm/drm_legacy.h>
- #include <linux/dma-buf.h>
- #include "nouveau_drv.h"
- #include "nouveau_gem.h"
- -struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *obj)
- +static int nouveau_gem_prime_begin_cpu_access(struct dma_buf *buf,
- + enum dma_data_direction direction)
- {
- - struct nouveau_bo *nvbo = nouveau_gem_object(obj);
- - int npages = nvbo->bo.num_pages;
- + struct nouveau_bo *bo = nouveau_gem_object(buf->priv);
- - return drm_prime_pages_to_sg(nvbo->bo.ttm->pages, npages);
- + nouveau_bo_sync_for_cpu(bo);
- +
- + return 0;
- }
- -void *nouveau_gem_prime_vmap(struct drm_gem_object *obj)
- +static int nouveau_gem_prime_end_cpu_access(struct dma_buf *buf,
- + enum dma_data_direction direction)
- {
- - struct nouveau_bo *nvbo = nouveau_gem_object(obj);
- + struct nouveau_bo *bo = nouveau_gem_object(buf->priv);
- +
- + nouveau_bo_sync_for_device(bo);
- +
- + return 0;
- +}
- +
- +static void *nouveau_gem_prime_kmap_atomic(struct dma_buf *buf,
- + unsigned long page)
- +{
- + return NULL;
- +}
- +
- +static void nouveau_gem_prime_kunmap_atomic(struct dma_buf *buf,
- + unsigned long page, void *addr)
- +{
- +}
- +
- +static void *nouveau_gem_prime_kmap(struct dma_buf *buf, unsigned long page)
- +{
- + return NULL;
- +}
- +
- +static void nouveau_gem_prime_kunmap(struct dma_buf *buf, unsigned long page,
- + void *addr)
- +{
- +}
- +
- +static inline u64 nouveau_bo_mmap_offset(struct nouveau_bo *bo)
- +{
- + return drm_vma_node_offset_addr(&bo->bo.vma_node) >> PAGE_SHIFT;
- +}
- +
- +static int nouveau_gem_prime_mmap(struct dma_buf *buf,
- + struct vm_area_struct *vma)
- +{
- + struct nouveau_bo *bo = nouveau_gem_object(buf->priv);
- + struct drm_gem_object *obj = buf->priv;
- + int ret;
- +
- + /* check for valid size */
- + if (obj->size < vma->vm_end - vma->vm_start)
- + return -EINVAL;
- +
- + vma->vm_pgoff += nouveau_bo_mmap_offset(bo);
- +
- + if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
- + return drm_legacy_mmap(vma->vm_file, vma);
- +
- + ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data);
- + if (ret)
- + return ret;
- +
- + ret = ttm_bo_mmap(vma->vm_file, vma, bo->bo.bdev);
- + drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data);
- +
- + return ret;
- +}
- +
- +static void *nouveau_gem_prime_vmap(struct dma_buf *buf)
- +{
- + struct nouveau_bo *bo = nouveau_gem_object(buf->priv);
- int ret;
- - ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.num_pages,
- - &nvbo->dma_buf_vmap);
- + ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->dma_buf_vmap);
- if (ret)
- return ERR_PTR(ret);
- - return nvbo->dma_buf_vmap.virtual;
- + return bo->dma_buf_vmap.virtual;
- }
- -void nouveau_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
- +static void nouveau_gem_prime_vunmap(struct dma_buf *buf, void *vaddr)
- {
- - struct nouveau_bo *nvbo = nouveau_gem_object(obj);
- + struct nouveau_bo *bo = nouveau_gem_object(buf->priv);
- - ttm_bo_kunmap(&nvbo->dma_buf_vmap);
- + ttm_bo_kunmap(&bo->dma_buf_vmap);
- }
- -struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
- - struct dma_buf_attachment *attach,
- - struct sg_table *sg)
- +static const struct dma_buf_ops nouveau_gem_prime_dmabuf_ops = {
- + .attach = drm_gem_map_attach,
- + .detach = drm_gem_map_detach,
- + .map_dma_buf = drm_gem_map_dma_buf,
- + .unmap_dma_buf = drm_gem_unmap_dma_buf,
- + .release = drm_gem_dmabuf_release,
- + .begin_cpu_access = nouveau_gem_prime_begin_cpu_access,
- + .end_cpu_access = nouveau_gem_prime_end_cpu_access,
- + .map_atomic = nouveau_gem_prime_kmap_atomic,
- + .unmap_atomic = nouveau_gem_prime_kunmap_atomic,
- + .map = nouveau_gem_prime_kmap,
- + .unmap = nouveau_gem_prime_kunmap,
- + .mmap = nouveau_gem_prime_mmap,
- + .vmap = nouveau_gem_prime_vmap,
- + .vunmap = nouveau_gem_prime_vunmap,
- +};
- +
- +struct dma_buf *nouveau_gem_prime_export(struct drm_device *dev,
- + struct drm_gem_object *obj,
- + int flags)
- +{
- + DEFINE_DMA_BUF_EXPORT_INFO(info);
- +
- + info.exp_name = KBUILD_MODNAME;
- + info.owner = dev->driver->fops->owner;
- + info.ops = &nouveau_gem_prime_dmabuf_ops;
- + info.size = obj->size;
- + info.flags = flags;
- + info.priv = obj;
- +
- + if (dev->driver->gem_prime_res_obj)
- + info.resv = dev->driver->gem_prime_res_obj(obj);
- +
- + return drm_gem_dmabuf_export(dev, &info);
- +}
- +
- +struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *dev,
- + struct dma_buf *buf)
- {
- struct nouveau_drm *drm = nouveau_drm(dev);
- - struct nouveau_bo *nvbo;
- - struct reservation_object *robj = attach->dmabuf->resv;
- - u32 flags = 0;
- + struct dma_buf_attachment *attach;
- + struct drm_gem_object *obj;
- + u32 flags = TTM_PL_FLAG_TT;
- + struct nouveau_bo *bo;
- + struct sg_table *sgt;
- int ret;
- - flags = TTM_PL_FLAG_TT;
- + if (buf->ops == &nouveau_gem_prime_dmabuf_ops) {
- + obj = buf->priv;
- - ww_mutex_lock(&robj->lock, NULL);
- - ret = nouveau_bo_new(&drm->client, attach->dmabuf->size, 0, flags, 0, 0,
- - sg, robj, &nvbo);
- - ww_mutex_unlock(&robj->lock);
- - if (ret)
- - return ERR_PTR(ret);
- + if (obj->dev == dev) {
- + /*
- + * Importing a DMA-BUF exported from our own GEM
- + * increases the reference count on the GEM itself
- + * instead of the f_count of the DMA-BUF.
- + */
- + drm_gem_object_get(obj);
- + return obj;
- + }
- + }
- - nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_GART;
- + attach = dma_buf_attach(buf, dev->dev);
- + if (IS_ERR(attach))
- + return ERR_CAST(attach);
- - /* Initialize the embedded gem-object. We return a single gem-reference
- - * to the caller, instead of a normal nouveau_bo ttm reference. */
- - ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size);
- - if (ret) {
- - nouveau_bo_ref(NULL, &nvbo);
- - return ERR_PTR(-ENOMEM);
- + get_dma_buf(buf);
- +
- + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
- + if (IS_ERR(sgt)) {
- + ret = PTR_ERR(sgt);
- + goto detach;
- }
- - return &nvbo->gem;
- + ww_mutex_lock(&attach->dmabuf->resv->lock, NULL);
- + ret = nouveau_bo_new(&drm->client, attach->dmabuf->size, 0, flags, 0,
- + 0, sgt, attach->dmabuf->resv, &bo);
- + ww_mutex_unlock(&attach->dmabuf->resv->lock);
- + if (ret)
- + goto unmap;
- +
- + bo->valid_domains = NOUVEAU_GEM_DOMAIN_GART;
- +
- + /*
- + * Initialize the embedded GEM object. We return a single GEM reference
- + * to the caller, instead of a normal nouveau_bo TTM reference.
- + */
- + ret = drm_gem_object_init(dev, &bo->gem, bo->bo.mem.size);
- + if (ret)
- + goto unref;
- +
- + bo->gem.import_attach = attach;
- +
- + return &bo->gem;
- +
- +unref:
- + nouveau_bo_ref(NULL, &bo);
- +unmap:
- + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
- +detach:
- + dma_buf_detach(buf, attach);
- + dma_buf_put(buf);
- +
- + return ERR_PTR(ret);
- }
- int nouveau_gem_prime_pin(struct drm_gem_object *obj)
- @@ -114,3 +251,11 @@ struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *obj)
- return nvbo->bo.resv;
- }
- +
- +struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *obj)
- +{
- + struct nouveau_bo *nvbo = nouveau_gem_object(obj);
- + int npages = nvbo->bo.num_pages;
- +
- + return drm_prime_pages_to_sg(nvbo->bo.ttm->pages, npages);
- +}
- diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
- index 25682ff..c453a8f 100644
- --- a/drivers/gpu/drm/panel/Kconfig
- +++ b/drivers/gpu/drm/panel/Kconfig
- @@ -81,6 +81,15 @@ config DRM_PANEL_LG_LG4573
- Say Y here if you want to enable support for LG4573 RGB panel.
- To compile this driver as a module, choose M here.
- +config DRM_PANEL_JDI_LPM062M326A
- + tristate "JDI LPM062M326A 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 JDI LPM062M326A,
- + used in the Nintendo Switch.
- +
- config DRM_PANEL_ORISETECH_OTM8009A
- tristate "Orise Technology otm8009a 480x800 dsi 2dl panel"
- depends on OF
- diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
- index f26efc1..17e2851 100644
- --- a/drivers/gpu/drm/panel/Makefile
- +++ b/drivers/gpu/drm/panel/Makefile
- @@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
- obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
- obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
- obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
- +obj-$(CONFIG_DRM_PANEL_JDI_LPM062M326A) += panel-jdi-lpm062m326a.o
- obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
- obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
- obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o
- diff --git a/drivers/gpu/drm/panel/panel-jdi-lpm062m326a.c b/drivers/gpu/drm/panel/panel-jdi-lpm062m326a.c
- new file mode 100644
- index 0000000..dc46f3b
- --- /dev/null
- +++ b/drivers/gpu/drm/panel/panel-jdi-lpm062m326a.c
- @@ -0,0 +1,475 @@
- +/*
- + * Copyright (C) 2018 SwtcR <swtcr0@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/gpio/consumer.h>
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/regulator/consumer.h>
- +
- +#include <drm/drmP.h>
- +#include <drm/drm_crtc.h>
- +#include <drm/drm_mipi_dsi.h>
- +#include <drm/drm_panel.h>
- +
- +#include <video/mipi_display.h>
- +
- +#define SLEEPY 2
- +
- +struct jdi_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 {
- + u8 cmd;
- + int length;
- + u8 data[0x40];
- +};
- +
- +struct init_cmd init_cmds_0x10[] = {
- + { 0xb9, 3, { 0xff, 0x83, 0x94 }},
- + { 0xbd, 1, { 0x00 }},
- + { 0xd8, 0x18, { 0xaa, 0xaa, 0xaa, 0xeb, 0xaa, 0xaa,
- + 0xaa, 0xaa, 0xaa, 0xeb, 0xaa, 0xaa,
- + 0xaa, 0xaa, 0xaa, 0xeb, 0xaa, 0xaa,
- + 0xaa, 0xaa, 0xaa, 0xeb, 0xaa, 0xaa }},
- + { 0xbd, 1, { 0x01 }},
- + { 0xd8, 0x26, { 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 }},
- + { 0xbd, 1, { 0x02 }},
- + { 0xd8, 0xe, { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }},
- + { 0xbd, 1, { 0x00 }},
- + { 0xd9, 1, { 0x06 }},
- + { 0xb9, 3, { 0x00, 0x00, 0x00 }},
- + { 0x00, -1, { 0x00, }},
- +};
- +
- +static inline struct jdi_panel *to_jdi_panel(struct drm_panel *panel)
- +{
- + return container_of(panel, struct jdi_panel, base);
- +}
- +
- +static int jdi_panel_init(struct jdi_panel *jdi)
- +{
- + struct mipi_dsi_device *dsi = jdi->dsi;
- + int ret;
- + u8 display_id[3] = {0};
- + struct init_cmd *init_cmds = NULL;
- +
- + dsi->mode_flags |= MIPI_DSI_MODE_LPM;
- +
- + ret = mipi_dsi_set_maximum_return_packet_size(dsi, 3);
- + if (ret < 0)
- + return ret;
- +
- + ret = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_ID, display_id,
- + sizeof(display_id));
- + if (ret < 0) {
- + dev_err(&dsi->dev, "failed to read panel ID: %d\n", ret);
- + } else {
- + dev_info(&dsi->dev, "display ID[%d]: %02x %02x %02x\n",
- + ret, display_id[0], display_id[1], display_id[2]);
- + }
- +
- + switch (display_id[0]) {
- + case 0x10:
- + dev_info(&dsi->dev, "using init sequence for ID 0x10\n");
- + init_cmds = init_cmds_0x10;
- + break;
- + default:
- + dev_info(&dsi->dev, "unknown display, no extra init\n");
- + break;
- + }
- +
- + msleep(10 * SLEEPY);
- +
- + ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- + if (ret < 0)
- + return ret;
- +
- + while (init_cmds && init_cmds->length != -1) {
- + ret = mipi_dsi_dcs_write(dsi, init_cmds->cmd, init_cmds->data,
- + init_cmds->length);
- + if (ret < 0)
- + return ret;
- + init_cmds++;
- + }
- +
- + msleep(180 * SLEEPY);
- +
- + ret = mipi_dsi_dcs_set_column_address(dsi, 0,
- + jdi->mode->hdisplay - 1);
- + if (ret < 0)
- + return ret;
- +
- + ret = mipi_dsi_dcs_set_page_address(dsi, 0,
- + jdi->mode->vdisplay - 1);
- + if (ret < 0)
- + return ret;
- +
- + ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
- + if (ret < 0)
- + return ret;
- +
- +// ret = mipi_dsi_dcs_set_address_mode(dsi, false, false, false,
- +// false, false, false, false, false);
- +// if (ret < 0)
- +// return ret;
- +
- + ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT);
- + if (ret < 0)
- + return ret;
- +
- + return 0;
- +}
- +
- +static int jdi_panel_on(struct jdi_panel *jdi)
- +{
- + struct mipi_dsi_device *dsi = jdi->dsi;
- + int ret;
- +
- + dsi->mode_flags |= MIPI_DSI_MODE_LPM;
- +
- + ret = mipi_dsi_dcs_set_display_on(dsi);
- + if (ret < 0)
- + return ret;
- +
- + msleep(20 * SLEEPY);
- +
- + return 0;
- +}
- +
- +static int jdi_panel_off(struct jdi_panel *jdi)
- +{
- + struct mipi_dsi_device *dsi = jdi->dsi;
- + int ret;
- +
- + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- +
- + ret = mipi_dsi_dcs_set_display_off(dsi);
- + if (ret < 0)
- + return ret;
- +
- + ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- + if (ret < 0)
- + return ret;
- +
- + return 0;
- +}
- +
- +
- +static int jdi_panel_disable(struct drm_panel *panel)
- +{
- + struct jdi_panel *jdi = to_jdi_panel(panel);
- +
- + if (!jdi->enabled)
- + return 0;
- +
- + if (jdi->backlight) {
- + jdi->backlight->props.power = FB_BLANK_POWERDOWN;
- + backlight_update_status(jdi->backlight);
- + }
- +
- + jdi->enabled = false;
- +
- + return 0;
- +}
- +
- +static int jdi_panel_unprepare(struct drm_panel *panel)
- +{
- + struct jdi_panel *jdi = to_jdi_panel(panel);
- + int ret;
- +
- + if (!jdi->prepared)
- + return 0;
- +
- + ret = jdi_panel_off(jdi);
- + if (ret < 0) {
- + dev_err(panel->dev, "failed to set panel off: %d\n", ret);
- + return ret;
- + }
- +
- + if (jdi->reset_gpio)
- + gpiod_set_value(jdi->reset_gpio, 0);
- +
- + msleep(10 * SLEEPY);
- + regulator_disable(jdi->supply2);
- + msleep(10 * SLEEPY);
- + regulator_disable(jdi->supply1);
- +
- + jdi->prepared = false;
- +
- + return 0;
- +}
- +
- +static int jdi_panel_prepare(struct drm_panel *panel)
- +{
- + struct jdi_panel *jdi = to_jdi_panel(panel);
- + int ret;
- +
- + if (jdi->prepared)
- + return 0;
- +
- + ret = regulator_enable(jdi->supply1);
- + if (ret < 0)
- + return ret;
- + msleep(10 * SLEEPY);
- + ret = regulator_enable(jdi->supply2);
- + if (ret < 0)
- + goto poweroff1;
- + msleep(10 * SLEEPY);
- +
- + if (jdi->reset_gpio) {
- + gpiod_set_value(jdi->reset_gpio, 0);
- + msleep(10 * SLEEPY);
- + gpiod_set_value(jdi->reset_gpio, 1);
- + msleep(60 * SLEEPY);
- + }
- +
- + ret = jdi_panel_init(jdi);
- + if (ret < 0) {
- + dev_err(panel->dev, "failed to init panel: %d\n", ret);
- + goto reset;
- + }
- +
- + ret = jdi_panel_on(jdi);
- + if (ret < 0) {
- + dev_err(panel->dev, "failed to set panel on: %d\n", ret);
- + goto reset;
- + }
- +
- + jdi->prepared = true;
- +
- + return 0;
- +
- +reset:
- + if (jdi->reset_gpio)
- + gpiod_set_value(jdi->reset_gpio, 0);
- + regulator_disable(jdi->supply2);
- +poweroff1:
- + regulator_disable(jdi->supply1);
- + return ret;
- +}
- +
- +static int jdi_panel_enable(struct drm_panel *panel)
- +{
- + struct jdi_panel *jdi = to_jdi_panel(panel);
- +
- + if (jdi->enabled)
- + return 0;
- +
- + if (jdi->backlight) {
- + jdi->backlight->props.power = FB_BLANK_UNBLANK;
- + backlight_update_status(jdi->backlight);
- + }
- +
- + jdi->enabled = true;
- +
- + return 0;
- +}
- +
- +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,
- + .vrefresh = 60,
- +};
- +
- +static int jdi_panel_get_modes(struct drm_panel *panel)
- +{
- + struct drm_display_mode *mode;
- +
- + mode = drm_mode_duplicate(panel->drm, &default_mode);
- + if (!mode) {
- + dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
- + default_mode.hdisplay, default_mode.vdisplay,
- + default_mode.vrefresh);
- + return -ENOMEM;
- + }
- +
- + drm_mode_set_name(mode);
- +
- + drm_mode_probed_add(panel->connector, mode);
- +
- + panel->connector->display_info.width_mm = 77;
- + panel->connector->display_info.height_mm = 137;
- +
- + return 1;
- +}
- +
- +static const struct drm_panel_funcs jdi_panel_funcs = {
- + .disable = jdi_panel_disable,
- + .unprepare = jdi_panel_unprepare,
- + .prepare = jdi_panel_prepare,
- + .enable = jdi_panel_enable,
- + .get_modes = jdi_panel_get_modes,
- +};
- +
- +static int jdi_panel_add(struct jdi_panel *jdi)
- +{
- + struct device *dev = &jdi->dsi->dev;
- + struct device_node *np;
- + int ret;
- +
- + jdi->mode = &default_mode;
- +
- + jdi->supply1 = devm_regulator_get(dev, "vdd1");
- + if (IS_ERR(jdi->supply1))
- + return PTR_ERR(jdi->supply1);
- +
- + jdi->supply2 = devm_regulator_get(dev, "vdd2");
- + if (IS_ERR(jdi->supply2))
- + return PTR_ERR(jdi->supply2);
- +
- + jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
- + if (IS_ERR(jdi->reset_gpio)) {
- + dev_err(dev, "cannot get reset-gpios %ld\n",
- + PTR_ERR(jdi->reset_gpio));
- + jdi->reset_gpio = NULL;
- + } else {
- + gpiod_set_value(jdi->reset_gpio, 0);
- + }
- +
- + np = of_parse_phandle(dev->of_node, "backlight", 0);
- + if (np) {
- + jdi->backlight = of_find_backlight_by_node(np);
- + of_node_put(np);
- +
- + if (!jdi->backlight)
- + return -EPROBE_DEFER;
- + }
- +
- + drm_panel_init(&jdi->base);
- + jdi->base.funcs = &jdi_panel_funcs;
- + jdi->base.dev = &jdi->dsi->dev;
- +
- + ret = drm_panel_add(&jdi->base);
- + if (ret < 0)
- + goto put_backlight;
- +
- + return 0;
- +
- +put_backlight:
- + if (jdi->backlight)
- + put_device(&jdi->backlight->dev);
- +
- + return ret;
- +}
- +
- +static void jdi_panel_del(struct jdi_panel *jdi)
- +{
- + if (jdi->base.dev)
- + drm_panel_remove(&jdi->base);
- +
- + if (jdi->backlight)
- + put_device(&jdi->backlight->dev);
- +}
- +
- +static int jdi_panel_probe(struct mipi_dsi_device *dsi)
- +{
- + struct jdi_panel *jdi;
- + 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_EOT_PACKET;
- +
- + jdi = devm_kzalloc(&dsi->dev, sizeof(*jdi), GFP_KERNEL);
- + if (!jdi)
- + return -ENOMEM;
- +
- + mipi_dsi_set_drvdata(dsi, jdi);
- +
- + jdi->dsi = dsi;
- +
- + ret = jdi_panel_add(jdi);
- + if (ret < 0)
- + return ret;
- +
- + return mipi_dsi_attach(dsi);
- +}
- +
- +static int jdi_panel_remove(struct mipi_dsi_device *dsi)
- +{
- + struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
- + int ret;
- +
- + ret = jdi_panel_disable(&jdi->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);
- +
- + drm_panel_detach(&jdi->base);
- + jdi_panel_del(jdi);
- +
- + return 0;
- +}
- +
- +static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
- +{
- + struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
- +
- + jdi_panel_disable(&jdi->base);
- +}
- +
- +static const struct of_device_id jdi_of_match[] = {
- + { .compatible = "jdi,lpm062m326a", },
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, jdi_of_match);
- +
- +static struct mipi_dsi_driver jdi_panel_driver = {
- + .driver = {
- + .name = "panel-jdi-lpm062m326a",
- + .of_match_table = jdi_of_match,
- + },
- + .probe = jdi_panel_probe,
- + .remove = jdi_panel_remove,
- + .shutdown = jdi_panel_shutdown,
- +};
- +module_mipi_dsi_driver(jdi_panel_driver);
- +
- +MODULE_AUTHOR("SwtcR <swtcr0@gmail.com>");
- +MODULE_DESCRIPTION("JDI LPM062M326A (720x1280) panel driver");
- +MODULE_LICENSE("GPL v2");
- diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
- index 7afe2f6..9c4bb51 100644
- --- a/drivers/gpu/drm/tegra/drm.c
- +++ b/drivers/gpu/drm/tegra/drm.c
- @@ -11,6 +11,7 @@
- #include <linux/host1x.h>
- #include <linux/idr.h>
- #include <linux/iommu.h>
- +#include <linux/sync_file.h>
- #include <drm/drm_atomic.h>
- #include <drm/drm_atomic_helper.h>
- @@ -347,6 +348,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- struct drm_tegra_submit *args, struct drm_device *drm,
- struct drm_file *file)
- {
- + struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
- unsigned int num_cmdbufs = args->num_cmdbufs;
- unsigned int num_relocs = args->num_relocs;
- unsigned int num_waitchks = args->num_waitchks;
- @@ -355,7 +357,6 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- struct drm_tegra_waitchk __user *user_waitchks;
- struct drm_tegra_syncpt __user *user_syncpt;
- struct drm_tegra_syncpt syncpt;
- - struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
- struct drm_gem_object **refs;
- struct host1x_syncpt *sp;
- struct host1x_job *job;
- @@ -375,6 +376,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- if (args->num_waitchks != 0)
- return -EINVAL;
- + /* Check for unrecognized flags */
- + if (args->flags & ~DRM_TEGRA_SUBMIT_FLAGS)
- + return -EINVAL;
- +
- job = host1x_job_alloc(context->channel, args->num_cmdbufs,
- args->num_relocs, args->num_waitchks);
- if (!job)
- @@ -386,6 +391,14 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- job->class = context->client->base.class;
- job->serialize = true;
- + if (args->flags & DRM_TEGRA_SUBMIT_WAIT_FENCE_FD) {
- + job->prefence = sync_file_get_fence(args->fence);
- + if (!job->prefence) {
- + err = -ENOENT;
- + goto put;
- + }
- + }
- +
- /*
- * Track referenced BOs so that they can be unreferenced after the
- * submission is complete.
- @@ -409,7 +422,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- if (copy_from_user(&cmdbuf, user_cmdbufs, sizeof(cmdbuf))) {
- err = -EFAULT;
- - goto fail;
- + goto put_bos;
- }
- /*
- @@ -418,13 +431,13 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- */
- if (cmdbuf.words > CDMA_GATHER_FETCHES_MAX_NB) {
- err = -EINVAL;
- - goto fail;
- + goto put_bos;
- }
- bo = host1x_bo_lookup(file, cmdbuf.handle);
- if (!bo) {
- err = -ENOENT;
- - goto fail;
- + goto put_bos;
- }
- offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32);
- @@ -438,7 +451,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- */
- if (offset & 3 || offset >= obj->gem.size) {
- err = -EINVAL;
- - goto fail;
- + goto put_bos;
- }
- host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
- @@ -455,7 +468,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- &user_relocs[num_relocs], drm,
- file);
- if (err < 0)
- - goto fail;
- + goto put_bos;
- reloc = &job->relocarray[num_relocs];
- obj = host1x_to_tegra_bo(reloc->cmdbuf.bo);
- @@ -469,7 +482,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- if (reloc->cmdbuf.offset & 3 ||
- reloc->cmdbuf.offset >= obj->gem.size) {
- err = -EINVAL;
- - goto fail;
- + goto put_bos;
- }
- obj = host1x_to_tegra_bo(reloc->target.bo);
- @@ -477,7 +490,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- if (reloc->target.offset >= obj->gem.size) {
- err = -EINVAL;
- - goto fail;
- + goto put_bos;
- }
- }
- @@ -489,7 +502,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- err = host1x_waitchk_copy_from_user(
- wait, &user_waitchks[num_waitchks], file);
- if (err < 0)
- - goto fail;
- + goto put_bos;
- obj = host1x_to_tegra_bo(wait->bo);
- refs[num_refs++] = &obj->gem;
- @@ -501,20 +514,20 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- if (wait->offset & 3 ||
- wait->offset >= obj->gem.size) {
- err = -EINVAL;
- - goto fail;
- + goto put_bos;
- }
- }
- if (copy_from_user(&syncpt, user_syncpt, sizeof(syncpt))) {
- err = -EFAULT;
- - goto fail;
- + goto put_bos;
- }
- /* check whether syncpoint ID is valid */
- sp = host1x_syncpt_get(host1x, syncpt.id);
- if (!sp) {
- err = -ENOENT;
- - goto fail;
- + goto put_bos;
- }
- job->is_addr_reg = context->client->ops->is_addr_reg;
- @@ -528,23 +541,60 @@ int tegra_drm_submit(struct tegra_drm_context *context,
- err = host1x_job_pin(job, context->client->base.dev);
- if (err)
- - goto fail;
- + goto put_bos;
- err = host1x_job_submit(job);
- if (err) {
- host1x_job_unpin(job);
- - goto fail;
- + goto put_bos;
- }
- - args->fence = job->syncpt_end;
- + if (args->flags & DRM_TEGRA_SUBMIT_CREATE_FENCE_FD) {
- + struct host1x_syncpt *syncpt;
- + struct dma_fence *fence;
- + struct sync_file *file;
- +
- + syncpt = host1x_syncpt_get(host1x, job->syncpt_id);
- + if (!syncpt) {
- + err = -EINVAL;
- + goto put_bos;
- + }
- -fail:
- + fence = host1x_fence_create(host1x, syncpt, job->syncpt_end);
- + if (!fence) {
- + err = -ENOMEM;
- + goto put_bos;
- + }
- +
- + file = sync_file_create(fence);
- + if (!file) {
- + dma_fence_put(fence);
- + err = -ENOMEM;
- + goto put_bos;
- + }
- +
- + err = get_unused_fd_flags(O_CLOEXEC);
- + if (err < 0) {
- + dma_fence_put(fence);
- + goto put_bos;
- + }
- +
- + fd_install(err, file->file);
- + args->fence = err;
- + } else {
- + args->fence = job->syncpt_end;
- + }
- +
- +put_bos:
- while (num_refs--)
- drm_gem_object_put_unlocked(refs[num_refs]);
- kfree(refs);
- put:
- + if (job->prefence)
- + dma_fence_put(job->prefence);
- +
- host1x_job_put(job);
- return err;
- }
- diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
- index 87c5d89..0ff4c39 100644
- --- a/drivers/gpu/drm/tegra/dsi.c
- +++ b/drivers/gpu/drm/tegra/dsi.c
- @@ -321,7 +321,7 @@ static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = {
- /*
- * non-burst mode with sync events
- */
- -static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
- +static const u32 pkt_seq_video_non_burst_sync_events_eotp[NUM_PKT_SEQ] = {
- [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
- PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
- PKT_LP,
- @@ -348,6 +348,32 @@ static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
- [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
- };
- +/*
- + * non-burst mode with sync events
- + */
- +static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
- + [ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
- + PKT_LP,
- + [ 1] = 0,
- + [ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
- + PKT_LP,
- + [ 3] = 0,
- + [ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
- + PKT_LP,
- + [ 5] = 0,
- + [ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
- + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
- + PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
- + [ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
- + [ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
- + PKT_LP,
- + [ 9] = 0,
- + [10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
- + PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
- + PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
- + [11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
- +};
- +
- static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = {
- [ 0] = 0,
- [ 1] = 0,
- @@ -505,8 +531,13 @@ static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
- DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n");
- pkt_seq = pkt_seq_video_non_burst_sync_pulses;
- } else if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
- - DRM_DEBUG_KMS("Non-burst video mode with sync events\n");
- - pkt_seq = pkt_seq_video_non_burst_sync_events;
- + if (!(dsi->flags & MIPI_DSI_MODE_EOT_PACKET)) {
- + DRM_DEBUG_KMS("Non-burst video mode with sync events and EOTp\n");
- + pkt_seq = pkt_seq_video_non_burst_sync_events_eotp;
- + } else {
- + DRM_DEBUG_KMS("Non-burst video mode with sync events\n");
- + pkt_seq = pkt_seq_video_non_burst_sync_events;
- + }
- } else {
- DRM_DEBUG_KMS("Command mode\n");
- pkt_seq = pkt_seq_command_mode;
- diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
- index 7d2a955..c472578 100644
- --- a/drivers/gpu/drm/tegra/sor.c
- +++ b/drivers/gpu/drm/tegra/sor.c
- @@ -342,7 +342,7 @@ struct tegra_sor {
- struct drm_info_list *debugfs_files;
- const struct tegra_sor_ops *ops;
- - enum tegra_io_pad pad;
- + unsigned int pad;
- /* for HDMI 2.0 */
- struct tegra_sor_hdmi_settings *settings;
- diff --git a/drivers/gpu/host1x/Kconfig b/drivers/gpu/host1x/Kconfig
- index 9191632..e41032e 100644
- --- a/drivers/gpu/host1x/Kconfig
- +++ b/drivers/gpu/host1x/Kconfig
- @@ -1,6 +1,7 @@
- config TEGRA_HOST1X
- tristate "NVIDIA Tegra host1x driver"
- depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
- + select DMA_SHARED_BUFFER
- select IOMMU_IOVA if IOMMU_SUPPORT
- help
- Driver for the NVIDIA Tegra host1x hardware.
- diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
- index b92016c..ae3a6ed 100644
- --- a/drivers/gpu/host1x/Makefile
- +++ b/drivers/gpu/host1x/Makefile
- @@ -9,6 +9,7 @@ host1x-y = \
- job.o \
- debug.o \
- mipi.o \
- + fence.o \
- hw/host1x01.o \
- hw/host1x02.o \
- hw/host1x04.o \
- diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
- index 43e9fab..c9071c9 100644
- --- a/drivers/gpu/host1x/dev.h
- +++ b/drivers/gpu/host1x/dev.h
- @@ -1,5 +1,5 @@
- /*
- - * Copyright (c) 2012-2015, NVIDIA Corporation.
- + * Copyright (C) 2012-2016 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,
- @@ -42,6 +42,7 @@ struct host1x_channel_ops {
- int (*init)(struct host1x_channel *channel, struct host1x *host,
- unsigned int id);
- int (*submit)(struct host1x_job *job);
- + void (*push_wait)(struct host1x_channel *ch, u32 id, u32 thresh);
- };
- struct host1x_cdma_ops {
- @@ -117,6 +118,8 @@ struct host1x {
- struct clk *clk;
- struct reset_control *rst;
- + u64 fence_ctx_base;
- +
- struct iommu_group *group;
- struct iommu_domain *domain;
- struct iova_domain iova;
- @@ -250,6 +253,13 @@ static inline int host1x_hw_channel_submit(struct host1x *host,
- return host->channel_op->submit(job);
- }
- +static inline void host1x_hw_channel_push_wait(struct host1x *host,
- + struct host1x_channel *channel,
- + u32 id, u32 thresh)
- +{
- + host->channel_op->push_wait(channel, id, thresh);
- +}
- +
- static inline void host1x_hw_cdma_start(struct host1x *host,
- struct host1x_cdma *cdma)
- {
- diff --git a/drivers/gpu/host1x/fence.c b/drivers/gpu/host1x/fence.c
- new file mode 100644
- index 0000000..3b05662
- --- /dev/null
- +++ b/drivers/gpu/host1x/fence.c
- @@ -0,0 +1,202 @@
- +/*
- + * Copyright (C) 2016 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/dma-fence.h>
- +#include <linux/dma-fence-array.h>
- +#include <linux/slab.h>
- +
- +#include "fence.h"
- +#include "intr.h"
- +#include "syncpt.h"
- +#include "cdma.h"
- +#include "channel.h"
- +#include "dev.h"
- +
- +struct host1x_fence {
- + struct dma_fence base;
- + spinlock_t lock;
- +
- + struct host1x_syncpt *syncpt;
- + u32 threshold;
- +
- + struct host1x *host;
- + void *waiter;
- +
- + char timeline_name[10];
- +};
- +
- +static inline struct host1x_fence *to_host1x_fence(struct dma_fence *fence)
- +{
- + return (struct host1x_fence *)fence;
- +}
- +
- +static const char *host1x_fence_get_driver_name(struct dma_fence *fence)
- +{
- + return "host1x";
- +}
- +
- +static const char *host1x_fence_get_timeline_name(struct dma_fence *fence)
- +{
- + struct host1x_fence *f = to_host1x_fence(fence);
- +
- + return f->timeline_name;
- +}
- +
- +static bool host1x_fence_enable_signaling(struct dma_fence *fence)
- +{
- + struct host1x_fence *f = to_host1x_fence(fence);
- +
- + if (host1x_syncpt_is_expired(f->syncpt, f->threshold))
- + return false;
- +
- + return true;
- +}
- +
- +static bool host1x_fence_signaled(struct dma_fence *fence)
- +{
- + struct host1x_fence *f = to_host1x_fence(fence);
- +
- + return host1x_syncpt_is_expired(f->syncpt, f->threshold);
- +}
- +
- +static void host1x_fence_release(struct dma_fence *fence)
- +{
- + struct host1x_fence *f = to_host1x_fence(fence);
- +
- + if (f->waiter)
- + host1x_intr_put_ref(f->host, f->syncpt->id, f->waiter);
- +
- + kfree(f);
- +}
- +
- +const struct dma_fence_ops host1x_fence_ops = {
- + .get_driver_name = host1x_fence_get_driver_name,
- + .get_timeline_name = host1x_fence_get_timeline_name,
- + .enable_signaling = host1x_fence_enable_signaling,
- + .signaled = host1x_fence_signaled,
- + .wait = dma_fence_default_wait,
- + .release = host1x_fence_release,
- +};
- +
- +static void host1x_fence_wait_single(struct host1x_fence *f,
- + struct host1x *host,
- + struct host1x_channel *ch)
- +{
- + if (host1x_syncpt_is_expired(f->syncpt, f->threshold))
- + return;
- +
- + host1x_hw_channel_push_wait(host, ch, f->syncpt->id, f->threshold);
- +}
- +
- +/**
- + * host1x_fence_is_waitable() - Check if DMA fence can be waited by hardware
- + * @fence: DMA fence
- + *
- + * Check is @fence is only backed by Host1x syncpoints and can therefore be
- + * waited using only hardware.
- + */
- +bool host1x_fence_is_waitable(struct dma_fence *fence)
- +{
- + struct dma_fence_array *array;
- + int i;
- +
- + array = to_dma_fence_array(fence);
- + if (!array)
- + return fence->ops == &host1x_fence_ops;
- +
- + for (i = 0; i < array->num_fences; ++i) {
- + if (array->fences[i]->ops != &host1x_fence_ops)
- + return false;
- + }
- +
- + return true;
- +}
- +
- +/**
- + * host1x_fence_wait() - Insert waits for fence into channel
- + * @fence: DMA fence
- + * @host: Host1x
- + * @ch: Host1x channel
- + *
- + * Inserts wait commands into Host1x channel fences in @fence.
- + * in @fence. @fence must only consist of syncpoint-backed fences.
- + *
- + * Return: 0 on success, -errno otherwise.
- + */
- +int host1x_fence_wait(struct dma_fence *fence, struct host1x *host,
- + struct host1x_channel *ch)
- +{
- + struct dma_fence_array *array;
- + int i = 0;
- +
- + if (!host1x_fence_is_waitable(fence))
- + return -EINVAL;
- +
- + array = to_dma_fence_array(fence);
- + if (!array) {
- + host1x_fence_wait_single(to_host1x_fence(fence), host, ch);
- + return 0;
- + }
- +
- + for (i = 0; i < array->num_fences; ++i) {
- + host1x_fence_wait_single(to_host1x_fence(array->fences[i]),
- + host, ch);
- + }
- +
- + return 0;
- +}
- +
- +struct dma_fence *host1x_fence_create(struct host1x *host,
- + struct host1x_syncpt *syncpt,
- + u32 threshold)
- +{
- + struct host1x_waitlist *waiter;
- + struct host1x_fence *f;
- + int err;
- +
- + f = kzalloc(sizeof(*f), GFP_KERNEL);
- + if (!f)
- + return NULL;
- +
- + waiter = kzalloc(sizeof(*waiter), GFP_KERNEL);
- + if (!waiter) {
- + kfree(f);
- + return NULL;
- + }
- +
- + f->host = host;
- + f->syncpt = syncpt;
- + f->threshold = threshold;
- + f->waiter = NULL;
- + snprintf(f->timeline_name, ARRAY_SIZE(f->timeline_name),
- + "%d", syncpt->id);
- +
- + spin_lock_init(&f->lock);
- + dma_fence_init(&f->base, &host1x_fence_ops, &f->lock,
- + host->fence_ctx_base + syncpt->id, threshold);
- +
- + err = host1x_intr_add_action(f->host, f->syncpt->id, f->threshold,
- + HOST1X_INTR_ACTION_SIGNAL_FENCE, f,
- + waiter, &f->waiter);
- + if (err) {
- + kfree(waiter);
- + dma_fence_put((struct dma_fence *)f);
- + return NULL;
- + }
- +
- + return (struct dma_fence *)f;
- +}
- +EXPORT_SYMBOL(host1x_fence_create);
- diff --git a/drivers/gpu/host1x/fence.h b/drivers/gpu/host1x/fence.h
- new file mode 100644
- index 0000000..5725c95
- --- /dev/null
- +++ b/drivers/gpu/host1x/fence.h
- @@ -0,0 +1,28 @@
- +/*
- + * Copyright (C) 2016 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 __HOST1X_FENCE_H
- +#define __HOST1X_FENCE_H
- +
- +struct host1x;
- +struct host1x_channel;
- +struct dma_fence;
- +
- +bool host1x_fence_is_waitable(struct dma_fence *fence);
- +int host1x_fence_wait(struct dma_fence *fence, struct host1x *host,
- + struct host1x_channel *ch);
- +
- +#endif
- diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
- index 9af7587..d438289 100644
- --- a/drivers/gpu/host1x/hw/channel_hw.c
- +++ b/drivers/gpu/host1x/hw/channel_hw.c
- @@ -1,7 +1,7 @@
- /*
- * Tegra host1x Channel
- *
- - * Copyright (c) 2010-2013, NVIDIA Corporation.
- + * Copyright (C) 2010-2016 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,
- @@ -16,6 +16,7 @@
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- +#include <linux/dma-fence.h>
- #include <linux/host1x.h>
- #include <linux/slab.h>
- @@ -23,6 +24,7 @@
- #include "../channel.h"
- #include "../dev.h"
- +#include "../fence.h"
- #include "../intr.h"
- #include "../job.h"
- @@ -68,11 +70,26 @@ static void submit_gathers(struct host1x_job *job)
- u32 op1 = host1x_opcode_gather(g->words);
- u32 op2 = g->base + g->offset;
- + /* add a setclass for modules that require it */
- + if (job->class)
- + host1x_cdma_push(cdma,
- + host1x_opcode_setclass(job->class, 0, 0),
- + HOST1X_OPCODE_NOP);
- +
- trace_write_gather(cdma, g->bo, g->offset, op1 & 0xffff);
- host1x_cdma_push(cdma, op1, op2);
- }
- }
- +static void channel_push_wait(struct host1x_channel *channel,
- + u32 id, u32 thresh)
- +{
- + host1x_cdma_push(&channel->cdma,
- + host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
- + host1x_uclass_wait_syncpt_r(), 1),
- + host1x_class_host_wait_syncpt(id, thresh));
- +}
- +
- static inline void synchronize_syncpt_base(struct host1x_job *job)
- {
- struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
- @@ -110,6 +127,16 @@ static int channel_submit(struct host1x_job *job)
- /* before error checks, return current max */
- prev_max = job->syncpt_end = host1x_syncpt_read_max(sp);
- + if (job->prefence) {
- + if (host1x_fence_is_waitable(job->prefence)) {
- + host1x_fence_wait(job->prefence, host, job->channel);
- + } else {
- + err = dma_fence_wait(job->prefence, true);
- + if (err)
- + goto error;
- + }
- + }
- +
- /* get submit lock */
- err = mutex_lock_interruptible(&ch->submitlock);
- if (err)
- @@ -151,12 +178,6 @@ static int channel_submit(struct host1x_job *job)
- job->syncpt_end = syncval;
- - /* add a setclass for modules that require it */
- - if (job->class)
- - host1x_cdma_push(&ch->cdma,
- - host1x_opcode_setclass(job->class, 0, 0),
- - HOST1X_OPCODE_NOP);
- -
- submit_gathers(job);
- /* end CDMA submit & stash pinned hMems into sync queue */
- @@ -212,4 +233,5 @@ static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev,
- static const struct host1x_channel_ops host1x_channel_ops = {
- .init = host1x_channel_init,
- .submit = channel_submit,
- + .push_wait = channel_push_wait
- };
- diff --git a/drivers/gpu/host1x/intr.c b/drivers/gpu/host1x/intr.c
- index 8b4fad0..b3d5128 100644
- --- a/drivers/gpu/host1x/intr.c
- +++ b/drivers/gpu/host1x/intr.c
- @@ -1,7 +1,7 @@
- /*
- * Tegra host1x Interrupt Management
- *
- - * Copyright (c) 2010-2013, NVIDIA Corporation.
- + * Copyright (C) 2010-2016 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,
- @@ -17,6 +17,7 @@
- */
- #include <linux/clk.h>
- +#include <linux/dma-fence.h>
- #include <linux/interrupt.h>
- #include <linux/slab.h>
- #include <linux/irq.h>
- @@ -133,12 +134,20 @@ static void action_wakeup_interruptible(struct host1x_waitlist *waiter)
- wake_up_interruptible(wq);
- }
- +static void action_signal_fence(struct host1x_waitlist *waiter)
- +{
- + struct dma_fence *fence = waiter->data;
- +
- + dma_fence_signal(fence);
- +}
- +
- typedef void (*action_handler)(struct host1x_waitlist *waiter);
- static const action_handler action_handlers[HOST1X_INTR_ACTION_COUNT] = {
- action_submit_complete,
- action_wakeup,
- action_wakeup_interruptible,
- + action_signal_fence
- };
- static void run_handlers(struct list_head completed[HOST1X_INTR_ACTION_COUNT])
- diff --git a/drivers/gpu/host1x/intr.h b/drivers/gpu/host1x/intr.h
- index 1370c2b..6b2c090 100644
- --- a/drivers/gpu/host1x/intr.h
- +++ b/drivers/gpu/host1x/intr.h
- @@ -1,7 +1,7 @@
- /*
- * Tegra host1x Interrupt Management
- *
- - * Copyright (c) 2010-2013, NVIDIA Corporation.
- + * Copyright (C) 2010-2016 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,
- @@ -43,6 +43,12 @@ enum host1x_intr_action {
- */
- HOST1X_INTR_ACTION_WAKEUP_INTERRUPTIBLE,
- + /*
- + * Signal a dma fence.
- + * 'data' points to a host1x_fence
- + */
- + HOST1X_INTR_ACTION_SIGNAL_FENCE,
- +
- HOST1X_INTR_ACTION_COUNT
- };
- diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
- index a2a952a..652803b 100644
- --- a/drivers/gpu/host1x/syncpt.c
- +++ b/drivers/gpu/host1x/syncpt.c
- @@ -18,6 +18,7 @@
- #include <linux/module.h>
- #include <linux/device.h>
- +#include <linux/dma-fence.h>
- #include <linux/slab.h>
- #include <trace/events/host1x.h>
- @@ -413,6 +414,7 @@ int host1x_syncpt_init(struct host1x *host)
- mutex_init(&host->syncpt_mutex);
- host->syncpt = syncpt;
- host->bases = bases;
- + host->fence_ctx_base = dma_fence_context_alloc(host->info->nb_pts);
- host1x_syncpt_restore(host);
- host1x_hw_syncpt_enable_protection(host);
- diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
- index 6ec307c..5772de1 100644
- --- a/drivers/hwmon/Kconfig
- +++ b/drivers/hwmon/Kconfig
- @@ -1291,7 +1291,7 @@ source drivers/hwmon/pmbus/Kconfig
- config SENSORS_PWM_FAN
- tristate "PWM fan"
- - depends on (PWM && OF) || COMPILE_TEST
- + depends on (PWM && OF && GPIOLIB && OF_GPIO) || COMPILE_TEST
- depends on THERMAL || THERMAL=n
- help
- If you say yes here you get support for fans connected to PWM lines.
- diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
- index 70cc0d1..c0cf501 100644
- --- a/drivers/hwmon/pwm-fan.c
- +++ b/drivers/hwmon/pwm-fan.c
- @@ -18,6 +18,7 @@
- #include <linux/hwmon.h>
- #include <linux/hwmon-sysfs.h>
- +#include <linux/gpio/consumer.h>
- #include <linux/module.h>
- #include <linux/mutex.h>
- #include <linux/of.h>
- @@ -31,6 +32,7 @@
- struct pwm_fan_ctx {
- struct mutex lock;
- struct pwm_device *pwm;
- + struct gpio_desc *enable_gpio;
- unsigned int pwm_value;
- unsigned int pwm_fan_state;
- unsigned int pwm_fan_max_state;
- @@ -56,6 +58,10 @@ static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
- ret = pwm_apply_state(ctx->pwm, &state);
- if (!ret)
- ctx->pwm_value = pwm;
- +
- + if (ctx->enable_gpio)
- + gpiod_set_value(ctx->enable_gpio, !!pwm);
- +
- exit_set_pwm_err:
- mutex_unlock(&ctx->lock);
- return ret;
- @@ -240,6 +246,13 @@ static int pwm_fan_probe(struct platform_device *pdev)
- return ret;
- }
- + ctx->enable_gpio = devm_gpiod_get(&pdev->dev, "enable", GPIOD_OUT_HIGH);
- + if (IS_ERR(ctx->enable_gpio)) {
- + ctx->enable_gpio = NULL;
- + } else {
- + gpiod_set_value(ctx->enable_gpio, 1);
- + }
- +
- hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan",
- ctx, pwm_fan_groups);
- if (IS_ERR(hwmon)) {
- diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
- index 074e506..c1f181e 100644
- --- a/drivers/iio/light/Kconfig
- +++ b/drivers/iio/light/Kconfig
- @@ -63,6 +63,16 @@ config APDS9960
- To compile this driver as a module, choose M here: the
- module will be called apds9960
- +config BH1730
- + tristate "ROHM BH1730 ambient light sensor"
- + depends on I2C
- + help
- + Say Y here to build support for the ROHM BH1730FVC ambient
- + light sensor.
- +
- + To compile this driver as a module, choose M here: the module will
- + be called bh1730.
- +
- config BH1750
- tristate "ROHM BH1750 ambient light sensor"
- depends on I2C
- diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
- index f177703..ee04d37 100644
- --- a/drivers/iio/light/Makefile
- +++ b/drivers/iio/light/Makefile
- @@ -9,6 +9,7 @@ obj-$(CONFIG_ADJD_S311) += adjd_s311.o
- obj-$(CONFIG_AL3320A) += al3320a.o
- obj-$(CONFIG_APDS9300) += apds9300.o
- obj-$(CONFIG_APDS9960) += apds9960.o
- +obj-$(CONFIG_BH1730) += bh1730.o
- obj-$(CONFIG_BH1750) += bh1750.o
- obj-$(CONFIG_BH1780) += bh1780.o
- obj-$(CONFIG_CM32181) += cm32181.o
- diff --git a/drivers/iio/light/bh1730.c b/drivers/iio/light/bh1730.c
- new file mode 100644
- index 0000000..e79e055
- --- /dev/null
- +++ b/drivers/iio/light/bh1730.c
- @@ -0,0 +1,435 @@
- +// SPDX-License-Identifier: GPL-2.0
- +/*
- + * ROHM BH1730 ambient light sensor driver
- + *
- + * Copyright (c) 2018 Google, Inc.
- + * Author: Pierre Bourdon <delroth@google.com>
- + *
- + * Based on a previous non-iio BH1730FVC driver:
- + * Copyright (C) 2012 Samsung Electronics. All rights reserved.
- + * Author: Won Huh <won.huh@samsung.com>
- + *
- + * Data sheets:
- + * http://www.rohm.com/web/global/datasheet/BH1730FVC/bh1730fvc-e
- + */
- +
- +#include <linux/delay.h>
- +#include <linux/i2c.h>
- +#include <linux/iio/iio.h>
- +#include <linux/module.h>
- +#include <linux/of.h>
- +#include <linux/time.h>
- +
- +#define BH1730_CMD_BIT BIT(7)
- +
- +#define BH1730_REG_CONTROL 0x00
- +#define BH1730_REG_TIMING 0x01
- +#define BH1730_REG_INTERRUPT 0x02
- +#define BH1730_REG_THLLOW 0x03
- +#define BH1730_REG_THLHIGH 0x04
- +#define BH1730_REG_THHLOW 0x05
- +#define BH1730_REG_THHHIGH 0x06
- +#define BH1730_REG_GAIN 0x07
- +#define BH1730_REG_ID 0x12
- +#define BH1730_REG_DATA0LOW 0x14
- +#define BH1730_REG_DATA0HIGH 0x15
- +#define BH1730_REG_DATA1LOW 0x16
- +#define BH1730_REG_DATA1HIGH 0x17
- +
- +#define BH1730_CONTROL_POWER_ON BIT(0)
- +#define BH1730_CONTROL_MEASURE BIT(1)
- +
- +#define BH1730_INTERNAL_CLOCK_NS 2800
- +
- +#define BH1730_DEFAULT_INTEG_MS 150
- +
- +enum bh1730_gain {
- + BH1730_GAIN_1X = 0,
- + BH1730_GAIN_2X,
- + BH1730_GAIN_64X,
- + BH1730_GAIN_128X,
- +};
- +#define BH1730_MAX_GAIN_MULTIPLIER 128
- +
- +struct bh1730_data {
- + struct i2c_client *client;
- + enum bh1730_gain gain;
- + int itime;
- +};
- +
- +static int bh1730_read_word(struct bh1730_data *bh1730, u8 reg)
- +{
- + int ret = i2c_smbus_read_word_data(bh1730->client,
- + BH1730_CMD_BIT | reg);
- + if (ret < 0)
- + dev_err(&bh1730->client->dev,
- + "i2c read failed error %d, register %01x\n",
- + ret, reg);
- +
- + return ret;
- +}
- +
- +static int bh1730_write(struct bh1730_data *bh1730, u8 reg, u8 val)
- +{
- + int ret = i2c_smbus_write_byte_data(bh1730->client,
- + BH1730_CMD_BIT | reg,
- + val);
- + if (ret < 0)
- + dev_err(&bh1730->client->dev,
- + "i2c write failed error %d, register %01x\n",
- + ret, reg);
- +
- + return ret;
- +}
- +
- +static int gain_setting_to_multiplier(enum bh1730_gain gain)
- +{
- + switch (gain) {
- + case BH1730_GAIN_1X:
- + return 1;
- + case BH1730_GAIN_2X:
- + return 2;
- + case BH1730_GAIN_64X:
- + return 64;
- + case BH1730_GAIN_128X:
- + return 128;
- + default:
- + return -EINVAL;
- + }
- +}
- +
- +static int bh1730_gain_multiplier(struct bh1730_data *bh1730)
- +{
- + int multiplier = gain_setting_to_multiplier(bh1730->gain);
- +
- + if (multiplier < 0) {
- + dev_warn(&bh1730->client->dev,
- + "invalid gain multiplier settings: %d\n",
- + bh1730->gain);
- + bh1730->gain = BH1730_GAIN_1X;
- + multiplier = 1;
- + }
- +
- + return multiplier;
- +}
- +
- +static int bh1730_itime_us(struct bh1730_data *bh1730)
- +{
- + return (BH1730_INTERNAL_CLOCK_NS * 964 * (256 - bh1730->itime))
- + / NSEC_PER_USEC;
- +}
- +
- +static int bh1730_set_gain(struct bh1730_data *bh1730, enum bh1730_gain gain)
- +{
- + int ret = bh1730_write(bh1730, BH1730_REG_GAIN, gain);
- +
- + if (ret < 0)
- + return ret;
- +
- + bh1730->gain = gain;
- +
- + return 0;
- +}
- +
- +static int bh1730_set_integration_time_ms(struct bh1730_data *bh1730,
- + int time_ms)
- +{
- + int ret, time_ns, itime;
- +
- + /* Prefilter obviously invalid time_ms values that would overflow. */
- + if (time_ms <= 0 || time_ms > 1000) {
- + goto out_of_range;
- + }
- +
- + time_ns = time_ms * (u64)NSEC_PER_MSEC;
- + itime = 256 - DIV_ROUND_CLOSEST(time_ns,
- + BH1730_INTERNAL_CLOCK_NS * 964);
- +
- + /* ITIME == 0 is reserved for manual integration mode. */
- + if (itime <= 0 || itime > 255) {
- + goto out_of_range;
- + }
- +
- + ret = bh1730_write(bh1730, BH1730_REG_TIMING, itime);
- + if (ret < 0)
- + return ret;
- +
- + bh1730->itime = itime;
- +
- + return 0;
- +
- +out_of_range:
- + dev_warn(&bh1730->client->dev, "integration time out of range: %dms\n",
- + time_ms);
- +
- + return -ERANGE;
- +}
- +
- +static void bh1730_wait_for_next_measurement(struct bh1730_data *bh1730)
- +{
- + udelay(bh1730_itime_us(bh1730) +
- + DIV_ROUND_UP(BH1730_INTERNAL_CLOCK_NS * 714, NSEC_PER_USEC));
- +}
- +
- +static int bh1730_adjust_gain(struct bh1730_data *bh1730)
- +{
- + int visible, ir, highest, gain, ret, i;
- +
- + visible = bh1730_read_word(bh1730, BH1730_REG_DATA0LOW);
- + if (visible < 0)
- + return visible;
- +
- + ir = bh1730_read_word(bh1730, BH1730_REG_DATA1LOW);
- + if (ir < 0)
- + return ir;
- +
- + highest = max(visible, ir);
- +
- + /*
- + * If the read value is being clamped, assume the worst and go to the
- + * lowest possible gain. The alternative is doing multiple
- + * recalibrations, which would be slower and have the same effect.
- + */
- + if (highest == USHRT_MAX)
- + gain = 1;
- + else
- + gain = bh1730_gain_multiplier(bh1730);
- +
- + highest = (highest * BH1730_MAX_GAIN_MULTIPLIER) / gain;
- +
- + /*
- + * Find the lowest gain multiplier which puts the measured values
- + * above 1024. This threshold is chosen to match the gap between 2X
- + * multiplier and 64X (next available) while keeping some margin.
- + */
- + for (i = BH1730_GAIN_1X; i < BH1730_GAIN_128X; ++i) {
- + int adj = highest * gain_setting_to_multiplier(i) /
- + BH1730_MAX_GAIN_MULTIPLIER;
- +
- + if (adj >= 1024)
- + break;
- + }
- +
- + if (i != bh1730->gain) {
- + ret = bh1730_set_gain(bh1730, i);
- + if (ret < 0)
- + return ret;
- +
- + bh1730_wait_for_next_measurement(bh1730);
- + }
- +
- + return 0;
- +}
- +
- +static int bh1730_get_millilux(struct bh1730_data *bh1730)
- +{
- + int visible, ir, visible_coef, ir_coef;
- + u64 millilux;
- +
- + visible = bh1730_read_word(bh1730, BH1730_REG_DATA0LOW);
- + if (visible < 0)
- + return visible;
- +
- + ir = bh1730_read_word(bh1730, BH1730_REG_DATA1LOW);
- + if (ir < 0)
- + return ir;
- +
- + if (ir * 1000 / visible < 500) {
- + visible_coef = 5002;
- + ir_coef = 7502;
- + } else if (ir * 1000 / visible < 754) {
- + visible_coef = 2250;
- + ir_coef = 2000;
- + } else if (ir * 1000 / visible < 1029) {
- + visible_coef = 1999;
- + ir_coef = 1667;
- + } else if (ir * 1000 / visible < 1373) {
- + visible_coef = 885;
- + ir_coef = 583;
- + } else if (ir * 1000 / visible < 1879) {
- + visible_coef = 309;
- + ir_coef = 165;
- + } else {
- + return 0;
- + }
- +
- + millilux = 103ULL * (visible_coef * visible - ir_coef * ir);
- + millilux *= USEC_PER_MSEC;
- + do_div(millilux, bh1730_itime_us(bh1730));
- + do_div(millilux, bh1730_gain_multiplier(bh1730));
- +
- + /*
- + * Overflow here can only happen in extreme conditions:
- + * - Completely saturated visible light sensor and no measured IR.
- + * - Integration time < 16ms (driver currently defaults to 150ms).
- + */
- + if (millilux > INT_MAX)
- + return -ERANGE;
- +
- + return (int)millilux;
- +}
- +
- +static int bh1730_power_on(struct bh1730_data *bh1730)
- +{
- + return bh1730_write(bh1730, BH1730_REG_CONTROL,
- + BH1730_CONTROL_POWER_ON | BH1730_CONTROL_MEASURE);
- +}
- +
- +static int bh1730_set_defaults(struct bh1730_data *bh1730)
- +{
- + int ret;
- +
- + ret = bh1730_set_gain(bh1730, BH1730_GAIN_1X);
- + if (ret < 0)
- + return ret;
- +
- + ret = bh1730_set_integration_time_ms(bh1730, BH1730_DEFAULT_INTEG_MS);
- + if (ret < 0)
- + return ret;
- +
- + bh1730_wait_for_next_measurement(bh1730);
- +
- + return 0;
- +}
- +
- +static int bh1730_power_off(struct bh1730_data *bh1730)
- +{
- + return bh1730_write(bh1730, BH1730_REG_CONTROL, 0);
- +}
- +
- +static int bh1730_read_raw(struct iio_dev *indio_dev,
- + struct iio_chan_spec const *chan,
- + int *val, int *val2, long mask)
- +{
- + struct bh1730_data *bh1730 = iio_priv(indio_dev);
- + int data_reg, ret;
- +
- + ret = bh1730_adjust_gain(bh1730);
- + if (ret < 0)
- + return ret;
- +
- + switch (mask) {
- + case IIO_CHAN_INFO_PROCESSED:
- + ret = bh1730_get_millilux(bh1730);
- + if (ret < 0)
- + return ret;
- + *val = ret / 1000;
- + *val2 = (ret % 1000) * 1000;
- + return IIO_VAL_INT_PLUS_MICRO;
- + case IIO_CHAN_INFO_RAW:
- + switch (chan->channel2) {
- + case IIO_MOD_LIGHT_CLEAR:
- + data_reg = BH1730_REG_DATA0LOW;
- + break;
- + case IIO_MOD_LIGHT_IR:
- + data_reg = BH1730_REG_DATA1LOW;
- + break;
- + default:
- + return -EINVAL;
- + }
- + ret = bh1730_read_word(bh1730, data_reg);
- + if (ret < 0)
- + return ret;
- + ret = ret * 1000 / bh1730_gain_multiplier(bh1730);
- + *val = ret / 1000;
- + *val2 = (ret % 1000) * 1000;
- + return IIO_VAL_INT_PLUS_MICRO;
- + default:
- + return -EINVAL;
- + }
- +}
- +
- +static const struct iio_info bh1730_info = {
- + .read_raw = bh1730_read_raw,
- +};
- +
- +static const struct iio_chan_spec bh1730_channels[] = {
- + {
- + .type = IIO_LIGHT,
- + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
- + },
- + {
- + .type = IIO_INTENSITY,
- + .modified = 1,
- + .channel2 = IIO_MOD_LIGHT_CLEAR,
- + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- + },
- + {
- + .type = IIO_INTENSITY,
- + .modified = 1,
- + .channel2 = IIO_MOD_LIGHT_IR,
- + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- + },
- +};
- +
- +static int bh1730_probe(struct i2c_client *client)
- +{
- + struct bh1730_data *bh1730;
- + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- + struct iio_dev *indio_dev;
- + int ret;
- +
- + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
- + return -EIO;
- +
- + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1730));
- + if (!indio_dev)
- + return -ENOMEM;
- +
- + bh1730 = iio_priv(indio_dev);
- + bh1730->client = client;
- + i2c_set_clientdata(client, indio_dev);
- +
- + ret = bh1730_power_on(bh1730);
- + if (ret < 0)
- + return ret;
- +
- + ret = bh1730_set_defaults(bh1730);
- + if (ret < 0)
- + return ret;
- +
- + indio_dev->dev.parent = &client->dev;
- + indio_dev->info = &bh1730_info;
- + indio_dev->name = "bh1730";
- + indio_dev->channels = bh1730_channels;
- + indio_dev->num_channels = ARRAY_SIZE(bh1730_channels);
- + indio_dev->modes = INDIO_DIRECT_MODE;
- +
- + ret = iio_device_register(indio_dev);
- + if (ret)
- + goto out_power_off;
- + return 0;
- +
- +out_power_off:
- + bh1730_power_off(bh1730);
- + return ret;
- +}
- +
- +static int bh1730_remove(struct i2c_client *client)
- +{
- + struct iio_dev *indio_dev = i2c_get_clientdata(client);
- + struct bh1730_data *bh1730 = iio_priv(indio_dev);
- +
- + iio_device_unregister(indio_dev);
- + return bh1730_power_off(bh1730);
- +}
- +
- +static const struct of_device_id of_bh1730_match[] = {
- + { .compatible = "rohm,bh1730fvc" },
- + {},
- +};
- +MODULE_DEVICE_TABLE(of, of_bh1730_match);
- +
- +static struct i2c_driver bh1730_driver = {
- + .probe_new = bh1730_probe,
- + .remove = bh1730_remove,
- + .driver = {
- + .name = "bh1730",
- + .of_match_table = of_bh1730_match,
- + },
- +};
- +module_i2c_driver(bh1730_driver);
- +
- +MODULE_AUTHOR("Pierre Bourdon <delroth@google.com>");
- +MODULE_DESCRIPTION("ROHM BH1730FVC driver");
- +MODULE_LICENSE("GPL v2");
- diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
- index 9591fc0..bac9188 100644
- --- a/drivers/input/joystick/Kconfig
- +++ b/drivers/input/joystick/Kconfig
- @@ -277,6 +277,18 @@ config JOYSTICK_JOYDUMP
- To compile this driver as a module, choose M here: the
- module will be called joydump.
- +config JOYSTICK_JOYCON
- + tristate "Joy-Con Rails"
- + select SERIAL_DEV_BUS
- + select POWER_SUPPLY
- + select CRC8
- + help
- + Say Y here if you have a one or more Joy-Con connected over UART
- +
- + To compile this driver as a module, choose M here: the
- + module will be called joycon.
- +
- +
- config JOYSTICK_XPAD
- tristate "X-Box gamepad support"
- depends on USB_ARCH_HAS_HCD
- diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
- index dd0492e..6a45ee9 100644
- --- a/drivers/input/joystick/Makefile
- +++ b/drivers/input/joystick/Makefile
- @@ -19,6 +19,7 @@ obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o
- obj-$(CONFIG_JOYSTICK_GUILLEMOT) += guillemot.o
- obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
- obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
- +obj-$(CONFIG_JOYSTICK_JOYCON) += joycon.o
- obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
- obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
- obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
- diff --git a/drivers/input/joystick/joycon.c b/drivers/input/joystick/joycon.c
- new file mode 100644
- index 000000000000..3179926b19c3
- --- /dev/null
- +++ b/drivers/input/joystick/joycon.c
- @@ -0,0 +1,950 @@
- +/*
- + * Copyright (c) 2018 Max Thomas
- + */
- +
- +/*
- + * Nintendo Joy-Con serial gamepad driver for Linux
- + */
- +
- +/*
- + * This program is free warftware; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- + *
- + * Should you need to contact me, the author, you can do so either by
- + * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- + * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/module.h>
- +#include <linux/slab.h>
- +#include <linux/input.h>
- +#include <linux/of.h>
- +#include <linux/tty.h>
- +#include <linux/serdev.h>
- +#include <linux/platform_device.h>
- +#include <linux/jiffies.h>
- +#include <linux/workqueue.h>
- +#include <linux/crc8.h>
- +#include <linux/power_supply.h>
- +#include <linux/gpio/consumer.h>
- +
- +#define DRIVER_DESC "Nintendo Joy-Con serial gamepad driver"
- +
- +MODULE_AUTHOR("Max Thomas <mtinc2@gmail.com>");
- +MODULE_DESCRIPTION(DRIVER_DESC);
- +MODULE_LICENSE("GPL");
- +
- +
- +/*
- + * Constants.
- + */
- +
- +
- +static const u8 switch_baud[0x14] = {0x19, 0x01, 0x03, 0x0F, 0x00, 0x91, 0x20, 0x08, 0x00, 0x00, 0xBD, 0xB1, 0xC0, 0xC6, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00};
- +static const u8 controller_status[0xD] = {0x19, 0x01, 0x03, 0x08, 0x00, 0x92, 0x00, 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F};
- +static const u8 unk_3[0x10] = {0x19, 0x01, 0x03, 0x0B, 0x00, 0x91, 0x12, 0x04, 0x00, 0x00, 0x12, 0xA6, 0x0F, 0x00, 0x00, 0x00};
- +
- +#define JOYCON_COMMAND_EXTSEND (0x91)
- +#define JOYCON_COMMAND_EXTRET (0x92)
- +#define JOYCON_COMMAND_INITRET (0x94)
- +#define JOYCON_COMMAND_HANDSHAKE (0xA5)
- +
- +#define JOYCON_INIT_MAC (0x1)
- +#define JOYCON_INIT_BAUDRATE (0x20)
- +#define JOYCON_INIT_UNK1 (0x11)
- +#define JOYCON_INIT_UNK2 (0x10)
- +#define JOYCON_INIT_UNK3 (0x12)
- +
- +#define JOYCON_EXT_ACK (0x1F)
- +#define JOYCON_EXT_INPUT (0x30)
- +#define JOYCON_EXT_HIDCOMMAND (0x21)
- +
- +#define JOYCON_HID_DEVICE_INFO (0x2)
- +#define JOYCON_HID_SPI_READ (0x10)
- +#define JOYCON_HID_GET_REGVOLT (0x50)
- +
- +#define JOYCON_SPI_FACTORY_CAL_2 (0x603D)
- +#define JOYCON_SPI_FACTORY_CAL_3 (0x6080)
- +#define JOYCON_SPI_STICK_USERCAL (0x8010)
- +
- +#define JOYCON_BATT_MV_MIN (3300)
- +#define JOYCON_BATT_MV_MAX (4200)
- +
- +#define JOYCON_BUTTONS_LEFT (0xFFE900)
- +#define JOYCON_BUTTONS_RIGHT (0x76FF)
- +#define JOYCON_BUTTONS_ALL (JOYCON_BUTTONS_LEFT | JOYCON_BUTTONS_RIGHT)
- +
- +#define JOYCON_BUTTONSET_LEFT BIT(0)
- +#define JOYCON_BUTTONSET_RIGHT BIT(1)
- +
- +#define JOYCON_CRC8_POLY (0x8D)
- +#define JOYCON_CRC8_INIT (0x00)
- +
- +typedef struct joycon_uart_initial
- +{
- + u8 magic[3];
- + u8 total_size;
- + u8 pad;
- +} joycon_uart_initial;
- +
- +typedef struct joycon_uart_header
- +{
- + joycon_uart_initial initial;
- + u8 command;
- + u8 data[5];
- + u8 crc;
- +} joycon_uart_header;
- +
- +typedef struct joycon_subcmd_packet
- +{
- + joycon_uart_header pre;
- + u8 command;
- + u8 data[];
- +} joycon_subcmd_packet;
- +
- +struct joycon_stick_calib
- +{
- + u16 x_max;
- + u16 y_max;
- + u16 x_cent;
- + u16 y_cent;
- + u16 x_min;
- + u16 y_min;
- +};
- +
- +/* Joy-Con button mappings */
- +static const signed short joycon_common_btn[] = {
- + BTN_Y, BTN_X, BTN_B, BTN_A,
- + BTN_0, BTN_1, BTN_TR, BTN_TR2,
- + BTN_SELECT, BTN_START,
- + BTN_THUMBR, BTN_THUMBL,
- + BTN_MODE, BTN_Z,
- + BTN_4, BTN_5, /* These two buttons do not exist on retail controllers. */
- + BTN_DPAD_DOWN, BTN_DPAD_UP, BTN_DPAD_RIGHT, BTN_DPAD_LEFT,
- + BTN_2, BTN_3, BTN_TL, BTN_TL2,
- + -1 /* terminating entry */
- +};
- +
- +/* Driver data */
- +struct joycon_device {
- + struct list_head list;
- +
- + struct device *dev;
- +
- + const char *name;
- + int irq;
- +};
- +
- +/*
- + * Per-Joy-Con data.
- + */
- +
- +struct joycon {
- + struct serdev_device *serdev;
- + struct input_dev *input_dev;
- + struct power_supply *batt_dev;
- + struct device *dev;
- + struct power_supply_desc batt_desc;
- + struct gpio_desc *charge_gpio;
- +
- + bool handshaken;
- + bool initialized;
- + bool factory_cal_2_parsed;
- + bool factory_cal_3_parsed;
- + bool usercal_parsed;
- +
- + int timeout_samples;
- + int num_samples;
- + int reconnect_threshold;
- +
- + u8 button_set;
- + struct joycon_stick_calib l_calib;
- + struct joycon_stick_calib r_calib;
- +
- + struct workqueue_struct *wq;
- +
- + int idx;
- + u16 regvolt;
- + u32 buttons;
- + u8 mac[6];
- +};
- +
- +/*
- + * Globals
- + */
- +static DEFINE_MUTEX(joycon_device_lock);
- +static DEFINE_MUTEX(joycon_input_lock);
- +static LIST_HEAD(joycon_device_list);
- +
- +static u8 crc_table[CRC8_TABLE_SIZE];
- +
- +static struct serdev_device_ops joycon_ops;
- +static struct input_dev *input_dev;
- +static u32 buttons;
- +static int stick_lx, stick_ly, stick_rx, stick_ry;
- +static int joycon_increment;
- +
- +
- +struct work_timeout_poll {
- + struct delayed_work work;
- + struct joycon* joycon;
- +};
- +
- +struct work_input_poll {
- + struct delayed_work work;
- + struct joycon* joycon;
- +};
- +
- +struct work_sync_poll {
- + struct delayed_work work;
- + struct joycon* joycon;
- +};
- +
- +u8 joycon_crc8(u8* data, size_t len)
- +{
- + return crc8(crc_table, data, len, JOYCON_CRC8_INIT);
- +}
- +
- +/*
- + * Battery stuff
- + */
- +
- +static enum power_supply_property joycon_battery_props[] = {
- + POWER_SUPPLY_PROP_TECHNOLOGY,
- + POWER_SUPPLY_PROP_SCOPE,
- + POWER_SUPPLY_PROP_CAPACITY,
- + POWER_SUPPLY_PROP_VOLTAGE_NOW,
- + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
- + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
- +};
- +
- +static int joycon_battery_get_property(struct power_supply *psy,
- + enum power_supply_property psp,
- + union power_supply_propval *val)
- +{
- + struct joycon *joycon = power_supply_get_drvdata(psy);
- + u32 regvolt_scaled, total_scaled;
- +
- + switch (psp)
- + {
- + case POWER_SUPPLY_PROP_TECHNOLOGY:
- + val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
- + break;
- + case POWER_SUPPLY_PROP_SCOPE:
- + val->intval = POWER_SUPPLY_SCOPE_DEVICE;
- + break;
- + case POWER_SUPPLY_PROP_CAPACITY:
- + regvolt_scaled = ((joycon->regvolt - JOYCON_BATT_MV_MIN) * 100);
- + total_scaled = (JOYCON_BATT_MV_MAX - JOYCON_BATT_MV_MIN);
- + val->intval = regvolt_scaled / total_scaled;
- + break;
- + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- + val->intval = joycon->regvolt * 1000;
- + break;
- + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
- + val->intval = JOYCON_BATT_MV_MAX * 1000;
- + break;
- + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
- + val->intval = JOYCON_BATT_MV_MIN * 1000;
- + break;
- + default:
- + return -EINVAL;
- + }
- +
- + return 0;
- +}
- +
- +
- +/*
- + * Packet crafting
- + */
- +
- +u16 joycon_packet_craft(u8 *out, u8 command, u8 *data, u16 size)
- +{
- + u16 packet_size = sizeof(joycon_uart_header);
- + joycon_uart_header *pre = (joycon_uart_header*)out;
- +
- + pre->initial.magic[0] = 0x19;
- + pre->initial.magic[1] = 0x01;
- + pre->initial.magic[2] = 0x3;
- +
- + pre->initial.total_size = 7;
- + pre->command = command;
- +
- + if (data)
- + memcpy(pre->data, data, size);
- +
- + pre->crc = joycon_crc8((void*)pre + 0x4, 0x7);
- +
- + return packet_size;
- +}
- +
- +u16 joycon_extcommand_craft(u8 *out, u8 command, u8 *data, u16 size)
- +{
- + u16 packet_size;
- + struct
- + {
- + u8 size[2];
- + } subcmd_data;
- +
- + joycon_subcmd_packet* subcmd_packet = (joycon_subcmd_packet*)out;
- +
- + subcmd_data.size[0] = (size + sizeof(u8)) >> 8;
- + subcmd_data.size[1] = (size + sizeof(u8)) & 0xFF;
- + packet_size = joycon_packet_craft(out, 0x92, (u8*)&subcmd_data, sizeof(subcmd_data));
- +
- + subcmd_packet->pre.initial.total_size += size;
- + subcmd_packet->command = command;
- + if (data)
- + memcpy(subcmd_packet->data, data, size);
- +
- + packet_size += size + sizeof(u8);
- + return packet_size;
- +}
- +
- +void joycon_send_command(struct serdev_device *serdev, u8 command, u8 *data, u16 size)
- +{
- + //TODO: memory corruption somewhere
- + u8 temp[0x1000]; //TODO: why did I make this static again
- + memset(temp, 0, sizeof(temp));
- +
- + size = joycon_packet_craft(temp, command, data, size);
- +
- + //print_bytes(temp, size);
- + serdev_device_write(serdev, temp, size, msecs_to_jiffies(200));
- +}
- +
- +void joycon_send_extcommand(struct serdev_device *serdev, u8 command, u8 *data, u16 size)
- +{
- + //u8 *temp = devm_kzalloc(&serdev->dev, size+0x1000, GFP_KERNEL);
- + u8 temp[0x1000];
- + memset(temp, 0, sizeof(temp));
- +
- + //TODO: memory corruption somewhere
- + size = joycon_extcommand_craft(temp, command, data, size);
- +
- + //print_bytes(temp, size);
- + serdev_device_write(serdev, temp, size, msecs_to_jiffies(200));
- + //kfree(temp);
- +}
- +
- +void joycon_send_hidcommand(struct serdev_device *serdev, u8 command, u8 *data, u16 size)
- +{
- + u8 data_gen[0x1000];
- + u8 rumble[8] = {0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40};
- +
- + memset(data_gen, 0, sizeof(data_gen));
- +
- + //TODO: memory corruption somewhere
- + //u8 *data_gen = devm_kzalloc(&serdev->dev, size+10+0x1000, GFP_KERNEL);
- + data_gen[0] = 0; //inc
- + memcpy(&data_gen[1], rumble, sizeof(rumble));
- + data_gen[9] = command;
- +
- + if (data)
- + memcpy(&data_gen[10], data, size);
- +
- + joycon_send_extcommand(serdev, 1, data_gen, 0x30);
- + //kfree(data_gen);
- +}
- +
- +/*
- + * Handlers
- + */
- +
- +static void timeout_handler(struct work_struct *work)
- +{
- + struct work_timeout_poll * data = (struct work_timeout_poll *)work;
- + struct joycon *joycon = data->joycon;
- + struct serdev_device *serdev = joycon->serdev;
- + int err;
- +
- + // Inactive for 600ms, try handshaking again
- + if (joycon->num_samples - joycon->timeout_samples == 0)
- + joycon->reconnect_threshold++;
- + else
- + joycon->reconnect_threshold = 0;
- +
- + // We haven't gotten any samples within 600ms, we've probably been disconnected.
- + if (joycon->reconnect_threshold > 3)
- + {
- + joycon->handshaken = false;
- + joycon->initialized = false;
- + joycon->regvolt = 0;
- + gpiod_set_value(joycon->charge_gpio, 0);
- +
- + err = serdev_device_write(serdev, (u8[]){0xA1, 0xA2, 0xA3, 0xA4}, 4, msecs_to_jiffies(200));
- + if (err) goto done;
- +
- + joycon_send_command(serdev, JOYCON_COMMAND_HANDSHAKE, (u8[]){0x02, 0x01, 0x7E}, 3); //TODO: error passing
- +
- + serdev_device_write_flush(serdev);
- +
- + joycon->reconnect_threshold = 0;
- + printk("Sent handshake\n");
- + }
- +
- + if (!joycon->initialized) goto done;
- +
- + joycon_send_hidcommand(serdev, JOYCON_HID_GET_REGVOLT, NULL, 0);
- +
- +done:
- + joycon->timeout_samples = joycon->num_samples;
- + INIT_DELAYED_WORK(&data->work,timeout_handler);
- + queue_delayed_work(joycon->wq, &data->work, msecs_to_jiffies(200));
- +}
- +
- +static void input_handler(struct work_struct *work)
- +{
- + struct work_input_poll * data = (struct work_input_poll *)work;
- + struct joycon *joycon = data->joycon;
- +
- + if (!joycon->initialized) goto done;
- + serdev_device_write(joycon->serdev, controller_status, sizeof(controller_status), msecs_to_jiffies(200));
- +
- + if (!joycon->button_set)
- + joycon_send_hidcommand(joycon->serdev, JOYCON_HID_DEVICE_INFO, NULL, 0);
- +
- + if (joycon->button_set && !joycon->factory_cal_2_parsed)
- + joycon_send_hidcommand(joycon->serdev, JOYCON_HID_SPI_READ, (u8[]){0x3D, 0x60, 0x00, 0x00, 0x1E}, 5); //TODO nicer
- +
- + if (joycon->factory_cal_2_parsed && !joycon->usercal_parsed)
- + joycon_send_hidcommand(joycon->serdev, JOYCON_HID_SPI_READ, (u8[]){0x10, 0x80, 0x00, 0x00, 0x2F}, 5); //TODO nicer
- +
- + if (joycon->factory_cal_2_parsed && !joycon->factory_cal_3_parsed)
- + joycon_send_hidcommand(joycon->serdev, JOYCON_HID_SPI_READ, (u8[]){0x80, 0x60, 0x00, 0x00, 0x17}, 5); //TODO nicer
- +
- +done:
- + INIT_DELAYED_WORK(&data->work, input_handler);
- + queue_delayed_work(joycon->wq, &data->work, msecs_to_jiffies(16));
- +}
- +
- +static void sync_handler(struct work_struct *work)
- +{
- + struct work_sync_poll * data = (struct work_sync_poll *)work;
- + struct joycon *joycon = data->joycon;
- + int i;
- +
- + mutex_lock(&joycon_input_lock);
- + for (i = 0; joycon_common_btn[i] >= 0; i++)
- + {
- + input_report_key(input_dev, joycon_common_btn[i], buttons & BIT(i));
- + }
- +
- + input_report_abs(input_dev, ABS_X, stick_lx);
- + input_report_abs(input_dev, ABS_Y, stick_ly);
- + input_report_abs(input_dev, ABS_RX, stick_rx);
- + input_report_abs(input_dev, ABS_RY, stick_ry);
- + input_sync(input_dev);
- + mutex_unlock(&joycon_input_lock);
- +
- + INIT_DELAYED_WORK(&data->work, sync_handler);
- + queue_delayed_work(joycon->wq, &data->work, msecs_to_jiffies(10));
- +}
- +
- +/*
- + * Packet parsing
- + */
- +
- +static void joycon_parse_stick_cal(struct joycon_stick_calib *calib, const u8* packed)
- +{
- + //min->max cent->min max->cent
- +
- + calib->x_cent = ((packed[1] << 8) & 0xF00) | packed[0];
- + calib->y_cent = (packed[2] << 4) | (packed[1] >> 4);
- + calib->x_min = ((packed[4] << 8) & 0xF00) | packed[3];
- + calib->y_min = (packed[5] << 4) | (packed[4] >> 4);
- + calib->x_max = ((packed[7] << 8) & 0xF00) | packed[6];
- + calib->y_max = (packed[8] << 4) | (packed[7] >> 4);
- +}
- +
- +static void joycon_calib_absinfo(struct input_absinfo *absinfo, unsigned int ax,
- + unsigned int ay, struct joycon_stick_calib *calib)
- +{
- + absinfo[ax].minimum = calib->x_cent - calib->x_min;
- + absinfo[ax].maximum = calib->x_cent + calib->x_max;
- + absinfo[ay].minimum = calib->y_cent - calib->y_min;
- + absinfo[ay].maximum = calib->y_cent + calib->y_max;
- +}
- +
- +static void joycon_parse_spi_read(struct serdev_device *serdev, const u8* packet, u32 size)
- +{
- + struct joycon *joycon = serdev_device_get_drvdata(serdev);
- + u32 addr = (packet[4] << 24) | (packet[3] << 16) | (packet[2] << 8)
- + | packet[1];
- + u8 bytes_read = packet[5];
- +
- + if (addr == JOYCON_SPI_FACTORY_CAL_2 && bytes_read >= 0x1E)
- + {
- + joycon_parse_stick_cal(&joycon->l_calib, packet + 5);
- + joycon_parse_stick_cal(&joycon->r_calib, packet + 14);
- +
- + //TODO: Colors
- +
- + if (joycon->button_set & JOYCON_BUTTONSET_LEFT)
- + {
- + joycon_calib_absinfo(input_dev->absinfo, ABS_X, ABS_Y,
- + &joycon->l_calib);
- + printk("Parsed left joystick configs\n");
- + }
- +
- + if (joycon->button_set & JOYCON_BUTTONSET_RIGHT)
- + {
- + joycon_calib_absinfo(input_dev->absinfo, ABS_RX, ABS_RY,
- + &joycon->r_calib);
- + printk("Parsed right joystick configs\n");
- + }
- +
- + joycon->factory_cal_2_parsed = true;
- + }
- + else if (addr == JOYCON_SPI_STICK_USERCAL)
- + {
- + if (packet[6] == 0xB2 && packet[7] == 0xA1
- + && joycon->button_set & JOYCON_BUTTONSET_LEFT)
- + {
- + joycon_parse_stick_cal(&joycon->l_calib, packet + 7);
- + joycon_calib_absinfo(input_dev->absinfo, ABS_X, ABS_Y,
- + &joycon->l_calib);
- + printk("Parsed left joystick user configs\n");
- + }
- +
- + if (packet[16] == 0xB2 && packet[17] == 0xA1
- + && joycon->button_set & JOYCON_BUTTONSET_RIGHT)
- + {
- + joycon_parse_stick_cal(&joycon->r_calib, packet + 17);
- + joycon_calib_absinfo(input_dev->absinfo, ABS_RX, ABS_RY,
- + &joycon->r_calib);
- + printk("Parsed right joystick user configs\n");
- + }
- +
- + //TODO: six-axis
- +
- + joycon->usercal_parsed = true;
- + }
- + else if (addr == JOYCON_SPI_FACTORY_CAL_3)
- + {
- + u16 dead_zone = packet[6+4] | (packet[6+5] << 8);
- + printk("Dead zone %x\n", dead_zone);
- +
- + /*if (joycon->button_set & JOYCON_BUTTONSET_LEFT)
- + {
- + input_dev->absinfo[ABS_X].flat = dead_zone;
- + input_dev->absinfo[ABS_Y].flat = dead_zone;
- + }
- +
- + if (joycon->button_set & JOYCON_BUTTONSET_RIGHT)
- + {
- + input_dev->absinfo[ABS_RX].flat = dead_zone;
- + input_dev->absinfo[ABS_RY].flat = dead_zone;
- + }*/
- +
- + joycon->factory_cal_3_parsed = true;
- + }
- +}
- +
- +static void joycon_hidret_parse(struct serdev_device *serdev, const u8* packet, u32 size)
- +{
- + struct joycon *joycon = serdev_device_get_drvdata(serdev);
- + switch (packet[0])
- + {
- + case JOYCON_HID_DEVICE_INFO:
- + printk("Joy-Con firmware version %u.%u\n", packet[1], packet[2]);
- + joycon->button_set = packet[3];
- + if (packet[3] == 1)
- + printk("Joy-Con is a left controller\n");
- + else if (packet[3] == 2)
- + printk("Joy-Con is a right controller\n");
- + else if (packet[3] == 3)
- + printk("Joy-Con is a pro controller\n");
- + else
- + printk("Joy-Con is unknown\n");
- + break;
- + case JOYCON_HID_SPI_READ:
- + joycon_parse_spi_read(serdev, packet, size);
- + break;
- + case JOYCON_HID_GET_REGVOLT:
- + // The actual regulated battery voltage is the raw * 2.5
- + joycon->regvolt = packet[1] | packet[2] << 8;
- + joycon->regvolt *= 5;
- + joycon->regvolt /= 2;
- + break;
- + default:
- + printk("Unknown hidret %x\n", packet[0]);
- + break;
- + }
- +
- + //print_bytes(packet, size);
- +}
- +
- +static void joycon_extret_parse(struct serdev_device *serdev, const u8* packet, u32 size)
- +{
- + struct joycon *joycon = serdev_device_get_drvdata(serdev);
- +
- + switch (packet[0])
- + {
- + case JOYCON_EXT_INPUT:
- + joycon->buttons = packet[3] | packet[4] << 8 | packet[5] << 16;
- +
- + mutex_lock(&joycon_input_lock);
- + if (joycon->button_set & JOYCON_BUTTONSET_LEFT)
- + {
- + buttons &= ~JOYCON_BUTTONS_LEFT;;
- + buttons |= (joycon->buttons & JOYCON_BUTTONS_LEFT);
- + }
- + if (joycon->button_set & JOYCON_BUTTONSET_RIGHT)
- + {
- + buttons &= ~JOYCON_BUTTONS_RIGHT;
- + buttons |= (joycon->buttons & JOYCON_BUTTONS_RIGHT);
- + }
- +
- + if (joycon->button_set & JOYCON_BUTTONSET_LEFT)
- + {
- + stick_lx = packet[6+0] | ((packet[6+1] & 0xF) << 8);
- + stick_ly = (packet[6+1] >> 4) | (packet[6+2] << 4);
- + }
- +
- + if (joycon->button_set & JOYCON_BUTTONSET_RIGHT)
- + {
- + stick_rx = packet[9+0] | ((packet[9+1] & 0xF) << 8);
- + stick_ry = (packet[9+1] >> 4) | (packet[9+2] << 4);
- + }
- + mutex_unlock(&joycon_input_lock);
- +
- +
- + joycon->num_samples++;
- + break;
- + case JOYCON_EXT_HIDCOMMAND:
- + joycon_hidret_parse(serdev, packet+14, size-14);
- + break;
- + default:
- + printk("Unknown extret %x\n", packet[0]);
- + break;
- + }
- +}
- +
- +static void joycon_initret_parse(struct serdev_device *serdev, const u8* packet, u32 size)
- +{
- + struct joycon *joycon = serdev_device_get_drvdata(serdev);
- + int i, j;
- +
- + switch (packet[0])
- + {
- + case JOYCON_INIT_MAC:
- + for (i = 0xC, j = 0; i >= 0x6; i--)
- + joycon->mac[j++] = packet[i];
- + printk("Joy-Con with MAC %02X::%02X::%02X::%02X::%02X::%02X\n",
- + joycon->mac[0], joycon->mac[1], joycon->mac[2],
- + joycon->mac[3], joycon->mac[4], joycon->mac[5]);
- +
- + // Next init command
- + //serdev_device_write(serdev, switch_baud, sizeof(switch_baud), msecs_to_jiffies(200));
- + joycon_send_command(serdev, JOYCON_COMMAND_EXTSEND, (u8[]){JOYCON_INIT_UNK1}, 1);
- + break;
- + case JOYCON_INIT_UNK1:
- + joycon_send_command(serdev, JOYCON_COMMAND_EXTSEND, (u8[]){JOYCON_INIT_UNK2}, 1);
- + break;
- + case JOYCON_INIT_UNK2:
- + serdev_device_write(serdev, unk_3, sizeof(unk_3), msecs_to_jiffies(200));
- + break;
- + case JOYCON_INIT_UNK3:
- + joycon->button_set = 0;
- + joycon->num_samples = 0;
- + joycon->factory_cal_2_parsed = false;
- + joycon->factory_cal_3_parsed = false;
- + joycon->usercal_parsed = false;
- + joycon->initialized = true;
- +
- + gpiod_set_value(joycon->charge_gpio, 1);
- + break;
- + case JOYCON_INIT_BAUDRATE:
- + serdev_device_set_baudrate(serdev, 3000000);
- + printk("High-speed baudrate shifted...\n");
- + break;
- + default:
- + printk("Unknown initret %x\n", packet[0]);
- + break;
- + }
- +}
- +
- +static void joycon_packet_parse(struct serdev_device *serdev, const u8* packet, size_t size)
- +{
- + struct joycon *joycon = serdev_device_get_drvdata(serdev);
- + joycon_uart_header* header = (joycon_uart_header*) packet;
- +
- + switch (header->command)
- + {
- + case JOYCON_COMMAND_EXTRET:
- + joycon_extret_parse(serdev, packet + sizeof(joycon_uart_header), (header->data[0] << 8) | header->data[1]);
- + break;
- + case JOYCON_COMMAND_INITRET:
- + joycon_initret_parse(serdev, packet + sizeof(joycon_uart_initial) + 1, size - sizeof(joycon_uart_initial) - 1);
- + break;
- + case JOYCON_COMMAND_HANDSHAKE:
- + printk("Got handshake response\n");
- + joycon->handshaken = true;
- +
- + // Get MAC
- + joycon_send_command(serdev, JOYCON_COMMAND_EXTSEND, (u8[]){JOYCON_INIT_MAC}, 1);
- + break;
- + default:
- + printk("Unknown command %x\n", header->command);
- + break;
- + }
- +}
- +
- +static int joycon_serdev_receive_buf(struct serdev_device *serdev, const unsigned char *buf, size_t len)
- +{
- + struct joycon *joycon = serdev_device_get_drvdata(serdev);
- +
- + if (!joycon || serdev != joycon->serdev) {
- + WARN_ON(1);
- + return 0;
- + }
- +
- + joycon_packet_parse(serdev, buf, len);
- +
- + return len;
- +}
- +
- +static void joycon_serdev_write_wakeup(struct serdev_device *serdev)
- +{
- + //printk("Wakeup\n");
- +}
- +
- +/*
- + * Serdev driver
- + */
- +
- +static int joycon_serdev_probe(struct serdev_device *serdev)
- +{
- + struct joycon *joycon;
- +
- + struct work_timeout_poll *work_timeout;
- + struct work_input_poll *work_input;
- + struct work_sync_poll *work_sync;
- + struct power_supply_config psy_cfg = {};
- + int i;
- + int err = -ENOMEM;
- +
- + printk("Joy-Con probe!\n");
- +
- + joycon = devm_kzalloc(&serdev->dev, sizeof(*joycon), GFP_KERNEL);
- + if (!joycon)
- + goto fail2;
- +
- + joycon->wq = create_workqueue("joycon_wq");
- +
- + if (input_dev) goto input_exists;
- +
- + // TODO: For USB/BT this should be an array w/ Joy-Con
- + // being matched to input devices by halves
- + input_dev = input_allocate_device();
- + if (!input_dev) goto fail2;
- +
- + input_dev->name = "Joy-Con Rails";
- + input_dev->id.bustype = BUS_VIRTUAL;
- + input_dev->id.vendor = 0x057E;
- + input_dev->id.product = 0x2008;
- + input_dev->id.version = 0x0100;
- + input_dev->dev.parent = &serdev->dev;
- +
- + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- +
- + /* set up standard buttons */
- + for (i = 0; joycon_common_btn[i] >= 0; i++)
- + __set_bit(joycon_common_btn[i], input_dev->keybit);
- +
- + //TODO: dead zones
- + input_set_abs_params(input_dev, ABS_X, 0x400, 0xC00, 0, 180);
- + input_set_abs_params(input_dev, ABS_Y, 0x400, 0xC00, 0, 180);
- + input_set_abs_params(input_dev, ABS_RX, 0x400, 0xC00, 0, 180);
- + input_set_abs_params(input_dev, ABS_RY, 0x400, 0xC00, 0, 180);
- +
- + err = input_register_device(input_dev);
- + if (err) goto fail1;
- +
- + // Start input sync polling
- + work_sync = kmalloc(sizeof(struct work_sync_poll), GFP_KERNEL);
- + INIT_DELAYED_WORK(&work_sync->work, sync_handler);
- + work_sync->joycon = joycon;
- + queue_delayed_work(joycon->wq, &work_sync->work, msecs_to_jiffies(10));
- +
- +input_exists:
- +
- + psy_cfg.of_node = serdev->dev.of_node;
- + psy_cfg.drv_data = joycon;
- +
- + joycon->batt_desc.name = kasprintf(GFP_KERNEL, "joycon_battery_%u", joycon_increment++);
- + joycon->batt_desc.type = POWER_SUPPLY_TYPE_BATTERY;
- + joycon->batt_desc.properties = joycon_battery_props;
- + joycon->batt_desc.num_properties = ARRAY_SIZE(joycon_battery_props);
- + joycon->batt_desc.get_property = joycon_battery_get_property;
- +
- + joycon->batt_dev = devm_power_supply_register(&serdev->dev, &joycon->batt_desc,
- + &psy_cfg);
- +
- + err = PTR_ERR_OR_ZERO(joycon->batt_dev);
- + if (err) {
- + dev_err(&serdev->dev, "failed to register power supply\n");
- + goto fail1;
- + }
- +
- + joycon->serdev = serdev;
- + joycon->dev = &serdev->dev;
- + joycon->input_dev = input_dev;
- +
- + serdev_device_set_drvdata(serdev, joycon);
- +
- + //TODO: error checking
- + serdev_device_open(serdev);
- + serdev_device_set_flow_control(serdev, true);
- + serdev_device_set_baudrate(serdev, 1000000);
- +
- + serdev_device_set_client_ops(serdev, &joycon_ops);
- +
- + // Get charging GPIO
- + joycon->charge_gpio = devm_gpiod_get(&serdev->dev, "charge", GPIOD_OUT_LOW);
- + if (IS_ERR(joycon->charge_gpio)) {
- + err = PTR_ERR(joycon->charge_gpio);
- + dev_err(&serdev->dev, "cannot get charge-gpio %d\n", err);
- + goto fail3;
- + }
- +
- + // Set up work polling
- + work_timeout = kmalloc(sizeof(struct work_timeout_poll), GFP_KERNEL);
- + INIT_DELAYED_WORK(&work_timeout->work, timeout_handler);
- + work_timeout->joycon = joycon;
- + queue_delayed_work(joycon->wq, &work_timeout->work, msecs_to_jiffies(200));
- +
- + work_input = kmalloc(sizeof(struct work_input_poll), GFP_KERNEL);
- + work_input->joycon = joycon;
- + INIT_DELAYED_WORK(&work_input->work, input_handler);
- + queue_delayed_work(joycon->wq, &work_input->work, msecs_to_jiffies(200));
- +
- + return 0;
- +
- + fail3: serdev_device_set_drvdata(serdev, NULL);
- + fail1: input_free_device(input_dev);
- + fail2:
- + kfree(joycon);
- + return err;
- +}
- +
- +static void joycon_serdev_remove(struct serdev_device *serdev)
- +{
- + struct joycon *joycon = serdev_device_get_drvdata(serdev);
- + printk("Joy-Con remove!\n");
- +
- + input_unregister_device(joycon->input_dev);
- +
- + flush_workqueue(joycon->wq);
- + destroy_workqueue(joycon->wq);
- +
- + kfree(joycon->batt_desc.name);
- + kfree(joycon);
- +}
- +
- +/*
- + * The serdev driver structure.
- + */
- +#ifdef CONFIG_OF
- +static const struct of_device_id joycon_uart_of_match[] = {
- + { .compatible = "nintendo,joycon-uart" },
- + { },
- +};
- +MODULE_DEVICE_TABLE(of, joycon_uart_of_match);
- +#endif
- +
- +static struct serdev_device_driver joycon_serdev_driver = {
- + .probe = joycon_serdev_probe,
- + .remove = joycon_serdev_remove,
- + .driver = {
- + .name = "joycon-uart",
- + .of_match_table = of_match_ptr(joycon_uart_of_match),
- + },
- +};
- +
- +static struct serdev_device_ops joycon_ops = {
- + .receive_buf = joycon_serdev_receive_buf,
- + .write_wakeup = joycon_serdev_write_wakeup,
- +};
- +
- +/*
- + * Joy-Con base driver
- + */
- +
- +static int joycon_probe(struct platform_device *pdev)
- +{
- + struct joycon_device *dev;
- +
- + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
- + if (!dev)
- + return -ENOMEM;
- +
- + dev->dev = &pdev->dev;
- + dev->irq = platform_get_irq(pdev, 0);
- +
- + platform_set_drvdata(pdev, dev);
- +
- + dev_info(&pdev->dev, "%s device registered.\n", dev->name);
- +
- + /* Place this instance on the device list */
- + mutex_lock(&joycon_device_lock);
- + list_add_tail(&dev->list, &joycon_device_list);
- + mutex_unlock(&joycon_device_lock);
- +
- + return 0;
- +}
- +
- +static int joycon_remove(struct platform_device *pdev)
- +{
- + struct joycon_device *dev = platform_get_drvdata(pdev);
- +
- + mutex_lock(&joycon_device_lock);
- + list_del(&dev->list);
- + mutex_unlock(&joycon_device_lock);
- +
- + dev_info(&pdev->dev, "%s device unregistered.\n", dev->name);
- +
- + return 0;
- +}
- +
- +static struct platform_driver joycon_driver = {
- + .probe = joycon_probe,
- + .remove = joycon_remove,
- + .driver = {
- + .name = "joycon",
- + },
- +};
- +
- +int __init joycon_init(void)
- +{
- + platform_driver_register(&joycon_driver);
- + serdev_device_driver_register(&joycon_serdev_driver);
- +
- + joycon_increment = 0;
- + crc8_populate_lsb(crc_table, JOYCON_CRC8_POLY);
- +
- + return 0;
- +}
- +
- +void __exit joycon_exit(void)
- +{
- + platform_driver_unregister(&joycon_driver);
- + serdev_device_driver_unregister(&joycon_serdev_driver);
- +}
- +
- +module_init(joycon_init);
- +module_exit(joycon_exit);
- diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
- index 704e990..3e026ab 100644
- --- a/drivers/input/touchscreen/stmfts.c
- +++ b/drivers/input/touchscreen/stmfts.c
- @@ -14,6 +14,7 @@
- #include <linux/module.h>
- #include <linux/pm_runtime.h>
- #include <linux/regulator/consumer.h>
- +#include <linux/kthread.h>
- /* I2C commands */
- #define STMFTS_READ_INFO 0x80
- @@ -34,6 +35,7 @@
- #define STMFTS_FULL_FORCE_CALIBRATION 0xa2
- #define STMFTS_MS_CX_TUNING 0xa3
- #define STMFTS_SS_CX_TUNING 0xa4
- +#define STMFTS_WRITE_REGISTER 0xb6
- /* events */
- #define STMFTS_EV_NO_EVENT 0x00
- @@ -104,6 +106,11 @@ struct stmfts_data {
- bool led_status;
- bool hover_enabled;
- bool running;
- + bool no_sleep_support;
- + int irq_enable_reg;
- + u8 irq_enable_data;
- +
- + struct task_struct *poll_thread;
- };
- static void stmfts_brightness_set(struct led_classdev *led_cdev,
- @@ -169,6 +176,7 @@ static int stmfts_read_events(struct stmfts_data *sdata)
- static void stmfts_report_contact_event(struct stmfts_data *sdata,
- const u8 event[])
- {
- +#if 0
- u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4;
- u16 x = event[1] | ((event[2] & STMFTS_MASK_X_MSB) << 8);
- u16 y = (event[2] >> 4) | (event[3] << 4);
- @@ -176,7 +184,17 @@ static void stmfts_report_contact_event(struct stmfts_data *sdata,
- u8 min = event[5];
- u8 orientation = event[6];
- u8 area = event[7];
- +#else
- + u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4;
- + u16 x = (event[1] << 4) | ((event[3] & 0xf0) >> 4);
- + u16 y = (event[2] << 4) | (event[3] & 0x0f);
- + u8 maj = event[4] | (event[5] << 8);
- + u8 min = maj;
- + // these two are not quite right but meh
- + u8 orientation = event[6];
- + u8 area = event[7];
- +#endif
- input_mt_slot(sdata->input, slot_id);
- input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true);
- @@ -313,6 +331,16 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
- return IRQ_HANDLED;
- }
- +static int stmfts_poll_thread(void *data)
- +{
- + while (!kthread_should_stop()) {
- + stmfts_irq_handler(0, data);
- + msleep(2);
- + }
- + return 0;
- +}
- +
- +
- static int stmfts_command(struct stmfts_data *sdata, const u8 cmd)
- {
- int err;
- @@ -330,6 +358,18 @@ static int stmfts_command(struct stmfts_data *sdata, const u8 cmd)
- return 0;
- }
- +static int stmfts_write_register(struct stmfts_data *sdata, const u16 reg, const u8 value)
- +{
- + u8 buf[3];
- +
- + buf[0] = reg >> 8;
- + buf[1] = reg & 0xff;
- + buf[2] = value;
- +
- + return i2c_smbus_write_i2c_block_data(sdata->client,
- + STMFTS_WRITE_REGISTER, 3, buf);
- +}
- +
- static int stmfts_input_open(struct input_dev *dev)
- {
- struct stmfts_data *sdata = input_get_drvdata(dev);
- @@ -546,18 +586,52 @@ static int stmfts_power_on(struct stmfts_data *sdata)
- sdata->fw_ver = be16_to_cpup((__be16 *)®[2]);
- sdata->config_id = reg[4];
- sdata->config_ver = reg[5];
- -
- - enable_irq(sdata->client->irq);
- +
- + if (sdata->client->irq)
- + enable_irq(sdata->client->irq);
- msleep(50);
- - err = stmfts_command(sdata, STMFTS_SYSTEM_RESET);
- + if (!sdata->client->irq) {
- + sdata->poll_thread = kthread_run(stmfts_poll_thread, sdata, "stmfts_poll");
- + if (IS_ERR(sdata->poll_thread))
- + return -EIO;
- + }
- +
- + /*
- + * IRQs may be disabled on startup, so we need to reset the chip, then
- + * immediately issue the command to enable IRQs. This will trigger
- + * the completion for the reset command's queued status message.
- + */
- + reinit_completion(&sdata->cmd_done);
- +
- + err = i2c_smbus_write_byte(sdata->client, STMFTS_SYSTEM_RESET);
- if (err)
- - return err;
- + goto cleanup_irq;
- +
- + msleep(10);
- +
- + if (sdata->client->irq && sdata->irq_enable_reg != -1) {
- + err = stmfts_write_register(sdata, sdata->irq_enable_reg,
- + sdata->irq_enable_data);
- + if (err)
- + goto cleanup_irq;
- + }
- +
- + if (!wait_for_completion_timeout(&sdata->cmd_done,
- + msecs_to_jiffies(1000))) {
- + err = -ETIMEDOUT;
- + dev_err(&sdata->client->dev,
- + "reset did not complete: %d\n", err);
- + goto cleanup_irq;
- + }
- err = stmfts_command(sdata, STMFTS_SLEEP_OUT);
- - if (err)
- - return err;
- + if (err) {
- + dev_warn(&sdata->client->dev,
- + "failed to perform sleep_out: %d\n", err);
- + sdata->no_sleep_support = true;
- + }
- /* optional tuning */
- err = stmfts_command(sdata, STMFTS_MS_CX_TUNING);
- @@ -572,23 +646,37 @@ static int stmfts_power_on(struct stmfts_data *sdata)
- "failed to perform self auto tune: %d\n", err);
- err = stmfts_command(sdata, STMFTS_FULL_FORCE_CALIBRATION);
- - if (err)
- - return err;
- + if (err) {
- + dev_err(&sdata->client->dev,
- + "failed to perform calibration: %d\n", err);
- + goto cleanup_irq;
- + }
- /*
- * At this point no one is using the touchscreen
- * and I don't really care about the return value
- */
- - (void) i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
- + if (!sdata->no_sleep_support)
- + (void) i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
- return 0;
- +
- +cleanup_irq:
- + if (!sdata->client->irq)
- + kthread_stop(sdata->poll_thread);
- + else
- + disable_irq(sdata->client->irq);
- + return err;
- }
- static void stmfts_power_off(void *data)
- {
- struct stmfts_data *sdata = data;
- - disable_irq(sdata->client->irq);
- + if (!sdata->client->irq)
- + kthread_stop(sdata->poll_thread);
- + else
- + disable_irq(sdata->client->irq);
- regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
- }
- @@ -625,6 +713,7 @@ static int stmfts_probe(struct i2c_client *client,
- {
- int err;
- struct stmfts_data *sdata;
- + u32 prop[2];
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
- I2C_FUNC_SMBUS_BYTE_DATA |
- @@ -670,6 +759,15 @@ static int stmfts_probe(struct i2c_client *client,
- sdata->use_key = device_property_read_bool(&client->dev,
- "touch-key-connected");
- +
- + if (!device_property_read_u32_array(&client->dev,
- + "interrupt-enable-reg", prop, 2)) {
- + sdata->irq_enable_reg = prop[0] & 0xffff;
- + sdata->irq_enable_data = prop[1] & 0xff;
- + } else {
- + sdata->irq_enable_reg = -1;
- + }
- +
- if (sdata->use_key) {
- input_set_capability(sdata->input, EV_KEY, KEY_MENU);
- input_set_capability(sdata->input, EV_KEY, KEY_BACK);
- @@ -689,13 +787,15 @@ static int stmfts_probe(struct i2c_client *client,
- * interrupts. To be on the safe side it's better to not enable
- * the interrupts during their request.
- */
- - irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
- - err = devm_request_threaded_irq(&client->dev, client->irq,
- - NULL, stmfts_irq_handler,
- - IRQF_ONESHOT,
- - "stmfts_irq", sdata);
- - if (err)
- - return err;
- + if (client->irq) {
- + irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
- + err = devm_request_threaded_irq(&client->dev, client->irq,
- + NULL, stmfts_irq_handler,
- + IRQF_ONESHOT,
- + "stmfts_irq", sdata);
- + if (err)
- + return err;
- + }
- dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n");
- @@ -747,6 +847,9 @@ static int __maybe_unused stmfts_runtime_suspend(struct device *dev)
- struct stmfts_data *sdata = dev_get_drvdata(dev);
- int ret;
- + if (sdata->no_sleep_support)
- + return 0;
- +
- ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
- if (ret)
- dev_warn(dev, "failed to suspend device: %d\n", ret);
- @@ -759,6 +862,9 @@ static int __maybe_unused stmfts_runtime_resume(struct device *dev)
- struct stmfts_data *sdata = dev_get_drvdata(dev);
- int ret;
- + if (sdata->no_sleep_support)
- + return 0;
- +
- ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT);
- if (ret)
- dev_err(dev, "failed to resume device: %d\n", ret);
- diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
- index b877c13..db438ce 100644
- --- a/drivers/mmc/host/sdhci-tegra.c
- +++ b/drivers/mmc/host/sdhci-tegra.c
- @@ -27,6 +27,7 @@
- #include <linux/mmc/mmc.h>
- #include <linux/mmc/slot-gpio.h>
- #include <linux/gpio/consumer.h>
- +#include <soc/tegra/pmc.h>
- #include "sdhci-pltfm.h"
- @@ -55,6 +56,7 @@
- #define NVQUIRK_ENABLE_SDR104 BIT(4)
- #define NVQUIRK_ENABLE_DDR50 BIT(5)
- #define NVQUIRK_HAS_PADCALIB BIT(6)
- +#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7)
- struct sdhci_tegra_soc_data {
- const struct sdhci_pltfm_data *pdata;
- @@ -66,6 +68,8 @@ struct sdhci_tegra {
- struct gpio_desc *power_gpio;
- bool ddr_signaling;
- bool pad_calib_required;
- + bool pad_control;
- + unsigned int pad_id;
- struct reset_control *rst;
- };
- @@ -166,7 +170,9 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
- * even if the device supports it because the IO voltage
- * cannot be configured.
- */
- - if (!IS_ERR(host->mmc->supply.vqmmc)) {
- + if (!IS_ERR(host->mmc->supply.vqmmc) &&
- + (!(soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) ||
- + tegra_host->pad_control)) {
- /* Erratum: Enable SDHCI spec v3.00 support */
- if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
- misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
- @@ -289,7 +295,7 @@ static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
- return mmc_send_tuning(host->mmc, opcode, NULL);
- }
- -static void tegra_sdhci_voltage_switch(struct sdhci_host *host)
- +static void tegra_sdhci_voltage_switch(struct sdhci_host *host, struct mmc_ios *ios)
- {
- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
- @@ -297,6 +303,24 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host)
- if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
- tegra_host->pad_calib_required = true;
- +
- + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
- + if (tegra_host->pad_control) {
- + tegra_io_pad_set_voltage(tegra_host->pad_id, TEGRA_IO_PAD_1800000UV);
- + }
- + }
- +}
- +
- +static void tegra_sdhci_pre_voltage_switch(struct sdhci_host *host, struct mmc_ios *ios)
- +{
- + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- + struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
- +
- + if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
- + if (tegra_host->pad_control) {
- + tegra_io_pad_set_voltage(tegra_host->pad_id, TEGRA_IO_PAD_3300000UV);
- + }
- + }
- }
- static const struct sdhci_ops tegra_sdhci_ops = {
- @@ -308,6 +332,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
- .reset = tegra_sdhci_reset,
- .platform_execute_tuning = tegra_sdhci_execute_tuning,
- .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
- + .pre_voltage_switch = tegra_sdhci_pre_voltage_switch,
- .voltage_switch = tegra_sdhci_voltage_switch,
- .get_max_clock = tegra_sdhci_get_max_clock,
- };
- @@ -413,6 +438,11 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
- static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
- .pdata = &sdhci_tegra210_pdata,
- + .nvquirks = NVQUIRK_ENABLE_SDR50 |
- + NVQUIRK_ENABLE_DDR50 |
- + NVQUIRK_ENABLE_SDR104 |
- + NVQUIRK_HAS_PADCALIB |
- + NVQUIRK_NEEDS_PAD_CONTROL,
- };
- static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
- @@ -458,6 +488,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
- struct sdhci_tegra *tegra_host;
- struct clk *clk;
- int rc;
- + struct device_node *np = pdev->dev.of_node;
- + u32 prop;
- match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
- if (!match)
- @@ -472,8 +504,14 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
- tegra_host = sdhci_pltfm_priv(pltfm_host);
- tegra_host->ddr_signaling = false;
- tegra_host->pad_calib_required = false;
- + tegra_host->pad_control = false;
- tegra_host->soc_data = soc_data;
- + if (!of_property_read_u32(np, "nvidia,pad", &prop)) {
- + tegra_host->pad_control = true;
- + tegra_host->pad_id = prop;
- + }
- +
- rc = mmc_of_parse(host->mmc);
- if (rc)
- goto err_parse_dt;
- diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
- index 2ededa7..ff44ecb 100644
- --- a/drivers/mmc/host/sdhci.c
- +++ b/drivers/mmc/host/sdhci.c
- @@ -1929,6 +1929,10 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
- case MMC_SIGNAL_VOLTAGE_330:
- if (!(host->flags & SDHCI_SIGNALING_330))
- return -EINVAL;
- +
- + if (host->ops->pre_voltage_switch)
- + host->ops->pre_voltage_switch(host, ios);
- +
- /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
- ctrl &= ~SDHCI_CTRL_VDD_180;
- sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- @@ -1941,6 +1945,11 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
- return -EIO;
- }
- }
- +
- + /* Some controller need to do more when switching */
- + if (host->ops->voltage_switch)
- + host->ops->voltage_switch(host, ios);
- +
- /* Wait for 5ms */
- usleep_range(5000, 5500);
- @@ -1956,6 +1965,11 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
- case MMC_SIGNAL_VOLTAGE_180:
- if (!(host->flags & SDHCI_SIGNALING_180))
- return -EINVAL;
- +
- + /* Some controller need to do more when switching */
- + if (host->ops->pre_voltage_switch)
- + host->ops->pre_voltage_switch(host, ios);
- +
- if (!IS_ERR(mmc->supply.vqmmc)) {
- ret = mmc_regulator_set_vqmmc(mmc, ios);
- if (ret) {
- @@ -1974,7 +1988,7 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
- /* Some controller need to do more when switching */
- if (host->ops->voltage_switch)
- - host->ops->voltage_switch(host);
- + host->ops->voltage_switch(host, ios);
- /* 1.8V regulator output should be stable within 5 ms */
- ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
- index c95b0a4..57a0ea8 100644
- --- a/drivers/mmc/host/sdhci.h
- +++ b/drivers/mmc/host/sdhci.h
- @@ -587,7 +587,9 @@ struct sdhci_ops {
- void (*hw_reset)(struct sdhci_host *host);
- void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
- void (*card_event)(struct sdhci_host *host);
- - void (*voltage_switch)(struct sdhci_host *host);
- + void (*pre_voltage_switch)(struct sdhci_host *host,
- + struct mmc_ios *ios);
- + void (*voltage_switch)(struct sdhci_host *host, struct mmc_ios *ios);
- };
- #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
- diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c
- index 485f759..d902b1f 100644
- --- a/drivers/mmc/host/sdhci_f_sdh30.c
- +++ b/drivers/mmc/host/sdhci_f_sdh30.c
- @@ -53,11 +53,16 @@ struct f_sdhost_priv {
- bool enable_cmd_dat_delay;
- };
- -static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
- +static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host,
- + struct mmc_ios *ios)
- {
- struct f_sdhost_priv *priv = sdhci_priv(host);
- u32 ctrl = 0;
- + // FIXME: do something when switching back to 3.3V?
- + if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180)
- + return;
- +
- usleep_range(2500, 3000);
- ctrl = sdhci_readl(host, F_SDH30_IO_CONTROL2);
- ctrl |= F_SDH30_CRES_O_DN;
- diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
- index 0d0177c..ba2b273 100644
- --- a/drivers/pci/host/Kconfig
- +++ b/drivers/pci/host/Kconfig
- @@ -36,7 +36,7 @@ config PCI_FTPCI100
- default ARCH_GEMINI
- config PCI_TEGRA
- - bool "NVIDIA Tegra PCIe controller"
- + tristate "NVIDIA Tegra PCIe controller"
- depends on ARCH_TEGRA
- depends on PCI_MSI_IRQ_DOMAIN
- help
- diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
- index b58df04..ea31de8 100644
- --- a/drivers/power/supply/bq24190_charger.c
- +++ b/drivers/power/supply/bq24190_charger.c
- @@ -1638,6 +1638,7 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
- return ret;
- if (v != BQ24190_REG_VPRS_PN_24190 &&
- + v != BQ24190_REG_VPRS_PN_24192 &&
- v != BQ24190_REG_VPRS_PN_24192I) {
- dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
- return -ENODEV;
- diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
- index 1a568df..9c85f95 100644
- --- a/drivers/power/supply/max17042_battery.c
- +++ b/drivers/power/supply/max17042_battery.c
- @@ -190,7 +190,7 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
- ret = regmap_read(chip->regmap, MAX17042_AvgVCELL, &val);
- if (ret < 0)
- - goto health_error;
- + return ret;
- /* bits [0-3] unused */
- vavg = val * 625 / 8;
- @@ -199,7 +199,7 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
- ret = regmap_read(chip->regmap, MAX17042_VCELL, &val);
- if (ret < 0)
- - goto health_error;
- + return ret;
- /* bits [0-3] unused */
- vbatt = val * 625 / 8;
- @@ -208,35 +208,31 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
- if (vavg < chip->pdata->vmin) {
- *health = POWER_SUPPLY_HEALTH_DEAD;
- - goto out;
- + return 0;
- }
- if (vbatt > chip->pdata->vmax + MAX17042_VMAX_TOLERANCE) {
- *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
- - goto out;
- + return 0;
- }
- ret = max17042_get_temperature(chip, &temp);
- if (ret < 0)
- - goto health_error;
- + return ret;
- if (temp < chip->pdata->temp_min) {
- *health = POWER_SUPPLY_HEALTH_COLD;
- - goto out;
- + return 0;
- }
- if (temp > chip->pdata->temp_max) {
- *health = POWER_SUPPLY_HEALTH_OVERHEAT;
- - goto out;
- + return 0;
- }
- *health = POWER_SUPPLY_HEALTH_GOOD;
- -out:
- return 0;
- -
- -health_error:
- - return ret;
- }
- static int max17042_get_property(struct power_supply *psy,
- diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
- index f8ebbec..ec4fcc7 100644
- --- a/drivers/pwm/pwm-tegra.c
- +++ b/drivers/pwm/pwm-tegra.c
- @@ -93,6 +93,9 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
- c *= (1 << PWM_DUTY_WIDTH);
- c = DIV_ROUND_CLOSEST_ULL(c, period_ns);
- + if (pwm->state.polarity == PWM_POLARITY_INVERSED)
- + c = (1 << PWM_DUTY_WIDTH) - c;
- +
- val = (u32)c << PWM_DUTY_SHIFT;
- /*
- @@ -144,6 +147,35 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
- return 0;
- }
- +static int tegra_pwm_set_polarity(struct pwm_chip *chip,
- + struct pwm_device *pwm,
- + enum pwm_polarity polarity)
- +{
- + struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
- + u32 val, duty;
- + int err;
- +
- + if (pwm->state.polarity != polarity) {
- + if (!pwm_is_enabled(pwm)) {
- + err = clk_prepare_enable(pc->clk);
- + if (err < 0)
- + return err;
- + }
- +
- + val = pwm_readl(pc, pwm->hwpwm);
- + duty = (val >> PWM_DUTY_SHIFT) & ((1 << (PWM_DUTY_WIDTH + 1)) - 1);
- + val &= ~(((1 << (PWM_DUTY_WIDTH + 1)) - 1) << PWM_DUTY_SHIFT);
- + duty = (1 << PWM_DUTY_SHIFT) - duty;
- + val |= duty << PWM_DUTY_SHIFT;
- + pwm_writel(pc, pwm->hwpwm, val);
- +
- + if (!pwm_is_enabled(pwm))
- + clk_disable_unprepare(pc->clk);
- + }
- +
- + return 0;
- +}
- +
- static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
- {
- struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
- @@ -177,6 +209,7 @@ static const struct pwm_ops tegra_pwm_ops = {
- .config = tegra_pwm_config,
- .enable = tegra_pwm_enable,
- .disable = tegra_pwm_disable,
- + .set_polarity = tegra_pwm_set_polarity,
- .owner = THIS_MODULE,
- };
- @@ -229,6 +262,8 @@ static int tegra_pwm_probe(struct platform_device *pdev)
- pwm->chip.dev = &pdev->dev;
- pwm->chip.ops = &tegra_pwm_ops;
- + pwm->chip.of_xlate = of_pwm_xlate_with_flags;
- + pwm->chip.of_pwm_n_cells = 3;
- pwm->chip.base = -1;
- pwm->chip.npwm = pwm->soc->num_channels;
- diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
- index d480346..e7de0c6 100644
- --- a/drivers/regulator/core.c
- +++ b/drivers/regulator/core.c
- @@ -3352,6 +3352,37 @@ int regulator_get_voltage(struct regulator *regulator)
- }
- EXPORT_SYMBOL_GPL(regulator_get_voltage);
- +/**
- + * regulator_get_constraint_voltages - get platform specific constraint voltage,
- + * @regulator: regulator source
- + * @min_uV: Minimum microvolts.
- + * @max_uV: Maximum microvolts.
- + *
- + * This returns the current regulator voltage in uV.
- + *
- + * NOTE: If the regulator is disabled it will return the voltage value. This
- + * function should not be used to determine regulator state.
- + */
- +
- +int regulator_get_constraint_voltages(struct regulator *regulator,
- + int *min_uV, int *max_uV)
- +{
- + struct regulator_dev *rdev = regulator->rdev;
- +
- + if (rdev->desc && rdev->desc->fixed_uV && rdev->desc->n_voltages == 1) {
- + *min_uV = rdev->desc->fixed_uV;
- + *max_uV = rdev->desc->fixed_uV;
- + return 0;
- + }
- + if (rdev->constraints) {
- + *min_uV = rdev->constraints->min_uV;
- + *max_uV = rdev->constraints->max_uV;
- + return 0;
- + }
- + return -EINVAL;
- +}
- +EXPORT_SYMBOL_GPL(regulator_get_constraint_voltages);
- +
- /**
- * regulator_set_current_limit - set regulator output current limit
- * @regulator: regulator source
- diff --git a/drivers/soc/tegra/fuse/speedo-tegra210.c b/drivers/soc/tegra/fuse/speedo-tegra210.c
- index 5373f4c..e8a08a0 100644
- --- a/drivers/soc/tegra/fuse/speedo-tegra210.c
- +++ b/drivers/soc/tegra/fuse/speedo-tegra210.c
- @@ -69,6 +69,7 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
- u8 speedo_rev, int *threshold)
- {
- int sku = sku_info->sku_id;
- + int rev = sku_info->revision;
- /* Assign to default */
- sku_info->cpu_speedo_id = 0;
- @@ -77,27 +78,38 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
- *threshold = THRESHOLD_INDEX_0;
- switch (sku) {
- - case 0x00: /* Engineering SKU */
- case 0x01: /* Engineering SKU */
- + case 0x13: /* Engineering SKU */
- + if (rev == TEGRA_REVISION_A02) {
- + sku_info->cpu_speedo_id = 1;
- + sku_info->gpu_speedo_id = 2;
- + }
- + /* fall through for a01 */
- + case 0x00: /* Engineering SKU */
- case 0x07:
- case 0x17:
- case 0x27:
- - if (speedo_rev >= 2)
- - sku_info->gpu_speedo_id = 1;
- + sku_info->gpu_speedo_id = 1;
- break;
- -
- - case 0x13:
- - if (speedo_rev >= 2)
- - sku_info->gpu_speedo_id = 1;
- -
- - sku_info->cpu_speedo_id = 1;
- + case 0x83:
- + if (rev == TEGRA_REVISION_A02) {
- + sku_info->cpu_speedo_id = 1;
- + sku_info->gpu_speedo_id = 4;
- + break;
- + }
- + /* fall through for a01 */
- + case 0x87:
- + sku_info->gpu_speedo_id = 3;
- break;
- -
- default:
- pr_err("Tegra210: unknown SKU %#04x\n", sku);
- /* Using the default for the error case */
- break;
- }
- +
- + /* Overwrite GPU speedo selection for speedo revision 0, 1 */
- + if (speedo_rev < 2)
- + sku_info->gpu_speedo_id = 0;
- }
- static int get_process_id(int value, const u32 *speedos, unsigned int num)
- diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
- index 3e3d12c..8f361cc 100644
- --- a/drivers/soc/tegra/pmc.c
- +++ b/drivers/soc/tegra/pmc.c
- @@ -131,7 +131,7 @@ struct tegra_powergate {
- };
- struct tegra_io_pad_soc {
- - enum tegra_io_pad id;
- + unsigned int id;
- unsigned int dpd;
- unsigned int voltage;
- };
- @@ -408,6 +408,11 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
- usleep_range(10, 20);
- + if (pg->pmc->soc->needs_mbist_war)
- + err = tegra210_clk_handle_mbist_war(pg->id);
- + if (err)
- + goto disable_clks;
- +
- if (pg->pmc->soc->needs_mbist_war)
- err = tegra210_clk_handle_mbist_war(pg->id);
- if (err)
- @@ -907,7 +912,7 @@ static void tegra_powergate_init(struct tegra_pmc *pmc,
- }
- static const struct tegra_io_pad_soc *
- -tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
- +tegra_io_pad_find(struct tegra_pmc *pmc, unsigned int id)
- {
- unsigned int i;
- @@ -918,7 +923,7 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
- return NULL;
- }
- -static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request,
- +static int tegra_io_pad_prepare(unsigned int id, unsigned long *request,
- unsigned long *status, u32 *mask)
- {
- const struct tegra_io_pad_soc *pad;
- @@ -991,7 +996,7 @@ static void tegra_io_pad_unprepare(void)
- *
- * Returns: 0 on success or a negative error code on failure.
- */
- -int tegra_io_pad_power_enable(enum tegra_io_pad id)
- +int tegra_io_pad_power_enable(unsigned int id)
- {
- unsigned long request, status;
- u32 mask;
- @@ -1027,7 +1032,7 @@ EXPORT_SYMBOL(tegra_io_pad_power_enable);
- *
- * Returns: 0 on success or a negative error code on failure.
- */
- -int tegra_io_pad_power_disable(enum tegra_io_pad id)
- +int tegra_io_pad_power_disable(unsigned int id)
- {
- unsigned long request, status;
- u32 mask;
- @@ -1057,7 +1062,7 @@ unlock:
- }
- EXPORT_SYMBOL(tegra_io_pad_power_disable);
- -int tegra_io_pad_set_voltage(enum tegra_io_pad id,
- +int tegra_io_pad_set_voltage(unsigned int id,
- enum tegra_io_pad_voltage voltage)
- {
- const struct tegra_io_pad_soc *pad;
- @@ -1095,7 +1100,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
- }
- EXPORT_SYMBOL(tegra_io_pad_set_voltage);
- -int tegra_io_pad_get_voltage(enum tegra_io_pad id)
- +int tegra_io_pad_get_voltage(unsigned int id)
- {
- const struct tegra_io_pad_soc *pad;
- u32 value;
- diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
- index e09f035..11f5d87 100644
- --- a/drivers/thermal/of-thermal.c
- +++ b/drivers/thermal/of-thermal.c
- @@ -993,8 +993,7 @@ int __init of_parse_thermal_zones(void)
- goto exit_free;
- }
- - /* No hwmon because there might be hwmon drivers registering */
- - tzp->no_hwmon = true;
- + tzp->no_hwmon = !of_property_read_bool(child, "hwmon");
- if (!of_property_read_u32(child, "sustainable-power", &prop))
- tzp->sustainable_power = prop;
- diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
- index af2a29c..aecb97d 100644
- --- a/drivers/tty/serial/serial-tegra.c
- +++ b/drivers/tty/serial/serial-tegra.c
- @@ -46,6 +46,10 @@
- #define TEGRA_UART_LSR_ANY (UART_LSR_OE | UART_LSR_BI | \
- UART_LSR_PE | UART_LSR_FE)
- #define TEGRA_UART_IRDA_CSR 0x08
- +#define TEGRA_UART_INVERT_RXD 0x01
- +#define TEGRA_UART_INVERT_TXD 0x02
- +#define TEGRA_UART_INVERT_CTS 0x04
- +#define TEGRA_UART_INVERT_RTS 0x08
- #define TEGRA_UART_SIR_ENABLED 0x80
- #define TEGRA_UART_TX_PIO 1
- @@ -99,12 +103,17 @@ struct tegra_uart_port {
- unsigned long mcr_shadow;
- unsigned long lcr_shadow;
- unsigned long ier_shadow;
- + unsigned long irda_csr_shadow;
- bool rts_active;
- int tx_in_progress;
- unsigned int tx_bytes;
- bool enable_modem_interrupt;
- + bool invert_rxd;
- + bool invert_txd;
- + bool invert_cts;
- + bool invert_rts;
- bool rx_timeout;
- int rx_in_progress;
- @@ -1148,6 +1157,17 @@ static void tegra_uart_set_termios(struct uart_port *u,
- tty_termios_encode_baud_rate(termios, baud, baud);
- spin_lock_irqsave(&u->lock, flags);
- + /* Line inversions */
- + if (tup->invert_rxd)
- + tup->irda_csr_shadow |= TEGRA_UART_INVERT_RXD;
- + if (tup->invert_txd)
- + tup->irda_csr_shadow |= TEGRA_UART_INVERT_TXD;
- + if (tup->invert_cts)
- + tup->irda_csr_shadow |= TEGRA_UART_INVERT_CTS;
- + if (tup->invert_rts)
- + tup->irda_csr_shadow |= TEGRA_UART_INVERT_RTS;
- + tegra_uart_write(tup, tup->irda_csr_shadow, TEGRA_UART_IRDA_CSR);
- +
- /* Flow control */
- if (termios->c_cflag & CRTSCTS) {
- tup->mcr_shadow |= TEGRA_UART_MCR_CTS_EN;
- @@ -1221,6 +1241,14 @@ static int tegra_uart_parse_dt(struct platform_device *pdev,
- tup->enable_modem_interrupt = of_property_read_bool(np,
- "nvidia,enable-modem-interrupt");
- + tup->invert_rxd = of_property_read_bool(np,
- + "nvidia,invert-rxd");
- + tup->invert_txd = of_property_read_bool(np,
- + "nvidia,invert-txd");
- + tup->invert_cts = of_property_read_bool(np,
- + "nvidia,invert-cts");
- + tup->invert_rts = of_property_read_bool(np,
- + "nvidia,invert-rts");
- return 0;
- }
- diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
- index 4d5f5d6..0797a04 100644
- --- a/include/drm/drm_prime.h
- +++ b/include/drm/drm_prime.h
- @@ -50,8 +50,10 @@ struct drm_prime_file_private {
- struct rb_root handles;
- };
- +enum dma_data_direction;
- struct device;
- +struct dma_buf_attachment;
- struct dma_buf_export_info;
- struct dma_buf;
- struct dma_buf_attachment;
- @@ -62,7 +64,15 @@ struct drm_device;
- struct drm_gem_object;
- struct drm_file;
- -struct device;
- +int drm_gem_map_attach(struct dma_buf *dma_buf, struct device *target_dev,
- + struct dma_buf_attachment *attach);
- +void drm_gem_map_detach(struct dma_buf *dma_buf,
- + struct dma_buf_attachment *attach);
- +struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
- + enum dma_data_direction dir);
- +void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
- + struct sg_table *sgt,
- + enum dma_data_direction dir);
- struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
- struct drm_gem_object *obj,
- diff --git a/include/dt-bindings/soc/tegra/pmc.h b/include/dt-bindings/soc/tegra/pmc.h
- new file mode 100644
- index 0000000..65bddda
- --- /dev/null
- +++ b/include/dt-bindings/soc/tegra/pmc.h
- @@ -0,0 +1,79 @@
- +/*
- + * Copyright (c) 2010 Google, Inc
- + * Copyright (c) 2014 NVIDIA Corporation
- + *
- + * Author:
- + * Colin Cross <ccross@google.com>
- + *
- + * This software is licensed under the terms of the GNU General Public
- + * License version 2, as published by the Free Software Foundation, and
- + * may be copied, distributed, and modified under those terms.
- + *
- + * 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.
- + *
- + */
- +
- +#ifndef _DT_BINDINGS_SOC_TEGRA_PMC_H
- +#define _DT_BINDINGS_SOC_TEGRA_PMC_H
- +
- +#define TEGRA_IO_PAD_AUDIO 0
- +#define TEGRA_IO_PAD_AUDIO_HV 1
- +#define TEGRA_IO_PAD_BB 2
- +#define TEGRA_IO_PAD_CAM 3
- +#define TEGRA_IO_PAD_COMP 4
- +#define TEGRA_IO_PAD_CONN 5
- +#define TEGRA_IO_PAD_CSIA 6
- +#define TEGRA_IO_PAD_CSIB 7
- +#define TEGRA_IO_PAD_CSIC 8
- +#define TEGRA_IO_PAD_CSID 9
- +#define TEGRA_IO_PAD_CSIE 10
- +#define TEGRA_IO_PAD_CSIF 11
- +#define TEGRA_IO_PAD_DBG 12
- +#define TEGRA_IO_PAD_DEBUG_NONAO 13
- +#define TEGRA_IO_PAD_DMIC 14
- +#define TEGRA_IO_PAD_DMIC_HV 15
- +#define TEGRA_IO_PAD_DP 16
- +#define TEGRA_IO_PAD_DSI 17
- +#define TEGRA_IO_PAD_DSIB 18
- +#define TEGRA_IO_PAD_DSIC 19
- +#define TEGRA_IO_PAD_DSID 20
- +#define TEGRA_IO_PAD_EDP 21
- +#define TEGRA_IO_PAD_EMMC 22
- +#define TEGRA_IO_PAD_EMMC2 23
- +#define TEGRA_IO_PAD_GPIO 24
- +#define TEGRA_IO_PAD_HDMI 25
- +#define TEGRA_IO_PAD_HDMI_DP0 26
- +#define TEGRA_IO_PAD_HDMI_DP1 27
- +#define TEGRA_IO_PAD_HSIC 28
- +#define TEGRA_IO_PAD_HV 29
- +#define TEGRA_IO_PAD_LVDS 30
- +#define TEGRA_IO_PAD_MIPI_BIAS 31
- +#define TEGRA_IO_PAD_NAND 32
- +#define TEGRA_IO_PAD_PEX_BIAS 33
- +#define TEGRA_IO_PAD_PEX_CLK_BIAS 34
- +#define TEGRA_IO_PAD_PEX_CLK1 35
- +#define TEGRA_IO_PAD_PEX_CLK2 36
- +#define TEGRA_IO_PAD_PEX_CLK3 37
- +#define TEGRA_IO_PAD_PEX_CNTRL 38
- +#define TEGRA_IO_PAD_SDMMC1 39
- +#define TEGRA_IO_PAD_SDMMC1_HV 40
- +#define TEGRA_IO_PAD_SDMMC2 41
- +#define TEGRA_IO_PAD_SDMMC2_HV 42
- +#define TEGRA_IO_PAD_SDMMC3 43
- +#define TEGRA_IO_PAD_SDMMC3_HV 44
- +#define TEGRA_IO_PAD_SDMMC4 45
- +#define TEGRA_IO_PAD_SPI 46
- +#define TEGRA_IO_PAD_SPI_HV 47
- +#define TEGRA_IO_PAD_SYS_DDC 48
- +#define TEGRA_IO_PAD_UART 49
- +#define TEGRA_IO_PAD_UFS 50
- +#define TEGRA_IO_PAD_USB0 51
- +#define TEGRA_IO_PAD_USB1 52
- +#define TEGRA_IO_PAD_USB2 53
- +#define TEGRA_IO_PAD_USB3 54
- +#define TEGRA_IO_PAD_USB_BIAS 55
- +
- +#endif /* _DT_BINDINGS_SOC_TEGRA_PMC_H */
- diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h
- index afb9edf..79809de 100644
- --- a/include/linux/clk/tegra.h
- +++ b/include/linux/clk/tegra.h
- @@ -128,6 +128,11 @@ extern void tegra210_sata_pll_hw_sequence_start(void);
- extern void tegra210_set_sata_pll_seq_sw(bool state);
- extern void tegra210_put_utmipll_in_iddq(void);
- extern void tegra210_put_utmipll_out_iddq(void);
- +#ifndef CONFIG_ARCH_TEGRA_210_SOC
- +static inline int tegra210_clk_handle_mbist_war(unsigned int id)
- +{ return -ENODEV; }
- +#else
- extern int tegra210_clk_handle_mbist_war(unsigned int id);
- +#endif
- #endif /* __LINUX_CLK_TEGRA_H_ */
- diff --git a/include/linux/host1x.h b/include/linux/host1x.h
- index ddf7f9c..fd4daa7 100644
- --- a/include/linux/host1x.h
- +++ b/include/linux/host1x.h
- @@ -1,5 +1,5 @@
- /*
- - * Copyright (c) 2009-2013, NVIDIA Corporation. All rights reserved.
- + * Copyright (C) 2009-2016 NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- @@ -71,6 +71,7 @@ struct host1x_client {
- * host1x buffer objects
- */
- +struct dma_fence;
- struct host1x_bo;
- struct sg_table;
- @@ -258,6 +259,9 @@ struct host1x_job {
- /* Add a channel wait for previous ops to complete */
- bool serialize;
- +
- + /* Wait for prefence to complete before submitting */
- + struct dma_fence *prefence;
- };
- struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
- @@ -343,4 +347,10 @@ int tegra_mipi_enable(struct tegra_mipi_device *device);
- int tegra_mipi_disable(struct tegra_mipi_device *device);
- int tegra_mipi_calibrate(struct tegra_mipi_device *device);
- +struct host1x_fence;
- +
- +struct dma_fence *host1x_fence_create(struct host1x *host,
- + struct host1x_syncpt *syncpt,
- + u32 threshold);
- +
- #endif
- diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
- index 25602af..1b212aa 100644
- --- a/include/linux/regulator/consumer.h
- +++ b/include/linux/regulator/consumer.h
- @@ -251,6 +251,8 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
- int regulator_set_voltage_time(struct regulator *regulator,
- int old_uV, int new_uV);
- int regulator_get_voltage(struct regulator *regulator);
- +int regulator_get_constraint_voltages(struct regulator *regulator,
- + int *min_uV, int *max_uV);
- int regulator_sync_voltage(struct regulator *regulator);
- int regulator_set_current_limit(struct regulator *regulator,
- int min_uA, int max_uA);
- diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
- index c32bf91..14bac22 100644
- --- a/include/soc/tegra/pmc.h
- +++ b/include/soc/tegra/pmc.h
- @@ -22,6 +22,7 @@
- #include <linux/reboot.h>
- #include <soc/tegra/pm.h>
- +#include <dt-bindings/soc/tegra/pmc.h>
- struct clk;
- struct reset_control;
- @@ -70,72 +71,6 @@ int tegra_pmc_cpu_remove_clamping(unsigned int cpuid);
- #define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D
- -/**
- - * enum tegra_io_pad - I/O pad group identifier
- - *
- - * I/O pins on Tegra SoCs are grouped into so-called I/O pads. Each such pad
- - * can be used to control the common voltage signal level and power state of
- - * the pins of the given pad.
- - */
- -enum tegra_io_pad {
- - TEGRA_IO_PAD_AUDIO,
- - TEGRA_IO_PAD_AUDIO_HV,
- - TEGRA_IO_PAD_BB,
- - TEGRA_IO_PAD_CAM,
- - TEGRA_IO_PAD_COMP,
- - TEGRA_IO_PAD_CONN,
- - TEGRA_IO_PAD_CSIA,
- - TEGRA_IO_PAD_CSIB,
- - TEGRA_IO_PAD_CSIC,
- - TEGRA_IO_PAD_CSID,
- - TEGRA_IO_PAD_CSIE,
- - TEGRA_IO_PAD_CSIF,
- - TEGRA_IO_PAD_DBG,
- - TEGRA_IO_PAD_DEBUG_NONAO,
- - TEGRA_IO_PAD_DMIC,
- - TEGRA_IO_PAD_DMIC_HV,
- - TEGRA_IO_PAD_DP,
- - TEGRA_IO_PAD_DSI,
- - TEGRA_IO_PAD_DSIB,
- - TEGRA_IO_PAD_DSIC,
- - TEGRA_IO_PAD_DSID,
- - TEGRA_IO_PAD_EDP,
- - TEGRA_IO_PAD_EMMC,
- - TEGRA_IO_PAD_EMMC2,
- - TEGRA_IO_PAD_GPIO,
- - TEGRA_IO_PAD_HDMI,
- - TEGRA_IO_PAD_HDMI_DP0,
- - TEGRA_IO_PAD_HDMI_DP1,
- - TEGRA_IO_PAD_HSIC,
- - TEGRA_IO_PAD_HV,
- - TEGRA_IO_PAD_LVDS,
- - TEGRA_IO_PAD_MIPI_BIAS,
- - TEGRA_IO_PAD_NAND,
- - TEGRA_IO_PAD_PEX_BIAS,
- - TEGRA_IO_PAD_PEX_CLK_BIAS,
- - TEGRA_IO_PAD_PEX_CLK1,
- - TEGRA_IO_PAD_PEX_CLK2,
- - TEGRA_IO_PAD_PEX_CLK3,
- - TEGRA_IO_PAD_PEX_CNTRL,
- - TEGRA_IO_PAD_SDMMC1,
- - TEGRA_IO_PAD_SDMMC1_HV,
- - TEGRA_IO_PAD_SDMMC2,
- - TEGRA_IO_PAD_SDMMC2_HV,
- - TEGRA_IO_PAD_SDMMC3,
- - TEGRA_IO_PAD_SDMMC3_HV,
- - TEGRA_IO_PAD_SDMMC4,
- - TEGRA_IO_PAD_SPI,
- - TEGRA_IO_PAD_SPI_HV,
- - TEGRA_IO_PAD_SYS_DDC,
- - TEGRA_IO_PAD_UART,
- - TEGRA_IO_PAD_UFS,
- - TEGRA_IO_PAD_USB0,
- - TEGRA_IO_PAD_USB1,
- - TEGRA_IO_PAD_USB2,
- - TEGRA_IO_PAD_USB3,
- - TEGRA_IO_PAD_USB_BIAS,
- -};
- -
- /* deprecated, use TEGRA_IO_PAD_{HDMI,LVDS} instead */
- #define TEGRA_IO_RAIL_HDMI TEGRA_IO_PAD_HDMI
- #define TEGRA_IO_RAIL_LVDS TEGRA_IO_PAD_LVDS
- @@ -160,11 +95,11 @@ int tegra_powergate_remove_clamping(unsigned int id);
- int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
- struct reset_control *rst);
- -int tegra_io_pad_power_enable(enum tegra_io_pad id);
- -int tegra_io_pad_power_disable(enum tegra_io_pad id);
- -int tegra_io_pad_set_voltage(enum tegra_io_pad id,
- +int tegra_io_pad_power_enable(unsigned int id);
- +int tegra_io_pad_power_disable(unsigned int id);
- +int tegra_io_pad_set_voltage(unsigned int id,
- enum tegra_io_pad_voltage voltage);
- -int tegra_io_pad_get_voltage(enum tegra_io_pad id);
- +int tegra_io_pad_get_voltage(unsigned int id);
- /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
- int tegra_io_rail_power_on(unsigned int id);
- @@ -202,23 +137,23 @@ static inline int tegra_powergate_sequence_power_up(unsigned int id,
- return -ENOSYS;
- }
- -static inline int tegra_io_pad_power_enable(enum tegra_io_pad id)
- +static inline int tegra_io_pad_power_enable(unsigned int id)
- {
- return -ENOSYS;
- }
- -static inline int tegra_io_pad_power_disable(enum tegra_io_pad id)
- +static inline int tegra_io_pad_power_disable(unsigned int id)
- {
- return -ENOSYS;
- }
- -static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id,
- +static inline int tegra_io_pad_set_voltage(unsigned int id,
- enum tegra_io_pad_voltage voltage)
- {
- return -ENOSYS;
- }
- -static inline int tegra_io_pad_get_voltage(enum tegra_io_pad id)
- +static inline int tegra_io_pad_get_voltage(unsigned int id)
- {
- return -ENOSYS;
- }
- diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
- index 259588a..e50e655 100644
- --- a/include/uapi/drm/nouveau_drm.h
- +++ b/include/uapi/drm/nouveau_drm.h
- @@ -114,6 +114,18 @@ struct drm_nouveau_gem_pushbuf {
- __u64 gart_available;
- };
- +#define NOUVEAU_GEM_PUSHBUF_FENCE_WAIT (1 << 0)
- +#define NOUVEAU_GEM_PUSHBUF_FENCE_EMIT (1 << 1)
- +#define NOUVEAU_GEM_PUSHBUF_FLAGS (NOUVEAU_GEM_PUSHBUF_FENCE_WAIT | \
- + NOUVEAU_GEM_PUSHBUF_FENCE_EMIT)
- +
- +struct drm_nouveau_gem_pushbuf2 {
- + struct drm_nouveau_gem_pushbuf base;
- + __u32 flags;
- + __s32 fence;
- + __u64 reserved;
- +};
- +
- #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001
- #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004
- struct drm_nouveau_gem_cpu_prep {
- @@ -138,12 +150,14 @@ struct drm_nouveau_gem_cpu_fini {
- #define DRM_NOUVEAU_GEM_CPU_PREP 0x42
- #define DRM_NOUVEAU_GEM_CPU_FINI 0x43
- #define DRM_NOUVEAU_GEM_INFO 0x44
- +#define DRM_NOUVEAU_GEM_PUSHBUF2 0x45
- #define DRM_IOCTL_NOUVEAU_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new)
- #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf)
- #define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep)
- #define DRM_IOCTL_NOUVEAU_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_FINI, struct drm_nouveau_gem_cpu_fini)
- #define DRM_IOCTL_NOUVEAU_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_INFO, struct drm_nouveau_gem_info)
- +#define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF2 DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF2, struct drm_nouveau_gem_pushbuf2)
- #if defined(__cplusplus)
- }
- diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
- index d954f8c..03492d6 100644
- --- a/include/uapi/drm/tegra_drm.h
- +++ b/include/uapi/drm/tegra_drm.h
- @@ -117,6 +117,11 @@ struct drm_tegra_waitchk {
- __u32 thresh;
- };
- +#define DRM_TEGRA_SUBMIT_WAIT_FENCE_FD (1 << 0)
- +#define DRM_TEGRA_SUBMIT_CREATE_FENCE_FD (1 << 1)
- +#define DRM_TEGRA_SUBMIT_FLAGS (DRM_TEGRA_SUBMIT_WAIT_FENCE_FD | \
- + DRM_TEGRA_SUBMIT_CREATE_FENCE_FD)
- +
- struct drm_tegra_submit {
- __u64 context;
- __u32 num_syncpts;
- @@ -129,9 +134,10 @@ struct drm_tegra_submit {
- __u64 cmdbufs;
- __u64 relocs;
- __u64 waitchks;
- - __u32 fence; /* Return value */
- + __u32 fence;
- + __u32 flags;
- - __u32 reserved[5]; /* future expansion */
- + __u32 reserved[4]; /* future expansion */
- };
- #define DRM_TEGRA_GEM_TILING_MODE_PITCH 0
Add Comment
Please, Sign In to add comment