Compare commits

20 Commits

Author SHA1 Message Date
8746e76486 t210: add prods 2025-12-27 03:08:25 +00:00
60832e95c5 tegra: clk: correct divider algo
Negative divider_ux1 values previously were resolved by extra checks and
caused undefined behavior with div1_5_not_allowed
2025-12-27 03:08:14 +00:00
ea57749891 update tegra abi 2025-12-27 03:06:44 +00:00
d224e99d2c t210: assign better mmc clocks 2025-12-27 03:06:29 +00:00
33d34b5ac8 t210b01: use b01-specific sdhci config 2025-12-27 03:05:11 +00:00
71d2767b92 [SPLIT] t210b01: correct sdmmc pinmux and actmon 2025-12-27 03:04:45 +00:00
3484f914c9 t210b01: do not configure pex_io_dpd 2025-12-27 03:04:18 +00:00
57ae2f4faa sdhci-tegra: add support for t210b01
t210b01 is basically the same as t210 but uses different tap delays
2025-12-27 03:01:36 +00:00
c29dd5c99e [SPLIT] sdhci-tegra: fix tuning procedure 2025-12-27 03:00:47 +00:00
f7485a509b clk changes, test later 2025-12-06 16:46:50 +00:00
201a374323 pci: tegra: update lanes when incorrect 2025-12-02 02:06:18 +00:00
335d7b24e1 prods driver fix 2025-12-02 01:55:51 +00:00
3e038a2f95 pci: tegra: b01 fix 2025-12-02 01:55:38 +00:00
Krishna Yarlagadda
a52caa6411 NVIDIA: SAUCE: tegra: prod: use legacy prod settings
BugLink: https://bugs.launchpad.net/bugs/2080908

This is an integration squash commit of following commits:

- [INTG: NVIDIA INTERNAL] phy: tegra: xusb: Support prod-settings properties
- [INTG]: drivers: spi: add support for prod framework
- [INTG: NVIDIA INTERNAL]: mmc: host: Add prod framework changes
- i2c: Add prod settings support
- i2c: tegra: Add new prod setting support
- spi: tegra114: Add new prod settings
- sdhci: tegra: Add new prod settings
- [NV INTERNAL] xusb: tegra: Add new prod setting
- sdhci-tegra: host: Avoid access to prod settings on PreSi.
- tegra: prod: use legacy prod settings

http://nvbugs/4359070
http://nvbugs/4097475
http://nvbugs/4099482
http://nvbugs/4189448
http://nvbugs/4189442
http://nvbugs/4165914
http://nvbugs/4165933
http://nvbugs/4165918
http://nvbugs/4165919
http://nvbugs/4765671
http://nvbugs/4754882

Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com>
Signed-off-by: Laxman Dewangan <ldewangan@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>
2025-11-22 02:50:47 +00:00
Laxman Dewangan
9cf1f30f0a 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>
2025-11-22 02:47:25 +00:00
9b8622f15f clk: tegra210: update pll_c4 parameters 2025-11-20 05:31:22 +00:00
6298de0220 ftm4: compile fixes 2025-11-15 21:39:12 +00:00
c140515f8b gki: update tegra syms 2025-11-15 21:38:43 +00:00
Alvin Park
eb6f6367f5 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>
2025-11-15 19:06:52 +00:00
azkali
1f47e5c13e touchscreen: stm: forward port ftm4 touchscreen driver from L4T 2025-11-13 05:01:24 +00:00
28 changed files with 5555 additions and 211 deletions

View File

@@ -0,0 +1,978 @@
/*
* Copyright (c) 2014-2025, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/ {
host1x@50000000 {
sor@54540000 {
prod-settings {
#prod-cells = <3>;
prod_c_dp {
prod = <
0x0000005c 0x0f000f10 0x01000310 // SOR_NV_PDISP_SOR_PLL0_0 27:24=ICHPMP 0x01
// 11:08=VCOCAP 0x03
// 04:04=RESISTORSEL 0x01
0x00000060 0x03f00100 0x00400100 // SOR_NV_PDISP_SOR_PLL1_0 25:24=LVDSCM 0x00
// 23:20=LOADADJ 0x04
// 08:08=TMDS_TERM 0x01
0x00000068 0x00002000 0x00002000 // SOR_NV_PDISP_SOR_PLL3_0 13:13=PLVVDD_MODE 0x01
0x00000070 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LVDS_0
0x00000180 0x00000001 0x00000001 // SOR_NV_PDISP_SOR_DP_SPARE0_0 00:00=SEQ_ENABLE 0x01
>;
};
};
};
sor@54580000 {
prod-settings {
#prod-cells = <3>;
prod_list_hdmi_soc = "prod_c_hdmi_0m_54m", "prod_c_hdmi_54m_111m",
"prod_c_hdmi_111m_223m", "prod_c_hdmi_223m_300m",
"prod_c_hdmi_300m_600m";
prod {
prod = <
0x000003a0 0x00000001 0x00000001 // SOR_NV_PDISP_INPUT_CONTROL 00:00=HDMI_SRC_SELECT 0x1
0x0000005c 0x0f000700 0x01000000 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x0
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333A3A3A // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3A
// 15:08=LANE1_DP_LANE1 0x3A
// 07:00=LANE0_DP_LANE2 0x3A
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00401000 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x10
>;
};
prod_c_hdmi_0m_54m {
prod = <
0x000003a0 0x000000002 0x00000002 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x1
0x0000005c 0x0f000700 0x01000000 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x0
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333A3A3A // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3A
// 15:08=LANE1_DP_LANE1 0x3A
// 07:00=LANE0_DP_LANE2 0x3A
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00401000 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x10
>;
};
prod_c_hdmi_54m_111m {
prod = <
0x000003a0 0x00000002 0x00000002 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x1
0x0000005c 0x0f000700 0x01000100 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x1
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333A3A3A // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3A
// 15:08=LANE1_DP_LANE1 0x3A
// 07:00=LANE0_DP_LANE2 0x3A
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00404000 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x40
>;
};
prod_c_hdmi_111m_223m {
prod = <
0x000003a0 0x00000002 0x00000000 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x0
0x0000005c 0x0f000700 0x01000300 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x3
// 27:24=ICHPMP 0x1
0x00000060 0xff0fe0ff 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333A3A3A // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3A
// 15:08=LANE1_DP_LANE1 0x3A
// 07:00=LANE0_DP_LANE2 0x3A
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00406600 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x66
>;
};
prod_c_hdmi_223m_300m {
prod = <
0x000003a0 0x00000002 0x00000000 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x0
0x0000005c 0x0f000700 0x01000300 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x3
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x0A000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0xA
0x00000138 0xffffffff 0x333F3F3F // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3F
// 15:08=LANE1_DP_LANE1 0x3F
// 07:00=LANE0_DP_LANE2 0x3F
0x00000148 0xffffffff 0x00171717 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x17
// 15:08=LANE1_DP_LANE1 0x17
// 07:00=LANE0_DP_LANE2 0x17
0x00000170 0x0040ff00 0x00406600 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x66
>;
};
prod_c_hdmi_300m_600m {
prod = <
0x000003a0 0x00000002 0x00000002 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x1
0x0000005c 0x0f000700 0x01000300 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x3
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333F3F3F // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3f
// 15:08=LANE1_DP_LANE1 0x3f
// 07:00=LANE0_DP_LANE2 0x3f
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00406600 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x66
>;
};
/* HDMI prod-settings for fall-back to old DT config
* when prod_list_hdmi_soc/board are not found */
prod_c_54M {
prod = <
0x000003a0 0x000000002 0x00000002 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x1
0x0000005c 0x0f000700 0x01000000 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x0
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333A3A3A // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3A
// 15:08=LANE1_DP_LANE1 0x3A
// 07:00=LANE0_DP_LANE2 0x3A
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00401000 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x10
>;
};
prod_c_75M {
prod = <
0x000003a0 0x00000002 0x00000002 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x1
0x0000005c 0x0f000700 0x01000100 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x1
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333A3A3A // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3A
// 15:08=LANE1_DP_LANE1 0x3A
// 07:00=LANE0_DP_LANE2 0x3A
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00404000 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x40
>;
};
prod_c_150M {
prod = <
0x000003a0 0x00000002 0x00000000 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x0
0x0000005c 0x0f000700 0x01000300 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x3
// 27:24=ICHPMP 0x1
0x00000060 0xff0fe0ff 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333A3A3A // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3A
// 15:08=LANE1_DP_LANE1 0x3A
// 07:00=LANE0_DP_LANE2 0x3A
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00406600 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x66
>;
};
prod_c_300M {
prod = <
0x000003a0 0x00000002 0x00000000 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x0
0x0000005c 0x0f000700 0x01000300 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x3
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x0A000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0xA
0x00000138 0xffffffff 0x333F3F3F // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3F
// 15:08=LANE1_DP_LANE1 0x3F
// 07:00=LANE0_DP_LANE2 0x3F
0x00000148 0xffffffff 0x00171717 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x17
// 15:08=LANE1_DP_LANE1 0x17
// 07:00=LANE0_DP_LANE2 0x17
0x00000170 0x0040ff00 0x00406600 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x66
>;
};
prod_c_600M {
prod = <
0x000003a0 0x00000002 0x00000002 // SOR_NV_PDISP_INPUT_CONTROL 01:01=ARM_VIDEO_RANGE 0x1
0x0000005c 0x0f000700 0x01000300 // SOR_NV_PDISP_SOR_PLL0_0 11:08=VCOCAP 0x3
// 27:24=ICHPMP 0x1
0x00000060 0x00f01f00 0x00401380 // SOR_NV_PDISP_SOR_PLL1_0 08:08=TMDS_TERM 0x1
// 12:09=TMDS_TERMADJ 0x9
// 23:20=LOADADJ 0x4
0x00000068 0x0f000000 0x08000000 // SOR_NV_PSIDP_SOR_PLL3_0 27:24=BG_VREF_LEVEL 0x8
0x00000138 0xffffffff 0x333F3F3F // SOR_NV_PDISP_SOR_LANE_DRIVE_CURRENT0_0
// 31:24=LANE3_DP_LANE3 0x33
// 23:16=LANE2_DP_LANE0 0x3f
// 15:08=LANE1_DP_LANE1 0x3f
// 07:00=LANE0_DP_LANE2 0x3f
0x00000148 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LANE_PREEMPHASIS0_0
// 31:24=LANE3_DP_LANE3 0x00
// 23:16=LANE2_DP_LANE0 0x00
// 15:08=LANE1_DP_LANE1 0x00
// 07:00=LANE0_DP_LANE2 0x00
0x00000170 0x0040ff00 0x00406600 // SOR_NV_PDISP_SOR_DP_PADCTL0_0
// 22:22=TX_PU 0x1
// 15:08=TX_PU_VALUE 0x66
>;
};
prod_c_dp {
prod = <
0x0000005c 0x0f000f10 0x01000310 // SOR_NV_PDISP_SOR_PLL0_0 27:24=ICHPMP 0x01
// 11:08=VCOCAP 0x03
// 04:04=RESISTORSEL 0x01
0x00000060 0x03f00100 0x00400100 // SOR_NV_PDISP_SOR_PLL1_0 25:24=LVDSCM 0x00
// 23:20=LOADADJ 0x04
// 08:08=TMDS_TERM 0x01
0x00000068 0x00002000 0x00002000 // SOR_NV_PDISP_SOR_PLL3_0 13:13=PLVVDD_MODE 0x01
0x00000070 0xffffffff 0x00000000 // SOR_NV_PDISP_SOR_LVDS_0
0x00000180 0x00000001 0x00000001 // SOR_NV_PDISP_SOR_DP_SPARE0_0 00:00=SEQ_ENABLE 0x01
>;
};
};
};
dpaux@545c0000 {
prod-settings {
#prod-cells = <3>;
prod_c_dpaux_dp {
prod = <
0x00000124 0x000037fe 0x000024c2
>;
};
prod_c_dpaux_hdmi {
prod = <
0x00000124 0x00000700 0x00000400
>;
};
};
};
dpaux@54040000 {
prod-settings {
#prod-cells = <3>;
prod_c_dpaux_dp {
prod = <
0x00000124 0x000037fe 0x000024c2
>;
};
prod_c_dpaux_hdmi {
prod = <
0x00000124 0x00000700 0x00000400
>;
};
};
};
};
pinmux@700008d4 {
prod-settings {
#prod-cells = <4>;
prod {
status = "okay";
nvidia,prod-boot-init;
prod = <0 0x1C4 0xF7F7F000 0x51212000
0 0x128 0x01F1F000 0x01010000 //GPIO_PZ0 DRVUP-DN
0 0x12C 0x01F1F000 0x01010000 //GPIO_PZ1 DRVUP-DN
0 0x1C8 0xF0003FFD 0x00001040
0 0x1DC 0xF7F7F000 0x51212000
0 0x1E0 0xF0003FFD 0x00001040
0 0x23C 0x01F1F000 0x01F1F000 //TOUCH_CLK DRVUP-DN
0 0x20 0x01F1F000 0x01010000 //AUD_MCLK
0 0x44 0x01F1F000 0x01010000 //CAM1_MCLK DRVUP-DN
0 0x50 0x01F1F000 0x01010000 //CAM2_MCLK DRVUP-DN
0 0x58 0x01F1F000 0x01010000 //CAM_AF_EN DRVUP-DN
0 0x5C 0x01F1F000 0x01010000 //CAM_FLASH_EN DRVUP-DN
0 0xA0 0x01F1F000 0x01010000 //I2S4B DIN
0 0xA4 0x01F1F000 0x01010000 //I2S4B DOUT
0 0xA8 0x01F1F000 0x01010000 //I2S4B FS
0 0xAC 0x01F1F000 0x01010000 //I2S4B SCLK
0 0xB0 0x01F1F000 0x01F1F000 //DMIC1 CLK
0 0xB4 0x01F1F000 0x01F1F000 //DMIC1 DATA
0 0xB8 0x01F1F000 0x01F1F000 //DMIC2 CLK
0 0xBC 0x01F1F000 0x01F1F000 //DMIC2 DATA
0 0xC0 0x01F1F000 0x01F1F000 //DMIC3 CLK
0 0xC4 0x01F1F000 0x01F1F000 //DMIC3 DATA
1 0x00 0x00007200 0x00002000
1 0x04 0x00007200 0x00002000
1 0x08 0x00007200 0x00002000
1 0x0C 0x00007200 0x00002000
1 0x10 0x00007200 0x00002000
1 0x14 0x00007200 0x00002000
1 0x1C 0x00007200 0x00002000
1 0x20 0x00007200 0x00002000
1 0x24 0x00007200 0x00002000
1 0x28 0x00007200 0x00002000
1 0x2C 0x00007200 0x00002000
1 0x30 0x00007200 0x00002000
1 0x160 0x00001000 0x00001000>;
};
i2s2_prod {
prod = <0 0xB0 0x01F1F000 0x01010000 // FS
0 0xB4 0x01F1F000 0x01010000 // DIN
0 0xB8 0x01F1F000 0x01010000 // DOUT
0 0xBC 0x01F1F000 0x01010000>; // SCLK
};
spi1_prod {
nvidia,prod-boot-init;
prod = <0 0x200 0xF0000000 0x50000000
0 0x204 0xF0000000 0x50000000
0 0x208 0xF0000000 0x50000000
0 0x20c 0xF0000000 0x50000000
0 0x210 0xF0000000 0x50000000
1 0x50 0x00006000 0x00006040
1 0x54 0x00006000 0x00006040
1 0x58 0x00006000 0x00006040
1 0x5c 0x00006000 0x00006040
1 0x60 0x00006000 0x00006040>;
};
spi2_prod {
nvidia,prod-boot-init;
prod = <0 0x214 0xF0000000 0xd0000000
0 0x218 0xF0000000 0xd0000000
0 0x21c 0xF0000000 0xd0000000
0 0x220 0xF0000000 0xd0000000
0 0x224 0xF0000000 0xd0000000
1 0x64 0x00006000 0x00006040
1 0x68 0x00006000 0x00006040
1 0x6c 0x00006000 0x00006040
1 0x70 0x00006000 0x00006040
1 0x74 0x00006000 0x00006040>;
};
spi3_prod {
nvidia,prod-boot-init;
prod = <0 0xcc 0x01404000 0x01414000
0 0xd0 0x01404000 0x01414000
0 0x140 0x01404000 0x01414000
0 0x144 0x01404000 0x01414000>;
};
spi4_prod {
nvidia,prod-boot-init;
prod = <0 0x268 0x01404000 0x01414000
0 0x26c 0x01404000 0x01414000
0 0x270 0x01404000 0x01414000
0 0x274 0x01404000 0x01414000>;
};
i2c0_prod {
nvidia,prod-boot-init;
prod = <0 0xD4 0x01F1F000 0x0001F000
0 0xD8 0x01F1F000 0x0001F000
1 0xBC 0x00001100 0x00000000
1 0xC0 0x00001100 0x00000000>;
};
i2c1_prod {
nvidia,prod-boot-init;
prod = <0 0xDC 0x01F1F000 0x0001F000
0 0xE0 0x01F1F000 0x0001F000
1 0xC4 0x00001100 0x00000000
1 0xC8 0x00001100 0x00000000>;
};
i2c2_prod {
nvidia,prod-boot-init;
prod = <0 0xE4 0x01F1F000 0x0001F000
0 0xE8 0x01F1F000 0x0001F000
1 0xCC 0x00001100 0x00000000
1 0xD0 0x00001100 0x00000000
0 0x60 0x01F1F000 0x0001F000
0 0x64 0x01F1F000 0x0001F000
1 0xD4 0x00001100 0x00000000
1 0xD8 0x00001100 0x00000000>;
};
i2c4_prod {
nvidia,prod-boot-init;
prod = <0 0x198 0x01F1F000 0x0001F000
0 0x19C 0x01F1F000 0x0001F000
1 0xDC 0x00001100 0x00000000
1 0xE0 0x00001100 0x00000000>;
};
i2c0_hs_prod {
prod = <0 0xD4 0x01F1F000 0x01F1F000
0 0xD8 0x01F1F000 0x01F1F000
1 0xBC 0x00001100 0x00001000
1 0xC0 0x00001100 0x00001000>;
};
i2c1_hs_prod {
prod = <0 0xDC 0x01F1F000 0x01F1F000
0 0xE0 0x01F1F000 0x01F1F000
1 0xC4 0x00001100 0x00001000
1 0xC8 0x00001100 0x00001000>;
};
i2c2_hs_prod {
prod = <0 0xE4 0x01F1F000 0x01F1F000
0 0xE8 0x01F1F000 0x01F1F000
1 0xCC 0x00001100 0x00001000
1 0xD0 0x00001100 0x00001000
0 0x60 0x01F1F000 0x01F1F000
0 0x64 0x01F1F000 0x01F1F000
1 0xD4 0x00001100 0x00001000
1 0xD8 0x00001100 0x00001000>;
};
i2c4_hs_prod {
prod = <0 0x198 0x01F1F000 0x01F1F000
0 0x19C 0x01F1F000 0x01F1F000
1 0xDC 0x00001100 0x00001000
1 0xE0 0x00001100 0x00001000>;
};
};
};
spi@7000d400 {
prod-settings {
#prod-cells = <3>;
prod {
prod = <0x04 0x00000fff 0x0>;
};
prod_c_flash {
status = "disabled";
/* enabled for spi flash rom */
prod = <0x04 0x0000003f 0x00000007>;
};
prod_c_loop {
status = "disabled";
/* enabled for spi loopback mode */
prod = <0x04 0x00000fff 0x0000044b>;
};
};
};
spi@7000d600 {
prod-settings {
#prod-cells = <3>;
prod {
prod = <0x04 0x00000fff 0x0>;
};
prod_c_flash {
status = "disabled";
/* enabled for spi flash rom */
prod = <0x04 0x0000003f 0x00000006>;
};
prod_c_loop {
status = "disabled";
/* enabled for spi loopback mode */
prod = <0x04 0x00000fff 0x0000044b>;
};
};
};
spi@7000d800 {
prod-settings {
#prod-cells = <3>;
prod {
prod = <0x04 0x00000fff 0x0>;
};
prod_c_flash {
status = "disabled";
/* enabled for spi flash rom */
prod = <0x04 0x0000003f 0x00000008>;
};
prod_c_loop {
status = "disabled";
/* enabled for spi loopback mode */
prod = <0x04 0x00000fff 0x0000044b>;
};
};
};
spi@7000da00 {
prod-settings {
#prod-cells = <3>;
prod {
prod = <0x04 0x00000fff 0x0>;
};
prod_c_flash {
status = "disabled";
/* enabled for spi loopback mode */
prod = <0x04 0x00000fff 0x0000044b>;
};
};
};
padctl@7009f000 {
prod-settings {
#prod-cells = <4>;
prod_c_bias {
prod = <
0 0x00000284 0x0000003f 0x0000003a
>;
};
prod_c_bias_a02 {
prod = <
0 0x00000284 0x0000003f 0x00000038
>;
};
prod_c_utmi0 {
prod = <
0 0x00000084 0x00000020 0x00000040
>;
};
prod_c_utmi1 {
prod = <
0 0x000000C4 0x00000020 0x00000040
>;
};
prod_c_utmi2 {
prod = <
0 0x00000104 0x00000020 0x00000040
>;
};
prod_c_utmi3 {
prod = <
0 0x00000144 0x00000020 0x00000040
>;
};
prod_c_ss0 {
prod = <
0 0x00000a60 0x00030000 0x00020000
0 0x00000a64 0x0000ffff 0x000000fc
0 0x00000a68 0xffffffff 0xc0077f1f
0 0x00000a74 0xffffffff 0xfcf01368
>;
};
prod_c_ss1 {
prod = <
0 0x00000aa0 0x00030000 0x00020000
0 0x00000aa4 0x0000ffff 0x000000fc
0 0x00000aa8 0xffffffff 0xc0077f1f
0 0x00000ab4 0xffffffff 0xfcf01368
>;
};
prod_c_ss2 {
prod = <
0 0x00000ae0 0x00030000 0x00020000
0 0x00000ae4 0x0000ffff 0x000000fc
0 0x00000ae8 0xffffffff 0xc0077f1f
0 0x00000af4 0xffffffff 0xfcf01368
>;
};
prod_c_ss3 {
prod = <
0 0x00000b20 0x00030000 0x00020000
0 0x00000b24 0x0000ffff 0x000000fc
0 0x00000b28 0xffffffff 0xc0077f1f
0 0x00000b34 0xffffffff 0xfcf01368
>;
};
prod_c_hsic0 {
prod = <
0 0x00000344 0x0000001f 0x0000001c
>;
};
prod_c_hsic1 {
prod = <
0 0x00000344 0x0000001f 0x0000001c
>;
};
};
};
sata@70020000 {
prod-settings {
#prod-cells = <4>;
prod {
prod = <
0 0x00000680 0x00000001 0x00000001 // SATA_CHX_INDEX_0 0
0 0x00000690 0x00000FFF 0x00000715 // SATA_CHX_PHY_CTRL1_GEN1_0 31:0
0 0x00000694 0x000FF0FF 0x0000E01B // SATA_CHX_PHY_CTRL1_GEN2_0 31:0
0 0x000006d0 0xFFFFFFFF 0x00AB000F // SATA_CHX_PHY_CTRL11_0 31:0
0 0x00000170 0x0000F000 0x00007000 // NV_PROJ_SATA_FIFO_0 15:12
2 0x00000960 0x03000000 0x01000000 // XUSB_PADCTL_UPHY_MISC_PAD_S0_CTL_1_0 25:24
>;
};
};
};
mmc@700b0600 {
prod-settings {
#prod-cells = <3>;
prod_c_ds {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_ddr52 {
prod = <0x00000100 0x1FFF0000 0x00000000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs200 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00004000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs400 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00004000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs533 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00002000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30000505 0x30000505>;
};
prod {
prod = <
0x0000100 0x1FFF000E 0x8090028 // SDMMC_VENDOR_CLOCK_CNTRL_0 28:24=TRIM_VAL 0x5
// 23:16=TAP_VAL 0x9
// 05:05=SDR50_TUNING_OVERRIDE 0x1
// 03:03=PADPIPE_CLKEN_OVERRIDE 0x1
// 02:02=SPI_MODE_CLKEN_OVERRIDE 0x0
// 01:01=INPUT_IO_CLK 0x0
0x0000010C 0x00003F00 0x00002800 //SDMMC_VENDOR_CAP_OVERRIDES_0 13:8=DQS_TRIM_VAL 0x28
0x00001C0 0x08001FC0 0x8000040 // SDMMC_VENDOR_TUNING_CNTRL0_0 12:06=MUL_M 0x1
// 27:27=RETUNING_REQ_EN_ON_CRC_ERR_DETECTION 0x1
0x00001C4 0x00000077 0x0 // SDMMC_VENDOR_TUNING_CNTRL1_0 02:00=STEP_SIZE_SDR50 0x0
// 06:04=STEP_SIZE_SDR104_HS200 0x0
0x0000120 0x00020001 0x00001 // SDMMC_VENDOR_MISC_CNTRL_0 0:0=ERASE_TIMEOUT_LIMIT 0x1
// 17:17=SDMMC_SPARE1[1] 0x0
0x0000128 0x43000000 0x00000000 // SDMMC_VENDOR_MISC_CNTRL2_0 30:30=SDMMC_CLK_OVR_ON 0x0
// 25:25=ADMA3_CLKEN_OVERRIDE 0x0
// 24:24=CQE_CLKEN_OVERRIDE 0x0
0x00001F0 0x00080000 0x00080000 // SDMMC_IO_SPARE_0 19:19=SPARE_OUT[3] 0x1
>;
};
};
};
mmc@700b0400 {
prod-settings {
#prod-cells = <3>;
prod_c_ds {
prod = <0x00000100 0x00FF0000 0x00010000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x3000007D>;
};
prod_c_hs {
prod = <0x00000100 0x00FF0000 0x00010000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x3000007D>;
};
prod_c_sdr12 {
prod = <0x00000100 0x00FF0000 0x00010000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_sdr25 {
prod = <0x00000100 0x00FF0000 0x00010000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_sdr50 {
prod = <0x00000100 0x00FF0000 0x00010000
0x000001C0 0x0000E000 0x00008000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_sdr104 {
prod = <0x00000100 0x00FF0000 0x00010000
0x000001C0 0x0000E000 0x00004000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_ddr52 {
prod = <0x00000100 0x1FFF0000 0x00000000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod {
prod = <
0x0000100 0x1FFF000E 0x3090028 // SDMMC_VENDOR_CLOCK_CNTRL_0 28:24=TRIM_VAL 0x5
// 23:16=TAP_VAL 0x9
// 05:05=SDR50_TUNING_OVERRIDE 0x1
// 03:03=PADPIPE_CLKEN_OVERRIDE 0x1
// 02:02=SPI_MODE_CLKEN_OVERRIDE 0x0
// 01:01=INPUT_IO_CLK 0x0
0x00001C0 0x08001FC0 0x8000040 // SDMMC_VENDOR_TUNING_CNTRL0_0 12:06=MUL_M 0x1
// 27:27=RETUNING_REQ_EN_ON_CRC_ERR_DETECTION 0x1
0x00001C4 0x00000077 0x0 // SDMMC_VENDOR_TUNING_CNTRL1_0 02:00=STEP_SIZE_SDR50 0x0
// 06:04=STEP_SIZE_SDR104_HS200 0x0
0x0000120 0x00020001 0x00001 // SDMMC_VENDOR_MISC_CNTRL_0 0:0=ERASE_TIMEOUT_LIMIT 0x1
// 17:17=SDMMC_SPARE1[1] 0x0
0x0000128 0x43000000 0x00000000 // SDMMC_VENDOR_MISC_CNTRL2_0 30:30=SDMMC_CLK_OVR_ON 0x0
// 25:25=ADMA3_CLKEN_OVERRIDE 0x0
// 24:24=CQE_CLKEN_OVERRIDE 0x0
0x00001F0 0x00080000 0x00080000 // SDMMC_IO_SPARE_0 19:19=SPARE_OUT[3] 0x1
>;
};
};
};
mmc@700b0200 {
prod-settings {
#prod-cells = <3>;
prod_c_ds {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_sdr12 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_sdr25 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_sdr50 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00008000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_sdr104 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00004000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_ddr52 {
prod = <0x00000100 0x1FFF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs200 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00004000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs400 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00004000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30000505>;
};
prod_c_hs533 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00002000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30000505 0x30000505>;
};
prod {
prod = <
0x0000100 0x1FFF000E 0x8090028 // SDMMC_VENDOR_CLOCK_CNTRL_0 28:24=TRIM_VAL 0x5
// 23:16=TAP_VAL 0x9
// 05:05=SDR50_TUNING_OVERRIDE 0x1
// 03:03=PADPIPE_CLKEN_OVERRIDE 0x1
// 02:02=SPI_MODE_CLKEN_OVERRIDE 0x0
// 01:01=INPUT_IO_CLK 0x0
0x00001C0 0x08001FC0 0x8000040 // SDMMC_VENDOR_TUNING_CNTRL0_0 12:06=MUL_M 0x1
// 27:27=RETUNING_REQ_EN_ON_CRC_ERR_DETECTION 0x1
0x00001C4 0x00000077 0x0 // SDMMC_VENDOR_TUNING_CNTRL1_0 02:00=STEP_SIZE_SDR50 0x0
// 06:04=STEP_SIZE_SDR104_HS200 0x0
0x0000120 0x00020001 0x00001 // SDMMC_VENDOR_MISC_CNTRL_0 0:0=ERASE_TIMEOUT_LIMIT 0x1
// 17:17=SDMMC_SPARE1[1] 0x0
0x0000128 0x43000000 0x00000000 // SDMMC_VENDOR_MISC_CNTRL2_0 30:30=SDMMC_CLK_OVR_ON 0x0
// 25:25=ADMA3_CLKEN_OVERRIDE 0x0
// 24:24=CQE_CLKEN_OVERRIDE 0x0
0x00001F0 0x00080000 0x00080000 // SDMMC_IO_SPARE_0 19:19=SPARE_OUT[3] 0x1
>;
};
};
};
mmc@700b0000 {
prod-settings {
#prod-cells = <3>;
prod_c_ds {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x3000007D>;
};
prod_c_hs {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x3000007D>;
};
prod_c_sdr12 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_sdr25 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_sdr50 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00008000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_sdr104 {
prod = <0x00000100 0x00FF0000 0x00040000
0x000001C0 0x0000E000 0x00004000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod_c_ddr52 {
prod = <0x00000100 0x1FFF0000 0x00000000
0x000001E0 0x0000000F 0x00000007
0x000001E4 0x30077F7F 0x30007B7B>;
};
prod {
prod = <
0x0000100 0x1FFF000E 0x2090028 // SDMMC_VENDOR_CLOCK_CNTRL_0 28:24=TRIM_VAL 0x5
// 23:16=TAP_VAL 0x9
// 05:05=SDR50_TUNING_OVERRIDE 0x1
// 03:03=PADPIPE_CLKEN_OVERRIDE 0x1
// 02:02=SPI_MODE_CLKEN_OVERRIDE 0x0
// 01:01=INPUT_IO_CLK 0x0
0x00001C0 0x08001FC0 0x8000040 // SDMMC_VENDOR_TUNING_CNTRL0_0 12:06=MUL_M 0x1
// 27:27=RETUNING_REQ_EN_ON_CRC_ERR_DETECTION 0x1
0x00001C4 0x00000077 0x0 // SDMMC_VENDOR_TUNING_CNTRL1_0 02:00=STEP_SIZE_SDR50 0x0
// 06:04=STEP_SIZE_SDR104_HS200 0x0
0x0000120 0x00020001 0x00001 // SDMMC_VENDOR_MISC_CNTRL_0 0:0=ERASE_TIMEOUT_LIMIT 0x1
// 17:17=SDMMC_SPARE1[1] 0x0
0x0000128 0x43000000 0x00000000 // SDMMC_VENDOR_MISC_CNTRL2_0 30:30=SDMMC_CLK_OVR_ON 0x0
// 25:25=ADMA3_CLKEN_OVERRIDE 0x0
// 24:24=CQE_CLKEN_OVERRIDE 0x0
0x00001F0 0x00080000 0x00080000 // SDMMC_IO_SPARE_0 19:19=SPARE_OUT[3] 0x1
>;
};
};
};
mipi@700e3000 {
prod-settings {
#prod-cells = <3>;
prod_c_dphy_dsi {
prod = <
0x00000038 0x00001f00 0x00000200 //MIPI_CAL_DSIA_MIPI_CAL_CONFIG_0 12:8=MIPI_CAL_HSPUOSDSIA 0x2
0x0000003c 0x00001f00 0x00000200 //MIPI_CAL_DSIB_MIPI_CAL_CONFIG_0 12:8=MIPI_CAL_HSPUOSDSIB 0x2
0x00000040 0x00001f00 0x00000200 //MIPI_CAL_DSIC_MIPI_CAL_CONFIG_0 12:8=MIPI_CAL_HSPUOSDSIC 0x2
0x00000044 0x00001f00 0x00000200 //MIPI_CAL_DSID_MIPI_CAL_CONFIG_0 12:8=MIPI_CAL_HSPUOSDSID 0x2
0x0000005c 0x00000f00 0x00000300 //MIPI_CAL_MIPI_BIAS_PAD_CFG1_0 11:8=PAD_DRIV_UP_REF 0x3
0x00000060 0x000f00f0 0x00010010 //MIPI_CAL_MIPI_BIAS_PAD_CFG2_0 07:04=PAD_VAUXP_LEVEL 0x1
// 19:16=PAD_VCLAMP_LEVEL 0x1
0x00000064 0x0000001f 0x00000002 //MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2_0 04:00=MIPI_CAL_HSCLKPUOSDSIA 0x2
0x00000068 0x0000001f 0x00000002 //MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2_0 04:00=MIPI_CAL_HSCLKPUOSDSIB 0x2
0x00000070 0x0000001f 0x00000002 //MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2_0 04:00=MIPI_CAL_HSCLKPUOSDSIC 0x2
0x00000074 0x0000001f 0x00000002 //MIPI_CAL_DSID_MIPI_CAL_CONFIG_2_0 04:00=MIPI_CAL_HSCLKPUOSDSID 0x2
>;
};
};
};
};

View File

@@ -1321,11 +1321,9 @@
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
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";
};
@@ -1388,8 +1386,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";

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,11 @@
pcie@1003000 {
compatible = "nvidia,tegra210b01-pcie";
// do not config pex_io_dpd on b01
/delete-property/ pinctrl-names;
/delete-property/ pinctrl-0;
/delete-property/ pinctrl-1;
};
host1x@50000000 {
@@ -35,36 +40,50 @@
compatible = "nvidia,tegra210b01-car";
};
// pinmux@700008d4 {
// status = "okay";
// sdmmc1_1v8_drv: pinmux-sdmmc1-1v8-drv {
// sdmmc1 {
// nvidia,pull-down-strength = <0x8>;
// nvidia,pull-up-strength = <0x8>;
// };
// };
actmon@6000c800 {
clocks = <&tegra_car TEGRA210_CLK_ACTMON>,
<&bpmp 0>;
clock-names = "actmon", "emc";
resets = <&tegra_car 119>;
reset-names = "actmon";
///delete-property/ operating-points-v2;
///delete-property/ interconnects;
///delete-property/ interconnect-names;
};
// sdmmc1_3v3_drv: pinmux-sdmmc1-3v3-drv {
// sdmmc1 {
// nvidia,pull-down-strength = <0x8>;
// nvidia,pull-up-strength = <0x8>;
// };
// };
pinmux@700008d4 {
sdmmc1_1v8_drv: pinmux-sdmmc1-1v8-drv {
sdmmc1 {
nvidia,pins = "drive_sdmmc1";
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
// sdmmc3_1v8_drv: pinmux-sdmmc3-1v8-drv {
// sdmmc3 {
// nvidia,pull-down-strength = <0x8>;
// nvidia,pull-up-strength = <0x8>;
// };
// };
sdmmc1_3v3_drv: pinmux-sdmmc1-3v3-drv {
sdmmc1 {
nvidia,pins = "drive_sdmmc1";
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
// sdmmc3_3v3_drv: pinmux-sdmmc3-3v3-drv {
// sdmmc3 {
// nvidia,pull-down-strength = <0x8>;
// nvidia,pull-up-strength = <0x8>;
// };
// };
// };
sdmmc3_1v8_drv: pinmux-sdmmc3-1v8-drv {
sdmmc3 {
nvidia,pins = "drive_sdmmc3";
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
sdmmc3_3v3_drv: pinmux-sdmmc3-3v3-drv {
sdmmc3 {
nvidia,pins = "drive_sdmmc3";
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
};
i2c@7000d100 {
/delete-property/ pinctrl-0;
@@ -92,30 +111,45 @@
/delete-node/ external-memory-controller@7001b000;
mmc@700b0000 {
compatible = "nvidia,tegra210b01-sdhci";
nvidia,default-tap = <0xb>;
nvidia,default-trim = <0xe>;
assigned-clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
<&tegra_car TEGRA210_CLK_PLL_C4_OUT2>,
<&tegra_car TEGRA210_CLK_PLL_C4>;
assigned-clock-parents = <&tegra_car TEGRA210_CLK_PLL_C4_OUT2>;
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>;
};
mmc@700b0200 {
compatible = "nvidia,tegra210b01-sdhci";
nvidia,default-tap = <0x8>;
nvidia,default-trim = <0xd>;
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>;
};
mmc@700b0400 {
compatible = "nvidia,tegra210b01-sdhci";
nvidia,default-tap = <0xb>;
nvidia,default-trim = <0x12>;
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>;
};
mmc@700b0600 {
compatible = "nvidia,tegra210b01-sdhci";
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>;
nvidia,dqs-trim = <0x28>;
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>;
};
/* Tegra210B01 has MBIST patched and is missing VI unit */

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 },
};

View File

@@ -1705,7 +1705,6 @@ static struct div_nmp pllss_nmp = {
static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = {
{ 38400000, 998400000, 52, 2, 1, 0 },
{ 38400000, 787200000, 41, 2, 1, 0 },
{ 0, 0, 0, 0, 0, 0 },
};
@@ -2177,9 +2176,9 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_i2s0] = { .dt_id = TEGRA210_CLK_I2S0, .present = true },
[tegra_clk_apbdma] = { .dt_id = TEGRA210_CLK_APBDMA, .present = true },
[tegra_clk_kfuse] = { .dt_id = TEGRA210_CLK_KFUSE, .present = true },
[tegra_clk_sbc1_9] = { .dt_id = TEGRA210_CLK_SBC1, .present = true },
[tegra_clk_sbc2_9] = { .dt_id = TEGRA210_CLK_SBC2, .present = true },
[tegra_clk_sbc3_9] = { .dt_id = TEGRA210_CLK_SBC3, .present = true },
[tegra_clk_sbc1_9] = { .dt_id = TEGRA210_CLK_SBC1, .use_integer_div = true, .present = true },
[tegra_clk_sbc2_9] = { .dt_id = TEGRA210_CLK_SBC2, .use_integer_div = true, .present = true },
[tegra_clk_sbc3_9] = { .dt_id = TEGRA210_CLK_SBC3, .use_integer_div = true, .present = true },
[tegra_clk_i2c5] = { .dt_id = TEGRA210_CLK_I2C5, .present = true },
[tegra_clk_csi] = { .dt_id = TEGRA210_CLK_CSI, .present = true },
[tegra_clk_i2c2] = { .dt_id = TEGRA210_CLK_I2C2, .present = true },
@@ -2189,20 +2188,20 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_bsev] = { .dt_id = TEGRA210_CLK_BSEV, .present = true },
[tegra_clk_uartd_8] = { .dt_id = TEGRA210_CLK_UARTD, .present = true },
[tegra_clk_i2c3] = { .dt_id = TEGRA210_CLK_I2C3, .present = true },
[tegra_clk_sbc4_9] = { .dt_id = TEGRA210_CLK_SBC4, .present = true },
[tegra_clk_sbc4_9] = { .dt_id = TEGRA210_CLK_SBC4, .use_integer_div = true, .present = true },
[tegra_clk_sdmmc3_9] = { .dt_id = TEGRA210_CLK_SDMMC3, .present = true },
[tegra_clk_pcie] = { .dt_id = TEGRA210_CLK_PCIE, .present = true },
[tegra_clk_owr_8] = { .dt_id = TEGRA210_CLK_OWR, .present = true },
[tegra_clk_afi] = { .dt_id = TEGRA210_CLK_AFI, .present = true },
[tegra_clk_csite_8] = { .dt_id = TEGRA210_CLK_CSITE, .present = true },
[tegra_clk_soc_therm_8] = { .dt_id = TEGRA210_CLK_SOC_THERM, .present = true },
[tegra_clk_soc_therm_8] = { .dt_id = TEGRA210_CLK_SOC_THERM, .use_integer_div = true, .present = true },
[tegra_clk_dtv] = { .dt_id = TEGRA210_CLK_DTV, .present = true },
[tegra_clk_i2cslow] = { .dt_id = TEGRA210_CLK_I2CSLOW, .present = true },
[tegra_clk_i2cslow] = { .dt_id = TEGRA210_CLK_I2CSLOW, .use_integer_div = true, .present = true },
[tegra_clk_tsec_8] = { .dt_id = TEGRA210_CLK_TSEC, .present = true },
[tegra_clk_xusb_host] = { .dt_id = TEGRA210_CLK_XUSB_HOST, .present = true },
[tegra_clk_csus] = { .dt_id = TEGRA210_CLK_CSUS, .present = true },
[tegra_clk_mselect] = { .dt_id = TEGRA210_CLK_MSELECT, .present = true },
[tegra_clk_tsensor] = { .dt_id = TEGRA210_CLK_TSENSOR, .present = true },
[tegra_clk_tsensor] = { .dt_id = TEGRA210_CLK_TSENSOR, .use_integer_div = true, .present = true },
[tegra_clk_i2s3] = { .dt_id = TEGRA210_CLK_I2S3, .present = true },
[tegra_clk_i2s4] = { .dt_id = TEGRA210_CLK_I2S4, .present = true },
[tegra_clk_i2c4] = { .dt_id = TEGRA210_CLK_I2C4, .present = true },
@@ -2217,8 +2216,8 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_sata_8] = { .dt_id = TEGRA210_CLK_SATA, .present = true },
[tegra_clk_hda_8] = { .dt_id = TEGRA210_CLK_HDA, .present = true },
[tegra_clk_hda2hdmi] = { .dt_id = TEGRA210_CLK_HDA2HDMI, .present = true },
[tegra_clk_cilab] = { .dt_id = TEGRA210_CLK_CILAB, .present = true },
[tegra_clk_cilcd] = { .dt_id = TEGRA210_CLK_CILCD, .present = true },
[tegra_clk_cilab] = { .dt_id = TEGRA210_CLK_CILAB, .use_integer_div = true, .present = true },
[tegra_clk_cilcd] = { .dt_id = TEGRA210_CLK_CILCD, .use_integer_div = true, .present = true },
[tegra_clk_cile] = { .dt_id = TEGRA210_CLK_CILE, .present = true },
[tegra_clk_dsialp] = { .dt_id = TEGRA210_CLK_DSIALP, .present = true },
[tegra_clk_dsiblp] = { .dt_id = TEGRA210_CLK_DSIBLP, .present = true },
@@ -2238,7 +2237,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, },
[tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true },
[tegra_clk_spdif_in_8] = { .dt_id = TEGRA210_CLK_SPDIF_IN, .present = true },
[tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .present = true },
[tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .use_integer_div = true, .present = true },
[tegra_clk_vi_10] = { .dt_id = TEGRA210_CLK_VI, .present = true },
[tegra_clk_vi_sensor_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR, .present = true },
[tegra_clk_fuse] = { .dt_id = TEGRA210_CLK_FUSE, .present = true },
@@ -2276,7 +2275,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_pll_u_60m] = { .dt_id = TEGRA210_CLK_PLL_U_60M, .present = true },
[tegra_clk_pll_u_48m] = { .dt_id = TEGRA210_CLK_PLL_U_48M, .present = true },
[tegra_clk_pll_x] = { .dt_id = TEGRA210_CLK_PLL_X, .present = true },
[tegra_clk_pll_x_out0] = { .dt_id = TEGRA210_CLK_PLL_X_OUT0, .present = true },
[tegra_clk_pll_re_vco] = { .dt_id = TEGRA210_CLK_PLL_RE_VCO, .present = true },
[tegra_clk_pll_re_out] = { .dt_id = TEGRA210_CLK_PLL_RE_OUT, .present = true },
[tegra_clk_spdif_in_sync] = { .dt_id = TEGRA210_CLK_SPDIF_IN_SYNC, .present = true },
@@ -2310,7 +2308,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_hclk] = { .dt_id = TEGRA210_CLK_HCLK, .present = true },
[tegra_clk_pclk] = { .dt_id = TEGRA210_CLK_PCLK, .present = true },
[tegra_clk_cclk_g] = { .dt_id = TEGRA210_CLK_CCLK_G, .present = true },
[tegra_clk_cclk_lp] = { .dt_id = TEGRA210_CLK_CCLK_LP, .present = true },
[tegra_clk_dfll_ref] = { .dt_id = TEGRA210_CLK_DFLL_REF, .present = true },
[tegra_clk_dfll_soc] = { .dt_id = TEGRA210_CLK_DFLL_SOC, .present = true },
[tegra_clk_vi_sensor2_8] = { .dt_id = TEGRA210_CLK_VI_SENSOR2, .present = true },
@@ -2325,8 +2322,8 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_spdif_mux] = { .dt_id = TEGRA210_CLK_SPDIF_MUX, .present = true },
[tegra_clk_maud] = { .dt_id = TEGRA210_CLK_MAUD, .present = true },
[tegra_clk_mipibif] = { .dt_id = TEGRA210_CLK_MIPIBIF, .present = true },
[tegra_clk_qspi] = { .dt_id = TEGRA210_CLK_QSPI, .present = true },
[tegra_clk_sdmmc_legacy] = { .dt_id = TEGRA210_CLK_SDMMC_LEGACY, .present = true },
[tegra_clk_qspi] = { .dt_id = TEGRA210_CLK_QSPI, .use_integer_div = true, .present = true },
[tegra_clk_sdmmc_legacy] = { .dt_id = TEGRA210_CLK_SDMMC_LEGACY, .use_integer_div = true, .present = true },
[tegra_clk_tsecb] = { .dt_id = TEGRA210_CLK_TSECB, .present = true },
[tegra_clk_uartape] = { .dt_id = TEGRA210_CLK_UARTAPE, .present = true },
[tegra_clk_vi_i2c] = { .dt_id = TEGRA210_CLK_VI_I2C, .present = true },
@@ -2535,7 +2532,7 @@ static void tegra210_utmi_hw_sequencer_enable(void)
udelay(1);
}
static int tegra210_enable_utmipll(void)
static int tegra210b01_enable_utmipll(void)
{
u32 reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
bool hw_on = reg & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
@@ -2618,7 +2615,7 @@ static int tegra210_enable_pllu(void)
return 0;
}
static int tegra210_init_pllu(void)
static int tegra210b01_init_pllu(void)
{
u32 reg;
int err;
@@ -2676,7 +2673,7 @@ static int tegra210_init_pllu(void)
}
/* enable UTMIPLL hw control if not yet done by the bootloader */
return tegra210_enable_utmipll();
return tegra210b01_enable_utmipll();
}
/*
@@ -2876,7 +2873,7 @@ static __init void tegra210_periph_clk_init(struct device_node *np,
tegra210_clk_register_mc("mc", "emc");
}
static void __init tegra210_pll_init(void __iomem *clk_base,
static void __init tegra210b01_pll_init(void __iomem *clk_base,
void __iomem *pmc)
{
struct clk *clk;
@@ -2921,7 +2918,7 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
clks[TEGRA210_CLK_PLL_C3] = clk;
/* PLLU_VCO */
if (!tegra210_init_pllu()) {
if (!tegra210b01_init_pllu()) {
clk = clk_register_fixed_rate(NULL, "pll_u_vco", "pll_ref", 0,
480*1000*1000);
clk_register_clkdev(clk, "pll_u_vco", NULL);
@@ -3030,8 +3027,8 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
clks[TEGRA210_CLK_PLL_E] = clk;
/* PLLC4 */
clk = tegra_clk_register_pllre_tegra210("pll_c4_vco", "pll_ref",
clk_base, pmc, 0, &pll_c4_vco_params, NULL, pll_ref_freq);
clk = tegra_clk_register_pllre("pll_c4_vco", "pll_ref", clk_base, pmc,
0, &pll_c4_vco_params, NULL, pll_ref_freq);
clk_register_clkdev(clk, "pll_c4_vco", NULL);
clks[TEGRA210_CLK_PLL_C4] = clk;
@@ -3098,6 +3095,55 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
clks[TEGRA210_CLK_PLL_P_UPHY_OUT] = clk;
}
static char *tegra210b01_determine_pllc4_rate(void)
{
struct device_node *node;
u32 val;
int out0_ratio, i;
unsigned long sdmmc_max_rate = 0;
struct clk *clk;
char *sclk_high_clk;
for_each_compatible_node(node, NULL, "nvidia,tegra210-sdhci") {
if (!of_device_is_available(node))
continue;
if (!of_property_read_u32(node, "max-frequency", &val)
&& val > sdmmc_max_rate)
sdmmc_max_rate = val;
}
switch (sdmmc_max_rate) {
case 266000000:
sclk_high_clk = "pll_c4_out1";
pll_c4_vco_params.fixed_rate = 798000000;
out0_ratio = 4;
break;
default:
sclk_high_clk = "pll_c4_out3";
pll_c4_vco_params.fixed_rate = 1000000000;
out0_ratio = 1;
break;
}
pll_c4_vco_params.fixed_rate /= pll_ref_freq/pll_c4_vco_params.mdiv_default;
pll_c4_vco_params.fixed_rate *= pll_ref_freq/pll_c4_vco_params.mdiv_default;
val = readl(clk_base + PLLC4_BASE);
for (i = 0; pll_vco_post_div_table[i].div; i++)
if (pll_vco_post_div_table[i].div >= out0_ratio)
break;
val &= ~GENMASK(23, 19);
val |= pll_vco_post_div_table[i].val << pll_c4_vco_params.div_nmp->divp_shift;
writel(val, clk_base + PLLC4_BASE);
clk = clk_register_fixed_factor(NULL, "pll_c4_out0", "pll_c4_vco", 0,
1, pll_vco_post_div_table[i].div);
clks[TEGRA210_CLK_PLL_C4_OUT0] = clk;
return sclk_high_clk;
}
/* Tegra210 CPU clock and reset control functions */
static void tegra210_wait_cpu_in_reset(u32 cpu)
{
@@ -3179,7 +3225,7 @@ static void tegra210_clk_resume(void)
fence_udelay(2, clk_base);
/* restore PLLs and all peripheral clock rates */
tegra210_init_pllu();
tegra210b01_init_pllu();
clk_restore_context();
/* restore saved context of peripheral clocks and reset state */
@@ -3223,12 +3269,9 @@ static const struct of_device_id pmc_match[] __initconst = {
};
static struct tegra_clk_init_table t210b01_init_table[] __initdata = {
{ TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1,
TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
{ TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 0, 1,
TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
{ TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0,
TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
{ TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1, TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
//{ TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 0, 1, TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
{ TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0, TEGRA_TABLE_RATE_CHANGE_OVERCLOCK },
{ TEGRA210_CLK_PLL_P_UPHY_OUT, TEGRA210_CLK_CLK_MAX, 102000000, 1 },
{ TEGRA210_CLK_SDMMC_LEGACY, TEGRA210_CLK_PLL_P, 12000000, 0 },
{ TEGRA210_CLK_I2CSLOW, TEGRA210_CLK_CLK_32K, 32000, 0 },
@@ -3399,48 +3442,6 @@ static int tegra210b01_reset_deassert(unsigned long id)
return 0;
}
static enum clk_id tegra210b01_integer_div_id[] = {
tegra_clk_cilab,
tegra_clk_cilcd,
tegra_clk_spdif_out,
tegra_clk_sbc1_9,
tegra_clk_sbc2_9,
tegra_clk_sbc3_9,
tegra_clk_sbc4_9,
tegra_clk_sdmmc_legacy,
tegra_clk_i2cslow,
tegra_clk_qspi,
tegra_clk_soc_therm_8,
tegra_clk_tsensor,
};
static void tegra210b01_adjust_clks(struct tegra_clk *tegra_clks)
{
int i;
/* Remove CPU_LP claster clocks */
tegra_clks[tegra_clk_cclk_lp].present = false;
tegra_clks[tegra_clk_pll_x_out0].present = false;
/* Prevent 1:1.5 fractional divider setting */
div1_5_not_allowed = true;
/* Prevent any fractional setting */
for (i = 0; i < ARRAY_SIZE(tegra210b01_integer_div_id); i++) {
enum clk_id cid = tegra210b01_integer_div_id[i];
if (cid >= tegra_clk_max || !tegra_clks[cid].present) {
pr_warn("%s: clk %d is not present\n", __func__, cid);
continue;
}
tegra_clks[cid].use_integer_div = true;
}
}
/**
* tegra210b01_clock_init - Tegra210-specific clock initialization
* @np: struct device_node * of the DT node for the SoC CAR IP block
@@ -3453,6 +3454,7 @@ static void tegra210b01_adjust_clks(struct tegra_clk *tegra_clks)
static void __init tegra210b01_clock_init(struct device_node *np)
{
struct device_node *node;
char *sclk_high_clk;
u32 value, clk_m_div;
clk_base = of_iomap(np, 0);
@@ -3481,7 +3483,8 @@ static void __init tegra210b01_clock_init(struct device_node *np)
if (!clks)
return;
tegra210b01_adjust_clks(tegra210_clks);
/* Prevent 1:1.5 fractional divider setting */
div1_5_not_allowed = true;
value = readl(clk_base + SPARE_REG0) >> CLK_M_DIVISOR_SHIFT;
clk_m_div = (value & CLK_M_DIVISOR_MASK) + 1;
@@ -3492,7 +3495,8 @@ static void __init tegra210b01_clock_init(struct device_node *np)
return;
tegra_fixed_clk_init(tegra210_clks);
tegra210_pll_init(clk_base, pmc_base);
sclk_high_clk = tegra210b01_determine_pllc4_rate();
tegra210b01_pll_init(clk_base, pmc_base);
tegra210_periph_clk_init(np, clk_base, pmc_base);
tegra_audio_clk_init(clk_base, pmc_base, tegra210_clks,
tegra210_audio_plls,

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,9 +31,6 @@ int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
if (flags & TEGRA_DIVIDER_INT)
divider_ux1 *= mul;
if (!div1_5_not_allowed && divider_ux1 < mul)
return 0;
divider_ux1 -= mul;
if (divider_ux1 > div_mask(width))

View File

@@ -27,6 +27,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/tegra_prod.h>
#define BYTES_PER_FIFO_WORD 4
@@ -64,6 +65,10 @@
#define I2C_CLK_DIVISOR 0x06c
#define I2C_CLK_DIVISOR_STD_FAST_MODE GENMASK(31, 16)
#define I2C_CLK_DIVISOR_HSMODE GENMASK(15, 0)
#define I2C_CLK_DIVISOR_STD_FAST_MODE_START 16
#define I2C_CLK_DIVISOR_STD_FAST_MODE_WIDTH 16
#define I2C_CLK_DIVISOR_HSMODE_START 0
#define I2C_CLK_DIVISOR_HSMODE_WIDTH 16
#define DVC_CTRL_REG1 0x000
#define DVC_CTRL_REG1_INTR_EN BIT(10)
@@ -108,21 +113,45 @@
#define I2C_MST_CORE_CLKEN_OVR BIT(0)
#define I2C_INTERFACE_TIMING_0 0x094
#define I2C_INTERFACE_TIMING_THIGH GENMASK(13, 8)
#define I2C_INTERFACE_TIMING_TLOW GENMASK(5, 0)
#define I2C_INTERFACE_TIMING_THIGH GENMASK(15, 8)
#define I2C_INTERFACE_TIMING_TLOW GENMASK(7, 0)
#define I2C_INTERFACE_TIMING_THIGH_START 8
#define I2C_INTERFACE_TIMING_THIGH_WIDTH 8
#define I2C_INTERFACE_TIMING_TLOW_START 0
#define I2C_INTERFACE_TIMING_TLOW_WIDTH 8
#define I2C_INTERFACE_TIMING_1 0x098
#define I2C_INTERFACE_TIMING_TBUF GENMASK(29, 24)
#define I2C_INTERFACE_TIMING_TSU_STO GENMASK(21, 16)
#define I2C_INTERFACE_TIMING_THD_STA GENMASK(13, 8)
#define I2C_INTERFACE_TIMING_TSU_STA GENMASK(5, 0)
#define I2C_INTERFACE_TIMING_TBUF_START 24
#define I2C_INTERFACE_TIMING_TBUF_WIDTH 6
#define I2C_INTERFACE_TIMING_TSU_STO_START 16
#define I2C_INTERFACE_TIMING_TSU_STO_WIDTH 6
#define I2C_INTERFACE_TIMING_THD_STA_START 8
#define I2C_INTERFACE_TIMING_THD_STA_WIDTH 6
#define I2C_INTERFACE_TIMING_TSU_STA_START 0
#define I2C_INTERFACE_TIMING_TSU_STA_WIDTH 6
#define I2C_HS_INTERFACE_TIMING_0 0x09c
#define I2C_HS_INTERFACE_TIMING_THIGH GENMASK(13, 8)
#define I2C_HS_INTERFACE_TIMING_TLOW GENMASK(5, 0)
#define I2C_HS_INTERFACE_TIMING_THIGH GENMASK(15, 8)
#define I2C_HS_INTERFACE_TIMING_TLOW GENMASK(7, 0)
#define I2C_HS_INTERFACE_TIMING_THIGH_START 8
#define I2C_HS_INTERFACE_TIMING_THIGH_WIDTH 8
#define I2C_HS_INTERFACE_TIMING_TLOW_START 0
#define I2C_HS_INTERFACE_TIMING_TLOW_WIDTH 8
#define I2C_HS_INTERFACE_TIMING_1 0x0a0
#define I2C_HS_INTERFACE_TIMING_TSU_STO GENMASK(21, 16)
#define I2C_HS_INTERFACE_TIMING_THD_STA GENMASK(13, 8)
#define I2C_HS_INTERFACE_TIMING_TSU_STA GENMASK(5, 0)
#define I2C_HS_INTERFACE_TIMING_TSU_STO_START 16
#define I2C_HS_INTERFACE_TIMING_TSU_STO_WIDTH 6
#define I2C_HS_INTERFACE_TIMING_THD_STA_START 8
#define I2C_HS_INTERFACE_TIMING_THD_STA_WIDTH 6
#define I2C_HS_INTERFACE_TIMING_TSU_STA_START 0
#define I2C_HS_INTERFACE_TIMING_TSU_STA_WIDTH 6
#define I2C_MST_FIFO_CONTROL 0x0b4
#define I2C_MST_FIFO_CONTROL_RX_FLUSH BIT(0)
@@ -288,6 +317,8 @@ struct tegra_i2c_dev {
dma_addr_t dma_phys;
void *dma_buf;
struct tegra_prod *prod_list;
bool multimaster_mode;
bool atomic_mode;
bool dma_mode;
@@ -604,42 +635,46 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
return 0;
}
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
static void tegra_i2c_write_prod_settings(struct tegra_i2c_dev *i2c_dev,
const char *prod_name)
{
u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode;
acpi_handle handle = ACPI_HANDLE(i2c_dev->dev);
struct i2c_timings *t = &i2c_dev->timings;
int err;
/*
* The reset shouldn't ever fail in practice. The failure will be a
* sign of a severe problem that needs to be resolved. Still we don't
* want to fail the initialization completely because this may break
* kernel boot up since voltage regulators use I2C. Hence, we will
* emit a noisy warning on error, which won't stay unnoticed and
* won't hose machine entirely.
*/
if (handle)
err = acpi_evaluate_object(handle, "_RST", NULL, NULL);
else
err = reset_control_reset(i2c_dev->rst);
err = tegra_prod_set_by_name(&i2c_dev->base, prod_name, i2c_dev->prod_list);
if (err < 0)
dev_dbg_once(i2c_dev->dev,
"Prod config not found for I2C: %d\n", err);
}
WARN_ON_ONCE(err);
static void tegra_i2c_config_prod_settings(struct tegra_i2c_dev *i2c_dev)
{
struct i2c_timings *t = &i2c_dev->timings;
char *prod_name;
if (IS_DVC(i2c_dev))
tegra_dvc_init(i2c_dev);
switch (t->bus_freq_hz) {
case I2C_MAX_FAST_MODE_PLUS_FREQ + 1 ... I2C_MAX_HIGH_SPEED_MODE_FREQ:
prod_name = "prod_c_hs";
break;
case I2C_MAX_FAST_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:
prod_name = "prod_c_fmplus";
break;
case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_FREQ:
prod_name = "prod_c_fm";
break;
case 0 ... I2C_MAX_STANDARD_MODE_FREQ:
default:
prod_name = "prod_c_sm";
break;
}
val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2);
tegra_i2c_write_prod_settings(i2c_dev, "prod");
tegra_i2c_write_prod_settings(i2c_dev, prod_name);
}
if (i2c_dev->hw->has_multi_master_mode)
val |= I2C_CNFG_MULTI_MASTER_MODE;
i2c_writel(i2c_dev, val, I2C_CNFG);
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
if (IS_VI(i2c_dev))
tegra_i2c_vi_init(i2c_dev);
static void tegra_i2c_set_clk_params(struct tegra_i2c_dev *i2c_dev)
{
u32 val, clk_divisor, tsu_thd, tlow, thigh, non_hs_mode;
struct i2c_timings *t = &i2c_dev->timings;
switch (t->bus_freq_hz) {
case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:
@@ -680,6 +715,23 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
*/
if (i2c_dev->hw->has_interface_timing_reg && tsu_thd)
i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
}
static int tegra_i2c_set_div_clk(struct tegra_i2c_dev *i2c_dev)
{
u32 clk_multiplier, tlow, thigh, non_hs_mode;
struct i2c_timings *t = &i2c_dev->timings;
u32 timing, clk_divisor;
int err;
timing = i2c_readl(i2c_dev, I2C_INTERFACE_TIMING_0);
tlow = FIELD_GET(I2C_INTERFACE_TIMING_TLOW, timing);
thigh = FIELD_GET(I2C_INTERFACE_TIMING_THIGH, timing);
clk_divisor = i2c_readl(i2c_dev, I2C_CLK_DIVISOR);
non_hs_mode = FIELD_GET(I2C_CLK_DIVISOR_STD_FAST_MODE, clk_divisor);
clk_multiplier = (tlow + thigh + 2) * (non_hs_mode + 1);
@@ -690,6 +742,54 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
return err;
}
return 0;
}
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
{
acpi_handle handle = ACPI_HANDLE(i2c_dev->dev);
u32 val;
int err;
/*
* The reset shouldn't ever fail in practice. The failure will be a
* sign of a severe problem that needs to be resolved. Still we don't
* want to fail the initialization completely because this may break
* kernel boot up since voltage regulators use I2C. Hence, we will
* emit a noisy warning on error, which won't stay unnoticed and
* won't hose machine entirely.
*/
if (handle)
err = acpi_evaluate_object(handle, "_RST", NULL, NULL);
else
err = reset_control_reset(i2c_dev->rst);
WARN_ON_ONCE(err);
if (IS_DVC(i2c_dev))
tegra_dvc_init(i2c_dev);
val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2);
if (i2c_dev->hw->has_multi_master_mode)
val |= I2C_CNFG_MULTI_MASTER_MODE;
i2c_writel(i2c_dev, val, I2C_CNFG);
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
if (IS_VI(i2c_dev))
tegra_i2c_vi_init(i2c_dev);
if (i2c_dev->prod_list)
tegra_i2c_config_prod_settings(i2c_dev);
else
tegra_i2c_set_clk_params(i2c_dev);
err = tegra_i2c_set_div_clk(i2c_dev);
if (err)
return err;
if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) {
u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
@@ -1786,6 +1886,12 @@ static int tegra_i2c_probe(struct platform_device *pdev)
if (err)
return err;
i2c_dev->prod_list = devm_tegra_prod_get(i2c_dev->dev);
if (IS_ERR_OR_NULL(i2c_dev->prod_list)) {
dev_dbg(&pdev->dev, "Prod-setting not available\n");
i2c_dev->prod_list = NULL;
}
tegra_i2c_parse_dt(i2c_dev);
err = tegra_i2c_init_reset(i2c_dev);

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"

View File

@@ -117,3 +117,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/

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.

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

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_ */

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2010 Google, Inc.
* Copyright (C) 2013 Google, Inc.
*/
#include <linux/bitfield.h>
@@ -28,6 +28,7 @@
#include <linux/reset.h>
#include <soc/tegra/common.h>
#include <linux/tegra_prod.h>
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
@@ -37,21 +38,28 @@
#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100
#define SDHCI_CLOCK_CTRL_TAP_MASK 0x00ff0000
#define SDHCI_CLOCK_CTRL_TAP_SHIFT 16
#define SDHCI_CLOCK_CTRL_TAP_WIDTH 8
#define SDHCI_CLOCK_CTRL_TRIM_MASK 0x1f000000
#define SDHCI_CLOCK_CTRL_TRIM_SHIFT 24
#define SDHCI_CLOCK_CTRL_TRIM_WIDTH 5
#define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5)
#define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE BIT(3)
#define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE BIT(2)
#define SDHCI_TEGRA_VENDOR_SYS_SW_CTRL 0x104
#define SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE BIT(31)
#define SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE_SHIFT 31
#define SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE_WIDTH 1
#define SDHCI_TEGRA_VENDOR_CAP_OVERRIDES 0x10c
#define SDHCI_TEGRA_CAP_OVERRIDES_DQS_TRIM_MASK 0x00003f00
#define SDHCI_TEGRA_CAP_OVERRIDES_DQS_TRIM_SHIFT 8
#define SDHCI_TEGRA_CAP_OVERRIDES_DQS_TRIM_WIDTH 6
#define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120
#define SDHCI_MISC_CTRL_ERASE_TIMEOUT_LIMIT BIT(0)
#define SDHCI_MISC_CTRL_ERASE_TIMEOUT_LIMIT_SHIFT 0
#define SDHCI_MISC_CTRL_ERASE_TIMEOUT_LIMIT_WIDTH 1
#define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8
#define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10
#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20
@@ -64,6 +72,8 @@
#define SDHCI_TEGRA_DLLCAL_STA_ACTIVE BIT(31)
#define SDHCI_VNDR_TUN_CTRL0_0 0x1c0
#define SDHCI_VNDR_TUN_CTRL0_CMD_CRC_ERR_EN_SHIFT 28
#define SDHCI_VNDR_TUN_CTRL0_CMD_CRC_ERR_EN_WIDTH 1
#define SDHCI_VNDR_TUN_CTRL0_TUN_HW_TAP 0x20000
#define SDHCI_VNDR_TUN_CTRL0_START_TAP_VAL_MASK 0x03fc0000
#define SDHCI_VNDR_TUN_CTRL0_START_TAP_VAL_SHIFT 18
@@ -71,9 +81,12 @@
#define SDHCI_VNDR_TUN_CTRL0_MUL_M_SHIFT 6
#define SDHCI_VNDR_TUN_CTRL0_TUN_ITER_MASK 0x000e000
#define SDHCI_VNDR_TUN_CTRL0_TUN_ITER_SHIFT 13
#define SDHCI_VNDR_TUN_CTRL0_TUN_ITER_WIDTH 3
#define TRIES_128 2
#define TRIES_256 4
#define SDHCI_VNDR_TUN_CTRL0_TUN_WORD_SEL_MASK 0x7
#define SDHCI_VNDR_TUN_CTRL0_DIV_N_SHIFT 3
#define SDHCI_VNDR_TUN_CTRL0_DIV_N_WIDTH 3
#define SDHCI_TEGRA_VNDR_TUN_CTRL1_0 0x1c4
#define SDHCI_TEGRA_VNDR_TUN_STATUS0 0x1C8
@@ -134,6 +147,20 @@
SDHCI_TRNS_BLK_CNT_EN | \
SDHCI_TRNS_DMA)
static char prod_device_states[MMC_TIMING_COUNTER][20] = {
"prod_c_ds", /* MMC_TIMING_LEGACY */
"prod_c_hs", /* MMC_TIMING_MMC_HS */
"prod_c_hs", /* MMC_TIMING_SD_HS */
"prod_c_sdr12", /* MMC_TIMING_UHS_SDR12 */
"prod_c_sdr25", /* MMC_TIMING_UHS_SDR25 */
"prod_c_sdr50", /* MMC_TIMING_UHS_SDR50 */
"prod_c_sdr104", /* MMC_TIMING_UHS_SDR104 */
"prod_c_ddr52", /* MMC_TIMING_UHS_DDR50 */
"prod_c_ddr52", /* MMC_TIMING_MMC_DDR52 */
"prod_c_hs200", /* MMC_TIMING_MMC_HS200 */
"prod_c_hs400", /* MMC_TIMING_MMC_HS400 */
};
struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
u64 dma_mask;
@@ -183,6 +210,7 @@ struct sdhci_tegra {
unsigned long curr_clk_rate;
u8 tuned_tap_delay;
u32 stream_id;
struct tegra_prod *prod_list;
};
static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -362,6 +390,19 @@ static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
}
}
static void tegra_sdhci_write_prod_settings(struct sdhci_host *host,
const char *prod_name)
{
int err;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
err = tegra_prod_set_by_name(&host->ioaddr, prod_name, tegra_host->prod_list);
if (err < 0)
dev_dbg_once(mmc_dev(host->mmc),
"Prod config not found for SDHCI: %d\n", err);
}
static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -374,6 +415,8 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
if (!(mask & SDHCI_RESET_ALL))
return;
tegra_sdhci_write_prod_settings(host, "prod");
tegra_sdhci_set_tap(host, tegra_host->default_tap);
misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
@@ -941,7 +984,7 @@ static void tegra_sdhci_post_tuning(struct sdhci_host *host)
u32 avg_tap_dly, val, min_tap_dly, max_tap_dly;
u8 fixed_tap, start_tap, end_tap, window_width;
u8 thdupper, thdlower;
u8 num_iter;
u16 num_iter;
u32 clk_rate_mhz, period_ps, bestcase, worstcase;
/* retain HW tuned tap to use incase if no correction is needed */
@@ -973,7 +1016,33 @@ static void tegra_sdhci_post_tuning(struct sdhci_host *host)
end_tap = (val >> SDHCI_TEGRA_VNDR_TUN_STATUS1_END_TAP_SHIFT) &
SDHCI_TEGRA_VNDR_TUN_STATUS1_TAP_MASK;
window_width = end_tap - start_tap;
num_iter = host->tuning_loop_count;
num_iter = (sdhci_readl(host, SDHCI_VNDR_TUN_CTRL0_0) &
SDHCI_VNDR_TUN_CTRL0_TUN_ITER_MASK) >>
SDHCI_VNDR_TUN_CTRL0_TUN_ITER_SHIFT;
switch (num_iter) {
case 0:
num_iter = 40;
break;
case 1:
num_iter = 64;
break;
case 2:
num_iter = 128;
break;
case 3:
num_iter = 196;
break;
case 4:
num_iter = 256;
break;
default:
WARN_ON("Invalid value of number of tuning iterations");
}
host->tuning_loop_count = num_iter;
/*
* partial window includes edges of the tuning range.
* merged window includes more taps so window width is higher
@@ -985,6 +1054,8 @@ static void tegra_sdhci_post_tuning(struct sdhci_host *host)
mmc_hostname(host->mmc));
tegra_sdhci_tap_correction(host, thdupper, thdlower,
fixed_tap);
pr_info("%s: Tap value after applying correction %u\n",
mmc_hostname(host->mmc), tegra_host->tuned_tap_delay);
}
}
@@ -1008,11 +1079,12 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
bool set_default_tap = false;
bool set_default_tap = false; // opposite of tuning_mode
bool set_num_tun_iter = false;
bool set_dqs_trim = false;
bool do_hs400_dll_cal = false;
u8 iter = TRIES_256;
u32 val;
bool set_padpipe_clk_override = false;
u32 ret;
tegra_host->ddr_signaling = false;
switch (timing) {
@@ -1021,12 +1093,13 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
case MMC_TIMING_UHS_SDR104:
case MMC_TIMING_MMC_HS200:
/* Don't set default tap on tunable modes. */
iter = TRIES_128;
set_num_tun_iter = true;
break;
case MMC_TIMING_MMC_HS400:
set_dqs_trim = true;
do_hs400_dll_cal = true;
iter = TRIES_128;
set_padpipe_clk_override = true;
set_num_tun_iter = true;
break;
case MMC_TIMING_MMC_DDR52:
case MMC_TIMING_UHS_DDR50:
@@ -1038,18 +1111,6 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
break;
}
val = sdhci_readl(host, SDHCI_VNDR_TUN_CTRL0_0);
val &= ~(SDHCI_VNDR_TUN_CTRL0_TUN_ITER_MASK |
SDHCI_VNDR_TUN_CTRL0_START_TAP_VAL_MASK |
SDHCI_VNDR_TUN_CTRL0_MUL_M_MASK);
val |= (iter << SDHCI_VNDR_TUN_CTRL0_TUN_ITER_SHIFT |
0 << SDHCI_VNDR_TUN_CTRL0_START_TAP_VAL_SHIFT |
1 << SDHCI_VNDR_TUN_CTRL0_MUL_M_SHIFT);
sdhci_writel(host, val, SDHCI_VNDR_TUN_CTRL0_0);
sdhci_writel(host, 0, SDHCI_TEGRA_VNDR_TUN_CTRL1_0);
host->tuning_loop_count = (iter == TRIES_128) ? 128 : 256;
sdhci_set_uhs_signaling(host, timing);
tegra_sdhci_pad_autocalib(host);
@@ -1059,6 +1120,29 @@ static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
else
tegra_sdhci_set_tap(host, tegra_host->default_tap);
/*set padpipe_clk_override*/
if (set_padpipe_clk_override) {
ret = tegra_prod_set_by_name_partially(&host->ioaddr,
prod_device_states[timing], tegra_host->prod_list,
0, SDHCI_TEGRA_VENDOR_CLOCK_CTRL,
SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"Failed to set padpipe clk override value for timing %d, %d\n",
timing, ret);
}
/* Set number of tuning iterations */
if (set_num_tun_iter) {
ret = tegra_prod_set_by_name_partially(&host->ioaddr,
prod_device_states[timing], tegra_host->prod_list,
0, SDHCI_VNDR_TUN_CTRL0_0,
SDHCI_VNDR_TUN_CTRL0_TUN_WORD_SEL_MASK <<
SDHCI_VNDR_TUN_CTRL0_TUN_ITER_SHIFT);
if (ret < 0)
dev_err(mmc_dev(host->mmc),
"Failed to set number of iterations for timing %d, %d\n",
timing, ret);
}
if (set_dqs_trim)
tegra_sdhci_set_dqs_trim(host, tegra_host->dqs_trim);
@@ -1129,6 +1213,12 @@ static int sdhci_tegra_start_signal_voltage_switch(struct mmc_host *mmc,
static int tegra_sdhci_init_pinctrl_info(struct device *dev,
struct sdhci_tegra *tegra_host)
{
tegra_host->prod_list = devm_tegra_prod_get(dev);
if (IS_ERR_OR_NULL(tegra_host->prod_list)) {
dev_dbg(dev, "Prod-setting not available\n");
tegra_host->prod_list = NULL;
}
tegra_host->pinctrl_sdmmc = devm_pinctrl_get(dev);
if (IS_ERR(tegra_host->pinctrl_sdmmc)) {
dev_dbg(dev, "No pinctrl info, err: %ld\n",
@@ -1506,6 +1596,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 +1680,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 },

View File

@@ -2171,6 +2171,15 @@ 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)
{
@@ -2199,12 +2208,22 @@ 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") ||
of_device_is_compatible(np, "nvidia,tegra210-pcie")) {
switch (lanes) {
@@ -2217,6 +2236,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) {
@@ -2339,7 +2365,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,
@@ -2851,7 +2878,7 @@ static const struct tegra_pcie_soc tegra210b01_pcie = {
.msi_base_shift = 8,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
.pads_refclk_cfg0 = 0x90b890b8,
.pads_refclk_cfg0 = 0xb0b880b8,
/* FC threshold is bit[25:18] */
.update_fc_threshold = 0x01800000,
.has_pex_clkreq_en = true,

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2016-2024, NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/delay.h>
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/tegra_prod.h>
#include <soc/tegra/fuse.h>
@@ -239,6 +240,24 @@
#define TEGRA_UTMI_PAD_MAX 4
/* Prod fields */
#define USB2_OTG_PADX_CTL0_LS_RSLEW_FIELD_START 17
#define USB2_OTG_PADX_CTL0_LS_RSLEW_FIELD_WIDTH 4
#define USB2_OTG_PADX_CTL0_LS_FSLEW_FIELD_START 21
#define USB2_OTG_PADX_CTL0_LS_FSLEW_FIELD_WIDTH 4
#define USB2_OTG_PADX_CTL3_HS_TXEQ_FIELD_START 1
#define USB2_OTG_PADX_CTL3_HS_TXEQ_FIELD_WIDTH 3
#define USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_FIELD_START 3
#define USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_FIELD_WIDTH 3
#define USB2_BIAS_PAD_CTL1_TRK_START_TIMER_FIELD_START 12
#define USB2_BIAS_PAD_CTL1_TRK_START_TIMER_FIELD_WIDTH 7
#define USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_FIELD_START 19
#define USB2_BIAS_PAD_CTL1_TRK_DONE_RESET_TIMER_FIELD_WIDTH 7
#define XUSB_PADCTL_USB2_OTG_PADX_CTL3(x) (0x94 + (x) * 0x40)
#define TEGRA186_LANE(_name, _offset, _shift, _mask, _type) \
{ \
.name = _name, \
@@ -267,6 +286,8 @@ struct tegra186_xusb_padctl {
struct tegra_xusb_padctl base;
void __iomem *ao_regs;
/* prod settings */
struct tegra_prod *prod_list;
struct tegra_xusb_fuse_calibration calib;
/* UTMI bias and tracking */
@@ -850,6 +871,14 @@ static int tegra186_utmi_phy_set_mode(struct phy *phy, enum phy_mode mode,
return err;
}
static int tegra186_utmi_write_prod_settings(struct tegra_xusb_padctl *padctl,
const char *prod_name)
{
struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl);
return tegra_prod_set_by_name(&padctl->regs, prod_name, priv->prod_list);
}
static int tegra186_utmi_phy_power_on(struct phy *phy)
{
struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
@@ -867,6 +896,12 @@ static int tegra186_utmi_phy_power_on(struct phy *phy)
return -ENODEV;
}
if (priv->prod_list) {
int err = tegra186_utmi_write_prod_settings(padctl, "prod");
if (err)
dev_dbg(dev, "failed to apply prod settings\n");
}
value = padctl_readl(padctl, XUSB_PADCTL_USB2_PAD_MUX);
value &= ~(USB2_PORT_MASK << USB2_PORT_SHIFT(index));
value |= (PORT_XUSB << USB2_PORT_SHIFT(index));
@@ -1512,6 +1547,12 @@ tegra186_xusb_padctl_probe(struct device *dev,
if (err < 0)
return ERR_PTR(err);
priv->prod_list = devm_tegra_prod_get(dev);
if (IS_ERR_OR_NULL(priv->prod_list)) {
dev_dbg(dev, "Prod-settings is not available\n");
priv->prod_list = NULL;
}
return &priv->base;
}

View File

@@ -15,6 +15,8 @@ source "drivers/platform/olpc/Kconfig"
source "drivers/platform/surface/Kconfig"
source "drivers/platform/tegra/Kconfig"
source "drivers/platform/x86/Kconfig"
source "drivers/platform/arm64/Kconfig"

View File

@@ -12,4 +12,5 @@ obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += arm64/

View File

@@ -0,0 +1,24 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Tegra Platform Specific Drivers
#
menuconfig TEGRA_PLATFORM_DEVICES
bool "Tegra Platform Specific Device Drivers"
default y
help
Say Y here to get to see options for device drivers of various
Tegra platforms. This option itself does not add any kernel code.
If you say N, all options in this submenu will be skipped and
disabled.
if TEGRA_PLATFORM_DEVICES
config TEGRA_PROD_LEGACY
def_bool y
help
This config helps client driver to identify whether prod
framework is implemented as legacy method or not.
endif # TEGRA_PLATFORM_DEVICES

View File

@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_TEGRA_PROD_LEGACY) += tegra_prod.o

View File

@@ -0,0 +1,620 @@
/*
* Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/io.h>
#include <linux/tegra_prod.h>
#define PROD_TUPLE_NUM (sizeof(struct prod_tuple)/sizeof(u32))
/* tegra_prod: Tegra Prod list for the given submodule
* @n_prod_cells: Number of prod setting cells.
*/
struct tegra_prod {
struct tegra_prod_config *prod_config;
int num; /* number of tegra_prod*/
int n_prod_cells;
};
struct prod_tuple {
u32 index; /* Address base index */
u32 addr; /* offset address*/
u32 mask; /* mask */
u32 val; /* value */
};
struct tegra_prod_config {
const char *name;
struct prod_tuple *prod_tuple;
int count; /* number of prod_tuple*/
bool boot_init;
};
static int tegra_prod_get_child_tupple_count(struct device *dev,
struct device_node *np,
int n_tupple)
{
struct device_node *child;
int count;
int total_tupple = 0;
count = of_property_count_u32_elems(np, "prod");
if (count > 0) {
if ((count < n_tupple) || (count % n_tupple != 0)) {
dev_err(dev, "Node %s has invalid entries\n", np->name);
return -EINVAL;
}
total_tupple = count / n_tupple;
}
for_each_available_child_of_node(np, child) {
count = tegra_prod_get_child_tupple_count(dev, child, n_tupple);
if (count < 0)
return count;
total_tupple += count;
}
return total_tupple;
}
static int tegra_prod_read_prod_data(struct device *dev,
struct device_node *np,
struct prod_tuple *p_tuple,
int n_tupple)
{
u32 pval;
int count;
int t_count;
int cnt;
int index;
int ret;
count = of_property_count_u32_elems(np, "prod");
if (count <= 0) {
dev_dbg(dev, "Node %s: prod prop not found\n", np->name);
return 0;
}
t_count = count / n_tupple;
for (cnt = 0; cnt < t_count; cnt++, p_tuple++) {
index = cnt * n_tupple;
if (n_tupple == 4) {
ret = of_property_read_u32_index(np, "prod", index,
&pval);
if (ret) {
dev_err(dev, "Failed to parse prod of node %s\n",
np->name);
return -EINVAL;
}
p_tuple->index = pval;
index++;
} else {
p_tuple->index = 0;
}
ret = of_property_read_u32_index(np, "prod", index, &pval);
if (ret) {
dev_err(dev, "Failed to parse address of node %s\n",
np->name);
return -EINVAL;
}
p_tuple->addr = pval;
index++;
ret = of_property_read_u32_index(np, "prod", index, &pval);
if (ret) {
dev_err(dev, "Failed to parse mask of node %s\n",
np->name);
return -EINVAL;
}
p_tuple->mask = pval;
index++;
ret = of_property_read_u32_index(np, "prod", index, &pval);
if (ret) {
dev_err(dev, "Failed to parse value of node %s\n",
np->name);
return -EINVAL;
}
p_tuple->val = pval;
}
return t_count;
}
static int tegra_prod_read_node_tupple(struct device *dev,
struct device_node *np,
struct prod_tuple *p_tuple,
int n_tupple)
{
int ret = 0;
int sindex;
struct device_node *child;
ret = tegra_prod_read_prod_data(dev, np, p_tuple, n_tupple);
if (ret < 0)
return -EINVAL;
sindex = ret;
p_tuple += ret;
for_each_available_child_of_node(np, child) {
ret = tegra_prod_read_node_tupple(dev, child,
p_tuple, n_tupple);
if (ret < 0)
return -EINVAL;
sindex += ret;
p_tuple += ret;
}
return sindex;
}
/* Process the tupples and optimise for the register configuration for
* Same location.
*/
static void tegra_prod_optimise_tupple(struct prod_tuple *p_tuple,
int n_tupple)
{
struct prod_tuple *ti, *tj;
u32 mask;
int i, j;
for (i = 0; i < n_tupple; ++i) {
ti = p_tuple + i;
for (j = i + 1; j < n_tupple; ++j) {
tj = p_tuple + j;
if (ti->index != tj->index)
continue;
if (ti->addr != tj->addr)
continue;
mask = ti->mask & tj->mask;
if (!mask)
continue;
ti->val &= ~mask;
ti->mask &= ~mask;
}
}
}
/**
* tegra_prod_parse_dt - Read the prod setting form Device tree.
* @np: device node from which the property value is to be read.
* @np_prod: Prod setting node.
* @tegra_prod: The list of tegra prods.
*
* Read the prod setting form DT according the prod name in tegra prod list.
* prod tuple will be allocated dynamically according to the tuple number of
* each prod in DT.
*
* Returns 0 on success.
*/
static int tegra_prod_parse_dt(struct device *dev,
const struct device_node *np,
const struct device_node *np_prod,
struct tegra_prod *tegra_prod)
{
struct device_node *child;
struct tegra_prod_config *t_prod;
struct prod_tuple *p_tuple;
int n_child;
int n_tupple = 3;
int ret;
int count;
u32 pval;
bool mask_opt;
if (!tegra_prod || !tegra_prod->prod_config) {
dev_err(dev, "Node %s: Invalid tegra prods list.\n", np->name);
return -EINVAL;
};
mask_opt = of_property_read_bool(np_prod, "enable-mask-optimisation");
ret = of_property_read_u32(np_prod, "#prod-cells", &pval);
if (!ret)
n_tupple = pval;
if ((n_tupple != 3) && (n_tupple != 4)) {
dev_err(dev, "Node %s: Prod cells not supported\n", np->name);
return -EINVAL;
}
tegra_prod->n_prod_cells = n_tupple;
n_child = 0;
for_each_available_child_of_node(np_prod, child) {
t_prod = &tegra_prod->prod_config[n_child];
t_prod->name = child->name;
count = tegra_prod_get_child_tupple_count(dev, child, n_tupple);
if (count < 0) {
dev_err(dev, "Node %s: Child has not proper setting\n",
child->name);
return -EINVAL;
}
if (!count) {
dev_err(dev, "Node %s: prod prop not found\n",
child->name);
return -EINVAL;
}
t_prod->count = count;
t_prod->prod_tuple = devm_kcalloc(dev, t_prod->count,
sizeof(*p_tuple), GFP_KERNEL);
if (!t_prod->prod_tuple)
return -ENOMEM;
t_prod->boot_init = of_property_read_bool(child,
"nvidia,prod-boot-init");
ret = tegra_prod_read_node_tupple(dev, child,
t_prod->prod_tuple, n_tupple);
if (ret < 0) {
dev_err(dev, "Node %s: Reading prod setting failed: %d\n",
child->name, ret);
return ret;
}
if (t_prod->count != ret) {
dev_err(dev, "Node %s: prod read failed: exp %d read %d\n",
child->name, t_prod->count, ret);
return -EINVAL;
}
/* Optimise the prod configuration */
if (mask_opt)
tegra_prod_optimise_tupple(t_prod->prod_tuple,
t_prod->count);
n_child++;
}
tegra_prod->num = n_child;
return 0;
}
/**
* tegra_prod_set_tuple - Only set a tuple.
* @base: base address of the register.
* @prod_tuple: the tuple to set.
* @new_mask: Mask override value, 0 means use from tupple.
*
* Returns 0 on success.
*/
static int tegra_prod_set_tuple(void __iomem **base,
struct prod_tuple *prod_tuple,
u32 new_mask)
{
u32 reg;
u32 mask = (new_mask) ? new_mask : prod_tuple->mask;
if (!prod_tuple)
return -EINVAL;
reg = readl(base[prod_tuple->index] + prod_tuple->addr);
reg = ((reg & ~mask) | (prod_tuple->val & mask));
writel(reg, base[prod_tuple->index] + prod_tuple->addr);
return 0;
}
/**
* tegra_prod_set - Set one prod setting.
* @base: base address of the register.
* @tegra_prod: the prod setting to set.
*
* Set all the tuples in one tegra_prod.
* Returns 0 on success.
*/
static int tegra_prod_set(void __iomem **base,
struct tegra_prod_config *tegra_prod)
{
int i;
int ret;
if (!tegra_prod)
return -EINVAL;
for (i = 0; i < tegra_prod->count; i++) {
ret = tegra_prod_set_tuple(base, &tegra_prod->prod_tuple[i], 0);
if (ret)
return ret;
}
return 0;
}
/**
* tegra_prod_set_list - Set all the prod settings of the list in sequence.
* @base: base address of the register.
* @tegra_prod: the list of tegra prods.
*
* Returns 0 on success.
*/
int tegra_prod_set_list(void __iomem **base,
struct tegra_prod *tegra_prod)
{
int i;
int ret;
if (!tegra_prod)
return -EINVAL;
for (i = 0; i < tegra_prod->num; i++) {
ret = tegra_prod_set(base, &tegra_prod->prod_config[i]);
if (ret)
return ret;
}
return 0;
}
EXPORT_SYMBOL(tegra_prod_set_list);
/**
* tegra_prod_set_boot_init - Set all the prod settings of the list in sequence
* Which are needed for boot initialisation.
* @base: base address of the register.
* @tegra_prod: the list of tegra prods.
*
* Returns 0 on success.
*/
int tegra_prod_set_boot_init(void __iomem **base,
struct tegra_prod *tegra_prod)
{
int i;
int ret;
if (!tegra_prod)
return -EINVAL;
for (i = 0; i < tegra_prod->num; i++) {
if (!tegra_prod->prod_config[i].boot_init)
continue;
ret = tegra_prod_set(base, &tegra_prod->prod_config[i]);
if (ret)
return ret;
}
return 0;
}
EXPORT_SYMBOL(tegra_prod_set_boot_init);
/**
* tegra_prod_set_by_name - Set the prod setting according the name.
* @base: base address of the register.
* @name: the name of tegra prod need to set.
* @tegra_prod: the list of tegra prods.
*
* Find the tegra prod in the list according to the name. Then set
* that tegra prod.
*
* Returns 0 on success.
*/
int tegra_prod_set_by_name(void __iomem **base, const char *name,
struct tegra_prod *tegra_prod)
{
int i;
struct tegra_prod_config *t_prod;
if (!tegra_prod)
return -EINVAL;
for (i = 0; i < tegra_prod->num; i++) {
t_prod = &tegra_prod->prod_config[i];
if (!strcasecmp(t_prod->name, name))
return tegra_prod_set(base, t_prod);
}
return -ENODEV;
}
EXPORT_SYMBOL(tegra_prod_set_by_name);
/**
* tegra_prod_set_by_name_partially - Set the prod setting from list partially
* under given prod name. The matching is done
* qith index, offset and mask.
* @base: base address of the register.
* @name: the name of tegra prod need to set.
* @tegra_prod: the list of tegra prods.
* @index: Index of base address.
* @offset: Offset of the register.
* @mask: Mask field on given register.
*
* Find the tegra prod in the list according to the name. Then set
* that tegra prod which has matching of index, offset and mask.
*
* Returns 0 on success.
*/
int tegra_prod_set_by_name_partially(void __iomem **base, const char *name,
struct tegra_prod *tegra_prod, u32 index,
u32 offset, u32 mask)
{
struct tegra_prod_config *t_prod;
int ret;
int i;
bool found = false;
if (!tegra_prod)
return -EINVAL;
for (i = 0; i < tegra_prod->num; i++) {
t_prod = &tegra_prod->prod_config[i];
if (!strcasecmp(t_prod->name, name)) {
found = true;
break;
}
}
if (!found)
return -ENODEV;
for (i = 0; i < t_prod->count; i++) {
struct prod_tuple *ptuple = &t_prod->prod_tuple[i];;
if ((ptuple->index != index) || (ptuple->addr != offset) ||
((ptuple->mask & mask) != mask))
continue;
ret = tegra_prod_set_tuple(base, ptuple, mask);
if (ret < 0)
return ret;
}
return 0;
}
EXPORT_SYMBOL(tegra_prod_set_by_name_partially);
bool tegra_prod_by_name_supported(struct tegra_prod *tegra_prod,
const char *name)
{
int i;
struct tegra_prod_config *t_prod;
if (!tegra_prod)
return false;
for (i = 0; i < tegra_prod->num; i++) {
t_prod = &tegra_prod->prod_config[i];
if (!t_prod)
break;
if (!strcasecmp(t_prod->name, name))
return true;
}
return false;
}
EXPORT_SYMBOL(tegra_prod_by_name_supported);
/**
* tegra_prod_init - Init tegra prod list.
# @dev: Device handle.
* @np: device node from which the property value is to be read.
*
* Query all the prod settings under DT node & Init the tegra prod list
* automatically.
*
* Returns 0 on success, -EINVAL for wrong prod number, -ENOMEM if failed
* to allocate memory for tegra prod list.
*/
static struct tegra_prod *tegra_prod_init(struct device *dev,
const struct device_node *np)
{
struct tegra_prod *tegra_prod;
struct device_node *np_prod;
int prod_num = 0;
int ret;
np_prod = of_get_child_by_name(np, "prod-settings");
if (!np_prod)
return ERR_PTR(-ENODEV);
/* Check whether child is enabled or not */
if (!of_device_is_available(np_prod)) {
dev_err(dev, "Node %s: Node is not enabled\n", np_prod->name);
return ERR_PTR(-ENODEV);
}
prod_num = of_get_child_count(np_prod);
if (prod_num <= 0) {
dev_err(dev, "Node %s: No child node for prod settings\n",
np_prod->name);
return ERR_PTR(-ENODEV);
}
tegra_prod = devm_kzalloc(dev, sizeof(*tegra_prod), GFP_KERNEL);
if (!tegra_prod)
return ERR_PTR(-ENOMEM);
tegra_prod->prod_config = devm_kcalloc(dev, prod_num,
sizeof(*tegra_prod->prod_config),
GFP_KERNEL);
if (!tegra_prod->prod_config)
return ERR_PTR(-ENOMEM);
tegra_prod->num = prod_num;
ret = tegra_prod_parse_dt(dev, np, np_prod, tegra_prod);
if (ret) {
dev_err(dev, "Node %s: Failed to read the Prod Setting.\n",
np->name);
return ERR_PTR(ret);
}
return tegra_prod;
}
static void devm_tegra_prod_release(struct device *dev, void *res)
{
}
struct tegra_prod *devm_tegra_prod_get(struct device *dev)
{
struct tegra_prod **ptr, *prod_list;
ptr = devres_alloc(devm_tegra_prod_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
prod_list = tegra_prod_init(dev, dev->of_node);
if (IS_ERR(prod_list)) {
devres_free(ptr);
return prod_list;
}
*ptr = prod_list;
devres_add(dev, ptr);
return prod_list;
}
EXPORT_SYMBOL(devm_tegra_prod_get);
struct tegra_prod *devm_tegra_prod_get_from_node(struct device *dev,
struct device_node *np)
{
struct tegra_prod **ptr, *prod_list;
ptr = devres_alloc(devm_tegra_prod_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
prod_list = tegra_prod_init(dev, np);
if (IS_ERR(prod_list)) {
devres_free(ptr);
return prod_list;
}
*ptr = prod_list;
devres_add(dev, ptr);
return prod_list;
}
EXPORT_SYMBOL(devm_tegra_prod_get_from_node);

View File

@@ -22,6 +22,7 @@
#include <linux/of.h>
#include <linux/reset.h>
#include <linux/spi/spi.h>
#include <linux/tegra_prod.h>
#define SPI_COMMAND1 0x000
#define SPI_BIT_LENGTH(x) (((x) & 0x1f) << 0)
@@ -63,6 +64,10 @@
#define SPI_COMMAND2 0x004
#define SPI_TX_TAP_DELAY(x) (((x) & 0x3F) << 6)
#define SPI_RX_TAP_DELAY(x) (((x) & 0x3F) << 0)
#define SPI_COMMAND2_RX_CLK_TAP_DELAY_START 0
#define SPI_COMMAND2_RX_CLK_TAP_DELAY_WIDTH 6
#define SPI_COMMAND2_TX_CLK_TAP_DELAY_START 6
#define SPI_COMMAND2_TX_CLK_TAP_DELAY_WIDTH 6
#define SPI_CS_TIMING1 0x008
#define SPI_SETUP_HOLD(setup, hold) (((setup) << 4) | (hold))
@@ -146,6 +151,10 @@
#define DATA_DIR_TX (1 << 0)
#define DATA_DIR_RX (1 << 1)
#define SPI_MISC 0x194
#define SPI_MISC_CLKEN_OVERRIDE_START 31
#define SPI_MISC_CLKEN_OVERRIDE_WIDTH 1
#define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000))
#define DEFAULT_SPI_DMA_BUF_LEN (16*1024)
#define TX_FIFO_EMPTY_COUNT_MAX SPI_TX_FIFO_EMPTY_COUNT(0x40)
@@ -218,6 +227,7 @@ struct tegra_spi_data {
dma_addr_t tx_dma_phys;
struct dma_async_tx_descriptor *tx_dma_desc;
const struct tegra_spi_soc_data *soc_data;
struct tegra_prod *prod_list;
};
static int tegra_spi_runtime_suspend(struct device *dev);
@@ -716,6 +726,31 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
dma_release_channel(dma_chan);
}
static void tegra_spi_write_prod_settings(struct tegra_spi_data *tspi,
const char *prod_name)
{
int err;
err = tegra_prod_set_by_name(&tspi->base, prod_name, tspi->prod_list);
if (err < 0)
dev_dbg_once(tspi->dev,
"Prod config not found for SPI: %d\n", err);
}
static void tegra_spi_set_prod(struct tegra_spi_data *tspi, int cs)
{
char prod_name[15];
/* Avoid write to register for transfers to last used device */
if (tspi->last_used_cs == cs)
return;
sprintf(prod_name, "prod_c_cs%d", cs);
tegra_spi_write_prod_settings(tspi, "prod");
tegra_spi_write_prod_settings(tspi, prod_name);
tspi->last_used_cs = cs;
}
static int tegra_spi_set_hw_cs_timing(struct spi_device *spi)
{
struct tegra_spi_data *tspi = spi_controller_get_devdata(spi->controller);
@@ -841,6 +876,7 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
command1 &= ~SPI_CS_SW_VAL;
}
if (!tspi->prod_list) {
if (tspi->last_used_cs != spi_get_chipselect(spi, 0)) {
if (cdata && cdata->tx_clk_tap_delay)
tx_tap = cdata->tx_clk_tap_delay;
@@ -852,6 +888,9 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
tegra_spi_writel(tspi, command2, SPI_COMMAND2);
tspi->last_used_cs = spi_get_chipselect(spi, 0);
}
} else {
tegra_spi_set_prod(tspi, spi_get_chipselect(spi, 0));
}
} else {
command1 = tspi->command1_reg;
@@ -1328,6 +1367,11 @@ static int tegra_spi_probe(struct platform_device *pdev)
tspi->host = host;
tspi->dev = &pdev->dev;
tspi->prod_list = devm_tegra_prod_get(tspi->dev);
if (IS_ERR_OR_NULL(tspi->prod_list)) {
dev_dbg(&pdev->dev, "Prod settings list not initialized\n");
tspi->prod_list = NULL;
}
spin_lock_init(&tspi->lock);
tspi->soc_data = of_device_get_match_data(&pdev->dev);
@@ -1396,12 +1440,14 @@ static int tegra_spi_probe(struct platform_device *pdev)
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
tspi->last_used_cs = host->num_chipselect + 1;
/* initialize CS with 0 in probe */
tegra_spi_set_prod(tspi, 0);
tspi->def_command1_reg = SPI_M_S;
tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
tspi->spi_cs_timing1 = tegra_spi_readl(tspi, SPI_CS_TIMING1);
tspi->spi_cs_timing2 = tegra_spi_readl(tspi, SPI_CS_TIMING2);
tspi->def_command2_reg = tegra_spi_readl(tspi, SPI_COMMAND2);
tspi->last_used_cs = host->num_chipselect + 1;
pm_runtime_put(&pdev->dev);
ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
tegra_spi_isr_thread, IRQF_ONESHOT,

View File

@@ -4,7 +4,7 @@
*
* High-speed serial driver for NVIDIA Tegra SoCs
*
* Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2012-2020, NVIDIA CORPORATION. All rights reserved.
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*/
@@ -1260,8 +1260,10 @@ static void tegra_uart_flush_buffer(struct uart_port *u)
struct tegra_uart_port *tup = to_tegra_uport(u);
tup->tx_bytes = 0;
if (tup->tx_dma_chan)
if (tup->tx_dma_chan) {
dmaengine_terminate_all(tup->tx_dma_chan);
tup->tx_in_progress = 0;
}
}
static void tegra_uart_shutdown(struct uart_port *u)

View File

@@ -2928,6 +2928,11 @@ pointer_reference {
kind: POINTER
pointee_type_id: 0x0b4592c2
}
pointer_reference {
id: 0x08451a23
kind: POINTER
pointee_type_id: 0x0b548e10
}
pointer_reference {
id: 0x084a0a2a
kind: POINTER
@@ -341018,6 +341023,11 @@ struct_union {
member_id: 0x321ff48e
}
}
struct_union {
id: 0x0b548e10
kind: STRUCT
name: "tegra_prod"
}
struct_union {
id: 0x539be05c
kind: STRUCT
@@ -389996,6 +390006,11 @@ function {
parameter_id: 0x5d8155a5
parameter_id: 0x4585663f
}
function {
id: 0x2329dac5
return_type_id: 0x08451a23
parameter_id: 0x0258f96e
}
function {
id: 0x244ac93e
return_type_id: 0x1847a854
@@ -423314,6 +423329,13 @@ function {
parameter_id: 0x3da0a8e3
parameter_id: 0x0faae5b1
}
function {
id: 0x9e556887
return_type_id: 0x6720d32f
parameter_id: 0x0cbf60eb
parameter_id: 0x3e10b518
parameter_id: 0x08451a23
}
function {
id: 0x9e559491
return_type_id: 0x6720d32f
@@ -423322,6 +423344,16 @@ function {
parameter_id: 0x1479c6e7
parameter_id: 0x2d8ee262
}
function {
id: 0x9e567dc1
return_type_id: 0x6720d32f
parameter_id: 0x0cbf60eb
parameter_id: 0x3e10b518
parameter_id: 0x08451a23
parameter_id: 0xc9082b19
parameter_id: 0xc9082b19
parameter_id: 0xc9082b19
}
function {
id: 0x9e584c40
return_type_id: 0x6720d32f
@@ -462049,6 +462081,15 @@ elf_symbol {
type_id: 0x2195423c
full_name: "devm_tegra_memory_controller_get"
}
elf_symbol {
id: 0x91b997b0
name: "devm_tegra_prod_get"
is_defined: true
symbol_type: FUNCTION
crc: 0x80f2a5af
type_id: 0x2329dac5
full_name: "devm_tegra_prod_get"
}
elf_symbol {
id: 0x0dd13028
name: "devm_thermal_of_cooling_device_register"
@@ -507215,6 +507256,24 @@ elf_symbol {
type_id: 0x8cffc9f3
full_name: "tegra_powergate_sequence_power_up"
}
elf_symbol {
id: 0x6e57088a
name: "tegra_prod_set_by_name"
is_defined: true
symbol_type: FUNCTION
crc: 0x94a77d4c
type_id: 0x9e556887
full_name: "tegra_prod_set_by_name"
}
elf_symbol {
id: 0xc54062b4
name: "tegra_prod_set_by_name_partially"
is_defined: true
symbol_type: FUNCTION
crc: 0xa19f1486
type_id: 0x9e567dc1
full_name: "tegra_prod_set_by_name_partially"
}
elf_symbol {
id: 0xcb1a674c
name: "tegra_sku_info"
@@ -521651,6 +521710,7 @@ interface {
symbol_id: 0x4433b91a
symbol_id: 0x072870b6
symbol_id: 0x43a4025b
symbol_id: 0x91b997b0
symbol_id: 0x0dd13028
symbol_id: 0xfc46114a
symbol_id: 0x5dc64161
@@ -526664,6 +526724,8 @@ interface {
symbol_id: 0x12723a3b
symbol_id: 0xdee7b025
symbol_id: 0xcfccceca
symbol_id: 0x6e57088a
symbol_id: 0xc54062b4
symbol_id: 0xcb1a674c
symbol_id: 0xfc1cafae
symbol_id: 0x5bbd3545

View File

@@ -205,6 +205,7 @@
devm_snd_soc_register_component
devm_tegra_core_dev_init_opp_table
devm_tegra_memory_controller_get
devm_tegra_prod_get
devm_thermal_of_zone_register
devm_usb_get_phy_by_node
_dev_notice
@@ -632,7 +633,9 @@
init_timer_key
init_wait_entry
__init_waitqueue_head
input_allocate_device
input_event
input_free_device
input_mt_init_slots
input_mt_report_slot_state
input_register_device
@@ -999,10 +1002,12 @@
regulator_bulk_set_supply_names
regulator_disable
regulator_enable
regulator_get
regulator_get_voltage_sel_regmap
regulator_is_enabled
regulator_list_voltage_linear
regulator_map_voltage_linear
regulator_put
regulator_set_voltage
regulator_set_voltage_sel_regmap
regulator_set_voltage_time_sel
@@ -1185,6 +1190,7 @@
tegra_powergate_power_off
tegra_powergate_remove_clamping
tegra_powergate_sequence_power_up
tegra_prod_set_by_name
tegra_sku_info
thermal_zone_device_priv
thermal_zone_device_update
@@ -1583,6 +1589,10 @@
unregister_filesystem
uuid_is_valid
# required by ftm4.ko
input_mt_destroy_slots
input_mt_report_finger_count
# required by fusb301.ko
__pm_relax
__pm_stay_awake
@@ -2205,8 +2215,6 @@
of_platform_depopulate
phy_create
phy_destroy
regulator_get
regulator_put
tegra210b01_plle_hw_sequence_is_enabled
tegra210b01_plle_hw_sequence_start
tegra210b01_xusb_pll_hw_control_enable
@@ -2340,8 +2348,6 @@
# required by rm31080a_ts.ko
find_vpid
input_allocate_device
input_free_device
pid_task
regulator_register_notifier
regulator_unregister_notifier
@@ -2403,6 +2409,7 @@
sdhci_setup_host
sdhci_start_signal_voltage_switch
sdhci_suspend_host
tegra_prod_set_by_name_partially
# required by serial-tegra.ko
handle_sysrq
@@ -2608,14 +2615,6 @@
spi_register_controller
spi_unregister_controller
# required by stmfts.ko
devm_input_allocate_device
devm_led_classdev_register_ext
devm_regulator_put
i2c_smbus_write_byte
input_set_capability
touchscreen_parse_properties
# required by stmmac-platform.ko
device_get_phy_mode
of_alias_get_highest_id

View File

@@ -65,6 +65,7 @@ struct mmc_ios {
#define MMC_TIMING_MMC_HS400 10
#define MMC_TIMING_SD_EXP 11
#define MMC_TIMING_SD_EXP_1_2V 12
#define MMC_TIMING_COUNTER 11
unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */

126
include/linux/tegra_prod.h Normal file
View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TEGRA_PRODS_H
#define _TEGRA_PRODS_H
struct tegra_prod;
/**
* tegra_prod_set_list(): Set all prods configurations
* @base: List of IO mapped registers.
* @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get()
* or tegra_prod_get_from_node();
*
* Configure all the prod configuration listed on prod-setting nodes.
*
* Returns 0 on success otherwise negive error number for failed case.
*/
int tegra_prod_set_list(void __iomem **base, struct tegra_prod *tegra_prod);
/**
* tegra_prod_set_boot_init(): Set all prods configurations which has boot init
* flag on the prod setting nodes.
* @base: List of IO mapped registers.
* @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get()
* or tegra_prod_get_from_node();
*
* Configure all the prod configuration listed on prod-setting nodes.
*
* Returns 0 on success otherwise negive error number for failed case.
*/
int tegra_prod_set_boot_init(void __iomem **base,
struct tegra_prod *tegra_prod);
/**
* tegra_prod_set_by_name(): Set prod configuration with specific prod name.
* This is used for conditional prod configurations.
* @base: List of IO mapped registers.
* @name: Name of conditional prod which need to be configure.
* @tegra_prod: tegra_prod handle which is allocated by devm_tegra_prod_get()
* or tegra_prod_get_from_node();
*
* Configure prod configuration with specific prod name for conditional
* prod configurations.
*
* Returns 0 on success otherwise negive error number for failed case.
*/
int tegra_prod_set_by_name(void __iomem **base, const char *name,
struct tegra_prod *tegra_prod);
/**
* tegra_prod_set_by_name_partially - Set the prod setting from list partially
* under given prod name. The matching is done
* qith index, offset and mask.
* @base: base address of the register.
* @name: the name of tegra prod need to set.
* @tegra_prod: the list of tegra prods.
* @index: Index of base address.
* @offset: Offset of the register.
* @mask: Mask field on given register.
*
* Find the tegra prod in the list according to the name. Then set
* that tegra prod which has matching of index, offset and mask.
*
* Returns 0 on success.
*/
int tegra_prod_set_by_name_partially(void __iomem **base, const char *name,
struct tegra_prod *tegra_prod, u32 index,
u32 offset, u32 mask);
/**
* tegra_prod_by_name_supported - Tell whether tegra prod will be supported by
* given name or not.
* @tegra_prod: the list of tegra prods.
* @name: the name of tegra prod need to set.
*
* Find the tegra prod in the list according to the name. If it exist then
* return true else false.
*/
bool tegra_prod_by_name_supported(struct tegra_prod *tegra_prod,
const char *name);
/**
* devm_tegra_prod_get(): Get the prod handle from the device.
* @dev: Device handle on which prod setting nodes are available.
*
* Parse the prod-setting node of the dev->of_node and keep all prod
* setting data in prod handle.
* This handle is used for setting prod configurations.
*
* Returns valid prod_list handle on success or pointer to the error
* when it failed.
*/
struct tegra_prod *devm_tegra_prod_get(struct device *dev);
/**
* devm_tegra_prod_get_from_node(): Get the prod handle from the node.
* @dev: Device handle.
* @np: Node pointer on which prod setting nodes are available.
*
* Parse the prod-setting node of the node pointer "np" and keep all prod
* setting data in prod handle.
* This handle is used for setting prod configurations.
*
* Returns valid prod_list handle on success or pointer to the error
* when it failed.
* The allocated resource is released by driver core framework when device
* is unbinded and so no need to call any release APIs for the tegra_prod
* handle.
*/
struct tegra_prod *devm_tegra_prod_get_from_node(struct device *dev,
struct device_node *np);
#endif