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