forked from AsahiLinux/m1n1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
isp.c
173 lines (148 loc) · 4.62 KB
/
isp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* SPDX-License-Identifier: MIT */
#include "adt.h"
#include "dart.h"
#include "firmware.h"
#include "isp.h"
#include "pmgr.h"
#include "soc.h"
#include "utils.h"
#define ISP_ASC_VERSION 0x1800000
#define ISP_VER_T8103 0xb0090
#define ISP_VER_T6000 0xb3091
#define ISP_VER_T8112 0xc1090
#define ISP_VER_T6020 0xc3091
// PMGR offset to enable to get the version info to work
#define ISP_PMGR_T8103 0x4018
#define ISP_PMGR_T6000 0x8
#define ISP_PMGR_T6020 0x4008
static bool isp_initialized = false;
static u64 heap_phys, heap_iova, heap_size, heap_top;
int isp_get_heap(u64 *phys, u64 *iova, u64 *size)
{
if (!isp_initialized)
return -1;
*phys = heap_phys;
*iova = heap_iova | isp_iova_base();
*size = heap_size;
return 0;
}
u64 isp_iova_base(void)
{
switch (chip_id) {
case 0x6020 ... 0x6fff:
return 0x10000000000;
default:
return 0;
}
}
int isp_init(void)
{
int err = 0;
const char *isp_path = "/arm-io/isp";
const char *dart_path = "/arm-io/dart-isp";
int adt_path[8], adt_isp_path[8];
int isp_node = adt_path_offset_trace(adt, isp_path, adt_isp_path);
int node = adt_path_offset_trace(adt, dart_path, adt_path);
if (node < 0 || isp_node < 0) {
isp_path = "/arm-io/isp0";
dart_path = "/arm-io/dart-isp0";
isp_node = adt_path_offset_trace(adt, isp_path, adt_isp_path);
node = adt_path_offset_trace(adt, dart_path, adt_path);
}
if (node < 0)
return 0;
if (pmgr_adt_power_enable(isp_path) < 0)
return -1;
u64 isp_base;
u64 pmgr_base;
err = adt_get_reg(adt, adt_isp_path, "reg", 0, &isp_base, NULL);
if (err)
return err;
err = adt_get_reg(adt, adt_isp_path, "reg", 1, &pmgr_base, NULL);
if (err)
return err;
u32 pmgr_off;
switch (chip_id) {
case T8103:
case T8112:
pmgr_off = ISP_PMGR_T8103;
break;
case T6000 ... T6002:
pmgr_off = ISP_PMGR_T6000;
break;
case T6020 ... T6022:
pmgr_off = ISP_PMGR_T6020;
break;
default:
printf("isp: Unsupported SoC\n");
return -1;
}
err = pmgr_set_mode(pmgr_base + pmgr_off, PMGR_PS_ACTIVE);
if (err) {
printf("isp: Failed to power on\n");
return err;
}
u32 ver_rev = read32(isp_base + ISP_ASC_VERSION);
printf("isp: Version 0x%x\n", ver_rev);
pmgr_set_mode(pmgr_base + pmgr_off, PMGR_PS_PWRGATE);
/* TODO: confirm versions */
switch (ver_rev) {
case ISP_VER_T8103:
case ISP_VER_T8112:
switch (os_firmware.version) {
case V12_3 ... V12_4:
heap_top = 0x1800000;
break;
case V13_5:
heap_top = 0x1000000;
break;
default:
printf("isp: unsupported firmware\n");
return -1;
}
break;
case ISP_VER_T6000:
switch (os_firmware.version) {
case V12_3:
heap_top = 0xe00000;
break;
case V13_5:
case V13_6_2:
heap_top = 0xf00000;
break;
default:
printf("isp: unsupported firmware\n");
return -1;
}
break;
case ISP_VER_T6020:
switch (os_firmware.version) {
case V13_5:
case V13_6_2:
heap_top = 0xf00000;
break;
default:
printf("isp: unsupported firmware\n");
return -1;
}
break;
default:
printf("isp: unknown revision 0x%x\n", ver_rev);
return -1;
}
const struct adt_segment_ranges *seg;
u32 segments_len;
seg = adt_getprop(adt, isp_node, "segment-ranges", &segments_len);
unsigned int count = segments_len / sizeof(*seg);
heap_iova = seg[count - 1].iova + seg[count - 1].size;
heap_size = heap_top - heap_iova;
heap_phys = top_of_memory_alloc(heap_size);
printf("isp: Code: 0x%lx..0x%lx (0x%x @ 0x%lx)\n", seg[0].iova, seg[0].iova + seg[0].size,
seg[0].size, seg[0].phys);
printf("isp: Data: 0x%lx..0x%lx (0x%x @ 0x%lx)\n", seg[1].iova, seg[1].iova + seg[1].size,
seg[1].size, seg[1].phys);
printf("isp: Heap: 0x%lx..0x%lx (0x%lx @ 0x%lx)\n", heap_iova, heap_top, heap_size, heap_phys);
isp_initialized = true;
pmgr_adt_power_disable(isp_path);
return err;
}