1983e3700STom Rini /*
2983e3700STom Rini * Copyright 2016 Texas Instruments, Inc.
3983e3700STom Rini *
4983e3700STom Rini * SPDX-License-Identifier: GPL-2.0+
5983e3700STom Rini */
6983e3700STom Rini
7983e3700STom Rini #include <common.h>
8*0e00a84cSMasahiro Yamada #include <linux/libfdt.h>
9983e3700STom Rini #include <fdt_support.h>
10983e3700STom Rini #include <malloc.h>
11983e3700STom Rini
12983e3700STom Rini #include <asm/omap_common.h>
13983e3700STom Rini #include <asm/arch-omap5/sys_proto.h>
14983e3700STom Rini
15983e3700STom Rini #ifdef CONFIG_TI_SECURE_DEVICE
16983e3700STom Rini
17983e3700STom Rini /* Give zero values if not already defined */
18983e3700STom Rini #ifndef TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ
19983e3700STom Rini #define TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ (0)
20983e3700STom Rini #endif
21983e3700STom Rini #ifndef CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ
22983e3700STom Rini #define CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ (0)
23983e3700STom Rini #endif
24983e3700STom Rini
25983e3700STom Rini static u32 hs_irq_skip[] = {
26983e3700STom Rini 8, /* Secure violation reporting interrupt */
27983e3700STom Rini 15, /* One interrupt for SDMA by secure world */
28983e3700STom Rini 118 /* One interrupt for Crypto DMA by secure world */
29983e3700STom Rini };
30983e3700STom Rini
ft_hs_fixup_crossbar(void * fdt,bd_t * bd)31983e3700STom Rini static int ft_hs_fixup_crossbar(void *fdt, bd_t *bd)
32983e3700STom Rini {
33983e3700STom Rini const char *path;
34983e3700STom Rini int offs;
35983e3700STom Rini int ret;
36983e3700STom Rini int len, i, old_cnt, new_cnt;
37983e3700STom Rini u32 *temp;
38983e3700STom Rini const u32 *p_data;
39983e3700STom Rini
40983e3700STom Rini /*
41983e3700STom Rini * Increase the size of the fdt
42983e3700STom Rini * so we have some breathing room
43983e3700STom Rini */
44983e3700STom Rini ret = fdt_increase_size(fdt, 512);
45983e3700STom Rini if (ret < 0) {
46983e3700STom Rini printf("Could not increase size of device tree: %s\n",
47983e3700STom Rini fdt_strerror(ret));
48983e3700STom Rini return ret;
49983e3700STom Rini }
50983e3700STom Rini
51983e3700STom Rini /* Reserve IRQs that are used/needed by secure world */
52983e3700STom Rini path = "/ocp/crossbar";
53983e3700STom Rini offs = fdt_path_offset(fdt, path);
54983e3700STom Rini if (offs < 0) {
55983e3700STom Rini debug("Node %s not found.\n", path);
56983e3700STom Rini return 0;
57983e3700STom Rini }
58983e3700STom Rini
59983e3700STom Rini /* Get current entries */
60983e3700STom Rini p_data = fdt_getprop(fdt, offs, "ti,irqs-skip", &len);
61983e3700STom Rini if (p_data)
62983e3700STom Rini old_cnt = len / sizeof(u32);
63983e3700STom Rini else
64983e3700STom Rini old_cnt = 0;
65983e3700STom Rini
66983e3700STom Rini new_cnt = sizeof(hs_irq_skip) /
67983e3700STom Rini sizeof(hs_irq_skip[0]);
68983e3700STom Rini
69983e3700STom Rini /* Create new/updated skip list for HS parts */
70983e3700STom Rini temp = malloc(sizeof(u32) * (old_cnt + new_cnt));
71983e3700STom Rini for (i = 0; i < new_cnt; i++)
72983e3700STom Rini temp[i] = cpu_to_fdt32(hs_irq_skip[i]);
73983e3700STom Rini for (i = 0; i < old_cnt; i++)
74983e3700STom Rini temp[i + new_cnt] = p_data[i];
75983e3700STom Rini
76983e3700STom Rini /* Blow away old data and set new data */
77983e3700STom Rini fdt_delprop(fdt, offs, "ti,irqs-skip");
78983e3700STom Rini ret = fdt_setprop(fdt, offs, "ti,irqs-skip",
79983e3700STom Rini temp,
80983e3700STom Rini (old_cnt + new_cnt) * sizeof(u32));
81983e3700STom Rini free(temp);
82983e3700STom Rini
83983e3700STom Rini /* Check if the update worked */
84983e3700STom Rini if (ret < 0) {
85983e3700STom Rini printf("Could not add ti,irqs-skip property to node %s: %s\n",
86983e3700STom Rini path, fdt_strerror(ret));
87983e3700STom Rini return ret;
88983e3700STom Rini }
89983e3700STom Rini
90983e3700STom Rini return 0;
91983e3700STom Rini }
92983e3700STom Rini
93983e3700STom Rini #if ((TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ != 0) || \
94983e3700STom Rini (CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ != 0))
ft_hs_fixup_sram(void * fdt,bd_t * bd)95983e3700STom Rini static int ft_hs_fixup_sram(void *fdt, bd_t *bd)
96983e3700STom Rini {
97983e3700STom Rini const char *path;
98983e3700STom Rini int offs;
99983e3700STom Rini int ret;
100983e3700STom Rini u32 temp[2];
101983e3700STom Rini
102983e3700STom Rini /*
103983e3700STom Rini * Update SRAM reservations on secure devices. The OCMC RAM
104983e3700STom Rini * is always reserved for secure use from the start of that
105983e3700STom Rini * memory region
106983e3700STom Rini */
107983e3700STom Rini path = "/ocp/ocmcram@40300000/sram-hs";
108983e3700STom Rini offs = fdt_path_offset(fdt, path);
109983e3700STom Rini if (offs < 0) {
110983e3700STom Rini debug("Node %s not found.\n", path);
111983e3700STom Rini return 0;
112983e3700STom Rini }
113983e3700STom Rini
114983e3700STom Rini /* relative start offset */
115983e3700STom Rini temp[0] = cpu_to_fdt32(0);
116983e3700STom Rini /* reservation size */
117983e3700STom Rini temp[1] = cpu_to_fdt32(max(TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ,
118983e3700STom Rini CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ));
119983e3700STom Rini fdt_delprop(fdt, offs, "reg");
120983e3700STom Rini ret = fdt_setprop(fdt, offs, "reg", temp, 2 * sizeof(u32));
121983e3700STom Rini if (ret < 0) {
122983e3700STom Rini printf("Could not add reg property to node %s: %s\n",
123983e3700STom Rini path, fdt_strerror(ret));
124983e3700STom Rini return ret;
125983e3700STom Rini }
126983e3700STom Rini
127983e3700STom Rini return 0;
128983e3700STom Rini }
129983e3700STom Rini #else
ft_hs_fixup_sram(void * fdt,bd_t * bd)130983e3700STom Rini static int ft_hs_fixup_sram(void *fdt, bd_t *bd) { return 0; }
131983e3700STom Rini #endif
132983e3700STom Rini
ft_hs_fixups(void * fdt,bd_t * bd)133983e3700STom Rini static void ft_hs_fixups(void *fdt, bd_t *bd)
134983e3700STom Rini {
135983e3700STom Rini /* Check we are running on an HS/EMU device type */
136983e3700STom Rini if (GP_DEVICE != get_device_type()) {
137983e3700STom Rini if ((ft_hs_fixup_crossbar(fdt, bd) == 0) &&
138983e3700STom Rini (ft_hs_disable_rng(fdt, bd) == 0) &&
139983e3700STom Rini (ft_hs_fixup_sram(fdt, bd) == 0) &&
140a8ff9685SAndrew F. Davis (ft_hs_fixup_dram(fdt, bd) == 0) &&
141a8ff9685SAndrew F. Davis (ft_hs_add_tee(fdt, bd) == 0))
142983e3700STom Rini return;
143983e3700STom Rini } else {
144983e3700STom Rini printf("ERROR: Incorrect device type (GP) detected!");
145983e3700STom Rini }
146983e3700STom Rini /* Fixup failed or wrong device type */
147983e3700STom Rini hang();
148983e3700STom Rini }
149983e3700STom Rini #else
ft_hs_fixups(void * fdt,bd_t * bd)150983e3700STom Rini static void ft_hs_fixups(void *fdt, bd_t *bd)
151983e3700STom Rini {
152983e3700STom Rini }
153983e3700STom Rini #endif /* #ifdef CONFIG_TI_SECURE_DEVICE */
154983e3700STom Rini
1551b42ab3eSSuman Anna #if defined(CONFIG_TARGET_DRA7XX_EVM) || defined(CONFIG_TARGET_AM57XX_EVM)
1561b42ab3eSSuman Anna #define OPP_DSP_CLK_NUM 3
1571b42ab3eSSuman Anna #define OPP_IVA_CLK_NUM 2
1581b42ab3eSSuman Anna #define OPP_GPU_CLK_NUM 2
1591b42ab3eSSuman Anna
1601b42ab3eSSuman Anna const char *dra7_opp_dsp_clk_names[OPP_DSP_CLK_NUM] = {
1611b42ab3eSSuman Anna "dpll_dsp_ck",
1621b42ab3eSSuman Anna "dpll_dsp_m2_ck",
1631b42ab3eSSuman Anna "dpll_dsp_m3x2_ck",
1641b42ab3eSSuman Anna };
1651b42ab3eSSuman Anna
1661b42ab3eSSuman Anna const char *dra7_opp_iva_clk_names[OPP_IVA_CLK_NUM] = {
1671b42ab3eSSuman Anna "dpll_iva_ck",
1681b42ab3eSSuman Anna "dpll_iva_m2_ck",
1691b42ab3eSSuman Anna };
1701b42ab3eSSuman Anna
1711b42ab3eSSuman Anna const char *dra7_opp_gpu_clk_names[OPP_GPU_CLK_NUM] = {
1721b42ab3eSSuman Anna "dpll_gpu_ck",
1731b42ab3eSSuman Anna "dpll_gpu_m2_ck",
1741b42ab3eSSuman Anna };
1751b42ab3eSSuman Anna
1761b42ab3eSSuman Anna /* DSPEVE voltage domain */
1771b42ab3eSSuman Anna u32 dra7_opp_dsp_clk_rates[NUM_OPPS][OPP_DSP_CLK_NUM] = {
1781b42ab3eSSuman Anna {}, /*OPP_LOW */
1791b42ab3eSSuman Anna {600000000, 600000000, 400000000}, /* OPP_NOM */
1801b42ab3eSSuman Anna {700000000, 700000000, 466666667}, /* OPP_OD */
1811b42ab3eSSuman Anna {750000000, 750000000, 500000000}, /* OPP_HIGH */
1821b42ab3eSSuman Anna };
1831b42ab3eSSuman Anna
1841b42ab3eSSuman Anna /* IVA voltage domain */
1851b42ab3eSSuman Anna u32 dra7_opp_iva_clk_rates[NUM_OPPS][OPP_IVA_CLK_NUM] = {
1861b42ab3eSSuman Anna {}, /* OPP_LOW */
1871b42ab3eSSuman Anna {1165000000, 388333334}, /* OPP_NOM */
1881b42ab3eSSuman Anna {860000000, 430000000}, /* OPP_OD */
1891b42ab3eSSuman Anna {1064000000, 532000000}, /* OPP_HIGH */
1901b42ab3eSSuman Anna };
1911b42ab3eSSuman Anna
1921b42ab3eSSuman Anna /* GPU voltage domain */
1931b42ab3eSSuman Anna u32 dra7_opp_gpu_clk_rates[NUM_OPPS][OPP_GPU_CLK_NUM] = {
1941b42ab3eSSuman Anna {}, /* OPP_LOW */
1951b42ab3eSSuman Anna {1277000000, 425666667}, /* OPP_NOM */
1961b42ab3eSSuman Anna {1000000000, 500000000}, /* OPP_OD */
1971b42ab3eSSuman Anna {1064000000, 532000000}, /* OPP_HIGH */
1981b42ab3eSSuman Anna };
1991b42ab3eSSuman Anna
ft_fixup_clocks(void * fdt,const char ** names,u32 * rates,int num)2001b42ab3eSSuman Anna static int ft_fixup_clocks(void *fdt, const char **names, u32 *rates, int num)
2011b42ab3eSSuman Anna {
2021b42ab3eSSuman Anna int offs, node_offs, ret, i;
2031b42ab3eSSuman Anna uint32_t phandle;
2041b42ab3eSSuman Anna
2051b42ab3eSSuman Anna offs = fdt_path_offset(fdt, "/ocp/l4@4a000000/cm_core_aon@5000/clocks");
2061b42ab3eSSuman Anna if (offs < 0) {
2071b42ab3eSSuman Anna debug("Could not find cm_core_aon clocks node path offset : %s\n",
2081b42ab3eSSuman Anna fdt_strerror(offs));
2091b42ab3eSSuman Anna return offs;
2101b42ab3eSSuman Anna }
2111b42ab3eSSuman Anna
2121b42ab3eSSuman Anna for (i = 0; i < num; i++) {
2131b42ab3eSSuman Anna node_offs = fdt_subnode_offset(fdt, offs, names[i]);
2141b42ab3eSSuman Anna if (node_offs < 0) {
2151b42ab3eSSuman Anna debug("Could not find clock sub-node %s: %s\n",
2161b42ab3eSSuman Anna names[i], fdt_strerror(node_offs));
2171b42ab3eSSuman Anna return offs;
2181b42ab3eSSuman Anna }
2191b42ab3eSSuman Anna
2201b42ab3eSSuman Anna phandle = fdt_get_phandle(fdt, node_offs);
2211b42ab3eSSuman Anna if (!phandle) {
2221b42ab3eSSuman Anna debug("Could not find phandle for clock %s\n",
2231b42ab3eSSuman Anna names[i]);
2241b42ab3eSSuman Anna return -1;
2251b42ab3eSSuman Anna }
2261b42ab3eSSuman Anna
2271b42ab3eSSuman Anna ret = fdt_setprop_u32(fdt, node_offs, "assigned-clocks",
2281b42ab3eSSuman Anna phandle);
2291b42ab3eSSuman Anna if (ret < 0) {
2301b42ab3eSSuman Anna debug("Could not add assigned-clocks property to clock node %s: %s\n",
2311b42ab3eSSuman Anna names[i], fdt_strerror(ret));
2321b42ab3eSSuman Anna return ret;
2331b42ab3eSSuman Anna }
2341b42ab3eSSuman Anna
2351b42ab3eSSuman Anna ret = fdt_setprop_u32(fdt, node_offs, "assigned-clock-rates",
2361b42ab3eSSuman Anna rates[i]);
2371b42ab3eSSuman Anna if (ret < 0) {
2381b42ab3eSSuman Anna debug("Could not add assigned-clock-rates property to clock node %s: %s\n",
2391b42ab3eSSuman Anna names[i], fdt_strerror(ret));
2401b42ab3eSSuman Anna return ret;
2411b42ab3eSSuman Anna }
2421b42ab3eSSuman Anna }
2431b42ab3eSSuman Anna
2441b42ab3eSSuman Anna return 0;
2451b42ab3eSSuman Anna }
2461b42ab3eSSuman Anna
ft_opp_clock_fixups(void * fdt,bd_t * bd)2471b42ab3eSSuman Anna static void ft_opp_clock_fixups(void *fdt, bd_t *bd)
2481b42ab3eSSuman Anna {
2491b42ab3eSSuman Anna const char **clk_names;
2501b42ab3eSSuman Anna u32 *clk_rates;
2511b42ab3eSSuman Anna int ret;
2521b42ab3eSSuman Anna
2531b42ab3eSSuman Anna if (!is_dra72x() && !is_dra7xx())
2541b42ab3eSSuman Anna return;
2551b42ab3eSSuman Anna
2561b42ab3eSSuman Anna /* fixup DSP clocks */
2571b42ab3eSSuman Anna clk_names = dra7_opp_dsp_clk_names;
2581b42ab3eSSuman Anna clk_rates = dra7_opp_dsp_clk_rates[get_voltrail_opp(VOLT_EVE)];
2591b42ab3eSSuman Anna ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_DSP_CLK_NUM);
2601b42ab3eSSuman Anna if (ret) {
2611b42ab3eSSuman Anna printf("ft_fixup_clocks failed for DSP voltage domain: %s\n",
2621b42ab3eSSuman Anna fdt_strerror(ret));
2631b42ab3eSSuman Anna return;
2641b42ab3eSSuman Anna }
2651b42ab3eSSuman Anna
2661b42ab3eSSuman Anna /* fixup IVA clocks */
2671b42ab3eSSuman Anna clk_names = dra7_opp_iva_clk_names;
2681b42ab3eSSuman Anna clk_rates = dra7_opp_iva_clk_rates[get_voltrail_opp(VOLT_IVA)];
2691b42ab3eSSuman Anna ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_IVA_CLK_NUM);
2701b42ab3eSSuman Anna if (ret) {
2711b42ab3eSSuman Anna printf("ft_fixup_clocks failed for IVA voltage domain: %s\n",
2721b42ab3eSSuman Anna fdt_strerror(ret));
2731b42ab3eSSuman Anna return;
2741b42ab3eSSuman Anna }
2751b42ab3eSSuman Anna
2761b42ab3eSSuman Anna /* fixup GPU clocks */
2771b42ab3eSSuman Anna clk_names = dra7_opp_gpu_clk_names;
2781b42ab3eSSuman Anna clk_rates = dra7_opp_gpu_clk_rates[get_voltrail_opp(VOLT_GPU)];
2791b42ab3eSSuman Anna ret = ft_fixup_clocks(fdt, clk_names, clk_rates, OPP_GPU_CLK_NUM);
2801b42ab3eSSuman Anna if (ret) {
2811b42ab3eSSuman Anna printf("ft_fixup_clocks failed for GPU voltage domain: %s\n",
2821b42ab3eSSuman Anna fdt_strerror(ret));
2831b42ab3eSSuman Anna return;
2841b42ab3eSSuman Anna }
2851b42ab3eSSuman Anna }
2861b42ab3eSSuman Anna #else
ft_opp_clock_fixups(void * fdt,bd_t * bd)2871b42ab3eSSuman Anna static void ft_opp_clock_fixups(void *fdt, bd_t *bd) { }
2881b42ab3eSSuman Anna #endif /* CONFIG_TARGET_DRA7XX_EVM || CONFIG_TARGET_AM57XX_EVM */
2891b42ab3eSSuman Anna
290983e3700STom Rini /*
291983e3700STom Rini * Place for general cpu/SoC FDT fixups. Board specific
292983e3700STom Rini * fixups should remain in the board files which is where
293983e3700STom Rini * this function should be called from.
294983e3700STom Rini */
ft_cpu_setup(void * fdt,bd_t * bd)295983e3700STom Rini void ft_cpu_setup(void *fdt, bd_t *bd)
296983e3700STom Rini {
297983e3700STom Rini ft_hs_fixups(fdt, bd);
2981b42ab3eSSuman Anna ft_opp_clock_fixups(fdt, bd);
299983e3700STom Rini }
300