script_uboot.c 5.66 KB
Newer Older
Alejandro Mery's avatar
Alejandro Mery committed
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
/*
 * Copyright (C) 2012 Alejandro Mery <amery@geeks.cl>
 *
 * 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, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "common.h"

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "script.h"
#include "script_uboot.h"

#define pr_info(...)	errf("fexc-uboot: " __VA_ARGS__)
#define pr_err(...)	errf("E: fexc-uboot: " __VA_ARGS__)

#ifdef DEBUG
#define pr_debug(...)	errf("D: fexc-uboot: " __VA_ARGS__)
#else
#define pr_debug(...)
#endif

35
static inline void out_u32_member(FILE *out, const char *key, int hexa, uint32_t val)
Alejandro Mery's avatar
Alejandro Mery committed
36
37
{
	const char *fmt;
38
	if (hexa)
Alejandro Mery's avatar
Alejandro Mery committed
39
40
41
42
43
44
45
		fmt = "\t.%s = %#x,\n";
	else
		fmt = "\t.%s = %u,\n";

	fprintf(out, fmt, key, val);
}

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
static inline void out_gpio_member(FILE *out, const char *key,
				   struct script_gpio_entry *gpio)
{
	fprintf(out, "\t.%s = ", key);

	if (gpio->port == 0xffff)
		fprintf(out, "GPIO_AXP_CFG(%u", gpio->port_num);
	else
		fprintf(out, "GPIO_CFG(%u, %u", gpio->port, gpio->port_num);

	for (const int *p = gpio->data, *pe = p+4; p != pe; p++) {
		if (*p == -1)
			fputs(", 0xff", out);
		else
			fprintf(out, ", %u", *p);
	}

	fputs("),\n", out);
}

66
67
68
/*
 * DRAM
 */
Alejandro Mery's avatar
Alejandro Mery committed
69
70
71
72
73
74
static int generate_dram_struct(FILE *out, struct script_section *sp)
{
	struct list_entry *le;
	struct script_entry *ep;
	struct script_single_entry *val;
	const char *key;
75
	int ret = 1, hexa;
Alejandro Mery's avatar
Alejandro Mery committed
76

77
	fprintf(out, "static struct dram_para dram_para = {\n");
Alejandro Mery's avatar
Alejandro Mery committed
78
79
80
81
82
83
84
85
	for (le = list_first(&sp->entries); le;
	     le = list_next(&sp->entries, le)) {
		ep = container_of(le, struct script_entry, entries);

		if (strncmp(ep->name, "dram_", 5) != 0)
			goto invalid_field;

		key = ep->name + 5;
86
		if (key[0] == '\0')
Alejandro Mery's avatar
Alejandro Mery committed
87
88
89
90
91
			goto invalid_field;
		else if (strcmp(key, "baseaddr") == 0)
			continue; /* skip */
		else if (strcmp(key, "clk") == 0)
			key = "clock";
92
93
		else if (strcmp(key, "chip_density") == 0)
			key = "density";
Alejandro Mery's avatar
Alejandro Mery committed
94

95
96
97
98
99
100
		if (strncmp(key, "tpr", 3) == 0 ||
		    strncmp(key, "emr", 3) == 0)
			hexa = 1;
		else
			hexa = 0;

Alejandro Mery's avatar
Alejandro Mery committed
101
102
103
104
		switch (ep->type) {
		case SCRIPT_VALUE_TYPE_SINGLE_WORD:
			val = container_of(ep, struct script_single_entry, entry);
			if (val->value > 0)
105
				out_u32_member(out, key, hexa, val->value);
Alejandro Mery's avatar
Alejandro Mery committed
106
107
108
109
110
111
112
113
114
115
116
			/* pass through */
		case SCRIPT_VALUE_TYPE_NULL:
			continue;
		default:
invalid_field:
			pr_err("dram_para: %s: invalid field\n", ep->name);
			ret = 0;
		}

	}
	fprintf(out, "};\n");
117
118
119
120
121
122
123
124
125
126
	fputs("\nint sunxi_dram_init(void)\n"
	      "{\n\treturn DRAMC_init(&dram_para);\n}\n",
	      out);

	return ret;
}

/*
 * PMU
 */
127
128
static int generate_pmu_struct(FILE *out, struct script_section *target,
			       struct script_section *pmu_para)
129
130
{
	struct list_entry *le;
131
	struct script_section *sp;
132
133
	struct script_entry *ep;
	struct script_single_entry *val;
134
	const char *key;
135
136
137
	int ret = 1;

	fputs("\nstatic struct pmu_para pmu_para = {\n", out);
138
139

	sp = target;
140
141
142
143
144
145
146
147
148
149
150
151
152
	for (le = list_first(&sp->entries); le;
	     le = list_next(&sp->entries, le)) {
		ep = container_of(le, struct script_entry, entries);

		switch (ep->type) {
		case SCRIPT_VALUE_TYPE_SINGLE_WORD:
			val = container_of(ep, struct script_single_entry, entry);
			if (val->value > 0)
				out_u32_member(out, ep->name, 0, val->value);
			/* pass through */
		case SCRIPT_VALUE_TYPE_NULL:
			continue;
		default:
153
			pr_err("target: %s: invalid field\n", ep->name);
154
155
156
157
			ret = 0;
		}

	}
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

	sp = pmu_para;
	for (le = list_first(&sp->entries); le;
	     le = list_next(&sp->entries, le)) {
		ep = container_of(le, struct script_entry, entries);

		if (strncmp(ep->name, "pmu_", 4) != 0)
			continue;
		key = ep->name+4;

		if (strcmp(key, "used2") == 0 ||
		    strcmp(key, "para") == 0 ||
		    strcmp(key, "adpdet") == 0 ||
		    strcmp(key, "shutdown_chgcur") == 0 ||
		    strcmp(key, "shutdown_chgcur2") == 0 ||
		    strcmp(key, "pwroff_vol") == 0 ||
		    strcmp(key, "pwron_vol") == 0) {

			switch(ep->type) {
			case SCRIPT_VALUE_TYPE_SINGLE_WORD:
				val = container_of(ep, struct script_single_entry, entry);
				out_u32_member(out, key, 0, val->value);
				break;
			case SCRIPT_VALUE_TYPE_NULL:
				break;
			case SCRIPT_VALUE_TYPE_GPIO:
				out_gpio_member(out, key,
					container_of(ep, struct script_gpio_entry, entry));
				break;
			default:
				pr_err("pmu_para: %s: invalid field\n", ep->name);
			}
		}
	}

193
194
195
196
	fputs("};\n", out);
	fputs("\nint sunxi_pmu_init(void)\n"
	      "{\n\treturn PMU_init(&pmu_para);\n}\n",
	      out);
Alejandro Mery's avatar
Alejandro Mery committed
197
	return ret;
198
199

	(void) pmu_para;
Alejandro Mery's avatar
Alejandro Mery committed
200
201
202
203
204
}

int script_generate_uboot(FILE *out, const char *UNUSED(filename),
			  struct script *script)
{
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	struct {
		const char *name;
		struct script_section *sp;
	} sections[] = {
		{ "dram_para", NULL },
		{ "target", NULL },
		{ "pmu_para", NULL },
	};

	for (unsigned i=0; i<ARRAY_SIZE(sections); i++) {
		struct script_section *sp;

		sp = script_find_section(script, sections[i].name);
		if (sp)
			sections[i].sp = sp;
		else {
			pr_err("%s: critical section missing",
			       sections[i].name);
			return 0;
		}
	}
Alejandro Mery's avatar
Alejandro Mery committed
226

227
228
	fputs("/* this file is generated, don't edit it yourself */\n\n"
	      "#include <common.h>\n"
229
	      "#include <asm/arch/pmu.h>\n"
230
231
	      "#include <asm/arch/dram.h>\n\n",
	      out);
Alejandro Mery's avatar
Alejandro Mery committed
232

233
234
	generate_dram_struct(out, sections[0].sp);
	generate_pmu_struct(out, sections[1].sp, sections[2].sp);
235

Alejandro Mery's avatar
Alejandro Mery committed
236
237
	return 1;
}