diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-01 19:35:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-01 19:35:31 -0500 |
commit | fe53d1443a146326b49d57fe6336b5c2a725223f (patch) | |
tree | 0bb6de8614bec52f025a0608910e80d6e9315245 /drivers/memory | |
parent | adbc128fa8b4e9ecfdd11d5dd0a7d9845c6ea510 (diff) | |
parent | 796543a64ebffdb638a22f428c4dadd037e34866 (diff) |
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Arnd Bergmann:
"A number of new drivers get added this time, along with many
low-priority bugfixes. The most interesting changes by subsystem are:
bus drivers:
- Updates to the Broadcom bus interface driver to support newer SoC
types
- The TI OMAP sysc driver now supports updated DT bindings
memory controllers:
- A new driver for Tegra186 gets added
- A new driver for the ti-emif sram, to allow relocating
suspend/resume handlers there
SoC specific:
- A new driver for Qualcomm QMI, the interface to the modem on MSM
SoCs
- A new driver for power domains on the actions S700 SoC
- A driver for the Xilinx Zynq VCU logicoreIP
reset controllers:
- A new driver for Amlogic Meson-AGX
- various bug fixes
tee subsystem:
- A new user interface got added to enable asynchronous communication
with the TEE supplicant.
- A new method of using user space memory for communication with the
TEE is added"
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (84 commits)
of: platform: fix OF node refcount leak
soc: fsl: guts: Add a NULL check for devm_kasprintf()
bus: ti-sysc: Fix smartreflex sysc mask
psci: add CPU_IDLE dependency
soc: xilinx: Fix Kconfig alignment
soc: xilinx: xlnx_vcu: Use bitwise & rather than logical && on clkoutdiv
soc: xilinx: xlnx_vcu: Depends on HAS_IOMEM for xlnx_vcu
soc: bcm: brcmstb: Be multi-platform compatible
soc: brcmstb: biuctrl: exit without warning on non brcmstb platforms
Revert "soc: brcmstb: Only register SoC device on STB platforms"
bus: omap: add MODULE_LICENSE tags
soc: brcmstb: Only register SoC device on STB platforms
tee: shm: Potential NULL dereference calling tee_shm_register()
soc: xilinx: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver
dt-bindings: soc: xilinx: Add DT bindings to xlnx_vcu driver
soc: xilinx: Create folder structure for soc specific drivers
of: platform: populate /firmware/ node from of_platform_default_populate_init()
soc: samsung: Add SPDX license identifiers
soc: qcom: smp2p: Use common error handling code in qcom_smp2p_probe()
tee: shm: don't put_page on null shm->pages
...
Diffstat (limited to 'drivers/memory')
-rw-r--r-- | drivers/memory/Kconfig | 10 | ||||
-rw-r--r-- | drivers/memory/Makefile | 8 | ||||
-rw-r--r-- | drivers/memory/Makefile.asm-offsets | 5 | ||||
-rw-r--r-- | drivers/memory/emif-asm-offsets.c | 92 | ||||
-rw-r--r-- | drivers/memory/emif.h | 17 | ||||
-rw-r--r-- | drivers/memory/tegra/Makefile | 1 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra114.c | 15 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra124.c | 17 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra186.c | 600 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra210.c | 15 | ||||
-rw-r--r-- | drivers/memory/tegra/tegra30.c | 15 | ||||
-rw-r--r-- | drivers/memory/ti-emif-pm.c | 324 | ||||
-rw-r--r-- | drivers/memory/ti-emif-sram-pm.S | 334 |
13 files changed, 1453 insertions, 0 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index ffc350258041..19a0e83f260d 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig | |||
@@ -84,6 +84,16 @@ config OMAP_GPMC_DEBUG | |||
84 | bootloader or else the GPMC timings won't be identical with the | 84 | bootloader or else the GPMC timings won't be identical with the |
85 | bootloader timings. | 85 | bootloader timings. |
86 | 86 | ||
87 | config TI_EMIF_SRAM | ||
88 | tristate "Texas Instruments EMIF SRAM driver" | ||
89 | depends on (SOC_AM33XX || SOC_AM43XX) && SRAM | ||
90 | help | ||
91 | This driver is for the EMIF module available on Texas Instruments | ||
92 | AM33XX and AM43XX SoCs and is required for PM. Certain parts of | ||
93 | the EMIF PM code must run from on-chip SRAM late in the suspend | ||
94 | sequence so this driver provides several relocatable PM functions | ||
95 | for the SoC PM code to use. | ||
96 | |||
87 | config MVEBU_DEVBUS | 97 | config MVEBU_DEVBUS |
88 | bool "Marvell EBU Device Bus Controller" | 98 | bool "Marvell EBU Device Bus Controller" |
89 | default y | 99 | default y |
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 929a601d4cd1..66f55240830e 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile | |||
@@ -23,3 +23,11 @@ obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o | |||
23 | 23 | ||
24 | obj-$(CONFIG_SAMSUNG_MC) += samsung/ | 24 | obj-$(CONFIG_SAMSUNG_MC) += samsung/ |
25 | obj-$(CONFIG_TEGRA_MC) += tegra/ | 25 | obj-$(CONFIG_TEGRA_MC) += tegra/ |
26 | obj-$(CONFIG_TI_EMIF_SRAM) += ti-emif-sram.o | ||
27 | ti-emif-sram-objs := ti-emif-pm.o ti-emif-sram-pm.o | ||
28 | |||
29 | AFLAGS_ti-emif-sram-pm.o :=-Wa,-march=armv7-a | ||
30 | |||
31 | include drivers/memory/Makefile.asm-offsets | ||
32 | |||
33 | drivers/memory/ti-emif-sram-pm.o: include/generated/ti-emif-asm-offsets.h | ||
diff --git a/drivers/memory/Makefile.asm-offsets b/drivers/memory/Makefile.asm-offsets new file mode 100644 index 000000000000..843ff60ccb5a --- /dev/null +++ b/drivers/memory/Makefile.asm-offsets | |||
@@ -0,0 +1,5 @@ | |||
1 | drivers/memory/emif-asm-offsets.s: drivers/memory/emif-asm-offsets.c | ||
2 | $(call if_changed_dep,cc_s_c) | ||
3 | |||
4 | include/generated/ti-emif-asm-offsets.h: drivers/memory/emif-asm-offsets.s FORCE | ||
5 | $(call filechk,offsets,__TI_EMIF_ASM_OFFSETS_H__) | ||
diff --git a/drivers/memory/emif-asm-offsets.c b/drivers/memory/emif-asm-offsets.c new file mode 100644 index 000000000000..71a89d5d3efd --- /dev/null +++ b/drivers/memory/emif-asm-offsets.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * TI AM33XX EMIF PM Assembly Offsets | ||
3 | * | ||
4 | * Copyright (C) 2016-2017 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | #include <linux/ti-emif-sram.h> | ||
16 | |||
17 | int main(void) | ||
18 | { | ||
19 | DEFINE(EMIF_SDCFG_VAL_OFFSET, | ||
20 | offsetof(struct emif_regs_amx3, emif_sdcfg_val)); | ||
21 | DEFINE(EMIF_TIMING1_VAL_OFFSET, | ||
22 | offsetof(struct emif_regs_amx3, emif_timing1_val)); | ||
23 | DEFINE(EMIF_TIMING2_VAL_OFFSET, | ||
24 | offsetof(struct emif_regs_amx3, emif_timing2_val)); | ||
25 | DEFINE(EMIF_TIMING3_VAL_OFFSET, | ||
26 | offsetof(struct emif_regs_amx3, emif_timing3_val)); | ||
27 | DEFINE(EMIF_REF_CTRL_VAL_OFFSET, | ||
28 | offsetof(struct emif_regs_amx3, emif_ref_ctrl_val)); | ||
29 | DEFINE(EMIF_ZQCFG_VAL_OFFSET, | ||
30 | offsetof(struct emif_regs_amx3, emif_zqcfg_val)); | ||
31 | DEFINE(EMIF_PMCR_VAL_OFFSET, | ||
32 | offsetof(struct emif_regs_amx3, emif_pmcr_val)); | ||
33 | DEFINE(EMIF_PMCR_SHDW_VAL_OFFSET, | ||
34 | offsetof(struct emif_regs_amx3, emif_pmcr_shdw_val)); | ||
35 | DEFINE(EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET, | ||
36 | offsetof(struct emif_regs_amx3, emif_rd_wr_level_ramp_ctrl)); | ||
37 | DEFINE(EMIF_RD_WR_EXEC_THRESH_OFFSET, | ||
38 | offsetof(struct emif_regs_amx3, emif_rd_wr_exec_thresh)); | ||
39 | DEFINE(EMIF_COS_CONFIG_OFFSET, | ||
40 | offsetof(struct emif_regs_amx3, emif_cos_config)); | ||
41 | DEFINE(EMIF_PRIORITY_TO_COS_MAPPING_OFFSET, | ||
42 | offsetof(struct emif_regs_amx3, emif_priority_to_cos_mapping)); | ||
43 | DEFINE(EMIF_CONNECT_ID_SERV_1_MAP_OFFSET, | ||
44 | offsetof(struct emif_regs_amx3, emif_connect_id_serv_1_map)); | ||
45 | DEFINE(EMIF_CONNECT_ID_SERV_2_MAP_OFFSET, | ||
46 | offsetof(struct emif_regs_amx3, emif_connect_id_serv_2_map)); | ||
47 | DEFINE(EMIF_OCP_CONFIG_VAL_OFFSET, | ||
48 | offsetof(struct emif_regs_amx3, emif_ocp_config_val)); | ||
49 | DEFINE(EMIF_LPDDR2_NVM_TIM_OFFSET, | ||
50 | offsetof(struct emif_regs_amx3, emif_lpddr2_nvm_tim)); | ||
51 | DEFINE(EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET, | ||
52 | offsetof(struct emif_regs_amx3, emif_lpddr2_nvm_tim_shdw)); | ||
53 | DEFINE(EMIF_DLL_CALIB_CTRL_VAL_OFFSET, | ||
54 | offsetof(struct emif_regs_amx3, emif_dll_calib_ctrl_val)); | ||
55 | DEFINE(EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET, | ||
56 | offsetof(struct emif_regs_amx3, emif_dll_calib_ctrl_val_shdw)); | ||
57 | DEFINE(EMIF_DDR_PHY_CTLR_1_OFFSET, | ||
58 | offsetof(struct emif_regs_amx3, emif_ddr_phy_ctlr_1)); | ||
59 | DEFINE(EMIF_EXT_PHY_CTRL_VALS_OFFSET, | ||
60 | offsetof(struct emif_regs_amx3, emif_ext_phy_ctrl_vals)); | ||
61 | DEFINE(EMIF_REGS_AMX3_SIZE, sizeof(struct emif_regs_amx3)); | ||
62 | |||
63 | BLANK(); | ||
64 | |||
65 | DEFINE(EMIF_PM_BASE_ADDR_VIRT_OFFSET, | ||
66 | offsetof(struct ti_emif_pm_data, ti_emif_base_addr_virt)); | ||
67 | DEFINE(EMIF_PM_BASE_ADDR_PHYS_OFFSET, | ||
68 | offsetof(struct ti_emif_pm_data, ti_emif_base_addr_phys)); | ||
69 | DEFINE(EMIF_PM_CONFIG_OFFSET, | ||
70 | offsetof(struct ti_emif_pm_data, ti_emif_sram_config)); | ||
71 | DEFINE(EMIF_PM_REGS_VIRT_OFFSET, | ||
72 | offsetof(struct ti_emif_pm_data, regs_virt)); | ||
73 | DEFINE(EMIF_PM_REGS_PHYS_OFFSET, | ||
74 | offsetof(struct ti_emif_pm_data, regs_phys)); | ||
75 | DEFINE(EMIF_PM_DATA_SIZE, sizeof(struct ti_emif_pm_data)); | ||
76 | |||
77 | BLANK(); | ||
78 | |||
79 | DEFINE(EMIF_PM_SAVE_CONTEXT_OFFSET, | ||
80 | offsetof(struct ti_emif_pm_functions, save_context)); | ||
81 | DEFINE(EMIF_PM_RESTORE_CONTEXT_OFFSET, | ||
82 | offsetof(struct ti_emif_pm_functions, restore_context)); | ||
83 | DEFINE(EMIF_PM_ENTER_SR_OFFSET, | ||
84 | offsetof(struct ti_emif_pm_functions, enter_sr)); | ||
85 | DEFINE(EMIF_PM_EXIT_SR_OFFSET, | ||
86 | offsetof(struct ti_emif_pm_functions, exit_sr)); | ||
87 | DEFINE(EMIF_PM_ABORT_SR_OFFSET, | ||
88 | offsetof(struct ti_emif_pm_functions, abort_sr)); | ||
89 | DEFINE(EMIF_PM_FUNCTIONS_SIZE, sizeof(struct ti_emif_pm_functions)); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h index bfe08bae961a..9e9f8037955d 100644 --- a/drivers/memory/emif.h +++ b/drivers/memory/emif.h | |||
@@ -555,6 +555,9 @@ | |||
555 | #define READ_LATENCY_SHDW_SHIFT 0 | 555 | #define READ_LATENCY_SHDW_SHIFT 0 |
556 | #define READ_LATENCY_SHDW_MASK (0x1f << 0) | 556 | #define READ_LATENCY_SHDW_MASK (0x1f << 0) |
557 | 557 | ||
558 | #define EMIF_SRAM_AM33_REG_LAYOUT 0x00000000 | ||
559 | #define EMIF_SRAM_AM43_REG_LAYOUT 0x00000001 | ||
560 | |||
558 | #ifndef __ASSEMBLY__ | 561 | #ifndef __ASSEMBLY__ |
559 | /* | 562 | /* |
560 | * Structure containing shadow of important registers in EMIF | 563 | * Structure containing shadow of important registers in EMIF |
@@ -585,5 +588,19 @@ struct emif_regs { | |||
585 | u32 ext_phy_ctrl_3_shdw; | 588 | u32 ext_phy_ctrl_3_shdw; |
586 | u32 ext_phy_ctrl_4_shdw; | 589 | u32 ext_phy_ctrl_4_shdw; |
587 | }; | 590 | }; |
591 | |||
592 | struct ti_emif_pm_functions; | ||
593 | |||
594 | extern unsigned int ti_emif_sram; | ||
595 | extern unsigned int ti_emif_sram_sz; | ||
596 | extern struct ti_emif_pm_data ti_emif_pm_sram_data; | ||
597 | extern struct emif_regs_amx3 ti_emif_regs_amx3; | ||
598 | |||
599 | void ti_emif_save_context(void); | ||
600 | void ti_emif_restore_context(void); | ||
601 | void ti_emif_enter_sr(void); | ||
602 | void ti_emif_exit_sr(void); | ||
603 | void ti_emif_abort_sr(void); | ||
604 | |||
588 | #endif /* __ASSEMBLY__ */ | 605 | #endif /* __ASSEMBLY__ */ |
589 | #endif /* __EMIF_H */ | 606 | #endif /* __EMIF_H */ |
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile index b44e8627a5e0..ce87a9470034 100644 --- a/drivers/memory/tegra/Makefile +++ b/drivers/memory/tegra/Makefile | |||
@@ -10,3 +10,4 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o | |||
10 | obj-$(CONFIG_TEGRA_MC) += tegra-mc.o | 10 | obj-$(CONFIG_TEGRA_MC) += tegra-mc.o |
11 | 11 | ||
12 | obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o | 12 | obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o |
13 | obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o | ||
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c index ba8fff3d66a6..b20e6e3e208e 100644 --- a/drivers/memory/tegra/tegra114.c +++ b/drivers/memory/tegra/tegra114.c | |||
@@ -912,11 +912,26 @@ static const struct tegra_smmu_swgroup tegra114_swgroups[] = { | |||
912 | { .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, | 912 | { .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 }, |
913 | }; | 913 | }; |
914 | 914 | ||
915 | static const unsigned int tegra114_group_display[] = { | ||
916 | TEGRA_SWGROUP_DC, | ||
917 | TEGRA_SWGROUP_DCB, | ||
918 | }; | ||
919 | |||
920 | static const struct tegra_smmu_group_soc tegra114_groups[] = { | ||
921 | { | ||
922 | .name = "display", | ||
923 | .swgroups = tegra114_group_display, | ||
924 | .num_swgroups = ARRAY_SIZE(tegra114_group_display), | ||
925 | }, | ||
926 | }; | ||
927 | |||
915 | static const struct tegra_smmu_soc tegra114_smmu_soc = { | 928 | static const struct tegra_smmu_soc tegra114_smmu_soc = { |
916 | .clients = tegra114_mc_clients, | 929 | .clients = tegra114_mc_clients, |
917 | .num_clients = ARRAY_SIZE(tegra114_mc_clients), | 930 | .num_clients = ARRAY_SIZE(tegra114_mc_clients), |
918 | .swgroups = tegra114_swgroups, | 931 | .swgroups = tegra114_swgroups, |
919 | .num_swgroups = ARRAY_SIZE(tegra114_swgroups), | 932 | .num_swgroups = ARRAY_SIZE(tegra114_swgroups), |
933 | .groups = tegra114_groups, | ||
934 | .num_groups = ARRAY_SIZE(tegra114_groups), | ||
920 | .supports_round_robin_arbitration = false, | 935 | .supports_round_robin_arbitration = false, |
921 | .supports_request_limit = false, | 936 | .supports_request_limit = false, |
922 | .num_tlb_lines = 32, | 937 | .num_tlb_lines = 32, |
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index 5a58e440f4a7..8b6360eabb8a 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c | |||
@@ -999,12 +999,27 @@ static const struct tegra_smmu_swgroup tegra124_swgroups[] = { | |||
999 | { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, | 999 | { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 }, |
1000 | }; | 1000 | }; |
1001 | 1001 | ||
1002 | static const unsigned int tegra124_group_display[] = { | ||
1003 | TEGRA_SWGROUP_DC, | ||
1004 | TEGRA_SWGROUP_DCB, | ||
1005 | }; | ||
1006 | |||
1007 | static const struct tegra_smmu_group_soc tegra124_groups[] = { | ||
1008 | { | ||
1009 | .name = "display", | ||
1010 | .swgroups = tegra124_group_display, | ||
1011 | .num_swgroups = ARRAY_SIZE(tegra124_group_display), | ||
1012 | }, | ||
1013 | }; | ||
1014 | |||
1002 | #ifdef CONFIG_ARCH_TEGRA_124_SOC | 1015 | #ifdef CONFIG_ARCH_TEGRA_124_SOC |
1003 | static const struct tegra_smmu_soc tegra124_smmu_soc = { | 1016 | static const struct tegra_smmu_soc tegra124_smmu_soc = { |
1004 | .clients = tegra124_mc_clients, | 1017 | .clients = tegra124_mc_clients, |
1005 | .num_clients = ARRAY_SIZE(tegra124_mc_clients), | 1018 | .num_clients = ARRAY_SIZE(tegra124_mc_clients), |
1006 | .swgroups = tegra124_swgroups, | 1019 | .swgroups = tegra124_swgroups, |
1007 | .num_swgroups = ARRAY_SIZE(tegra124_swgroups), | 1020 | .num_swgroups = ARRAY_SIZE(tegra124_swgroups), |
1021 | .groups = tegra124_groups, | ||
1022 | .num_groups = ARRAY_SIZE(tegra124_groups), | ||
1008 | .supports_round_robin_arbitration = true, | 1023 | .supports_round_robin_arbitration = true, |
1009 | .supports_request_limit = true, | 1024 | .supports_request_limit = true, |
1010 | .num_tlb_lines = 32, | 1025 | .num_tlb_lines = 32, |
@@ -1029,6 +1044,8 @@ static const struct tegra_smmu_soc tegra132_smmu_soc = { | |||
1029 | .num_clients = ARRAY_SIZE(tegra124_mc_clients), | 1044 | .num_clients = ARRAY_SIZE(tegra124_mc_clients), |
1030 | .swgroups = tegra124_swgroups, | 1045 | .swgroups = tegra124_swgroups, |
1031 | .num_swgroups = ARRAY_SIZE(tegra124_swgroups), | 1046 | .num_swgroups = ARRAY_SIZE(tegra124_swgroups), |
1047 | .groups = tegra124_groups, | ||
1048 | .num_groups = ARRAY_SIZE(tegra124_groups), | ||
1032 | .supports_round_robin_arbitration = true, | 1049 | .supports_round_robin_arbitration = true, |
1033 | .supports_request_limit = true, | 1050 | .supports_request_limit = true, |
1034 | .num_tlb_lines = 32, | 1051 | .num_tlb_lines = 32, |
diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c new file mode 100644 index 000000000000..7254fb596979 --- /dev/null +++ b/drivers/memory/tegra/tegra186.c | |||
@@ -0,0 +1,600 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/io.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | #include <dt-bindings/memory/tegra186-mc.h> | ||
14 | |||
15 | struct tegra_mc { | ||
16 | struct device *dev; | ||
17 | void __iomem *regs; | ||
18 | }; | ||
19 | |||
20 | struct tegra_mc_client { | ||
21 | const char *name; | ||
22 | unsigned int sid; | ||
23 | struct { | ||
24 | unsigned int override; | ||
25 | unsigned int security; | ||
26 | } regs; | ||
27 | }; | ||
28 | |||
29 | static const struct tegra_mc_client tegra186_mc_clients[] = { | ||
30 | { | ||
31 | .name = "ptcr", | ||
32 | .sid = TEGRA186_SID_PASSTHROUGH, | ||
33 | .regs = { | ||
34 | .override = 0x000, | ||
35 | .security = 0x004, | ||
36 | }, | ||
37 | }, { | ||
38 | .name = "afir", | ||
39 | .sid = TEGRA186_SID_AFI, | ||
40 | .regs = { | ||
41 | .override = 0x070, | ||
42 | .security = 0x074, | ||
43 | }, | ||
44 | }, { | ||
45 | .name = "hdar", | ||
46 | .sid = TEGRA186_SID_HDA, | ||
47 | .regs = { | ||
48 | .override = 0x0a8, | ||
49 | .security = 0x0ac, | ||
50 | }, | ||
51 | }, { | ||
52 | .name = "host1xdmar", | ||
53 | .sid = TEGRA186_SID_HOST1X, | ||
54 | .regs = { | ||
55 | .override = 0x0b0, | ||
56 | .security = 0x0b4, | ||
57 | }, | ||
58 | }, { | ||
59 | .name = "nvencsrd", | ||
60 | .sid = TEGRA186_SID_NVENC, | ||
61 | .regs = { | ||
62 | .override = 0x0e0, | ||
63 | .security = 0x0e4, | ||
64 | }, | ||
65 | }, { | ||
66 | .name = "satar", | ||
67 | .sid = TEGRA186_SID_SATA, | ||
68 | .regs = { | ||
69 | .override = 0x0f8, | ||
70 | .security = 0x0fc, | ||
71 | }, | ||
72 | }, { | ||
73 | .name = "mpcorer", | ||
74 | .sid = TEGRA186_SID_PASSTHROUGH, | ||
75 | .regs = { | ||
76 | .override = 0x138, | ||
77 | .security = 0x13c, | ||
78 | }, | ||
79 | }, { | ||
80 | .name = "nvencswr", | ||
81 | .sid = TEGRA186_SID_NVENC, | ||
82 | .regs = { | ||
83 | .override = 0x158, | ||
84 | .security = 0x15c, | ||
85 | }, | ||
86 | }, { | ||
87 | .name = "afiw", | ||
88 | .sid = TEGRA186_SID_AFI, | ||
89 | .regs = { | ||
90 | .override = 0x188, | ||
91 | .security = 0x18c, | ||
92 | }, | ||
93 | }, { | ||
94 | .name = "hdaw", | ||
95 | .sid = TEGRA186_SID_HDA, | ||
96 | .regs = { | ||
97 | .override = 0x1a8, | ||
98 | .security = 0x1ac, | ||
99 | }, | ||
100 | }, { | ||
101 | .name = "mpcorew", | ||
102 | .sid = TEGRA186_SID_PASSTHROUGH, | ||
103 | .regs = { | ||
104 | .override = 0x1c8, | ||
105 | .security = 0x1cc, | ||
106 | }, | ||
107 | }, { | ||
108 | .name = "sataw", | ||
109 | .sid = TEGRA186_SID_SATA, | ||
110 | .regs = { | ||
111 | .override = 0x1e8, | ||
112 | .security = 0x1ec, | ||
113 | }, | ||
114 | }, { | ||
115 | .name = "ispra", | ||
116 | .sid = TEGRA186_SID_ISP, | ||
117 | .regs = { | ||
118 | .override = 0x220, | ||
119 | .security = 0x224, | ||
120 | }, | ||
121 | }, { | ||
122 | .name = "ispwa", | ||
123 | .sid = TEGRA186_SID_ISP, | ||
124 | .regs = { | ||
125 | .override = 0x230, | ||
126 | .security = 0x234, | ||
127 | }, | ||
128 | }, { | ||
129 | .name = "ispwb", | ||
130 | .sid = TEGRA186_SID_ISP, | ||
131 | .regs = { | ||
132 | .override = 0x238, | ||
133 | .security = 0x23c, | ||
134 | }, | ||
135 | }, { | ||
136 | .name = "xusb_hostr", | ||
137 | .sid = TEGRA186_SID_XUSB_HOST, | ||
138 | .regs = { | ||
139 | .override = 0x250, | ||
140 | .security = 0x254, | ||
141 | }, | ||
142 | }, { | ||
143 | .name = "xusb_hostw", | ||
144 | .sid = TEGRA186_SID_XUSB_HOST, | ||
145 | .regs = { | ||
146 | .override = 0x258, | ||
147 | .security = 0x25c, | ||
148 | }, | ||
149 | }, { | ||
150 | .name = "xusb_devr", | ||
151 | .sid = TEGRA186_SID_XUSB_DEV, | ||
152 | .regs = { | ||
153 | .override = 0x260, | ||
154 | .security = 0x264, | ||
155 | }, | ||
156 | }, { | ||
157 | .name = "xusb_devw", | ||
158 | .sid = TEGRA186_SID_XUSB_DEV, | ||
159 | .regs = { | ||
160 | .override = 0x268, | ||
161 | .security = 0x26c, | ||
162 | }, | ||
163 | }, { | ||
164 | .name = "tsecsrd", | ||
165 | .sid = TEGRA186_SID_TSEC, | ||
166 | .regs = { | ||
167 | .override = 0x2a0, | ||
168 | .security = 0x2a4, | ||
169 | }, | ||
170 | }, { | ||
171 | .name = "tsecswr", | ||
172 | .sid = TEGRA186_SID_TSEC, | ||
173 | .regs = { | ||
174 | .override = 0x2a8, | ||
175 | .security = 0x2ac, | ||
176 | }, | ||
177 | }, { | ||
178 | .name = "gpusrd", | ||
179 | .sid = TEGRA186_SID_GPU, | ||
180 | .regs = { | ||
181 | .override = 0x2c0, | ||
182 | .security = 0x2c4, | ||
183 | }, | ||
184 | }, { | ||
185 | .name = "gpuswr", | ||
186 | .sid = TEGRA186_SID_GPU, | ||
187 | .regs = { | ||
188 | .override = 0x2c8, | ||
189 | .security = 0x2cc, | ||
190 | }, | ||
191 | }, { | ||
192 | .name = "sdmmcra", | ||
193 | .sid = TEGRA186_SID_SDMMC1, | ||
194 | .regs = { | ||
195 | .override = 0x300, | ||
196 | .security = 0x304, | ||
197 | }, | ||
198 | }, { | ||
199 | .name = "sdmmcraa", | ||
200 | .sid = TEGRA186_SID_SDMMC2, | ||
201 | .regs = { | ||
202 | .override = 0x308, | ||
203 | .security = 0x30c, | ||
204 | }, | ||
205 | }, { | ||
206 | .name = "sdmmcr", | ||
207 | .sid = TEGRA186_SID_SDMMC3, | ||
208 | .regs = { | ||
209 | .override = 0x310, | ||
210 | .security = 0x314, | ||
211 | }, | ||
212 | }, { | ||
213 | .name = "sdmmcrab", | ||
214 | .sid = TEGRA186_SID_SDMMC4, | ||
215 | .regs = { | ||
216 | .override = 0x318, | ||
217 | .security = 0x31c, | ||
218 | }, | ||
219 | }, { | ||
220 | .name = "sdmmcwa", | ||
221 | .sid = TEGRA186_SID_SDMMC1, | ||
222 | .regs = { | ||
223 | .override = 0x320, | ||
224 | .security = 0x324, | ||
225 | }, | ||
226 | }, { | ||
227 | .name = "sdmmcwaa", | ||
228 | .sid = TEGRA186_SID_SDMMC2, | ||
229 | .regs = { | ||
230 | .override = 0x328, | ||
231 | .security = 0x32c, | ||
232 | }, | ||
233 | }, { | ||
234 | .name = "sdmmcw", | ||
235 | .sid = TEGRA186_SID_SDMMC3, | ||
236 | .regs = { | ||
237 | .override = 0x330, | ||
238 | .security = 0x334, | ||
239 | }, | ||
240 | }, { | ||
241 | .name = "sdmmcwab", | ||
242 | .sid = TEGRA186_SID_SDMMC4, | ||
243 | .regs = { | ||
244 | .override = 0x338, | ||
245 | .security = 0x33c, | ||
246 | }, | ||
247 | }, { | ||
248 | .name = "vicsrd", | ||
249 | .sid = TEGRA186_SID_VIC, | ||
250 | .regs = { | ||
251 | .override = 0x360, | ||
252 | .security = 0x364, | ||
253 | }, | ||
254 | }, { | ||
255 | .name = "vicswr", | ||
256 | .sid = TEGRA186_SID_VIC, | ||
257 | .regs = { | ||
258 | .override = 0x368, | ||
259 | .security = 0x36c, | ||
260 | }, | ||
261 | }, { | ||
262 | .name = "viw", | ||
263 | .sid = TEGRA186_SID_VI, | ||
264 | .regs = { | ||
265 | .override = 0x390, | ||
266 | .security = 0x394, | ||
267 | }, | ||
268 | }, { | ||
269 | .name = "nvdecsrd", | ||
270 | .sid = TEGRA186_SID_NVDEC, | ||
271 | .regs = { | ||
272 | .override = 0x3c0, | ||
273 | .security = 0x3c4, | ||
274 | }, | ||
275 | }, { | ||
276 | .name = "nvdecswr", | ||
277 | .sid = TEGRA186_SID_NVDEC, | ||
278 | .regs = { | ||
279 | .override = 0x3c8, | ||
280 | .security = 0x3cc, | ||
281 | }, | ||
282 | }, { | ||
283 | .name = "aper", | ||
284 | .sid = TEGRA186_SID_APE, | ||
285 | .regs = { | ||
286 | .override = 0x3d0, | ||
287 | .security = 0x3d4, | ||
288 | }, | ||
289 | }, { | ||
290 | .name = "apew", | ||
291 | .sid = TEGRA186_SID_APE, | ||
292 | .regs = { | ||
293 | .override = 0x3d8, | ||
294 | .security = 0x3dc, | ||
295 | }, | ||
296 | }, { | ||
297 | .name = "nvjpgsrd", | ||
298 | .sid = TEGRA186_SID_NVJPG, | ||
299 | .regs = { | ||
300 | .override = 0x3f0, | ||
301 | .security = 0x3f4, | ||
302 | }, | ||
303 | }, { | ||
304 | .name = "nvjpgswr", | ||
305 | .sid = TEGRA186_SID_NVJPG, | ||
306 | .regs = { | ||
307 | .override = 0x3f8, | ||
308 | .security = 0x3fc, | ||
309 | }, | ||
310 | }, { | ||
311 | .name = "sesrd", | ||
312 | .sid = TEGRA186_SID_SE, | ||
313 | .regs = { | ||
314 | .override = 0x400, | ||
315 | .security = 0x404, | ||
316 | }, | ||
317 | }, { | ||
318 | .name = "seswr", | ||
319 | .sid = TEGRA186_SID_SE, | ||
320 | .regs = { | ||
321 | .override = 0x408, | ||
322 | .security = 0x40c, | ||
323 | }, | ||
324 | }, { | ||
325 | .name = "etrr", | ||
326 | .sid = TEGRA186_SID_ETR, | ||
327 | .regs = { | ||
328 | .override = 0x420, | ||
329 | .security = 0x424, | ||
330 | }, | ||
331 | }, { | ||
332 | .name = "etrw", | ||
333 | .sid = TEGRA186_SID_ETR, | ||
334 | .regs = { | ||
335 | .override = 0x428, | ||
336 | .security = 0x42c, | ||
337 | }, | ||
338 | }, { | ||
339 | .name = "tsecsrdb", | ||
340 | .sid = TEGRA186_SID_TSECB, | ||
341 | .regs = { | ||
342 | .override = 0x430, | ||
343 | .security = 0x434, | ||
344 | }, | ||
345 | }, { | ||
346 | .name = "tsecswrb", | ||
347 | .sid = TEGRA186_SID_TSECB, | ||
348 | .regs = { | ||
349 | .override = 0x438, | ||
350 | .security = 0x43c, | ||
351 | }, | ||
352 | }, { | ||
353 | .name = "gpusrd2", | ||
354 | .sid = TEGRA186_SID_GPU, | ||
355 | .regs = { | ||
356 | .override = 0x440, | ||
357 | .security = 0x444, | ||
358 | }, | ||
359 | }, { | ||
360 | .name = "gpuswr2", | ||
361 | .sid = TEGRA186_SID_GPU, | ||
362 | .regs = { | ||
363 | .override = 0x448, | ||
364 | .security = 0x44c, | ||
365 | }, | ||
366 | }, { | ||
367 | .name = "axisr", | ||
368 | .sid = TEGRA186_SID_GPCDMA_0, | ||
369 | .regs = { | ||
370 | .override = 0x460, | ||
371 | .security = 0x464, | ||
372 | }, | ||
373 | }, { | ||
374 | .name = "axisw", | ||
375 | .sid = TEGRA186_SID_GPCDMA_0, | ||
376 | .regs = { | ||
377 | .override = 0x468, | ||
378 | .security = 0x46c, | ||
379 | }, | ||
380 | }, { | ||
381 | .name = "eqosr", | ||
382 | .sid = TEGRA186_SID_EQOS, | ||
383 | .regs = { | ||
384 | .override = 0x470, | ||
385 | .security = 0x474, | ||
386 | }, | ||
387 | }, { | ||
388 | .name = "eqosw", | ||
389 | .sid = TEGRA186_SID_EQOS, | ||
390 | .regs = { | ||
391 | .override = 0x478, | ||
392 | .security = 0x47c, | ||
393 | }, | ||
394 | }, { | ||
395 | .name = "ufshcr", | ||
396 | .sid = TEGRA186_SID_UFSHC, | ||
397 | .regs = { | ||
398 | .override = 0x480, | ||
399 | .security = 0x484, | ||
400 | }, | ||
401 | }, { | ||
402 | .name = "ufshcw", | ||
403 | .sid = TEGRA186_SID_UFSHC, | ||
404 | .regs = { | ||
405 | .override = 0x488, | ||
406 | .security = 0x48c, | ||
407 | }, | ||
408 | }, { | ||
409 | .name = "nvdisplayr", | ||
410 | .sid = TEGRA186_SID_NVDISPLAY, | ||
411 | .regs = { | ||
412 | .override = 0x490, | ||
413 | .security = 0x494, | ||
414 | }, | ||
415 | }, { | ||
416 | .name = "bpmpr", | ||
417 | .sid = TEGRA186_SID_BPMP, | ||
418 | .regs = { | ||
419 | .override = 0x498, | ||
420 | .security = 0x49c, | ||
421 | }, | ||
422 | }, { | ||
423 | .name = "bpmpw", | ||
424 | .sid = TEGRA186_SID_BPMP, | ||
425 | .regs = { | ||
426 | .override = 0x4a0, | ||
427 | .security = 0x4a4, | ||
428 | }, | ||
429 | }, { | ||
430 | .name = "bpmpdmar", | ||
431 | .sid = TEGRA186_SID_BPMP, | ||
432 | .regs = { | ||
433 | .override = 0x4a8, | ||
434 | .security = 0x4ac, | ||
435 | }, | ||
436 | }, { | ||
437 | .name = "bpmpdmaw", | ||
438 | .sid = TEGRA186_SID_BPMP, | ||
439 | .regs = { | ||
440 | .override = 0x4b0, | ||
441 | .security = 0x4b4, | ||
442 | }, | ||
443 | }, { | ||
444 | .name = "aonr", | ||
445 | .sid = TEGRA186_SID_AON, | ||
446 | .regs = { | ||
447 | .override = 0x4b8, | ||
448 | .security = 0x4bc, | ||
449 | }, | ||
450 | }, { | ||
451 | .name = "aonw", | ||
452 | .sid = TEGRA186_SID_AON, | ||
453 | .regs = { | ||
454 | .override = 0x4c0, | ||
455 | .security = 0x4c4, | ||
456 | }, | ||
457 | }, { | ||
458 | .name = "aondmar", | ||
459 | .sid = TEGRA186_SID_AON, | ||
460 | .regs = { | ||
461 | .override = 0x4c8, | ||
462 | .security = 0x4cc, | ||
463 | }, | ||
464 | }, { | ||
465 | .name = "aondmaw", | ||
466 | .sid = TEGRA186_SID_AON, | ||
467 | .regs = { | ||
468 | .override = 0x4d0, | ||
469 | .security = 0x4d4, | ||
470 | }, | ||
471 | }, { | ||
472 | .name = "scer", | ||
473 | .sid = TEGRA186_SID_SCE, | ||
474 | .regs = { | ||
475 | .override = 0x4d8, | ||
476 | .security = 0x4dc, | ||
477 | }, | ||
478 | }, { | ||
479 | .name = "scew", | ||
480 | .sid = TEGRA186_SID_SCE, | ||
481 | .regs = { | ||
482 | .override = 0x4e0, | ||
483 | .security = 0x4e4, | ||
484 | }, | ||
485 | }, { | ||
486 | .name = "scedmar", | ||
487 | .sid = TEGRA186_SID_SCE, | ||
488 | .regs = { | ||
489 | .override = 0x4e8, | ||
490 | .security = 0x4ec, | ||
491 | }, | ||
492 | }, { | ||
493 | .name = "scedmaw", | ||
494 | .sid = TEGRA186_SID_SCE, | ||
495 | .regs = { | ||
496 | .override = 0x4f0, | ||
497 | .security = 0x4f4, | ||
498 | }, | ||
499 | }, { | ||
500 | .name = "apedmar", | ||
501 | .sid = TEGRA186_SID_APE, | ||
502 | .regs = { | ||
503 | .override = 0x4f8, | ||
504 | .security = 0x4fc, | ||
505 | }, | ||
506 | }, { | ||
507 | .name = "apedmaw", | ||
508 | .sid = TEGRA186_SID_APE, | ||
509 | .regs = { | ||
510 | .override = 0x500, | ||
511 | .security = 0x504, | ||
512 | }, | ||
513 | }, { | ||
514 | .name = "nvdisplayr1", | ||
515 | .sid = TEGRA186_SID_NVDISPLAY, | ||
516 | .regs = { | ||
517 | .override = 0x508, | ||
518 | .security = 0x50c, | ||
519 | }, | ||
520 | }, { | ||
521 | .name = "vicsrd1", | ||
522 | .sid = TEGRA186_SID_VIC, | ||
523 | .regs = { | ||
524 | .override = 0x510, | ||
525 | .security = 0x514, | ||
526 | }, | ||
527 | }, { | ||
528 | .name = "nvdecsrd1", | ||
529 | .sid = TEGRA186_SID_NVDEC, | ||
530 | .regs = { | ||
531 | .override = 0x518, | ||
532 | .security = 0x51c, | ||
533 | }, | ||
534 | }, | ||
535 | }; | ||
536 | |||
537 | static int tegra186_mc_probe(struct platform_device *pdev) | ||
538 | { | ||
539 | struct resource *res; | ||
540 | struct tegra_mc *mc; | ||
541 | unsigned int i; | ||
542 | int err = 0; | ||
543 | |||
544 | mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); | ||
545 | if (!mc) | ||
546 | return -ENOMEM; | ||
547 | |||
548 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
549 | mc->regs = devm_ioremap_resource(&pdev->dev, res); | ||
550 | if (IS_ERR(mc->regs)) | ||
551 | return PTR_ERR(mc->regs); | ||
552 | |||
553 | mc->dev = &pdev->dev; | ||
554 | |||
555 | for (i = 0; i < ARRAY_SIZE(tegra186_mc_clients); i++) { | ||
556 | const struct tegra_mc_client *client = &tegra186_mc_clients[i]; | ||
557 | u32 override, security; | ||
558 | |||
559 | override = readl(mc->regs + client->regs.override); | ||
560 | security = readl(mc->regs + client->regs.security); | ||
561 | |||
562 | dev_dbg(&pdev->dev, "client %s: override: %x security: %x\n", | ||
563 | client->name, override, security); | ||
564 | |||
565 | dev_dbg(&pdev->dev, "setting SID %u for %s\n", client->sid, | ||
566 | client->name); | ||
567 | writel(client->sid, mc->regs + client->regs.override); | ||
568 | |||
569 | override = readl(mc->regs + client->regs.override); | ||
570 | security = readl(mc->regs + client->regs.security); | ||
571 | |||
572 | dev_dbg(&pdev->dev, "client %s: override: %x security: %x\n", | ||
573 | client->name, override, security); | ||
574 | } | ||
575 | |||
576 | platform_set_drvdata(pdev, mc); | ||
577 | |||
578 | return err; | ||
579 | } | ||
580 | |||
581 | static const struct of_device_id tegra186_mc_of_match[] = { | ||
582 | { .compatible = "nvidia,tegra186-mc", }, | ||
583 | { /* sentinel */ } | ||
584 | }; | ||
585 | MODULE_DEVICE_TABLE(of, tegra186_mc_of_match); | ||
586 | |||
587 | static struct platform_driver tegra186_mc_driver = { | ||
588 | .driver = { | ||
589 | .name = "tegra186-mc", | ||
590 | .of_match_table = tegra186_mc_of_match, | ||
591 | .suppress_bind_attrs = true, | ||
592 | }, | ||
593 | .prevent_deferred_probe = true, | ||
594 | .probe = tegra186_mc_probe, | ||
595 | }; | ||
596 | module_platform_driver(tegra186_mc_driver); | ||
597 | |||
598 | MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); | ||
599 | MODULE_DESCRIPTION("NVIDIA Tegra186 Memory Controller driver"); | ||
600 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c index 5e144abe4c18..d398bcd3fc57 100644 --- a/drivers/memory/tegra/tegra210.c +++ b/drivers/memory/tegra/tegra210.c | |||
@@ -1059,11 +1059,26 @@ static const struct tegra_smmu_swgroup tegra210_swgroups[] = { | |||
1059 | { .name = "tsecb", .swgroup = TEGRA_SWGROUP_TSECB, .reg = 0xad4 }, | 1059 | { .name = "tsecb", .swgroup = TEGRA_SWGROUP_TSECB, .reg = 0xad4 }, |
1060 | }; | 1060 | }; |
1061 | 1061 | ||
1062 | static const unsigned int tegra210_group_display[] = { | ||
1063 | TEGRA_SWGROUP_DC, | ||
1064 | TEGRA_SWGROUP_DCB, | ||
1065 | }; | ||
1066 | |||
1067 | static const struct tegra_smmu_group_soc tegra210_groups[] = { | ||
1068 | { | ||
1069 | .name = "display", | ||
1070 | .swgroups = tegra210_group_display, | ||
1071 | .num_swgroups = ARRAY_SIZE(tegra210_group_display), | ||
1072 | }, | ||
1073 | }; | ||
1074 | |||
1062 | static const struct tegra_smmu_soc tegra210_smmu_soc = { | 1075 | static const struct tegra_smmu_soc tegra210_smmu_soc = { |
1063 | .clients = tegra210_mc_clients, | 1076 | .clients = tegra210_mc_clients, |
1064 | .num_clients = ARRAY_SIZE(tegra210_mc_clients), | 1077 | .num_clients = ARRAY_SIZE(tegra210_mc_clients), |
1065 | .swgroups = tegra210_swgroups, | 1078 | .swgroups = tegra210_swgroups, |
1066 | .num_swgroups = ARRAY_SIZE(tegra210_swgroups), | 1079 | .num_swgroups = ARRAY_SIZE(tegra210_swgroups), |
1080 | .groups = tegra210_groups, | ||
1081 | .num_groups = ARRAY_SIZE(tegra210_groups), | ||
1067 | .supports_round_robin_arbitration = true, | 1082 | .supports_round_robin_arbitration = true, |
1068 | .supports_request_limit = true, | 1083 | .supports_request_limit = true, |
1069 | .num_tlb_lines = 32, | 1084 | .num_tlb_lines = 32, |
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c index b44737840e70..d756c837f23e 100644 --- a/drivers/memory/tegra/tegra30.c +++ b/drivers/memory/tegra/tegra30.c | |||
@@ -934,11 +934,26 @@ static const struct tegra_smmu_swgroup tegra30_swgroups[] = { | |||
934 | { .name = "isp", .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, | 934 | { .name = "isp", .swgroup = TEGRA_SWGROUP_ISP, .reg = 0x258 }, |
935 | }; | 935 | }; |
936 | 936 | ||
937 | static const unsigned int tegra30_group_display[] = { | ||
938 | TEGRA_SWGROUP_DC, | ||
939 | TEGRA_SWGROUP_DCB, | ||
940 | }; | ||
941 | |||
942 | static const struct tegra_smmu_group_soc tegra30_groups[] = { | ||
943 | { | ||
944 | .name = "display", | ||
945 | .swgroups = tegra30_group_display, | ||
946 | .num_swgroups = ARRAY_SIZE(tegra30_group_display), | ||
947 | }, | ||
948 | }; | ||
949 | |||
937 | static const struct tegra_smmu_soc tegra30_smmu_soc = { | 950 | static const struct tegra_smmu_soc tegra30_smmu_soc = { |
938 | .clients = tegra30_mc_clients, | 951 | .clients = tegra30_mc_clients, |
939 | .num_clients = ARRAY_SIZE(tegra30_mc_clients), | 952 | .num_clients = ARRAY_SIZE(tegra30_mc_clients), |
940 | .swgroups = tegra30_swgroups, | 953 | .swgroups = tegra30_swgroups, |
941 | .num_swgroups = ARRAY_SIZE(tegra30_swgroups), | 954 | .num_swgroups = ARRAY_SIZE(tegra30_swgroups), |
955 | .groups = tegra30_groups, | ||
956 | .num_groups = ARRAY_SIZE(tegra30_groups), | ||
942 | .supports_round_robin_arbitration = false, | 957 | .supports_round_robin_arbitration = false, |
943 | .supports_request_limit = false, | 958 | .supports_request_limit = false, |
944 | .num_tlb_lines = 16, | 959 | .num_tlb_lines = 16, |
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c new file mode 100644 index 000000000000..62a86c4bcd0b --- /dev/null +++ b/drivers/memory/ti-emif-pm.c | |||
@@ -0,0 +1,324 @@ | |||
1 | /* | ||
2 | * TI AM33XX SRAM EMIF Driver | ||
3 | * | ||
4 | * Copyright (C) 2016-2017 Texas Instruments Inc. | ||
5 | * Dave Gerlach | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/err.h> | ||
18 | #include <linux/genalloc.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_platform.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/sram.h> | ||
26 | #include <linux/ti-emif-sram.h> | ||
27 | |||
28 | #include "emif.h" | ||
29 | |||
30 | #define TI_EMIF_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \ | ||
31 | (unsigned long)&ti_emif_sram) | ||
32 | |||
33 | #define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 | ||
34 | |||
35 | struct ti_emif_data { | ||
36 | phys_addr_t ti_emif_sram_phys; | ||
37 | phys_addr_t ti_emif_sram_data_phys; | ||
38 | unsigned long ti_emif_sram_virt; | ||
39 | unsigned long ti_emif_sram_data_virt; | ||
40 | struct gen_pool *sram_pool_code; | ||
41 | struct gen_pool *sram_pool_data; | ||
42 | struct ti_emif_pm_data pm_data; | ||
43 | struct ti_emif_pm_functions pm_functions; | ||
44 | }; | ||
45 | |||
46 | static struct ti_emif_data *emif_instance; | ||
47 | |||
48 | static u32 sram_suspend_address(struct ti_emif_data *emif_data, | ||
49 | unsigned long addr) | ||
50 | { | ||
51 | return (emif_data->ti_emif_sram_virt + | ||
52 | TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); | ||
53 | } | ||
54 | |||
55 | static phys_addr_t sram_resume_address(struct ti_emif_data *emif_data, | ||
56 | unsigned long addr) | ||
57 | { | ||
58 | return ((unsigned long)emif_data->ti_emif_sram_phys + | ||
59 | TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); | ||
60 | } | ||
61 | |||
62 | static void ti_emif_free_sram(struct ti_emif_data *emif_data) | ||
63 | { | ||
64 | gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, | ||
65 | ti_emif_sram_sz); | ||
66 | gen_pool_free(emif_data->sram_pool_data, | ||
67 | emif_data->ti_emif_sram_data_virt, | ||
68 | sizeof(struct emif_regs_amx3)); | ||
69 | } | ||
70 | |||
71 | static int ti_emif_alloc_sram(struct device *dev, | ||
72 | struct ti_emif_data *emif_data) | ||
73 | { | ||
74 | struct device_node *np = dev->of_node; | ||
75 | int ret; | ||
76 | |||
77 | emif_data->sram_pool_code = of_gen_pool_get(np, "sram", 0); | ||
78 | if (!emif_data->sram_pool_code) { | ||
79 | dev_err(dev, "Unable to get sram pool for ocmcram code\n"); | ||
80 | return -ENODEV; | ||
81 | } | ||
82 | |||
83 | emif_data->ti_emif_sram_virt = | ||
84 | gen_pool_alloc(emif_data->sram_pool_code, | ||
85 | ti_emif_sram_sz); | ||
86 | if (!emif_data->ti_emif_sram_virt) { | ||
87 | dev_err(dev, "Unable to allocate code memory from ocmcram\n"); | ||
88 | return -ENOMEM; | ||
89 | } | ||
90 | |||
91 | /* Save physical address to calculate resume offset during pm init */ | ||
92 | emif_data->ti_emif_sram_phys = | ||
93 | gen_pool_virt_to_phys(emif_data->sram_pool_code, | ||
94 | emif_data->ti_emif_sram_virt); | ||
95 | |||
96 | /* Get sram pool for data section and allocate space */ | ||
97 | emif_data->sram_pool_data = of_gen_pool_get(np, "sram", 1); | ||
98 | if (!emif_data->sram_pool_data) { | ||
99 | dev_err(dev, "Unable to get sram pool for ocmcram data\n"); | ||
100 | ret = -ENODEV; | ||
101 | goto err_free_sram_code; | ||
102 | } | ||
103 | |||
104 | emif_data->ti_emif_sram_data_virt = | ||
105 | gen_pool_alloc(emif_data->sram_pool_data, | ||
106 | sizeof(struct emif_regs_amx3)); | ||
107 | if (!emif_data->ti_emif_sram_data_virt) { | ||
108 | dev_err(dev, "Unable to allocate data memory from ocmcram\n"); | ||
109 | ret = -ENOMEM; | ||
110 | goto err_free_sram_code; | ||
111 | } | ||
112 | |||
113 | /* Save physical address to calculate resume offset during pm init */ | ||
114 | emif_data->ti_emif_sram_data_phys = | ||
115 | gen_pool_virt_to_phys(emif_data->sram_pool_data, | ||
116 | emif_data->ti_emif_sram_data_virt); | ||
117 | /* | ||
118 | * These functions are called during suspend path while MMU is | ||
119 | * still on so add virtual base to offset for absolute address | ||
120 | */ | ||
121 | emif_data->pm_functions.save_context = | ||
122 | sram_suspend_address(emif_data, | ||
123 | (unsigned long)ti_emif_save_context); | ||
124 | emif_data->pm_functions.enter_sr = | ||
125 | sram_suspend_address(emif_data, | ||
126 | (unsigned long)ti_emif_enter_sr); | ||
127 | emif_data->pm_functions.abort_sr = | ||
128 | sram_suspend_address(emif_data, | ||
129 | (unsigned long)ti_emif_abort_sr); | ||
130 | |||
131 | /* | ||
132 | * These are called during resume path when MMU is not enabled | ||
133 | * so physical address is used instead | ||
134 | */ | ||
135 | emif_data->pm_functions.restore_context = | ||
136 | sram_resume_address(emif_data, | ||
137 | (unsigned long)ti_emif_restore_context); | ||
138 | emif_data->pm_functions.exit_sr = | ||
139 | sram_resume_address(emif_data, | ||
140 | (unsigned long)ti_emif_exit_sr); | ||
141 | |||
142 | emif_data->pm_data.regs_virt = | ||
143 | (struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt; | ||
144 | emif_data->pm_data.regs_phys = emif_data->ti_emif_sram_data_phys; | ||
145 | |||
146 | return 0; | ||
147 | |||
148 | err_free_sram_code: | ||
149 | gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, | ||
150 | ti_emif_sram_sz); | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int ti_emif_push_sram(struct device *dev, struct ti_emif_data *emif_data) | ||
155 | { | ||
156 | void *copy_addr; | ||
157 | u32 data_addr; | ||
158 | |||
159 | copy_addr = sram_exec_copy(emif_data->sram_pool_code, | ||
160 | (void *)emif_data->ti_emif_sram_virt, | ||
161 | &ti_emif_sram, ti_emif_sram_sz); | ||
162 | if (!copy_addr) { | ||
163 | dev_err(dev, "Cannot copy emif code to sram\n"); | ||
164 | return -ENODEV; | ||
165 | } | ||
166 | |||
167 | data_addr = sram_suspend_address(emif_data, | ||
168 | (unsigned long)&ti_emif_pm_sram_data); | ||
169 | copy_addr = sram_exec_copy(emif_data->sram_pool_code, | ||
170 | (void *)data_addr, | ||
171 | &emif_data->pm_data, | ||
172 | sizeof(emif_data->pm_data)); | ||
173 | if (!copy_addr) { | ||
174 | dev_err(dev, "Cannot copy emif data to code sram\n"); | ||
175 | return -ENODEV; | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Due to Usage Note 3.1.2 "DDR3: JEDEC Compliance for Maximum | ||
183 | * Self-Refresh Command Limit" found in AM335x Silicon Errata | ||
184 | * (Document SPRZ360F Revised November 2013) we must configure | ||
185 | * the self refresh delay timer to 0xA (8192 cycles) to avoid | ||
186 | * generating too many refresh command from the EMIF. | ||
187 | */ | ||
188 | static void ti_emif_configure_sr_delay(struct ti_emif_data *emif_data) | ||
189 | { | ||
190 | writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, | ||
191 | (emif_data->pm_data.ti_emif_base_addr_virt + | ||
192 | EMIF_POWER_MANAGEMENT_CONTROL)); | ||
193 | |||
194 | writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, | ||
195 | (emif_data->pm_data.ti_emif_base_addr_virt + | ||
196 | EMIF_POWER_MANAGEMENT_CTRL_SHDW)); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * ti_emif_copy_pm_function_table - copy mapping of pm funcs in sram | ||
201 | * @sram_pool: pointer to struct gen_pool where dst resides | ||
202 | * @dst: void * to address that table should be copied | ||
203 | * | ||
204 | * Returns 0 if success other error code if table is not available | ||
205 | */ | ||
206 | int ti_emif_copy_pm_function_table(struct gen_pool *sram_pool, void *dst) | ||
207 | { | ||
208 | void *copy_addr; | ||
209 | |||
210 | if (!emif_instance) | ||
211 | return -ENODEV; | ||
212 | |||
213 | copy_addr = sram_exec_copy(sram_pool, dst, | ||
214 | &emif_instance->pm_functions, | ||
215 | sizeof(emif_instance->pm_functions)); | ||
216 | if (!copy_addr) | ||
217 | return -ENODEV; | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | EXPORT_SYMBOL_GPL(ti_emif_copy_pm_function_table); | ||
222 | |||
223 | /** | ||
224 | * ti_emif_get_mem_type - return type for memory type in use | ||
225 | * | ||
226 | * Returns memory type value read from EMIF or error code if fails | ||
227 | */ | ||
228 | int ti_emif_get_mem_type(void) | ||
229 | { | ||
230 | unsigned long temp; | ||
231 | |||
232 | if (!emif_instance) | ||
233 | return -ENODEV; | ||
234 | |||
235 | temp = readl(emif_instance->pm_data.ti_emif_base_addr_virt + | ||
236 | EMIF_SDRAM_CONFIG); | ||
237 | |||
238 | temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT; | ||
239 | return temp; | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(ti_emif_get_mem_type); | ||
242 | |||
243 | static const struct of_device_id ti_emif_of_match[] = { | ||
244 | { .compatible = "ti,emif-am3352", .data = | ||
245 | (void *)EMIF_SRAM_AM33_REG_LAYOUT, }, | ||
246 | { .compatible = "ti,emif-am4372", .data = | ||
247 | (void *)EMIF_SRAM_AM43_REG_LAYOUT, }, | ||
248 | {}, | ||
249 | }; | ||
250 | MODULE_DEVICE_TABLE(of, ti_emif_of_match); | ||
251 | |||
252 | static int ti_emif_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | int ret; | ||
255 | struct resource *res; | ||
256 | struct device *dev = &pdev->dev; | ||
257 | const struct of_device_id *match; | ||
258 | struct ti_emif_data *emif_data; | ||
259 | |||
260 | emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL); | ||
261 | if (!emif_data) | ||
262 | return -ENOMEM; | ||
263 | |||
264 | match = of_match_device(ti_emif_of_match, &pdev->dev); | ||
265 | if (!match) | ||
266 | return -ENODEV; | ||
267 | |||
268 | emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data; | ||
269 | |||
270 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
271 | emif_data->pm_data.ti_emif_base_addr_virt = devm_ioremap_resource(dev, | ||
272 | res); | ||
273 | if (IS_ERR(emif_data->pm_data.ti_emif_base_addr_virt)) { | ||
274 | dev_err(dev, "could not ioremap emif mem\n"); | ||
275 | ret = PTR_ERR(emif_data->pm_data.ti_emif_base_addr_virt); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | emif_data->pm_data.ti_emif_base_addr_phys = res->start; | ||
280 | |||
281 | ti_emif_configure_sr_delay(emif_data); | ||
282 | |||
283 | ret = ti_emif_alloc_sram(dev, emif_data); | ||
284 | if (ret) | ||
285 | return ret; | ||
286 | |||
287 | ret = ti_emif_push_sram(dev, emif_data); | ||
288 | if (ret) | ||
289 | goto fail_free_sram; | ||
290 | |||
291 | emif_instance = emif_data; | ||
292 | |||
293 | return 0; | ||
294 | |||
295 | fail_free_sram: | ||
296 | ti_emif_free_sram(emif_data); | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int ti_emif_remove(struct platform_device *pdev) | ||
302 | { | ||
303 | struct ti_emif_data *emif_data = emif_instance; | ||
304 | |||
305 | emif_instance = NULL; | ||
306 | |||
307 | ti_emif_free_sram(emif_data); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static struct platform_driver ti_emif_driver = { | ||
313 | .probe = ti_emif_probe, | ||
314 | .remove = ti_emif_remove, | ||
315 | .driver = { | ||
316 | .name = KBUILD_MODNAME, | ||
317 | .of_match_table = of_match_ptr(ti_emif_of_match), | ||
318 | }, | ||
319 | }; | ||
320 | module_platform_driver(ti_emif_driver); | ||
321 | |||
322 | MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>"); | ||
323 | MODULE_DESCRIPTION("Texas Instruments SRAM EMIF driver"); | ||
324 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/memory/ti-emif-sram-pm.S b/drivers/memory/ti-emif-sram-pm.S new file mode 100644 index 000000000000..a5369181e5c2 --- /dev/null +++ b/drivers/memory/ti-emif-sram-pm.S | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * Low level PM code for TI EMIF | ||
3 | * | ||
4 | * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * Dave Gerlach | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation version 2. | ||
10 | * | ||
11 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
12 | * kind, whether express or implied; without even the implied warranty | ||
13 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <generated/ti-emif-asm-offsets.h> | ||
18 | #include <linux/linkage.h> | ||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/memory.h> | ||
21 | |||
22 | #include "emif.h" | ||
23 | |||
24 | #define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 | ||
25 | #define EMIF_POWER_MGMT_SR_TIMER_MASK 0x00f0 | ||
26 | #define EMIF_POWER_MGMT_SELF_REFRESH_MODE 0x0200 | ||
27 | #define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 0x0700 | ||
28 | |||
29 | #define EMIF_SDCFG_TYPE_DDR2 0x2 << SDRAM_TYPE_SHIFT | ||
30 | #define EMIF_STATUS_READY 0x4 | ||
31 | |||
32 | #define AM43XX_EMIF_PHY_CTRL_REG_COUNT 0x120 | ||
33 | |||
34 | #define EMIF_AM437X_REGISTERS 0x1 | ||
35 | |||
36 | .arm | ||
37 | .align 3 | ||
38 | |||
39 | ENTRY(ti_emif_sram) | ||
40 | |||
41 | /* | ||
42 | * void ti_emif_save_context(void) | ||
43 | * | ||
44 | * Used during suspend to save the context of all required EMIF registers | ||
45 | * to local memory if the EMIF is going to lose context during the sleep | ||
46 | * transition. Operates on the VIRTUAL address of the EMIF. | ||
47 | */ | ||
48 | ENTRY(ti_emif_save_context) | ||
49 | stmfd sp!, {r4 - r11, lr} @ save registers on stack | ||
50 | |||
51 | adr r4, ti_emif_pm_sram_data | ||
52 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] | ||
53 | ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] | ||
54 | |||
55 | /* Save EMIF configuration */ | ||
56 | ldr r1, [r0, #EMIF_SDRAM_CONFIG] | ||
57 | str r1, [r2, #EMIF_SDCFG_VAL_OFFSET] | ||
58 | |||
59 | ldr r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] | ||
60 | str r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET] | ||
61 | |||
62 | ldr r1, [r0, #EMIF_SDRAM_TIMING_1] | ||
63 | str r1, [r2, #EMIF_TIMING1_VAL_OFFSET] | ||
64 | |||
65 | ldr r1, [r0, #EMIF_SDRAM_TIMING_2] | ||
66 | str r1, [r2, #EMIF_TIMING2_VAL_OFFSET] | ||
67 | |||
68 | ldr r1, [r0, #EMIF_SDRAM_TIMING_3] | ||
69 | str r1, [r2, #EMIF_TIMING3_VAL_OFFSET] | ||
70 | |||
71 | ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
72 | str r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
73 | |||
74 | ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] | ||
75 | str r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET] | ||
76 | |||
77 | ldr r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] | ||
78 | str r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] | ||
79 | |||
80 | ldr r1, [r0, #EMIF_DDR_PHY_CTRL_1] | ||
81 | str r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET] | ||
82 | |||
83 | ldr r1, [r0, #EMIF_COS_CONFIG] | ||
84 | str r1, [r2, #EMIF_COS_CONFIG_OFFSET] | ||
85 | |||
86 | ldr r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING] | ||
87 | str r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET] | ||
88 | |||
89 | ldr r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING] | ||
90 | str r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET] | ||
91 | |||
92 | ldr r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING] | ||
93 | str r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET] | ||
94 | |||
95 | ldr r1, [r0, #EMIF_OCP_CONFIG] | ||
96 | str r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET] | ||
97 | |||
98 | ldr r5, [r4, #EMIF_PM_CONFIG_OFFSET] | ||
99 | cmp r5, #EMIF_SRAM_AM43_REG_LAYOUT | ||
100 | bne emif_skip_save_extra_regs | ||
101 | |||
102 | ldr r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL] | ||
103 | str r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET] | ||
104 | |||
105 | ldr r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD] | ||
106 | str r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET] | ||
107 | |||
108 | ldr r1, [r0, #EMIF_LPDDR2_NVM_TIMING] | ||
109 | str r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET] | ||
110 | |||
111 | ldr r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW] | ||
112 | str r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET] | ||
113 | |||
114 | ldr r1, [r0, #EMIF_DLL_CALIB_CTRL] | ||
115 | str r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET] | ||
116 | |||
117 | ldr r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW] | ||
118 | str r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET] | ||
119 | |||
120 | /* Loop and save entire block of emif phy regs */ | ||
121 | mov r5, #0x0 | ||
122 | add r4, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET | ||
123 | add r3, r0, #EMIF_EXT_PHY_CTRL_1 | ||
124 | ddr_phy_ctrl_save: | ||
125 | ldr r1, [r3, r5] | ||
126 | str r1, [r4, r5] | ||
127 | add r5, r5, #0x4 | ||
128 | cmp r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT | ||
129 | bne ddr_phy_ctrl_save | ||
130 | |||
131 | emif_skip_save_extra_regs: | ||
132 | ldmfd sp!, {r4 - r11, pc} @ restore regs and return | ||
133 | ENDPROC(ti_emif_save_context) | ||
134 | |||
135 | /* | ||
136 | * void ti_emif_restore_context(void) | ||
137 | * | ||
138 | * Used during resume to restore the context of all required EMIF registers | ||
139 | * from local memory after the EMIF has lost context during a sleep transition. | ||
140 | * Operates on the PHYSICAL address of the EMIF. | ||
141 | */ | ||
142 | ENTRY(ti_emif_restore_context) | ||
143 | adr r4, ti_emif_pm_sram_data | ||
144 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET] | ||
145 | ldr r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET] | ||
146 | |||
147 | /* Config EMIF Timings */ | ||
148 | ldr r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET] | ||
149 | str r1, [r0, #EMIF_DDR_PHY_CTRL_1] | ||
150 | str r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW] | ||
151 | |||
152 | ldr r1, [r2, #EMIF_TIMING1_VAL_OFFSET] | ||
153 | str r1, [r0, #EMIF_SDRAM_TIMING_1] | ||
154 | str r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW] | ||
155 | |||
156 | ldr r1, [r2, #EMIF_TIMING2_VAL_OFFSET] | ||
157 | str r1, [r0, #EMIF_SDRAM_TIMING_2] | ||
158 | str r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW] | ||
159 | |||
160 | ldr r1, [r2, #EMIF_TIMING3_VAL_OFFSET] | ||
161 | str r1, [r0, #EMIF_SDRAM_TIMING_3] | ||
162 | str r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW] | ||
163 | |||
164 | ldr r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET] | ||
165 | str r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] | ||
166 | str r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW] | ||
167 | |||
168 | ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
169 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
170 | |||
171 | ldr r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET] | ||
172 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] | ||
173 | |||
174 | ldr r1, [r2, #EMIF_COS_CONFIG_OFFSET] | ||
175 | str r1, [r0, #EMIF_COS_CONFIG] | ||
176 | |||
177 | ldr r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET] | ||
178 | str r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING] | ||
179 | |||
180 | ldr r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET] | ||
181 | str r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING] | ||
182 | |||
183 | ldr r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET] | ||
184 | str r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING] | ||
185 | |||
186 | ldr r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET] | ||
187 | str r1, [r0, #EMIF_OCP_CONFIG] | ||
188 | |||
189 | ldr r5, [r4, #EMIF_PM_CONFIG_OFFSET] | ||
190 | cmp r5, #EMIF_SRAM_AM43_REG_LAYOUT | ||
191 | bne emif_skip_restore_extra_regs | ||
192 | |||
193 | ldr r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET] | ||
194 | str r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL] | ||
195 | |||
196 | ldr r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET] | ||
197 | str r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD] | ||
198 | |||
199 | ldr r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET] | ||
200 | str r1, [r0, #EMIF_LPDDR2_NVM_TIMING] | ||
201 | |||
202 | ldr r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET] | ||
203 | str r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW] | ||
204 | |||
205 | ldr r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET] | ||
206 | str r1, [r0, #EMIF_DLL_CALIB_CTRL] | ||
207 | |||
208 | ldr r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET] | ||
209 | str r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW] | ||
210 | |||
211 | ldr r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] | ||
212 | str r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] | ||
213 | |||
214 | /* Loop and restore entire block of emif phy regs */ | ||
215 | mov r5, #0x0 | ||
216 | /* Load ti_emif_regs_amx3 + EMIF_EXT_PHY_CTRL_VALS_OFFSET for address | ||
217 | * to phy register save space | ||
218 | */ | ||
219 | add r3, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET | ||
220 | add r4, r0, #EMIF_EXT_PHY_CTRL_1 | ||
221 | ddr_phy_ctrl_restore: | ||
222 | ldr r1, [r3, r5] | ||
223 | str r1, [r4, r5] | ||
224 | add r5, r5, #0x4 | ||
225 | cmp r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT | ||
226 | bne ddr_phy_ctrl_restore | ||
227 | |||
228 | emif_skip_restore_extra_regs: | ||
229 | /* | ||
230 | * Output impedence calib needed only for DDR3 | ||
231 | * but since the initial state of this will be | ||
232 | * disabled for DDR2 no harm in restoring the | ||
233 | * old configuration | ||
234 | */ | ||
235 | ldr r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] | ||
236 | str r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] | ||
237 | |||
238 | /* Write to sdcfg last for DDR2 only */ | ||
239 | ldr r1, [r2, #EMIF_SDCFG_VAL_OFFSET] | ||
240 | and r2, r1, #SDRAM_TYPE_MASK | ||
241 | cmp r2, #EMIF_SDCFG_TYPE_DDR2 | ||
242 | streq r1, [r0, #EMIF_SDRAM_CONFIG] | ||
243 | |||
244 | mov pc, lr | ||
245 | ENDPROC(ti_emif_restore_context) | ||
246 | |||
247 | /* | ||
248 | * void ti_emif_enter_sr(void) | ||
249 | * | ||
250 | * Programs the EMIF to tell the SDRAM to enter into self-refresh | ||
251 | * mode during a sleep transition. Operates on the VIRTUAL address | ||
252 | * of the EMIF. | ||
253 | */ | ||
254 | ENTRY(ti_emif_enter_sr) | ||
255 | stmfd sp!, {r4 - r11, lr} @ save registers on stack | ||
256 | |||
257 | adr r4, ti_emif_pm_sram_data | ||
258 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] | ||
259 | ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] | ||
260 | |||
261 | ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
262 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
263 | orr r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE | ||
264 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
265 | |||
266 | ldmfd sp!, {r4 - r11, pc} @ restore regs and return | ||
267 | ENDPROC(ti_emif_enter_sr) | ||
268 | |||
269 | /* | ||
270 | * void ti_emif_exit_sr(void) | ||
271 | * | ||
272 | * Programs the EMIF to tell the SDRAM to exit self-refresh mode | ||
273 | * after a sleep transition. Operates on the PHYSICAL address of | ||
274 | * the EMIF. | ||
275 | */ | ||
276 | ENTRY(ti_emif_exit_sr) | ||
277 | adr r4, ti_emif_pm_sram_data | ||
278 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET] | ||
279 | ldr r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET] | ||
280 | |||
281 | /* | ||
282 | * Toggle EMIF to exit refresh mode: | ||
283 | * if EMIF lost context, PWR_MGT_CTRL is currently 0, writing disable | ||
284 | * (0x0), wont do diddly squat! so do a toggle from SR(0x2) to disable | ||
285 | * (0x0) here. | ||
286 | * *If* EMIF did not lose context, nothing broken as we write the same | ||
287 | * value(0x2) to reg before we write a disable (0x0). | ||
288 | */ | ||
289 | ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
290 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
291 | orr r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE | ||
292 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
293 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
294 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
295 | |||
296 | /* Wait for EMIF to become ready */ | ||
297 | 1: ldr r1, [r0, #EMIF_STATUS] | ||
298 | tst r1, #EMIF_STATUS_READY | ||
299 | beq 1b | ||
300 | |||
301 | mov pc, lr | ||
302 | ENDPROC(ti_emif_exit_sr) | ||
303 | |||
304 | /* | ||
305 | * void ti_emif_abort_sr(void) | ||
306 | * | ||
307 | * Disables self-refresh after a failed transition to a low-power | ||
308 | * state so the kernel can jump back to DDR and follow abort path. | ||
309 | * Operates on the VIRTUAL address of the EMIF. | ||
310 | */ | ||
311 | ENTRY(ti_emif_abort_sr) | ||
312 | stmfd sp!, {r4 - r11, lr} @ save registers on stack | ||
313 | |||
314 | adr r4, ti_emif_pm_sram_data | ||
315 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] | ||
316 | ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] | ||
317 | |||
318 | ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
319 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
320 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
321 | |||
322 | /* Wait for EMIF to become ready */ | ||
323 | 1: ldr r1, [r0, #EMIF_STATUS] | ||
324 | tst r1, #EMIF_STATUS_READY | ||
325 | beq 1b | ||
326 | |||
327 | ldmfd sp!, {r4 - r11, pc} @ restore regs and return | ||
328 | ENDPROC(ti_emif_abort_sr) | ||
329 | |||
330 | .align 3 | ||
331 | ENTRY(ti_emif_pm_sram_data) | ||
332 | .space EMIF_PM_DATA_SIZE | ||
333 | ENTRY(ti_emif_sram_sz) | ||
334 | .word . - ti_emif_save_context | ||