Compare commits

148 Commits
Author SHA1 Message Date
tmakin eff4d587d2 xusb: t210: support utmi pad biasing
Based on t186 driver and downstream:
https://gitlab.com/nvidia/nv-tegra/linux-4.9/-/commit/8d05313ac9fd54a2fc373a0e789390dfa0607726
2026-09-12 12:52:17 -05:00
tmakin 366514a4be bm92t 2026-09-12 01:04:02 -05:00
tmakin f9b2980f86 gki hax 2026-09-12 01:03:55 -05:00
Bibhay Ranjan 494a158389 pinctrl: t210b01: Add SDMMC2 pinmux support
Add sdmmc2 pinmux support inorder to use
SDMMC2 controller on t210b01 platforms.

Bug 200360711

Change-Id: Ie2d3a20d10325d42dc5dbf601c9da747ff0caa66
Signed-off-by: Bibhay Ranjan <bibhayr@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1593367
Reviewed-on: https://git-master.nvidia.com/r/1648549
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: Pavan Kunapuli <pkunapuli@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2026-08-30 12:20:53 -05:00
tmakin a409dcbfec xusb: tegra210: add needed reg for b01 2026-08-28 19:17:11 -05:00
Peter De Schrijver 98f77a3a33 clk: tegra: dfll: fix use of tune values
There was some confusion on the use of the tune values. They were
defined in 2 different structs, but only initialzed in one of them.
Remove most of the references in struct tegra_dfll_soc_data and adjust
the code accordingly. Only tune_high_min_millivolts is left, because
this can be adjusted using debugfs. Hence copy the initial value from
the cvb table at boot.
2026-08-28 19:17:11 -05:00
Peter De Schrijver fd2bf45a19 clk: tegra: apply regulator align to Vmin
Apply regulator alignment when using Vmin to determine the lowest possible
rate generated by the DFLL.

Change-Id: I169528614871733e4a7568f3ec740079b0e9d097
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1584439
GVS: Gerrit_Virtual_Submit
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
2026-08-28 19:17:10 -05:00
tmakin 0c0127fdc3 soc/tegra: fuse: print speedo IDs on info 2026-08-28 19:17:10 -05:00
tmakin 4e346d269a drm/tegra: dsi: detect possible_crtcs
Other platforms allow dsi across multiple heads, but some have
one or more heads disabled. This results in a mismatch between
possible_crtcs and the real crtc mask. Apply the same
`tegra_output_find_possible_crtcs` function to DSI to properly
detect.
2026-08-28 19:17:10 -05:00
Alex Frid 8e4d11a333 soc: tegra: Add support for DFLL Vmin CVB
Added Vmin coefficients to CPU DFLL CVB table, and updated Vmin
calculations during OPP table build accordingly. Changed build function
signature to return final Vmin.

Bug 1906940

Change-Id: I6e19266f865e9a3dda21c9e0f7178feece055ddf
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1565468
Reviewed-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Tested-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Timo Alho <talho@nvidia.com>
2026-08-28 19:17:10 -05:00
Alex Frid 3543245775 clk: soc: tegra: Add DFLL tune high margin voltage
Added DFLL tune high margin voltage entry in CVB table. This allows to
replace current fixed margin defined as number of DFLL voltage steps
with per-table/per-chip margin in millivolts, and convert it to steps
during DFLL initialization.

Bug 1967884

Change-Id: I56268ae2faf9cc633b9f988cacbfd0ea3ba77ff3
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1576307
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2026-08-28 19:17:10 -05:00
Alex Frid cbf2e8abe9 clk: soc: tegra: Add DFLL tune1_high parameter
Added support for DFLL tune1_high parameter

Bug 1967884

Change-Id: I0140724a22c43a3b05d39735b7a7faebd4be2908
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1577129
Reviewed-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Tested-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
2026-08-28 19:17:10 -05:00
tmakin acf07bcb94 clk: tegra: add locking support to DFLL
Based on part of https://gitlab.com/nvidia/nv-tegra/linux-4.9/-/commit/4f0b1e6e76f7b0ff8d028c66d34da9f37ca39233
2026-08-28 19:17:09 -05:00
Alex Frid e449ec78a4 clk: soc: tegra: Rename DFLL tune1 to tune1_low
Renamed DFLL tune1 to tune1_low to be consistent with
tune0_low/tune0_high naming convention.

Bug 1967884

Change-Id: If23170305143b05c2918e04691c73fe13b777272
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1576306
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2026-08-28 19:17:09 -05:00
Vince Hsu 35a4c34d22 clk: tegra: add DFLL dynamic tuning support
This patch is heavily based on the DFLL driver which is
written by Paul Walmsley and used by Tegra124 Chrome
projects currently.

The DFLL output can be fine tuned by the tuning parameters
depending on the voltage threshold. Both of the tuning
parameters and voltage threshold are specified by the
chip characterization. This patch introduces a tuning
timer which controls/monitors the tuning status. When
the DFLL is in open loop, only the tune low parameter
can be used. Once the DFLL enters the close loop, we
can switch to the tune high state if the output voltage
goes higher than the predefined threshold.

Added support for PWM regulator based DFLL.

Bug 200262988

Change-Id: I5ed51fbbf4b18cbd8cced5ab27848817201d8b39
Signed-off-by: Vince Hsu <vinceh@nvidia.com>
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1565464
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Timo Alho <talho@nvidia.com>
2026-08-28 19:17:09 -05:00
tmakin e07a012ff0 gpio: tegra: deprecate static allocation 2026-08-28 19:17:09 -05:00
tmakin a87a23eb5b tegra210b01: use tegra210b01 pinctrl 2026-08-28 19:17:09 -05:00
Laxman Dewangan 8530ab4958 pinctrl: tegra210: Add support for LPDR bit
Tegra SOC Tegra210b01 have the support for LPDR configuration
via DT property "nvidia,lpdr".

Add support for configuring this property.

bug 200302268

Change-Id: I314af7f5094de6097f3c5944b28ad91ca61b1fdd
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/1469552
Reviewed-on: https://git-master.nvidia.com/r/1557094
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Pavan Kunapuli <pkunapuli@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-28 19:17:09 -05:00
Maulik Shah bd1802e48c gpio: Use IRQ trigger mask helpers
Use IRQ_TYPE_LEVEL_MASK and IRQ_TYPE_EDGE_BOTH instead of open-coded
trigger type combinations in irqchip callbacks.

No functional change intended.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Maulik Shah <maulik.shah@oss.qualcomm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260802-b4b4-irq-trigger-mask-gpio-v1-1-948973636c84@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-08-28 19:17:09 -05:00
Runyu Xiao 75be9aeeac gpio: tegra: do not call pinctrl for GPIO direction
tegra_gpio_direction_input() and tegra_gpio_direction_output() already
program the GPIO controller direction registers directly. The additional
pinctrl_gpio_direction_input/output() calls do not add a Tegra pinctrl
operation, because the Tegra pinmux ops provide GPIO request/free
handling but no gpio_set_direction hook.

The extra call still enters the pinctrl core and takes pctldev->mutex.
Shared GPIO users can call the direction path while holding their
per-line spinlock, so this otherwise redundant pinctrl direction call can
sleep in an atomic context.

This was found by our static analysis tool and then confirmed by manual
review of tegra_gpio_probe(), the Tegra GPIO direction callbacks and the
Tegra pinctrl ops. The reviewed path has a default non-sleeping
struct gpio_chip while the direction callback still enters the pinctrl
mutex path.

A directed runtime validation kept the same non-sleeping chip registration
and drove:

  gpio_shared_proxy_direction_output()
  gpiod_direction_output_raw_commit()
  tegra_gpio_direction_output()
  pinctrl_gpio_direction_output()

Lockdep reported a sleep-in-atomic warning with the shared GPIO spinlock
held and pinctrl_get_device_gpio_range() plus tegra_gpio_direction_output()
on the stack.

Do not mark the whole chip as can_sleep to paper over this: can_sleep
describes whether get()/set() may sleep, and Tegra value access is MMIO.
Remove the redundant pinctrl direction calls and keep pinctrl involvement
in the existing request/free path.

Fixes: 11da905412 ("gpio: tegra: Fix offset of pinctrl calls")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Link: https://patch.msgid.link/20260619152439.1239561-1-runyu.xiao@seu.edu.cn
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
2026-08-28 19:17:08 -05:00
tmakin dd86f157f6 Revert "bm92t: convert to typec fwk"
This reverts commit ee65e16217.
2026-08-28 19:17:08 -05:00
tmakin ee65e16217 bm92t: convert to typec fwk
note: ai
2026-08-24 18:39:43 -05:00
tmakin 84af317cf3 bm92t fix 2026-08-24 18:39:43 -05:00
tmakin a64e4bf1c1 bm92t: err change 2026-08-24 18:39:43 -05:00
tmakin a75c8520d0 power: bq24190: add get_current_limit 2026-08-24 18:39:43 -05:00
tmakin bbf04e9a89 emc: t186: fix mutex 2026-08-24 18:39:43 -05:00
tmakin c66af1b766 pci: tegra: update lanes if dt incorrect 2026-08-24 18:39:43 -05:00
tmakin 2458ea9a04 Revert "mmc: sdhci: pedantic clock rate debug logging"
This reverts commit 17bfd541f2b904f4ba87f0fcb3e2d3b4332d1802.
2026-08-24 18:39:43 -05:00
tmakin 14f6277465 sor: allow selection of alt sor1 tuning 2026-08-24 18:39:42 -05:00
tmakin d786880067 mmc: sdhci: pedantic clock rate debug logging
Add pr_info-level logging across the SDHCI subsystem and the Tegra
SDMMC clock providers so clock rate calculation, rounding, assigned
clocks and parents are visible in dmesg without needing dynamic_debug.

  - sdhci-tegra: log curr_clk_rate/max_clk/clock on set_clock entry and
    after clk_get_rate(), the requested host_clk, the rounded
    get_max_clock value, and dump regs before hw tuning.
  - sdhci: promote the DBG() macro from pr_debug to pr_info and log
    host->clock/max_clk/clock plus the computed divider/actual clock
    in sdhci_calc_clk() and sdhci_set_clock().
  - clk-sdmmc-mux / clk-divider / clk-utils: log div, mul, parent_rate,
    rounded rate and recalc_rate results in round_rate/recalc_rate/
    set_rate/div_frac_get so the full rate decision path is traceable.
  - mmc core: log the requested speed in mmc_set_clock() and the
    tuning entry/host-exec points in mmc_execute_tuning().

Change-Id: I4d569a01da8355db3319e82de942f1401dfac911
2026-08-24 18:39:42 -05:00
Alexandre Hamamdjian e3d103cf3e dt-bindings: usb: add Rohm BM92TXX Type-C controller
Add the device-tree binding documentation for the Rohm BM92TXX family
of USB Type-C and Power Delivery controllers. The device is controlled
over I2C and signals state changes through a dedicated interrupt line.

Document the rohm,* properties consumed by the driver: the optional
VCONN-enable GPIO, the DisplayPort alternate-mode toggles
(rohm,dp-disable, rohm,dp-alerts-enable, rohm,dp-signal-toggle-on-resume,
rohm,dp-lanes), the suspend/dock tunables (rohm,led-static-on-suspend,
rohm,dock-power-limit-disable) and the four
rohm,pd-{5,9,12,15}v-current-limit-ma per-PDO charging current limits.
A graph port is required to link the controller to a USB role switch
consumer.

Signed-off-by: Alexandre Hamamdjian <azkali.limited@gmail.com>
2026-08-24 18:39:42 -05:00
CTCaer c7a50eb91f usb: typec: bm92txx: add Rohm BM92TXX support
Add a driver for the Rohm Semiconductor BM92TXX family of USB Type-C
and Power Delivery controllers. The IC integrates an MCU that runs the
PD state machine; the host configures it and observes status over I2C
and reacts to a level-triggered ALERT interrupt.

The driver exposes the controller through extcon and a USB role switch,
manages the VBUS sink, optional VBUS source and battery-charger
regulators along with the VCONN-enable GPIO, and applies per-PDO
charging current limits (5 V, 9 V, 12 V, 15 V) sourced from device
tree. DisplayPort alternate-mode handling and dock LED behaviour are
configurable through rohm,* properties so the same driver can serve
boards that wire the part up differently. A debugfs interface under
bm92txx/ is provided for register dumps and low-level command access
when CONFIG_DEBUG_FS is enabled.

Signed-off-by: CTCaer <ctcaer@gmail.com>
Signed-off-by: Alexandre Hamamdjian <azkali.limited@gmail.com>
2026-08-24 18:39:42 -05:00
azkali 84d6d81d7e regulator: fan52555: add support for fan53528 fan 2026-08-24 18:39:42 -05:00
tmakin 18b308e7ed t210: assign better mmc clocks 2026-08-24 18:39:42 -05:00
tmakin fe8a0116e4 clk changes, test later 2026-08-24 18:39:42 -05:00
Laxman Dewangan ea82274201 NVIDIA: SAUCE: platform: tegra: Add tegra prod as built-in driver
BugLink: https://bugs.launchpad.net/bugs/2080908

This is an integration squash change of below commits.

 - [INTG: NV INTERNAL] platform: tegra: Add tegra prod as built-in
 - [INTG: NV INTERNAL] platform: tegra: Add tegra prod framework
 - [INTG: NV INTERNAL] platform: tegra: Add support for mask with 1s
 - [INTG: NV INTERNAL] platform: tegra_prod: Use kmemleak_not_leak for allocated memory
 - [INTG: NV INTERNAL] platform: tegra_prod: Fix prod setting parsing for package/board
 - [INTG: NV INTERNAL] platform: tegra_prod: Use proper variable name
 - [INTG: NV INTERNAL] platform: tegra_prod: Use for_each_available_child_of_node()
 - [INTG: NV INTERNAL] platform: tegra: move struct tegra_prod_list to private
 - [INTG: NV INTERNAL] platform: tegra_prod: Add APIs to managed allocation of prod_list
 - [INTG: NV INTERNAL] platform: tegra_prod: Remove unused APIs from public header
 - [INTG: NV INTERNAL] platform: tegra_prod: Get rid of tegra_prod_release()
 - [INTG: NV INTERNAL] platform: tegra_prod: Add support for nested prod nodes
 - [INTG: NV INTERNAL] platform: tegra_prod: Add devm_tegra_prod_get_from_node()
 - [INTG: NV INTERNAL] platform: tegra_prod: use devm_ for allocation
 - [INTG: NV INTERNAL] platform: tegra_prod: Do not use kmemleak_not_leak()
 - [INTG: NV INTERNAL] platform: tegra: Add support to find prod setting
 - [INTG: NV INTERNAL] platform: tegra: APIs to set prod based on name/index/offset/mask
 - [INTG: NV INTERNAL] prod: Add support for masked write in partially prod config
 - [INTG: NV INTERNAL] platform: tegra_prod: Use strcasecmp() for prod name
 - [INTG: NV INTERNAL] prod: set prod-settings mask to 1-style default
 - [INTG: NV INTERNAL] platform: tegra_prod: add support to avoid multiple configruation
 - soc: tegra: Add prod configuration parser
 - prod: remove package and board specific prod node
 - platform: tegra: Add config for next generation tegra prod
 - tegra-prod: Add legacy and next gen prod based on config
 - tegra-prod: Fix missing last entry
 - tegra-prod: Fix null pointer error
 - tegra-prod: Fix null pointer error
 - tegra: prod: remove new prod settings support

http://nvbugs/4165866
http://nvbugs/200416207
http://nvbugs/1758682
http://nvbugs/1745386
http://nvbugs/1768583
http://nvbugs/200217343
http://nvbugs/200215286
http://nvbugs/1807581
http://nvbugs/1865456
http://nvbugs/4097475
http://nvbugs/3389584
http://nvbugs/4638219
http://nvbugs/4283554
http://nvbugs/4765671
http://nvbugs/4754882

Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com>
Acked-by: Noah Wager <noah.wager@canonical.com>
Acked-by: Jacob Martin <jacob.martin@canonical.com>
Signed-off-by: Noah Wager <noah.wager@canonical.com>
2026-08-24 18:39:41 -05:00
tmakin 9fcb37425f clk: tegra210: update pll_c4 parameters 2026-08-24 18:39:41 -05:00
tmakin 10d17dbcce ftm4: compile fixes 2026-08-24 18:39:41 -05:00
Alvin Park bc5942c904 serial: tegra: clear tx_in_progress in flush func
Cleared tx_in_progress when tegra_uart_flush_buffer is called.
If tegra_uart_flush_buffer is called before complete to transmit
through DMA, next transmit could not be started because
tx_in_progress is not cleared.

Bug 3098159

Change-Id: I4b6b001314479313d7854d04a10d8394357a37cf
Signed-off-by: Alvin Park <apark@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-4.9/+/2405363
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Hardik T Shah <hardikts@nvidia.com>
Reviewed-by: Phoenix Jung <pjung@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Signed-off-by: CTCaer <ctcaer@gmail.com>
2026-08-24 18:39:41 -05:00
azkali b54985fe3d touchscreen: stm: forward port ftm4 touchscreen driver from L4T 2026-08-24 18:39:41 -05:00
tmakin 3091c05197 dts: misc updates 2026-08-24 18:39:41 -05:00
tmakin f11ecb413d memory: tegra: populate dt subnodes
Tegra210b01 uses tegra186-emc driver as emc clock is controlled by BPMP.
However, this driver expects emc as subnode of mc. Adjust Tegra30 mc
probe routine to populate subnodes.
2026-08-24 18:39:41 -05:00
Vidya Sagar 74ff5e5f6d PCI: tegra: add PCI_REASSIGN_ALL_BUS flag
adds PCI_REASSIGN_ALL_BUS pci flag so as to enable
re-assigning bus numbers (if there is any bridge device added
recently) during rescan.

Bug 200192107

Change-Id: Iffc02827a75dcb82f5e02b69e96e65b38a0b7cd6
Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Reviewed-on: http://git-master/r/1144609
(cherry picked from commit 26464cda2eff345548e3271f26b00ddcd79d9264)
Reviewed-on: http://git-master/r/1176833
(cherry picked from commit bf21f6959bbecc70b4dce07329e0deea32b41b67)
Reviewed-on: http://git-master/r/1141937
(cherry picked from commit 284d2e97ce311771808d8dbd75c861a95c16d031)
Reviewed-on: http://git-master/r/1210983
(cherry picked from commit ef83e7563eb0ce4dad493abba2c92d20a67f41ac)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-4.14/+/2371135
(cherry picked from commit a43acb68398f7fd6208988684698b49962b3c6f9)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407883
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:41 -05:00
Manikanta Maddireddy 31811f31cc PCI: tegra: Add DT support to disable CLKREQ# control on PLLE
Sometimes CLKREQ# pin connection might be missing on a platform. Add DT
support to disable CLKREQ# control on PLLE in driver. Platform device tree
can use this DT property to disable CLKREQ# control on PLLE. In kernel-5.9,
upstream device tree property "supports-clkreq" is used in place of
kernel-4.14 custom device tree property "nvidia,disable-clock-request".

bug 200420606

Change-Id: I6ac44bd99d090e158fa10e5e9b62d63e52563c8c
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786551
(cherry picked from commit 6870a94b48a4bbbe9df607802c7f7c1f61806b7b)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407880
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Manikanta Maddireddy a5329b2b64 PCI: tegra: aspm DT support
Squashed below k414 commits into single change.

PCI: tegra: Add DT support to disable per state aspm

Kernel config option provides choice to disable L0s & L1 or L1 substates
combinedly. Add DT support to disable each aspm state individually.

bug 200420606

Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786548
(cherry picked from commit f3c5bcdc3ab8cadd3d24ea4d1a8e0aba7beea751)

PCI: tegra: Fix ASPM DT property parsing code

DT property "nvidia,disable-aspm-states" is part of PCIe port node.
Use correct of_node pointer to parse this property.

bug 200434876

Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-4.14/+/2383766
(cherry picked from commit 8dd957e9ecf29da4ba94471e3d74b2aef98a0643)

Change-Id: Iee1f573a103c0045d4f8f6606db13b47575b8cb9
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2408709
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: Bitan Biswas <bbiswas@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2026-08-24 18:39:40 -05:00
Manikanta Maddireddy b9088d4a23 PCI: tegra: Bypass CLKREQ# control over PLLE
When PCIe link is L2 CLKREQ# will be floating and this might interfere
with PLL power down. Bypass CLKREQ# control over PLLE when link is in L2.

bug 1356695
bug 200420606

Change-Id: I361db03df5f9a1a8d38bd9fb816d17fc4c64a9fc
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786565
(cherry picked from commit 69e79f42f65df70b0c76e62200aca40ed3972e3b)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407877
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Manikanta Maddireddy fddd6304c2 PCI: tegra: Fix incorrect CLKREQ and PLLE programming
CLKREQ_EN bit should be cleared to control REFCLK through CLKREQ# pin.
Enable PCIE2PLLE bit to control PLLE through clock clamp signal.
Program PADS2PLLE and PCIE2PLLE bits only if Tegra PCIe supports L1SS.

bug 200420606

Change-Id: I04cacf64fce8eed0f17bb632457ffcc9f052819d
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786550
(cherry picked from commit e71a64e47225b848c9b8a1d33e8c80a7bdb9d3cc)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407876
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Vidya Sagar 5150f5d841 PCI: tegra: Fixups to avoid unnecessary wakeup from ASPM-L1.2
sets CLKREQ asserted delay to a higher value to avoid
unnecessary wake up from L1.2.ENTRY state for Tegra210

bug 200420606

Change-Id: Iec2564bfd434897f0e50cd3f0ad6bc76aacc12e8
Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786545
(cherry picked from commit d7785c1e6c98e33a85ba9487d3be6ab7e518a285)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407875
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Vidya Sagar 322c8e45b5 PCI: tegra: Apply sw fixups to support ASPM-L1 Sub-States
Programs Port Common_Mode_Restore_Time and Port T_POWER_ON values
(from the L1 PM Substates Capabilities Register, PCIe 4.0r0.9, sec 7.8.3.2)
to get them reflected in ASPM-L1 Sub-States capability registers.
Also adjusts internal counter values according to 19.2 MHz clk_m value.

bug 200420606

Change-Id: Ie139255e522e4476fdfbe64aa6250d0293b7ae89
Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786544
(cherry picked from commit 9ac6211e1a99583618945c86748214ccc33de463)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407874
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Manikanta Maddireddy 7b4c276857 PCI: tegra: Configure L1 power save parameters
Programmed bits of register RP_VEND_XP_PAD_PWRDN are defined as follows,

L1(bit[0]):
 This bit, when set, causes the analog pads to power down when we're in L1.
 When clear, the LTSSM still enters L1 as required, but the analog pads
 are left at full power.
DYNAMIC(bit[1]):
 This bit, when set, causes unused analog pads to power down after
 "Dynamic Link Width Re-negotiation" takes place.  When clear, all analog
 pads remain powered up, even those that are no longer being used after
 "Dynamic Link Width Re-negotiation" down-sizes the link.
DISABLED(bit[2]):
 This bit, when set, causes the analog pads to power down when we're in the
 DISABLED_DOWN state. When clear, the LTSSM still enters DISBLED_DOWN as
 required, but the analog pads are left at full power.
L1_CLKREQ(bit[15]):
 This bit, when set, causes the analog pads to power down to
 SLEEP_MODE_L1_REQ when clkreq signal is deasserted in L1.
 (NV_PROJ__PCIE2_RP_VEND_XP_PAD_PWRDN_L1 needs to be set in order to power
 down pad in L1.)  Also, when clkreq is asserted in L1, ltssm will exit L1
 immediately. When clear, the clkreq signal doesn't affect the power
 management.
SLEEP_MODE_L1(bits[4:3]):
 It defines the 2-bit sleep-mode coding in the pad when LTSSM is in the L1
 state or DISABLED state.
SLEEP_MODE_DYNAMIC(bits[6:5]):
 It defines the 2-bit sleep-mode coding in the pad when the lane shut down
 due to dynamic link downsizing.
SLEEP_MODE_L1_CLKREQ(bits[17:16]):
 It defines the 2-bit sleep-mode coding when clkreq is deasserted in L1.
The 2-bit sleep-mode encoding is defined as:
 - L0 (0x0): Normal power-up mode
 - L1 (0x1): L1 power-down mode; Tx common mode on, Rx e-idle detect on
 - L1P (0x2): L1 power-down mode; Tx common mode off, Rx e-idle detect on
 - L1PP (0x3): L1 power-down mode; Tx common mode off, Rx e-idle detect off

bug 200420606

Change-Id: I74aa9c1460d882084b1ecccb9c0168dd667c9d84
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786547
(cherry picked from commit d7899c186f89ecf503812003b743adbae07c4cbe)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407873
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Vidya Sagar 820e88911d PCI: tegra: Advertise ASPM L1 PM support
Enables advertisement of ASPM-L1 support in capability
registers of applicable Tegra chips

bug 200420606

Change-Id: Ie5dbb3a262ca1c0c9cc59c91a8710bf6bd6a6900
Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786543
(cherry picked from commit 7eedf2a02489b529374bc1ca95234be1f02b9119)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407872
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Manikanta Maddireddy e9d731ffb6 PCI: tegra: Convert WRAP transactions to increment burst
AFI module doesn't support WRAP transactions in Tegra. WRAP instructions
from CPU targeting PCIe BAR memory can cause data corruption. This can
happen if PCIe memory is marked as normal cacheable or GRE device.
Program mselect register to convert WRAP transactions to increment burst
for slave PCIe.

bug 200353330
bug 200420606

Change-Id: I867da85eb63332708bc294238e30ad99a71f345d
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1786561
(cherry picked from commit b345cfae7b7633a3a52e0f2a659baf44feee1466)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407869
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:40 -05:00
Manikanta Maddireddy 3f763023a0 PCI: tegra: Access endpoint config only if PCIe link is up
Few endpoints like Wi-Fi supports power on/off and to leverage that
root port must support hot-plug and hot-unplug. Tegra PCIe doesn't
support hot-plug and hot-unplug, however it supports endpoint power
on/off feature as follows,
 - Power off sequence:
   - Transition of PCIe link to L2
   - Power off endpoint
   - Leave root port in power up state with the link in L2
 - Power on sequence:
   - Power on endpoint
   - Apply hot reset to get PCIe link up

PCIe client driver stops accessing PCIe endpoint config and BAR registers
after endpoint is powered off. However, software applications like x11
server or lspci can access endpoint config registers in which case
host controller raises "response decoding" errors. To avoid this scenario,
add PCIe link up check in config read and write callback functions before
accessing endpoint config registers.

Change-Id: I47653cb0b580c2b764cb0ad9c42deeb9c8823c58
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-4.14/+/2371131
(cherry picked from commit be664bfdd901138222a8ea8bb17160a2fa9de04a)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.9/+/2407866
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2026-08-24 18:39:39 -05:00
tmakin 96595f6b1b [WAR] core: don't loop 2026-08-24 18:39:39 -05:00
tmakin 28a7b211f7 memory: tegra186-emc: support t210b01
Tegra210b01 uses Tegra186 style emc management, as in it is
offloaded to BPMP. This driver already implements this, so no
reason to shoehorn in elsewhere.

Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-24 18:39:39 -05:00
tmakin a00de5720b tegra210b01: do not enable venc
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-24 18:39:39 -05:00
tmakin 176ffad43c tegra-drm: add t210b01 dsi support
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-24 18:39:39 -05:00
tmakin 4c56a02679 enable max77812
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-24 18:39:39 -05:00
tmakin 9856c0e55d panel-nx: match jdi panel driver style
squash later
2026-08-24 18:39:39 -05:00
azkali cb59995ea8 panel: dsi-nx: Add dsi-nx panel driver
dsi-nx is a new blanket driver for panels on the Nintendo Switch.
The Switch boots Linux via the "hekate" custom bootloader, which
performs panel initialization and passes panel info to kernel.

This driver is based on panel-jdi-lpm062m326a by SwitchR.

Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-24 18:38:09 -05:00
Laxman Dewangan 1ae6f14cf5 regulator: core: add API to get min/max voltage for rails
Add API to get min/max rail voltage configured from platform for
given rails. This will help to set the pad voltage based on platform
specific power tree.

bug 200083043

Change-Id: I054734ca2a25b5c830525e27ab22e43534f67351
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/712001
(cherry picked from commit c0d1de0da091132d037e1bb32f2ee09b5c00369b)
Reviewed-on: http://git-master/r/1119836
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-19 00:26:51 -05:00
Alex Frid 913fd81513 clk: Add parent change notifications
Added parent change notifications to be used when drivers behavior
depends on physical nature of the parent, not just clock rate it
supplies (e.g., selection of Tegra DFLL as CPU clock source changes
mechanism of voltage control even if the clock rate stays the same
as on PLL).

Bug 200269751

Change-Id: I617c94927ef437caf240efd91497b49ad6f5c39d
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1573111
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
Reviewed-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Tested-by: Peter De Schrijver <pdeschrijver@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: Timo Alho <talho@nvidia.com>
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-19 00:26:51 -05:00
Alex Frid 10ce718089 clk: tegra: Add subtree change notifications
Added PRE_SUBTREE_CHANGE and POST_SUBTREE_CHANGE that called before
and after rate change is propagated down the sub-tree rooted in clk.
This would allow children to be aware that next set rate operation
is triggered by downward rate propagation, rather than direct set rate
on a child clock.

Bug 200267979

Change-Id: I6f2acbeca7cead0ecd385dcb2e58ced32448e998
Signed-off-by: Alex Frid <afrid@nvidia.com>
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
(cherry picked from commit 62f0d763fcb6c9d5bd9a373d22d802503ab0fdc5)
Reviewed-on: https://git-master.nvidia.com/r/1558143
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Timo Alho <talho@nvidia.com>
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-19 00:26:51 -05:00
tmakin f487855fe4 arm64: t210b01: enable max77812
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-14 17:11:58 -05:00
tmakin 70b6a47406 arm64: t210b01: add max77620 support
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-14 17:11:58 -05:00
tmakin 6243bfbf66 arm64: t210: add initial support for nx
The Nintendo Switch is a video game console based on the
Tegra X1 (T210) and X1+ (T210B01).

Signed-off-by: Thomas Makin <halorocker89@gmail.com>
2026-08-14 17:11:56 -05:00
Aaron Kling 3b9f47e3eb ANDROID: GKI: Export Nvidia dts'
Change-Id: I6e882d22300339288fa4f40d07faf0d4e9f413b0
2026-07-24 02:44:58 -05:00
Keir Fraser 74f0caece2 Revert "Revert "ANDROID: Support CONFIG_CMDLINE_EXTEND""
This reverts commit 68cf9989a1 and
reinstates long-standing Android command-line parsing behaviour with
CONFIG_CMDLINE_EXTEND.

Bug: 357781595
Bug: 120440972
Bug: 278749606
Signed-off-by: Keir Fraser <keirf@google.com>
Change-Id: Iac374066a980d38a1dadf1fa13fff16f48bd44c5
2026-07-24 02:44:57 -05:00
Aaron Kling a03b6f66bc arm64: tegra: Add support for NVIDIA Shield TV 2019
Add initial device-tree support for NVIDIA Shield TV 2019 (a.k.a Sif)
based on the Tegra210B01 SoC with 2 GiB of LPDDR4 RAM.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling 9873589051 arm64: tegra: Enable HDA controller on P2894
The HDA controller can be used for audio playback over HDMI.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling 56ea16deb2 arm64: tegra: Enable HDMI on P2894
Add regulators and enable the host1x nodes necessary to attain video
output via hdmi.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling de4822b2cd arm64: tegra: Enable DFLL clock on P2894
Add pinmux for PWM-based DFLL support.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling f249e36754 arm64: tegra: Enable PWM fan on P2894
This is based on 6f78a94, which enabled added the fan and thermal zones
for the Jetson Nano Devkit. The fan and thermal characteristics of the
two devices are similar, so using the same configuration.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling d1e3693094 arm64: tegra: Add Wifi node for Tegra210B01 P2894
The Tegra210B01 p2894 product has a BCM4356 module with wifi on pcie.
Enable the pcie port it is plugged into and add a node for the wifi
card.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling fd293334af arm64: tegra: Add Wifi node for Tegra210 P2894
The Tegra210 p2894 product has a BCM4354 module with wifi on sdio.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling 3296008419 arm64: tegra: Wire up Bluetooth for P2894
The p2894 product contains a BCM4354 module with bluetooth on uart.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling c8fd7d765c arm64: tegra: Enable PCIe Ethernet on P2894
The P2894 product has a Realtek r6168 PCIe ethernet adapter. Enable the
pcie port the adapter is attached to.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling 317014bc1c arm64: tegra: Enable XUSB controller on P2894
Enable the XUSB controller on P2894. One of the USB 3.0 lanes goes to a
switchable USB-A port, while the second USB 3.0 lane supports the normal
USB-A port.

The padctl layout is different between the Tegra210 and Tegra210B01
variants. The latter is overridden in the device specific dts.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling cc4cd8a3c6 arm64: tegra: Enable gpu on P2894
This adds the gpu regulator and enables the gpu node.

Change-Id: I7d9580967edf9af4c31d500608f880eeb9d1e0b5
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:57 -05:00
Aaron Kling 9acaeaaf9b arm64: tegra: Add support for NVIDIA Shield TV Pro 2019
Add initial device-tree support for NVIDIA Shield TV Pro 2019 (a.k.a
MDarcy) based up the Tegra210B01 SoC with 3 GiB of LPDDR4 RAM.

This device is very similar to the Tegra210 p2894 device, so this shares
the p2894 dtsi with a few overrides to the pinmux and power tree.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
Aaron Kling 0c44639c93 arm64: tegra: tegra210-p2894: Move arch dtsi include
In preparation for support of the Tegra210B01 p2894 variant, move the
arch dtsi include to the Tegra210 revision specific dts. This will allow
the p2894 dtsi to be shared across archs, as the variants share a
majority of the hardware design.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
Aaron Kling ae145cf0ce arm64: tegra: Add Tegra210B01 support
Also known as Tegra X1+, the Tegra210B01 has higher CPU and GPU clocks
than the original Tegra210.

Add a SoC-level device tree file that describes most of the hardware
available on the SoC. This is derived from the Tegra210 dtsi, as they
share a lot.

Co-developed-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
Aaron Kling 4dafef233b arm64: tegra: Add BPMP node for Tegra210
The Tegra210 soc supports bpmp offload for power management among other
things. This was considered insecure partway through the soc's lifecycle
and support was removed in the bootloader. However, Tegra210B01 returned
to using the bpmp. Plus old bootloaders on the original Tegra210 still
work with the existing driver. So add the node to the common Tegra210
soc dtsi, but disabled by default.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
tmakin 403913ad76 mmc: sdhci-tegra: add support for Tegra210B01
Tegra210B01 is basically the same as Tegra210 but uses different tap
delays.

Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
tmakin 61454e44bd pci: tegra: add t210b01 support
This commit also fixes configuration checks

Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Co-developed-by: Aaron Kling <webgeek1234@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
Aaron Kling 40510b5744 usb: gadget: tegra-xudc: Add Tegra210B01 Support
It doesn't need some of the workarounds that the original Tegra210 does.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
Aaron Kling e47d24e45e usb: xhci: tegra: Add Tegra210B01 support
This uses a different firmware, but is otherwise compatible with
Tegra210.

Co-developed-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
Aaron Kling 03a4db0586 phy: tegra: xusb: Add Tegra201B01 Support
This covers a few differences:
* Lanes compared to the original Tegra210
* The soc has a different clock driver and thus callbacks
* The soc has an extra clock for uphy management

Co-developed-by: Thomas Makin <halorocker89@gmail.com>
Change-Id: I455358267b3a700461caa8f9f9963d33596dd189
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:56 -05:00
tmakin dee32fa9a0 memory: tegra: populate dt subnodes
Tegra210b01 uses tegra186-emc driver as emc clock is controlled by BPMP.
However, this driver expects emc as subnode of mc. Adjust Tegra30 mc
probe routine to populate subnodes.
2026-07-24 02:44:55 -05:00
Alexandre Hamamdjian 1b14f1b567 soc/tegra: pmc: Add Tegra210B01 support
The PMC in Tegra210B01 is very similar to the one in the original
Tegra210, but has a few powergate differences. Specifically sata and ve2
are removed.

Signed-off-by: Alexandre Hamamdjian <azkali.limited@gmail.com>
Co-developed-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Co-developed-by: Aaron Kling <webgeek1234@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:55 -05:00
tmakin 972da4752e nouveau: add Tegra210B01 support
This is a revision of the GM20B chipset. Almost all the handling is the
same, except for different clocks and voltages.

Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Co-developed-by: Aaron Kling <webgeek1234@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:55 -05:00
Aaron Kling 9e0a4a690f thermal: tegra: Add Tegra210B01 Support
Add Tegra210B01 SOC_THERM configuration

Change-Id: Ib094bedbe13dd0e3ff750e7c4da025b46e033ddc
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:55 -05:00
tmakin e58928e559 tegra: clk: correct divider algo
Negative divider_ux1 values previously were resolved by extra checks and
caused undefined behavior with div1_5_not_allowed
2026-07-24 02:44:55 -05:00
Aaron Kling 209d82d0ab clk: tegra: dfll: add CVB tables for Tegra210B01
To generate OPP tables for the soc

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:54 -05:00
Aaron Kling d3f3e70dad soc/tegra: fuse: speedo-tegra210: Support revision b01
Tegra210B01 has a separate set of skus and speedo tables

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:54 -05:00
Aaron Kling 756247da37 soc/tegra: fuse: Support revision B01
Previously, all supported SoCs only used the A major revision. The
Tegra210B01 SoC incremented the major revision. Add support for this.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:54 -05:00
Aaron Klingandtmakin 8202f10782 clk: tegra: Add Tegra210B01 support
This is based on the downstream Nvidia 5.10 kernel. That version was
semi-integrated into the Tegra210 clock driver. Looking at the existing
Tegra210 support, it made more sense to make this a fully independent
driver, so that is implemented here.

Co-authored-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:54 -05:00
Aaron Kling b671a469df dt-bindings: clock: tegra: Document Tegra210B01
* Add the compatible string for Tegra210B01 clock and reset
* Add Tegra210B01 specific clock bindings

Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:53 -05:00
Aaron Kling 4efe795b62 drm/tegra: Create switch class for primary hdmi
Change-Id: I353b1c5ad98bcd69b4827b0c74327511b4d8222d
2026-07-24 02:44:52 -05:00
Faith Ekstrand b821768cef nouveau: Use WC maps instead of uncached 2026-07-24 02:44:52 -05:00
Aaron Kling 81117ffffe ANDROID: GKI: Add tegra gki hacks
* Enable xz ramdisk for small t210 recovery partitions

Change-Id: I3bb0f7277722305d0498776d4494c8f60a322343
2026-07-24 02:44:52 -05:00
Vishwaroop A 43f3dece0a drivers: spi: add support for prod framework
Add support for prod framework in spi core

Change-Id: Iaa70f8b3bb3efb3a3b13aa7f2d43562b9fff9e51
Signed-off-by: Vishwaroop A <va@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Abhilash G <abhilashg@nvidia.com>
2026-07-24 02:44:52 -05:00
Shardar Shariff Md 9334c17ced i2c: core: skip prod-settings node during i2c device registration
skip prod-settings node during i2c device registration as
prod-settings is not i2c device

Change-Id: Iaeff454cf17ffd68a7273aeb8afcce6e2c8894c6
Signed-off-by: Shardar Shariff Md <smohammed@nvidia.com>
Signed-off-by: Bitan Biswas <bbiswas@nvidia.com>
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
Reviewed-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Tested-by: Akhil R <akhilrajeev@nvidia.com>
Signed-off-by: Abhilash G <abhilashg@nvidia.com>
2026-07-24 02:44:52 -05:00
David Ng 8c1109c2a6 arm64: Add 32-bit sigcontext definition to uapi signcontext.h
The arm64 uapi sigcontext.h can be included by 32-bit userspace
modules.  Since arm and arm64 sigcontext definition are not
compatible, add arm sigcontext definition to arm64 sigcontext.h.

Signed-off-by: David Ng <dave@codeaurora.org>
Signed-off-by: Divya Sharma <c_shard@codeaurora.org>
Signed-off-by: Anh Nguyen <anguyen@codeaurora.org>
Change-Id: Iaed58045fd345e4ca66e8a6981c6b4f80c4bdfca
2026-07-24 02:44:52 -05:00
Aaron Kling ede5ebe26b arm64: Disable some cpu feature sanity checks
On t186, these differ between denver and a57

Change-Id: I65b1515ef9f5d42b0da1dfa605e51536eb902ca5
2026-07-24 02:44:52 -05:00
Aaron Kling f2cd633afe ANDROID: gki_defconfig: Enable Tegra SoC Support
The archs are already enabled, but some additional configs are still
necessary to reasonably boot.

Change-Id: I05541c6e1fc1ccd9ab430451a66f0d5cc3c7b0e1
2026-07-24 02:44:52 -05:00
Aaron Kling d53cf85bcb ANDROID: amba: Allow ahb to build on relevant platforms
Change-Id: Ie8bc48498d6acf98c107e8133f7dc25d01e0f773
2026-07-24 02:44:52 -05:00
Ahmad Chaudhry 9bc36a47ff ANDROID: GKI: Enable Tegra Host1x
Select hidden config CONFIG_TEGRA_HOST1X_CONTEXT_BUS.
This config is needed as it adds host1x_context_device_bus_type
to iommu_buses private array, needed for host1x.ko module

Bug: 418986815
Change-Id: Icbc697638e39a08a648b2a3dbf7947d6107ac310
Signed-off-by: Ahmad Chaudhry <ahmadc@nvidia.com>
2026-07-24 02:44:52 -05:00
Aaron Kling 2561655eb4 HACK: Revert "UPSTREAM: drm/nouveau: select FW caching"
This reverts commit cf4c97db94.

Commit knowingly breaks building the nouveau module. As the issue only
affects full gsp devices, revert to keep builds going.
https://patchwork.freedesktop.org/patch/635827/#comment_1165994

Change-Id: I67d544b433f4a2dc047ed07088eda73466594cc6
2026-07-24 02:44:51 -05:00
Venkat Reddy Talla 8207bb4fc6 regulator: max77812: add max77812 regulator driver
Adding regulator driver for MAX77812 device which is
used in t210b01 based platforms for powering cpu,gpu
and dram io

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:51 -05:00
Aaron Kling 59f8f7a811 power: supply: bq24190_charger: Support usb role switching
Change-Id: Ia1e650f15ae55bb0972612b378d093a20d8a8a98
2026-07-24 02:44:51 -05:00
Aaron Kling 98672e71bd power: supply: bq24190_charger: Export current regulator
Change-Id: I3958896da66740d503aec5ed93e14a7d743a43ac
2026-07-24 02:44:51 -05:00
Aaron Kling a910dcea09 memory: tegra210-emc: Support Device Tree EMC Tables
These are generated by the Tegra210 Android bootloader. This is similar
to the Tegra124 handling, so the support is based on that and modified
to match Tegra210 by referencing the downstream Nvidia 4.9 kernel.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:51 -05:00
Aaron Kling 0b928354a0 arm64: tegra: Add EMC timings to P2180
These entries are imported from the downstream Nvidia Linux4Tegra
kernel. They are expected to be updated with the trained values by the
bootloader. This is done by the Nvidia Android bootloader, which is
different from the handling by the Nvidia Linux bootloader which places
these values in a reserved memory location. P2180 is supported by both
bootloaders, so lets support initializing emc on both.

It should be noted that the bootloader will not create these nodes in
the kernel dtb if they do not exist. It will only set in place existing
properties.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:51 -05:00
Aaron Kling a89e369cf2 WIP: drm/tegra: Add devfreq support to media engines
TODO: Better limit frequency count

Change-Id: If86527dc4985d9afd9d510430d1f3c137ca7f220
2026-07-24 02:44:51 -05:00
Aaron Kling 59a45f29ee drm/tegra: Support Tegra186+ in NVJPG
Change-Id: I7bf2c200d4ad9690c4f21a004ecc6dea8065f93e
2026-07-24 02:44:51 -05:00
Aaron Kling d0bf78d473 drm/tegra: Add NVENC driver
Add support for booting and using NVENC on Tegra210+ to the Host1x
and TegraDRM drivers. This driver only supports the new TegraDRM uAPI.

Change-Id: I07e1386604d7638ba43381c3f289688d7c5cb12b
2026-07-24 02:44:51 -05:00
Aaron Kling 49b8aeda99 arm64: tegra: Add support for NVIDIA Shield TV 2015
Add initial device-tree support for NVIDIA Shield TV (a.k.a. Foster)
based upon Tegra210 SoC with 3 GiB of LPDDR4 RAM. It is based on P2571.

Change-Id: Ideeeb15f835ebf7f7617d3989908d245aff4b316
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:51 -05:00
Aaron Kling 7de2507df7 arm64: tegra: Enable sd card on P2571
Change-Id: I2320654ef9fc15dad901b516bd22379329e5ab88
2026-07-24 02:44:51 -05:00
Aaron Kling 3872ea97ca arm64: tegra: Enable HDA controller on P2571
The HDA controller can be used for audio playback over HDMI.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling 66bd4205f3 arm64: tegra: Enable HDMI on P2571
Add regulators and enable the host1x nodes necessary to attain video
output via hdmi.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling 4535649c39 arm64: tegra: Enable DFLL clock on P2530
Using pwm regulator

Change-Id: Id41340bcfc4e12df74b579ec34e61ebba857d81c
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling a78fa2cdf4 arm64: tegra: Enable XUSB controller on P2571
Enable the XUSB controller on P2571. One of the USB 3.0 lanes goes to an
internal ethernet interface, while two other USB 3.0 lanes support the
the USB-A receptacles on the I/O board.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling 846ada9e33 arm64: tegra: Enable PWM fan on P2571
This is based on 6f78a94, which enabled added the fan and thermal zones
for the Jetson Nano Devkit. The fan and thermal characteristics of the
two devices are similar, so using the same configuration.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling dbffbcb14d arm64: tegra: Add power supplies to emmc on P2530
Change-Id: I3ddf282a9a4cf7b407897f8e7af073c1852704b7
2026-07-24 02:44:50 -05:00
Aaron Kling 05629d040e arm64: tegra: Add Wifi node for P2530
The p2530 som has a BCM4354 module with wifi on sdio.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling a0543b422c arm64: tegra: Wire up Bluetooth for P2530
The p2530 som contains a BCM4354 module with bluetooth on uart.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling 0e0c4d980c arm64: tegra: Enable gpu on P2530
This adds the gpu regulator and enables the gpu node.

Change-Id: I8a0f580fa600d8f37fb3fa497cf657abf2905d5f
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling 3283c40ce3 arm64: tegra: Add PMIC support on P2530
Based on the p2180 pmic config, modified to match p2530

Change-Id: Ic7baa787b8e9633da72622a4562258860c05fca6
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling 49ab99dea7 arm64: tegra: Enable CPU idle support for P2530
Enable CPU idle support for the P2530 module

Change-Id: Ia73f192b3450fe9c143fbaaea03d6a50527927a7
2026-07-24 02:44:50 -05:00
Aaron Kling 75b5fa2f68 arm64: tegra: Add P2530 SC7 timings
Same as 106f7a0 and 47b4e12. Without these, the pmc driver locks up
during boot.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:50 -05:00
Aaron Kling 97c550d455 dt-bindings: tegra: Document SHIELD TV 2015
The SHIELD TV 2015 is a consumer media Android device that is based on
P2571

Change-Id: Ib981728d277f7daca812223ec3534d98555d43a1
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:49 -05:00
Aaron Kling a4b10a99ff arm64: tegra: Enable bluetooth on P3310
The p3310 som contains a BCM4354 module with bluetooth on uart.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:49 -05:00
Aaron Kling 200397ed67 arm64: tegra: Enable wifi on P3310
The p3310 som has a BCM4354 module with wifi on sdio.

Change-Id: Ie4b42165fb81a129a7afe58c1c632261d13eca53
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:49 -05:00
Aaron Kling 6516ffb4c2 arm64: tegra: Fix ldo5 voltage on P3310
This appears to be a typo. The voltage input to the wireless module is
expected to be 1.8V-3.3V, per the downstream device tree.

Fixes: 02df3f03a8 ("arm64: tegra: Add initial power tree for P3310")
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:49 -05:00
Aaron Kling 16f8d9d290 arm64: tegra: Add CPU OPP tables for Tegra194
Add OPP table and interconnects property to scale DDR frequency with
CPU frequency for better performance. Each operating point entry of
the OPP table has CPU freq to per MC channel bandwidth mapping.
One table is added for each cluster even though the table data is
same because the bandwidth request is per cluster. This is done
because the OPP framework creates a single icc path and hence single
bandwidth request if the table is marked as 'opp-shared' and shared
among all clusters. For us, the OPP table data is same but the MC
Client ID argument to interconnects property is different for each
cluster. So, having per cluster tables makes different icc paths for
each cluster and helps to make per cluster BW requests.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:49 -05:00
Aaron Kling 2a4d8783a5 arm64: tegra: Add CPU OPP tables for Tegra186
Add OPP table and interconnects property to scale DDR frequency with
CPU frequency for better performance. Each operating point entry of
the OPP table has CPU freq to per MC channel bandwidth mapping. One
table is added for each cluster because the different cpu types have
different scaling curves.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:49 -05:00
Aaron Kling 3ccf195e5b memory: tegra194: Support icc scaling
Add Interconnect framework support to dynamically set the DRAM
bandwidth from different clients. The MC driver is added as an ICC
provider and the EMC driver is already a provider.

Change-Id: I1c315f833711ed33f972bc0e26c1e3b91de32eba
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-24 02:44:49 -05:00
Aaron Kling de738636ef memory: tegra186: Support icc scaling
Add Interconnect framework support to dynamically set the DRAM
bandwidth from different clients. The MC driver is added as an ICC
provider and the EMC driver is already a provider.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 23:04:44 -05:00
Aaron Kling 3c57813597 memory: tegra186-emc: Support non-bpmp icc scaling
This adds support for dynamic frequency scaling of external memory on
devices with bpmp firmware that does not support bwmgr.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling 6109842b1a dt-bindings: memory: tegra194-mc: Add dummy client IDs for Tegra194
Add ICC IDs for dummy software clients representing CCPLEX clusters.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling 4726d21918 dt-bindings: memory: tegra186-mc: Add dummy client IDs for Tegra186
Add ICC IDs for dummy software clients representing CCPLEX clusters.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling 7e0f740103 arm64: tegra: Fix P2371 pcie lane assignments
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling c35c0f4c06 arm64: tegra: Enable interconnect for MC and EMC on Tegra210
These are being referenced by actmon, but are not currently enabled.

Fixes: 654427e0b9 ("arm64: tegra: Add OPP tables on Tegra210")
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling 7bf5d17757 memory: tegra210: Support interconnect framework
This makes mc and emc interconnect providers and allows for dynamic
memory clock scaling.

Change-Id: I3d787bd3bd18f0baa346844140094e2c11d8d91b
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling ea0b719033 arm64: tegra: Enable mmu on Tegra194 display controllers
These use a separate mmu instance compared to everything else currently
enabled for the soc.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling c9d97a2bba Revert "arm64: tegra: Disable ISO SMMU for Tegra194"
This reverts commit ebea268ea5.

Mmu is now being enabled for the display controllers.

Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
2026-07-23 16:15:49 -05:00
Aaron Kling 3336d897c6 drm/tegra: Enable cmu for Tegra186 and Tegra194
Without the cmu, nvdisplay will display colors that are notably darker
than intended. The vendor bootloader and the downstream display driver
enable the cmu and sets a sRGB table. Loading that table here results in
the intended colors.

Co-developed-by: Kurt Kiefer <kekiefer@gmail.com>
Signed-off-by: Kurt Kiefer <kekiefer@gmail.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
Tested-by: Jasper Korten <jja2000@gmail.com>
2026-07-23 16:15:49 -05:00
139 changed files with 68936 additions and 370 deletions

No files matched your search

+11
View File
@@ -1707,6 +1707,17 @@ devicetree_library(
deps = ["//common:dtc_includes_aarch64"],
)
devicetree_library(
name = "all_nvidia_dts",
hdrs = glob([
"arch/arm64/boot/dts/nvidia/*.dtsi",
"arch/arm64/boot/dts/nvidia/*.dts",
]),
includes = ["arch/arm64/boot/dts/nvidia"],
visibility = ["//vendor:__subpackages__"],
deps = [":dtc_includes_aarch64"],
)
_KSELFTEST_DIR = "testcases/selftests"
_KSELFTEST_COPTS = [
@@ -240,6 +240,17 @@ properties:
- const: google,smaug-rev1
- const: google,smaug
- const: nvidia,tegra210
- description: NVIDIA Shield TV 2015
items:
- const: nvidia,p2571-0930
- const: nvidia,foster_e
- const: nvidia,tegra210
- description: NVIDIA Shield TV Pro 2015
items:
- const: nvidia,p2571-0932
- const: nvidia,foster_e_hdd
- const: nvidia,foster_e
- const: nvidia,tegra210
- description: Jetson TX2 Developer Kit
items:
- const: nvidia,p2771-0000
@@ -32,6 +32,7 @@ properties:
- nvidia,tegra30-car
- nvidia,tegra114-car
- nvidia,tegra210-car
- nvidia,tegra210b01-car
reg:
maxItems: 1
@@ -0,0 +1,50 @@
MAX77812 voltage regulator
Required properties:
- compatible: "maxim,max77812-regulator"
- reg: I2C slave address
Regulators subnode:
MAX77812 supports four regulators, regulators should be described under
regualtors subnode.
Optional properties:
-maxim,ramp-up-slew-rate: to configure slew rate during regulator
voltage ramp up time
-maxim,ramp-down-slew-rate: to configre slew rate during regulator
voltage ramp down time
-maxim,soft-start-slew-rate: to configure slew rate during regulator
enable time
-maxim,shutdown-slew-rate: to configure slew rate during regulator
disable time or shutdown time
Each regulator is defined using the standard binding for regulators.
Example:
max77812@1b {
compatible = "maxim,max77812-regulator";
reg = <0x1b>;
regulators {
m1vout {
regulator-name = "mvout1";
regulator-min-microvolt = <250000>;
regulator-max-microvolt = <1525000>;
regulator-boot-on;
regulator-always-on;
regulator-init-mode = <REGULATOR_MODE_NORMAL>;
};
m2vout {
regulator-name = "mvout2";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <250000>;
regulator-max-microvolt = <1525000>;
regulator-init-mode = <REGULATOR_MODE_NORMAL>;
};
};
};
@@ -0,0 +1,128 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/rohm,bm92t.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rohm BM92TXX USB Type-C and Power Delivery controller
maintainers:
- CTCaer <ctcaer@gmail.com>
- Alexandre Hamamdjian <azkali.limited@gmail.com>
description:
The Rohm BM92TXX is a family of USB Type-C and Power Delivery
controllers with an integrated MCU. The host communicates with the
device over I2C and is notified of state changes through a dedicated
interrupt line.
properties:
compatible:
const: rohm,bm92t
reg:
maxItems: 1
interrupts:
maxItems: 1
vbus-supply:
description: VBUS sink regulator.
vbus-source-supply:
description: VBUS source (provider) regulator.
pd_bat_chg-supply:
description: Battery charger regulator gated by Power Delivery state.
rohm,vconn-en-gpio:
maxItems: 1
description: GPIO controlling the external VCONN switch.
rohm,dp-disable:
type: boolean
description: Disable DisplayPort alternate-mode handling.
rohm,dp-alerts-enable:
type: boolean
description: Enable DisplayPort status alerts.
rohm,dp-signal-toggle-on-resume:
type: boolean
description:
Toggle the DisplayPort signal on resume to work around sinks that
do not re-train after system resume.
rohm,dp-lanes:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [2, 4]
default: 2
description: Number of DisplayPort lanes to negotiate.
rohm,led-static-on-suspend:
type: boolean
description:
Keep the charge LED in a static state during system suspend
instead of letting the controller animate it.
rohm,dock-power-limit-disable:
type: boolean
description:
Disable the lower power limit applied when a dock is detected.
rohm,pd-5v-current-limit-ma:
description: Charging current limit in mA when 5V PD contract is active.
rohm,pd-9v-current-limit-ma:
description: Charging current limit in mA when 9V PD contract is active.
rohm,pd-12v-current-limit-ma:
description: Charging current limit in mA when 12V PD contract is active.
rohm,pd-15v-current-limit-ma:
description: Charging current limit in mA when 15V PD contract is active.
port:
$ref: /schemas/graph.yaml#/properties/port
description:
Output port linking to a USB role switch consumer endpoint.
required:
- compatible
- reg
- interrupts
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
typec@18 {
compatible = "rohm,bm92t";
reg = <0x18>;
interrupt-parent = <&gpio>;
interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
vbus-supply = <&vbus_reg>;
vbus-source-supply = <&vbus_src_reg>;
pd_bat_chg-supply = <&pd_bat_chg_reg>;
rohm,dp-lanes = <4>;
rohm,pd-5v-current-limit-ma = <2000>;
rohm,pd-9v-current-limit-ma = <2000>;
rohm,pd-12v-current-limit-ma = <1500>;
rohm,pd-15v-current-limit-ma = <1200>;
port {
bm92t_ep: endpoint {
remote-endpoint = <&usb_role_sw>;
};
};
};
};
+8
View File
@@ -23259,6 +23259,14 @@ L: linux-iio@vger.kernel.org
S: Supported
F: drivers/iio/pressure/rohm-bm1390.c
ROHM BM92TXX USB TYPE-C CONTROLLER DRIVER
M: CTCaer <ctcaer@gmail.com>
M: Alexandre Hamamdjian <azkali.limited@gmail.com>
L: linux-usb@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/usb/rohm,bm92t.yaml
F: drivers/usb/typec/bm92txx.c
ROHM BU270xx LIGHT SENSOR DRIVERs
M: Matti Vaittinen <mazziesaccount@gmail.com>
L: linux-iio@vger.kernel.org
+6
View File
@@ -2391,6 +2391,12 @@ config CMDLINE_FROM_BOOTLOADER
the boot loader doesn't provide any, the default kernel command
string provided in CMDLINE will be used.
config CMDLINE_EXTEND
bool "Extend bootloader kernel arguments"
help
The command-line arguments provided by the boot loader will be
appended to the default kernel command string.
config CMDLINE_FORCE
bool "Always use the default kernel command string"
help
+11
View File
@@ -2,6 +2,8 @@
# Enables support for device-tree overlays
DTC_FLAGS_tegra210-p2371-2180 := -@
DTC_FLAGS_tegra210-p2571-0930 := -@
DTC_FLAGS_tegra210-p2571-0932 := -@
DTC_FLAGS_tegra210-p3450-0000 := -@
DTC_FLAGS_tegra210-p3541-0000 := -@
DTC_FLAGS_tegra186-p2771-0000 := -@
@@ -20,10 +22,19 @@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra132-norrin.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571-0930.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571-0932.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p3450-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p3541-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2894-0050-a08.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-p2894-2551-b00.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-p3425-0050-a04.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-odin.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-p2894-0050-a08.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-odin.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-vali.dtb
dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210b01-fric.dtb
dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb
dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p3509-0000+p3636-0001.dtb
dtb-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-p2972-0000.dtb
+36 -2
View File
@@ -19,7 +19,9 @@
i2c7 = "/i2c@31e0000";
mmc0 = "/mmc@3460000";
mmc1 = "/mmc@3400000";
mmc2 = "/mmc@3440000";
serial0 = &uarta;
serial3 = &uartd;
};
chosen {
@@ -66,6 +68,24 @@
status = "okay";
};
serial@3130000 {
/delete-property/ reg-shift;
status = "okay";
compatible = "nvidia,tegra30-hsuart";
reset-names = "serial";
bluetooth {
compatible = "brcm,bcm43540-bt";
device-wakeup-gpios = <&gpio TEGRA186_MAIN_GPIO(Y, 4) GPIO_ACTIVE_HIGH>;
shutdown-gpios = <&gpio TEGRA186_MAIN_GPIO(H, 5) GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio_aon>;
interrupts = <TEGRA186_AON_GPIO(FF, 4) IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "host-wakeup";
vbat-supply = <&vdd_5v0_sys>;
vddio-supply = <&vdd_1v8>;
};
};
i2c@3160000 {
status = "okay";
@@ -147,7 +167,21 @@
/* SDMMC3 (SDIO) */
mmc@3440000 {
status = "okay";
bus-width = <4>;
non-removable;
power-gpios = <&gpio TEGRA186_MAIN_GPIO(N, 0) GPIO_ACTIVE_HIGH>;
vqmmc-supply = <&vddio_sdmmc3>;
vmmc-supply = <&vdd_1v8>;
#address-cells = <1>;
#size-cells = <0>;
wifi@1 {
compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac";
reg = <1>;
interrupt-parent = <&gpio_aon>;
interrupts = <TEGRA186_AON_GPIO(FF, 3) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "host-wake";
};
};
/* SDMMC4 (eMMC) */
@@ -348,8 +382,8 @@
vddio_sdmmc3: ldo5 {
regulator-name = "VDDIO_SDMMC3_AP";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
vdd_hdmi_1v05: ldo7 {
+317
View File
@@ -1954,6 +1954,8 @@
denver_0: cpu@0 {
compatible = "nvidia,tegra186-denver";
device_type = "cpu";
operating-points-v2 = <&dnv_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
i-cache-size = <0x20000>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -1967,6 +1969,8 @@
denver_1: cpu@1 {
compatible = "nvidia,tegra186-denver";
device_type = "cpu";
operating-points-v2 = <&dnv_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
i-cache-size = <0x20000>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -1980,6 +1984,8 @@
ca57_0: cpu@2 {
compatible = "arm,cortex-a57";
device_type = "cpu";
operating-points-v2 = <&a57_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
i-cache-size = <0xC000>;
i-cache-line-size = <64>;
i-cache-sets = <256>;
@@ -1993,6 +1999,8 @@
ca57_1: cpu@3 {
compatible = "arm,cortex-a57";
device_type = "cpu";
operating-points-v2 = <&a57_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
i-cache-size = <0xC000>;
i-cache-line-size = <64>;
i-cache-sets = <256>;
@@ -2006,6 +2014,8 @@
ca57_2: cpu@4 {
compatible = "arm,cortex-a57";
device_type = "cpu";
operating-points-v2 = <&a57_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
i-cache-size = <0xC000>;
i-cache-line-size = <64>;
i-cache-sets = <256>;
@@ -2019,6 +2029,8 @@
ca57_3: cpu@5 {
compatible = "arm,cortex-a57";
device_type = "cpu";
operating-points-v2 = <&a57_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
i-cache-size = <0xC000>;
i-cache-line-size = <64>;
i-cache-sets = <256>;
@@ -2193,4 +2205,309 @@
interrupt-parent = <&gic>;
always-on;
};
dnv_opp_tbl: opp-table-cluster0 {
compatible = "operating-points-v2";
opp-shared;
opp-998400000 {
opp-hz = /bits/ 64 <998400000>;
opp-peak-kBps = <816000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
opp-peak-kBps = <816000>;
};
opp-1075200000 {
opp-hz = /bits/ 64 <1075200000>;
opp-peak-kBps = <816000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
opp-peak-kBps = <1600000>;
};
opp-1152000000 {
opp-hz = /bits/ 64 <1152000000>;
opp-peak-kBps = <1600000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
opp-peak-kBps = <1600000>;
};
opp-1228800000 {
opp-hz = /bits/ 64 <1228800000>;
opp-peak-kBps = <1600000>;
};
opp-1267200000 {
opp-hz = /bits/ 64 <1267200000>;
opp-peak-kBps = <1600000>;
};
opp-1305600000 {
opp-hz = /bits/ 64 <1305600000>;
opp-peak-kBps = <1600000>;
};
opp-1344000000 {
opp-hz = /bits/ 64 <1344000000>;
opp-peak-kBps = <1600000>;
};
opp-1382400000 {
opp-hz = /bits/ 64 <1382400000>;
opp-peak-kBps = <1600000>;
};
opp-1420800000 {
opp-hz = /bits/ 64 <1420800000>;
opp-peak-kBps = <1600000>;
};
opp-1459200000 {
opp-hz = /bits/ 64 <1459200000>;
opp-peak-kBps = <3200000>;
};
opp-1497600000 {
opp-hz = /bits/ 64 <1497600000>;
opp-peak-kBps = <3200000>;
};
opp-1536000000 {
opp-hz = /bits/ 64 <1536000000>;
opp-peak-kBps = <3200000>;
};
opp-1574400000 {
opp-hz = /bits/ 64 <1574400000>;
opp-peak-kBps = <3200000>;
};
opp-1612800000 {
opp-hz = /bits/ 64 <1612800000>;
opp-peak-kBps = <3200000>;
};
opp-1651200000 {
opp-hz = /bits/ 64 <1651200000>;
opp-peak-kBps = <3200000>;
};
opp-1689600000 {
opp-hz = /bits/ 64 <1689600000>;
opp-peak-kBps = <3200000>;
};
opp-1728000000 {
opp-hz = /bits/ 64 <1728000000>;
opp-peak-kBps = <3200000>;
};
opp-1766400000 {
opp-hz = /bits/ 64 <1766400000>;
opp-peak-kBps = <3200000>;
};
opp-1804800000 {
opp-hz = /bits/ 64 <1804800000>;
opp-peak-kBps = <3200000>;
};
opp-1843200000 {
opp-hz = /bits/ 64 <1843200000>;
opp-peak-kBps = <3200000>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
opp-peak-kBps = <3200000>;
};
opp-1920000000 {
opp-hz = /bits/ 64 <1920000000>;
opp-peak-kBps = <3200000>;
};
opp-1958400000 {
opp-hz = /bits/ 64 <1958400000>;
opp-peak-kBps = <3200000>;
};
opp-1996800000 {
opp-hz = /bits/ 64 <1996800000>;
opp-peak-kBps = <3732000>;
};
opp-2035200000 {
opp-hz = /bits/ 64 <2035200000>;
opp-peak-kBps = <3732000>;
};
};
a57_opp_tbl: opp-table-cluster1 {
compatible = "operating-points-v2";
opp-shared;
opp-883200000 {
opp-hz = /bits/ 64 <883200000>;
opp-peak-kBps = <816000>;
};
opp-921600000 {
opp-hz = /bits/ 64 <921600000>;
opp-peak-kBps = <816000>;
};
opp-960000000 {
opp-hz = /bits/ 64 <960000000>;
opp-peak-kBps = <816000>;
};
opp-998400000 {
opp-hz = /bits/ 64 <998400000>;
opp-peak-kBps = <816000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
opp-peak-kBps = <816000>;
};
opp-1075200000 {
opp-hz = /bits/ 64 <1075200000>;
opp-peak-kBps = <816000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
opp-peak-kBps = <1600000>;
};
opp-1152000000 {
opp-hz = /bits/ 64 <1152000000>;
opp-peak-kBps = <1600000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
opp-peak-kBps = <1600000>;
};
opp-1228800000 {
opp-hz = /bits/ 64 <1228800000>;
opp-peak-kBps = <1600000>;
};
opp-1267200000 {
opp-hz = /bits/ 64 <1267200000>;
opp-peak-kBps = <1600000>;
};
opp-1305600000 {
opp-hz = /bits/ 64 <1305600000>;
opp-peak-kBps = <1600000>;
};
opp-1344000000 {
opp-hz = /bits/ 64 <1344000000>;
opp-peak-kBps = <1600000>;
};
opp-1382400000 {
opp-hz = /bits/ 64 <1382400000>;
opp-peak-kBps = <1600000>;
};
opp-1420800000 {
opp-hz = /bits/ 64 <1420800000>;
opp-peak-kBps = <1600000>;
};
opp-1459200000 {
opp-hz = /bits/ 64 <1459200000>;
opp-peak-kBps = <3200000>;
};
opp-1497600000 {
opp-hz = /bits/ 64 <1497600000>;
opp-peak-kBps = <3200000>;
};
opp-1536000000 {
opp-hz = /bits/ 64 <1536000000>;
opp-peak-kBps = <3200000>;
};
opp-1574400000 {
opp-hz = /bits/ 64 <1574400000>;
opp-peak-kBps = <3200000>;
};
opp-1612800000 {
opp-hz = /bits/ 64 <1612800000>;
opp-peak-kBps = <3200000>;
};
opp-1651200000 {
opp-hz = /bits/ 64 <1651200000>;
opp-peak-kBps = <3200000>;
};
opp-1689600000 {
opp-hz = /bits/ 64 <1689600000>;
opp-peak-kBps = <3200000>;
};
opp-1728000000 {
opp-hz = /bits/ 64 <1728000000>;
opp-peak-kBps = <3200000>;
};
opp-1766400000 {
opp-hz = /bits/ 64 <1766400000>;
opp-peak-kBps = <3200000>;
};
opp-1804800000 {
opp-hz = /bits/ 64 <1804800000>;
opp-peak-kBps = <3200000>;
};
opp-1843200000 {
opp-hz = /bits/ 64 <1843200000>;
opp-peak-kBps = <3200000>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
opp-peak-kBps = <3200000>;
};
opp-1920000000 {
opp-hz = /bits/ 64 <1920000000>;
opp-peak-kBps = <3200000>;
};
opp-1958400000 {
opp-hz = /bits/ 64 <1958400000>;
opp-peak-kBps = <3200000>;
};
opp-1996800000 {
opp-hz = /bits/ 64 <1996800000>;
opp-peak-kBps = <3732000>;
};
opp-2035200000 {
opp-hz = /bits/ 64 <2035200000>;
opp-peak-kBps = <3732000>;
};
};
};
+642 -2
View File
@@ -1722,7 +1722,7 @@
nvidia,apbmisc = <&apbmisc>;
};
iommu@10000000 {
smmu_iso: iommu@10000000 {
compatible = "nvidia,tegra194-smmu", "nvidia,smmu-500";
reg = <0x0 0x10000000 0x0 0x800000>;
interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
@@ -1795,7 +1795,7 @@
#iommu-cells = <1>;
nvidia,memory-controller = <&mc>;
status = "disabled";
status = "okay";
};
smmu: iommu@12000000 {
@@ -1962,6 +1962,7 @@
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
interconnect-names = "dma-mem", "read-1";
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
nvidia,head = <0>;
@@ -1980,6 +1981,7 @@
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
interconnect-names = "dma-mem", "read-1";
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
nvidia,head = <1>;
@@ -1998,6 +2000,7 @@
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
interconnect-names = "dma-mem", "read-1";
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
nvidia,head = <2>;
@@ -2016,6 +2019,7 @@
interconnects = <&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR &emc>,
<&mc TEGRA194_MEMORY_CLIENT_NVDISPLAYR1 &emc>;
interconnect-names = "dma-mem", "read-1";
iommus = <&smmu_iso TEGRA194_SID_NVDISPLAY>;
nvidia,outputs = <&sor0 &sor1 &sor2 &sor3>;
nvidia,head = <3>;
@@ -2877,6 +2881,8 @@
device_type = "cpu";
reg = <0x000>;
enable-method = "psci";
operating-points-v2 = <&cl0_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -2891,6 +2897,8 @@
device_type = "cpu";
reg = <0x001>;
enable-method = "psci";
operating-points-v2 = <&cl0_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER0 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -2905,6 +2913,8 @@
device_type = "cpu";
reg = <0x100>;
enable-method = "psci";
operating-points-v2 = <&cl1_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -2919,6 +2929,8 @@
device_type = "cpu";
reg = <0x101>;
enable-method = "psci";
operating-points-v2 = <&cl1_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER1 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -2933,6 +2945,8 @@
device_type = "cpu";
reg = <0x200>;
enable-method = "psci";
operating-points-v2 = <&cl2_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -2947,6 +2961,8 @@
device_type = "cpu";
reg = <0x201>;
enable-method = "psci";
operating-points-v2 = <&cl2_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER2 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -2961,6 +2977,8 @@
device_type = "cpu";
reg = <0x300>;
enable-method = "psci";
operating-points-v2 = <&cl3_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER3 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -2975,6 +2993,8 @@
device_type = "cpu";
reg = <0x301>;
enable-method = "psci";
operating-points-v2 = <&cl3_opp_tbl>;
interconnects = <&mc TEGRA_ICC_MC_CPU_CLUSTER3 &emc>;
i-cache-size = <131072>;
i-cache-line-size = <64>;
i-cache-sets = <512>;
@@ -3167,4 +3187,624 @@
interrupt-parent = <&gic>;
always-on;
};
cl0_opp_tbl: opp-table-cluster0 {
compatible = "operating-points-v2";
opp-shared;
opp-115200000 {
opp-hz = /bits/ 64 <115200000>;
opp-peak-kBps = <816000>;
};
opp-192000000 {
opp-hz = /bits/ 64 <192000000>;
opp-peak-kBps = <816000>;
};
opp-268800000 {
opp-hz = /bits/ 64 <268800000>;
opp-peak-kBps = <816000>;
};
opp-345600000 {
opp-hz = /bits/ 64 <345600000>;
opp-peak-kBps = <816000>;
};
opp-422400000 {
opp-hz = /bits/ 64 <422400000>;
opp-peak-kBps = <816000>;
};
opp-499200000 {
opp-hz = /bits/ 64 <499200000>;
opp-peak-kBps = <816000>;
};
opp-576000000 {
opp-hz = /bits/ 64 <576000000>;
opp-peak-kBps = <816000>;
};
opp-652800000 {
opp-hz = /bits/ 64 <652800000>;
opp-peak-kBps = <816000>;
};
opp-729600000 {
opp-hz = /bits/ 64 <729600000>;
opp-peak-kBps = <816000>;
};
opp-806400000 {
opp-hz = /bits/ 64 <806400000>;
opp-peak-kBps = <816000>;
};
opp-883200000 {
opp-hz = /bits/ 64 <883200000>;
opp-peak-kBps = <816000>;
};
opp-960000000 {
opp-hz = /bits/ 64 <960000000>;
opp-peak-kBps = <816000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
opp-peak-kBps = <816000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
opp-peak-kBps = <1600000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
opp-peak-kBps = <1600000>;
};
opp-1267200000 {
opp-hz = /bits/ 64 <1267200000>;
opp-peak-kBps = <1600000>;
};
opp-1344000000 {
opp-hz = /bits/ 64 <1344000000>;
opp-peak-kBps = <1600000>;
};
opp-1420800000 {
opp-hz = /bits/ 64 <1420800000>;
opp-peak-kBps = <1600000>;
};
opp-1497600000 {
opp-hz = /bits/ 64 <1497600000>;
opp-peak-kBps = <3200000>;
};
opp-1574400000 {
opp-hz = /bits/ 64 <1574400000>;
opp-peak-kBps = <3200000>;
};
opp-1651200000 {
opp-hz = /bits/ 64 <1651200000>;
opp-peak-kBps = <3200000>;
};
opp-1728000000 {
opp-hz = /bits/ 64 <1728000000>;
opp-peak-kBps = <3200000>;
};
opp-1804800000 {
opp-hz = /bits/ 64 <1804800000>;
opp-peak-kBps = <3200000>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
opp-peak-kBps = <3200000>;
};
opp-1907200000 {
opp-hz = /bits/ 64 <1907200000>;
opp-peak-kBps = <3200000>;
};
opp-1958400000 {
opp-hz = /bits/ 64 <1958400000>;
opp-peak-kBps = <3200000>;
};
opp-2035200000 {
opp-hz = /bits/ 64 <2035200000>;
opp-peak-kBps = <3200000>;
};
opp-2112000000 {
opp-hz = /bits/ 64 <2112000000>;
opp-peak-kBps = <4266000>;
};
opp-2188800000 {
opp-hz = /bits/ 64 <2188800000>;
opp-peak-kBps = <4266000>;
};
opp-2265600000 {
opp-hz = /bits/ 64 <2265600000>;
opp-peak-kBps = <4266000>;
};
};
cl1_opp_tbl: opp-table-cluster1 {
compatible = "operating-points-v2";
opp-shared;
opp-115200000 {
opp-hz = /bits/ 64 <115200000>;
opp-peak-kBps = <816000>;
};
opp-192000000 {
opp-hz = /bits/ 64 <192000000>;
opp-peak-kBps = <816000>;
};
opp-268800000 {
opp-hz = /bits/ 64 <268800000>;
opp-peak-kBps = <816000>;
};
opp-345600000 {
opp-hz = /bits/ 64 <345600000>;
opp-peak-kBps = <816000>;
};
opp-422400000 {
opp-hz = /bits/ 64 <422400000>;
opp-peak-kBps = <816000>;
};
opp-499200000 {
opp-hz = /bits/ 64 <499200000>;
opp-peak-kBps = <816000>;
};
opp-576000000 {
opp-hz = /bits/ 64 <576000000>;
opp-peak-kBps = <816000>;
};
opp-652800000 {
opp-hz = /bits/ 64 <652800000>;
opp-peak-kBps = <816000>;
};
opp-729600000 {
opp-hz = /bits/ 64 <729600000>;
opp-peak-kBps = <816000>;
};
opp-806400000 {
opp-hz = /bits/ 64 <806400000>;
opp-peak-kBps = <816000>;
};
opp-883200000 {
opp-hz = /bits/ 64 <883200000>;
opp-peak-kBps = <816000>;
};
opp-960000000 {
opp-hz = /bits/ 64 <960000000>;
opp-peak-kBps = <816000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
opp-peak-kBps = <816000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
opp-peak-kBps = <1600000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
opp-peak-kBps = <1600000>;
};
opp-1267200000 {
opp-hz = /bits/ 64 <1267200000>;
opp-peak-kBps = <1600000>;
};
opp-1344000000 {
opp-hz = /bits/ 64 <1344000000>;
opp-peak-kBps = <1600000>;
};
opp-1420800000 {
opp-hz = /bits/ 64 <1420800000>;
opp-peak-kBps = <1600000>;
};
opp-1497600000 {
opp-hz = /bits/ 64 <1497600000>;
opp-peak-kBps = <3200000>;
};
opp-1574400000 {
opp-hz = /bits/ 64 <1574400000>;
opp-peak-kBps = <3200000>;
};
opp-1651200000 {
opp-hz = /bits/ 64 <1651200000>;
opp-peak-kBps = <3200000>;
};
opp-1728000000 {
opp-hz = /bits/ 64 <1728000000>;
opp-peak-kBps = <3200000>;
};
opp-1804800000 {
opp-hz = /bits/ 64 <1804800000>;
opp-peak-kBps = <3200000>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
opp-peak-kBps = <3200000>;
};
opp-1907200000 {
opp-hz = /bits/ 64 <1907200000>;
opp-peak-kBps = <3200000>;
};
opp-1958400000 {
opp-hz = /bits/ 64 <1958400000>;
opp-peak-kBps = <3200000>;
};
opp-2035200000 {
opp-hz = /bits/ 64 <2035200000>;
opp-peak-kBps = <3200000>;
};
opp-2112000000 {
opp-hz = /bits/ 64 <2112000000>;
opp-peak-kBps = <4266000>;
};
opp-2188800000 {
opp-hz = /bits/ 64 <2188800000>;
opp-peak-kBps = <4266000>;
};
opp-2265600000 {
opp-hz = /bits/ 64 <2265600000>;
opp-peak-kBps = <4266000>;
};
};
cl2_opp_tbl: opp-table-cluster2 {
compatible = "operating-points-v2";
opp-shared;
opp-115200000 {
opp-hz = /bits/ 64 <115200000>;
opp-peak-kBps = <816000>;
};
opp-192000000 {
opp-hz = /bits/ 64 <192000000>;
opp-peak-kBps = <816000>;
};
opp-268800000 {
opp-hz = /bits/ 64 <268800000>;
opp-peak-kBps = <816000>;
};
opp-345600000 {
opp-hz = /bits/ 64 <345600000>;
opp-peak-kBps = <816000>;
};
opp-422400000 {
opp-hz = /bits/ 64 <422400000>;
opp-peak-kBps = <816000>;
};
opp-499200000 {
opp-hz = /bits/ 64 <499200000>;
opp-peak-kBps = <816000>;
};
opp-576000000 {
opp-hz = /bits/ 64 <576000000>;
opp-peak-kBps = <816000>;
};
opp-652800000 {
opp-hz = /bits/ 64 <652800000>;
opp-peak-kBps = <816000>;
};
opp-729600000 {
opp-hz = /bits/ 64 <729600000>;
opp-peak-kBps = <816000>;
};
opp-806400000 {
opp-hz = /bits/ 64 <806400000>;
opp-peak-kBps = <816000>;
};
opp-883200000 {
opp-hz = /bits/ 64 <883200000>;
opp-peak-kBps = <816000>;
};
opp-960000000 {
opp-hz = /bits/ 64 <960000000>;
opp-peak-kBps = <816000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
opp-peak-kBps = <816000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
opp-peak-kBps = <1600000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
opp-peak-kBps = <1600000>;
};
opp-1267200000 {
opp-hz = /bits/ 64 <1267200000>;
opp-peak-kBps = <1600000>;
};
opp-1344000000 {
opp-hz = /bits/ 64 <1344000000>;
opp-peak-kBps = <1600000>;
};
opp-1420800000 {
opp-hz = /bits/ 64 <1420800000>;
opp-peak-kBps = <1600000>;
};
opp-1497600000 {
opp-hz = /bits/ 64 <1497600000>;
opp-peak-kBps = <3200000>;
};
opp-1574400000 {
opp-hz = /bits/ 64 <1574400000>;
opp-peak-kBps = <3200000>;
};
opp-1651200000 {
opp-hz = /bits/ 64 <1651200000>;
opp-peak-kBps = <3200000>;
};
opp-1728000000 {
opp-hz = /bits/ 64 <1728000000>;
opp-peak-kBps = <3200000>;
};
opp-1804800000 {
opp-hz = /bits/ 64 <1804800000>;
opp-peak-kBps = <3200000>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
opp-peak-kBps = <3200000>;
};
opp-1907200000 {
opp-hz = /bits/ 64 <1907200000>;
opp-peak-kBps = <3200000>;
};
opp-1958400000 {
opp-hz = /bits/ 64 <1958400000>;
opp-peak-kBps = <3200000>;
};
opp-2035200000 {
opp-hz = /bits/ 64 <2035200000>;
opp-peak-kBps = <3200000>;
};
opp-2112000000 {
opp-hz = /bits/ 64 <2112000000>;
opp-peak-kBps = <4266000>;
};
opp-2188800000 {
opp-hz = /bits/ 64 <2188800000>;
opp-peak-kBps = <4266000>;
};
opp-2265600000 {
opp-hz = /bits/ 64 <2265600000>;
opp-peak-kBps = <4266000>;
};
};
cl3_opp_tbl: opp-table-cluster3 {
compatible = "operating-points-v2";
opp-shared;
opp-115200000 {
opp-hz = /bits/ 64 <115200000>;
opp-peak-kBps = <816000>;
};
opp-192000000 {
opp-hz = /bits/ 64 <192000000>;
opp-peak-kBps = <816000>;
};
opp-268800000 {
opp-hz = /bits/ 64 <268800000>;
opp-peak-kBps = <816000>;
};
opp-345600000 {
opp-hz = /bits/ 64 <345600000>;
opp-peak-kBps = <816000>;
};
opp-422400000 {
opp-hz = /bits/ 64 <422400000>;
opp-peak-kBps = <816000>;
};
opp-499200000 {
opp-hz = /bits/ 64 <499200000>;
opp-peak-kBps = <816000>;
};
opp-576000000 {
opp-hz = /bits/ 64 <576000000>;
opp-peak-kBps = <816000>;
};
opp-652800000 {
opp-hz = /bits/ 64 <652800000>;
opp-peak-kBps = <816000>;
};
opp-729600000 {
opp-hz = /bits/ 64 <729600000>;
opp-peak-kBps = <816000>;
};
opp-806400000 {
opp-hz = /bits/ 64 <806400000>;
opp-peak-kBps = <816000>;
};
opp-883200000 {
opp-hz = /bits/ 64 <883200000>;
opp-peak-kBps = <816000>;
};
opp-960000000 {
opp-hz = /bits/ 64 <960000000>;
opp-peak-kBps = <816000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
opp-peak-kBps = <816000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
opp-peak-kBps = <1600000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
opp-peak-kBps = <1600000>;
};
opp-1267200000 {
opp-hz = /bits/ 64 <1267200000>;
opp-peak-kBps = <1600000>;
};
opp-1344000000 {
opp-hz = /bits/ 64 <1344000000>;
opp-peak-kBps = <1600000>;
};
opp-1420800000 {
opp-hz = /bits/ 64 <1420800000>;
opp-peak-kBps = <1600000>;
};
opp-1497600000 {
opp-hz = /bits/ 64 <1497600000>;
opp-peak-kBps = <3200000>;
};
opp-1574400000 {
opp-hz = /bits/ 64 <1574400000>;
opp-peak-kBps = <3200000>;
};
opp-1651200000 {
opp-hz = /bits/ 64 <1651200000>;
opp-peak-kBps = <3200000>;
};
opp-1728000000 {
opp-hz = /bits/ 64 <1728000000>;
opp-peak-kBps = <3200000>;
};
opp-1804800000 {
opp-hz = /bits/ 64 <1804800000>;
opp-peak-kBps = <3200000>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
opp-peak-kBps = <3200000>;
};
opp-1907200000 {
opp-hz = /bits/ 64 <1907200000>;
opp-peak-kBps = <3200000>;
};
opp-1958400000 {
opp-hz = /bits/ 64 <1958400000>;
opp-peak-kBps = <3200000>;
};
opp-2035200000 {
opp-hz = /bits/ 64 <2035200000>;
opp-peak-kBps = <3200000>;
};
opp-2112000000 {
opp-hz = /bits/ 64 <2112000000>;
opp-peak-kBps = <4266000>;
};
opp-2188800000 {
opp-hz = /bits/ 64 <2188800000>;
opp-peak-kBps = <4266000>;
};
opp-2265600000 {
opp-hz = /bits/ 64 <2265600000>;
opp-peak-kBps = <4266000>;
};
};
};
File diff suppressed because it is too large. Load diff
@@ -2,6 +2,7 @@
#include <dt-bindings/mfd/max77620.h>
#include "tegra210.dtsi"
#include "tegra210-p2180-emc.dtsi"
/ {
model = "NVIDIA Jetson TX1";
@@ -16,16 +16,16 @@
vddio-pex-ctl-supply = <&vdd_1v8>;
pci@1,0 {
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>;
<&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3";
status = "okay";
};
pci@2,0 {
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
phy-names = "pcie-0";
status = "okay";
};
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/mfd/max77620.h>
#include "tegra210.dtsi"
/ {
@@ -6,8 +8,10 @@
compatible = "nvidia,p2530", "nvidia,tegra210";
aliases {
rtc0 = "/i2c@7000d000/pmic@3c";
rtc1 = "/rtc@7000e000";
serial0 = &uarta;
serial3 = &uartd;
};
chosen {
@@ -19,6 +23,27 @@
reg = <0x0 0x80000000 0x0 0xc0000000>;
};
gpu@57000000 {
vdd-supply = <&vdd_gpu>;
status = "okay";
};
pinmux@700008d4 {
dvfs_pwm_active_state: pinmux-dvfs-pwm-active {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
};
dvfs_pwm_inactive_state: pinmux-dvfs-pwm-inactive {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_ENABLE>;
};
};
};
/* debug port */
serial@70006000 {
/delete-property/ dmas;
@@ -26,13 +51,279 @@
status = "okay";
};
serial@70006300 {
/delete-property/ reg-shift;
status = "okay";
compatible = "nvidia,tegra30-hsuart";
reset-names = "serial";
bluetooth {
compatible = "brcm,bcm43540-bt";
device-wakeup-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>;
shutdown-gpios = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 5) IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "host-wakeup";
};
};
i2c@7000d000 {
status = "okay";
clock-frequency = <400000>;
pmic: pmic@3c {
compatible = "maxim,max77620";
reg = <0x3c>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
#interrupt-cells = <2>;
interrupt-controller;
#gpio-cells = <2>;
gpio-controller;
pinctrl-names = "default";
pinctrl-0 = <&max77620_default>;
fps {
fps0 {
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
maxim,shutdown-fps-time-period-us = <5120>;
};
fps1 {
maxim,device-state-on-disabled-event = <MAX77620_FPS_INACTIVE_STATE_SLEEP>;
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
maxim,shutdown-fps-time-period-us = <5120>;
};
fps2 {
maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
};
};
max77620_default: pinmux {
gpio0 {
pins = "gpio0";
function = "gpio";
};
gpio1 {
pins = "gpio1";
function = "fps-out";
drive-push-pull = <1>;
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
maxim,active-fps-power-up-slot = <7>;
maxim,active-fps-power-down-slot = <0>;
};
gpio2_3 {
pins = "gpio2", "gpio3";
function = "fps-out";
drive-open-drain = <1>;
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
};
gpio4 {
pins = "gpio4";
function = "32k-out1";
};
gpio5_6_7 {
pins = "gpio5", "gpio6", "gpio7";
function = "gpio";
drive-push-pull = <1>;
};
};
regulators {
in-ldo0-1-supply = <&vdd_pre>;
in-ldo7-8-supply = <&vdd_pre>;
vdd_soc: sd0 {
regulator-name = "VDD_SOC";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1400000>;
regulator-always-on;
regulator-boot-on;
regulator-enable-ramp-delay = <146>;
regulator-ramp-delay = <9100>;
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
};
vdd_ddr: sd1 {
regulator-name = "VDD_DDR_1V1_PMIC";
regulator-always-on;
regulator-boot-on;
regulator-enable-ramp-delay = <130>;
regulator-ramp-delay = <9100>;
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
};
vdd_pre: sd2 {
regulator-name = "VDD_PRE_REG_1V35";
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
regulator-enable-ramp-delay = <176>;
regulator-ramp-delay = <7900>;
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
};
vdd_1v8: sd3 {
regulator-name = "VDD_1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
regulator-boot-on;
regulator-enable-ramp-delay = <242>;
regulator-ramp-delay = <7700>;
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
};
vdd_sys_1v2: ldo0 {
regulator-name = "AVDD_SYS_1V2";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-boot-on;
regulator-enable-ramp-delay = <26>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
};
vdd_pex_1v05: ldo1 {
regulator-name = "VDD_PEX_1V05";
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-enable-ramp-delay = <22>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
};
vddio_sdmmc: ldo2 {
regulator-name = "VDDIO_SDMMC";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
};
vdd_cam_hv: ldo3 {
regulator-name = "VDD_CAM_HV";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-enable-ramp-delay = <50>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
};
vdd_rtc: ldo4 {
regulator-name = "VDD_RTC";
regulator-min-microvolt = <850000>;
regulator-max-microvolt = <850000>;
regulator-always-on;
regulator-boot-on;
regulator-enable-ramp-delay = <22>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
};
vdd_ts_hv: ldo5 {
regulator-name = "VDD_TS_HV";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <62>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_NONE>;
};
vdd_ts: ldo6 {
regulator-name = "VDD_TS_1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-enable-ramp-delay = <36>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
};
avdd_1v05_pll: ldo7 {
regulator-name = "AVDD_1V05_PLL";
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-always-on;
regulator-boot-on;
regulator-enable-ramp-delay = <24>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
};
avdd_1v05: ldo8 {
regulator-name = "AVDD_SATA_HDMI_DP_1V05";
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-enable-ramp-delay = <22>;
regulator-ramp-delay = <50000>;
maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
};
};
};
};
pmc@7000e400 {
nvidia,invert-interrupt;
nvidia,suspend-mode = <0>;
nvidia,cpu-pwr-good-time = <0>;
nvidia,cpu-pwr-off-time = <0>;
nvidia,core-pwr-good-time = <4587 3876>;
nvidia,core-pwr-off-time = <39065>;
nvidia,core-power-req-active-high;
nvidia,sys-clock-req-active-high;
};
mmc@700b0200 {
status = "okay";
bus-width = <4>;
non-removable;
power-gpios = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
vqmmc-supply = <&vdd_1v8>;
vmmc-supply = <&vdd_3v3_sys>;
#address-cells = <1>;
#size-cells = <0>;
wifi@1 {
compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac";
reg = <1>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 2) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "host-wake";
};
};
/* eMMC */
@@ -40,6 +331,29 @@
status = "okay";
bus-width = <8>;
non-removable;
vqmmc-supply = <&vdd_1v8>;
vmmc-supply = <&vdd_3v3_sys>;
};
clock@70110000 {
status = "okay";
nvidia,cf = <6>;
nvidia,ci = <0>;
nvidia,cg = <2>;
nvidia,droop-ctrl = <0x00000f00>;
nvidia,force-mode = <1>;
nvidia,sample-rate = <25000>;
nvidia,pwm-min-microvolts = <708000>;
nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */
nvidia,pwm-to-pmic;
nvidia,pwm-tristate-microvolts = <1000000>;
nvidia,pwm-voltage-step-microvolts = <19200>;
pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
pinctrl-0 = <&dvfs_pwm_active_state>;
pinctrl-1 = <&dvfs_pwm_inactive_state>;
};
clk32k_in: clock-32k {
@@ -64,10 +378,50 @@
cpu@3 {
enable-method = "psci";
};
idle-states {
cpu-sleep {
status = "okay";
};
};
};
psci {
compatible = "arm,psci-0.2";
method = "smc";
};
vdd_3v3_sys: regulator-vdd-3v3-sys {
compatible = "regulator-fixed";
regulator-name = "VDD_3V3_SYS";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
gpio = <&pmic 3 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vdd_3v3_sd: regulator-vdd-3v3-sd {
compatible = "regulator-fixed";
regulator-name = "VDD_3V3_SD";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio TEGRA_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
enable-active-high;
vin-supply = <&vdd_3v3_sys>;
regulator-enable-ramp-delay = <472>;
};
vdd_gpu: regulator-vdd-gpu {
compatible = "pwm-regulator";
pwms = <&pwm 1 8000>;
regulator-name = "VDD_GPU";
regulator-min-microvolt = <710000>;
regulator-max-microvolt = <1320000>;
enable-gpios = <&pmic 6 GPIO_ACTIVE_HIGH>;
regulator-ramp-delay = <160>;
regulator-enable-ramp-delay = <2000>;
};
};
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "tegra210-p2571.dts"
/ {
model = "NVIDIA Shield TV 2015";
compatible = "nvidia,p2571-0930", "nvidia,tegra210";
hda@70030000 {
nvidia,model = "NVIDIA SHIELD TV APE";
};
sound {
label = "NVIDIA SHIELD TV APE";
};
};
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "tegra210-p2571-0930.dts"
/ {
model = "NVIDIA Shield TV Pro 2015";
compatible = "nvidia,p2571-0932", "nvidia,p2571-0930", "nvidia,tegra210";
sata@70020000 {
status = "okay";
phys = <&{/padctl@7009f000/pads/sata/lanes/sata-0}>;
};
mmc@700b0600 {
status = "disabled";
};
};
@@ -8,6 +8,24 @@
model = "NVIDIA Tegra210 P2571 reference design";
compatible = "nvidia,p2571", "nvidia,tegra210";
host1x@50000000 {
dpaux@54040000 {
status = "okay";
};
sor@54580000 {
status = "okay";
avdd-io-hdmi-dp-supply = <&avdd_1v05>;
vdd-hdmi-dp-pll-supply = <&vdd_1v8>;
hdmi-supply = <&vdd_hdmi>;
nvidia,ddc-i2c-bus = <&hdmi_ddc>;
nvidia,hpd-gpio = <&gpio TEGRA_GPIO(CC, 1)
GPIO_ACTIVE_LOW>;
};
};
pinmux: pinmux@700008d4 {
pinctrl-names = "boot";
pinctrl-0 = <&state_boot>;
@@ -1300,4 +1318,329 @@
};
};
};
pwm@7000a000 {
status = "okay";
};
/* HDMI DDC */
hdmi_ddc: i2c@7000c700 {
status = "okay";
clock-frequency = <100000>;
};
hda@70030000 {
status = "okay";
nvidia,model = "NVIDIA P2571 HDA";
};
usb@70090000 {
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/usb2/lanes/usb2-1}>,
<&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
<&{/padctl@7009f000/pads/usb2/lanes/usb2-3}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", "usb3-0",
"usb3-1", "usb3-2";
dvddio-pex-supply = <&vdd_pex_1v05>;
hvddio-pex-supply = <&vdd_1v8>;
avdd-usb-supply = <&vdd_3v3_sys>;
status = "okay";
};
padctl@7009f000 {
status = "okay";
avdd-pll-utmip-supply = <&vdd_1v8>;
avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
dvdd-pex-pll-supply = <&vdd_pex_1v05>;
hvdd-pex-pll-e-supply = <&vdd_1v8>;
pads {
usb2 {
status = "okay";
lanes {
micro_b: usb2-0 {
nvidia,function = "xusb";
status = "okay";
};
usb2-1 {
nvidia,function = "xusb";
status = "okay";
};
usb2-2 {
nvidia,function = "xusb";
status = "okay";
};
usb2-3 {
nvidia,function = "xusb";
status = "okay";
};
};
};
pcie {
status = "okay";
lanes {
pcie-0 {
nvidia,function = "usb3-ss";
status = "okay";
};
pcie-1 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-2 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-3 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-4 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-5 {
nvidia,function = "usb3-ss";
status = "okay";
};
pcie-6 {
nvidia,function = "usb3-ss";
status = "okay";
};
};
};
sata {
status = "okay";
lanes {
sata-0 {
nvidia,function = "sata";
status = "okay";
};
};
};
};
ports {
usb2-0 {
status = "okay";
vbus-supply = <&vdd_sys_mux>;
usb-role-switch;
mode = "otg";
connector {
compatible = "gpio-usb-b-connector",
"usb-b-connector";
label = "micro-USB";
type = "micro";
vbus-gpios = <&gpio TEGRA_GPIO(Z, 0)
GPIO_ACTIVE_LOW>;
id-gpios = <&pmic 0 GPIO_ACTIVE_HIGH>;
};
};
usb2-1 {
status = "okay";
vbus-supply = <&vdd_usb_vbus0>;
mode = "host";
};
usb2-2 {
status = "okay";
vbus-supply = <&vdd_usb_vbus1>;
mode = "host";
};
usb2-3 {
status = "okay";
vbus-supply = <&vdd_usb_vbus2>;
mode = "host";
};
usb3-0 {
nvidia,usb2-companion = <1>;
status = "okay";
};
usb3-1 {
nvidia,usb2-companion = <2>;
status = "okay";
};
usb3-2 {
nvidia,usb2-companion = <3>;
status = "okay";
};
};
};
/* MMC/SD */
mmc@700b0000 {
status = "okay";
bus-width = <4>;
cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
disable-wp;
vqmmc-supply = <&vddio_sdmmc>;
vmmc-supply = <&vdd_3v3_sd>;
};
usb@700d0000 {
status = "okay";
phys = <&micro_b>;
phy-names = "usb2-0";
avddio-usb-supply = <&vdd_3v3_sys>;
hvdd-usb-supply = <&vdd_1v8>;
};
fan: pwm-fan {
compatible = "pwm-fan";
pwms = <&pwm 3 45334>;
fan-supply = <&vdd_fan>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(G, 0) IRQ_TYPE_EDGE_RISING>;
cooling-levels = <0 64 128 255>;
#cooling-cells = <2>;
};
vdd_sys_mux: regulator-vdd-sys-mux {
compatible = "regulator-fixed";
regulator-name = "VDD_SYS_MUX";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
regulator-boot-on;
};
vdd_5v0_sys: regulator-vdd-5v0-sys {
compatible = "regulator-fixed";
regulator-name = "VDD_5V0_SYS";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
regulator-boot-on;
gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
enable-active-high;
vin-supply = <&vdd_sys_mux>;
};
vdd_hdmi: regulator-vdd-hdmi {
compatible = "regulator-fixed";
regulator-name = "VDD_HDMI_5V0";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio TEGRA_GPIO(CC, 7) GPIO_ACTIVE_HIGH>;
enable-active-high;
vin-supply = <&vdd_5v0_sys>;
};
vdd_usb_vbus0: regulator-vdd-usb-vbus0 {
compatible = "regulator-fixed";
regulator-name = "USB_VBUS_EN0";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio TEGRA_GPIO(CC, 4) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vdd_usb_vbus1: regulator-vdd-usb-vbus1 {
compatible = "regulator-fixed";
regulator-name = "USB_VBUS_EN1";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio TEGRA_GPIO(CC, 5) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vdd_usb_vbus2: regulator-vdd-usb-vbus2 {
compatible = "regulator-fixed";
regulator-name = "USB_VBUS_EN2";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio TEGRA_GPIO(D, 4) GPIO_ACTIVE_HIGH>;
enable-active-high;
};
vdd_fan: regulator-vdd-fan {
compatible = "regulator-fixed";
regulator-name = "VDD_FAN";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio TEGRA_GPIO(E, 4) GPIO_ACTIVE_LOW>;
enable-active-high;
regulator-enable-ramp-delay = <284>;
};
thermal-zones {
cpu-thermal {
trips {
cpu_trip_critical: critical {
temperature = <96500>;
hysteresis = <0>;
type = "critical";
};
cpu_trip_hot: hot {
temperature = <70000>;
hysteresis = <2000>;
type = "hot";
};
cpu_trip_active: active {
temperature = <50000>;
hysteresis = <2000>;
type = "active";
};
cpu_trip_passive: passive {
temperature = <30000>;
hysteresis = <2000>;
type = "passive";
};
};
cooling-maps {
map0 {
cooling-device = <&fan 3 3>;
trip = <&cpu_trip_critical>;
};
map1 {
cooling-device = <&fan 2 2>;
trip = <&cpu_trip_hot>;
};
map2 {
cooling-device = <&fan 1 1>;
trip = <&cpu_trip_active>;
};
map3 {
cooling-device = <&fan 0 0>;
trip = <&cpu_trip_passive>;
};
};
};
};
};
@@ -1,9 +1,29 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "tegra210.dtsi"
#include "tegra210-p2894.dtsi"
/ {
model = "NVIDIA Shield TV";
compatible = "nvidia,p2894-0050-a08", "nvidia,darcy", "nvidia,tegra210";
mmc@700b0200 {
status = "okay";
bus-width = <4>;
non-removable;
power-gpios = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
vqmmc-supply = <&max77620_sd3>;
vmmc-supply = <&vdd_3v3>;
#address-cells = <1>;
#size-cells = <0>;
wifi@1 {
compatible = "brcm,bcm4354-fmac", "brcm,bcm4329-fmac";
reg = <1>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 2) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "host-wake";
};
};
};
+296 -1
View File
@@ -4,11 +4,11 @@
#include <dt-bindings/input/gpio-keys.h>
#include <dt-bindings/mfd/max77620.h>
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
#include "tegra210.dtsi"
/ {
aliases {
serial0 = &uarta;
serial3 = &uartd;
};
chosen {
@@ -21,6 +21,43 @@
reg = <0x0 0x80000000 0x0 0xc0000000>;
};
pcie@1003000 {
status = "okay";
hvddio-pex-supply = <&max77620_sd3>;
dvddio-pex-supply = <&max77620_ldo1>;
vddio-pex-ctl-supply = <&max77620_sd3>;
pci@2,0 {
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>;
phy-names = "pcie-0";
status = "okay";
};
};
host1x@50000000 {
dpaux@54040000 {
status = "okay";
};
sor@54580000 {
status = "okay";
avdd-io-hdmi-dp-supply = <&max77620_ldo8>;
vdd-hdmi-dp-pll-supply = <&max77620_sd3>;
hdmi-supply = <&vdd_hdmi>;
nvidia,ddc-i2c-bus = <&hdmi_ddc>;
nvidia,hpd-gpio = <&gpio TEGRA_GPIO(CC, 1)
GPIO_ACTIVE_LOW>;
};
};
gpu@57000000 {
vdd-supply = <&vdd_gpu>;
status = "okay";
};
pinmux: pinmux@700008d4 {
status = "okay";
pinctrl-names = "boot";
@@ -1318,6 +1355,20 @@
nvidia,open-drain = <TEGRA_PIN_DISABLE>;
};
};
dvfs_pwm_active_state: pinmux-dvfs-pwm-active {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
};
dvfs_pwm_inactive_state: pinmux-dvfs-pwm-inactive {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_ENABLE>;
};
};
};
serial@70006000 {
@@ -1326,6 +1377,26 @@
status = "okay";
};
pwm@7000a000 {
status = "okay";
};
serial@70006300 {
/delete-property/ reg-shift;
status = "okay";
compatible = "nvidia,tegra30-hsuart";
reset-names = "serial";
bluetooth {
compatible = "brcm,bcm43540-bt";
device-wakeup-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_HIGH>;
shutdown-gpios = <&gpio TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(H, 5) IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "host-wakeup";
};
};
i2c@7000d000 {
status = "okay";
clock-frequency = <400000>;
@@ -1570,6 +1641,12 @@
};
};
/* HDMI DDC */
hdmi_ddc: i2c@7000c700 {
status = "okay";
clock-frequency = <100000>;
};
pmc@7000e400 {
nvidia,invert-interrupt;
nvidia,suspend-mode = <0>;
@@ -1582,12 +1659,154 @@
status = "okay";
};
hda@70030000 {
status = "okay";
nvidia,model = "NVIDIA SHIELD TV HDA";
};
usb@70090000 {
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
phy-names = "usb2-0", "usb2-2", "usb3-0", "usb3-1";
dvddio-pex-supply = <&max77620_ldo1>;
hvddio-pex-supply = <&max77620_sd3>;
avdd-usb-supply = <&vdd_3v3>;
status = "okay";
};
padctl@7009f000 {
status = "okay";
avdd-pll-utmip-supply = <&max77620_sd3>;
avdd-pll-uerefe-supply = <&max77620_ldo7>;
dvdd-pex-pll-supply = <&max77620_ldo1>;
hvdd-pex-pll-e-supply = <&max77620_sd3>;
pads {
usb2 {
status = "okay";
lanes {
usb2-0 {
nvidia,function = "xusb";
status = "okay";
};
usb2-2 {
nvidia,function = "xusb";
status = "okay";
};
};
};
pcie {
status = "okay";
lanes {
pcie-0 {
nvidia,function = "pcie-x1";
status = "okay";
};
pcie-1 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-2 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-3 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-4 {
nvidia,function = "pcie-x4";
status = "okay";
};
pcie-5 {
nvidia,function = "usb3-ss";
status = "okay";
};
pcie-6 {
nvidia,function = "usb3-ss";
status = "okay";
};
};
};
};
ports {
usb2-0 {
status = "okay";
vbus-supply = <&usb_vbus1>;
usb-role-switch;
role-switch-default-mode = "peripheral";
mode = "otg";
};
usb2-2 {
status = "okay";
vbus-supply = <&usb_vbus2>;
mode = "host";
};
usb3-0 {
nvidia,usb2-companion = <0>;
status = "okay";
};
usb3-1 {
nvidia,usb2-companion = <2>;
status = "okay";
};
};
};
mmc@700b0600 {
bus-width = <8>;
non-removable;
status = "okay";
};
usb@700d0000 {
status = "okay";
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>;
phy-names = "usb2-0", "usb3-0";
avddio-usb-supply = <&max77620_ldo1>;
hvdd-usb-supply = <&vdd_3v3>;
};
clock@70110000 {
status = "okay";
nvidia,cf = <6>;
nvidia,ci = <0>;
nvidia,cg = <2>;
nvidia,droop-ctrl = <0x00000f00>;
nvidia,force-mode = <1>;
nvidia,sample-rate = <25000>;
nvidia,pwm-min-microvolts = <708000>;
nvidia,pwm-period-nanoseconds = <2500>; /* 2.5us */
nvidia,pwm-to-pmic;
nvidia,pwm-tristate-microvolts = <1000000>;
nvidia,pwm-voltage-step-microvolts = <19200>;
pinctrl-names = "dvfs_pwm_enable", "dvfs_pwm_disable";
pinctrl-0 = <&dvfs_pwm_active_state>;
pinctrl-1 = <&dvfs_pwm_inactive_state>;
};
clk32k_in: clock-32k {
compatible = "fixed-clock";
clock-frequency = <32768>;
@@ -1637,6 +1856,18 @@
method = "smc";
};
fan: pwm-fan {
compatible = "pwm-fan";
pwms = <&pwm 3 65536>;
fan-supply = <&vdd_fan>;
interrupt-parent = <&gpio>;
interrupts = <TEGRA_GPIO(G, 0) IRQ_TYPE_EDGE_RISING>;
/* cooling level (0, 1, 2, 3) - pwm inverted */
cooling-levels = <255 128 64 0>;
#cooling-cells = <2>;
};
battery_reg: regulator-vdd-ac-bat {
compatible = "regulator-fixed";
regulator-name = "vdd-ac-bat";
@@ -1831,4 +2062,68 @@
enable-active-high;
gpio-open-drain;
};
vdd_gpu: regulator-vdd-gpu {
compatible = "pwm-regulator";
pwms = <&pwm 1 8000>;
regulator-name = "VDD_GPU";
regulator-min-microvolt = <710000>;
regulator-max-microvolt = <1320000>;
enable-gpios = <&pmic 6 GPIO_ACTIVE_HIGH>;
regulator-ramp-delay = <80>;
regulator-enable-ramp-delay = <2000>;
regulator-settling-time-us = <160>;
};
thermal-zones {
cpu-thermal {
trips {
cpu_trip_critical: critical {
temperature = <96500>;
hysteresis = <0>;
type = "critical";
};
cpu_trip_hot: hot {
temperature = <70000>;
hysteresis = <2000>;
type = "hot";
};
cpu_trip_active: active {
temperature = <50000>;
hysteresis = <2000>;
type = "active";
};
cpu_trip_passive: passive {
temperature = <30000>;
hysteresis = <2000>;
type = "passive";
};
};
cooling-maps {
map0 {
cooling-device = <&fan 3 3>;
trip = <&cpu_trip_critical>;
};
map1 {
cooling-device = <&fan 2 2>;
trip = <&cpu_trip_hot>;
};
map2 {
cooling-device = <&fan 1 1>;
trip = <&cpu_trip_active>;
};
map3 {
cooling-device = <&fan 0 0>;
trip = <&cpu_trip_passive>;
};
};
};
};
};
+22 -7
View File
@@ -1018,6 +1018,21 @@
status = "disabled";
};
bpmp: bpmp@70016000 {
compatible = "nvidia,tegra210-bpmp";
reg = <0x0 0x70016000 0x0 0x2000
0x0 0x60001000 0x0 0x1000>;
status = "disabled";
interrupts = <GIC_SPI 6 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 4 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "tx", "rx";
iommus = <&mc TEGRA_SWGROUP_AVPC>;
#clock-cells = <1>;
};
mc: memory-controller@70019000 {
compatible = "nvidia,tegra210-mc";
reg = <0x0 0x70019000 0x0 0x1000>;
@@ -1028,6 +1043,7 @@
#iommu-cells = <1>;
#reset-cells = <1>;
#interconnect-cells = <1>;
};
emc: external-memory-controller@7001b000 {
@@ -1041,6 +1057,7 @@
nvidia,memory-controller = <&mc>;
operating-points-v2 = <&emc_icc_dvfs_opp_table>;
#interconnect-cells = <0>;
#cooling-cells = <2>;
};
@@ -1293,11 +1310,9 @@
nvidia,pad-autocal-pull-down-offset-sdr104 = <0x0>;
nvidia,default-tap = <0x2>;
nvidia,default-trim = <0x4>;
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
<&tegra_car TEGRA210_CLK_PLL_C4_OUT0>,
<&tegra_car TEGRA210_CLK_PLL_C4>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>;
assigned-clock-rates = <200000000>, <1000000000>, <1000000000>;
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
status = "disabled";
};
@@ -1360,8 +1375,8 @@
nvidia,default-tap = <0x8>;
nvidia,default-trim = <0x0>;
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
<&tegra_car TEGRA210_CLK_PLL_C4_OUT0>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT0>;
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
nvidia,dqs-trim = <40>;
mmc-hs400-1_8v;
status = "disabled";
@@ -0,0 +1,99 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "tegra210b01.dtsi"
#include "tegra210-p2894.dtsi"
/ {
model = "NVIDIA Shield TV Pro 2019";
compatible = "nvidia,p2894-2551-b00", "nvidia,darcy", "nvidia,tegra210b01",
"nvidia,tegra210";
pcie@1003000 {
pci@1,0 {
phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>;
phy-names = "pcie-0", "pcie-1";
status = "okay";
wifi@0,0 {
compatible = "brcm,bcm4356-fmac", "brcm,bcm4329-fmac";
};
};
};
pinmux@700008d4 {
pinmux {
pex_l0_rst_n_pa0 {
nvidia,function = "pe0";
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
pex_l0_clkreq_n_pa1 {
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,io-hv = <TEGRA_PIN_DISABLE>;
};
pex_wake_n_pa2 {
nvidia,pull = <TEGRA_PIN_PULL_UP>;
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,io-hv = <TEGRA_PIN_DISABLE>;
};
wifi_wake_ap_ph2 {
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
};
pz1 {
nvidia,pull = <TEGRA_PIN_PULL_UP>;
};
};
};
i2c@7000d000 {
pmic@3c {
regulators {
sd2 {
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
};
};
};
};
usb@70090000 {
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
phy-names = "usb2-0", "usb2-2", "usb3-0", "usb3-1";
dvddio-pex-supply = <&max77620_ldo1>;
hvddio-pex-supply = <&max77620_sd3>;
avdd-usb-supply = <&vdd_3v3>;
status = "okay";
};
padctl@7009f000 {
pads {
pcie {
lanes {
pcie-1 {
nvidia,function = "usb3-ss";
};
pcie-4 {
nvidia,function = "usb3-ss";
};
pcie-6 {
/delete-property/ nvidia,function;
status = "disabled";
};
};
};
};
};
usb@700d0000 {
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
};
};
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,142 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "tegra210b01-nx.dtsi"
/ {
model = "Nintendo Switch Lite";
compatible = "nvidia,vali", "nintendo,hoag", "nintendo,nx", "nvidia,tegra210b01", "nvidia,tegra210";
/* Joycon/Fan power (usb) */
v_vdd50_b: v-vdd50-b {
status = "disabled"; /* Only enabled on Odin/Modin */
};
en_vdd_jcl_chgr: left-joycon-charger {
status = "disabled"; /* Only enabled on Odin/Modin/Fric */
};
en_vdd_jcr_chgr: right-joycon-charger {
status = "disabled"; /* Only enabled on Odin/Modin/Fric */
};
spi@7000da00 {
status = "disabled"; /* Disabled for Vali since Sio uses it */
};
/* Right Joycon */
serial@70006040 {
status = "disabled";
joyconr {
status = "disabled";
};
};
/* Left Joycon / Sio */
serial@70006200 {
status = "okay";
/delete-property/ nvidia,invert-txd;
/delete-property/ nvidia,invert-rts;
joyconl {
status = "disabled";
};
sio {
status = "okay";
};
};
i2c@7000c000 {
bm92t: bm92t@18 {
status = "disabled";
/delete-property/ rohm,dp-signal-toggle-on-resume;
rohm,dp-disable;
rohm,pd-5v-current-limit-ma = <2000>;
rohm,pd-9v-current-limit-ma = <1500>;
rohm,pd-12v-current-limit-ma = <1200>;
rohm,pd-15v-current-limit-ma = <900>;
};
bq2419x: bq24193@6b {
battery_charger: charger {
ti,charge-voltage-limit-millivolt = <4320>; /* Adjusted by cell age */
ti,fast-charge-current-limit-milliamp = <1664>;
ti,temp-range = <0 18 47 58>;
ti,charge-thermal-voltage-limit = <4320 4320 4320 4080>; /* Adjusted by cell age */
ti,charge-current-limit = <512 640 1664 1664>;
};
};
fuel_gauge: fuel-gauge@36 {
maxim,over-volt = <4320>; /* Actual: 4370 mV */
maxim,kernel-maximum-soc = <100>; /* Adjusted by cell age */
};
};
i2c@7000d000 {
pmic_b: pmic@3c {
regulators {
/* Vali: Powers LDO 2V8 for Sio VDD
* Powers LDO 1V8 for I2C1 VDDQ and ALC5639.
*/
ldo8 {
regulator-name = "vdd-i2c1";
regulator-max-microvolt = <2800000>;
regulator-always-on;
regulator-boot-on;
};
};
};
};
i2c@546c0000 {
bus-pullup-supply = <&battery_reg>;
};
host1x@50000000 {
/* tegradc.1: DP */
dc@54240000 {
status = "disabled";
};
};
xusb: usb@70090000 {
status = "okay";
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
phy-names = "usb2-0", "usb3-0";
extcon = <&bm92t 0>;
extcon-cable-names = "vbus";
avdd-usb-supply = <&vdd_3v3>;
dvddio-pex-supply = <&max77620_ldo1>;
hvddio-pex-supply = <&max77620_sd3>;
};
xudc: usb@700d0000 {
status = "okay";
phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
<&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
phy-names = "usb2-0", "usb3-0";
extcon = <&bm92t 1>;
extcon-cable-names = "id";
hvdd-usb-supply = <&vdd_3v3>;
avddio-usb-supply = <&max77620_ldo1>;
};
padctl@7009f000 {
status = "okay";
avdd-pll-utmip-supply = <&max77620_sd3>;
avdd-pll-uerefe-supply = <&max77620_ldo1>;
dvdd-pex-pll-supply = <&max77620_ldo1>;
hvdd-pex-pll-e-supply = <&max77620_sd3>;
};
};
+184
View File
@@ -0,0 +1,184 @@
// SPDX-License-Identifier: GPL-2.0
#include "tegra210.dtsi"
/delete-node/ &emc;
/delete-node/ &{/sata@70020000};
/ {
compatible = "nvidia,tegra210b01", "nvidia,tegra210";
pcie@1003000 {
compatible = "nvidia,tegra210b01-pcie";
/delete-property/ pinctrl-names;
/delete-property/ pinctrl-0;
/delete-property/ pinctrl-1;
};
host1x@50000000 {
/delete-node/ sor@54540000;
/delete-node/ dpaux@545c0000;
/delete-node/ vi@54080000;
/delete-node/ i2c@546c0000;
dc@54200000 {
nvidia,outputs = <&dsia &dsib &sor1>;
};
dc@54240000 {
nvidia,outputs = <&dsia &dsib &sor1>;
};
dsi@54300000 {
compatible = "nvidia,tegra210b01-dsi";
};
dsi@54400000 {
compatible = "nvidia,tegra210b01-dsi";
};
};
clock@60006000 {
compatible = "nvidia,tegra210b01-car";
};
actmon@6000c800 {
clocks = <&tegra_car TEGRA210_CLK_ACTMON>,
<&bpmp 0>;
};
pinmux@700008d4 {
compatible = "nvidia,tegra210b01-pinmux";
pinmux-sdmmc1-1v8-drv {
sdmmc1 {
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
pinmux-sdmmc3-1v8-drv {
sdmmc3 {
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
};
i2c@7000d100 {
/delete-property/ pinctrl-0;
/delete-property/ pinctrl-1;
/delete-property/ pinctrl-names;
};
memory-controller@70019000 {
#address-cells = <2>;
#size-cells = <2>;
emc: external-memory-controller@7001b000 {
compatible = "nvidia,tegra186-emc";
reg = <0x0 0x7001b000 0x0 0x1000>;
clocks = <&bpmp 0>;
clock-names = "emc";
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
#cooling-cells = <2>;
#interconnect-cells = <0>;
nvidia,bpmp = <&bpmp>;
};
};
mmc@700b0000 {
compatible = "nvidia,tegra210b01-sdhci";
nvidia,pad-autocal-pull-up-offset-3v3 = <0x06>;
nvidia,pad-autocal-pull-down-offset-3v3 = <0x06>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
nvidia,default-tap = <0xb>;
nvidia,default-trim = <0xe>;
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
};
mmc@700b0200 {
compatible = "nvidia,tegra210b01-sdhci";
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
nvidia,default-tap = <0x8>;
nvidia,default-trim = <0xd>;
};
mmc@700b0400 {
compatible = "nvidia,tegra210b01-sdhci";
nvidia,pad-autocal-pull-up-offset-3v3 = <0x06>;
nvidia,pad-autocal-pull-down-offset-3v3 = <0x06>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
nvidia,default-tap = <0xb>;
nvidia,default-trim = <0x12>;
};
mmc@700b0600 {
compatible = "nvidia,tegra210b01-sdhci";
nvidia,pad-autocal-pull-up-offset-1v8 = <0x06>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x06>;
nvidia,default-tap = <0x9>;
nvidia,default-trim = <0xd>;
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
assigned-clock-rates = <199680000>, <199680000>;
};
/* Tegra210B01 has MBIST patched and is missing VI unit */
pmc@7000e400 {
compatible = "nvidia,tegra210b01-pmc";
powergates {
/delete-node/ venc;
};
};
bpmp@70016000 {
status = "okay";
};
usb@70090000 {
compatible = "nvidia,tegra210b01-xusb";
};
padctl@7009f000 {
compatible = "nvidia,tegra210b01-xusb-padctl";
pads {
pcie {
clocks = <&tegra_car TEGRA210_CLK_PLL_E>,
<&tegra_car TEGRA210_CLK_PLL_P_UPHY_OUT>;
clock-names = "pll", "uphy_mgmt";
};
};
};
usb@700d0000 {
compatible = "nvidia,tegra210b01-xudc";
};
thermal-sensor@700e2000 {
compatible = "nvidia,tegra210b01-soctherm";
throttle-cfgs {
heavy {
nvidia,cpu-throt-percent = <0>;
nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_NONE>;
};
};
};
clock@70110000 {
compatible = "nvidia,tegra210b01-dfll";
};
};
+1
View File
@@ -872,6 +872,7 @@ CONFIG_REGULATOR_HI6421V530=y
CONFIG_REGULATOR_HI655X=y
CONFIG_REGULATOR_LP873X=m
CONFIG_REGULATOR_MAX77620=y
CONFIG_REGULATOR_MAX77812=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_MAX20411=m
CONFIG_REGULATOR_MP8859=y
+5 -8
View File
@@ -1,5 +1,6 @@
CONFIG_LOCALVERSION="-4k"
CONFIG_AUDIT=y
CONFIG_GENERIC_IRQ_DEBUGFS=y
CONFIG_TIME_KUNIT_TEST=m
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -9,7 +10,6 @@ CONFIG_BPF_JIT_ALWAYS_ON=y
# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
CONFIG_BPF_LSM=y
CONFIG_PREEMPT=y
CONFIG_SCHED_CLASS_EXT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
@@ -43,14 +43,12 @@ CONFIG_RT_SOFTIRQ_AWARE_SCHED=y
CONFIG_RELAY=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
CONFIG_BOOT_CONFIG=y
CONFIG_EXPERT=y
# CONFIG_FHANDLE is not set
# CONFIG_RSEQ is not set
CONFIG_PROFILING=y
CONFIG_RUST=y
CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_HISI=y
CONFIG_ARCH_QCOM=y
@@ -70,6 +68,7 @@ CONFIG_RANDOMIZE_BASE=y
# CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set
CONFIG_UNWIND_PATCH_PAC_INTO_SCS=y
CONFIG_CMDLINE="console=ttynull stack_depot_disable=on cgroup_disable=pressure kasan.stacktrace=off kvm-arm.mode=protected bootconfig ioremap_guard"
CONFIG_CMDLINE_EXTEND=y
# CONFIG_DMI is not set
CONFIG_HIBERNATION=y
CONFIG_PM_USERSPACE_AUTOSLEEP=y
@@ -422,7 +421,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=0
CONFIG_SERIAL_8250_DW=y
# CONFIG_SERIAL_8250_TEGRA is not set
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -441,7 +439,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_HISI is not set
# CONFIG_HW_RANDOM_HISTB is not set
CONFIG_HW_RANDOM_CCTRNG=m
# CONFIG_DEVMEM is not set
# CONFIG_DEVPORT is not set
# CONFIG_I2C_HELPER_AUTO is not set
# CONFIG_I2C_TEGRA_BPMP is not set
@@ -607,15 +604,16 @@ CONFIG_VIRTIO_BALLOON=m
CONFIG_VHOST_VSOCK=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ASHMEM_RUST=y
CONFIG_COMMON_CLK_SCPI=y
# CONFIG_SUNXI_CCU is not set
CONFIG_CLK_KUNIT_TEST=m
CONFIG_CLK_GATE_KUNIT_TEST=m
CONFIG_HWSPINLOCK=y
CONFIG_TEGRA186_TIMER=y
# CONFIG_SUN50I_ERRATUM_UNKNOWN1 is not set
CONFIG_TEGRA_HSP_MBOX=y
CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_RPMSG_CHAR=y
@@ -628,6 +626,7 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y
CONFIG_DEVFREQ_GOV_PASSIVE=y
CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_MEMORY=y
CONFIG_TEGRA210_EMC=y
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
CONFIG_IIO_TRIGGER=y
@@ -763,8 +762,6 @@ CONFIG_STACKTRACE_BUILD_ID=y
CONFIG_DYNAMIC_DEBUG_CORE=y
CONFIG_DEBUG_INFO_DWARF5=y
CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_MODULE_ALLOW_BTF_MISMATCH=y
CONFIG_HEADERS_INSTALL=y
# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
CONFIG_MAGIC_SYSRQ=y
+32
View File
@@ -19,6 +19,7 @@
#ifndef __ASSEMBLER__
#ifdef CONFIG_64BIT
#include <linux/types.h>
/*
@@ -192,6 +193,37 @@ struct gcs_context {
__u64 reserved;
};
#else /* CONFIG_64BIT */
/*
* Signal context structure - contains all info to do with the state
* before the signal handler was invoked. Note: only add new entries
* to the end of the structure.
*/
struct sigcontext {
unsigned long trap_no;
unsigned long error_code;
unsigned long oldmask;
unsigned long arm_r0;
unsigned long arm_r1;
unsigned long arm_r2;
unsigned long arm_r3;
unsigned long arm_r4;
unsigned long arm_r5;
unsigned long arm_r6;
unsigned long arm_r7;
unsigned long arm_r8;
unsigned long arm_r9;
unsigned long arm_r10;
unsigned long arm_fp;
unsigned long arm_ip;
unsigned long arm_sp;
unsigned long arm_lr;
unsigned long arm_pc;
unsigned long arm_cpsr;
unsigned long fault_address;
};
#endif /* CONFIG_64BIT */
#endif /* !__ASSEMBLER__ */
#include <asm/sve_context.h>
+4 -3
View File
@@ -525,7 +525,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr4[] = {
static const struct arm64_ftr_bits ftr_ctr[] = {
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_EL0_DIC_SHIFT, 1, 1),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_EL0_IDC_SHIFT, 1, 1),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, CTR_EL0_IDC_SHIFT, 1, 1),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_EL0_CWG_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_EL0_ERG_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_EL0_DminLine_SHIFT, 4, 1),
@@ -570,6 +570,7 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
* of support.
*/
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_EL1_PMUVer_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64DFR0_EL1_TraceVer_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_EL1_DebugVer_SHIFT, 4, 0x6),
ARM64_FTR_END,
};
@@ -715,8 +716,8 @@ static const struct arm64_ftr_bits ftr_id_dfr0[] = {
/* [31:28] TraceFilt */
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_DFR0_EL1_PerfMon_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MProfDbg_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapTrc_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopTrc_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapTrc_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopTrc_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapDbg_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopSDbg_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopDbg_SHIFT, 4, 0),
+4 -1
View File
@@ -385,8 +385,11 @@ static __init void parse_cmdline(const void *fdt, int chosen)
static char const cmdline[] __initconst = CONFIG_CMDLINE;
const u8 *prop = get_bootargs_cmdline(fdt, chosen);
if (IS_ENABLED(CONFIG_CMDLINE_FORCE) || !prop)
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
!prop) {
__parse_cmdline(cmdline, true);
}
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && prop)
__parse_cmdline(prop, true);
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -6,7 +6,7 @@ if ARM_AMBA
config TEGRA_AHB
bool "Enable AHB driver for NVIDIA Tegra SoCs" if COMPILE_TEST
default y if ARCH_TEGRA && !GKI_HACKS_TO_FIX
default y if (ARCH_TEGRA && ARM) || ARCH_TEGRA_210_SOC
help
Adds AHB configuration functionality for NVIDIA Tegra SoCs,
which controls AHB bus master arbitration and some performance
+9
View File
@@ -2236,6 +2236,15 @@ static int fw_devlink_create_devlink(struct device *con,
goto out;
}
/*
* SYNC_STATE_ONLY links are useless once a consumer device has probed.
* So, only create it if the consumer hasn't probed yet.
*/
if (flags & DL_FLAG_SYNC_STATE_ONLY &&
con->links.status != DL_DEV_NO_DRIVER &&
con->links.status != DL_DEV_PROBING)
goto out;
if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
dev_err(con, "Failed to create device link (0x%x) with supplier %s for %pfwf\n",
flags, dev_name(sup_dev), link->consumer);
+23 -2
View File
@@ -2464,6 +2464,13 @@ static void clk_change_rate(struct clk_core *core)
if (core->ops->post_rate_change)
core->ops->post_rate_change(core->hw, old_rate, core->rate);
/*
* Allow children to be aware that next set rate operation is triggered
* by downward rate propagation, rather than direct set rate on itself.
*/
if (core->notifier_count)
__clk_notify(core, PRE_SUBTREE_CHANGE, old_rate, core->rate);
/*
* Use safe iteration, as change_rate can actually swap parents
* for certain clock types.
@@ -2479,6 +2486,9 @@ static void clk_change_rate(struct clk_core *core)
if (core->new_child)
clk_change_rate(core->new_child);
if (core->notifier_count)
__clk_notify(core, POST_SUBTREE_CHANGE, old_rate, core->rate);
clk_pm_runtime_put(core);
}
@@ -2858,6 +2868,7 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
int ret = 0;
int p_index = 0;
unsigned long p_rate = 0;
unsigned long old_p_rate = 0;
lockdep_assert_held(&prepare_lock);
@@ -2900,13 +2911,23 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
if (ret & NOTIFY_STOP_MASK)
goto runtime_put;
/* do the re-parent */
ret = __clk_set_parent(core, parent, p_index);
/* propagate PRE_PARENT_CHANGE notifications */
if (core->parent)
old_p_rate = core->parent->rate;
ret = __clk_notify(core, PRE_PARENT_CHANGE, old_p_rate, p_rate);
/* do the re-parent if no objections */
if (!(ret & NOTIFY_STOP_MASK))
ret = __clk_set_parent(core, parent, p_index);
/* propagate rate an accuracy recalculation accordingly */
if (ret) {
__clk_notify(core, ABORT_PARENT_CHANGE, old_p_rate, p_rate);
__clk_recalc_rates(core, true, ABORT_RATE_CHANGE);
} else {
__clk_notify(core, POST_PARENT_CHANGE, old_p_rate, p_rate);
__clk_recalc_rates(core, true, POST_RATE_CHANGE);
__clk_recalc_accuracies(core);
}
+1
View File
@@ -27,6 +27,7 @@ obj-$(CONFIG_TEGRA124_CLK_EMC) += clk-tegra124-emc.o
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
obj-y += cvb.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210b01.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210-emc.o
obj-$(CONFIG_CLK_TEGRA_BPMP) += clk-bpmp.o
obj-y += clk-utils.o
+326 -15
View File
@@ -31,6 +31,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
@@ -193,6 +194,37 @@
*/
#define REF_CLK_CYC_PER_DVCO_SAMPLE 4
/*
* DFLL_OUTPUT_RAMP_DELAY: after the DFLL's I2C PMIC output starts
* requesting the minimum TUNE_HIGH voltage, the minimum number of
* microseconds to wait for the PMIC's voltage output to finish
* slewing
*/
#define DFLL_OUTPUT_RAMP_DELAY 100
/*
* DFLL_TUNE_HIGH_DELAY: number of microseconds to wait between tests
* to see if the high voltage has been reached yet, during a
* transition from the low-voltage range to the high-voltage range
*/
#define DFLL_TUNE_HIGH_DELAY 2000
/*
* DFLL_TUNE_HIGH_MARGIN_STEPS: attempt to initially program the DFLL
* voltage target to a (DFLL_TUNE_HIGH_MARGIN_STEPS * 10 millivolt)
* margin above the high voltage floor, in closed-loop mode in the
* high-voltage range
*/
#define DFLL_TUNE_HIGH_MARGIN_STEPS 2
/*
* I2C_OUTPUT_ACTIVE_TEST_US: mandatory minimum interval (in
* microseconds) between testing whether the I2C controller is
* currently sending a voltage-set command. Some comments list this
* as being a worst-case margin for "disable propagation."
*/
#define I2C_OUTPUT_ACTIVE_TEST_US 2
/*
* REF_CLOCK_RATE: the DFLL reference clock rate currently supported by this
* driver, in Hz
@@ -224,6 +256,9 @@ enum dfll_ctrl_mode {
* enum dfll_tune_range - voltage range that the driver believes it's in
* @DFLL_TUNE_UNINITIALIZED: DFLL tuning not yet programmed
* @DFLL_TUNE_LOW: DFLL in the low-voltage range (or open-loop mode)
* @DFLL_TUNE_WAIT_DFLL: waiting for DFLL voltage output to reach high
* @DFLL_TUNE_WAIT_PMIC: waiting for PMIC to react to DFLL output
* @DFLL_TUNE_HIGH: DFLL in the high-voltage range
*
* Some DFLL tuning parameters may need to change depending on the
* DVCO's voltage; these states represent the ranges that the driver
@@ -232,7 +267,10 @@ enum dfll_ctrl_mode {
*/
enum dfll_tune_range {
DFLL_TUNE_UNINITIALIZED = 0,
DFLL_TUNE_LOW = 1,
DFLL_TUNE_LOW,
DFLL_TUNE_WAIT_DFLL,
DFLL_TUNE_WAIT_PMIC,
DFLL_TUNE_HIGH,
};
@@ -285,6 +323,10 @@ struct tegra_dfll {
struct dfll_rate_req last_req;
unsigned long last_unrounded_rate;
struct hrtimer tune_timer;
ktime_t tune_delay;
ktime_t tune_ramp_delay;
/* Parameters from DT */
u32 droop_ctrl;
u32 sample_rate;
@@ -305,6 +347,11 @@ struct tegra_dfll {
int lut_size;
u8 lut_bottom, lut_min, lut_max, lut_safe;
/* tuning parameters */
u8 tune_high_out_start;
u8 tune_high_out_min;
u8 tune_out_last;
/* PWM interface */
enum tegra_dfll_pmu_if pmu_if;
unsigned long pwm_rate;
@@ -312,6 +359,9 @@ struct tegra_dfll {
struct pinctrl_state *pwm_enable_state;
struct pinctrl_state *pwm_disable_state;
u32 reg_init_uV;
/* spinlock protecting register accesses */
spinlock_t lock;
};
#define clk_hw_to_dfll(_hw) container_of(_hw, struct tegra_dfll, dfll_clk_hw)
@@ -324,6 +374,8 @@ static const char * const mode_name[] = {
[DFLL_CLOSED_LOOP] = "closed_loop",
};
static void dfll_load_i2c_lut(struct tegra_dfll *td);
/*
* Register accessors
*/
@@ -361,6 +413,36 @@ static inline void dfll_i2c_wmb(struct tegra_dfll *td)
dfll_i2c_readl(td, DFLL_I2C_CFG);
}
/**
* is_output_i2c_req_pending - is an I2C voltage-set command in progress?
* @pdev: DFLL instance
*
* Returns 1 if an I2C request is in progress, or 0 if not. The DFLL
* IP block requires two back-to-back reads of the I2C_REQ_PENDING
* field to return 0 before the software can be sure that no I2C
* request is currently pending. Also, a minimum time interval
* between DFLL_I2C_STS reads is required by the IP block.
*/
static int is_output_i2c_req_pending(struct tegra_dfll *td)
{
u32 sts;
if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
return 0;
sts = dfll_i2c_readl(td, DFLL_I2C_STS);
if (sts & DFLL_I2C_STS_I2C_REQ_PENDING)
return 1;
udelay(I2C_OUTPUT_ACTIVE_TEST_US);
sts = dfll_i2c_readl(td, DFLL_I2C_STS);
if (sts & DFLL_I2C_STS_I2C_REQ_PENDING)
return 1;
return 0;
}
/**
* dfll_is_running - is the DFLL currently generating a clock?
* @td: DFLL instance
@@ -452,13 +534,139 @@ static void dfll_tune_low(struct tegra_dfll *td)
td->tune_range = DFLL_TUNE_LOW;
dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune0_low, DFLL_TUNE0);
dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1, DFLL_TUNE1);
dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1_low, DFLL_TUNE1);
dfll_wmb(td);
if (td->soc->set_clock_trimmers_low)
td->soc->set_clock_trimmers_low();
}
/**
* dfll_tune_high - tune DFLL and CPU clock shaper for high voltages
* @td: DFLL instance
*
* Tune the DFLL oscillator parameters and the CPU clock shaper
* for the high-voltage range. The bottom end of the high-voltage
* range is represented by the index td->soc->tune_high_min_millivolts.
* Used in closed-loop mode. No return value.
*/
static void dfll_tune_high(struct tegra_dfll *td)
{
u32 tune0_high;
u32 tune1_high;
td->tune_range = DFLL_TUNE_HIGH;
tune0_high = td->soc->cvb->cpu_dfll_data.tune0_high;
if (!tune0_high)
tune0_high = td->soc->cvb->cpu_dfll_data.tune0_low;
dfll_writel(td, tune0_high, DFLL_TUNE0);
tune1_high = td->soc->cvb->cpu_dfll_data.tune1_high;
if (!tune1_high)
tune1_high = td->soc->cvb->cpu_dfll_data.tune1_low;
dfll_writel(td, tune1_high, DFLL_TUNE1);
dfll_wmb(td);
if (td->soc->set_clock_trimmers_high)
td->soc->set_clock_trimmers_high();
}
/**
* dfll_set_close_loop_config - prepare to switch to closed-loop mode
* @pdev: DFLL instance
* @req: requested output rate
*
* Prepare to switch the DFLL to closed-loop mode. This involves
* switching the DFLL's tuning voltage regime (if necessary), and
* rewriting the LUT to restrict the minimum and maximum voltages. No
* return value.
*/
static void dfll_set_close_loop_config(struct tegra_dfll *td,
struct dfll_rate_req *req)
{
bool sample_tune_out_last = false;
switch (td->tune_range) {
case DFLL_TUNE_LOW:
if (req->lut_index > td->tune_high_out_start) {
hrtimer_start(&td->tune_timer, td->tune_delay,
HRTIMER_MODE_REL);
}
sample_tune_out_last = true;
break;
case DFLL_TUNE_HIGH:
case DFLL_TUNE_WAIT_DFLL:
case DFLL_TUNE_WAIT_PMIC:
if (req->lut_index <= td->tune_high_out_start)
dfll_tune_low(td);
break;
default:
BUG();
}
td->lut_min = td->tune_range == DFLL_TUNE_LOW ?
0 : td->tune_high_out_min;
if (sample_tune_out_last && td->pmu_if == TEGRA_DFLL_PMU_I2C) {
u32 val;
val = dfll_i2c_readl(td, DFLL_I2C_STS);
td->tune_out_last = val >> DFLL_I2C_STS_I2C_LAST_SHIFT;
td->tune_out_last &= OUT_MASK;
}
}
/**
* dfll_tune_timer_cb - timer callback while tuning low to high
* @data: struct platform_device * of the DFLL instance
*
* Timer callback, used when switching from TUNE_LOW to TUNE_HIGH in
* closed-loop mode. Waits for DFLL I2C voltage command output to
* reach tune_high_out_min, then waits for the PMIC to react to the
* command. No return value.
*/
static enum hrtimer_restart dfll_tune_timer_cb(struct hrtimer *timer)
{
struct tegra_dfll *td;
u32 val, out_min, out_last;
bool use_ramp_delay;
td = container_of(timer, struct tegra_dfll, tune_timer);
if (td->tune_range == DFLL_TUNE_WAIT_DFLL) {
out_min = td->lut_min;
if (td->pmu_if == TEGRA_DFLL_PMU_I2C) {
val = dfll_i2c_readl(td, DFLL_I2C_STS);
out_last = val >> DFLL_I2C_STS_I2C_LAST_SHIFT;
out_last &= OUT_MASK;
} else {
out_last = out_min;
}
use_ramp_delay = !is_output_i2c_req_pending(td);
use_ramp_delay |= td->tune_out_last != out_last;
if (use_ramp_delay &&
(out_last >= td->tune_high_out_min) &&
(out_min >= td->tune_high_out_min)) {
td->tune_range = DFLL_TUNE_WAIT_PMIC;
hrtimer_start(&td->tune_timer, td->tune_ramp_delay,
HRTIMER_MODE_REL);
} else {
hrtimer_start(&td->tune_timer, td->tune_delay,
HRTIMER_MODE_REL);
}
} else if (td->tune_range == DFLL_TUNE_WAIT_PMIC) {
dfll_tune_high(td);
}
return HRTIMER_NORESTART;
}
/*
* Output clock scaler helpers
*/
@@ -554,7 +762,6 @@ static int dfll_i2c_set_output_enabled(struct tegra_dfll *td, bool enable)
return 0;
}
/*
* DFLL-to-PWM controller interface
*/
@@ -679,10 +886,10 @@ static void dfll_load_i2c_lut(struct tegra_dfll *td)
u32 val;
for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
if (i < td->lut_min)
lut_index = td->lut_min;
else if (i > td->lut_max)
lut_index = td->lut_max;
if (i < td->lut_bottom)
lut_index = td->lut_bottom;
else if (i > td->lut_size - 1)
lut_index = td->lut_size - 1;
else
lut_index = i;
@@ -813,6 +1020,28 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
return -ENOENT;
}
/**
* find_mv_out_cap - find the out_map index with voltage >= @mv
* @td: DFLL instance
* @mv: millivolts
*
* Find the lut index with voltage greater than or equal to @mv,
* and return it. If all of the voltages in out_map are less than
* @mv, then return the lut index * corresponding to the highest
* possible voltage, even though it's less than @mv.
*/
static u8 find_mv_out_cap(struct tegra_dfll *td, int mv)
{
u8 i;
for (i = td->lut_bottom; i < td->lut_size; i++) {
if (td->lut_uv[i] >= mv * 1000)
return i;
}
return i - 1; /* maximum possible output */
}
/**
* dfll_calculate_rate_request - calculate DFLL parameters for a given rate
* @td: DFLL instance
@@ -913,6 +1142,7 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
{
int ret;
struct dfll_rate_req req;
unsigned long flags;
if (td->mode == DFLL_UNINITIALIZED) {
dev_err(td->dev, "%s: Cannot set DFLL rate in %s mode\n",
@@ -927,8 +1157,12 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
td->last_unrounded_rate = rate;
td->last_req = req;
if (td->mode == DFLL_CLOSED_LOOP)
if (td->mode == DFLL_CLOSED_LOOP) {
spin_lock_irqsave(&td->lock, flags);
dfll_set_close_loop_config(td, &td->last_req);
dfll_set_frequency_request(td, &td->last_req);
spin_unlock_irqrestore(&td->lock, flags);
}
return 0;
}
@@ -946,13 +1180,18 @@ static int dfll_request_rate(struct tegra_dfll *td, unsigned long rate)
*/
static int dfll_disable(struct tegra_dfll *td)
{
unsigned long flags;
if (td->mode != DFLL_OPEN_LOOP) {
dev_err(td->dev, "cannot disable DFLL in %s mode\n",
mode_name[td->mode]);
return -EINVAL;
}
spin_lock_irqsave(&td->lock, flags);
dfll_set_mode(td, DFLL_DISABLED);
spin_unlock_irqrestore(&td->lock, flags);
pm_runtime_put_sync(td->dev);
return 0;
@@ -1016,6 +1255,7 @@ static void dfll_set_open_loop_config(struct tegra_dfll *td)
static int dfll_lock(struct tegra_dfll *td)
{
struct dfll_rate_req *req = &td->last_req;
unsigned long flags;
switch (td->mode) {
case DFLL_CLOSED_LOOP:
@@ -1033,9 +1273,12 @@ static int dfll_lock(struct tegra_dfll *td)
else
dfll_i2c_set_output_enabled(td, true);
spin_lock_irqsave(&td->lock, flags);
dfll_set_mode(td, DFLL_CLOSED_LOOP);
dfll_set_close_loop_config(td, req);
dfll_set_frequency_request(td, req);
dfll_set_force_output_enabled(td, false);
spin_unlock_irqrestore(&td->lock, flags);
return 0;
default:
@@ -1055,14 +1298,19 @@ static int dfll_lock(struct tegra_dfll *td)
*/
static int dfll_unlock(struct tegra_dfll *td)
{
unsigned long flags;
switch (td->mode) {
case DFLL_CLOSED_LOOP:
spin_lock_irqsave(&td->lock, flags);
dfll_set_open_loop_config(td);
dfll_set_mode(td, DFLL_OPEN_LOOP);
if (td->pmu_if == TEGRA_DFLL_PMU_PWM)
dfll_pwm_set_output_enabled(td, false);
else
dfll_i2c_set_output_enabled(td, false);
spin_unlock_irqrestore(&td->lock, flags);
return 0;
case DFLL_OPEN_LOOP:
@@ -1325,8 +1573,10 @@ static int attr_registers_show(struct seq_file *s, void *data)
{
u32 val, offs;
struct tegra_dfll *td = s->private;
unsigned long flags;
seq_puts(s, "CONTROL REGISTERS:\n");
spin_lock_irqsave(&td->lock, flags);
for (offs = 0; offs <= DFLL_MONITOR_DATA; offs += 4) {
if (offs == DFLL_OUTPUT_CFG)
val = dfll_i2c_readl(td, offs);
@@ -1355,6 +1605,8 @@ static int attr_registers_show(struct seq_file *s, void *data)
__raw_readl(td->lut_base + offs));
}
spin_unlock_irqrestore(&td->lock, flags);
return 0;
}
@@ -1445,6 +1697,53 @@ static int dfll_init_clks(struct tegra_dfll *td)
return 0;
}
/**
* dfll_init_tuning_thresholds - set up the high voltage range, if possible
* @td: DFLL instance
*
* Determine whether the DFLL tuning parameters need to be
* reprogrammed when the DFLL voltage reaches a certain minimum
* threshold. No return value.
*/
static void dfll_init_tuning_thresholds(struct tegra_dfll *td)
{
u8 out_min, out_start, max_voltage_index;
max_voltage_index = td->lut_size - 1;
/*
* Convert high tuning voltage threshold into output LUT
* index, and add necessary margin. If voltage threshold is
* outside operating range set it at maximum output level to
* effectively disable tuning parameters adjustment.
*/
td->tune_high_out_min = max_voltage_index;
td->tune_high_out_start = max_voltage_index;
if (td->soc->tune_high_min_millivolts < td->soc->min_millivolts)
return; /* no difference between low & high voltage range */
out_min = find_mv_out_cap(td, td->soc->tune_high_min_millivolts);
if ((out_min + 2) > max_voltage_index)
return;
if (td->soc->cvb->cpu_dfll_data.tune_high_margin_millivolts) {
unsigned int mv;
mv = td->soc->tune_high_min_millivolts +
td->soc->cvb->cpu_dfll_data.tune_high_margin_millivolts;
if (mv * 1000 > td->lut_uv[max_voltage_index])
return;
out_start = max((u8)(out_min + 1), find_mv_out_cap(td, mv));
} else {
out_start = out_min + DFLL_TUNE_HIGH_MARGIN_STEPS;
}
if (out_start > max_voltage_index)
return;
td->tune_high_out_min = out_min;
td->tune_high_out_start = out_start;
}
/**
* dfll_init - Prepare the DFLL IP block for use
* @td: DFLL instance
@@ -1501,6 +1800,8 @@ static int dfll_init(struct tegra_dfll *td)
dfll_init_out_if(td);
dfll_init_tuning_thresholds(td);
pm_runtime_put_sync(td->dev);
return 0;
@@ -1647,7 +1948,7 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
int i;
unsigned long rate, reg_volt;
u8 lut_bottom = MAX_DFLL_VOLTAGES;
int v_min = td->soc->cvb->min_millivolts * 1000;
int v_min = td->soc->min_millivolts * 1000;
for (i = 0; i < MAX_DFLL_VOLTAGES; i++) {
reg_volt = td->lut_uv[i];
@@ -1667,7 +1968,7 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
if ((lut_bottom == MAX_DFLL_VOLTAGES) ||
(lut_bottom + 1 >= td->lut_size)) {
dev_err(td->dev, "no voltage above DFLL minimum %d mV\n",
td->soc->cvb->min_millivolts);
td->soc->min_millivolts);
return -EINVAL;
}
td->lut_bottom = lut_bottom;
@@ -1676,7 +1977,7 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
rate = get_dvco_rate_below(td, td->lut_bottom);
if (!rate) {
dev_err(td->dev, "no opp below DFLL minimum voltage %d mV\n",
td->soc->cvb->min_millivolts);
td->soc->min_millivolts);
return -EINVAL;
}
td->dvco_rate_min = rate;
@@ -1699,17 +2000,20 @@ static int dfll_build_pwm_lut(struct tegra_dfll *td, unsigned long v_max)
*/
static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
{
unsigned long rate, v, v_opp;
unsigned long rate, v, v_opp, v_min_align;
int ret = -EINVAL;
int j, selector, lut;
v = td->soc->cvb->min_millivolts * 1000;
v = td->soc->min_millivolts * 1000;
lut = find_vdd_map_entry_exact(td, v);
if (lut < 0)
goto out;
td->lut[0] = lut;
td->lut_bottom = 0;
v_min_align = DIV_ROUND_UP(td->soc->min_millivolts * 1000,
td->soc->alignment.step_uv) * td->soc->alignment.step_uv;
for (j = 1, rate = 0; ; rate++) {
struct dev_pm_opp *opp;
@@ -1718,7 +2022,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
break;
v_opp = dev_pm_opp_get_voltage(opp);
if (v_opp <= td->soc->cvb->min_millivolts * 1000)
if (v_opp <= v_min_align)
td->dvco_rate_min = dev_pm_opp_get_freq(opp);
dev_pm_opp_put(opp);
@@ -1749,7 +2053,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td, unsigned long v_max)
if (!td->dvco_rate_min)
dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
td->soc->cvb->min_millivolts);
td->soc->min_millivolts);
else {
ret = 0;
for (j = 0; j < td->lut_size; j++)
@@ -2057,12 +2361,19 @@ int tegra_dfll_register(struct platform_device *pdev,
if (ret)
return ret;
spin_lock_init(&td->lock);
ret = dfll_register_clk(td);
if (ret) {
dev_err(&pdev->dev, "DFLL clk registration failed\n");
return ret;
}
/* Initialize tuning timer */
hrtimer_setup(&td->tune_timer, dfll_tune_timer_cb, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
td->tune_delay = ktime_set(0, DFLL_TUNE_HIGH_DELAY * 1000);
td->tune_ramp_delay = ktime_set(0, DFLL_OUTPUT_RAMP_DELAY * 1000);
dfll_debug_init(td);
return 0;
+2
View File
@@ -31,6 +31,8 @@ struct tegra_dfll_soc_data {
unsigned long max_freq;
const struct cvb_table *cvb;
struct rail_alignment alignment;
unsigned int min_millivolts;
unsigned int tune_high_min_millivolts;
void (*init_clock_trimmers)(void);
void (*set_clock_trimmers_high)(void);
+3
View File
@@ -878,6 +878,9 @@ static void __init periph_clk_init(void __iomem *clk_base,
if (!bank)
continue;
if (tegra_clks[data->clk_id].use_integer_div)
data->periph.divider.flags |= TEGRA_DIVIDER_INT;
data->periph.gate.regs = bank;
clk = tegra_clk_register_periph_data(clk_base, data);
*dt_clk = clk;
+185 -25
View File
@@ -64,7 +64,7 @@ static const unsigned long tegra114_cpu_max_freq_table[] = {
.cpu_dfll_data = { \
.tune0_low = 0x00b0039d, \
.tune0_high = 0x00b0009d, \
.tune1 = 0x0000001f, \
.tune1_low = 0x0000001f, \
.tune_high_min_millivolts = 1050, \
}
@@ -100,7 +100,7 @@ static const struct cvb_table tegra114_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0x00b0019d,
.tune0_high = 0x00b0019d,
.tune1 = 0x0000001f,
.tune1_low = 0x0000001f,
.tune_high_min_millivolts = 1000,
}
},
@@ -167,7 +167,7 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0x005020ff,
.tune0_high = 0x005040ff,
.tune1 = 0x00000060,
.tune1_low = 0x00000060,
}
},
};
@@ -335,7 +335,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -348,7 +348,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -361,7 +361,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
}
},
{
@@ -373,7 +373,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
}
},
{
@@ -385,7 +385,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
}
},
{
@@ -397,7 +397,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
}
},
{
@@ -409,7 +409,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -422,7 +422,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -434,7 +434,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
TEGRA210_CPU_CVB_TABLE,
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
}
},
{
@@ -445,7 +445,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
TEGRA210_CPU_CVB_TABLE,
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune1 = 0x25501d0,
.tune1_low = 0x25501d0,
}
},
{
@@ -457,7 +457,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -470,7 +470,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x25501d0,
.tune1_low = 0x25501d0,
.tune_high_min_millivolts = 864,
}
},
@@ -482,7 +482,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
TEGRA210_CPU_CVB_TABLE_XA,
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune1 = 0x17711BD,
.tune1_low = 0x17711BD,
}
},
{
@@ -494,7 +494,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -507,7 +507,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x25501d0,
.tune1_low = 0x25501d0,
.tune_high_min_millivolts = 864,
}
},
@@ -519,7 +519,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
TEGRA210_CPU_CVB_TABLE,
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
}
},
{
@@ -530,7 +530,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
TEGRA210_CPU_CVB_TABLE,
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune1 = 0x25501d0,
.tune1_low = 0x25501d0,
}
},
{
@@ -542,7 +542,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -555,7 +555,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x25501d0,
.tune1_low = 0x25501d0,
.tune_high_min_millivolts = 864,
}
},
@@ -568,7 +568,7 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x20091d9,
.tune1_low = 0x20091d9,
.tune_high_min_millivolts = 864,
}
},
@@ -581,12 +581,157 @@ static struct cvb_table tegra210_cpu_cvb_tables[] = {
.cpu_dfll_data = {
.tune0_low = 0xffead0ff,
.tune0_high = 0xffead0ff,
.tune1 = 0x25501d0,
.tune1_low = 0x25501d0,
.tune_high_min_millivolts = 864,
}
},
};
static const unsigned long tegra210b01_cpu_max_freq_table[] = {
[0] = 1963500000UL,
[1] = 1963500000UL,
[2] = 2091000000UL,
[3] = 2014500000UL,
};
#define CPUB01_CVB_TABLE_SLT_B1 \
.speedo_scale = 100, \
.voltage_scale = 1000, \
.entries = { \
{ 204000000UL, { 732856, -17335, 113 } }, \
{ 306000000UL, { 760024, -18195, 113 } }, \
{ 408000000UL, { 789258, -19055, 113 } }, \
{ 510000000UL, { 820558, -19915, 113 } }, \
{ 612000000UL, { 853926, -20775, 113 } }, \
{ 714000000UL, { 889361, -21625, 113 } }, \
{ 816000000UL, { 926862, -22485, 113 } }, \
{ 918000000UL, { 966431, -23345, 113 } }, \
{ 1020000000UL, { 1008066, -24205, 113 } }, \
{ 1122000000UL, { 1051768, -25065, 113 } }, \
{ 1224000000UL, { 1097537, -25925, 113 } }, \
{ 1326000000UL, { 1145373, -26785, 113 } }, \
{ 1428000000UL, { 1195276, -27645, 113 } }, \
{ 1581000000UL, { 1274006, -28935, 113 } }, \
{ 1683000000UL, { 1329076, -29795, 113 } }, \
{ 1785000000UL, { 1386213, -30655, 113 } }, \
{ 1887000000UL, { 1445416, -31515, 113 } }, \
{ 1963500000UL, { 1490873, -32155, 113 } }, \
{ 2065500000UL, { 1553683, -33015, 113 } }, \
{ 2091000000UL, { 1580725, -33235, 113 } }, \
{ 0UL, { 0, 0, 0 } }, \
}
#define CPUB01_CVB_TABLE_SLT_B0 \
.speedo_scale = 100, \
.voltage_scale = 1000, \
.entries = { \
{ 204000000UL, { 732856, -17335, 113 } }, \
{ 306000000UL, { 760024, -18195, 113 } }, \
{ 408000000UL, { 789258, -19055, 113 } }, \
{ 510000000UL, { 820558, -19915, 113 } }, \
{ 612000000UL, { 853926, -20775, 113 } }, \
{ 714000000UL, { 889361, -21625, 113 } }, \
{ 816000000UL, { 926862, -22485, 113 } }, \
{ 918000000UL, { 966431, -23345, 113 } }, \
{ 1020000000UL, { 1008066, -24205, 113 } }, \
{ 1122000000UL, { 1051768, -25065, 113 } }, \
{ 1224000000UL, { 1097537, -25925, 113 } }, \
{ 1326000000UL, { 1145373, -26785, 113 } }, \
{ 1428000000UL, { 1195276, -27645, 113 } }, \
{ 1581000000UL, { 1274006, -28935, 113 } }, \
{ 1683000000UL, { 1329076, -29795, 113 } }, \
{ 1785000000UL, { 1386213, -30655, 113 } }, \
{ 1887000000UL, { 1445416, -31515, 113 } }, \
{ 1963500000UL, { 1490873, -32155, 113 } }, \
{ 2065500000UL, { 1553683, -33015, 113 } }, \
{ 2091000000UL, { 1580725, -33235, 113 } }, \
{ 0UL, { 0, 0, 0 } }, \
}
#define CPUB01_CVB_TABLE \
.speedo_scale = 100, \
.voltage_scale = 1000, \
.entries = { \
{ 204000000UL, { 721589, -12695, 27 } }, \
{ 306000000UL, { 747134, -14195, 27 } }, \
{ 408000000UL, { 776324, -15705, 27 } }, \
{ 510000000UL, { 809160, -17205, 27 } }, \
{ 612000000UL, { 845641, -18715, 27 } }, \
{ 714000000UL, { 885768, -20215, 27 } }, \
{ 816000000UL, { 929540, -21725, 27 } }, \
{ 918000000UL, { 976958, -23225, 27 } }, \
{ 1020000000UL, { 1028021, -24725, 27 } }, \
{ 1122000000UL, { 1082730, -26235, 27 } }, \
{ 1224000000UL, { 1141084, -27735, 27 } }, \
{ 1326000000UL, { 1203084, -29245, 27 } }, \
{ 1428000000UL, { 1268729, -30745, 27 } }, \
{ 1581000000UL, { 1374032, -33005, 27 } }, \
{ 1683000000UL, { 1448791, -34505, 27 } }, \
{ 1785000000UL, { 1527196, -36015, 27 } }, \
{ 1887000000UL, { 1609246, -37515, 27 } }, \
{ 1963500000UL, { 1675751, -38635, 27 } }, \
{ 2014500000UL, { 1716501, -39395, 27 } }, \
{ 0UL, { 0, 0, 0 } }, \
}
static struct cvb_table tegra210b01_cpu_cvb_tables[] = {
{
.speedo_id = 3,
.process_id = -1,
.max_millivolts = 1120,
CPUB01_CVB_TABLE,
.vmin_coefficients = { 620000, 0, 0 },
.cpu_dfll_data = {
.tune0_low = 0x0000ffcf,
.tune1_low = 0x012207ff,
.tune1_high = 0x03FFF7FF,
.tune_high_min_millivolts = 850,
.tune_high_margin_millivolts = 38,
}
},
{
.speedo_id = 2,
.process_id = 1,
.max_millivolts = 1120,
CPUB01_CVB_TABLE_SLT_B1,
.vmin_coefficients = { 600000, 0, 0 },
.cpu_dfll_data = {
.tune0_low = 0x0000ffa0,
.tune0_high = 0x0000ffff,
.tune1_low = 0x021107ff,
.tune_high_min_millivolts = 850,
.tune_high_margin_millivolts = 38,
}
},
{
.speedo_id = 2,
.process_id = 0,
.max_millivolts = 1120,
CPUB01_CVB_TABLE_SLT_B0,
.vmin_coefficients = { 600000, 0, 0 },
.cpu_dfll_data = {
.tune0_low = 0x0000ff90,
.tune0_high = 0x0000ffff,
.tune1_low = 0x021107ff,
.tune_high_min_millivolts = 850,
.tune_high_margin_millivolts = 38,
}
},
{
.speedo_id = -1,
.process_id = -1,
.max_millivolts = 1120,
CPUB01_CVB_TABLE,
.vmin_coefficients = { 620000, 0, 0 },
.cpu_dfll_data = {
.tune0_low = 0x0000ffcf,
.tune1_low = 0x012207ff,
.tune_high_min_millivolts = 850,
.tune_high_margin_millivolts = 38,
}
},
};
static const struct dfll_fcpu_data tegra114_dfll_fcpu_data = {
.cpu_max_freq_table = tegra114_cpu_max_freq_table,
.cpu_max_freq_table_size = ARRAY_SIZE(tegra114_cpu_max_freq_table),
@@ -608,6 +753,13 @@ static const struct dfll_fcpu_data tegra210_dfll_fcpu_data = {
.cpu_cvb_tables_size = ARRAY_SIZE(tegra210_cpu_cvb_tables),
};
static const struct dfll_fcpu_data tegra210b01_dfll_fcpu_data = {
.cpu_max_freq_table = tegra210b01_cpu_max_freq_table,
.cpu_max_freq_table_size = ARRAY_SIZE(tegra210b01_cpu_max_freq_table),
.cpu_cvb_tables = tegra210b01_cpu_cvb_tables,
.cpu_cvb_tables_size = ARRAY_SIZE(tegra210b01_cpu_cvb_tables),
};
static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
{
.compatible = "nvidia,tegra114-dfll",
@@ -621,6 +773,10 @@ static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
.compatible = "nvidia,tegra210-dfll",
.data = &tegra210_dfll_fcpu_data
},
{
.compatible = "nvidia,tegra210b01-dfll",
.data = &tegra210b01_dfll_fcpu_data
},
{ },
};
@@ -698,7 +854,8 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
soc->cvb = tegra_cvb_add_opp_table(soc->dev, fcpu_data->cpu_cvb_tables,
fcpu_data->cpu_cvb_tables_size,
&align, process_id, speedo_id,
speedo_value, soc->max_freq);
speedo_value, soc->max_freq,
&soc->min_millivolts);
soc->alignment = align;
if (IS_ERR(soc->cvb)) {
@@ -707,6 +864,9 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
return PTR_ERR(soc->cvb);
}
soc->tune_high_min_millivolts =
soc->cvb->cpu_dfll_data.tune_high_min_millivolts;
err = tegra_dfll_register(pdev, soc);
if (err < 0) {
tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
+10 -8
View File
@@ -1812,7 +1812,7 @@ static struct div_nmp pllss_nmp = {
static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = {
{ 12000000, 600000000, 50, 1, 1, 0 },
{ 13000000, 600000000, 46, 1, 1, 0 }, /* actual: 598.0 MHz */
{ 38400000, 600000000, 62, 4, 1, 0 }, /* actual: 595.2 MHz */
{ 38400000, 998400000, 78, 3, 1, 0 },
{ 0, 0, 0, 0, 0, 0 },
};
@@ -1824,14 +1824,16 @@ static const struct clk_div_table pll_vco_post_div_table[] = {
{ .val = 4, .div = 5 },
{ .val = 5, .div = 6 },
{ .val = 6, .div = 8 },
{ .val = 7, .div = 10 },
{ .val = 8, .div = 12 },
{ .val = 9, .div = 16 },
{ .val = 10, .div = 12 },
{ .val = 7, .div = 9 },
{ .val = 8, .div = 10 },
{ .val = 9, .div = 12 },
{ .val = 10, .div = 15 },
{ .val = 11, .div = 16 },
{ .val = 12, .div = 20 },
{ .val = 13, .div = 24 },
{ .val = 14, .div = 32 },
{ .val = 12, .div = 18 },
{ .val = 13, .div = 20 },
{ .val = 14, .div = 24 },
{ .val = 15, .div = 30 },
{ .val = 16, .div = 32 },
{ .val = 0, .div = 0 },
};
File diff suppressed because it is too large. Load diff
+5 -5
View File
@@ -12,11 +12,11 @@
int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
u8 frac_width, u8 flags)
{
u64 divider_ux1 = parent_rate;
s64 divider_ux1 = parent_rate;
int mul;
if (!rate)
return 0;
return div_mask(width);
mul = 1 << frac_width;
@@ -31,13 +31,13 @@ int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
if (flags & TEGRA_DIVIDER_INT)
divider_ux1 *= mul;
if (divider_ux1 < mul)
return 0;
divider_ux1 -= mul;
if (divider_ux1 > div_mask(width))
return div_mask(width);
if (div1_5_not_allowed && (divider_ux1 > 0) && (divider_ux1 < mul))
divider_ux1 = (flags & TEGRA_DIVIDER_ROUND_UP) ? mul : 0;
return divider_ux1;
}
+17 -2
View File
@@ -26,6 +26,7 @@ static struct tegra_cpu_car_ops dummy_car_ops;
struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
int *periph_clk_enb_refcnt;
bool div1_5_not_allowed;
static int periph_banks;
static u32 *periph_state_ctx;
static struct clk **clks;
@@ -289,13 +290,27 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl,
}
}
if (tbl->rate)
if (clk_set_rate(clk, tbl->rate)) {
if (tbl->rate) {
bool can_set_rate = true;
if ((tbl->flags & TEGRA_TABLE_RATE_CHANGE_OVERCLOCK) &&
__clk_is_enabled(clk)) {
if (tbl->rate != clk_get_rate(clk)) {
pr_err("%s: Can't set rate %lu of %s\n",
__func__, tbl->rate,
__clk_get_name(clk));
WARN_ON(1);
}
can_set_rate = false;
}
if (can_set_rate && clk_set_rate(clk, tbl->rate)) {
pr_err("%s: Failed to set rate %lu of %s\n",
__func__, tbl->rate,
__clk_get_name(clk));
WARN_ON(1);
}
}
if (tbl->state)
if (clk_prepare_enable(clk)) {
+6
View File
@@ -87,6 +87,7 @@ struct tegra_clk_sync_source {
extern const struct clk_ops tegra_clk_sync_source_ops;
extern int *periph_clk_enb_refcnt;
extern bool div1_5_not_allowed;
struct clk *tegra_clk_register_sync_source(const char *name,
unsigned long max_rate);
@@ -800,14 +801,18 @@ struct clk *tegra_clk_register_sdmmc_mux_div(const char *name,
* @parent_id: parent clock id as mentioned in device tree bindings
* @rate: rate to set
* @state: enable/disable
* @flags: clock initialization flags
*/
struct tegra_clk_init_table {
unsigned int clk_id;
unsigned int parent_id;
unsigned long rate;
int state;
u32 flags;
};
#define TEGRA_TABLE_RATE_CHANGE_OVERCLOCK BIT(0)
/**
* struct clk_duplicate - duplicate clocks
* @clk_id: clock id as mentioned in device tree bindings
@@ -830,6 +835,7 @@ struct tegra_clk_duplicate {
struct tegra_clk {
int dt_id;
bool present;
bool use_integer_div;
};
struct tegra_devclk {
+13 -4
View File
@@ -54,13 +54,18 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up)
static int build_opp_table(struct device *dev, const struct cvb_table *table,
struct rail_alignment *align,
int speedo_value, unsigned long max_freq)
int speedo_value, unsigned long max_freq, int *vmin)
{
int i, ret, dfll_mv, min_mv, max_mv;
min_mv = round_voltage(table->min_millivolts, align, UP);
max_mv = round_voltage(table->max_millivolts, align, DOWN);
dfll_mv = get_cvb_voltage(
speedo_value, table->speedo_scale, &table->vmin_coefficients);
dfll_mv = round_cvb_voltage(dfll_mv, table->voltage_scale, align);
min_mv = max(min_mv, dfll_mv);
for (i = 0; i < MAX_DVFS_FREQS; i++) {
const struct cvb_table_freq_entry *entry = &table->entries[i];
@@ -78,6 +83,9 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
return ret;
}
if (vmin)
*vmin = min_mv;
return 0;
}
@@ -90,7 +98,8 @@ static int build_opp_table(struct device *dev, const struct cvb_table *table,
* @process_id: process id of the HW module
* @speedo_id: speedo id of the HW module
* @speedo_value: speedo value of the HW module
* @max_freq: highest safe clock rate
* @max_rate: highest safe clock rate
* @vmin: final minimum voltage returned to the caller
*
* On Tegra, a CVB table encodes the relationship between operating voltage
* and safe maximal frequency for a given module (e.g. GPU or CPU). This
@@ -103,7 +112,7 @@ const struct cvb_table *
tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
size_t count, struct rail_alignment *align,
int process_id, int speedo_id, int speedo_value,
unsigned long max_freq)
unsigned long max_freq, int *vmin)
{
size_t i;
int ret;
@@ -118,7 +127,7 @@ tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
continue;
ret = build_opp_table(dev, table, align, speedo_value,
max_freq);
max_freq, vmin);
return ret ? ERR_PTR(ret) : table;
}
+5 -2
View File
@@ -31,8 +31,10 @@ struct cvb_table_freq_entry {
struct cvb_cpu_dfll_data {
u32 tune0_low;
u32 tune0_high;
u32 tune1;
u32 tune1_low;
u32 tune1_high;
unsigned int tune_high_min_millivolts;
unsigned int tune_high_margin_millivolts;
};
struct cvb_table {
@@ -46,13 +48,14 @@ struct cvb_table {
int voltage_scale;
struct cvb_table_freq_entry entries[MAX_DVFS_FREQS];
struct cvb_cpu_dfll_data cpu_dfll_data;
struct cvb_coefficients vmin_coefficients;
};
const struct cvb_table *
tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
size_t count, struct rail_alignment *align,
int process_id, int speedo_id, int speedo_value,
unsigned long max_freq);
unsigned long max_freq, int *vmin);
void tegra_cvb_remove_opp_table(struct device *dev,
const struct cvb_table *table,
unsigned long max_freq);
+4 -4
View File
@@ -285,9 +285,9 @@ static void gpio_irq_unmask(struct irq_data *d)
gpiochip_enable_irq(&chips->chip, hwirq);
status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
status &= IRQ_TYPE_EDGE_BOTH;
if (!status)
status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
status = IRQ_TYPE_EDGE_BOTH;
if (status & IRQ_TYPE_EDGE_FALLING)
writel_relaxed(mask, &g->set_falling);
@@ -297,7 +297,7 @@ static void gpio_irq_unmask(struct irq_data *d)
static int gpio_irq_type(struct irq_data *d, unsigned trigger)
{
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
if (trigger & ~IRQ_TYPE_EDGE_BOTH)
return -EINVAL;
return 0;
@@ -400,7 +400,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
mask = __gpio_mask(i);
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
if (trigger & ~IRQ_TYPE_EDGE_BOTH)
return -EINVAL;
writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+1 -1
View File
@@ -160,7 +160,7 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
rg->hlevel | rg->llevel) & mask)
return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
type = IRQ_TYPE_EDGE_BOTH;
}
rg->rising &= ~mask;
+2 -2
View File
@@ -1263,14 +1263,14 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
gc = irq_get_domain_generic_chip(mvchip->domain, 0);
gc->private = mvchip;
ct = &gc->chip_types[0];
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
ct->type = IRQ_TYPE_LEVEL_MASK;
ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
ct->chip.name = mvchip->chip.label;
ct = &gc->chip_types[1];
ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
ct->type = IRQ_TYPE_EDGE_BOTH;
ct->chip.irq_ack = mvebu_gpio_irq_ack;
ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
+2 -2
View File
@@ -198,7 +198,7 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
gc->private = port;
ct = &gc->chip_types[0];
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
ct->type = IRQ_TYPE_LEVEL_MASK;
ct->chip.irq_ack = irq_gc_ack_set_bit;
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
@@ -210,7 +210,7 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR;
ct = &gc->chip_types[1];
ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
ct->type = IRQ_TYPE_EDGE_BOTH;
ct->chip.irq_ack = irq_gc_ack_set_bit;
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+4 -5
View File
@@ -432,8 +432,7 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
if (type & ~IRQ_TYPE_SENSE_MASK)
return -EINVAL;
if (!bank->regs->leveldetect0 &&
(type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
if (!bank->regs->leveldetect0 && (type & IRQ_TYPE_LEVEL_MASK))
return -EINVAL;
raw_spin_lock_irqsave(&bank->lock, flags);
@@ -450,9 +449,9 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
}
raw_spin_unlock_irqrestore(&bank->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
if (type & IRQ_TYPE_LEVEL_MASK)
irq_set_handler_locked(d, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
else if (type & IRQ_TYPE_EDGE_BOTH)
/*
* Edge IRQs are already cleared/acked in irq_handler and
* not need to be masked, as result handle_edge_irq()
@@ -702,7 +701,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
* after enabing the interrupt to clear the wakeup status.
*/
if (bank->regs->leveldetect0 && bank->regs->wkup_en &&
trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
trigger & IRQ_TYPE_LEVEL_MASK)
omap_clear_gpio_irqstatus(bank, offset);
if (trigger)
+2 -3
View File
@@ -132,8 +132,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
if (offset < 0 || offset >= PL061_GPIO_NR)
return -EINVAL;
if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) &&
(trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)))
if ((trigger & IRQ_TYPE_LEVEL_MASK) && (trigger & IRQ_TYPE_EDGE_BOTH))
{
dev_err(gc->parent,
"trying to configure line %d for both level and edge "
@@ -149,7 +148,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
gpiois = readb(pl061->base + GPIOIS);
gpioibe = readb(pl061->base + GPIOIBE);
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
if (trigger & IRQ_TYPE_LEVEL_MASK) {
bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
/* Disable edge detection */
+1 -1
View File
@@ -406,7 +406,7 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
if (__gpio_is_occupied(pchip, gpio))
return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
type = IRQ_TYPE_EDGE_BOTH;
}
gpdr = readl_relaxed(c->regbase + GPDR_OFFSET);
+2 -2
View File
@@ -169,9 +169,9 @@ static int rda_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
if (ret)
return ret;
if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
if (flow_type & IRQ_TYPE_LEVEL_MASK)
irq_set_handler_locked(data, handle_level_irq);
else if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
else if (flow_type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(data, handle_edge_irq);
return 0;
+1 -1
View File
@@ -134,7 +134,7 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
if (type == IRQ_TYPE_PROBE) {
if ((sgc->irqrising | sgc->irqfalling) & mask)
return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
type = IRQ_TYPE_EDGE_BOTH;
}
if (type & IRQ_TYPE_EDGE_RISING)
+1 -1
View File
@@ -158,7 +158,7 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
sd->gc->private = sd;
ct = sd->gc->chip_types;
ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
ct->type = IRQ_TYPE_LEVEL_MASK;
ct->regs.eoi = GPSTR;
ct->regs.mask = GPIO_INT;
ct->chip.irq_mask = irq_gc_mask_clr_bit;
+1 -1
View File
@@ -149,7 +149,7 @@ static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
int regoffset = offset / 8;
int mask = BIT(offset % 8);
if (type & IRQ_TYPE_LEVEL_LOW || type & IRQ_TYPE_LEVEL_HIGH)
if (type & IRQ_TYPE_LEVEL_MASK)
return -EINVAL;
/* STMPE801 and STMPE 1600 don't have RE and FE registers */
+4 -19
View File
@@ -172,18 +172,11 @@ static int tegra_gpio_direction_input(struct gpio_chip *chip,
unsigned int offset)
{
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
int ret;
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
tegra_gpio_enable(tgi, offset);
ret = pinctrl_gpio_direction_input(chip, offset);
if (ret < 0)
dev_err(tgi->dev,
"Failed to set pinctrl input direction of GPIO %d: %d",
chip->base + offset, ret);
return ret;
return 0;
}
static int tegra_gpio_direction_output(struct gpio_chip *chip,
@@ -191,19 +184,12 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip,
int value)
{
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
int ret;
tegra_gpio_set(chip, offset, value);
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
tegra_gpio_enable(tgi, offset);
ret = pinctrl_gpio_direction_output(chip, offset);
if (ret < 0)
dev_err(tgi->dev,
"Failed to set pinctrl output direction of GPIO %d: %d",
chip->base + offset, ret);
return ret;
return 0;
}
static int tegra_gpio_get_direction(struct gpio_chip *chip,
@@ -356,9 +342,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return ret;
}
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
if (type & IRQ_TYPE_LEVEL_MASK)
irq_set_handler_locked(d, handle_level_irq);
else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
else if (type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(d, handle_edge_irq);
if (d->parent_data)
@@ -722,7 +708,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)
tgi->gc.direction_output = tegra_gpio_direction_output;
tgi->gc.set = tegra_gpio_set;
tgi->gc.get_direction = tegra_gpio_get_direction;
tgi->gc.base = 0;
tgi->gc.ngpio = tgi->bank_count * 32;
tgi->gc.parent = &pdev->dev;
+1 -1
View File
@@ -149,7 +149,7 @@ static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
if (ver > 2)
bflr = ioread32(tgpio->membase + TGPIO_BFLR);
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
if (trigger & IRQ_TYPE_LEVEL_MASK) {
bflr &= ~(1 << offset);
flr &= ~(1 << offset);
if (trigger & IRQ_TYPE_LEVEL_HIGH)
-1
View File
@@ -4,7 +4,6 @@ config DRM_NOUVEAU
depends on DRM && PCI
select IOMMU_API
select FW_LOADER
select FW_CACHE if PM_SLEEP
select DRM_CLIENT_SELECTION
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDMI_HELPER
@@ -134,5 +134,6 @@ int gf100_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gk104_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
int gk20a_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
int gm20b_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
int gm20b_b01_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
int gp10b_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
#endif
@@ -42,4 +42,5 @@ int gf117_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gk104_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
int gk20a_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
int gm20b_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
int gm20b_b01_volt_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_volt **);
#endif
+1 -1
View File
@@ -73,7 +73,7 @@ nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags)
enum ttm_caching caching;
if (nvbo->force_coherent)
caching = ttm_uncached;
caching = ttm_write_combined;
else if (drm->agp.bridge)
caching = ttm_write_combined;
else
@@ -2072,6 +2072,31 @@ nv12b_chipset = {
.sw = { 0x00000001, gf100_sw_new },
};
static const struct nvkm_device_chip
nv12e_chipset = {
.name = "GM20B",
.acr = { 0x00000001, gm20b_acr_new },
.bar = { 0x00000001, gm20b_bar_new },
.bus = { 0x00000001, gf100_bus_new },
.clk = { 0x00000001, gm20b_b01_clk_new },
.fb = { 0x00000001, gm20b_fb_new },
.fuse = { 0x00000001, gm107_fuse_new },
.imem = { 0x00000001, gk20a_instmem_new },
.ltc = { 0x00000001, gm200_ltc_new },
.mc = { 0x00000001, gk20a_mc_new },
.mmu = { 0x00000001, gm20b_mmu_new },
.pmu = { 0x00000001, gm20b_pmu_new },
.privring = { 0x00000001, gk20a_privring_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, gk104_top_new },
.volt = { 0x00000001, gm20b_b01_volt_new },
.ce = { 0x00000004, gm200_ce_new },
.dma = { 0x00000001, gf119_dma_new },
.fifo = { 0x00000001, gm200_fifo_new },
.gr = { 0x00000001, gm20b_gr_new },
.sw = { 0x00000001, gf100_sw_new },
};
static const struct nvkm_device_chip
nv130_chipset = {
.name = "GP100",
@@ -3328,6 +3353,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x124: device->chip = &nv124_chipset; break;
case 0x126: device->chip = &nv126_chipset; break;
case 0x12b: device->chip = &nv12b_chipset; break;
case 0x12e: device->chip = &nv12e_chipset; break;
case 0x130: device->chip = &nv130_chipset; break;
case 0x132: device->chip = &nv132_chipset; break;
case 0x134: device->chip = &nv134_chipset; break;
@@ -717,6 +717,112 @@ gm20b_pstates[] = {
},
};
static struct nvkm_pstate
gm20b_b01_pstates[] = {
{
.base = {
.domain[nv_clk_src_gpc] = 76800,
.voltage = 0,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 153600,
.voltage = 1,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 230400,
.voltage = 2,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 307200,
.voltage = 3,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 384000,
.voltage = 4,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 460800,
.voltage = 5,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 537600,
.voltage = 6,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 614400,
.voltage = 7,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 691200,
.voltage = 8,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 768000,
.voltage = 9,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 844800,
.voltage = 10,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 921600,
.voltage = 11,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 998400,
.voltage = 12,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 1075200,
.voltage = 13,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 1152000,
.voltage = 14,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 1228800,
.voltage = 15,
},
},
{
.base = {
.domain[nv_clk_src_gpc] = 1267200,
.voltage = 16,
},
},
};
static void
gm20b_clk_fini(struct nvkm_clk *base)
{
@@ -912,6 +1018,23 @@ gm20b_clk = {
},
};
static const struct nvkm_clk_func
gm20b_b01_clk = {
.init = gm20b_clk_init,
.fini = gk20a_clk_fini,
.read = gk20a_clk_read,
.calc = gk20a_clk_calc,
.prog = gk20a_clk_prog,
.tidy = gk20a_clk_tidy,
.pstates = gm20b_b01_pstates,
.nr_pstates = ARRAY_SIZE(gm20b_b01_pstates),
.domains = {
{ nv_clk_src_crystal, 0xff },
{ nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
{ nv_clk_src_max },
},
};
static int
gm20b_clk_new_speedo0(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_clk **pclk)
@@ -1074,3 +1197,63 @@ gm20b_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
return 0;
}
int
gm20b_b01_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_clk **pclk)
{
struct nvkm_device_tegra *tdev = device->func->tegra(device);
struct gm20b_clk *clk;
struct nvkm_subdev *subdev;
struct gk20a_clk_pllg_params *clk_params;
int ret;
/* Speedo 0 GPUs cannot use noise-aware PLL */
if (tdev->gpu_speedo_id == 0)
return -EINVAL;
/* Speedo >= 1, use NAPLL */
clk = kzalloc(sizeof(*clk) + sizeof(*clk_params), GFP_KERNEL);
if (!clk)
return -ENOMEM;
*pclk = &clk->base.base;
subdev = &clk->base.base.subdev;
/* duplicate the clock parameters since we will patch them below */
clk_params = (void *) (clk + 1);
*clk_params = gm20b_pllg_params;
ret = gk20a_clk_ctor(device, type, inst, &gm20b_b01_clk, clk_params, &clk->base);
if (ret)
return ret;
/*
* NAPLL can only work with max_u, clamp the m range so
* gk20a_pllg_calc_mnp always uses it
*/
clk_params->max_m = clk_params->min_m = DIV_ROUND_UP(clk_params->max_u,
(clk->base.parent_rate / KHZ));
if (clk_params->max_m == 0) {
nvkm_error(subdev, "cannot use NAPLL, and legacy clock unavailable...\n");
kfree(clk);
return -EINVAL;
}
clk->base.pl_to_div = pl_to_div;
clk->base.div_to_pl = div_to_pl;
clk->dvfs_params = &gm20b_dvfs_params;
ret = gm20b_clk_init_fused_params(clk);
/*
* we will calibrate during init - should never happen on
* prod parts
*/
if (ret)
nvkm_warn(subdev, "no fused calibration parameters\n");
ret = gm20b_clk_init_safe_fmax(clk);
if (ret)
return ret;
return 0;
}
@@ -91,3 +91,54 @@ gm20b_volt_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
return gk20a_volt_ctor(device, type, inst, gm20b_cvb_coef,
ARRAY_SIZE(gm20b_cvb_coef), vmin, volt);
}
static const struct cvb_coef gm20b_b01_na_cvb_coef[] = {
/* KHz, c0, c1, c2, c3, c4, c5 */
/* 76800 */ { 610000, 0, 0, 0, 0, 0 },
/* 153600 */ { 610000, 0, 0, 0, 0, 0 },
/* 230400 */ { 610000, 0, 0, 0, 0, 0 },
/* 307200 */ { 610000, 0, 0, 0, 0, 0 },
/* 384000 */ { 610000, 0, 0, 0, 0, 0 },
/* 460800 */ { 610000, 0, 0, 0, 0, 0 },
/* 537600 */ { 801688, -10900, -163, 298, -10599, 162 },
/* 614400 */ { 824214, -5743, -452, 238, -6325, 81 },
/* 691200 */ { 848830, -3903, -552, 119, -4030, -2 },
/* 768000 */ { 891575, -4409, -584, 0, -2849, 39 },
/* 844800 */ { 940071, -5367, -602, -60, -63, -93 },
/* 921600 */ { 986765, -6637, -614, -179, 1905, -13 },
/* 998400 */ { 1098475, -13529, -497, -179, 3626, 9 },
/* 1075200 */ { 1163644, -12688, -648, 0, 1077, 40 },
/* 1152000 */ { 1204812, -9908, -830, 0, 1469, 110 },
/* 1228800 */ { 1277303, -11675, -859, 0, 3722, 313 },
/* 1267200 */ { 1335531, -12567, -867, 0, 3681, 559 },
};
int
gm20b_b01_volt_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_volt **pvolt)
{
struct nvkm_device_tegra *tdev = device->func->tegra(device);
struct gk20a_volt *volt;
u32 vmin;
if (tdev->gpu_speedo_id >= ARRAY_SIZE(speedo_to_vmin)) {
nvdev_error(device, "unsupported speedo %d\n",
tdev->gpu_speedo_id);
return -EINVAL;
}
volt = kzalloc(sizeof(*volt), GFP_KERNEL);
if (!volt)
return -ENOMEM;
*pvolt = &volt->base;
vmin = speedo_to_vmin[tdev->gpu_speedo_id];
switch (tdev->gpu_speedo_id) {
case 1:
return gk20a_volt_ctor(device, type, inst, gm20b_b01_na_cvb_coef,
ARRAY_SIZE(gm20b_b01_na_cvb_coef), vmin, volt);
default:
return -EINVAL;
}
}
+9
View File
@@ -354,6 +354,15 @@ config DRM_PANEL_JDI_LPM102A188A
The panel has a 2560×1800 resolution. It provides a MIPI DSI interface
to the host.
config DRM_PANEL_NX_DSI
tristate "Nintendo Switch 720x1280 DSI panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for the DSI panels
used in the Nintendo Switch.
config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
+1
View File
@@ -62,6 +62,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37700F) += panel-novatek-nt37700f.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT37801) += panel-novatek-nt37801.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o
obj-$(CONFIG_DRM_PANEL_NX_DSI) += panel-nx-dsi.o
obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o
obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o
obj-$(CONFIG_DRM_PANEL_ORISETECH_OTA5601A) += panel-orisetech-ota5601a.o
+772
View File
@@ -0,0 +1,772 @@
/*
* Copyright (C) 2018 SwtcR <swtcr0@gmail.com>
* Copyright (C) 2023-2024 Azkali <a.ffcc7@gmail.com>
*
* Based on Sharp ls043t1le01 panel driver by Werner Johansson <werner.johansson@sonymobile.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/backlight.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_crtc.h>
#include <drm/drm_panel.h>
#include <drm/drm_modes.h>
/*! MIPI DCS Panel Private CMDs. */
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE ((u8)0xA0)
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET ((u8)0xB0)
#define MIPI_DCS_PRIV_SM_SET_ELVSS ((u8)0xB1) /* OLED backlight tuning. Byte7: PWM transition time in frames. */
#define MIPI_DCS_PRIV_SET_POWER_CONTROL ((u8)0xB1)
#define MIPI_DCS_PRIV_SET_EXTC ((u8)0xB9) /* Enable extended commands. */
#define MIPI_DCS_PRIV_UNK_BD ((u8)0xBD)
#define MIPI_DCS_PRIV_UNK_D5 ((u8)0xD5)
#define MIPI_DCS_PRIV_UNK_D6 ((u8)0xD6)
#define MIPI_DCS_PRIV_UNK_D8 ((u8)0xD8)
#define MIPI_DCS_PRIV_UNK_D9 ((u8)0xD9)
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK ((u8)0xE2)
/* BL Control */
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT ((u8)BIT(2))
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL ((u8)BIT(2))
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL ((u8)BIT(3))
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL ((u8)BIT(5))
/* OLED Panels color mode */
#define DCS_SM_COLOR_MODE_SATURATED ((u8)0x00) /* Disabled. Similar to vivid but over-saturated. Wide gamut? */
#define DCS_SM_COLOR_MODE_WASHED ((u8)0x45)
#define DCS_SM_COLOR_MODE_BASIC ((u8)0x03)
#define DCS_SM_COLOR_MODE_POR_RESET ((u8)0x20) /* Reset value on power on. */
#define DCS_SM_COLOR_MODE_NATURAL ((u8)0x23) /* Not actually natural.. */
#define DCS_SM_COLOR_MODE_VIVID ((u8)0x65)
#define DCS_SM_COLOR_MODE_NIGHT0 ((u8)0x43) /* Based on washed out. */
#define DCS_SM_COLOR_MODE_NIGHT1 ((u8)0x15) /* Based on basic. */
#define DCS_SM_COLOR_MODE_NIGHT2 ((u8)0x35) /* Based on natural. */
#define DCS_SM_COLOR_MODE_NIGHT3 ((u8)0x75) /* Based on vivid. */
#define DCS_SM_COLOR_MODE_ENABLE ((u8)BIT(0))
enum
{
PANEL_JDI_XXX062M = 0x10,
PANEL_JDI_LAM062M109A = 0x0910,
PANEL_JDI_LPM062M326A = 0x2610,
PANEL_INL_P062CCA_AZ1 = 0x0F20,
PANEL_AUO_A062TAN01 = 0x0F30,
PANEL_INL_2J055IA_27A = 0x1020,
PANEL_AUO_A055TAN01 = 0x1030,
PANEL_SHP_LQ055T1SW10 = 0x1040,
PANEL_SAM_AMS699VC01 = 0x2050,
PANEL_RR_SUPER5_OLED_V1 = 0x10E0,
PANEL_RR_SUPER5_OLED_HD_V1 = 0x10E1,
PANEL_RR_SUPER7_IPS_V1 = 0x0FE0,
PANEL_RR_SUPER7_IPS_HD_V1 = 0x0FE1,
PANEL_RR_SUPER7_OLED_7_V1 = 0x20E0,
PANEL_RR_SUPER7_OLED_HD_7_V1 = 0x20E1,
// Found on 6/2" clones. Unknown markings. Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F].
PANEL_OEM_CLONE_6_2 = 0x0F83,
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
PANEL_OEM_CLONE_5_5 = 0x00B3,
// Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
PANEL_OEM_CLONE = 0x0000
};
struct init_cmd {
u8 cmd;
int length;
u8 data[64];
};
struct nx_panel {
struct drm_panel base;
struct mipi_dsi_device *dsi;
struct backlight_device *backlight;
struct regulator *supply1;
struct regulator *supply2;
struct gpio_desc *reset_gpio;
bool prepared;
bool enabled;
const struct drm_display_mode *mode;
struct init_cmd *init_cmds;
struct init_cmd *suspend_cmds;
u16 display_id;
};
struct init_cmd init_cmds_default[] = {
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
120,
},
{ MIPI_DCS_SET_DISPLAY_ON, 2, { 0x00, 0x0 } },
{
0xFF,
20,
},
};
struct init_cmd init_cmds_PANEL_JDI_XXX062M[] = {
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x00, 0x0 } },
{ MIPI_DCS_PRIV_UNK_D8, 24, { 0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xEB, 0xAA, 0xAA } },
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x01, 0x0 } },
{ MIPI_DCS_PRIV_UNK_D8,
38,
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } },
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x02, 0x0 } },
{ MIPI_DCS_PRIV_UNK_D8,
14,
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF } },
{ MIPI_DCS_PRIV_UNK_BD, 2, { 0x00, 0x00 } },
{ MIPI_DCS_PRIV_UNK_D9, 2, { 0x06, 0x0 } },
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0x00, 0x00, 0x00 } },
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
180,
},
{ MIPI_DCS_SET_DISPLAY_ON, 2, { 0x00, 0x0 } },
{
0xFF,
20,
},
{ MIPI_DCS_NOP, -1, { 0x00 } },
};
struct init_cmd suspend_cmds_PANEL_JDI_XXX062M[] = {
{ MIPI_DCS_SET_DISPLAY_OFF, 2, { 0x00, 0x0 } },
{
0xFF,
50,
},
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
{ MIPI_DCS_PRIV_UNK_D5,
32,
{ 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 } },
{ MIPI_DCS_PRIV_SET_POWER_CONTROL,
10,
{ 0x41, 0x0F, 0x4F, 0x33, 0xA4, 0x79, 0xF1, 0x81, 0x2D, 0x00 } },
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0x00, 0x00, 0x00 } },
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
50,
},
{ MIPI_DCS_NOP, -1, { 0x00 } },
};
struct init_cmd init_cmds_PANEL_SAM_AMS699VC01[] = {
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
180,
},
// Set color mode to basic (natural). Stock is Saturated (0x00). (Reset value is 0x20).
{ MIPI_DCS_PRIV_SM_SET_COLOR_MODE, 2, { 0x23, 0x0 } },
// Enable backlight and smooth PWM.
{ MIPI_DCS_WRITE_CONTROL_DISPLAY, 2, { 0x28, 0x0 } },
// Unlock Level 2 registers.
{ 0x05, 9, { 0x0, 0x0, 0xE2, 0x5A, 0x5A, 0x5A, 0x5A, 0x0, 0x0 } },
// Set registers offset and set PWM transition to 6 frames (100ms).
{ MIPI_DCS_PRIV_SM_SET_REG_OFFSET, 2, { 0x07, 0x0 } },
{ MIPI_DCS_PRIV_SM_SET_ELVSS, 2, { 0x06, 0x0 } },
// Relock Level 2 registers.
{ 0x05, 9, { 0x0, 0x0, 0xE2, 0x5A, 0x5A, 0xA5, 0xA5, 0x0, 0x0 } },
// MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%.
{ 0x03, 7, { 0x00, 0x00, 0x51, 0x0, 0x0, 0x0, 0x0 } },
{
0xFF,
5,
},
};
struct init_cmd init_cmds_PANEL_AUO_A062TAN01[] = {
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
180,
},
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
{
0xFF,
5,
},
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 6, { 0x48, 0x11, 0x71, 0x09, 0x32, 0x14 } },
};
struct init_cmd suspend_cmds_PANEL_AUO_A062TAN01[] = {
{
0xFF,
100,
},
{
0xFF,
5,
},
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
50,
},
};
struct init_cmd suspend_cmds_PANEL_AUO_A055TAN01[] = {
{
0xFF,
100,
},
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
{
0xFF,
5,
},
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x11, 0x71, 0x09, 0x32, 0x14, 0x71, 0x31, 0x4D, 0x11 } },
{
0xFF,
5,
},
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
50,
},
};
struct init_cmd init_cmds_PANEL_INL_P062CCA_AZ1[] = {
{ MIPI_DCS_EXIT_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
180,
},
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
{
0xFF,
5,
},
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 6, { 0x48, 0x15, 0x75, 0x09, 0x32, 0x14 } },
};
struct init_cmd suspend_cmds_PANEL_INL_2J055IA_27A[] = {
{
0xFF,
100,
},
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
{
0xFF,
5,
},
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x15, 0x75, 0x09, 0x32, 0x14, 0x71, 0x31, 0x4D, 0x11 } },
{
0xFF,
5,
},
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
50,
},
};
struct init_cmd suspend_cmds_PANEL_SHP_LQ055T1SW10[] = {
{
0xFF,
100,
},
{ MIPI_DCS_PRIV_SET_EXTC, 3, { 0xFF, 0x83, 0x94 } },
{
0xFF,
5,
},
{ MIPI_DCS_PRIV_SET_POWER_CONTROL, 10, { 0x48, 0x13, 0x73, 0x09, 0x32, 0x24, 0x71, 0x31, 0x4C, 0x00 } },
{
0xFF,
5,
},
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
50,
},
};
struct init_cmd suspend_cmds_PANEL_SAM_AMS699VC01[] = {
{
0xFF,
100,
},
{ MIPI_DCS_ENTER_SLEEP_MODE, 2, { 0x00, 0x0 } },
{
0xFF,
120,
},
};
static inline struct nx_panel *to_nx_panel(struct drm_panel *panel)
{
return container_of(panel, struct nx_panel, base);
}
static void nx_panel_detect(struct nx_panel *nx)
{
int ret;
nx->init_cmds = NULL;
nx->suspend_cmds = NULL;
memset(&(nx->display_id), 0, sizeof(nx->display_id));
ret = mipi_dsi_dcs_read(nx->dsi, MIPI_DCS_GET_DISPLAY_ID,
&(nx->display_id), sizeof(nx->display_id));
if (ret < 0) {
dev_err(&nx->dsi->dev, "failed to read panel ID: %d\n", ret);
} else {
dev_info(&nx->dsi->dev, "display ID[%d]: %04x\n",
ret, nx->display_id);
}
dev_info(&nx->dsi->dev,
"setting init sequence for ID %04x\n", nx->display_id);
switch (nx->display_id) {
case PANEL_JDI_XXX062M:
nx->init_cmds = init_cmds_PANEL_JDI_XXX062M;
break;
case PANEL_SAM_AMS699VC01:
nx->init_cmds = init_cmds_PANEL_SAM_AMS699VC01;
break;
case PANEL_INL_P062CCA_AZ1:
nx->init_cmds = init_cmds_PANEL_INL_P062CCA_AZ1;
break;
case PANEL_AUO_A062TAN01:
nx->init_cmds = init_cmds_PANEL_AUO_A062TAN01;
break;
case PANEL_INL_2J055IA_27A:
case PANEL_AUO_A055TAN01:
case PANEL_SHP_LQ055T1SW10:
default:
dev_info(&nx->dsi->dev, "using default init sequence\n");
nx->init_cmds = init_cmds_default;
break;
}
dev_info(&nx->dsi->dev,
"setting suspend sequence for ID %04x\n", nx->display_id);
switch (nx->display_id) {
case PANEL_JDI_XXX062M:
nx->suspend_cmds = suspend_cmds_PANEL_JDI_XXX062M;
break;
case PANEL_AUO_A062TAN01:
nx->suspend_cmds = suspend_cmds_PANEL_AUO_A062TAN01;
break;
case PANEL_INL_2J055IA_27A:
nx->suspend_cmds = suspend_cmds_PANEL_INL_2J055IA_27A;
break;
case PANEL_AUO_A055TAN01:
nx->suspend_cmds = suspend_cmds_PANEL_AUO_A055TAN01;
break;
case PANEL_SHP_LQ055T1SW10:
nx->suspend_cmds = suspend_cmds_PANEL_SHP_LQ055T1SW10;
break;
case PANEL_SAM_AMS699VC01:
nx->suspend_cmds = suspend_cmds_PANEL_SAM_AMS699VC01;
break;
case PANEL_INL_P062CCA_AZ1:
default:
dev_info(&nx->dsi->dev, "using default suspend sequence\n");
break;
}
msleep(20);
}
static int nx_mipi_dsi_dcs_cmds(struct init_cmd *cmds, struct nx_panel *nx)
{
int ret = 0;
while (cmds && cmds->length != -1) {
if (cmds->cmd == 0xFF)
msleep(cmds->length);
else {
ret = mipi_dsi_dcs_write(nx->dsi, cmds->cmd,
cmds->data, cmds->length);
if (ret < 0) {
dev_err(&nx->dsi->dev,
"failed to write dsi_cmd: %d error: %d\n",
cmds->cmd, ret);
return ret;
}
}
cmds++;
}
return ret;
}
static int nx_panel_init(struct nx_panel *nx)
{
struct mipi_dsi_device *dsi = nx->dsi;
struct device *dev = &nx->dsi->dev;
int ret;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
ret = mipi_dsi_set_maximum_return_packet_size(dsi, 3);
if (ret < 0) {
dev_err(dev, "failed to set maximum return packet size: %d\n",
ret);
return ret;
}
nx_panel_detect(nx);
ret = nx_mipi_dsi_dcs_cmds(nx->init_cmds, nx);
if (ret < 0)
return ret;
ret = mipi_dsi_dcs_set_column_address(dsi, 0, nx->mode->hdisplay - 1);
if (ret < 0) {
dev_err(dev, "failed to set page address: %d\n", ret);
return ret;
}
ret = mipi_dsi_dcs_set_page_address(dsi, 0, nx->mode->vdisplay - 1);
if (ret < 0) {
dev_err(dev, "failed to set column address: %d\n", ret);
return ret;
}
ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
if (ret < 0) {
dev_err(dev, "failed to set vblank tear on: %d\n", ret);
return ret;
}
ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT);
if (ret < 0) {
dev_err(dev, "failed to set pixel format: %d\n", ret);
return ret;
}
return 0;
}
static int nx_panel_enable(struct drm_panel *panel)
{
struct nx_panel *nx = to_nx_panel(panel);
if (nx->enabled)
return 0;
backlight_enable(nx->backlight);
nx->enabled = true;
return 0;
}
static int nx_panel_disable(struct drm_panel *panel)
{
struct nx_panel *nx = to_nx_panel(panel);
if (!nx->enabled)
return 0;
backlight_disable(nx->backlight);
nx->enabled = false;
return 0;
}
static int nx_panel_unprepare(struct drm_panel *panel)
{
struct nx_panel *nx = to_nx_panel(panel);
int ret;
if (!nx->prepared)
return 0;
nx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = nx_mipi_dsi_dcs_cmds(nx->suspend_cmds, nx);
if (ret < 0)
dev_err(&nx->dsi->dev, "failed to write suspend cmds: %d\n",
ret);
if (nx->reset_gpio)
gpiod_set_value(nx->reset_gpio, 0);
msleep(10);
regulator_disable(nx->supply2);
msleep(10);
regulator_disable(nx->supply1);
nx->prepared = false;
return 0;
}
static int nx_panel_prepare(struct drm_panel *panel)
{
struct nx_panel *nx = to_nx_panel(panel);
struct device *dev = &nx->dsi->dev;
int ret;
if (nx->prepared)
return 0;
ret = regulator_enable(nx->supply1);
if (ret < 0)
return ret;
msleep(10);
ret = regulator_enable(nx->supply2);
if (ret < 0)
goto poweroff;
msleep(10);
if (nx->reset_gpio) {
gpiod_set_value(nx->reset_gpio, 0);
msleep(10);
gpiod_set_value(nx->reset_gpio, 1);
msleep(60);
}
nx->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
ret = nx_panel_init(nx);
if (ret < 0) {
dev_err(dev, "failed to init panel: %d\n", ret);
goto reset;
}
nx->prepared = true;
return 0;
reset:
if (nx->reset_gpio)
gpiod_set_value(nx->reset_gpio, 0);
regulator_disable(nx->supply2);
poweroff:
regulator_disable(nx->supply1);
return ret;
}
static const struct drm_display_mode default_mode = {
.clock = 78000,
.hdisplay = 720,
.hsync_start = 720 + 136,
.hsync_end = 720 + 136 + 72,
.htotal = 720 + 136 + 72 + 72,
.vdisplay = 1280,
.vsync_start = 1280 + 10,
.vsync_end = 1280 + 10 + 2,
.vtotal = 1280 + 10 + 1 + 9,
.flags = 0,
};
static int nx_panel_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct drm_display_mode *mode;
struct nx_panel *nx = to_nx_panel(panel);
struct device *dev = &nx->dsi->dev;
mode = drm_mode_duplicate(connector->dev, &default_mode);
if (!mode) {
dev_err(dev, "failed to add mode %ux%ux@%u\n",
default_mode.hdisplay, default_mode.vdisplay,
drm_mode_vrefresh(&default_mode));
return -ENOMEM;
}
drm_mode_set_name(mode);
drm_mode_probed_add(connector, mode);
connector->display_info.width_mm = 77;
connector->display_info.height_mm = 137;
connector->display_info.bpc = 8;
return 1;
}
static const struct drm_panel_funcs nx_panel_funcs = {
.prepare = nx_panel_prepare,
.unprepare = nx_panel_unprepare,
.enable = nx_panel_enable,
.disable = nx_panel_disable,
.get_modes = nx_panel_get_modes,
};
static int nx_panel_add(struct nx_panel *nx)
{
struct device *dev = &nx->dsi->dev;
struct device_node *np;
nx->mode = &default_mode;
nx->supply1 = devm_regulator_get(dev, "vdd1");
if (IS_ERR(nx->supply1))
return PTR_ERR(nx->supply1);
nx->supply2 = devm_regulator_get(dev, "vdd2");
if (IS_ERR(nx->supply2))
return PTR_ERR(nx->supply2);
nx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(nx->reset_gpio)) {
dev_err(dev, "cannot get reset-gpios %ld\n",
PTR_ERR(nx->reset_gpio));
nx->reset_gpio = NULL;
} else {
gpiod_set_value(nx->reset_gpio, 0);
}
usleep_range(2000, 4000);
np = of_parse_phandle(dev->of_node, "backlight", 0);
if (np) {
nx->backlight = of_find_backlight_by_node(np);
of_node_put(np);
if (!nx->backlight)
return -EPROBE_DEFER;
}
drm_panel_init(&nx->base, &nx->dsi->dev, &nx_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
drm_panel_add(&nx->base);
return 0;
}
static void nx_panel_del(struct nx_panel *nx)
{
if (nx->base.dev)
drm_panel_remove(&nx->base);
if (nx->backlight)
put_device(&nx->backlight->dev);
}
static int nx_panel_probe(struct mipi_dsi_device *dsi)
{
struct nx_panel *nx;
int ret;
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_CLOCK_NON_CONTINUOUS |
MIPI_DSI_MODE_NO_EOT_PACKET;
nx = devm_kzalloc(&dsi->dev, sizeof(*nx), GFP_KERNEL);
if (!nx)
return -ENOMEM;
mipi_dsi_set_drvdata(dsi, nx);
nx->dsi = dsi;
ret = nx_panel_add(nx);
if (ret < 0)
return ret;
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
nx_panel_del(nx);
return ret;
}
return 0;
}
static void nx_panel_remove(struct mipi_dsi_device *dsi)
{
struct nx_panel *nx = mipi_dsi_get_drvdata(dsi);
int ret;
ret = nx_panel_disable(&nx->base);
if (ret < 0)
dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
nx_panel_del(nx);
}
static void nx_panel_shutdown(struct mipi_dsi_device *dsi)
{
struct nx_panel *nx = mipi_dsi_get_drvdata(dsi);
nx_panel_disable(&nx->base);
}
static const struct of_device_id nx_panel_of_match[] = {
{
.compatible = "nintendo,nx-dsi",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, nx_panel_of_match);
static struct mipi_dsi_driver nx_panel_driver = {
.driver = {
.name = "panel-nx-dsi",
.of_match_table = nx_panel_of_match,
},
.probe = nx_panel_probe,
.remove = nx_panel_remove,
.shutdown = nx_panel_shutdown,
};
module_mipi_dsi_driver(nx_panel_driver);
MODULE_AUTHOR("SwtcR <swtcr0@gmail.com>");
MODULE_DESCRIPTION("Nintendo Switch DSI (720x1280) panel driver");
MODULE_LICENSE("GPL v2");
+1
View File
@@ -25,6 +25,7 @@ tegra-drm-y := \
falcon.o \
vic.o \
nvdec.o \
nvenc.o \
nvjpg.o \
riscv.o
+116
View File
@@ -36,6 +36,103 @@
#include "hub.h"
#include "plane.h"
static const u16 default_srgb_lut[] = {
0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4, 0x6469, 0x64F0, 0x656B, 0x65DF, 0x664A,
0x66B0, 0x6711, 0x676D, 0x67C4, 0x6819, 0x686A, 0x68B8, 0x6904, 0x694D, 0x6994, 0x69D8,
0x6A1B, 0x6A5D, 0x6A9C, 0x6ADA, 0x6B17, 0x6B52, 0x6B8C, 0x6BC5, 0x6BFD, 0x6C33, 0x6C69,
0x6C9E, 0x6CD1, 0x6D04, 0x6D36, 0x6D67, 0x6D98, 0x6DC7, 0x6DF6, 0x6E25, 0x6E52, 0x6E7F,
0x6EAC, 0x6ED7, 0x6F03, 0x6F2D, 0x6F58, 0x6F81, 0x6FAA, 0x6FD3, 0x6FFB, 0x7023, 0x704B,
0x7071, 0x7098, 0x70BE, 0x70E4, 0x7109, 0x712E, 0x7153, 0x7177, 0x719B, 0x71BF, 0x71E2,
0x7205, 0x7227, 0x724A, 0x726C, 0x728E, 0x72AF, 0x72D0, 0x72F1, 0x7312, 0x7333, 0x7353,
0x7373, 0x7392, 0x73B2, 0x73D1, 0x73F0, 0x740F, 0x742D, 0x744C, 0x746A, 0x7488, 0x74A6,
0x74C3, 0x74E0, 0x74FE, 0x751B, 0x7537, 0x7554, 0x7570, 0x758D, 0x75A9, 0x75C4, 0x75E0,
0x75FC, 0x7617, 0x7632, 0x764D, 0x7668, 0x7683, 0x769E, 0x76B8, 0x76D3, 0x76ED, 0x7707,
0x7721, 0x773B, 0x7754, 0x776E, 0x7787, 0x77A0, 0x77B9, 0x77D2, 0x77EB, 0x7804, 0x781D,
0x7835, 0x784E, 0x7866, 0x787E, 0x7896, 0x78AE, 0x78C6, 0x78DD, 0x78F5, 0x790D, 0x7924,
0x793B, 0x7952, 0x796A, 0x7981, 0x7997, 0x79AE, 0x79C5, 0x79DB, 0x79F2, 0x7A08, 0x7A1F,
0x7A35, 0x7A4B, 0x7A61, 0x7A77, 0x7A8D, 0x7AA3, 0x7AB8, 0x7ACE, 0x7AE3, 0x7AF9, 0x7B0E,
0x7B24, 0x7B39, 0x7B4E, 0x7B63, 0x7B78, 0x7B8D, 0x7BA2, 0x7BB6, 0x7BCB, 0x7BE0, 0x7BF4,
0x7C08, 0x7C1D, 0x7C31, 0x7C45, 0x7C59, 0x7C6E, 0x7C82, 0x7C96, 0x7CA9, 0x7CBD, 0x7CD1,
0x7CE5, 0x7CF8, 0x7D0C, 0x7D1F, 0x7D33, 0x7D46, 0x7D59, 0x7D6D, 0x7D80, 0x7D93, 0x7DA6,
0x7DB9, 0x7DCC, 0x7DDF, 0x7DF2, 0x7E04, 0x7E17, 0x7E2A, 0x7E3C, 0x7E4F, 0x7E61, 0x7E74,
0x7E86, 0x7E98, 0x7EAB, 0x7EBD, 0x7ECF, 0x7EE1, 0x7EF3, 0x7F05, 0x7F17, 0x7F29, 0x7F3B,
0x7F4D, 0x7F5E, 0x7F70, 0x7F82, 0x7F93, 0x7FA5, 0x7FB6, 0x7FC8, 0x7FD9, 0x7FEB, 0x7FFC,
0x800D, 0x801E, 0x8030, 0x8041, 0x8052, 0x8063, 0x8074, 0x8085, 0x8096, 0x80A7, 0x80B7,
0x80C8, 0x80D9, 0x80EA, 0x80FA, 0x810B, 0x811C, 0x812C, 0x813D, 0x814D, 0x815D, 0x816E,
0x817E, 0x818E, 0x819F, 0x81AF, 0x81BF, 0x81CF, 0x81DF, 0x81EF, 0x81FF, 0x820F, 0x821F,
0x822F, 0x823F, 0x824F, 0x825F, 0x826F, 0x827E, 0x828E, 0x829E, 0x82AD, 0x82BD, 0x82CC,
0x82DC, 0x82EB, 0x82FB, 0x830A, 0x831A, 0x8329, 0x8338, 0x8348, 0x8357, 0x8366, 0x8375,
0x8385, 0x8394, 0x83A3, 0x83B2, 0x83C1, 0x83D0, 0x83DF, 0x83EE, 0x83FD, 0x840C, 0x841A,
0x8429, 0x8438, 0x8447, 0x8455, 0x8464, 0x8473, 0x8481, 0x8490, 0x849F, 0x84AD, 0x84BC,
0x84CA, 0x84D9, 0x84E7, 0x84F5, 0x8504, 0x8512, 0x8521, 0x852F, 0x853D, 0x854B, 0x855A,
0x8568, 0x8576, 0x8584, 0x8592, 0x85A0, 0x85AE, 0x85BC, 0x85CA, 0x85D8, 0x85E6, 0x85F4,
0x8602, 0x8610, 0x861E, 0x862C, 0x8639, 0x8647, 0x8655, 0x8663, 0x8670, 0x867E, 0x868C,
0x8699, 0x86A7, 0x86B5, 0x86C2, 0x86D0, 0x86DD, 0x86EB, 0x86F8, 0x8705, 0x8713, 0x8720,
0x872E, 0x873B, 0x8748, 0x8756, 0x8763, 0x8770, 0x877D, 0x878B, 0x8798, 0x87A5, 0x87B2,
0x87BF, 0x87CC, 0x87D9, 0x87E6, 0x87F3, 0x8801, 0x880E, 0x881A, 0x8827, 0x8834, 0x8841,
0x884E, 0x885B, 0x8868, 0x8875, 0x8882, 0x888E, 0x889B, 0x88A8, 0x88B5, 0x88C1, 0x88CE,
0x88DB, 0x88E7, 0x88F4, 0x8900, 0x890D, 0x891A, 0x8926, 0x8933, 0x893F, 0x894C, 0x8958,
0x8965, 0x8971, 0x897D, 0x898A, 0x8996, 0x89A3, 0x89AF, 0x89BB, 0x89C8, 0x89D4, 0x89E0,
0x89EC, 0x89F9, 0x8A05, 0x8A11, 0x8A1D, 0x8A29, 0x8A36, 0x8A42, 0x8A4E, 0x8A5A, 0x8A66,
0x8A72, 0x8A7E, 0x8A8A, 0x8A96, 0x8AA2, 0x8AAE, 0x8ABA, 0x8AC6, 0x8AD2, 0x8ADE, 0x8AEA,
0x8AF5, 0x8B01, 0x8B0D, 0x8B19, 0x8B25, 0x8B31, 0x8B3C, 0x8B48, 0x8B54, 0x8B60, 0x8B6B,
0x8B77, 0x8B83, 0x8B8E, 0x8B9A, 0x8BA6, 0x8BB1, 0x8BBD, 0x8BC8, 0x8BD4, 0x8BDF, 0x8BEB,
0x8BF6, 0x8C02, 0x8C0D, 0x8C19, 0x8C24, 0x8C30, 0x8C3B, 0x8C47, 0x8C52, 0x8C5D, 0x8C69,
0x8C74, 0x8C80, 0x8C8B, 0x8C96, 0x8CA1, 0x8CAD, 0x8CB8, 0x8CC3, 0x8CCF, 0x8CDA, 0x8CE5,
0x8CF0, 0x8CFB, 0x8D06, 0x8D12, 0x8D1D, 0x8D28, 0x8D33, 0x8D3E, 0x8D49, 0x8D54, 0x8D5F,
0x8D6A, 0x8D75, 0x8D80, 0x8D8B, 0x8D96, 0x8DA1, 0x8DAC, 0x8DB7, 0x8DC2, 0x8DCD, 0x8DD8,
0x8DE3, 0x8DEE, 0x8DF9, 0x8E04, 0x8E0E, 0x8E19, 0x8E24, 0x8E2F, 0x8E3A, 0x8E44, 0x8E4F,
0x8E5A, 0x8E65, 0x8E6F, 0x8E7A, 0x8E85, 0x8E90, 0x8E9A, 0x8EA5, 0x8EB0, 0x8EBA, 0x8EC5,
0x8ECF, 0x8EDA, 0x8EE5, 0x8EEF, 0x8EFA, 0x8F04, 0x8F0F, 0x8F19, 0x8F24, 0x8F2E, 0x8F39,
0x8F43, 0x8F4E, 0x8F58, 0x8F63, 0x8F6D, 0x8F78, 0x8F82, 0x8F8C, 0x8F97, 0x8FA1, 0x8FAC,
0x8FB6, 0x8FC0, 0x8FCB, 0x8FD5, 0x8FDF, 0x8FEA, 0x8FF4, 0x8FFE, 0x9008, 0x9013, 0x901D,
0x9027, 0x9031, 0x903C, 0x9046, 0x9050, 0x905A, 0x9064, 0x906E, 0x9079, 0x9083, 0x908D,
0x9097, 0x90A1, 0x90AB, 0x90B5, 0x90BF, 0x90C9, 0x90D3, 0x90DD, 0x90E7, 0x90F1, 0x90FB,
0x9105, 0x910F, 0x9119, 0x9123, 0x912D, 0x9137, 0x9141, 0x914B, 0x9155, 0x915F, 0x9169,
0x9173, 0x917D, 0x9186, 0x9190, 0x919A, 0x91A4, 0x91AE, 0x91B8, 0x91C1, 0x91CB, 0x91D5,
0x91DF, 0x91E9, 0x91F2, 0x91FC, 0x9206, 0x9210, 0x9219, 0x9223, 0x922D, 0x9236, 0x9240,
0x924A, 0x9253, 0x925D, 0x9267, 0x9270, 0x927A, 0x9283, 0x928D, 0x9297, 0x92A0, 0x92AA,
0x92B3, 0x92BD, 0x92C6, 0x92D0, 0x92DA, 0x92E3, 0x92ED, 0x92F6, 0x9300, 0x9309, 0x9313,
0x931C, 0x9325, 0x932F, 0x9338, 0x9342, 0x934B, 0x9355, 0x935E, 0x9367, 0x9371, 0x937A,
0x9384, 0x938D, 0x9396, 0x93A0, 0x93A9, 0x93B2, 0x93BC, 0x93C5, 0x93CE, 0x93D7, 0x93E1,
0x93EA, 0x93F3, 0x93FC, 0x9406, 0x940F, 0x9418, 0x9421, 0x942B, 0x9434, 0x943D, 0x9446,
0x944F, 0x9459, 0x9462, 0x946B, 0x9474, 0x947D, 0x9486, 0x948F, 0x9499, 0x94A2, 0x94AB,
0x94B4, 0x94BD, 0x94C6, 0x94CF, 0x94D8, 0x94E1, 0x94EA, 0x94F3, 0x94FC, 0x9505, 0x950E,
0x9517, 0x9520, 0x9529, 0x9532, 0x953B, 0x9544, 0x954D, 0x9556, 0x955F, 0x9568, 0x9571,
0x957A, 0x9583, 0x958C, 0x9595, 0x959D, 0x95A6, 0x95AF, 0x95B8, 0x95C1, 0x95CA, 0x95D3,
0x95DB, 0x95E4, 0x95ED, 0x95F6, 0x95FF, 0x9608, 0x9610, 0x9619, 0x9622, 0x962B, 0x9633,
0x963C, 0x9645, 0x964E, 0x9656, 0x965F, 0x9668, 0x9671, 0x9679, 0x9682, 0x968B, 0x9693,
0x969C, 0x96A5, 0x96AD, 0x96B6, 0x96BF, 0x96C7, 0x96D0, 0x96D9, 0x96E1, 0x96EA, 0x96F2,
0x96FB, 0x9704, 0x970C, 0x9715, 0x971D, 0x9726, 0x972E, 0x9737, 0x9740, 0x9748, 0x9751,
0x9759, 0x9762, 0x976A, 0x9773, 0x977B, 0x9784, 0x978C, 0x9795, 0x979D, 0x97A6, 0x97AE,
0x97B6, 0x97BF, 0x97C7, 0x97D0, 0x97D8, 0x97E1, 0x97E9, 0x97F1, 0x97FA, 0x9802, 0x980B,
0x9813, 0x981B, 0x9824, 0x982C, 0x9834, 0x983D, 0x9845, 0x984D, 0x9856, 0x985E, 0x9866,
0x986F, 0x9877, 0x987F, 0x9888, 0x9890, 0x9898, 0x98A0, 0x98A9, 0x98B1, 0x98B9, 0x98C1,
0x98CA, 0x98D2, 0x98DA, 0x98E2, 0x98EB, 0x98F3, 0x98FB, 0x9903, 0x990B, 0x9914, 0x991C,
0x9924, 0x992C, 0x9934, 0x993C, 0x9945, 0x994D, 0x9955, 0x995D, 0x9965, 0x996D, 0x9975,
0x997D, 0x9986, 0x998E, 0x9996, 0x999E, 0x99A6, 0x99AE, 0x99B6, 0x99BE, 0x99C6, 0x99CE,
0x99D6, 0x99DE, 0x99E6, 0x99EE, 0x99F6, 0x99FE, 0x9A06, 0x9A0E, 0x9A16, 0x9A1E, 0x9A26,
0x9A2E, 0x9A36, 0x9A3E, 0x9A46, 0x9A4E, 0x9A56, 0x9A5E, 0x9A66, 0x9A6E, 0x9A76, 0x9A7E,
0x9A86, 0x9A8E, 0x9A96, 0x9A9D, 0x9AA5, 0x9AAD, 0x9AB5, 0x9ABD, 0x9AC5, 0x9ACD, 0x9AD5,
0x9ADC, 0x9AE4, 0x9AEC, 0x9AF4, 0x9AFC, 0x9B04, 0x9B0C, 0x9B13, 0x9B1B, 0x9B23, 0x9B2B,
0x9B33, 0x9B3A, 0x9B42, 0x9B4A, 0x9B52, 0x9B59, 0x9B61, 0x9B69, 0x9B71, 0x9B79, 0x9B80,
0x9B88, 0x9B90, 0x9B97, 0x9B9F, 0x9BA7, 0x9BAF, 0x9BB6, 0x9BBE, 0x9BC6, 0x9BCD, 0x9BD5,
0x9BDD, 0x9BE5, 0x9BEC, 0x9BF4, 0x9BFC, 0x9C03, 0x9C0B, 0x9C12, 0x9C1A, 0x9C22, 0x9C29,
0x9C31, 0x9C39, 0x9C40, 0x9C48, 0x9C50, 0x9C57, 0x9C5F, 0x9C66, 0x9C6E, 0x9C75, 0x9C7D,
0x9C85, 0x9C8C, 0x9C94, 0x9C9B, 0x9CA3, 0x9CAA, 0x9CB2, 0x9CBA, 0x9CC1, 0x9CC9, 0x9CD0,
0x9CD8, 0x9CDF, 0x9CE7, 0x9CEE, 0x9CF6, 0x9CFD, 0x9D05, 0x9D0C, 0x9D14, 0x9D1B, 0x9D23,
0x9D2A, 0x9D32, 0x9D39, 0x9D40, 0x9D48, 0x9D4F, 0x9D57, 0x9D5E, 0x9D66, 0x9D6D, 0x9D75,
0x9D7C, 0x9D83, 0x9D8B, 0x9D92, 0x9D9A, 0x9DA1, 0x9DA8, 0x9DB0, 0x9DB7, 0x9DBE, 0x9DC6,
0x9DCD, 0x9DD5, 0x9DDC, 0x9DE3, 0x9DEB, 0x9DF2, 0x9DF9, 0x9E01, 0x9E08, 0x9E0F, 0x9E17,
0x9E1E, 0x9E25, 0x9E2D, 0x9E34, 0x9E3B, 0x9E43, 0x9E4A, 0x9E51, 0x9E58, 0x9E60, 0x9E67,
0x9E6E, 0x9E75, 0x9E7D, 0x9E84, 0x9E8B, 0x9E92, 0x9E9A, 0x9EA1, 0x9EA8, 0x9EAF, 0x9EB7,
0x9EBE, 0x9EC5, 0x9ECC, 0x9ED4, 0x9EDB, 0x9EE2, 0x9EE9, 0x9EF0, 0x9EF7, 0x9EFF, 0x9F06,
0x9F0D, 0x9F14, 0x9F1B, 0x9F23, 0x9F2A, 0x9F31, 0x9F38, 0x9F3F, 0x9F46, 0x9F4D, 0x9F55,
0x9F5C, 0x9F63, 0x9F6A, 0x9F71, 0x9F78, 0x9F7F, 0x9F86, 0x9F8D, 0x9F95, 0x9F9C, 0x9FA3,
0x9FAA, 0x9FB1, 0x9FB8, 0x9FBF, 0x9FC6, 0x9FCD, 0x9FD4, 0x9FDB, 0x9FE2, 0x9FE9, 0x9FF0,
0x9FF7, 0x9FFF,
};
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state);
@@ -3251,6 +3348,25 @@ static int tegra_dc_probe(struct platform_device *pdev)
if (dc->irq < 0)
return -ENXIO;
if (dc->soc->has_nvdisplay) {
unsigned int i;
u64 r;
dc->cmu_output_lut =
dmam_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
&dc->cmu_output_lut_phys, GFP_KERNEL);
if (!dc->cmu_output_lut) {
dev_err(dc->dev, "failed to allocate lut for cmu\n");
return -ENOMEM;
}
for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
r = default_srgb_lut[i];
dc->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
}
}
err = tegra_dc_rgb_probe(dc);
if (err < 0 && err != -ENODEV)
return dev_err_probe(&pdev->dev, err,
+13
View File
@@ -103,6 +103,9 @@ struct tegra_dc {
const struct tegra_dc_soc_info *soc;
bool has_opp_table;
u64 *cmu_output_lut;
dma_addr_t cmu_output_lut_phys;
};
static inline struct tegra_dc *
@@ -447,6 +450,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define BASE_COLOR_SIZE_888 ( 8 << 0)
#define BASE_COLOR_SIZE_101010 ( 10 << 0)
#define BASE_COLOR_SIZE_121212 ( 12 << 0)
#define CMU_ENABLE_ENABLE (1 << 20)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC1_H_QUALIFIER_NONE (1 << 16)
@@ -732,6 +736,15 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define PROTOCOL_MASK (0xf << 8)
#define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT 0x431
#define OUTPUT_LUT_MODE_MASK (3 << 5)
#define OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
#define OUTPUT_LUT_SIZE_MASK (3 << 1)
#define OUTPUT_LUT_SIZE_SIZE_1025 (2 << 1)
#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE 0x432
#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI 0x433
#define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR 0x442
#define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR 0x446
+9
View File
@@ -1378,10 +1378,12 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra132-dsi", },
{ .compatible = "nvidia,tegra210-dc", },
{ .compatible = "nvidia,tegra210-dsi", },
{ .compatible = "nvidia,tegra210b01-dsi", },
{ .compatible = "nvidia,tegra210-sor", },
{ .compatible = "nvidia,tegra210-sor1", },
{ .compatible = "nvidia,tegra210-vic", },
{ .compatible = "nvidia,tegra210-nvdec", },
{ .compatible = "nvidia,tegra210-nvenc", },
{ .compatible = "nvidia,tegra210-nvjpg", },
{ .compatible = "nvidia,tegra186-display", },
{ .compatible = "nvidia,tegra186-dc", },
@@ -1389,13 +1391,19 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra186-sor1", },
{ .compatible = "nvidia,tegra186-vic", },
{ .compatible = "nvidia,tegra186-nvdec", },
{ .compatible = "nvidia,tegra186-nvenc", },
{ .compatible = "nvidia,tegra186-nvjpg", },
{ .compatible = "nvidia,tegra194-display", },
{ .compatible = "nvidia,tegra194-dc", },
{ .compatible = "nvidia,tegra194-sor", },
{ .compatible = "nvidia,tegra194-vic", },
{ .compatible = "nvidia,tegra194-nvdec", },
{ .compatible = "nvidia,tegra194-nvenc", },
{ .compatible = "nvidia,tegra194-nvjpg", },
{ .compatible = "nvidia,tegra234-vic", },
{ .compatible = "nvidia,tegra234-nvdec", },
{ .compatible = "nvidia,tegra234-nvenc", },
{ .compatible = "nvidia,tegra234-nvjpg", },
{ /* sentinel */ }
};
@@ -1421,6 +1429,7 @@ static struct platform_driver * const drivers[] = {
&tegra_gr3d_driver,
&tegra_vic_driver,
&tegra_nvdec_driver,
&tegra_nvenc_driver,
&tegra_nvjpg_driver,
};
+14
View File
@@ -129,9 +129,22 @@ void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
struct cec_notifier;
struct notify_dev {
const char *name;
struct device *dev;
int index;
int state;
ssize_t (*print_name)(struct notify_dev *sdev, char *buf);
ssize_t (*print_state)(struct notify_dev *sdev, char *buf);
};
struct tegra_output {
struct device_node *of_node;
struct device *dev;
struct notify_dev notify_data;
struct class *switch_class;
atomic_t switch_count;
struct drm_bridge *bridge;
struct drm_panel *panel;
@@ -214,6 +227,7 @@ extern struct platform_driver tegra_gr2d_driver;
extern struct platform_driver tegra_gr3d_driver;
extern struct platform_driver tegra_vic_driver;
extern struct platform_driver tegra_nvdec_driver;
extern struct platform_driver tegra_nvenc_driver;
extern struct platform_driver tegra_nvjpg_driver;
#endif /* HOST1X_DRM_H */
+139 -38
View File
@@ -54,6 +54,21 @@ to_dsi_state(struct drm_connector_state *state)
return container_of(state, struct tegra_dsi_state, base);
}
/*
* remap of registers revised in Tegra210B01
*/
struct dsi_regmap {
int init_seq_data_15;
int slew_impedance[4];
int preemphasis;
int bias;
int ganged_mode_control;
int ganged_mode_start;
int ganged_mode_size;
int dbg_regs_cnt;
struct debugfs_reg32 dbg_regs_ext[16];
};
struct tegra_dsi {
struct host1x_client client;
struct tegra_output output;
@@ -83,6 +98,8 @@ struct tegra_dsi {
/* for ganged-mode support */
struct tegra_dsi *master;
struct tegra_dsi *slave;
const struct dsi_regmap *regmap;
};
static inline struct tegra_dsi *
@@ -124,7 +141,7 @@ static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value,
#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
static const struct debugfs_reg32 tegra_dsi_regs[] = {
static const struct debugfs_reg32 tegra_dsi_regs_common[] = {
DEBUGFS_REG32(DSI_INCR_SYNCPT),
DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL),
DEBUGFS_REG32(DSI_INCR_SYNCPT_ERROR),
@@ -183,19 +200,6 @@ static const struct debugfs_reg32 tegra_dsi_regs[] = {
DEBUGFS_REG32(DSI_PAD_CONTROL_2),
DEBUGFS_REG32(DSI_PAD_CONTROL_3),
DEBUGFS_REG32(DSI_PAD_CONTROL_4),
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL),
DEBUGFS_REG32(DSI_GANGED_MODE_START),
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE),
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT),
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15),
};
static int tegra_dsi_show_regs(struct seq_file *s, void *data)
@@ -214,10 +218,17 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data)
goto unlock;
}
for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs); i++) {
unsigned int offset = tegra_dsi_regs[i].offset;
for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs_common); i++) {
unsigned int offset = tegra_dsi_regs_common[i].offset;
seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs[i].name,
seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs_common[i].name,
offset, tegra_dsi_readl(dsi, offset));
}
for (i = 0; i < dsi->regmap->dbg_regs_cnt; i++) {
unsigned int offset = dsi->regmap->dbg_regs_ext[i].offset;
seq_printf(s, "%-32s %#05x %08x\n", dsi->regmap->dbg_regs_ext[i].name,
offset, tegra_dsi_readl(dsi, offset));
}
@@ -448,11 +459,11 @@ static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start,
{
u32 value;
tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START);
tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE);
tegra_dsi_writel(dsi, start, dsi->regmap->ganged_mode_start);
tegra_dsi_writel(dsi, size << 16 | size, dsi->regmap->ganged_mode_size);
value = DSI_GANGED_MODE_CONTROL_ENABLE;
tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL);
tegra_dsi_writel(dsi, value, dsi->regmap->ganged_mode_control);
}
static void tegra_dsi_enable(struct tegra_dsi *dsi)
@@ -656,9 +667,9 @@ static void tegra_dsi_video_disable(struct tegra_dsi *dsi)
static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
{
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_start);
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_size);
tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_control);
}
static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
@@ -674,7 +685,7 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
{
u32 value;
int err;
int err, i;
/*
* XXX Is this still needed? The module reset is deasserted right
@@ -682,21 +693,29 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
*/
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
for (i = 0; i < ARRAY_SIZE(dsi->regmap->slew_impedance); i++) {
if (dsi->regmap->slew_impedance[i])
tegra_dsi_writel(dsi, 0, dsi->regmap->slew_impedance[i]);
}
/* start calibration */
tegra_dsi_pad_enable(dsi);
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
DSI_PAD_OUT_CLK(0x0);
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
/* do not set padctl 2 slew by default */
if (of_property_read_bool(dsi->dev->of_node, "nvidia,slew-enable")) {
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
DSI_PAD_OUT_CLK(0x0);
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
}
value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
value = tegra_dsi_readl(dsi, dsi->regmap->preemphasis);
value |= DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
tegra_dsi_writel(dsi, value, dsi->regmap->preemphasis);
tegra_dsi_writel(dsi, 0, dsi->regmap->bias);
err = tegra_mipi_start_calibration(dsi->mipi);
if (err < 0)
@@ -1069,7 +1088,7 @@ static int tegra_dsi_init(struct host1x_client *client)
dev_err(dsi->dev, "failed to initialize output: %d\n",
err);
dsi->output.encoder.possible_crtcs = 0x3;
tegra_output_find_possible_crtcs(&dsi->output, drm);
}
return 0;
@@ -1633,6 +1652,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
goto remove;
}
dsi->regmap = of_device_get_match_data(&pdev->dev);
if (IS_ERR(dsi->regmap)) {
err = PTR_ERR(dsi->regmap);
goto remove;
}
dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
if (IS_ERR(dsi->mipi)) {
err = PTR_ERR(dsi->mipi);
@@ -1688,11 +1713,87 @@ static void tegra_dsi_remove(struct platform_device *pdev)
tegra_mipi_free(dsi->mipi);
}
static const struct dsi_regmap tegra_dsi_regmap = {
.init_seq_data_15 = DSI_INIT_SEQ_DATA_15,
.slew_impedance = { DSI_PAD_CONTROL_2 },
.preemphasis = DSI_PAD_CONTROL_3,
.bias = DSI_PAD_CONTROL_4,
.ganged_mode_control = DSI_GANGED_MODE_CONTROL,
.ganged_mode_start = DSI_GANGED_MODE_START,
.ganged_mode_size = DSI_GANGED_MODE_SIZE,
.dbg_regs_cnt = 13,
.dbg_regs_ext = {
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL),
DEBUGFS_REG32(DSI_GANGED_MODE_START),
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE),
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT),
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15),
},
};
static const struct dsi_regmap tegra_dsi_regmap_b01 = {
.init_seq_data_15 = DSI_INIT_SEQ_DATA_15_B01,
.slew_impedance = {
DSI_PAD_CONTROL_2,
DSI_PAD_CONTROL_3,
DSI_PAD_CONTROL_4,
DSI_PAD_CONTROL_5_B01,
},
.preemphasis = DSI_PAD_CONTROL_6_B01,
.bias = DSI_PAD_CONTROL_7_B01,
.ganged_mode_control = DSI_GANGED_MODE_CONTROL_B01,
.ganged_mode_start = DSI_GANGED_MODE_START_B01,
.ganged_mode_size = DSI_GANGED_MODE_SIZE_B01,
.dbg_regs_cnt = 16,
.dbg_regs_ext = {
DEBUGFS_REG32(DSI_PAD_CONTROL_5_B01),
DEBUGFS_REG32(DSI_PAD_CONTROL_6_B01),
DEBUGFS_REG32(DSI_PAD_CONTROL_7_B01),
DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL_B01),
DEBUGFS_REG32(DSI_GANGED_MODE_START_B01),
DEBUGFS_REG32(DSI_GANGED_MODE_SIZE_B01),
DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT_B01),
DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14_B01),
DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15_B01),
},
};
static const struct of_device_id tegra_dsi_of_match[] = {
{ .compatible = "nvidia,tegra210-dsi", },
{ .compatible = "nvidia,tegra132-dsi", },
{ .compatible = "nvidia,tegra124-dsi", },
{ .compatible = "nvidia,tegra114-dsi", },
{
.compatible = "nvidia,tegra210b01-dsi",
.data = &tegra_dsi_regmap_b01
},
{
.compatible = "nvidia,tegra210-dsi",
.data = &tegra_dsi_regmap
},
{
.compatible = "nvidia,tegra132-dsi",
.data = &tegra_dsi_regmap
},
{
.compatible = "nvidia,tegra124-dsi",
.data = &tegra_dsi_regmap
},
{
.compatible = "nvidia,tegra114-dsi",
.data = &tegra_dsi_regmap
},
{ },
};
MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
+18
View File
@@ -130,6 +130,24 @@
#define DSI_INIT_SEQ_DATA_14 0x5e
#define DSI_INIT_SEQ_DATA_15 0x5f
// Tegra210B01 has a revised set of regs
#define DSI_PAD_CONTROL_5_B01 0x53
#define DSI_PAD_CONTROL_6_B01 0x54
#define DSI_PAD_CONTROL_7_B01 0x55
#define DSI_GANGED_MODE_CONTROL_B01 0x56
#define DSI_GANGED_MODE_START_B01 0x57
#define DSI_GANGED_MODE_SIZE_B01 0x58
#define DSI_RAW_DATA_BYTE_COUNT_B01 0x59
#define DSI_ULTRA_LOW_POWER_CONTROL_B01 0x5a
#define DSI_INIT_SEQ_DATA_8_B01 0x5b
#define DSI_INIT_SEQ_DATA_9_B01 0x5c
#define DSI_INIT_SEQ_DATA_10_B01 0x5d
#define DSI_INIT_SEQ_DATA_11_B01 0x5e
#define DSI_INIT_SEQ_DATA_12_B01 0x5f
#define DSI_INIT_SEQ_DATA_13_B01 0x60
#define DSI_INIT_SEQ_DATA_14_B01 0x61
#define DSI_INIT_SEQ_DATA_15_B01 0x62
/*
* pixel format as used in the DSI_CONTROL_FORMAT field
*/
+92
View File
@@ -5,6 +5,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/devfreq.h>
#include <linux/dma-mapping.h>
#include <linux/host1x.h>
#include <linux/iommu.h>
@@ -43,6 +44,7 @@ struct nvdec {
struct clk_bulk_data clks[3];
unsigned int num_clks;
struct reset_control *reset;
struct devfreq *devfreq;
/* Platform configuration */
const struct nvdec_config *config;
@@ -63,6 +65,75 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
writel(value, nvdec->regs + offset);
}
static int nvdec_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct nvdec *nvdec = dev_get_drvdata(dev);
int err;
err = clk_set_rate(nvdec->clks[0].clk, *freq);
if (err < 0)
return err;
*freq = clk_get_rate(nvdec->clks[0].clk);
return 0;
}
static int nvdec_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct nvdec *nvdec = dev_get_drvdata(dev);
*freq = clk_get_rate(nvdec->clks[0].clk);
return 0;
}
static struct devfreq_dev_profile nvdec_devfreq_profile = {
.polling_ms = 50,
.target = nvdec_devfreq_target,
.get_cur_freq = nvdec_devfreq_get_cur_freq,
};
static int nvdec_devfreq_init(struct nvdec *nvdec)
{
struct clk *clk = nvdec->clks[0].clk;
unsigned long max_rate = clk_round_rate(clk, ULONG_MAX);
unsigned long min_rate = clk_round_rate(clk, 0);
unsigned long margin = clk_round_rate(clk, min_rate + 1) - min_rate;
unsigned long rate = min_rate;
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
struct devfreq *devfreq;
if (min_rate == max_rate) {
dev_info(nvdec->dev, "Only one supported clock rate, disabling devfreq\n");
return 0;
}
// Only allow up to 20 rates
if (hw_rates > 20)
margin *= DIV_ROUND_UP(hw_rates, 20);
while (rate < max_rate) {
dev_pm_opp_add(nvdec->dev, rate, 0);
rate += margin;
}
// The margin step may not fall on max rate exactly, so add max rate explicitly
dev_pm_opp_add(nvdec->dev, max_rate, 0);
devfreq = devm_devfreq_add_device(nvdec->dev,
&nvdec_devfreq_profile,
DEVFREQ_GOV_USERSPACE,
NULL);
if (IS_ERR(devfreq))
return PTR_ERR(devfreq);
nvdec->devfreq = devfreq;
return 0;
}
static int nvdec_boot_falcon(struct nvdec *nvdec)
{
u32 stream_id;
@@ -329,6 +400,12 @@ static __maybe_unused int nvdec_runtime_resume(struct device *dev)
goto disable;
}
if (nvdec->devfreq) {
err = devfreq_resume_device(nvdec->devfreq);
if (err < 0)
goto disable;
}
return 0;
disable:
@@ -339,6 +416,13 @@ disable:
static __maybe_unused int nvdec_runtime_suspend(struct device *dev)
{
struct nvdec *nvdec = dev_get_drvdata(dev);
int err;
if (nvdec->devfreq) {
err = devfreq_suspend_device(nvdec->devfreq);
if (err < 0)
return err;
}
host1x_channel_stop(nvdec->channel);
@@ -530,12 +614,20 @@ static int nvdec_probe(struct platform_device *pdev)
goto exit_falcon;
}
err = nvdec_devfreq_init(nvdec);
if (err < 0) {
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
goto unregister_client;
}
pm_runtime_enable(dev);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 500);
return 0;
unregister_client:
host1x_client_unregister(&nvdec->client.base);
exit_falcon:
falcon_exit(&nvdec->falcon);
+551
View File
@@ -0,0 +1,551 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/devfreq.h>
#include <linux/dma-mapping.h>
#include <linux/host1x.h>
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include "drm.h"
#include "falcon.h"
#include "vic.h"
#define NVENC_TFBIF_TRANSCFG 0x1844
struct nvenc_config {
const char *firmware;
unsigned int version;
bool supports_sid;
};
struct nvenc {
struct falcon falcon;
void __iomem *regs;
struct tegra_drm_client client;
struct host1x_channel *channel;
struct device *dev;
struct clk *clk;
struct devfreq *devfreq;
/* Platform configuration */
const struct nvenc_config *config;
};
static inline struct nvenc *to_nvenc(struct tegra_drm_client *client)
{
return container_of(client, struct nvenc, client);
}
static inline void nvenc_writel(struct nvenc *nvenc, u32 value,
unsigned int offset)
{
writel(value, nvenc->regs + offset);
}
static int nvenc_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct nvenc *nvenc = dev_get_drvdata(dev);
int err;
err = clk_set_rate(nvenc->clk, *freq);
if (err < 0)
return err;
*freq = clk_get_rate(nvenc->clk);
return 0;
}
static int nvenc_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct nvenc *nvenc = dev_get_drvdata(dev);
*freq = clk_get_rate(nvenc->clk);
return 0;
}
static struct devfreq_dev_profile nvenc_devfreq_profile = {
.polling_ms = 50,
.target = nvenc_devfreq_target,
.get_cur_freq = nvenc_devfreq_get_cur_freq,
};
static int nvenc_devfreq_init(struct nvenc *nvenc)
{
unsigned long max_rate = clk_round_rate(nvenc->clk, ULONG_MAX);
unsigned long min_rate = clk_round_rate(nvenc->clk, 0);
unsigned long margin = clk_round_rate(nvenc->clk, min_rate + 1) - min_rate;
unsigned long rate = min_rate;
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
struct devfreq *devfreq;
if (min_rate == max_rate) {
dev_info(nvenc->dev, "Only one supported clock rate, disabling devfreq\n");
return 0;
}
// Only allow up to 20 rates
if (hw_rates > 20)
margin *= DIV_ROUND_UP(hw_rates, 20);
while (rate < max_rate) {
dev_pm_opp_add(nvenc->dev, rate, 0);
rate += margin;
}
// The margin step may not fall on max rate exactly, so add max rate explicitly
dev_pm_opp_add(nvenc->dev, max_rate, 0);
devfreq = devm_devfreq_add_device(nvenc->dev,
&nvenc_devfreq_profile,
DEVFREQ_GOV_USERSPACE,
NULL);
if (IS_ERR(devfreq))
return PTR_ERR(devfreq);
nvenc->devfreq = devfreq;
return 0;
}
static int nvenc_init(struct host1x_client *client)
{
struct tegra_drm_client *drm = host1x_to_drm_client(client);
struct drm_device *dev = dev_get_drvdata(client->host);
struct tegra_drm *tegra = dev->dev_private;
struct nvenc *nvenc = to_nvenc(drm);
int err;
err = host1x_client_iommu_attach(client);
if (err < 0 && err != -ENODEV) {
dev_err(nvenc->dev, "failed to attach to domain: %d\n", err);
return err;
}
nvenc->channel = host1x_channel_request(client);
if (!nvenc->channel) {
err = -ENOMEM;
goto detach;
}
client->syncpts[0] = host1x_syncpt_request(client, 0);
if (!client->syncpts[0]) {
err = -ENOMEM;
goto free_channel;
}
err = tegra_drm_register_client(tegra, drm);
if (err < 0)
goto free_syncpt;
/*
* Inherit the DMA parameters (such as maximum segment size) from the
* parent host1x device.
*/
client->dev->dma_parms = client->host->dma_parms;
return 0;
free_syncpt:
host1x_syncpt_put(client->syncpts[0]);
free_channel:
host1x_channel_put(nvenc->channel);
detach:
host1x_client_iommu_detach(client);
return err;
}
static int nvenc_exit(struct host1x_client *client)
{
struct tegra_drm_client *drm = host1x_to_drm_client(client);
struct drm_device *dev = dev_get_drvdata(client->host);
struct tegra_drm *tegra = dev->dev_private;
struct nvenc *nvenc = to_nvenc(drm);
int err;
/* avoid a dangling pointer just in case this disappears */
client->dev->dma_parms = NULL;
err = tegra_drm_unregister_client(tegra, drm);
if (err < 0)
return err;
pm_runtime_dont_use_autosuspend(client->dev);
pm_runtime_force_suspend(client->dev);
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(nvenc->channel);
host1x_client_iommu_detach(client);
nvenc->channel = NULL;
if (client->group) {
dma_unmap_single(nvenc->dev, nvenc->falcon.firmware.phys,
nvenc->falcon.firmware.size, DMA_TO_DEVICE);
tegra_drm_free(tegra, nvenc->falcon.firmware.size,
nvenc->falcon.firmware.virt,
nvenc->falcon.firmware.iova);
} else {
dma_free_coherent(nvenc->dev, nvenc->falcon.firmware.size,
nvenc->falcon.firmware.virt,
nvenc->falcon.firmware.iova);
}
return 0;
}
static const struct host1x_client_ops nvenc_client_ops = {
.init = nvenc_init,
.exit = nvenc_exit,
};
static int nvenc_load_falcon_firmware(struct nvenc *nvenc)
{
struct host1x_client *client = &nvenc->client.base;
struct tegra_drm *tegra = nvenc->client.drm;
dma_addr_t iova;
size_t size;
void *virt;
int err;
if (nvenc->falcon.firmware.virt)
return 0;
err = falcon_read_firmware(&nvenc->falcon, nvenc->config->firmware);
if (err < 0)
return err;
size = nvenc->falcon.firmware.size;
if (!client->group) {
virt = dma_alloc_coherent(nvenc->dev, size, &iova, GFP_KERNEL);
if (!virt)
return -ENOMEM;
} else {
virt = tegra_drm_alloc(tegra, size, &iova);
if (IS_ERR(virt))
return PTR_ERR(virt);
}
nvenc->falcon.firmware.virt = virt;
nvenc->falcon.firmware.iova = iova;
err = falcon_load_firmware(&nvenc->falcon);
if (err < 0)
goto cleanup;
/*
* In this case we have received an IOVA from the shared domain, so we
* need to make sure to get the physical address so that the DMA API
* knows what memory pages to flush the cache for.
*/
if (client->group) {
dma_addr_t phys;
phys = dma_map_single(nvenc->dev, virt, size, DMA_TO_DEVICE);
err = dma_mapping_error(nvenc->dev, phys);
if (err < 0)
goto cleanup;
nvenc->falcon.firmware.phys = phys;
}
return 0;
cleanup:
if (!client->group)
dma_free_coherent(nvenc->dev, size, virt, iova);
else
tegra_drm_free(tegra, size, virt, iova);
return err;
}
static int nvenc_boot_falcon(struct nvenc *nvenc)
{
u32 stream_id;
int err;
if (nvenc->config->supports_sid && tegra_dev_iommu_get_stream_id(nvenc->dev, &stream_id)) {
u32 value;
value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW);
nvenc_writel(nvenc, value, NVENC_TFBIF_TRANSCFG);
nvenc_writel(nvenc, stream_id, VIC_THI_STREAMID0);
nvenc_writel(nvenc, stream_id, VIC_THI_STREAMID1);
}
err = falcon_boot(&nvenc->falcon);
if (err < 0)
return err;
err = falcon_wait_idle(&nvenc->falcon);
if (err < 0) {
dev_err(nvenc->dev, "falcon boot timed out\n");
return err;
}
return 0;
}
static __maybe_unused int nvenc_runtime_resume(struct device *dev)
{
struct nvenc *nvenc = dev_get_drvdata(dev);
int err;
err = clk_prepare_enable(nvenc->clk);
if (err < 0)
return err;
usleep_range(20, 30);
err = nvenc_load_falcon_firmware(nvenc);
if (err < 0)
goto disable_clk;
err = nvenc_boot_falcon(nvenc);
if (err < 0)
goto disable_clk;
if (nvenc->devfreq) {
err = devfreq_resume_device(nvenc->devfreq);
if (err < 0)
goto disable_clk;
}
return 0;
disable_clk:
clk_disable_unprepare(nvenc->clk);
return err;
}
static __maybe_unused int nvenc_runtime_suspend(struct device *dev)
{
struct nvenc *nvenc = dev_get_drvdata(dev);
int err;
if (nvenc->devfreq) {
err = devfreq_suspend_device(nvenc->devfreq);
if (err < 0)
return err;
}
host1x_channel_stop(nvenc->channel);
clk_disable_unprepare(nvenc->clk);
return 0;
}
static int nvenc_open_channel(struct tegra_drm_client *client,
struct tegra_drm_context *context)
{
struct nvenc *nvenc = to_nvenc(client);
context->channel = host1x_channel_get(nvenc->channel);
if (!context->channel)
return -ENOMEM;
return 0;
}
static void nvenc_close_channel(struct tegra_drm_context *context)
{
host1x_channel_put(context->channel);
}
static int nvenc_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported)
{
*supported = true;
return 0;
}
static const struct tegra_drm_client_ops nvenc_ops = {
.open_channel = nvenc_open_channel,
.close_channel = nvenc_close_channel,
.submit = tegra_drm_submit,
.get_streamid_offset = tegra_drm_get_streamid_offset_thi,
.can_use_memory_ctx = nvenc_can_use_memory_ctx,
};
#define NVIDIA_TEGRA_210_NVENC_FIRMWARE "nvidia/tegra210/nvenc.bin"
static const struct nvenc_config nvenc_t210_config = {
.firmware = NVIDIA_TEGRA_210_NVENC_FIRMWARE,
.version = 0x21,
.supports_sid = false,
};
#define NVIDIA_TEGRA_186_NVENC_FIRMWARE "nvidia/tegra186/nvenc.bin"
static const struct nvenc_config nvenc_t186_config = {
.firmware = NVIDIA_TEGRA_186_NVENC_FIRMWARE,
.version = 0x18,
.supports_sid = true,
};
#define NVIDIA_TEGRA_194_NVENC_FIRMWARE "nvidia/tegra194/nvenc.bin"
static const struct nvenc_config nvenc_t194_config = {
.firmware = NVIDIA_TEGRA_194_NVENC_FIRMWARE,
.version = 0x19,
.supports_sid = true,
};
#define NVIDIA_TEGRA_234_NVENC_FIRMWARE "nvidia/tegra234/nvenc.bin"
static const struct nvenc_config nvenc_t234_config = {
.firmware = NVIDIA_TEGRA_234_NVENC_FIRMWARE,
.version = 0x23,
.supports_sid = true,
};
static const struct of_device_id tegra_nvenc_of_match[] = {
{ .compatible = "nvidia,tegra210-nvenc", .data = &nvenc_t210_config },
{ .compatible = "nvidia,tegra186-nvenc", .data = &nvenc_t186_config },
{ .compatible = "nvidia,tegra194-nvenc", .data = &nvenc_t194_config },
{ .compatible = "nvidia,tegra234-nvenc", .data = &nvenc_t234_config },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_nvenc_of_match);
static int nvenc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct host1x_syncpt **syncpts;
struct nvenc *nvenc;
u32 host_class;
int err;
/* inherit DMA mask from host1x parent */
err = dma_coerce_mask_and_coherent(dev, *dev->parent->dma_mask);
if (err < 0) {
dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
return err;
}
nvenc = devm_kzalloc(dev, sizeof(*nvenc), GFP_KERNEL);
if (!nvenc)
return -ENOMEM;
nvenc->config = of_device_get_match_data(dev);
syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
if (!syncpts)
return -ENOMEM;
nvenc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(nvenc->regs))
return PTR_ERR(nvenc->regs);
nvenc->clk = devm_clk_get(dev, "nvenc");
if (IS_ERR(nvenc->clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
return PTR_ERR(nvenc->clk);
}
err = clk_set_rate(nvenc->clk, ULONG_MAX);
if (err < 0) {
dev_err(&pdev->dev, "failed to set clock rate\n");
return err;
}
nvenc->falcon.dev = dev;
nvenc->falcon.regs = nvenc->regs;
err = falcon_init(&nvenc->falcon);
if (err < 0)
return err;
err = of_property_read_u32(dev->of_node, "nvidia,host1x-class", &host_class);
if (err < 0)
host_class = HOST1X_CLASS_NVENC;
platform_set_drvdata(pdev, nvenc);
INIT_LIST_HEAD(&nvenc->client.base.list);
nvenc->client.base.ops = &nvenc_client_ops;
nvenc->client.base.dev = dev;
nvenc->client.base.class = host_class;
nvenc->client.base.syncpts = syncpts;
nvenc->client.base.num_syncpts = 1;
nvenc->dev = dev;
INIT_LIST_HEAD(&nvenc->client.list);
nvenc->client.version = nvenc->config->version;
nvenc->client.ops = &nvenc_ops;
err = host1x_client_register(&nvenc->client.base);
if (err < 0) {
dev_err(dev, "failed to register host1x client: %d\n", err);
goto exit_falcon;
}
err = nvenc_devfreq_init(nvenc);
if (err < 0) {
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
goto unregister_client;
}
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 500);
devm_pm_runtime_enable(dev);
return 0;
unregister_client:
host1x_client_unregister(&nvenc->client.base);
exit_falcon:
falcon_exit(&nvenc->falcon);
return err;
}
static void nvenc_remove(struct platform_device *pdev)
{
struct nvenc *nvenc = platform_get_drvdata(pdev);
host1x_client_unregister(&nvenc->client.base);
falcon_exit(&nvenc->falcon);
}
static const struct dev_pm_ops nvenc_pm_ops = {
RUNTIME_PM_OPS(nvenc_runtime_suspend, nvenc_runtime_resume, NULL)
SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
struct platform_driver tegra_nvenc_driver = {
.driver = {
.name = "tegra-nvenc",
.of_match_table = tegra_nvenc_of_match,
.pm = &nvenc_pm_ops
},
.probe = nvenc_probe,
.remove = nvenc_remove,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_210_NVENC_FIRMWARE);
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_186_NVENC_FIRMWARE);
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_194_NVENC_FIRMWARE);
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_234_NVENC_FIRMWARE);
#endif
+226 -5
View File
@@ -2,6 +2,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/devfreq.h>
#include <linux/dma-mapping.h>
#include <linux/host1x.h>
#include <linux/iommu.h>
@@ -12,10 +13,14 @@
#include "drm.h"
#include "falcon.h"
#include "vic.h"
#define NVJPG_TFBIF_TRANSCFG 0x1444
struct nvjpg_config {
const char *firmware;
unsigned int version;
bool supports_sid;
};
struct nvjpg {
@@ -23,8 +28,10 @@ struct nvjpg {
void __iomem *regs;
struct tegra_drm_client client;
struct host1x_channel *channel;
struct device *dev;
struct clk *clk;
struct devfreq *devfreq;
/* Platform configuration */
const struct nvjpg_config *config;
@@ -35,6 +42,80 @@ static inline struct nvjpg *to_nvjpg(struct tegra_drm_client *client)
return container_of(client, struct nvjpg, client);
}
static inline void nvjpg_writel(struct nvjpg *nvjpg, u32 value,
unsigned int offset)
{
writel(value, nvjpg->regs + offset);
}
static int nvjpg_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct nvjpg *nvjpg = dev_get_drvdata(dev);
int err;
err = clk_set_rate(nvjpg->clk, *freq);
if (err < 0)
return err;
*freq = clk_get_rate(nvjpg->clk);
return 0;
}
static int nvjpg_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct nvjpg *nvjpg = dev_get_drvdata(dev);
*freq = clk_get_rate(nvjpg->clk);
return 0;
}
static struct devfreq_dev_profile nvjpg_devfreq_profile = {
.polling_ms = 50,
.target = nvjpg_devfreq_target,
.get_cur_freq = nvjpg_devfreq_get_cur_freq,
};
static int nvjpg_devfreq_init(struct nvjpg *nvjpg)
{
unsigned long max_rate = clk_round_rate(nvjpg->clk, ULONG_MAX);
unsigned long min_rate = clk_round_rate(nvjpg->clk, 0);
unsigned long margin = clk_round_rate(nvjpg->clk, min_rate + 1) - min_rate;
unsigned long rate = min_rate;
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
struct devfreq *devfreq;
if (min_rate == max_rate) {
dev_info(nvjpg->dev, "Only one supported clock rate, disabling devfreq\n");
return 0;
}
// Only allow up to 20 rates
if (hw_rates > 20)
margin *= DIV_ROUND_UP(hw_rates, 20);
while (rate < max_rate) {
dev_pm_opp_add(nvjpg->dev, rate, 0);
rate += margin;
}
// The margin step may not fall on max rate exactly, so add max rate explicitly
dev_pm_opp_add(nvjpg->dev, max_rate, 0);
devfreq = devm_devfreq_add_device(nvjpg->dev,
&nvjpg_devfreq_profile,
DEVFREQ_GOV_USERSPACE,
NULL);
if (IS_ERR(devfreq))
return PTR_ERR(devfreq);
nvjpg->devfreq = devfreq;
return 0;
}
static int nvjpg_init(struct host1x_client *client)
{
struct tegra_drm_client *drm = host1x_to_drm_client(client);
@@ -49,9 +130,21 @@ static int nvjpg_init(struct host1x_client *client)
return err;
}
nvjpg->channel = host1x_channel_request(client);
if (!nvjpg->channel) {
err = -ENOMEM;
goto detach;
}
client->syncpts[0] = host1x_syncpt_request(client, 0);
if (!client->syncpts[0]) {
err = -ENOMEM;
goto free_channel;
}
err = tegra_drm_register_client(tegra, drm);
if (err < 0)
goto detach;
goto free_syncpt;
/*
* Inherit the DMA parameters (such as maximum segment size) from the
@@ -61,6 +154,10 @@ static int nvjpg_init(struct host1x_client *client)
return 0;
free_syncpt:
host1x_syncpt_put(client->syncpts[0]);
free_channel:
host1x_channel_put(nvjpg->channel);
detach:
host1x_client_iommu_detach(client);
@@ -85,8 +182,12 @@ static int nvjpg_exit(struct host1x_client *client)
pm_runtime_dont_use_autosuspend(client->dev);
pm_runtime_force_suspend(client->dev);
host1x_syncpt_put(client->syncpts[0]);
host1x_channel_put(nvjpg->channel);
host1x_client_iommu_detach(client);
nvjpg->channel = NULL;
if (client->group) {
dma_unmap_single(nvjpg->dev, nvjpg->falcon.firmware.phys,
nvjpg->falcon.firmware.size, DMA_TO_DEVICE);
@@ -170,6 +271,34 @@ cleanup:
return err;
}
static int nvjpg_boot_falcon(struct nvjpg *nvjpg)
{
u32 stream_id;
int err;
if (nvjpg->config->supports_sid && tegra_dev_iommu_get_stream_id(nvjpg->dev, &stream_id)) {
u32 value;
value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW);
nvjpg_writel(nvjpg, value, NVJPG_TFBIF_TRANSCFG);
nvjpg_writel(nvjpg, stream_id, VIC_THI_STREAMID0);
nvjpg_writel(nvjpg, stream_id, VIC_THI_STREAMID1);
}
err = falcon_boot(&nvjpg->falcon);
if (err < 0)
return err;
err = falcon_wait_idle(&nvjpg->falcon);
if (err < 0) {
dev_err(nvjpg->dev, "falcon boot timed out\n");
return err;
}
return 0;
}
static __maybe_unused int nvjpg_runtime_resume(struct device *dev)
{
struct nvjpg *nvjpg = dev_get_drvdata(dev);
@@ -185,10 +314,16 @@ static __maybe_unused int nvjpg_runtime_resume(struct device *dev)
if (err < 0)
goto disable_clk;
err = falcon_boot(&nvjpg->falcon);
err = nvjpg_boot_falcon(nvjpg);
if (err < 0)
goto disable_clk;
if (nvjpg->devfreq) {
err = devfreq_resume_device(nvjpg->devfreq);
if (err < 0)
goto disable_clk;
}
return 0;
disable_clk:
@@ -199,21 +334,50 @@ disable_clk:
static __maybe_unused int nvjpg_runtime_suspend(struct device *dev)
{
struct nvjpg *nvjpg = dev_get_drvdata(dev);
int err;
if (nvjpg->devfreq) {
err = devfreq_suspend_device(nvjpg->devfreq);
if (err < 0)
return err;
}
host1x_channel_stop(nvjpg->channel);
clk_disable_unprepare(nvjpg->clk);
return 0;
}
static int nvjpg_open_channel(struct tegra_drm_client *client,
struct tegra_drm_context *context)
{
struct nvjpg *nvjpg = to_nvjpg(client);
context->channel = host1x_channel_get(nvjpg->channel);
if (!context->channel)
return -ENOMEM;
return 0;
}
static void nvjpg_close_channel(struct tegra_drm_context *context)
{
host1x_channel_put(context->channel);
}
static int nvjpg_can_use_memory_ctx(struct tegra_drm_client *client, bool *supported)
{
*supported = false;
*supported = true;
return 0;
}
static const struct tegra_drm_client_ops nvjpg_ops = {
.get_streamid_offset = NULL,
.open_channel = nvjpg_open_channel,
.close_channel = nvjpg_close_channel,
.submit = tegra_drm_submit,
.get_streamid_offset = tegra_drm_get_streamid_offset_thi,
.can_use_memory_ctx = nvjpg_can_use_memory_ctx,
};
@@ -222,10 +386,38 @@ static const struct tegra_drm_client_ops nvjpg_ops = {
static const struct nvjpg_config tegra210_nvjpg_config = {
.firmware = NVIDIA_TEGRA_210_NVJPG_FIRMWARE,
.version = 0x21,
.supports_sid = false,
};
#define NVIDIA_TEGRA_186_NVJPG_FIRMWARE "nvidia/tegra186/nvjpg.bin"
static const struct nvjpg_config tegra186_nvjpg_config = {
.firmware = NVIDIA_TEGRA_186_NVJPG_FIRMWARE,
.version = 0x18,
.supports_sid = true,
};
#define NVIDIA_TEGRA_194_NVJPG_FIRMWARE "nvidia/tegra194/nvjpg.bin"
static const struct nvjpg_config tegra194_nvjpg_config = {
.firmware = NVIDIA_TEGRA_194_NVJPG_FIRMWARE,
.version = 0x19,
.supports_sid = true,
};
#define NVIDIA_TEGRA_234_NVJPG_FIRMWARE "nvidia/tegra234/nvjpg.bin"
static const struct nvjpg_config tegra234_nvjpg_config = {
.firmware = NVIDIA_TEGRA_234_NVJPG_FIRMWARE,
.version = 0x23,
.supports_sid = true,
};
static const struct of_device_id tegra_nvjpg_of_match[] = {
{ .compatible = "nvidia,tegra210-nvjpg", .data = &tegra210_nvjpg_config },
{ .compatible = "nvidia,tegra186-nvjpg", .data = &tegra186_nvjpg_config },
{ .compatible = "nvidia,tegra194-nvjpg", .data = &tegra194_nvjpg_config },
{ .compatible = "nvidia,tegra234-nvjpg", .data = &tegra234_nvjpg_config },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_nvjpg_of_match);
@@ -233,7 +425,9 @@ MODULE_DEVICE_TABLE(of, tegra_nvjpg_of_match);
static int nvjpg_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct host1x_syncpt **syncpts;
struct nvjpg *nvjpg;
u32 host_class;
int err;
/* inherit DMA mask from host1x parent */
@@ -249,6 +443,10 @@ static int nvjpg_probe(struct platform_device *pdev)
nvjpg->config = of_device_get_match_data(dev);
syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL);
if (!syncpts)
return -ENOMEM;
nvjpg->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(nvjpg->regs))
return PTR_ERR(nvjpg->regs);
@@ -272,12 +470,18 @@ static int nvjpg_probe(struct platform_device *pdev)
if (err < 0)
return err;
err = of_property_read_u32(dev->of_node, "nvidia,host1x-class", &host_class);
if (err < 0)
host_class = HOST1X_CLASS_NVJPG;
platform_set_drvdata(pdev, nvjpg);
INIT_LIST_HEAD(&nvjpg->client.base.list);
nvjpg->client.base.ops = &nvjpg_client_ops;
nvjpg->client.base.dev = dev;
nvjpg->client.base.class = HOST1X_CLASS_NVJPG;
nvjpg->client.base.class = host_class;
nvjpg->client.base.syncpts = syncpts;
nvjpg->client.base.num_syncpts = 1;
nvjpg->dev = dev;
INIT_LIST_HEAD(&nvjpg->client.list);
@@ -290,12 +494,20 @@ static int nvjpg_probe(struct platform_device *pdev)
goto exit_falcon;
}
err = nvjpg_devfreq_init(nvjpg);
if (err < 0) {
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
goto unregister_client;
}
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 500);
devm_pm_runtime_enable(dev);
return 0;
unregister_client:
host1x_client_unregister(&nvjpg->client.base);
exit_falcon:
falcon_exit(&nvjpg->falcon);
@@ -328,3 +540,12 @@ struct platform_driver tegra_nvjpg_driver = {
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_210_NVJPG_FIRMWARE);
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_186_NVJPG_FIRMWARE);
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_194_NVJPG_FIRMWARE);
#endif
#if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
MODULE_FIRMWARE(NVIDIA_TEGRA_234_NVJPG_FIRMWARE);
#endif
+142 -9
View File
@@ -18,6 +18,117 @@
#include <media/cec-notifier.h>
static ssize_t state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
struct notify_dev *sdev = (struct notify_dev *)
dev_get_drvdata(dev);
if (sdev->print_state) {
ret = sdev->print_state(sdev, buf);
if (ret >= 0)
return ret;
}
return sprintf(buf, "%d\n", sdev->state);
}
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int ret;
struct notify_dev *sdev = (struct notify_dev *)
dev_get_drvdata(dev);
if (sdev->print_name) {
ret = sdev->print_name(sdev, buf);
if (ret >= 0)
return ret;
}
return sprintf(buf, "%s\n", sdev->name);
}
static DEVICE_ATTR_RO(state);
static DEVICE_ATTR_RO(name);
static int create_switch_class(struct class **switch_class, atomic_t *switch_count)
{
if (!*switch_class) {
*switch_class = class_create("switch");
if (IS_ERR(*switch_class))
return PTR_ERR(*switch_class);
atomic_set(switch_count, 0);
}
return 0;
}
static int disp_uevent_dev_register(struct notify_dev *sdev, struct class **switch_class, atomic_t *switch_count)
{
int ret;
if (!*switch_class) {
ret = create_switch_class(switch_class, switch_count);
if (ret != 0)
return ret;
}
sdev->index = atomic_inc_return(switch_count);
sdev->dev = device_create(*switch_class, NULL,
MKDEV(0, sdev->index), NULL, sdev->name);
if (IS_ERR(sdev->dev))
return PTR_ERR(sdev->dev);
ret = device_create_file(sdev->dev, &dev_attr_state);
if (ret < 0)
goto err_create_file_1;
ret = device_create_file(sdev->dev, &dev_attr_name);
if (ret < 0)
goto err_create_file_2;
dev_set_drvdata(sdev->dev, sdev);
sdev->state = 0;
return 0;
err_create_file_2:
device_remove_file(sdev->dev, &dev_attr_state);
err_create_file_1:
device_destroy(*switch_class, MKDEV(0, sdev->index));
printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name);
return ret;
}
static void disp_uevent_dev_unregister(struct notify_dev *sdev, struct class *switch_class)
{
device_remove_file(sdev->dev, &dev_attr_name);
device_remove_file(sdev->dev, &dev_attr_state);
device_destroy(switch_class, MKDEV(0, sdev->index));
dev_set_drvdata(sdev->dev, NULL);
}
static int notify_uevent_user(struct notify_dev *sdev, int state)
{
char *envp[3];
char name_buf[120];
char state_buf[120];
if (sdev == NULL)
return -1;
if (sdev->state != state)
sdev->state = state;
snprintf(name_buf, sizeof(name_buf), "SWITCH_NAME=%s", sdev->name);
envp[0] = name_buf;
snprintf(state_buf, sizeof(state_buf), "SWITCH_STATE=%d", sdev->state);
envp[1] = state_buf;
envp[2] = NULL;
kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp);
return 0;
}
int tegra_output_connector_get_modes(struct drm_connector *connector)
{
struct tegra_output *output = connector_to_output(connector);
@@ -88,9 +199,14 @@ static irqreturn_t hpd_irq(int irq, void *data)
{
struct tegra_output *output = data;
if (output->connector.dev)
if (output->connector.dev) {
drm_helper_hpd_irq_event(output->connector.dev);
if (output->connector.connector_type == DRM_MODE_CONNECTOR_HDMIA ||
output->connector.connector_type == DRM_MODE_CONNECTOR_HDMIB)
notify_uevent_user(&output->notify_data, (output->connector.status == connector_status_connected ? 1 : 0));
}
return IRQ_HANDLED;
}
@@ -207,13 +323,7 @@ void tegra_output_remove(struct tegra_output *output)
int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
{
int connector_type;
/*
* The connector is now registered and ready to receive hotplug events
* so the hotplug interrupt can be enabled.
*/
if (output->hpd_gpio)
enable_irq(output->hpd_irq);
int err;
connector_type = output->connector.connector_type;
/*
@@ -228,8 +338,29 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
&conn_info);
if (!output->cec)
return -ENOMEM;
if (output->hpd_gpio) {
output->notify_data.name = "hdmi"; // now hwc not support DP
output->notify_data.index = 0;
output->notify_data.state = 0;
err = disp_uevent_dev_register(&output->notify_data, &output->switch_class, &output->switch_count);
if (err < 0) {
dev_err(output->dev, "switch_dev_register failed: %d\n", err);
return err;
}
if (tegra_output_connector_detect(&output->connector, false) == connector_status_connected)
notify_uevent_user(&output->notify_data, 1);
}
}
/*
* The connector is now registered and ready to receive hotplug events
* so the hotplug interrupt can be enabled.
*/
if (output->hpd_gpio)
enable_irq(output->hpd_irq);
return 0;
}
@@ -239,8 +370,10 @@ void tegra_output_exit(struct tegra_output *output)
* The connector is going away, so the interrupt must be disabled to
* prevent the hotplug interrupt handler from potentially crashing.
*/
if (output->hpd_gpio)
if (output->hpd_gpio) {
disable_irq(output->hpd_irq);
disp_uevent_dev_unregister(&output->notify_data, output->switch_class);
}
}
void tegra_output_find_possible_crtcs(struct tegra_output *output,
+48 -4
View File
@@ -55,7 +55,6 @@ struct tegra_sor_hdmi_settings {
u8 preemphasis[4];
};
#if 1
static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
{
.frequency = 54000000,
@@ -134,8 +133,8 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
.preemphasis = { 0x00, 0x00, 0x00, 0x00 },
},
};
#else
static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_odin[] = {
{
.frequency = 75000000,
.vcocap = 0x3,
@@ -198,7 +197,6 @@ static const struct tegra_sor_hdmi_settings tegra210_sor_hdmi_defaults[] = {
.preemphasis = { 0x02, 0x3f, 0x3f, 0x3f },
},
};
#endif
static const struct tegra_sor_hdmi_settings tegra186_sor_hdmi_defaults[] = {
{
@@ -2557,6 +2555,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
value &= ~DITHER_CONTROL_MASK;
value &= ~BASE_COLOR_SIZE_MASK;
if (dc->soc->has_nvdisplay) {
tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
value |= CMU_ENABLE_ENABLE;
}
switch (state->bpc) {
case 6:
@@ -2921,6 +2930,20 @@ static void tegra_sor_dp_enable(struct drm_encoder *encoder)
if (err < 0)
dev_err(sor->dev, "failed to attach SOR: %d\n", err);
if (dc->soc->has_nvdisplay) {
value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
tegra_dc_writel(dc, lower_32_bits(dc->cmu_output_lut_phys),
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
tegra_dc_writel(dc, upper_32_bits(dc->cmu_output_lut_phys),
DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
value |= CMU_ENABLE_ENABLE;
tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
}
value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
value |= SOR_ENABLE(sor->index);
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
@@ -3508,6 +3531,26 @@ static const struct tegra_sor_soc tegra210_sor1 = {
.tx_pu = tegra124_sor_tx_pu,
};
static const struct tegra_sor_soc tegra210_sor1_odin = {
.supports_lvds = false,
.supports_hdmi = true,
.supports_dp = true,
.supports_audio = true,
.supports_hdcp = true,
.regs = &tegra210_sor_regs,
.has_nvdisplay = false,
.num_settings = ARRAY_SIZE(tegra210_sor_hdmi_odin),
.settings = tegra210_sor_hdmi_odin,
.xbar_cfg = tegra210_sor_xbar_cfg,
.lane_map = tegra210_sor_lane_map,
.voltage_swing = tegra124_sor_voltage_swing,
.pre_emphasis = tegra124_sor_pre_emphasis,
.post_cursor = tegra124_sor_post_cursor,
.tx_pu = tegra124_sor_tx_pu,
};
static const struct tegra_sor_regs tegra186_sor_regs = {
.head_state0 = 0x151,
.head_state1 = 0x154,
@@ -3631,6 +3674,7 @@ static const struct of_device_id tegra_sor_of_match[] = {
{ .compatible = "nvidia,tegra194-sor", .data = &tegra194_sor },
{ .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor },
{ .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 },
{ .compatible = "nvidia,tegra210-sor1-odin", .data = &tegra210_sor1_odin },
{ .compatible = "nvidia,tegra210-sor", .data = &tegra210_sor },
{ .compatible = "nvidia,tegra132-sor", .data = &tegra132_sor },
{ .compatible = "nvidia,tegra124-sor", .data = &tegra124_sor },
+90
View File
@@ -5,6 +5,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/devfreq.h>
#include <linux/dma-mapping.h>
#include <linux/host1x.h>
#include <linux/iommu.h>
@@ -35,6 +36,7 @@ struct vic {
struct device *dev;
struct clk *clk;
struct reset_control *rst;
struct devfreq *devfreq;
bool can_use_context;
@@ -52,6 +54,74 @@ static void vic_writel(struct vic *vic, u32 value, unsigned int offset)
writel(value, vic->regs + offset);
}
static int vic_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct vic *vic = dev_get_drvdata(dev);
int err;
err = clk_set_rate(vic->clk, *freq);
if (err < 0)
return err;
*freq = clk_get_rate(vic->clk);
return 0;
}
static int vic_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct vic *vic = dev_get_drvdata(dev);
*freq = clk_get_rate(vic->clk);
return 0;
}
static struct devfreq_dev_profile vic_devfreq_profile = {
.polling_ms = 50,
.target = vic_devfreq_target,
.get_cur_freq = vic_devfreq_get_cur_freq,
};
static int vic_devfreq_init(struct vic *vic)
{
unsigned long max_rate = clk_round_rate(vic->clk, ULONG_MAX);
unsigned long min_rate = clk_round_rate(vic->clk, 0);
unsigned long margin = clk_round_rate(vic->clk, min_rate + 1) - min_rate;
unsigned long rate = min_rate;
unsigned int hw_rates = ((max_rate - min_rate) / margin) + 1;
struct devfreq *devfreq;
if (min_rate == max_rate) {
dev_info(vic->dev, "Only one supported clock rate, disabling devfreq\n");
return 0;
}
// Only allow up to 20 rates
if (hw_rates > 20)
margin *= DIV_ROUND_UP(hw_rates, 20);
while (rate < max_rate) {
dev_pm_opp_add(vic->dev, rate, 0);
rate += margin;
}
// The margin step may not fall on max rate exactly, so add max rate explicitly
dev_pm_opp_add(vic->dev, max_rate, 0);
devfreq = devm_devfreq_add_device(vic->dev,
&vic_devfreq_profile,
DEVFREQ_GOV_USERSPACE,
NULL);
if (IS_ERR(devfreq))
return PTR_ERR(devfreq);
vic->devfreq = devfreq;
return 0;
}
static int vic_boot(struct vic *vic)
{
u32 fce_ucode_size, fce_bin_data_offset, stream_id;
@@ -328,6 +398,12 @@ static int __maybe_unused vic_runtime_resume(struct device *dev)
if (err < 0)
goto assert;
if (vic->devfreq) {
err = devfreq_resume_device(vic->devfreq);
if (err < 0)
goto assert;
}
return 0;
assert:
@@ -342,6 +418,12 @@ static int __maybe_unused vic_runtime_suspend(struct device *dev)
struct vic *vic = dev_get_drvdata(dev);
int err;
if (vic->devfreq) {
err = devfreq_suspend_device(vic->devfreq);
if (err < 0)
return err;
}
host1x_channel_stop(vic->channel);
err = reset_control_assert(vic->rst);
@@ -520,12 +602,20 @@ static int vic_probe(struct platform_device *pdev)
goto exit_falcon;
}
err = vic_devfreq_init(vic);
if (err < 0) {
dev_err(&pdev->dev, "failed to init devfreq: %d\n", err);
goto unregister_client;
}
pm_runtime_enable(dev);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 500);
return 0;
unregister_client:
host1x_client_unregister(&vic->client.base);
exit_falcon:
falcon_exit(&vic->falcon);
+3
View File
@@ -97,6 +97,9 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
bus = of_node_get(adap->dev.of_node);
for_each_available_child_of_node(bus, node) {
if (!strcmp(node->name, "prod-settings"))
continue;
if (of_node_test_and_set_flag(node, OF_POPULATED))
continue;
+1
View File
@@ -11,6 +11,7 @@ menuconfig INPUT_TOUCHSCREEN
If unsure, say Y.
if INPUT_TOUCHSCREEN
source "drivers/input/touchscreen/stm/Kconfig"
config TOUCHSCREEN_88PM860X
tristate "Marvell 88PM860x touchscreen"
+1
View File
@@ -119,3 +119,4 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o
obj-$(CONFIG_TOUCHSCREEN_IQS7211) += iqs7211.o
obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o
obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o
obj-$(CONFIG_TOUCHSCREEN_FTM4) += stm/
+19
View File
@@ -0,0 +1,19 @@
#
# STMicroelectronics TOUCH driver configuration
#
config TOUCHSCREEN_FTM4
tristate "STMicroelectronics i2c multitouch touchscreen - FTM4 with FingerTipS"
depends on I2C
help
Say Y here to enable STMicroelectronics touchscreen support.
If unsure, say N.
To compile this driver as a module, choose M here: the module
will be called fts_touch.
config TOUCHSCREEN_FTM4_SHOW_EVENTS
bool "Enable debug of FTM4 events"
depends on TOUCHSCREEN_FTM4
help
Say Y here to enable dumping of touch driver events. This should
only be enabled for debugging and not for shipping code.
+3
View File
@@ -0,0 +1,3 @@
# FTM4 driver
obj-$(CONFIG_TOUCHSCREEN_FTM4) += ftm4.o
ftm4-objs += ftm4_ts.o
File diff suppressed because it is too large. Load diff
+374
View File
@@ -0,0 +1,374 @@
/******************************** FingerTipS 4CD60D ****************************
*
* File Name : fts.c
* Authors : Copyright (c) 2012 STMicroelectronics, Analog Mems Sensor Team
* Copyright (c) 2019-2020 Billy Laws <blaws05@gmail.com>
* Copyright (c) 2019-2021 Kostas Missos <ctcaer@gmail.com>
* Description : FTS Capacitive touch screen controller (FingerTipS)
*
********************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
*******************************************************************************/
#ifndef _LINUX_FTM4_TS_H_
#define _LINUX_FTM4_TS_H_
#include <linux/device.h>
#include <linux/atomic.h>
#include <linux/printk.h>
#define tsp_debug_dbg(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
#define tsp_debug_info(dev, fmt, ...) dev_info(dev, fmt, ## __VA_ARGS__)
#define tsp_debug_err(dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__)
#ifdef CONFIG_TOUCHSCREEN_FTM4_SHOW_EVENTS
#define tsp_debug_event(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
#else
#define tsp_debug_event(dev, fmt, ...)
#endif
#define FTS_INPUT_OPEN_DWORK_TIME 10
#define FTS_TS_DRV_NAME "fts_touch"
#define FTS_TS_DRV_VERSION "4CD60D"
#define STM_DEVICE_NAME "STM"
#define FTS_ID0 0x36
#define FTS_ID1 0x70
#define FTS_DIGITAL_REV_1 0x01
#define FTS_DIGITAL_REV_2 0x02
#define FTS_FIFO_MAX 32
#define FTS_EVENT_SIZE 8
#define FTS_FW_UPDATE_RETRY 3
#define FTS_LOCKDOWNCODE_SIZE 13
#define PRESSURE_MIN 0
#define PRESSURE_MAX 500
#define FINGER_MAX 10
#define EVENTID_NO_EVENT 0x00
#define EVENTID_ENTER_POINTER 0x03
#define EVENTID_LEAVE_POINTER 0x04
#define EVENTID_HOS_EVENT 0x04
#define EVENTID_MOTION_POINTER 0x05
#define EVENTID_HOVER_ENTER_POINTER 0x07
#define EVENTID_HOVER_LEAVE_POINTER 0x08
#define EVENTID_MOTION_POINTER 0x05
#define EVENTID_HOVER_MOTION_POINTER 0x09
#define EVENTID_PROXIMITY_IN 0x0B
#define EVENTID_PROXIMITY_OUT 0x0C
#define EVENTID_MSKEY 0x0E
#define EVENTID_ERROR 0x0F
#define EVENTID_CONTROLLER_READY 0x10
#define EVENTID_SLEEPOUT_CONTROLLER_READY 0x11
#define EVENTID_RESULT_READ_REGISTER 0x12
#define EVENTID_STATUS_REQUEST_COMP 0x13
#define EVENTID_STATUS_EVENT 0x16
#define EVENTID_INTERNAL_RELEASE_INFO 0x14
#define EVENTID_EXTERNAL_RELEASE_INFO 0x15
#define EVENTID_FROM_STRING 0x80
#define EVENTID_GESTURE 0x20
#define EVENTID_SIDE_SCROLL 0x40
/* side touch event-id for debug, remove after f/w fixed */
#define EVENTID_SIDE_TOUCH_DEBUG 0xDB
#define EVENTID_SIDE_TOUCH 0x0B
#define EVENTID_ERROR_FLASH_CORRUPTION 0x03
/* define flash corruption type */
#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_1 0x01
#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_2 0x02
#define EVENTID_ERROR_CX_FLASH_CORRUPTION 0x03
#define EVENTID_LOCKDOWN_CODE 0x1E
#define EVENTID_ERROR_LOCKDOWN 0x0B
#define STATUS_EVENT_MS_CX_TUNING_DONE 0x01
#define STATUS_EVENT_SS_CX_TUNING_DONE 0x02
#define STATUS_EVENT_FLASH_WRITE_CONFIG 0x03
#define STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE 0x04
#define STATUS_EVENT_FORCE_CAL_MUTUAL_SELF 0x05
#define STATUS_EVENT_FORCE_CAL_DONE 0x06
#define STATUS_EVENT_FORCE_CAL_MUTUAL 0x15
#define STATUS_EVENT_FORCE_CAL_SELF 0x06
#define STATUS_EVENT_PARAM1_FCAL_MS_SS_DONE 0x23
#define STATUS_EVENT_WATERMODE_ON 0x07
#define STATUS_EVENT_WATERMODE_OFF 0x08
#define STATUS_EVENT_RTUNE_MUTUAL 0x09
#define STATUS_EVENT_RTUNE_SELF 0x0A
#define STATUS_EVENT_PANEL_TEST_RESULT 0x0B
#define STATUS_EVENT_GLOVE_MODE 0x0C
#define STATUS_EVENT_RAW_DATA_READY 0x0D
#define STATUS_EVENT_MUTUAL_CAL_FRAME_CHECK 0xC1
#define STATUS_EVENT_SELF_CAL_FRAME_CHECK 0xC2
#define STATUS_EVENT_CHARGER_CONNECTED 0xCC
#define STATUS_EVENT_CHARGER_DISCONNECTED 0xCD
#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_WRITE_FINISH 0x10
#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_CLEAR_FINISH 0x11
#define INT_ENABLE 0x48
#define INT_DISABLE 0x08
#define FTS_READ_STATUS 0x84
#define FTS_READ_ONE_EVENT 0x85
#define FTS_READ_ALL_EVENT 0x86
#define FTS_CMD_SENSEOFF 0x92
#define FTS_CMD_SENSEON 0x93
#define FTS_CMD_HOVER_OFF 0x94
#define FTS_CMD_HOVER_ON 0x95
#define FTS_CMD_MSKEY_AUTOTUNE 0x96
#define FTS_CMD_TRIM_LOW_POWER_OSCILLATOR 0x97
#define FTS_CMD_KEY_SENSE_OFF 0x9A
#define FTS_CMD_KEY_SENSE_ON 0x9B
#define FTS_CMD_SET_FAST_GLOVE_MODE 0x9D
#define FTS_CMD_MSHOVER_OFF 0x9E
#define FTS_CMD_MSHOVER_ON 0x9F
#define FTS_CMD_SET_NOR_GLOVE_MODE 0x9F
#define FTS_CMD_FLUSHBUFFER 0xA1
#define FTS_CMD_FORCECALIBRATION 0xA2
#define FTS_CMD_MS_CX_TUNING 0xA3
#define FTS_CMD_SS_CX_TUNING 0xA4
#define FTS_CMD_ITO_CHECK 0xA7
#define FTS_CMD_CHARGER_PLUGGED 0xA8
#define FTS_CMD_CHARGER_UNPLUGGED 0xAB
#define FTS_CMD_RELEASEINFO 0xAA
#define FTS_CMD_STYLUS_OFF 0xAB
#define FTS_CMD_STYLUS_ON 0xAC
#define FTS_CMD_LOWPOWER_MODE 0xAD
#define FTS_CMD_WRITE_REG 0xB6
#define FTS_CMS_ENABLE_FEATURE 0xC1
#define FTS_CMS_DISABLE_FEATURE 0xC2
#define FTS_CMD_SWITCH_SENSE_MODE 0xC3
#define FTS_CMD_LOCKDOWN_READ 0xC4
#define FTS_CMD_WRITE_PRAM 0xF0
#define FTS_CMD_BURN_PROG_FLASH 0xF2
#define FTS_CMD_ERASE_PROG_FLASH 0xF3
#define FTS_CMD_READ_FLASH_STAT 0xF4
#define FTS_CMD_UNLOCK_FLASH 0xF7
#define FTS_CMD_SAVE_FWCONFIG 0xFB
#define FTS_CMD_SAVE_CX_TUNING 0xFC
#define FTS_CMD_FAST_SCAN 0x01
#define FTS_CMD_SLOW_SCAN 0x02
#define FTS_CMD_USLOW_SCAN 0x03
#define FTS_STYLUS_MODE 0x00
#define FTS_FINGER_MODE 0x01
#define FTS_HOVER_MODE 0x02
#define FTS_REPORT_RATE_90HZ 0
#define FTS_REPORT_RATE_60HZ 1
#define FTS_REPORT_RATE_30HZ 2
#define FTS_CMD_STRING_ACCESS 0xEC00
#define FTS_CMD_NOTIFY 0xC0
#define FTS_RETRY_COUNT 10
/* QUICK SHOT : Quick Camera Launching */
#define FTS_STRING_EVENT_REAR_CAM (1 << 0)
#define FTS_STRING_EVENT_FRONT_CAM (1 << 1)
/* SCRUB : Display Watch, Event Status / Fast Access Event */
#define FTS_STRING_EVENT_WATCH_STATUS (1 << 2)
#define FTS_STRING_EVENT_FAST_ACCESS (1 << 3)
#define FTS_STRING_EVENT_DIRECT_INDICATOR ((1 << 3) | (1 << 2))
#define FTS_STRING_EVENT_SPAY (1 << 4)
#define FTS_STRING_EVENT_SPAY1 (1 << 5)
#define FTS_STRING_EVENT_SPAY2 ((1 << 4) | (1 << 5))
#define FTS_SIDEGESTURE_EVENT_SINGLE_STROKE 0xE0
#define FTS_SIDEGESTURE_EVENT_DOUBLE_STROKE 0xE1
#define FTS_SIDEGESTURE_EVENT_INNER_STROKE 0xE3
#define FTS_SIDETOUCH_EVENT_LONG_PRESS 0xBB
#define FTS_SIDETOUCH_EVENT_REBOOT_BY_ESD 0xED
#define FTS_ENABLE 1
#define FTS_DISABLE 0
#define FTS_MODE_QUICK_SHOT (1 << 0)
#define FTS_MODE_SCRUB (1 << 1)
#define FTS_MODE_SPAY (1 << 1)
#define FTS_MODE_QUICK_APP_ACCESS (1 << 2)
#define FTS_MODE_DIRECT_INDICATOR (1 << 3)
#define TSP_BUF_SIZE 2048
#define CMD_STR_LEN 32
#define CMD_RESULT_STR_LEN 2048
#define CMD_PARAM_NUM 8
#define FTS_LOWP_FLAG_QUICK_CAM (1 << 0)
#define FTS_LOWP_FLAG_2ND_SCREEN (1 << 1)
#define FTS_LOWP_FLAG_BLACK_UI (1 << 2)
#define FTS_LOWP_FLAG_QUICK_APP_ACCESS (1 << 3)
#define FTS_LOWP_FLAG_DIRECT_INDICATOR (1 << 4)
#define FTS_LOWP_FLAG_SPAY (1 << 5)
#define FTS_LOWP_FLAG_TEMP_CMD (1 << 6)
enum fts_error_return {
FTS_NOT_ERROR = 0,
FTS_ERROR_INVALID_CHIP_ID,
FTS_ERROR_INVALID_CHIP_VERSION_ID,
FTS_ERROR_INVALID_SW_VERSION,
FTS_ERROR_EVENT_ID,
FTS_ERROR_TIMEOUT,
FTS_ERROR_FW_UPDATE_FAIL,
};
#define RAW_MAX 3750
/**
* struct fts_finger - Represents fingers.
* @ state: finger status (Event ID).
* @ mcount: moving counter for debug.
*/
struct fts_finger {
unsigned char state;
int lx;
int ly;
};
enum tsp_power_mode {
FTS_POWER_STATE_ACTIVE = 0,
FTS_POWER_STATE_POWERDOWN,
};
enum fts_customer_feature {
FTS_FEATURE_ORIENTATION_GESTURE = 1,
FTS_FEATURE_STYLUS,
FTS_FEATURE_QUICK_SHORT_CAMERA_ACCESS,
FTS_FEATURE_SIDE_GUSTURE,
FTS_FEATURE_COVER_GLASS,
FTS_FEATURE_COVER_WALLET,
FTS_FEATURE_COVER_LED,
FTS_FEATURE_COVER_CLEAR_FLIP,
FTS_FEATURE_DUAL_SIDE_GUSTURE,
FTS_FEATURE_CUSTOM_COVER_GLASS_ON,
};
struct fts_flash_corruption_info {
bool fw_broken;
bool cfg_broken;
bool cx_broken;
};
struct fts_i2c_platform_data {
bool disable_tuning;
bool delayed_open;
unsigned int delayed_open_time;
int max_x;
int max_y;
struct regulator *regulator_dvdd;
struct regulator *regulator_avdd;
int (*power)(void *data, bool on);
unsigned gpio;
int vdd_gpio;
int vio_gpio;
int irq_type;
int coord_factor;
int x_axis_real_max;
int y_axis_real_max;
int x_axis_edge_offset;
int y_axis_edge_offset;
};
struct fts_ts_info {
struct device *dev;
struct i2c_client *client;
struct input_dev *input_dev;
struct work_struct work;
int irq;
int irq_type;
atomic_t irq_enabled;
struct fts_i2c_platform_data *board;
bool run_autotune;
int power_state;
int touch_count;
struct fts_finger finger[FINGER_MAX];
bool palm_pressed;
int palm_touch_id;
int touch_mode;
struct delayed_work open_work;
struct mutex i2c_mutex;
struct mutex device_mutex;
spinlock_t lock;
unsigned char data[FTS_EVENT_SIZE * FTS_FIFO_MAX];
struct fts_flash_corruption_info flash_corruption_info;
};
#define WRITE_CHUNK_SIZE 32
#define FLASH_CHUNK (64 * 1024)
#define DMA_CHUNK 32
#define FW_HEADER_SIZE 64
#define FW_HEADER_FTB_SIGNATURE 0xAA55AA55
#define FW_FTB_VER 0x00000001
#define FW_BYTES_ALLIGN 4
#define FW_BIN_VER_OFFSET 16
#define FW_BIN_CONFIG_VER_OFFSET 20
/* Command for flash */
#define FLASH_CMD_UNLOCK 0xF7
#define FLASH_CMD_WRITE_64K 0xF8
#define FLASH_CMD_READ_REGISTER 0xF9
#define FLASH_CMD_WRITE_REGISTER 0xFA
/* Parameters for commands */
#define ADDR_WARM_BOOT 0x001E
#define WARM_BOOT_VALUE 0x38
#define FLASH_ADDR_CODE 0x00000000
#define FLASH_ADDR_CONFIG 0x0000FC00
#define FLASH_UNLOCK_CODE0 0x74
#define FLASH_UNLOCK_CODE1 0x45
#define FLASH_ERASE_UNLOCK_CODE0 0x72
#define FLASH_ERASE_UNLOCK_CODE1 0x03
#define FLASH_ERASE_UNLOCK_CODE2 0x02
#define FLASH_ERASE_CODE0 0x02
#define FLASH_ERASE_CODE1 0xC0
#define FLASH_DMA_CODE0 0x05
#define FLASH_DMA_CODE1 0xC0
#define FLASH_DMA_CONFIG 0x06
#endif /* _LINUX_FTM4_TS_H_ */
+1
View File
@@ -55,6 +55,7 @@ config TEGRA210_EMC
tristate "NVIDIA Tegra210 External Memory Controller driver"
depends on ARCH_TEGRA_210_SOC || COMPILE_TEST
select TEGRA210_EMC_TABLE
select PM_OPP
help
This driver is for the External Memory Controller (EMC) found on
Tegra210 chips. The EMC controls the external DRAM on the board.
+8
View File
@@ -541,6 +541,14 @@ int tegra30_mc_probe(struct tegra_mc *mc)
if (err < 0)
return dev_err_probe(mc->dev, err, "failed to setup timings\n");
err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
if (err < 0)
return err;
err = of_platform_populate(mc->dev->of_node, NULL, NULL, mc->dev);
if (err < 0)
return err;
return 0;
}
+135 -2
View File
@@ -18,6 +18,17 @@ struct tegra186_emc_dvfs {
unsigned long rate;
};
enum emc_rate_request_type {
EMC_RATE_DEBUG,
EMC_RATE_ICC,
EMC_RATE_TYPE_MAX,
};
struct emc_rate_request {
unsigned long min_rate;
unsigned long max_rate;
};
struct tegra186_emc {
struct tegra_bpmp *bpmp;
struct device *dev;
@@ -34,8 +45,90 @@ struct tegra186_emc {
} debugfs;
struct icc_provider provider;
/*
* There are multiple sources in the EMC driver which could request
* a min/max clock rate, these rates are contained in this array.
*/
struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
/* protect shared rate-change code path */
struct mutex rate_lock;
};
static void tegra186_emc_rate_requests_init(struct tegra186_emc *emc)
{
unsigned int i;
for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
emc->requested_rate[i].min_rate = 0;
emc->requested_rate[i].max_rate = ULONG_MAX;
}
}
static int emc_request_rate(struct tegra186_emc *emc,
unsigned long new_min_rate,
unsigned long new_max_rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = emc->requested_rate;
unsigned long min_rate = 0, max_rate = ULONG_MAX;
unsigned int i;
int err;
/* select minimum and maximum rates among the requested rates */
for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
if (i == type) {
min_rate = max(new_min_rate, min_rate);
max_rate = min(new_max_rate, max_rate);
} else {
min_rate = max(req->min_rate, min_rate);
max_rate = min(req->max_rate, max_rate);
}
}
if (min_rate > max_rate) {
dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
__func__, type, min_rate, max_rate);
return -ERANGE;
}
err = clk_set_rate(emc->clk, min_rate);
if (err)
return err;
emc->requested_rate[type].min_rate = new_min_rate;
emc->requested_rate[type].max_rate = new_max_rate;
return 0;
}
static int emc_set_min_rate(struct tegra186_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, rate, req->max_rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
static int emc_set_max_rate(struct tegra186_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, req->min_rate, rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
/*
* debugfs interface
*
@@ -108,7 +201,7 @@ static int tegra186_emc_debug_min_rate_set(void *data, u64 rate)
if (!tegra186_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_min_rate(emc->clk, rate);
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -138,7 +231,7 @@ static int tegra186_emc_debug_max_rate_set(void *data, u64 rate)
if (!tegra186_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_max_rate(emc->clk, rate);
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -218,6 +311,12 @@ static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc *emc)
return 0;
}
static inline struct tegra186_emc *
to_tegra186_emc_provider(struct icc_provider *provider)
{
return container_of(provider, struct tegra186_emc, provider);
}
/*
* tegra186_emc_icc_set_bw() - Set BW api for EMC provider
* @src: ICC node for External Memory Controller (EMC)
@@ -228,6 +327,33 @@ static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc *emc)
*/
static int tegra186_emc_icc_set_bw(struct icc_node *src, struct icc_node *dst)
{
struct tegra186_emc *emc = to_tegra186_emc_provider(dst->provider);
struct tegra_mc *mc = dev_get_drvdata(emc->dev->parent);
unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
unsigned long long rate = max(avg_bw, peak_bw);
const unsigned int ddr = 2;
int err;
/*
* Do nothing here if bwmgr is supported in BPMP-FW. BPMP-FW sets the final
* Freq based on the passed values.
*/
if (mc->bwmgr_mrq_supported)
return 0;
/*
* Tegra186 EMC runs on a clock rate of SDRAM bus. This means that
* EMC clock rate is twice smaller than the peak data rate because
* data is sampled on both EMC clock edges.
*/
do_div(rate, ddr);
rate = min_t(u64, rate, U32_MAX);
err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
if (err)
return err;
return 0;
}
@@ -317,6 +443,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
if (!emc)
return -ENOMEM;
mutex_init(&emc->rate_lock);
emc->bpmp = tegra_bpmp_get(&pdev->dev);
if (IS_ERR(emc->bpmp))
return dev_err_probe(&pdev->dev, PTR_ERR(emc->bpmp),
@@ -339,6 +467,8 @@ static int tegra186_emc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, emc);
emc->dev = &pdev->dev;
tegra186_emc_rate_requests_init(emc);
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_EMC_DVFS_LATENCY)) {
err = tegra186_emc_get_emc_dvfs_latency(emc);
if (err)
@@ -393,6 +523,9 @@ static const struct of_device_id tegra186_emc_of_match[] = {
#if defined(CONFIG_ARCH_TEGRA_186_SOC)
{ .compatible = "nvidia,tegra186-emc" },
#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210b01-emc" },
#endif
#if defined(CONFIG_ARCH_TEGRA_194_SOC)
{ .compatible = "nvidia,tegra194-emc" },
#endif
+102
View File
@@ -898,6 +898,14 @@ static const struct tegra_mc_client tegra186_mc_clients[] = {
.security = 0x51c,
},
},
}, {
.id = TEGRA_ICC_MC_CPU_CLUSTER0,
.name = "sw_cluster0",
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA_ICC_MC_CPU_CLUSTER1,
.name = "sw_cluster1",
.type = TEGRA_ICC_NISO,
},
};
@@ -910,6 +918,99 @@ static const struct tegra_mc_intmask tegra186_mc_intmasks[] = {
},
};
static int tegra186_mc_icc_set(struct icc_node *src, struct icc_node *dst)
{
/* TODO: program PTSA */
return 0;
}
static int tegra186_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
struct icc_provider *p = node->provider;
struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
node->id == TEGRA_ICC_MC_CPU_CLUSTER1) {
if (mc)
peak_bw = peak_bw * mc->num_channels;
}
/*
* ISO clients need to reserve extra bandwidth up-front because
* there could be high bandwidth pressure during initial filling
* of the client's FIFO buffers. Secondly, we need to take into
* account impurities of the memory subsystem.
*/
if (tag & TEGRA_MC_ICC_TAG_ISO)
peak_bw = tegra_mc_scale_percents(peak_bw, 400);
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
static int tegra186_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
{
*avg = 0;
*peak = 0;
return 0;
}
static struct icc_node_data *
tegra186_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
{
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
const struct tegra_mc_client *client;
unsigned int i, idx = spec->args[0];
struct icc_node_data *ndata;
struct icc_node *node;
list_for_each_entry(node, &mc->provider.nodes, node_list) {
if (node->id != idx)
continue;
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
if (!ndata)
return ERR_PTR(-ENOMEM);
client = &mc->soc->clients[idx];
ndata->node = node;
switch (client->sid) {
case TEGRA186_SID_NVDISPLAY:
case TEGRA186_SID_VI:
/* these clients are isochronous by default */
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
break;
default:
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
break;
}
return ndata;
}
for (i = 0; i < mc->soc->num_clients; i++) {
if (mc->soc->clients[i].id == idx)
return ERR_PTR(-EPROBE_DEFER);
}
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
return ERR_PTR(-EINVAL);
}
static const struct tegra_mc_icc_ops tegra186_mc_icc_ops = {
.xlate_extended = tegra186_mc_of_icc_xlate_extended,
.aggregate = tegra186_mc_icc_aggregate,
.get_bw = tegra186_mc_icc_get_init_bw,
.set = tegra186_mc_icc_set,
};
const struct tegra_mc_soc tegra186_mc_soc = {
.num_clients = ARRAY_SIZE(tegra186_mc_clients),
.clients = tegra186_mc_clients,
@@ -919,6 +1020,7 @@ const struct tegra_mc_soc tegra186_mc_soc = {
.intmasks = tegra186_mc_intmasks,
.num_intmasks = ARRAY_SIZE(tegra186_mc_intmasks),
.ops = &tegra186_mc_ops,
.icc_ops = &tegra186_mc_icc_ops,
.ch_intmask = 0x0000000f,
.global_intstatus_channel_shift = 0,
.regs = &tegra20_mc_regs,
+105 -1
View File
@@ -3,6 +3,8 @@
* Copyright (C) 2017-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/dev_printk.h>
#include <linux/of.h>
#include <soc/tegra/mc.h>
#include <dt-bindings/memory/tegra194-mc.h>
@@ -1340,6 +1342,22 @@ static const struct tegra_mc_client tegra194_mc_clients[] = {
.security = 0x7fc,
},
},
}, {
.id = TEGRA_ICC_MC_CPU_CLUSTER0,
.name = "sw_cluster0",
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA_ICC_MC_CPU_CLUSTER1,
.name = "sw_cluster1",
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA_ICC_MC_CPU_CLUSTER2,
.name = "sw_cluster2",
.type = TEGRA_ICC_NISO,
}, {
.id = TEGRA_ICC_MC_CPU_CLUSTER3,
.name = "sw_cluster3",
.type = TEGRA_ICC_NISO,
},
};
@@ -1352,6 +1370,92 @@ static const struct tegra_mc_intmask tegra194_mc_intmasks[] = {
},
};
static int tegra194_mc_icc_set(struct icc_node *src, struct icc_node *dst)
{
/* TODO: program PTSA */
return 0;
}
static int tegra194_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
struct icc_provider *p = node->provider;
struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
node->id == TEGRA_ICC_MC_CPU_CLUSTER1 ||
node->id == TEGRA_ICC_MC_CPU_CLUSTER2 ||
node->id == TEGRA_ICC_MC_CPU_CLUSTER3) {
if (mc)
peak_bw = peak_bw * mc->num_channels;
}
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
static int tegra194_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
{
*avg = 0;
*peak = 0;
return 0;
}
static struct icc_node_data *
tegra194_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
{
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
const struct tegra_mc_client *client;
unsigned int i, idx = spec->args[0];
struct icc_node_data *ndata;
struct icc_node *node;
list_for_each_entry(node, &mc->provider.nodes, node_list) {
if (node->id != idx)
continue;
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
if (!ndata)
return ERR_PTR(-ENOMEM);
client = &mc->soc->clients[idx];
ndata->node = node;
switch (client->sid) {
case TEGRA194_SID_NVDISPLAY:
case TEGRA194_SID_VI:
/* these clients are isochronous by default */
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
break;
default:
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
break;
}
return ndata;
}
for (i = 0; i < mc->soc->num_clients; i++) {
if (mc->soc->clients[i].id == idx)
return ERR_PTR(-EPROBE_DEFER);
}
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
return ERR_PTR(-EINVAL);
}
static const struct tegra_mc_icc_ops tegra194_mc_icc_ops = {
.xlate_extended = tegra194_mc_of_icc_xlate_extended,
.aggregate = tegra194_mc_icc_aggregate,
.get_bw = tegra194_mc_icc_get_init_bw,
.set = tegra194_mc_icc_set,
};
const struct tegra_mc_soc tegra194_mc_soc = {
.num_clients = ARRAY_SIZE(tegra194_mc_clients),
.clients = tegra194_mc_clients,
@@ -1362,7 +1466,7 @@ const struct tegra_mc_soc tegra194_mc_soc = {
.num_intmasks = ARRAY_SIZE(tegra194_mc_intmasks),
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
.icc_ops = &tegra_mc_icc_ops,
.icc_ops = &tegra194_mc_icc_ops,
.ch_intmask = 0x00000f00,
.global_intstatus_channel_shift = 8,
.regs = &tegra20_mc_regs,
+520 -13
View File
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/thermal.h>
#include <soc/tegra/fuse.h>
@@ -87,6 +88,13 @@
#define LPDDR2_MR4_SRR GENMASK(2, 0)
/*
* Tegra210 memory layout can be 1 channel at 64-bit or 2 channels at 32-bit
* each. Either way, the total bus width will always be 64-bit.
*/
#define DRAM_DATA_BUS_WIDTH_BYTES (64 / 8)
#define DDR 2
static const struct tegra210_emc_sequence *tegra210_emc_sequences[] = {
&tegra210_emc_r21021,
};
@@ -1569,6 +1577,79 @@ static int tegra210_emc_set_rate(struct device *dev,
return 0;
}
static void tegra210_emc_rate_requests_init(struct tegra210_emc *emc)
{
unsigned int i;
for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
emc->requested_rate[i].min_rate = 0;
emc->requested_rate[i].max_rate = ULONG_MAX;
}
}
static int emc_request_rate(struct tegra210_emc *emc,
unsigned long new_min_rate,
unsigned long new_max_rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = emc->requested_rate;
unsigned long min_rate = 0, max_rate = ULONG_MAX;
unsigned int i;
int err;
/* select minimum and maximum rates among the requested rates */
for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
if (i == type) {
min_rate = max(new_min_rate, min_rate);
max_rate = min(new_max_rate, max_rate);
} else {
min_rate = max(req->min_rate, min_rate);
max_rate = min(req->max_rate, max_rate);
}
}
if (min_rate > max_rate) {
dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
__func__, type, min_rate, max_rate);
return -ERANGE;
}
err = clk_set_rate(emc->clk, min_rate);
if (err)
return err;
emc->requested_rate[type].min_rate = new_min_rate;
emc->requested_rate[type].max_rate = new_max_rate;
return 0;
}
static int emc_set_min_rate(struct tegra210_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, rate, req->max_rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
static int emc_set_max_rate(struct tegra210_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, req->min_rate, rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
/*
* debugfs interface
*
@@ -1641,7 +1722,7 @@ static int tegra210_emc_debug_min_rate_set(void *data, u64 rate)
if (!tegra210_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_min_rate(emc->clk, rate);
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -1671,7 +1752,7 @@ static int tegra210_emc_debug_max_rate_set(void *data, u64 rate)
if (!tegra210_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_max_rate(emc->clk, rate);
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -1758,6 +1839,194 @@ static void tegra210_emc_debugfs_init(struct tegra210_emc *emc)
&tegra210_emc_debug_temperature_fops);
}
static inline struct tegra210_emc *
to_tegra210_emc_provider(struct icc_provider *provider)
{
return container_of(provider, struct tegra210_emc, icc_provider);
}
static struct icc_node_data *
emc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
{
struct icc_provider *provider = data;
struct icc_node_data *ndata;
struct icc_node *node;
/* External Memory is the only possible ICC route */
list_for_each_entry(node, &provider->nodes, node_list) {
if (node->id != TEGRA_ICC_EMEM)
continue;
ndata = kzalloc_obj(*ndata);
if (!ndata)
return ERR_PTR(-ENOMEM);
/*
* SRC and DST nodes should have matching TAG in order to have
* it set by default for a requested path.
*/
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
ndata->node = node;
return ndata;
}
return ERR_PTR(-EPROBE_DEFER);
}
static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct tegra210_emc *emc = to_tegra210_emc_provider(dst->provider);
unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
unsigned long long rate = max(avg_bw, peak_bw);
int err;
/*
* Tegra210 EMC runs on a clock rate of SDRAM bus. This means that
* EMC clock rate is twice smaller than the peak data rate because
* data is sampled on both EMC clock edges.
*/
do_div(rate, DDR * DRAM_DATA_BUS_WIDTH_BYTES);
rate = min_t(u64, rate, U32_MAX);
err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
if (err)
return err;
return 0;
}
static int tegra210_emc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
{
*avg = 0;
*peak = 0;
return 0;
}
static int tegra210_emc_interconnect_init(struct tegra210_emc *emc)
{
const struct tegra_mc_soc *soc = emc->mc->soc;
struct icc_node *node;
int err;
emc->icc_provider.dev = emc->dev;
emc->icc_provider.set = emc_icc_set;
emc->icc_provider.data = &emc->icc_provider;
emc->icc_provider.aggregate = soc->icc_ops->aggregate;
emc->icc_provider.xlate_extended = emc_of_icc_xlate_extended;
emc->icc_provider.get_bw = tegra210_emc_icc_get_init_bw;
icc_provider_init(&emc->icc_provider);
/* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node))
return PTR_ERR(node);
node->name = "External Memory Controller";
icc_node_add(node, &emc->icc_provider);
/* link External Memory Controller to External Memory (DRAM) */
err = icc_link_create(node, TEGRA_ICC_EMEM);
if (err)
goto remove_nodes;
/* create External Memory node */
node = icc_node_create(TEGRA_ICC_EMEM);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto remove_nodes;
}
node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->icc_provider);
err = icc_provider_register(&emc->icc_provider);
if (err)
goto remove_nodes;
return 0;
remove_nodes:
icc_nodes_remove(&emc->icc_provider);
return dev_err_probe(emc->dev, err, "failed to initialize ICC\n");
}
static int tegra210_emc_opp_table_init(struct tegra210_emc *emc)
{
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
struct dev_pm_opp *opp;
unsigned long rate;
int err, max_opps, i;
err = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
if (err < 0)
return dev_err_probe(emc->dev, err, "failed to set OPP supported HW\n");
emc->hw_opp_token = err;
err = dev_pm_opp_of_add_table(emc->dev);
if (err) {
if (err == -ENODEV)
dev_err_probe(emc->dev, err,
"OPP table not found, please update your device tree\n");
else
dev_err_probe(emc->dev, err, "failed to add OPP table\n");
goto put_hw_table;
}
max_opps = dev_pm_opp_get_opp_count(emc->dev);
if (max_opps <= 0) {
err = max_opps ?: -EINVAL;
dev_err_probe(emc->dev, err, "Failed to add OPPs\n");
goto remove_table;
}
if (emc->num_timings != max_opps) {
err = -EINVAL;
dev_err_probe(emc->dev, err, "OPP table does not match emc table\n");
goto remove_table;
}
for (i = 0; i < emc->num_timings; i++) {
rate = emc->timings[i].rate * 1000;
opp = dev_pm_opp_find_freq_exact(emc->dev, rate, true);
if (IS_ERR(opp)) {
err = PTR_ERR(opp);
dev_err_probe(emc->dev, err, "Rate %lu not found in OPP table\n", rate);
goto remove_table;
}
dev_pm_opp_put(opp);
}
dev_info_once(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
hw_version, clk_get_rate(emc->clk) / 1000000);
return 0;
remove_table:
dev_pm_opp_of_remove_table(emc->dev);
put_hw_table:
dev_pm_opp_put_supported_hw(emc->hw_opp_token);
emc->hw_opp_token = 0;
return err;
}
static void tegra210_emc_opp_table_cleanup(struct tegra210_emc *emc)
{
if (emc->hw_opp_token) {
dev_pm_opp_of_remove_table(emc->dev);
dev_pm_opp_put_supported_hw(emc->hw_opp_token);
emc->hw_opp_token = 0;
}
}
static void tegra210_emc_detect(struct tegra210_emc *emc)
{
u32 value;
@@ -1784,6 +2053,226 @@ static void tegra210_emc_detect(struct tegra210_emc *emc)
emc->num_channels = 1;
}
static struct device_node *
tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
{
struct device_node *np;
int err;
for_each_child_of_node(node, np) {
u32 value;
err = of_property_read_u32(np, "nvidia,ram-code", &value);
if (err || (value != ram_code))
continue;
return np;
}
return NULL;
}
static int load_one_timing_from_dt(struct tegra210_emc *emc,
struct tegra210_emc_timing *timing,
struct device_node *node)
{
int err;
#define EMC_READ_PROP(prop, dtprop) { \
err = of_property_read_u32(node, dtprop, &timing->prop); \
if (err) { \
dev_err(emc->dev, "timing %pOFn: failed to read " #prop ": %d\n", \
node, err); \
return err; \
} \
}
#define EMC_READ_PROP_STRING(prop, dtprop) { \
err = of_property_read_string(node, dtprop, (const char **)&timing->prop); \
if (err) { \
dev_err(emc->dev, "timing %pOFn: failed to read " #prop ": %d\n", \
node, err); \
return err; \
} \
}
#define EMC_READ_PROP_ARRAY(prop, dtprop, length) { \
err = of_property_read_u32_array(node, dtprop, timing->prop, length); \
if (err) { \
dev_err(emc->dev, "timing %pOFn: failed to read " #prop ": %d\n", \
node, err); \
return err; \
} \
}
EMC_READ_PROP_STRING(clock_src, "nvidia,source")
EMC_READ_PROP_STRING(dvfs_ver, "nvidia,dvfs-version")
EMC_READ_PROP(revision, "nvidia,revision")
EMC_READ_PROP(rate, "clock-frequency")
EMC_READ_PROP(min_volt, "nvidia,emc-min-mv")
EMC_READ_PROP(gpu_min_volt, "nvidia,gk20a-min-mv")
EMC_READ_PROP(clk_src_emc, "nvidia,src-sel-reg")
EMC_READ_PROP(num_burst, "nvidia,burst-regs-num")
EMC_READ_PROP(emc_cfg_2, "nvidia,emc-cfg-2")
EMC_READ_PROP(emc_sel_dpd_ctrl, "nvidia,emc-sel-dpd-ctrl")
EMC_READ_PROP(emc_auto_cal_config, "nvidia,emc-auto-cal-config")
EMC_READ_PROP(emc_auto_cal_config2, "nvidia,emc-auto-cal-config2")
EMC_READ_PROP(emc_auto_cal_config3, "nvidia,emc-auto-cal-config3")
EMC_READ_PROP(latency, "nvidia,emc-clock-latency-change")
EMC_READ_PROP_ARRAY(burst_regs, "nvidia,emc-registers", timing->num_burst)
EMC_READ_PROP(needs_training, "nvidia,needs-training")
EMC_READ_PROP(trained, "nvidia,trained")
if (timing->revision >= 0x6) {
EMC_READ_PROP(periodic_training, "nvidia,periodic_training")
EMC_READ_PROP(trained_dram_clktree[C0D0U0], "nvidia,trained_dram_clktree_c0d0u0")
EMC_READ_PROP(trained_dram_clktree[C0D0U1], "nvidia,trained_dram_clktree_c0d0u1")
EMC_READ_PROP(trained_dram_clktree[C0D1U0], "nvidia,trained_dram_clktree_c0d1u0")
EMC_READ_PROP(trained_dram_clktree[C0D1U1], "nvidia,trained_dram_clktree_c0d1u1")
EMC_READ_PROP(trained_dram_clktree[C1D0U0], "nvidia,trained_dram_clktree_c1d0u0")
EMC_READ_PROP(trained_dram_clktree[C1D0U1], "nvidia,trained_dram_clktree_c1d0u1")
EMC_READ_PROP(trained_dram_clktree[C1D1U0], "nvidia,trained_dram_clktree_c1d1u0")
EMC_READ_PROP(trained_dram_clktree[C1D1U1], "nvidia,trained_dram_clktree_c1d1u1")
EMC_READ_PROP(current_dram_clktree[C0D0U0], "nvidia,current_dram_clktree_c0d0u0")
EMC_READ_PROP(current_dram_clktree[C0D0U1], "nvidia,current_dram_clktree_c0d0u1")
EMC_READ_PROP(current_dram_clktree[C0D1U0], "nvidia,current_dram_clktree_c0d1u0")
EMC_READ_PROP(current_dram_clktree[C0D1U1], "nvidia,current_dram_clktree_c0d1u1")
EMC_READ_PROP(current_dram_clktree[C1D0U0], "nvidia,current_dram_clktree_c1d0u0")
EMC_READ_PROP(current_dram_clktree[C1D0U1], "nvidia,current_dram_clktree_c1d0u1")
EMC_READ_PROP(current_dram_clktree[C1D1U0], "nvidia,current_dram_clktree_c1d1u0")
EMC_READ_PROP(current_dram_clktree[C1D1U1], "nvidia,current_dram_clktree_c1d1u1")
EMC_READ_PROP(run_clocks, "nvidia,run_clocks")
EMC_READ_PROP(tree_margin, "nvidia,tree_margin")
}
EMC_READ_PROP(num_burst_per_ch, "nvidia,burst-regs-per-ch-num")
EMC_READ_PROP(num_trim, "nvidia,trim-regs-num")
EMC_READ_PROP(num_trim_per_ch, "nvidia,trim-regs-per-ch-num")
EMC_READ_PROP(num_mc_regs, "nvidia,burst-mc-regs-num")
EMC_READ_PROP(num_up_down, "nvidia,la-scale-regs-num")
EMC_READ_PROP(vref_num, "nvidia,vref-regs-num")
EMC_READ_PROP(dram_timing_num, "nvidia,dram-timing-regs-num")
EMC_READ_PROP(min_mrs_wait, "nvidia,min-mrs-wait")
EMC_READ_PROP(emc_mrw, "nvidia,emc-mrw")
EMC_READ_PROP(emc_mrw2, "nvidia,emc-mrw2")
EMC_READ_PROP(emc_mrw3, "nvidia,emc-mrw3")
EMC_READ_PROP(emc_mrw4, "nvidia,emc-mrw4")
EMC_READ_PROP(emc_mrw9, "nvidia,emc-mrw9")
EMC_READ_PROP(emc_mrs, "nvidia,emc-mrs")
EMC_READ_PROP(emc_emrs, "nvidia,emc-emrs")
EMC_READ_PROP(emc_emrs2, "nvidia,emc-emrs2")
EMC_READ_PROP(emc_auto_cal_config4, "nvidia,emc-auto-cal-config4")
EMC_READ_PROP(emc_auto_cal_config5, "nvidia,emc-auto-cal-config5")
EMC_READ_PROP(emc_auto_cal_config6, "nvidia,emc-auto-cal-config6")
EMC_READ_PROP(emc_auto_cal_config7, "nvidia,emc-auto-cal-config7")
EMC_READ_PROP(emc_auto_cal_config8, "nvidia,emc-auto-cal-config8")
EMC_READ_PROP(emc_fdpd_ctrl_cmd_no_ramp, "nvidia,emc-fdpd-ctrl-cmd-no-ramp")
EMC_READ_PROP(dll_clk_src, "nvidia,dll-clk-src")
EMC_READ_PROP(clk_out_enb_x_0_clk_enb_emc_dll, "nvidia,clk-out-enb-x-0-clk-enb-emc-dll")
if (timing->revision >= 0x7)
EMC_READ_PROP_ARRAY(ptfv_list, "nvidia,ptfv", ARRAY_SIZE(timing->ptfv_list))
EMC_READ_PROP_ARRAY(burst_reg_per_ch, "nvidia,emc-burst-regs-per-ch",
timing->num_burst_per_ch)
EMC_READ_PROP_ARRAY(shadow_regs_ca_train, "nvidia,emc-shadow-regs-ca-train",
timing->num_burst)
EMC_READ_PROP_ARRAY(shadow_regs_quse_train, "nvidia,emc-shadow-regs-quse-train",
timing->num_burst)
EMC_READ_PROP_ARRAY(shadow_regs_rdwr_train, "nvidia,emc-shadow-regs-rdwr-train",
timing->num_burst)
EMC_READ_PROP_ARRAY(trim_regs, "nvidia,emc-trim-regs", timing->num_trim)
EMC_READ_PROP_ARRAY(trim_perch_regs, "nvidia,emc-trim-regs-per-ch", timing->num_trim_per_ch)
EMC_READ_PROP_ARRAY(vref_perch_regs, "nvidia,emc-vref-regs", timing->vref_num)
EMC_READ_PROP_ARRAY(dram_timings, "nvidia,emc-dram-timing-regs", timing->dram_timing_num)
EMC_READ_PROP_ARRAY(burst_mc_regs, "nvidia,emc-burst-mc-regs", timing->num_mc_regs)
EMC_READ_PROP_ARRAY(la_scale_regs, "nvidia,emc-la-scale-regs", timing->num_up_down)
#undef EMC_READ_PROP
#undef EMC_READ_STRING
#undef EMC_READ_PROP_ARRAY
return 0;
}
#define NOMINAL_COMPATIBLE "nvidia,tegra21-emc-table"
#define DERATED_COMPATIBLE "nvidia,tegra21-emc-table-derated"
static int tegra210_emc_load_timings_from_dt(struct tegra210_emc *emc,
struct device_node *node)
{
struct tegra210_emc_timing *timing;
unsigned int num_nominal = 0, num_derated = 0;
int err;
emc->num_timings = 0;
for_each_child_of_node_scoped(node, child) {
if (of_device_is_compatible(child, NOMINAL_COMPATIBLE))
emc->num_timings++;
else if (of_device_is_compatible(child, DERATED_COMPATIBLE))
num_derated++;
}
if (!emc->num_timings || (num_derated && (emc->num_timings != num_derated)))
return -EINVAL;
emc->nominal = devm_kcalloc(emc->dev, emc->num_timings, sizeof(*timing),
GFP_KERNEL);
if (!emc->nominal)
return -ENOMEM;
if (num_derated) {
num_derated = 0;
emc->derated = devm_kcalloc(emc->dev, emc->num_timings, sizeof(*timing),
GFP_KERNEL);
if (!emc->derated)
return -ENOMEM;
}
for_each_child_of_node_scoped(node, child) {
if (of_device_is_compatible(child, NOMINAL_COMPATIBLE))
timing = &emc->nominal[num_nominal++];
else if (of_device_is_compatible(child, DERATED_COMPATIBLE))
timing = &emc->derated[num_derated++];
else
continue;
err = load_one_timing_from_dt(emc, timing, child);
if (err)
return err;
}
return 0;
}
static int tegra210_emc_parse_dt(struct tegra210_emc *emc)
{
struct device_node *node, *np = emc->dev->of_node;
int ram_code, ret = 0;
if (!np) {
dev_err(emc->dev, "Unable to find emc node\n");
return -ENODEV;
}
if (of_find_property(np, "nvidia,use-ram-code", NULL)) {
ram_code = tegra_read_ram_code();
node = tegra_emc_find_node_by_ram_code(np, ram_code);
if (!node) {
dev_warn(emc->dev, "can't find emc table for ram-code\n");
return -ENODEV;
}
ret = tegra210_emc_load_timings_from_dt(emc, node);
of_node_put(node);
} else {
ret = tegra210_emc_load_timings_from_dt(emc, np);
}
return ret;
}
static int tegra210_emc_validate_timings(struct tegra210_emc *emc,
struct tegra210_emc_timing *timings,
unsigned int num_timings)
@@ -1816,6 +2305,7 @@ static int tegra210_emc_probe(struct platform_device *pdev)
struct device_node *np;
unsigned int i;
int err;
bool have_dt_tables = false;
emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
if (!emc)
@@ -1848,16 +2338,20 @@ static int tegra210_emc_probe(struct platform_device *pdev)
np = pdev->dev.of_node;
/* attach to the nominal and (optional) derated tables */
err = of_reserved_mem_device_init_by_name(emc->dev, np, "nominal");
if (err < 0) {
dev_err(emc->dev, "failed to get nominal EMC table: %d\n", err);
return err;
}
if (of_reserved_mem_device_init_by_name(emc->dev, np, "nominal") >= 0) {
err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
if (err < 0 && err != -ENODEV) {
dev_err(emc->dev, "failed to get derated EMC table: %d\n", err);
goto release;
}
} else {
err = tegra210_emc_parse_dt(emc);
if (err < 0) {
dev_err(emc->dev, "failed to get EMC tables: %d\n", err);
return err;
}
err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
if (err < 0 && err != -ENODEV) {
dev_err(emc->dev, "failed to get derated EMC table: %d\n", err);
goto release;
have_dt_tables = true;
}
/* validate the tables */
@@ -1966,22 +2460,33 @@ static int tegra210_emc_probe(struct platform_device *pdev)
tegra210_emc_debugfs_init(emc);
err = tegra210_emc_opp_table_init(emc);
if (!err) {
tegra210_emc_rate_requests_init(emc);
tegra210_emc_interconnect_init(emc);
} else if (err != -ENODEV) {
goto detach;
}
cd = devm_thermal_of_child_cooling_device_register(emc->dev, np, "emc", emc,
&tegra210_emc_cd_ops);
if (IS_ERR(cd)) {
err = PTR_ERR(cd);
dev_err(emc->dev, "failed to register cooling device: %d\n",
err);
goto detach;
goto cleanup_table;
}
return 0;
cleanup_table:
tegra210_emc_opp_table_cleanup(emc);
detach:
debugfs_remove_recursive(emc->debugfs.root);
tegra210_clk_emc_detach(emc->clk);
release:
of_reserved_mem_device_release(emc->dev);
if (!have_dt_tables)
of_reserved_mem_device_release(emc->dev);
return err;
}
@@ -1990,6 +2495,7 @@ static void tegra210_emc_remove(struct platform_device *pdev)
{
struct tegra210_emc *emc = platform_get_drvdata(pdev);
tegra210_emc_opp_table_cleanup(emc);
debugfs_remove_recursive(emc->debugfs.root);
tegra210_clk_emc_detach(emc->clk);
of_reserved_mem_device_release(emc->dev);
@@ -2050,6 +2556,7 @@ static struct platform_driver tegra210_emc_driver = {
.name = "tegra210-emc",
.of_match_table = tegra210_emc_of_match,
.pm = &tegra210_emc_pm_ops,
.sync_state = icc_sync_state,
},
.probe = tegra210_emc_probe,
.remove = tegra210_emc_remove,
+24
View File
@@ -8,6 +8,7 @@
#include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@ -784,6 +785,17 @@ enum {
#define TRIM_REGS_SIZE 138
#define BURST_REGS_SIZE 221
enum emc_rate_request_type {
EMC_RATE_DEBUG,
EMC_RATE_ICC,
EMC_RATE_TYPE_MAX,
};
struct emc_rate_request {
unsigned long min_rate;
unsigned long max_rate;
};
struct tegra210_emc_per_channel_regs {
u16 bank;
u16 offset;
@@ -932,6 +944,18 @@ struct tegra210_emc {
} debugfs;
struct tegra210_clk_emc_provider provider;
struct icc_provider icc_provider;
int hw_opp_token;
/*
* There are multiple sources in the EMC driver which could request
* a min/max clock rate, these rates are contained in this array.
*/
struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
/* protect shared rate-change code path */
struct mutex rate_lock;
};
struct tegra210_emc_sequence {
+81
View File
@@ -3,6 +3,9 @@
* Copyright (C) 2015-2026 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/of.h>
#include <linux/device.h>
#include <dt-bindings/memory/tegra210-mc.h>
#include "mc.h"
@@ -1282,6 +1285,83 @@ static const struct tegra_mc_intmask tegra210_mc_intmasks[] = {
},
};
static int tegra210_mc_icc_set(struct icc_node *src, struct icc_node *dst)
{
/* TODO: program PTSA */
return 0;
}
static int tegra210_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
/*
* ISO clients need to reserve extra bandwidth up-front because
* there could be high bandwidth pressure during initial filling
* of the client's FIFO buffers. Secondly, we need to take into
* account impurities of the memory subsystem.
*/
if (tag & TEGRA_MC_ICC_TAG_ISO)
peak_bw = tegra_mc_scale_percents(peak_bw, 400);
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
static struct icc_node_data *
tegra210_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
{
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
const struct tegra_mc_client *client;
unsigned int i, idx = spec->args[0];
struct icc_node_data *ndata;
struct icc_node *node;
list_for_each_entry(node, &mc->provider.nodes, node_list) {
if (node->id != idx)
continue;
ndata = kzalloc_obj(*ndata);
if (!ndata)
return ERR_PTR(-ENOMEM);
client = &mc->soc->clients[idx];
ndata->node = node;
switch (client->swgroup) {
case TEGRA_SWGROUP_DC:
case TEGRA_SWGROUP_DCB:
case TEGRA_SWGROUP_PTC:
case TEGRA_SWGROUP_VI:
/* these clients are isochronous by default */
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
break;
default:
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
break;
}
return ndata;
}
for (i = 0; i < mc->soc->num_clients; i++) {
if (mc->soc->clients[i].id == idx)
return ERR_PTR(-EPROBE_DEFER);
}
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
return ERR_PTR(-EINVAL);
}
static const struct tegra_mc_icc_ops tegra210_mc_icc_ops = {
.xlate_extended = tegra210_mc_of_icc_xlate_extended,
.aggregate = tegra210_mc_icc_aggregate,
.set = tegra210_mc_icc_set,
};
const struct tegra_mc_soc tegra210_mc_soc = {
.clients = tegra210_mc_clients,
.num_clients = ARRAY_SIZE(tegra210_mc_clients),
@@ -1294,6 +1374,7 @@ const struct tegra_mc_soc tegra210_mc_soc = {
.reset_ops = &tegra_mc_reset_ops_common,
.resets = tegra210_mc_resets,
.num_resets = ARRAY_SIZE(tegra210_mc_resets),
.icc_ops = &tegra210_mc_icc_ops,
.ops = &tegra30_mc_ops,
.regs = &tegra20_mc_regs,
.handle_irq = tegra30_mc_irq_handlers,
+14
View File
@@ -1506,6 +1506,19 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
.max_tap_delay = 185,
};
static const struct sdhci_tegra_soc_data soc_data_tegra210b01 = {
.pdata = &sdhci_tegra210_pdata,
.dma_mask = DMA_BIT_MASK(34),
.nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
NVQUIRK_HAS_PADCALIB |
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
NVQUIRK_ENABLE_SDR50 |
NVQUIRK_ENABLE_SDR104 |
NVQUIRK_HAS_TMCLK,
.min_tap_delay = 91,
.max_tap_delay = 149,
};
static const struct sdhci_ops tegra186_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
@@ -1577,6 +1590,7 @@ static const struct of_device_id sdhci_tegra_dt_match[] = {
{ .compatible = "nvidia,tegra194-sdhci", .data = &soc_data_tegra194 },
{ .compatible = "nvidia,tegra186-sdhci", .data = &soc_data_tegra186 },
{ .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 },
{ .compatible = "nvidia,tegra210b01-sdhci", .data = &soc_data_tegra210b01 },
{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 },
{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
+46 -24
View File
@@ -1089,10 +1089,33 @@ int __init early_init_dt_scan_memory(void)
return found_memory;
}
/*
* Convert configs to something easy to use in C code
*/
#if defined(CONFIG_CMDLINE_FORCE)
static const int overwrite_incoming_cmdline = 1;
static const int read_dt_cmdline;
static const int concat_cmdline;
#elif defined(CONFIG_CMDLINE_EXTEND)
static const int overwrite_incoming_cmdline;
static const int read_dt_cmdline = 1;
static const int concat_cmdline = 1;
#else /* CMDLINE_FROM_BOOTLOADER */
static const int overwrite_incoming_cmdline;
static const int read_dt_cmdline = 1;
static const int concat_cmdline;
#endif
#ifdef CONFIG_CMDLINE
static const char *config_cmdline = CONFIG_CMDLINE;
#else
static const char *config_cmdline = "";
#endif
int __init early_init_dt_scan_chosen(char *cmdline)
{
int l, node;
const char *p;
int l = 0, node;
const char *p = NULL;
const void *rng_seed;
const void *fdt = initial_boot_params;
@@ -1121,30 +1144,29 @@ int __init early_init_dt_scan_chosen(char *cmdline)
fdt_totalsize(initial_boot_params));
}
/* Retrieve command line */
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0)
strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE));
/* Put CONFIG_CMDLINE in if forced or if data had nothing in it to start */
if (overwrite_incoming_cmdline || !cmdline[0])
strscpy(cmdline, config_cmdline, COMMAND_LINE_SIZE);
/* Retrieve command line unless forcing */
if (read_dt_cmdline)
p = of_get_flat_dt_prop(node, "bootargs", &l);
if (p != NULL && l > 0) {
if (concat_cmdline) {
int cmdline_len;
int copy_len;
strlcat(cmdline, " ", COMMAND_LINE_SIZE);
cmdline_len = strlen(cmdline);
copy_len = COMMAND_LINE_SIZE - cmdline_len - 1;
copy_len = min((int)l, copy_len);
strncpy(cmdline + cmdline_len, p, copy_len);
cmdline[cmdline_len + copy_len] = '\0';
} else {
strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE));
}
}
handle_cmdline:
/*
* CONFIG_CMDLINE is meant to be a default in case nothing else
* managed to set the command line, unless CONFIG_CMDLINE_FORCE
* is set in which case we override whatever was found earlier.
*/
#ifdef CONFIG_CMDLINE
#if defined(CONFIG_CMDLINE_EXTEND)
strlcat(cmdline, " ", COMMAND_LINE_SIZE);
strlcat(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#else
/* No arguments from boot loader, use kernel's cmdl*/
if (!((char *)cmdline)[0])
strscpy(cmdline, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif
#endif /* CONFIG_CMDLINE */
pr_debug("Command line is: %s\n", (char *)cmdline);
return 0;
+428 -5
View File
@@ -6,7 +6,7 @@
* Author: Mike Rapoport <mike@compulab.co.il>
*
* Based on NVIDIA PCIe driver
* Copyright (c) 2008-2009, NVIDIA Corporation.
* Copyright (c) 2008-2020, NVIDIA Corporation.
*
* Bits taken from arch/arm/mach-dove/pcie.c
*
@@ -165,10 +165,64 @@
#define AFI_PLLE_CONTROL 0x160
#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
#define AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL (1 << 8)
#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
#define AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN (1 << 0)
#define AFI_PEXBIAS_CTRL_0 0x168
#define RP_PRIV_XP_DL 0x00000494
#define RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD (0x1ff << 1)
#define RP_L1_PM_SUBSTATES_CTL 0xc00
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2 (0x1 << 0)
#define RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1 (0x1 << 1)
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2 (0x1 << 2)
#define RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1 (0x1 << 3)
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK (0xff << 8)
#define RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT 8
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK (0x3 << 16)
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT 16
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK (0x1f << 19)
#define RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT 19
#define RP_L1_PM_SUBSTATES_CTL_HIDE_CAP (0x1 << 24)
#define RP_L1_PM_SUBSTATES_1_CTL 0xc04
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK 0x1fff
#define RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY 0x26
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK (0x1ff << 13)
#define RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY (0x27 << 13)
#define RP_L1_PM_SUBSTATES_2_CTL 0xc08
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK 0x1fff
#define RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY 0x4d
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK (0xff << 13)
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND (0x13 << 13)
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK (0xf << 21)
#define RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP (0x2 << 21)
#define RP_RX_HDR_LIMIT 0x00000e00
#define RP_RX_HDR_LIMIT_PW_MASK (0xff << 8)
#define RP_RX_HDR_LIMIT_PW (0x0e << 8)
#define RP_TIMEOUT0 0xe24
#define RP_TIMEOUT0_PAD_PWRUP_MASK 0xff
#define RP_TIMEOUT0_PAD_PWRUP 0xa
#define RP_TIMEOUT0_PAD_PWRUP_CM_MASK 0xffff00
#define RP_TIMEOUT0_PAD_PWRUP_CM (0x180 << 8)
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK (0xff << 24)
#define RP_TIMEOUT0_PAD_SPDCHNG_GEN2 (0xa << 24)
#define RP_TIMEOUT1 0xe28
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK (0xff << 16)
#define RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE (0x10 << 16)
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK (0xff << 24)
#define RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE (0x74 << 24)
#define RP_ECTL_1_R1 0x00000e80
#define RP_ECTL_1_R1_TX_DRV_AMP_1C_MASK 0x3f
#define RP_ECTL_2_R1 0x00000e84
#define RP_ECTL_2_R1_RX_CTLE_1C_MASK 0xffff
@@ -182,6 +236,9 @@
#define RP_ECTL_6_R1 0x00000e94
#define RP_ECTL_6_R1_RX_EQ_CTRL_H_1C_MASK 0xffffffff
#define RP_ECTL_1_R2 0x00000ea0
#define RP_ECTL_1_R2_TX_DRV_AMP_1C_MASK 0x3f
#define RP_ECTL_2_R2 0x00000ea4
#define RP_ECTL_2_R2_RX_CTLE_1C_MASK 0xffff
@@ -201,6 +258,19 @@
#define RP_VEND_XP_OPPORTUNISTIC_UPDATEFC (1 << 28)
#define RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK (0xff << 18)
#define RP_VEND_XP1 0xf04
#define RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S (1 << 23)
#define RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT (1 << 21)
#define RP_XP_REF 0xf30
#define RP_XP_REF_MICROSECOND_LIMIT_MASK 0xff
#define RP_XP_REF_MICROSECOND_LIMIT 0x14
#define RP_XP_REF_MICROSECOND_ENABLE (1 << 8)
#define RP_XP_REF_CPL_TO_OVERRIDE (1 << 13)
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK (0x1ffff << 14)
#define RP_XP_REF_CPL_TO_CUSTOM_VALUE (0x1770 << 14)
#define RP_VEND_CTL0 0x00000f44
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH_MASK (0xf << 12)
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH (0x9 << 12)
@@ -224,12 +294,23 @@
#define RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD (0xf << 24)
#define RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE (1 << 31)
#define RP_VEND_XP_PAD_PWRDN 0x00000f50
#define RP_VEND_XP_PAD_PWRDN_L1_EN (1 << 0)
#define RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN (1 << 1)
#define RP_VEND_XP_PAD_PWRDN_DISABLED_EN (1 << 2)
#define RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN (1 << 15)
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP (3 << 5)
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP (3 << 3)
#define RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP (3 << 16)
#define RP_LINK_CONTROL_STATUS 0x00000090
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
#define RP_LINK_CONTROL_STATUS_2 0x000000b0
#define RP_L1_PM_SUBSTATES_CAP 0x144
#define PADS_CTL_SEL 0x0000009c
#define PADS_CTL 0x000000a0
@@ -306,12 +387,18 @@ struct tegra_pcie_soc {
bool program_deskew_time;
bool update_fc_timer;
bool has_cache_bars;
bool enable_wrap;
bool has_aspm_l1;
bool has_aspm_l1ss;
bool l1ss_rp_wake_fixup;
struct {
struct {
u32 rp_ectl_1_r1;
u32 rp_ectl_2_r1;
u32 rp_ectl_4_r1;
u32 rp_ectl_5_r1;
u32 rp_ectl_6_r1;
u32 rp_ectl_1_r2;
u32 rp_ectl_2_r2;
u32 rp_ectl_4_r2;
u32 rp_ectl_5_r2;
@@ -368,6 +455,8 @@ struct tegra_pcie_port {
void __iomem *base;
unsigned int index;
unsigned int lanes;
unsigned int aspm_state;
bool supports_clkreq;
struct phy **phys;
@@ -396,6 +485,14 @@ static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset)
return readl(pcie->pads + offset);
}
static bool tegra_pcie_link_up(struct tegra_pcie_port *port)
{
u32 value;
value = readl(port->base + RP_LINK_CONTROL_STATUS);
return !!(value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE);
}
/*
* The configuration space mapping on Tegra is somewhat similar to the ECAM
* defined by PCIe. However it deviates a bit in how the 4 bits for extended
@@ -461,20 +558,50 @@ static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus,
static int tegra_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *value)
{
struct tegra_pcie *pcie = bus->sysdata;
struct pci_dev *bridge;
struct tegra_pcie_port *port;
if (bus->number == 0)
return pci_generic_config_read32(bus, devfn, where, size,
value);
bridge = pcie_find_root_port(bus->self);
list_for_each_entry(port, &pcie->ports, list)
if (port->index + 1 == PCI_SLOT(bridge->devfn))
break;
/* If there is no link, then there is no device */
if (!tegra_pcie_link_up(port)) {
*value = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
return pci_generic_config_read(bus, devfn, where, size, value);
}
static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 value)
{
struct tegra_pcie *pcie = bus->sysdata;
struct tegra_pcie_port *port;
struct pci_dev *bridge;
if (bus->number == 0)
return pci_generic_config_write32(bus, devfn, where, size,
value);
bridge = pcie_find_root_port(bus->self);
list_for_each_entry(port, &pcie->ports, list)
if (port->index + 1 == PCI_SLOT(bridge->devfn))
break;
/* If there is no link, then there is no device */
if (!tegra_pcie_link_up(port))
return PCIBIOS_DEVICE_NOT_FOUND;
return pci_generic_config_write(bus, devfn, where, size, value);
}
@@ -531,6 +658,44 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
}
}
static void disable_aspm_l0s(struct tegra_pcie_port *port)
{
u32 val = 0;
val = readl(port->base + RP_VEND_XP1);
val |= RP_VEND_XP1_LINK_PVT_CTL_IGNORE_L0S;
writel(val, port->base + RP_VEND_XP1);
}
static void disable_aspm_l10(struct tegra_pcie_port *port)
{
u32 val = 0;
val = readl(port->base + RP_VEND_XP1);
val &= ~RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
writel(val, port->base + RP_VEND_XP1);
}
static void disable_aspm_l11(struct tegra_pcie_port *port)
{
u32 val = 0;
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_1;
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_1;
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
}
static void disable_aspm_l12(struct tegra_pcie_port *port)
{
u32 val = 0;
val = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
val &= ~RP_L1_PM_SUBSTATES_CTL_PCI_PM_L1_2;
val &= ~RP_L1_PM_SUBSTATES_CTL_ASPM_L1_2;
writel(val, port->base + RP_L1_PM_SUBSTATES_CTL);
}
static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
{
const struct tegra_pcie_soc *soc = port->pcie->soc;
@@ -567,6 +732,47 @@ static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
}
writel(value, port->base + RP_PRIV_MISC);
if (soc->has_aspm_l1) {
/* Advertise ASPM-L1 state capability*/
value = readl(port->base + RP_VEND_XP1);
value |= RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT;
writel(value, port->base + RP_VEND_XP1);
/* Power saving configuration for L1 sleep/idle */
value = readl(port->base + RP_VEND_XP_PAD_PWRDN);
value |= RP_VEND_XP_PAD_PWRDN_DISABLED_EN;
value |= RP_VEND_XP_PAD_PWRDN_DYNAMIC_EN;
value |= RP_VEND_XP_PAD_PWRDN_L1_EN;
value |= RP_VEND_XP_PAD_PWRDN_L1_CLKREQ_EN;
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_DYNAMIC_L1PP;
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_L1PP;
value |= RP_VEND_XP_PAD_PWRDN_SLEEP_MODE_L1_CLKREQ_L1PP;
writel(value, port->base + RP_VEND_XP_PAD_PWRDN);
if (port->aspm_state & 0x1)
disable_aspm_l0s(port);
if (port->aspm_state & 0x2)
disable_aspm_l10(port);
}
if (soc->has_aspm_l1ss) {
if (port->aspm_state & 0x2) {
disable_aspm_l11(port);
disable_aspm_l12(port);
}
if (port->aspm_state & 0x4)
disable_aspm_l11(port);
if (port->aspm_state & 0x8)
disable_aspm_l12(port);
/* Disable L1SS capability if CLKREQ# is not present */
if (!port->supports_clkreq) {
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
value |= RP_L1_PM_SUBSTATES_CTL_HIDE_CAP;
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
}
}
}
static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
@@ -574,6 +780,11 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
const struct tegra_pcie_soc *soc = port->pcie->soc;
u32 value;
value = readl(port->base + RP_ECTL_1_R1);
value &= ~RP_ECTL_1_R1_TX_DRV_AMP_1C_MASK;
value |= soc->ectl.regs.rp_ectl_1_r1;
writel(value, port->base + RP_ECTL_1_R1);
value = readl(port->base + RP_ECTL_2_R1);
value &= ~RP_ECTL_2_R1_RX_CTLE_1C_MASK;
value |= soc->ectl.regs.rp_ectl_2_r1;
@@ -595,6 +806,11 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
value |= soc->ectl.regs.rp_ectl_6_r1;
writel(value, port->base + RP_ECTL_6_R1);
value = readl(port->base + RP_ECTL_1_R2);
value &= ~RP_ECTL_1_R2_TX_DRV_AMP_1C_MASK;
value |= soc->ectl.regs.rp_ectl_1_r2;
writel(value, port->base + RP_ECTL_1_R2);
value = readl(port->base + RP_ECTL_2_R2);
value &= ~RP_ECTL_2_R2_RX_CTLE_1C_MASK;
value |= soc->ectl.regs.rp_ectl_2_r2;
@@ -617,6 +833,26 @@ static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
writel(value, port->base + RP_ECTL_6_R2);
}
static void tegra_pcie_enable_wrap(void)
{
u32 val;
void __iomem *msel_base;
#define MSELECT_CONFIG_BASE 0x50060000
#define MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1 BIT(28)
#define MSELECT_CONFIG_ERR_RESP_EN_SLAVE1 BIT(24)
/* Config MSELECT to support wrap trans for normal NC & GRE mapping */
msel_base = ioremap(MSELECT_CONFIG_BASE, 4);
val = readl(msel_base);
/* Enable WRAP_TO_INCR_SLAVE1 */
val |= MSELECT_CONFIG_WRAP_TO_INCR_SLAVE1;
/* Disable ERR_RESP_EN_SLAVE1 */
val &= ~MSELECT_CONFIG_ERR_RESP_EN_SLAVE1;
writel(val, msel_base);
iounmap(msel_base);
}
static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
{
const struct tegra_pcie_soc *soc = port->pcie->soc;
@@ -651,6 +887,76 @@ static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
value &= ~PCI_EXP_LNKSTA_CLS;
value |= PCI_EXP_LNKSTA_CLS_2_5GB;
writel(value, port->base + RP_LINK_CONTROL_STATUS_2);
if (soc->enable_wrap)
tegra_pcie_enable_wrap();
if (soc->has_aspm_l1ss) {
/* Set port Common_Mode_Restore_Time to 30us */
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
value &= ~RP_L1_PM_SUBSTATES_CTL_CM_RTIME_MASK;
value |= (0x1E << RP_L1_PM_SUBSTATES_CTL_CM_RTIME_SHIFT);
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
/* set port T_POWER_ON to 70us */
value = readl(port->base + RP_L1_PM_SUBSTATES_CTL);
value &= ~(RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_MASK |
RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_MASK);
value |= (1 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_SCL_SHIFT) |
(7 << RP_L1_PM_SUBSTATES_CTL_T_PWRN_VAL_SHIFT);
writel(value, port->base + RP_L1_PM_SUBSTATES_CTL);
/* Following is based on clk_m being 19.2 MHz */
value = readl(port->base + RP_TIMEOUT0);
value &= ~RP_TIMEOUT0_PAD_PWRUP_MASK;
value |= RP_TIMEOUT0_PAD_PWRUP;
value &= ~RP_TIMEOUT0_PAD_PWRUP_CM_MASK;
value |= RP_TIMEOUT0_PAD_PWRUP_CM;
value &= ~RP_TIMEOUT0_PAD_SPDCHNG_GEN2_MASK;
value |= RP_TIMEOUT0_PAD_SPDCHNG_GEN2;
writel(value, port->base + RP_TIMEOUT0);
value = readl(port->base + RP_TIMEOUT1);
value &= ~RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE_MASK;
value |= RP_TIMEOUT1_RCVRY_SPD_SUCCESS_EIDLE;
value &= ~RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE_MASK;
value |= RP_TIMEOUT1_RCVRY_SPD_UNSUCCESS_EIDLE;
writel(value, port->base + RP_TIMEOUT1);
value = readl(port->base + RP_XP_REF);
value &= ~RP_XP_REF_MICROSECOND_LIMIT_MASK;
value |= RP_XP_REF_MICROSECOND_LIMIT;
value |= RP_XP_REF_MICROSECOND_ENABLE;
value |= RP_XP_REF_CPL_TO_OVERRIDE;
value &= ~RP_XP_REF_CPL_TO_CUSTOM_VALUE_MASK;
value |= RP_XP_REF_CPL_TO_CUSTOM_VALUE;
writel(value, port->base + RP_XP_REF);
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
value &= ~RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY_MASK;
value |= RP_L1_PM_SUBSTATES_1_CTL_PWR_OFF_DLY;
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
value = readl(port->base + RP_L1_PM_SUBSTATES_2_CTL);
value &= ~RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY_MASK;
value |= RP_L1_PM_SUBSTATES_2_CTL_T_L1_2_DLY;
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_MASK;
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND;
value &= ~RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP_MASK;
value |= RP_L1_PM_SUBSTATES_2_CTL_MICROSECOND_COMP;
writel(value, port->base + RP_L1_PM_SUBSTATES_2_CTL);
}
if (soc->l1ss_rp_wake_fixup) {
/*
* Set CLKREQ asserted delay greater than Power_Off
* time (2us) to avoid RP wakeup in L1.2.ENTRY
*/
value = readl(port->base + RP_L1_PM_SUBSTATES_1_CTL);
value &= ~RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY_MASK;
value |= RP_L1SS_1_CTL_CLKREQ_ASSERTED_DLY;
writel(value, port->base + RP_L1_PM_SUBSTATES_1_CTL);
}
}
static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
@@ -663,8 +969,12 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
value = afi_readl(port->pcie, ctrl);
value |= AFI_PEX_CTRL_REFCLK_EN;
if (soc->has_pex_clkreq_en)
value |= AFI_PEX_CTRL_CLKREQ_EN;
if (soc->has_pex_clkreq_en) {
if (port->supports_clkreq)
value &= ~AFI_PEX_CTRL_CLKREQ_EN;
else
value |= AFI_PEX_CTRL_CLKREQ_EN;
}
value |= AFI_PEX_CTRL_OVERRIDE_EN;
@@ -1094,10 +1404,20 @@ static void tegra_pcie_enable_controller(struct tegra_pcie *pcie)
unsigned long value;
/* enable PLL power down */
if (pcie->phy) {
if (soc->has_aspm_l1ss) {
value = afi_readl(pcie, AFI_PLLE_CONTROL);
value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
list_for_each_entry(port, &pcie->ports, list) {
if (!port->supports_clkreq) {
value &= ~AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
break;
}
}
value &= ~AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL;
value |= AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN;
afi_writel(pcie, value, AFI_PLLE_CONTROL);
}
@@ -1529,6 +1849,11 @@ static void tegra_pcie_pme_turnoff(struct tegra_pcie_port *port)
val = afi_readl(pcie, AFI_PCIE_PME);
val &= ~(0x1 << soc->ports[port->index].pme.turnoff_bit);
afi_writel(pcie, val, AFI_PCIE_PME);
/* PCIe link is in L2, bypass CLKREQ# control over PLLE power down */
val = afi_readl(pcie, AFI_PLLE_CONTROL);
val |= AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
afi_writel(pcie, val, AFI_PLLE_CONTROL);
}
static void tegra_pcie_msi_irq(struct irq_desc *desc)
@@ -1820,6 +2145,13 @@ static void tegra_pcie_disable_interrupts(struct tegra_pcie *pcie)
afi_writel(pcie, value, AFI_INTR_MASK);
}
static void update_rp_lanes(struct tegra_pcie *pcie, u32 lanes)
{
struct tegra_pcie_port *port = NULL;
list_for_each_entry(port, &pcie->ports, list)
port->lanes = (lanes >> (port->index << 3)) & 0xFF;
}
static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
u32 *xbar)
{
@@ -1848,6 +2180,20 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
"switching to default 2x1, 1x1, 1x1 "
"configuration\n");
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211;
update_rp_lanes(pcie, 0x010102);
return 0;
}
} else if (of_device_is_compatible(np, "nvidia,tegra210b01-pcie")) {
switch (lanes) {
case 0x0104:
dev_info(dev, "4x1, 1x1 configuration\n");
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
return 0;
default:
dev_info(dev, "wrong configuration updated in DT, "
"switching to default 4x1, 1x1 configuration\n");
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
update_rp_lanes(pcie, 0x0104);
return 0;
}
} else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") ||
@@ -1862,6 +2208,13 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
dev_info(dev, "2x1, 1x1 configuration\n");
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1;
return 0;
default:
dev_info(dev, "wrong configuration updated in DT, "
"switching to default 4x1, 1x1 configuration\n");
*xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1;
update_rp_lanes(pcie, 0x0104);
return 0;
}
} else if (of_device_is_compatible(np, "nvidia,tegra30-pcie")) {
switch (lanes) {
@@ -1984,7 +2337,8 @@ static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
pcie->supplies[i++].supply = "hvdd-pex-pll";
pcie->supplies[i++].supply = "hvdd-pex";
pcie->supplies[i++].supply = "vddio-pexctl-aud";
} else if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
} else if (of_device_is_compatible(np, "nvidia,tegra210-pcie") ||
of_device_is_compatible(np, "nvidia,tegra210b01-pcie")) {
pcie->num_supplies = 3;
pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
@@ -2164,6 +2518,14 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
"failed to get reset GPIO\n");
}
err = of_property_read_u32(port, "nvidia,disable-aspm-states",
&rp->aspm_state);
if (err < 0)
rp->aspm_state = 0;
rp->supports_clkreq = of_property_read_bool(port,
"supports-clkreq");
list_add_tail(&rp->list, &pcie->ports);
}
@@ -2352,6 +2714,10 @@ static const struct tegra_pcie_soc tegra20_pcie = {
.program_deskew_time = false,
.update_fc_timer = false,
.has_cache_bars = true,
.enable_wrap = false,
.has_aspm_l1 = false,
.has_aspm_l1ss = false,
.l1ss_rp_wake_fixup = false,
.ectl.enable = false,
};
@@ -2381,6 +2747,10 @@ static const struct tegra_pcie_soc tegra30_pcie = {
.program_deskew_time = false,
.update_fc_timer = false,
.has_cache_bars = false,
.enable_wrap = false,
.has_aspm_l1 = true,
.has_aspm_l1ss = false,
.l1ss_rp_wake_fixup = false,
.ectl.enable = false,
};
@@ -2402,6 +2772,10 @@ static const struct tegra_pcie_soc tegra124_pcie = {
.program_deskew_time = false,
.update_fc_timer = false,
.has_cache_bars = false,
.enable_wrap = false,
.has_aspm_l1 = true,
.has_aspm_l1ss = false,
.l1ss_rp_wake_fixup = false,
.ectl.enable = false,
};
@@ -2425,12 +2799,18 @@ static const struct tegra_pcie_soc tegra210_pcie = {
.program_deskew_time = true,
.update_fc_timer = true,
.has_cache_bars = false,
.enable_wrap = true,
.has_aspm_l1 = true,
.has_aspm_l1ss = true,
.l1ss_rp_wake_fixup = true,
.ectl = {
.regs = {
.rp_ectl_1_r1 = 0x0000001f,
.rp_ectl_2_r1 = 0x0000000f,
.rp_ectl_4_r1 = 0x00000067,
.rp_ectl_5_r1 = 0x55010000,
.rp_ectl_6_r1 = 0x00000001,
.rp_ectl_1_r2 = 0x0000001f,
.rp_ectl_2_r2 = 0x0000008f,
.rp_ectl_4_r2 = 0x000000c7,
.rp_ectl_5_r2 = 0x55010000,
@@ -2440,6 +2820,42 @@ static const struct tegra_pcie_soc tegra210_pcie = {
},
};
static const struct tegra_pcie_soc tegra210b01_pcie = {
.num_ports = 2,
.ports = tegra20_pcie_ports,
.msi_base_shift = 8,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
.pads_refclk_cfg0 = 0xb0b880b8,
/* FC threshold is bit[25:18] */
.update_fc_threshold = 0x01800000,
.has_pex_clkreq_en = true,
.has_pex_bias_ctrl = true,
.has_intr_prsnt_sense = true,
.has_cml_clk = true,
.has_gen2 = true,
.force_pca_enable = true,
.program_uphy = true,
.program_deskew_time = true,
.update_fc_timer = true,
.has_cache_bars = false,
.ectl = {
.regs = {
.rp_ectl_1_r1 = 0x00000027,
.rp_ectl_2_r1 = 0x0000000f,
.rp_ectl_4_r1 = 0x00000067,
.rp_ectl_5_r1 = 0x00000000,
.rp_ectl_6_r1 = 0x00000000,
.rp_ectl_1_r2 = 0x00000027,
.rp_ectl_2_r2 = 0x0000008f,
.rp_ectl_4_r2 = 0x000000c7,
.rp_ectl_5_r2 = 0x00000000,
.rp_ectl_6_r2 = 0x00000000,
},
.enable = true,
},
};
static const struct tegra_pcie_port_soc tegra186_pcie_ports[] = {
{ .pme.turnoff_bit = 0, .pme.ack_bit = 5 },
{ .pme.turnoff_bit = 8, .pme.ack_bit = 10 },
@@ -2466,12 +2882,17 @@ static const struct tegra_pcie_soc tegra186_pcie = {
.program_deskew_time = false,
.update_fc_timer = false,
.has_cache_bars = false,
.enable_wrap = false,
.has_aspm_l1 = true,
.has_aspm_l1ss = true,
.l1ss_rp_wake_fixup = false,
.ectl.enable = false,
};
static const struct of_device_id tegra_pcie_of_match[] = {
{ .compatible = "nvidia,tegra186-pcie", .data = &tegra186_pcie },
{ .compatible = "nvidia,tegra210-pcie", .data = &tegra210_pcie },
{ .compatible = "nvidia,tegra210b01-pcie", .data = &tegra210b01_pcie },
{ .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie },
{ .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie },
{ .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie },
@@ -2595,6 +3016,8 @@ static int tegra_pcie_probe(struct platform_device *pdev)
goto pm_runtime_put;
}
pci_add_flags(PCI_REASSIGN_ALL_BUS);
host->ops = &tegra_pcie_ops;
host->map_irq = tegra_pcie_map_irq;
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff. Show more