1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "cx18-driver.h"
19#include "cx18-io.h"
20#include "cx18-scb.h"
21#include "cx18-irq.h"
22#include "cx18-firmware.h"
23#include "cx18-cards.h"
24#include <linux/firmware.h>
25
26#define CX18_PROC_SOFT_RESET 0xc70010
27#define CX18_DDR_SOFT_RESET 0xc70014
28#define CX18_CLOCK_SELECT1 0xc71000
29#define CX18_CLOCK_SELECT2 0xc71004
30#define CX18_HALF_CLOCK_SELECT1 0xc71008
31#define CX18_HALF_CLOCK_SELECT2 0xc7100C
32#define CX18_CLOCK_POLARITY1 0xc71010
33#define CX18_CLOCK_POLARITY2 0xc71014
34#define CX18_ADD_DELAY_ENABLE1 0xc71018
35#define CX18_ADD_DELAY_ENABLE2 0xc7101C
36#define CX18_CLOCK_ENABLE1 0xc71020
37#define CX18_CLOCK_ENABLE2 0xc71024
38
39#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
40
41#define CX18_FAST_CLOCK_PLL_INT 0xc78000
42#define CX18_FAST_CLOCK_PLL_FRAC 0xc78004
43#define CX18_FAST_CLOCK_PLL_POST 0xc78008
44#define CX18_FAST_CLOCK_PLL_PRESCALE 0xc7800C
45#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
46
47#define CX18_SLOW_CLOCK_PLL_INT 0xc78014
48#define CX18_SLOW_CLOCK_PLL_FRAC 0xc78018
49#define CX18_SLOW_CLOCK_PLL_POST 0xc7801C
50#define CX18_MPEG_CLOCK_PLL_INT 0xc78040
51#define CX18_MPEG_CLOCK_PLL_FRAC 0xc78044
52#define CX18_MPEG_CLOCK_PLL_POST 0xc78048
53#define CX18_PLL_POWER_DOWN 0xc78088
54#define CX18_SW1_INT_STATUS 0xc73104
55#define CX18_SW1_INT_ENABLE_PCI 0xc7311C
56#define CX18_SW2_INT_SET 0xc73140
57#define CX18_SW2_INT_STATUS 0xc73144
58#define CX18_ADEC_CONTROL 0xc78120
59
60#define CX18_DDR_REQUEST_ENABLE 0xc80000
61#define CX18_DDR_CHIP_CONFIG 0xc80004
62#define CX18_DDR_REFRESH 0xc80008
63#define CX18_DDR_TIMING1 0xc8000C
64#define CX18_DDR_TIMING2 0xc80010
65#define CX18_DDR_POWER_REG 0xc8001C
66
67#define CX18_DDR_TUNE_LANE 0xc80048
68#define CX18_DDR_INITIAL_EMRS 0xc80054
69#define CX18_DDR_MB_PER_ROW_7 0xc8009C
70#define CX18_DDR_BASE_63_ADDR 0xc804FC
71
72#define CX18_WMB_CLIENT02 0xc90108
73#define CX18_WMB_CLIENT05 0xc90114
74#define CX18_WMB_CLIENT06 0xc90118
75#define CX18_WMB_CLIENT07 0xc9011C
76#define CX18_WMB_CLIENT08 0xc90120
77#define CX18_WMB_CLIENT09 0xc90124
78#define CX18_WMB_CLIENT10 0xc90128
79#define CX18_WMB_CLIENT11 0xc9012C
80#define CX18_WMB_CLIENT12 0xc90130
81#define CX18_WMB_CLIENT13 0xc90134
82#define CX18_WMB_CLIENT14 0xc90138
83
84#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
85
86#define APU_ROM_SYNC1 0x6D676553
87#define APU_ROM_SYNC2 0x72646548
88
89struct cx18_apu_rom_seghdr {
90 u32 sync1;
91 u32 sync2;
92 u32 addr;
93 u32 size;
94};
95
96static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
97{
98 const struct firmware *fw = NULL;
99 int i, j;
100 unsigned size;
101 u32 __iomem *dst = (u32 __iomem *)mem;
102 const u32 *src;
103
104 if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
105 CX18_ERR("Unable to open firmware %s\n", fn);
106 CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
107 return -ENOMEM;
108 }
109
110 src = (const u32 *)fw->data;
111
112 for (i = 0; i < fw->size; i += 4096) {
113 cx18_setup_page(cx, i);
114 for (j = i; j < fw->size && j < i + 4096; j += 4) {
115
116 cx18_raw_writel(cx, *src, dst);
117 if (cx18_raw_readl(cx, dst) != *src) {
118 CX18_ERR("Mismatch at offset %x\n", i);
119 release_firmware(fw);
120 cx18_setup_page(cx, 0);
121 return -EIO;
122 }
123 dst++;
124 src++;
125 }
126 }
127 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
128 CX18_INFO("loaded %s firmware (%zu bytes)\n", fn, fw->size);
129 size = fw->size;
130 release_firmware(fw);
131 cx18_setup_page(cx, SCB_OFFSET);
132 return size;
133}
134
135static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
136 u32 *entry_addr)
137{
138 const struct firmware *fw = NULL;
139 int i, j;
140 unsigned size;
141 const u32 *src;
142 struct cx18_apu_rom_seghdr seghdr;
143 const u8 *vers;
144 u32 offset = 0;
145 u32 apu_version = 0;
146 int sz;
147
148 if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
149 CX18_ERR("unable to open firmware %s\n", fn);
150 CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
151 cx18_setup_page(cx, 0);
152 return -ENOMEM;
153 }
154
155 *entry_addr = 0;
156 src = (const u32 *)fw->data;
157 vers = fw->data + sizeof(seghdr);
158 sz = fw->size;
159
160 apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
161 while (offset + sizeof(seghdr) < fw->size) {
162 const __le32 *shptr = (__force __le32 *)src + offset / 4;
163
164 seghdr.sync1 = le32_to_cpu(shptr[0]);
165 seghdr.sync2 = le32_to_cpu(shptr[1]);
166 seghdr.addr = le32_to_cpu(shptr[2]);
167 seghdr.size = le32_to_cpu(shptr[3]);
168
169 offset += sizeof(seghdr);
170 if (seghdr.sync1 != APU_ROM_SYNC1 ||
171 seghdr.sync2 != APU_ROM_SYNC2) {
172 offset += seghdr.size;
173 continue;
174 }
175 CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
176 seghdr.addr + seghdr.size - 1);
177 if (*entry_addr == 0)
178 *entry_addr = seghdr.addr;
179 if (offset + seghdr.size > sz)
180 break;
181 for (i = 0; i < seghdr.size; i += 4096) {
182 cx18_setup_page(cx, seghdr.addr + i);
183 for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
184
185 cx18_raw_writel(cx, src[(offset + j) / 4],
186 dst + seghdr.addr + j);
187 if (cx18_raw_readl(cx, dst + seghdr.addr + j)
188 != src[(offset + j) / 4]) {
189 CX18_ERR("Mismatch at offset %x\n",
190 offset + j);
191 release_firmware(fw);
192 cx18_setup_page(cx, 0);
193 return -EIO;
194 }
195 }
196 }
197 offset += seghdr.size;
198 }
199 if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
200 CX18_INFO("loaded %s firmware V%08x (%zu bytes)\n",
201 fn, apu_version, fw->size);
202 size = fw->size;
203 release_firmware(fw);
204 cx18_setup_page(cx, 0);
205 return size;
206}
207
208void cx18_halt_firmware(struct cx18 *cx)
209{
210 CX18_DEBUG_INFO("Preparing for firmware halt.\n");
211 cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
212 0x0000000F, 0x000F000F);
213 cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
214 0x00000002, 0x00020002);
215}
216
217void cx18_init_power(struct cx18 *cx, int lowpwr)
218{
219
220
221 cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
222
223
224 cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
225 0x00000000, 0x00020002);
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
267 cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
268 CX18_FAST_CLOCK_PLL_FRAC);
269
270 cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
271 cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
272 cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
273
274
275
276
277 cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT);
278 cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F,
279 CX18_SLOW_CLOCK_PLL_FRAC);
280 cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST);
281
282
283
284 cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
285 cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);
286 cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 if (lowpwr) {
304 cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
305 0x00000020, 0xFFFFFFFF);
306 cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
307 0x00000004, 0xFFFFFFFF);
308 } else {
309
310 cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,
311 0x00000004, 0x00060006);
312 cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,
313 0x00000006, 0x00060006);
314 }
315
316 cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
317 0x00000002, 0xFFFFFFFF);
318 cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,
319 0x00000104, 0xFFFFFFFF);
320 cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,
321 0x00009026, 0xFFFFFFFF);
322 cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,
323 0x00003105, 0xFFFFFFFF);
324}
325
326void cx18_init_memory(struct cx18 *cx)
327{
328 cx18_msleep_timeout(10, 0);
329 cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,
330 0x00000000, 0x00010001);
331 cx18_msleep_timeout(10, 0);
332
333 cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
334
335 cx18_msleep_timeout(10, 0);
336
337 cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
338 cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
339 cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
340
341 cx18_msleep_timeout(10, 0);
342
343
344 cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
345 cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
346
347 cx18_msleep_timeout(10, 0);
348
349 cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,
350 0x00000000, 0x00020002);
351 cx18_msleep_timeout(10, 0);
352
353
354 cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
355
356 cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,
357 0x00000001, 0x00010001);
358
359 cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
360 cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
361
362 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02);
363 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09);
364 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05);
365 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06);
366 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07);
367 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10);
368 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12);
369 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13);
370 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11);
371 cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);
372}
373
374#define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw"
375#define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw"
376
377int cx18_firmware_init(struct cx18 *cx)
378{
379 u32 fw_entry_addr;
380 int sz, retries;
381 u32 api_args[MAX_MB_ARGUMENTS];
382
383
384 cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
385
386
387 cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
388 0x0000000F, 0x000F000F);
389
390 cx18_msleep_timeout(1, 0);
391
392
393 if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {
394 CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);
395 return -EIO;
396 }
397
398 cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
399 cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
400
401 sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx);
402 if (sz <= 0)
403 return sz;
404
405
406 cx18_init_scb(cx);
407
408 fw_entry_addr = 0;
409 sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx,
410 &fw_entry_addr);
411 if (sz <= 0)
412 return sz;
413
414
415 cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,
416 0x00000000, 0x00080008);
417
418
419 for (retries = 0;
420 retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;
421 retries++)
422 cx18_msleep_timeout(10, 0);
423
424 cx18_msleep_timeout(200, 0);
425
426 if (retries == 50 &&
427 (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {
428 CX18_ERR("Could not start the CPU\n");
429 return -EIO;
430 }
431
432
433
434
435
436
437
438
439
440
441 cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
442
443
444 sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);
445 if (sz < 0)
446 return sz;
447
448
449 cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
450 return 0;
451}
452
453MODULE_FIRMWARE(CX18_CPU_FIRMWARE);
454MODULE_FIRMWARE(CX18_APU_FIRMWARE);
455