2 * Copyright (C) 2007 Michael Buesch <m@bues.ch>
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
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
31 struct list_head list;
34 /* The IV in the binary file */
40 } data __attribute__((__packed__));
41 } __attribute__((__packed__));
43 #define FW_IV_OFFSET_MASK 0x7FFF
44 #define FW_IV_32BIT 0x8000
47 struct ivals_context {
48 /* Pointer to the parsed section structure */
49 const struct initvals_sect *sect;
50 /* List of struct initval */
51 struct list_head ivals;
52 /* Number of initvals. */
53 unsigned int ivals_count;
56 #define _msg_helper(type, ctx, msg, x...) do { \
57 fprintf(stderr, "InitVals " type); \
58 fprintf(stderr, " (Section \"%s\")", ctx->sect->name); \
59 fprintf(stderr, ":\n " msg "\n" ,##x); \
62 #define iv_error(ctx, msg, x...) do { \
63 _msg_helper("ERROR", ctx, msg ,##x); \
67 #define iv_warn(ctx, msg, x...) \
68 _msg_helper("warning", ctx, msg ,##x)
70 #define iv_info(ctx, msg, x...) \
71 _msg_helper("info", ctx, msg ,##x)
74 static void assemble_write_mmio(struct ivals_context *ctx,
81 iv = xmalloc(sizeof(struct initval));
85 INIT_LIST_HEAD(&iv->list);
86 list_add_tail(&iv->list, &ctx->ivals);
90 static void assemble_write_phy(struct ivals_context *ctx,
94 assemble_write_mmio(ctx, 0x3FC, SIZE_16BIT, offset);
95 assemble_write_mmio(ctx, 0x3FE, SIZE_16BIT, value);
98 static void assemble_write_radio(struct ivals_context *ctx,
102 assemble_write_mmio(ctx, 0x3F6, SIZE_16BIT, offset);
103 assemble_write_mmio(ctx, 0x3FA, SIZE_16BIT, value);
106 static void shm_control_word(struct ivals_context *ctx,
107 unsigned int routing,
110 unsigned int control;
112 control = (routing & 0xFFFF);
114 control |= (offset & 0xFFFF);
115 assemble_write_mmio(ctx, 0x160, SIZE_32BIT, control);
118 static void shm_write32(struct ivals_context *ctx,
119 unsigned int routing,
123 if ((routing & 0xFF) == 0x01) {
124 /* Is SHM Shared-memory */
125 //TODO assert((offset & 0x0001) == 0);
126 if (offset & 0x0003) {
127 /* Unaligned access */
128 shm_control_word(ctx, routing, offset >> 2);
129 assemble_write_mmio(ctx, 0x166, SIZE_16BIT,
130 (value >> 16) & 0xFFFF);
131 shm_control_word(ctx, routing, (offset >> 2) + 1);
132 assemble_write_mmio(ctx, 0x164, SIZE_16BIT,
138 shm_control_word(ctx, routing, offset);
139 assemble_write_mmio(ctx, 0x164, SIZE_32BIT, value);
142 static void shm_write16(struct ivals_context *ctx,
143 unsigned int routing,
147 if ((routing & 0xFF) == 0x01) {
148 /* Is SHM Shared-memory */
149 //TODO assert((offset & 0x0001) == 0);
150 if (offset & 0x0003) {
151 /* Unaligned access */
152 shm_control_word(ctx, routing, offset >> 2);
153 assemble_write_mmio(ctx, 0x166, SIZE_16BIT,
159 shm_control_word(ctx, routing, offset);
160 assemble_write_mmio(ctx, 0x164, SIZE_16BIT, value);
163 static void assemble_write_shm(struct ivals_context *ctx,
164 unsigned int routing,
169 switch (routing & 0xFF) {
170 case 0: case 1: case 2: case 3: case 4:
181 shm_write16(ctx, routing, offset, value);
184 shm_write32(ctx, routing, offset, value);
187 fprintf(stderr, "Internal assembler BUG. SHMwrite invalid size\n");
192 /* Template RAM write */
193 static void assemble_write_tram(struct ivals_context *ctx,
197 assemble_write_mmio(ctx, 0x130, SIZE_32BIT, offset);
198 assemble_write_mmio(ctx, 0x134, SIZE_32BIT, value);
201 static void assemble_ival_section(struct ivals_context *ctx,
202 const struct initvals_sect *sect)
204 struct initval_op *op;
207 if (list_empty(§->ops)) {
211 list_for_each_entry(op, §->ops, list) {
214 assemble_write_mmio(ctx, op->args[1],
219 assemble_write_mmio(ctx, op->args[1],
224 assemble_write_phy(ctx, op->args[1],
228 assemble_write_radio(ctx, op->args[1],
232 assemble_write_shm(ctx, op->args[1],
238 assemble_write_shm(ctx, op->args[1],
244 assemble_write_tram(ctx, op->args[1],
251 static unsigned int initval_to_raw(struct ivals_context *ctx,
252 struct initval_raw *raw,
253 const struct initval *iv)
257 memset(raw, 0, sizeof(*raw));
258 if (iv->offset & ~FW_IV_OFFSET_MASK) {
259 iv_error(ctx, "Initval offset 0x%04X too big. "
260 "Offset must be <= 0x%04X",
261 iv->offset, FW_IV_OFFSET_MASK);
263 raw->offset_size = cpu_to_be16(iv->offset);
267 raw->data.d16 = cpu_to_be16(iv->value);
268 size = sizeof(be16_t) + sizeof(be16_t);
271 raw->data.d32 = cpu_to_be32(iv->value);
272 raw->offset_size |= cpu_to_be16(FW_IV_32BIT);
273 size = sizeof(be16_t) + sizeof(be32_t);
276 iv_error(ctx, "Internal error. initval_to_raw invalid size.");
283 static void emit_ival_section(struct ivals_context *ctx)
289 struct initval_raw raw;
290 struct fw_header hdr;
292 unsigned int filesize = 0;
294 memset(&hdr, 0, sizeof(hdr));
295 hdr.type = FW_TYPE_IV;
296 hdr.ver = FW_HDR_VER;
297 hdr.size = cpu_to_be32(ctx->ivals_count);
299 fn_len = strlen(ctx->sect->name) + strlen(cmdargs.initvals_fn_extension ? : "") + 1;
300 fn = xmalloc(fn_len);
301 snprintf(fn, fn_len, "%s%s", ctx->sect->name, cmdargs.initvals_fn_extension ? : "");
302 fd = fopen(fn, "w+");
304 fprintf(stderr, "Could not open initval output file \"%s\"\n", fn);
309 if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
310 fprintf(stderr, "Could not write initvals outfile\n");
314 if (IS_VERBOSE_DEBUG)
315 fprintf(stderr, "\nInitvals \"%s\":\n", ctx->sect->name);
316 list_for_each_entry(iv, &ctx->ivals, list) {
317 if (IS_VERBOSE_DEBUG) {
318 fprintf(stderr, "%04X %u %08X\n",
323 size = initval_to_raw(ctx, &raw, iv);
324 if (fwrite(&raw, size, 1, fd) != 1) {
325 fprintf(stderr, "Could not write initvals outfile\n");
331 if (cmdargs.print_sizes) {
332 printf("%s: %d values (%u bytes)\n",
333 fn, ctx->ivals_count, filesize);
340 void assemble_initvals(void)
342 struct ivals_context ctx;
343 struct initvals_sect *sect;
345 list_for_each_entry(sect, &infile.ivals, list) {
346 memset(&ctx, 0, sizeof(ctx));
347 INIT_LIST_HEAD(&ctx.ivals);
349 assemble_ival_section(&ctx, sect);
350 emit_ival_section(&ctx);