blob: e5ab2eb0ff0ca175ce77a6cef8dcd89ba8c4d9e0 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2
3 Copyright (c) 2014-2015 Lantiq Deutschland GmbH
4 Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
5 Copyright 2016, Intel Corporation.
6
7 For licensing information, see the file 'LICENSE' in the root folder of
8 this software module.
9
10******************************************************************************/
11
12/**
13 \file dxs_init.c
14 Implementation of initialization functions.
15*/
16
17/* ========================================================================== */
18/* Includes */
19/* ========================================================================== */
20#include <stdlib.h>
21
22#include "dxs_config.h"
23#include "dxs_version.h"
24#include "dxs_init.h"
25#include "dxs_errno.h"
26#include "dxs_error.h"
27#include "dxs_fw_cmd.h"
28#include "dxs_pcm.h"
29#include "dxs_sdd.h"
30#include "dxs_sig.h"
31#include "dxs_gpio.h"
32#include "dxs_access.h"
33#include "dxs_cid.h"
34#include "dxs_pollint.h"
35#include "dxs_outbox.h"
36#include "dxs_event.h"
37#include "dxs_spi.h"
38#include "dxs_dcdc_hw.h"
39#include "dxs_ring.h"
40#ifdef EVENT_LOGGER_DEBUG
41#include <sys/ioctl.h>
42#endif
43
44const char DXS_WHATVERSION[] = DXS_WHAT_STR;
45
46/* ========================================================================== */
47/* Macro definitions */
48/* ========================================================================== */
49
50/* ========================================================================== */
51/* Type definitions */
52/* ========================================================================== */
53/** Data structure for DXS_FW_SYS_VERS_ECMD firmware command */
54typedef struct
55{
56#if __BYTE_ORDER == __BIG_ENDIAN
57 CMD_HEAD_BE;
58 /** Device Number */
59 uint32_t DEVNR : 11;
60 /** Calender Week */
61 uint32_t CW : 6;
62 /** Production Year */
63 uint32_t YEAR : 6;
64 /** Channel */
65 uint32_t CH : 1;
66 /** Device ID Representing PEB Number */
67 uint32_t DEV : 8;
68 /** Major */
69 uint32_t MAJ : 8;
70 /** Minor */
71 uint32_t MIN : 8;
72 /** Hotfix */
73 uint32_t HF : 8 ;
74 /** Reserved */
75 uint32_t Res02 : 8;
76 /** Time Stamp */
77 uint32_t TIME;
78#else
79 CMD_HEAD_LE;
80 /** Device ID Representing PEB Number */
81 uint32_t DEV : 8;
82 /** Channel */
83 uint32_t CH : 1;
84 /** Production Year */
85 uint32_t YEAR : 6;
86 /** Calender Week */
87 uint32_t CW : 6;
88 /** Device Number */
89 uint32_t DEVNR : 11;
90 /** Reserved */
91 uint32_t Res02 : 8;
92 /** Hotfix */
93 uint32_t HF : 8 ;
94 /** Minor */
95 uint32_t MIN : 8;
96 /** Major */
97 uint32_t MAJ : 8;
98 /** Time Stamp */
99 uint32_t TIME;
100#endif
101} __attribute__ ((packed)) DXS_FW_SYS_VERS_t;
102#define DXS_FW_SYS_VERS_ECMD 6
103#define DXS_FW_SYS_VERS_LENGTH 12
104
105/** Data structure for system capabilities firmware command */
106typedef struct
107{
108#if __BYTE_ORDER == __BIG_ENDIAN
109 CMD_HEAD_BE;
110 /* Reserved */
111 uint32_t Res02 : 25;
112 /* Howler Support Available */
113 uint32_t HOWLER : 1;
114 /* Caller ID Available */
115 uint32_t CID : 1;
116 /* Universal Tone Detector Available */
117 uint32_t UTD : 1;
118 /* Teletax Support Available */
119 uint32_t TTX : 1;
120 /* Reserved */
121 uint32_t Res03 : 1;
122 /* AC Level Meter Support Available */
123 uint32_t ACLM : 1;
124 /* GR909 available */
125 uint32_t GR909 : 1;
126#else
127 CMD_HEAD_LE;
128 /* GR909 available */
129 uint32_t GR909 : 1;
130 /* AC Level Meter Support Available */
131 uint32_t ACLM : 1;
132 /* Reserved */
133 uint32_t Res03 : 1;
134 /* Teletax Support Available */
135 uint32_t TTX : 1;
136 /* Universal Tone Detector Available */
137 uint32_t UTD : 1;
138 /* Caller ID Available */
139 uint32_t CID : 1;
140 /* Howler Support Available */
141 uint32_t HOWLER : 1;
142 /* Reserved */
143 uint32_t Res02 : 25;
144#endif
145} __attribute__ ((packed)) DXS_FW_SYS_CAPS_t;
146#define DXS_FW_SYS_CAPS_ECMD 7
147#define DXS_FW_SYS_CAPS_LENGTH 4
148
149/** Data structure for DXS_FW_SYS_Control_ECMD firmware command */
150typedef struct
151{
152#if __BYTE_ORDER == __BIG_ENDIAN
153 CMD_HEAD_BE;
154 /* Reserved */
155 uint32_t Res02 : 25;
156 /* Sync-Fail/ Clock-Fail Handling Enable */
157 uint32_t SYCLKE : 1;
158 /* PLL Limiter Enable */
159 uint32_t PLIM : 1;
160 /* Charge Pump Voltage Level */
161 uint32_t CP_VOLT : 3;
162 /* Charge Pump Enable */
163 uint32_t CP_EN : 1;
164 /* Sleep Enable */
165 uint32_t SE : 1;
166#else
167 CMD_HEAD_LE;
168 /* Sleep Enable */
169 uint32_t SE : 1;
170 /* Charge Pump Enable */
171 uint32_t CP_EN : 1;
172 /* Charge Pump Voltage Level */
173 uint32_t CP_VOLT : 3;
174 /* PLL Limiter Enable */
175 uint32_t PLIM : 1;
176 /* Sync-Fail/ Clock-Fail Handling Enable */
177 uint32_t SYCLKE : 1;
178 /* Reserved */
179 uint32_t Res02 : 25;
180#endif
181} __attribute__ ((packed)) DXS_FW_SYS_Control_t;
182#define DXS_FW_SYS_Control_ECMD 8
183#define DXS_FW_SYS_Control_LENGTH 4
184#define DXS_FW_SYS_Control_CP_VOLT_5_0V 3
185
186/** Device capabilities */
187typedef struct
188{
189 /* status flag */
190 uint32_t flag;
191#define DXS_DEV_CAPS_INITIALIZED 1
192#define DXS_DEV_CAPS_UPDATED 2
193#define DXS_DEV_SYS_CTRL_UPDATED 4
194 /* device version */
195 DXS_Dev_t dev;
196 /* device package */
197 DXS_Package_t pack;
198 /* firmware version */
199 DXS_FW_SYS_VERS_t fw_vers;
200 /* firmware capabilities */
201 DXS_FW_SYS_CAPS_t fw_caps;
202 /* firmware system control */
203 DXS_FW_SYS_Control_t fw_sys_ctrl;
204} DXS_Dev_Caps_t;
205
206/* ========================================================================== */
207/* Global variables */
208/* ========================================================================== */
209/* static data */
210static DXS_DEVICE_t dxs_devices[DXS_MAX_DEVICES] = {0};
211static DXS_Dev_Caps_t dxs_caps[DXS_MAX_DEVICES] = {0};
212
213/* ========================================================================== */
214/* Function prototypes */
215/* ========================================================================== */
216static int32_t dxs_controller_reset(DXS_DEVICE_t *pDev);
217
218/* ========================================================================== */
219/* Function implementation */
220/* ========================================================================== */
221#ifdef EVENT_LOGGER_DEBUG
222static void dxs_el_register(DXS_DEVICE_t *pDev)
223{
224 EL_IoctlRegister_t el_reg;
225 int ret;
226
227 pDev->el_fd = open(EL_DEVICE_NAME, 2, 0644);
228 if (pDev->el_fd < 0)
229 {
230 return;
231 }
232 else
233 {
234 snprintf(el_reg.sName, sizeof(el_reg.sName), "dxs_lib");
235
236 el_reg.nType = DXS_LIB_DEV_TYPE;
237 el_reg.nDevNum = pDev->nDevNum;
238
239 ret = ioctl(pDev->el_fd, EL_REGISTER, (int32_t)&el_reg);
240 if (ret == IFX_SUCCESS)
241 {
242 IFX_char_t *pCmd ="echo \"*\" > /proc/driver/el/logs/all";
243 FILE *el_pipe_fd;
244
245 el_pipe_fd = popen(pCmd, "r");
246 if (!el_pipe_fd)
247 {
248 return;
249 }
250 pclose(el_pipe_fd);
251 }
252 }
253}
254
255static void dxs_el_unregister(DXS_DEVICE_t *pDev)
256{
257 EL_IoctlRegister_t el_reg;
258
259 snprintf(el_reg.sName, sizeof(el_reg.sName), "dxs_lib");
260 el_reg.nType = DXS_LIB_DEV_TYPE;
261 el_reg.nDevNum = pDev->nDevNum;
262
263 if (pDev->el_fd > 0)
264 {
265 ioctl(pDev->el_fd, EL_UNREGISTER, (int32_t)&el_reg);
266 }
267}
268#endif
269
270/**
271 Function dxs_caps_init
272
273 \param dev - device number
274
275*/
276static void *dxs_caps_init(uint8_t dev)
277{
278 DXS_Dev_Caps_t *p;
279
280 if (dev >= DXS_MAX_DEVICES)
281 return (void *)NULL;
282
283 p = &dxs_caps[dev];
284
285 p->flag = 0;
286
287 p->fw_vers.CMD = CMD_EOP;
288 p->fw_vers.MOD = MOD_SYS;
289 p->fw_vers.ECMD = DXS_FW_SYS_VERS_ECMD;
290 p->fw_vers.LENGTH = DXS_FW_SYS_VERS_LENGTH;
291
292 p->fw_caps.CMD = CMD_EOP;
293 p->fw_caps.MOD = MOD_SYS;
294 p->fw_caps.ECMD = DXS_FW_SYS_CAPS_ECMD;
295 p->fw_caps.LENGTH = DXS_FW_SYS_CAPS_LENGTH;
296
297 p->fw_sys_ctrl.CMD = CMD_EOP;
298 p->fw_sys_ctrl.MOD = MOD_SYS;
299 p->fw_sys_ctrl.ECMD = DXS_FW_SYS_Control_ECMD;
300 p->fw_sys_ctrl.LENGTH = DXS_FW_SYS_Control_LENGTH;
301
302 p->flag |= DXS_DEV_CAPS_INITIALIZED;
303
304 return (void *)p;
305}
306
307/**
308 Function dxs_caps_vers_update
309
310 \param pDev - pointer to DXS device structure
311
312 \return
313 - DXS_status_t
314*/
315int32_t dxs_caps_vers_update(DXS_DEVICE_t *pDev)
316{
317 DXS_Dev_Caps_t *p;
318 int32_t err;
319
320 if (pDev == NULL)
321 {
322 DXS_RETURN(DXS_statusInvalidParam);
323 }
324 p = (DXS_Dev_Caps_t *)pDev->caps;
325
326 if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
327 {
328 DXS_RETURN(DXS_statusNotInitResource);
329 }
330
331 if (!(p->flag & DXS_DEV_CAPS_UPDATED))
332 {
333 err = CmdRead(pDev, (uint32_t *)&p->fw_caps, (uint32_t *)&p->fw_caps);
334 if (err)
335 {
336 DXS_RETURN(DXS_statusCapVersUpdateError);
337 }
338 err = CmdRead(pDev, (uint32_t *)&p->fw_vers, (uint32_t *)&p->fw_vers);
339 if (err)
340 {
341 DXS_RETURN(DXS_statusCapVersUpdateError);
342 }
343 /* update device ROM version */
344 pDev->rom_mask_ver = p->fw_vers.MAJ & 0x7F;
345
346 if (p->fw_vers.DEV == 0x9)
347 {
348 /* XS_VQFN-68_ES DXS Engineering Sample (A11 design)
349 in PG-VQFN-68 package */
350 p->pack = DXS_PACKAGE_VQFN68;
351 if (p->fw_vers.CH == 0)
352 {
353 p->dev = DXS_DEV_PEF32002_A11;
354 pDev->nChannels = 2;
355 }
356 else
357 {
358 p->dev = DXS_DEV_PEF32001_A11;
359 pDev->nChannels = 1;
360 }
361 }
362 else if (p->fw_vers.DEV == 0xA)
363 {
364 /* XS_VQFN-68_V11 DXS V1.1 (A12 design)
365 in PG-VQFN-68 package */
366 p->pack = DXS_PACKAGE_VQFN68;
367 if (p->fw_vers.CH == 0)
368 {
369 p->dev = DXS_DEV_PEF32002_A12;
370 pDev->nChannels = 2;
371 }
372 else
373 {
374 p->dev = DXS_DEV_PEF32001_A12;
375 pDev->nChannels = 1;
376 }
377 }
378 else if (p->fw_vers.DEV == 0x2A)
379 {
380 /* XC_VQFN-68_V11 DXC2 V1.1 (A12 design)
381 in PG-VQFN-68 package, only 2 channel version */
382 p->pack = DXS_PACKAGE_VQFN68;
383 p->dev = DXC_DEV_PEF31002_A12;
384 pDev->nChannels = 2;
385 }
386 else if (p->fw_vers.DEV == 0x49)
387 {
388 /* XS_VQFN-48_ES DXS1 Engineering Sample (A11 design)
389 in PG-VQFN-48 package */
390 p->pack = DXS_PACKAGE_VQFN48;
391 p->dev = DXS_DEV_PEF32001_A11;
392 pDev->nChannels = 1;
393 }
394 else if (p->fw_vers.DEV == 0x4A)
395 {
396 /* XS_VQFN-48_V11 DXS1 V1.1 (A12 design)
397 in PG-VQFN-48 package */
398 p->pack = DXS_PACKAGE_VQFN48;
399 p->dev = DXS_DEV_PEF32001_A12;
400 pDev->nChannels = 1;
401 }
402 else if (p->fw_vers.DEV == 0x6A)
403 {
404 /* XC_VQFN-48_V11 DXC1 V1.1 (A12 design)
405 in PG-VQFN-48 package */
406 p->pack = DXS_PACKAGE_VQFN48;
407 p->dev = DXC_DEV_PEF31001_A12;
408 pDev->nChannels = 1;
409 }
410 else if (p->fw_vers.DEV == 0x0B)
411 {
412 /* XS_VQFN-68_V12 DXS2 V1.2 (A13 design)
413 in PG-VQFN-68 package */
414 p->pack = DXS_PACKAGE_VQFN68;
415 p->dev = DXS_DEV_PEF32002_V12_A13;
416 pDev->nChannels = 2;
417 }
418 else if (p->fw_vers.DEV == 0x2B)
419 {
420 /* XC_VQFN-68_V12 DXC2 V1.2 (A13 design)
421 in PG-VQFN-68 package */
422 p->pack = DXS_PACKAGE_VQFN68;
423 p->dev = DXC_DEV_PEF31002_V12_A13;
424 pDev->nChannels = 2;
425 }
426 else if (p->fw_vers.DEV == 0x8C)
427 {
428 /* XS_VQFN-44_V12 DXS1 V1.2
429 (A11 new codec design) in PG-VQFN-44 package */
430 p->pack = DXS_PACKAGE_VQFN44;
431 p->dev = DXS_DEV_PEF32001_V12_A11;
432 pDev->nChannels = 1;
433 }
434 else if (p->fw_vers.DEV == 0xAC)
435 {
436 /* XC_VQFN-44_V12 DXC1 V1.2
437 (A11 new codec design) in PG-VQFN-44 package */
438 p->pack = DXS_PACKAGE_VQFN44;
439 p->dev = DXC_DEV_PEF31001_V12_A11;
440 pDev->nChannels = 1;
441 }
442 else if (p->fw_vers.DEV == 0x4C)
443 {
444 /* XS_VQFN-48_V12 DXS1 V1.2
445 (A11 new codec design) in PG-VQFN-48 package */
446 p->pack = DXS_PACKAGE_VQFN48;
447 p->dev = DXS_DEV_PEF32001_V12_A11;
448 pDev->nChannels = 1;
449
450 }
451 else if (p->fw_vers.DEV == 0x6C)
452 {
453 /* XC_VQFN-48_V12 DXC1 V1.2
454 (A11 new codec design) in PG-VQFN-48 package */
455 p->pack = DXS_PACKAGE_VQFN48;
456 p->dev = DXC_DEV_PEF31001_V12_A11;
457 pDev->nChannels = 1;
458 }
459 else if (p->fw_vers.DEV == 0x0C)
460 {
461 /* XS_VQFN-68_V12 DXS1 V1.2
462 (A11 new codec design) in PG-VQFN-68 package */
463 p->pack = DXS_PACKAGE_VQFN68;
464 p->dev = DXS_DEV_PEF32001_V12_A11;
465 pDev->nChannels = 1;
466 }
467 else if (p->fw_vers.DEV == 0x2C)
468 {
469 /* XC_VQFN-68_V12 DXC1 V1.2
470 (A11 new codec design) in PG-VQFN-68 package */
471 p->pack = DXS_PACKAGE_VQFN68;
472 p->dev = DXC_DEV_PEF31001_V12_A11;
473 pDev->nChannels = 1;
474 }
475 else
476 {
477 p->pack = DXS_PACKAGE_UNKNOWN;
478 p->dev = DXS_DEV_UNKNOWN;
479 /* default for unfused device */
480 pDev->nChannels = 1;
481 }
482
483 p->flag |= DXS_DEV_CAPS_UPDATED;
484 }
485
486 return DXS_statusOk;
487}
488
489/**
490 Function dxs_caps_vers_forget
491
492 \param pDev - pointer to DXS device structure
493
494 \return
495 - DXS_status_t
496*/
497int32_t dxs_caps_vers_forget(DXS_DEVICE_t *pDev)
498{
499 DXS_Dev_Caps_t *p;
500
501 if (pDev == NULL)
502 {
503 DXS_RETURN(DXS_statusInvalidParam);
504 }
505 p = (DXS_Dev_Caps_t *)pDev->caps;
506
507 p->flag &= ~DXS_DEV_CAPS_UPDATED;
508
509 return DXS_statusOk;
510}
511
512/**
513 Function dxs_get_dev
514
515 \param dxs - device number
516
517 \return
518 - pointer to DxS device structure
519*/
520DXS_DEVICE_t *dxs_get_dev (uint8_t dxs)
521{
522 if (dxs >= DXS_MAX_DEVICES)
523 return NULL;
524
525 return &dxs_devices[dxs];
526}
527
528
529/**
530 Calculate CRC-8-CCITT. POLYNOMIAL = 0x07
531
532 \param pData Pointer to data for CRC calculation
533 \param nLength Length of data buffer
534
535 \return
536 Calculated CRC value.
537*/
538uint8_t dxs_CRC_8_CCITT(uint8_t *pData, uint32_t nLength)
539{
540 uint8_t nCRC = 0;
541 int32_t i, j;
542
543 /* Perform modulo-2 division, a byte at a time. */
544 for (i = 0; i < nLength; i++)
545 {
546 /* Bring the next byte into the nCRC. */
547 nCRC ^= pData[i];
548
549 /* Perform modulo-2 division, a bit at a time. */
550 for (j = 8; j > 0; j--)
551 {
552 /* Try to divide the current data bit. */
553 if (nCRC & 0x80)
554 nCRC = (nCRC << 1) ^ 0x07;
555 else
556 nCRC = (nCRC << 1);
557 }
558 }
559 return nCRC;
560}
561
562
563/**
564 Function dxs_exit
565
566 \param pDev - pointer to DXS device structure
567
568*/
569int32_t dxs_exit(DXS_DEVICE_t *pDev)
570{
571 uint8_t ch;
572 int32_t ret = DXS_statusOk;
573
574 if (pDev->flags & DXS_DEV_INITIALIZED)
575 {
576 /* DCDC HW specific deinit */
577 DXS_DCDC_HW_Exit(pDev);
578
579 if (pDev->irqNumber == -1)
580 {
581 /* stop polling */
582 dxs_polling_timer_stop();
583 }
584 else
585 {
586 /* uninstall interrupt handler */
587 dxs_interrupt_exit();
588 }
589
590 /* stop obx handling thread */
591 dxs_outbox_handler_exit(pDev);
592 pDev->flags &= ~DXS_DEV_OBX_HND_INITIALIZED;
593
594 /* uninitialize event memory pool */
595 dxs_event_pool_exit(pDev);
596
597 /* uninitialize message queues */
598 fifo_destroy(pDev->event_queue);
599 fifo_destroy(pDev->cmd_obx_queue);
600
601 /* close SPI interface */
602 dxs_spi_linux_exit(pDev->spidev);
603 pDev->flags &= ~DXS_DEV_ACCESS_INITIALIZED;
604
605 /* delete mbx access mutex */
606 ret = pthread_mutex_unlock(&pDev->mtxMbxAcc);
607 if (ret != 0)
608 DXS_ERROR_PUSH(ret);
609 ret = pthread_mutex_destroy(&pDev->mtxMbxAcc);
610 if (ret != 0)
611 DXS_ERROR_PUSH(ret);
612
613 sem_destroy(&pDev->mtxPatchDwld);
614
615#ifdef DXS_FEAT_UTD
616 /* delete UTD mutex */
617 dxs_sig_utd_mtx_destroy();
618#endif /* DXS_FEAT_UTD */
619
620 /* close channel resources */
621 for (ch = 0; ch < pDev->nChannels; ch++)
622 {
623 DXS_CHANNEL_t *pCh = &pDev->pChannel[ch];
624
625#ifdef DXS_FEAT_HSM
626 DXS_Dial_Cleanup(pCh);
627#endif
628 /* cleanup only for SDD resource */
629 ret = DXS_SDD_ChExit(pCh);
630 if (ret != DXS_statusOk)
631 DXS_ERROR_PUSH(ret);
632 }
633
634#ifdef EVENT_LOGGER_DEBUG
635 dxs_el_unregister(pDev);
636#endif /* EVENT_LOGGER_DEBUG */
637
638 pDev->flags &= ~DXS_DEV_INITIALIZED;
639 }
640 DXS_RETURN(ret);
641}
642
643/**
644 Default initialization of DXS registers.
645
646 Enable the required interrupts in the register interface.
647
648 \param pDev pointer to the device structure
649
650 \return
651 - DXS_statusOk
652 - DXS_statusSpiAccError
653*/
654static int32_t dxs_default_reg_init(DXS_DEVICE_t *pDev)
655{
656 int32_t ret = DXS_statusOk;
657 uint16_t nRegHostIen1, nRegHostIen2;
658
659 /*
660 Enable the interrupts OBX_RDY and ERR.
661 */
662 nRegHostIen1 = DXS_REG_IEN1_RESET;
663 nRegHostIen1 |= DXS_REG_IEN1_OBX_RDY;
664 nRegHostIen1 |= DXS_REG_IEN1_ERR;
665 ret = DXS_RegWrite(pDev, DXS_REG_IEN1, nRegHostIen1);
666 if (ret != DXS_statusOk)
667 DXS_RETURN(ret);
668
669 /*
670 Enable the interrupts OBX_UFL and IBX_OFL.
671 */
672 nRegHostIen2 = DXS_REG_IEN2_RESET;
673 nRegHostIen2 |= DXS_REG_IEN2_OBX_UFL;
674 nRegHostIen2 |= DXS_REG_IEN2_IBX_OFL;
675 ret = DXS_RegWrite(pDev, DXS_REG_IEN2, nRegHostIen2);
676
677 DXS_RETURN(ret);
678}
679
680/**
681 Function dxs_init
682
683 \param pDev - pointer to DXS device structure
684 \param chipSelect - CS number
685 \param irqNumber - IRQ line number
686 \param dcdcType - DCDC variant handled by DXS_DCDC_Var_t type
687 \param dev - device number
688
689 \return
690 - DXS_status_t
691*/
692/*
693 * should return either 0 or -1
694 */
695int32_t dxs_init(DXS_DEVICE_t *pDev, uint8_t chipSelect, int32_t irqNumber,
696 uint8_t dcdcType, uint8_t access, uint8_t dev)
697{
698 int32_t ret = DXS_statusOk, i;
699#ifdef DXS_FEAT_HSM
700 DXS_status_t status;
701#endif
702 uint8_t ch;
703
704 if (access >= DXS_ACCESS_LAST)
705 {
706 DXS_RETURN(DXS_statusInvalidParam);
707 }
708
709 if (dev >= DXS_MAX_DEVICES)
710 {
711 DXS_RETURN(DXS_statusInvalidParam);
712 }
713
714 for (i=0; i<DXS_MAX_DEVICES; i++)
715 {
716 DXS_DEVICE_t *pdev = dxs_get_dev(i);
717
718 if (pdev->flags & DXS_DEV_INITIALIZED && pdev->dcdcType != dcdcType)
719 {
720 /* provided dcdcType does not match
721 with previously initialized devices */
722 DXS_RETURN(DXS_statusInvalidParam);
723 }
724 }
725
726 ret = dxs_exit(pDev);
727 if (ret != DXS_statusOk)
728 {
729 DXS_RETURN(DXS_statusDevInitFailed);
730 }
731
732 pDev->nDevNum = dev;
733 pDev->chipSelect = chipSelect;
734 pDev->irqNumber = irqNumber;
735 pDev->dcdcType = dcdcType;
736 pDev->access = access;
737
738 pthread_mutex_init(&pDev->mtxMbxAcc, NULL);
739 pDev->nMbxCachedCbiLen = 0;
740
741#ifdef EVENT_LOGGER_DEBUG
742 dxs_el_register(pDev);
743#endif
744
745 /* open SPI interface */
746 pDev->spidev = dxs_spi_linux_init(chipSelect, access);
747 if (pDev->spidev > 0)
748 {
749 pDev->flags |= DXS_DEV_ACCESS_INITIALIZED;
750 }
751 else
752 {
753 DXS_RETURN(DXS_statusSpiOpenError);
754 }
755
756 /* TODO: light chip access test + error code if failed */
757
758 /* Reset the DXS controller to bring the chip into the default state.
759 The data structures of the driver will be initialized to the same
760 known default state.*/
761 dxs_controller_reset(pDev);
762
763 /* initialize message queues */
764 pDev->event_queue = fifo_init (20);
765 if (NULL == pDev->event_queue)
766 {
767 DXS_RETURN(DXS_statusMsgQueueCreatError);
768 }
769 pDev->cmd_obx_queue = fifo_init (64);
770 if (NULL == pDev->cmd_obx_queue)
771 {
772 DXS_RETURN(DXS_statusMsgQueueCreatError);
773 }
774
775 /* initialize event memory pool */
776 if (DXS_statusOk != dxs_event_pool_init(pDev))
777 {
778 DXS_RETURN(DXS_statusMpoolInitError);
779 }
780
781 /* start obx handling thread */
782 ret = dxs_outbox_handler_init(pDev);
783 if (ret != DXS_statusOk)
784 {
785 DXS_RETURN(DXS_statusObxHandlerStartError);
786 }
787 pDev->flags |= DXS_DEV_OBX_HND_INITIALIZED;
788
789 /* initialize device resources */
790 pDev->caps = dxs_caps_init(dev);
791 pDev->pcm = dxs_pcm_dev_init(dev);
792
793 if (pDev->access == DXS_ACCESS_CSI)
794 {
795 /* default configuration of CSI Master */
796 uint16_t nCSIMasterCFG =
797 (DXS_REG_CSI_M_CFG_PAUSE_DEFAULT | DXS_REG_CSI_M_CFG_PDEMUX);
798 ret = DXS_RegWrite(pDev, DXS_REG_CSI_M_CFG, nCSIMasterCFG);
799 if (ret != DXS_statusOk)
800 {
801 DXS_RETURN(ret);
802 }
803 }
804
805#ifdef DXS_FEAT_GPIO
806 pDev->gpio = DXS_GPIO_DevInit(dev);
807#endif
808
809 /* start device polling */
810 if (pDev->irqNumber != 255 &&
811 (pDev->irqNumber == -1 || dxs_interrupt_init(pDev) != DXS_statusOk))
812 {
813 dxs_polling_timer_start();
814 }
815
816 /* In IRQ as well as polling mode set the interrupt masks. */
817 ret = dxs_default_reg_init(pDev);
818 if (ret != DXS_statusOk)
819 {
820 DXS_RETURN(ret);
821 }
822
823 /* read capabilities and version from device -
824 must be after polling start or interrupt enable */
825 dxs_caps_vers_update(pDev);
826
827#ifdef DXS_FEAT_UTD
828 /* initialize UTD mutex */
829 dxs_sig_utd_mtx_init();
830#endif /* DXS_FEAT_UTD */
831
832 /* initialize channel resources -
833 must be after capabilities read */
834 for (ch = 0; ch < pDev->nChannels; ch++)
835 {
836 DXS_CHANNEL_t *pCh = &pDev->pChannel[ch];
837
838 pCh->pParent = pDev;
839 pCh->nCh = ch;
840 pCh->pcm = dxs_pcm_ch_init(pDev->nDevNum, ch);
841 pCh->sdd = DXS_SDD_ChInit(pDev->nDevNum, ch);
842 pCh->sig = dxs_sig_ch_init(pDev->nDevNum, ch);
843#ifdef DXS_FEAT_HSM
844 status = DXS_Dial_Initialise_Unprot(pCh);
845 if (status != DXS_statusOk)
846 {
847 DXS_RETURN(status);
848 }
849#endif
850#ifdef DXS_FEAT_CID
851 /* cleanup static data */
852 DXS_CID_Cleanup(pCh);
853#endif
854 pCh->ring = DXS_Ring_ResInit(pCh);
855 DXS_EventMaskSetDefault(pCh);
856 }
857
858 /* From now on process all events. */
859 dxs_outbox_handler_enable(pDev);
860
861 /* patch download sync sem */
862 sem_init(&pDev->mtxPatchDwld, 0, 0);
863 pDev->bWaitingInPatchDwld = 0;
864
865 /* DCDC HW specific init */
866 DXS_DCDC_HW_Init(pDev);
867
868 pDev->flags |= DXS_DEV_INITIALIZED;
869
870 return DXS_statusOk;
871}
872
873/**
874 Function dxs_controller_reset
875
876 \param pDev - pointer to DXS device structure
877
878 \return
879 - DXS_status_t
880*/
881int32_t dxs_controller_reset(DXS_DEVICE_t *pDev)
882{
883 int32_t ret = DXS_statusOk;
884 uint16_t nDxsRegBootCfg = 0,
885 nDxsRegBootInfo = 0,
886 nDxsRegCfg = 0;
887
888 /* Set the controller startup configuration in the Boot Configuration
889 Register to boot from ROM. */
890 nDxsRegBootCfg = DXS_REG_BCFG_ASC_ROM;
891 ret = DXS_RegWrite(pDev, DXS_REG_BCFG, nDxsRegBootCfg);
892 if (ret != DXS_statusOk)
893 {
894 /* errmsg: Setting of boot configuration register failed. */
895 ret = DXS_statusSetBootCfgErr;
896 }
897
898 /* Reset controller to start the boot. */
899 if (ret == DXS_statusOk)
900 {
901 nDxsRegCfg = DXS_REG_CFG_RST_RSTCORE|DXS_REG_CFG_8BIT_EN;
902 ret = DXS_RegWrite(pDev, DXS_REG_CFG, nDxsRegCfg);
903 if (ret != DXS_statusOk)
904 {
905 /* errmsg: Controller reset failed. */
906 ret = DXS_statusCtrlResErr;
907 }
908 }
909
910 /* Check success of the reset by reading the boot info register. */
911 if (ret == DXS_statusOk)
912 {
913 uint8_t loop = 10;
914
915 while (loop > 0)
916 {
917 struct timespec ts = {0, 2000000}; /* 2 ms */
918
919 nanosleep(&ts, NULL);
920
921 /* read the boot state indication */
922 ret = DXS_RegRead(pDev, DXS_REG_BINF, &nDxsRegBootInfo);
923
924 if ((ret == DXS_statusOk) &&
925 ((nDxsRegBootInfo & DXS_REG_BINF_BOOTSTATE_MASK) >= 0x10))
926 {
927 break;
928 }
929
930 loop--;
931 }
932
933 if (loop == 0)
934 {
935 /* errmsg: Firmware download timeout. */
936 ret = DXS_statusFwDwldTimeout;
937 }
938 }
939
940 DXS_RETURN(ret);
941}
942
943/**
944 Function dxs_caps_read
945
946 \param pDev - pointer to DXS device structure
947 \param pCap - pointer to DXS_Caps_t structure
948
949 \return
950 - DXS_status_t
951*/
952int32_t dxs_caps_read(DXS_DEVICE_t *pDev, DXS_Caps_t *pCap)
953{
954 DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
955
956 if (DXS_statusOk == dxs_caps_vers_update(pDev))
957 {
958 pCap->nChannels = pDev->nChannels;
959 pCap->nGR909 = p->fw_caps.GR909;
960 pCap->nACLM = p->fw_caps.ACLM;
961 pCap->nTTX = p->fw_caps.TTX;
962 pCap->nUTD = p->fw_caps.UTD;
963 pCap->nCID = p->fw_caps.CID;
964 pCap->nHowler = p->fw_caps.HOWLER;
965 }
966 else
967 {
968 DXS_RETURN(DXS_statusCapVersUpdateError);
969 }
970
971 return DXS_statusOk;
972}
973
974/**
975 Function dxs_vers_read
976
977 \param pDev - pointer to DXS device structure
978 \param pVersion - pointer to DXS_Version_t structure
979
980 \return
981 - DXS_status_t
982*/
983int32_t dxs_vers_read(DXS_DEVICE_t *pDev, DXS_Version_t *pVersion)
984{
985 DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
986
987 if (DXS_statusOk == dxs_caps_vers_update(pDev))
988 {
989 pVersion->device = p->dev;
990 pVersion->package = p->pack;
991
992 pVersion->fw_maj = p->fw_vers.MAJ;
993 pVersion->fw_min = p->fw_vers.MIN;
994 pVersion->fw_hfix = p->fw_vers.HF;
995 pVersion->fw_time = p->fw_vers.TIME;
996
997 pVersion->lib_ver = DXS_LIB_VERSION;
998 pVersion->api_ver = DXS_API_VERSION;
999 }
1000 else
1001 {
1002 DXS_RETURN(DXS_statusCapVersUpdateError);
1003 }
1004
1005 return DXS_statusOk;
1006}
1007
1008/**
1009 Function dxs_sleep
1010
1011 \param pDev - pointer to DXS device structure
1012 \param enable - enable
1013
1014 \return
1015 - DXS_status_t
1016*/
1017int32_t dxs_sleep(DXS_DEVICE_t *pDev, uint8_t enable)
1018{
1019 DXS_Dev_Caps_t *p;
1020 int32_t ret = DXS_statusOk;
1021
1022 if (pDev == NULL || enable > 1)
1023 {
1024 DXS_RETURN(DXS_statusInvalidParam);
1025 }
1026 p = (DXS_Dev_Caps_t *)pDev->caps;
1027
1028 if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
1029 {
1030 DXS_RETURN(DXS_statusNotInitResource);
1031 }
1032
1033 if (!(p->flag & DXS_DEV_SYS_CTRL_UPDATED))
1034 {
1035 ret = CmdRead(pDev, (uint32_t *)&p->fw_sys_ctrl, (uint32_t *)&p->fw_sys_ctrl);
1036 if (ret != DXS_statusOk)
1037 {
1038 DXS_RETURN(ret);
1039 }
1040 p->flag |= DXS_DEV_SYS_CTRL_UPDATED;
1041 }
1042
1043 /* sleep mode is not allowed for shared DCDC */
1044 if (pDev->dcdcType == DXS_DCDC_IFB12CH8 && enable)
1045 {
1046 DXS_RETURN(DXS_statusSleepModeNotAllowed);
1047 }
1048
1049 /* update command */
1050 if (enable != p->fw_sys_ctrl.SE)
1051 {
1052 p->fw_sys_ctrl.SE = enable;
1053 ret = CmdWrite(pDev, (uint32_t *)&p->fw_sys_ctrl);
1054 }
1055
1056 DXS_RETURN(ret);
1057}
1058
1059/**
1060 Check if a particular feature is supported by the device
1061
1062 \param pDev - pointer to DXS device structure
1063 \param cap - feature enumerator \ref e_DXS_DevCaps
1064
1065 \return
1066 - 1 if a featire is supported, 0 if not
1067*/
1068int32_t DXS_IsFeatureSupported(DXS_DEVICE_t *pDev, enum e_DXS_DevCaps cap)
1069{
1070 DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
1071 DXS_FW_SYS_CAPS_t *pCap = &p->fw_caps;
1072 uint32_t sys_read_caps_I1 = *((uint32_t *)pCap + 1);
1073
1074 if (sys_read_caps_I1 & (1 << cap))
1075 return 1;
1076
1077 return 0;
1078}
1079
1080/**
1081 Switch on the Charge Pump
1082
1083 \param pDev - pointer to DXS device structure
1084
1085 \return
1086 - DXS_status_t
1087*/
1088int32_t DXS_ChargePumpSwitchOn(DXS_DEVICE_t *pDev)
1089{
1090 DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
1091 DXS_FW_SYS_Control_t *pSysCtrl = &p->fw_sys_ctrl;
1092 int32_t ret = DXS_statusOk;
1093
1094 /* for IFB12CH8 apply the configuration only for the device
1095 that owns a master channel */
1096 if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
1097 {
1098 DXS_CHANNEL_t *pCh, *pChMaster;
1099 uint8_t i = 0, master_found = 0;
1100
1101 if ((pChMaster=DXS_DCDC_HW_SharedDcDcMasterChGetInt(pDev)) != NULL)
1102 {
1103 for (pCh=&pDev->pChannel[0],i=0; i < pDev->nChannels; i++, pCh++)
1104 {
1105 if (pCh == pChMaster)
1106 {
1107 master_found = 1;
1108 break;
1109 }
1110 }
1111
1112 if (!master_found)
1113 return DXS_statusOk;
1114 }
1115 }
1116
1117 if (pSysCtrl->CP_EN != 1)
1118 {
1119 pSysCtrl->CP_VOLT = DXS_FW_SYS_Control_CP_VOLT_5_0V;
1120 pSysCtrl->CP_EN = 1;
1121 ret = CmdWrite(pDev, (uint32_t *)pSysCtrl);
1122 }
1123
1124 DXS_RETURN(ret);
1125}
1126
1127#if 0
1128/**
1129 Switch off the Charge Pump
1130
1131 \param pDev - pointer to DXS device structure
1132
1133 \return
1134 - DXS_status_t
1135*/
1136int32_t DXS_ChargePumpSwitchOff(DXS_DEVICE_t *pDev)
1137{
1138 DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
1139 DXS_FW_SYS_Control_t *pSysCtrl = &p->fw_sys_ctrl;
1140 int32_t ret = DXS_statusOk;
1141
1142 /* for IFB12CH8 apply the configuration only for the device
1143 that owns a master channel */
1144 if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
1145 {
1146 DXS_CHANNEL_t *pCh, *pChMaster;
1147 uint8_t i = 0, master_found = 0;
1148
1149 if ((pChMaster=DXS_DCDC_HW_SharedDcDcMasterChGetInt(pDev)) != NULL)
1150 {
1151 for (pCh=&pDev->pChannel[0],i=0; i < pDev->nChannels; i++, pCh++)
1152 {
1153 if (pCh == pChMaster)
1154 {
1155 master_found = 1;
1156 break;
1157 }
1158 }
1159
1160 if (!master_found)
1161 return DXS_statusOk;
1162 }
1163 }
1164
1165 if (pSysCtrl->CP_EN != 0)
1166 {
1167 pSysCtrl->CP_EN = 0;
1168 ret = CmdWrite(pDev, (uint32_t *)pSysCtrl);
1169 }
1170
1171 DXS_RETURN(ret);
1172}
1173#endif /* 0 */
1174
1175/**
1176 Switch on/off Clock Failure handling
1177
1178 \param pDev - pointer to DXS device structure
1179 \param enable - 0 or 1
1180
1181 \return
1182 - DXS_status_t
1183*/
1184int32_t DXS_CfEsdSwitch (DXS_DEVICE_t *pDev, uint8_t enable)
1185{
1186 DXS_Dev_Caps_t *p;
1187 int32_t ret = DXS_statusOk;
1188 uint8_t plim;
1189
1190 if (pDev == NULL || enable > 1)
1191 {
1192 DXS_RETURN(DXS_statusInvalidParam);
1193 }
1194
1195 p = (DXS_Dev_Caps_t *)pDev->caps;
1196
1197 if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
1198 {
1199 DXS_RETURN(DXS_statusNotInitResource);
1200 }
1201
1202 if (!(p->flag & DXS_DEV_SYS_CTRL_UPDATED))
1203 {
1204 ret = CmdRead(pDev, (uint32_t *)&p->fw_sys_ctrl, (uint32_t *)&p->fw_sys_ctrl);
1205 if (ret != DXS_statusOk)
1206 {
1207 DXS_RETURN(ret);
1208 }
1209 p->flag |= DXS_DEV_SYS_CTRL_UPDATED;
1210 }
1211
1212 plim = enable ? 0 : 1;
1213
1214 if (p->fw_sys_ctrl.PLIM != plim || p->fw_sys_ctrl.SYCLKE != enable)
1215 {
1216 p->fw_sys_ctrl.PLIM = plim;
1217 p->fw_sys_ctrl.SYCLKE = enable;
1218 ret = CmdWrite(pDev, (uint32_t *)&p->fw_sys_ctrl);
1219 }
1220
1221 DXS_RETURN(ret);
1222}
1223
1224/**
1225 Get device info
1226
1227 \param pDev - pointer to DXS device structure
1228 \param pROM_id - ROM mask ID (output)
1229 \param pChannels - number of channels (output)
1230
1231 \return
1232 - DXS_status_t
1233*/
1234void DXS_DevInfoGet (DXS_DEVICE_t *pDev, uint8_t *pROM_id,
1235 uint8_t *pChannels)
1236{
1237 DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
1238
1239 *pROM_id = p->fw_vers.MAJ & 0x7f;
1240 *pChannels = p->fw_vers.CH ? 1 : 2;
1241}