blob: c1859eb60a468cf807caba98d10d76bb9b8beeac [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Driver for Audio DSP.
4 *
5 * Copyright (C) 2023 ASRMicro
6 *
7 * Author: Wang Yan <yjgwang@asrmicro.com>
8 */
9
10
11/******************************************************************************
12* MODULE IMPLEMENTATION FILE
13*******************************************************************************
14* Title: Driver for ADSP in AP subsystem
15*
16* Filename: adsp.c
17*
18* Authors: Wang Yan
19*
20* Description: Driver file for ADSP.
21*
22* Last Updated:
23*
24* Notes:
25******************************************************************************/
26
27
28/******************************************************************************
29* Include files
30******************************************************************************/
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/delay.h>
35#include <linux/of_device.h>
36#include <linux/uaccess.h>
37#include <linux/proc_fs.h>
38#include <linux/fs.h>
39#include <linux/debugfs.h>
40#include <linux/gpio.h>
41#include <linux/regulator/consumer.h>
42#include <linux/pinctrl/consumer.h>
43#include <linux/platform_device.h>
44#include <linux/mutex.h>
45#include <linux/of.h>
46#include <linux/of_gpio.h>
47#include <asm/io.h>
48#include <linux/interrupt.h>
49#include <linux/cputype.h>
50#include <linux/cdev.h>
51#include <linux/device.h>
52#include <linux/ioctl.h>
53#include <linux/vmalloc.h>
54#include <linux/irq.h>
55#include <linux/of_irq.h>
56#include <linux/of_platform.h>
57#include <linux/kthread.h>
58#include <linux/dma-mapping.h>
59#include <linux/bug.h>
60#include <asm/cacheflush.h>
61#include "adsp.h"
62#include "adsp_ve.h"
63
64
65/******************************************************************************
66* Macro definitions
67******************************************************************************/
68#define ADSP_PRINT_IPC 0
69
70#define IPC_MAX_CMD_LENGTH 128
71
72#define MIN(x, y) ((x < y) ? x : y)
73
74#define IPC_SUB_OPCODE( OPCODE ) ((OPCODE) & 0x3F)
75#define IPC_SET_ID( OPCODE ) ((UINT16)(((OPCODE) >> IPC_HEADER_SETID_BITNUM) & 0x3))
76#define IPC_DATA_BIT( OPCODE ) ((UINT16)(((OPCODE) >> IPC_HEADER_DATA_BITNUM) & 0x1))
77#define IPC_OPCODE(SET_ID, SUB_OPCODE) ((SET_ID << IPC_HEADER_SETID_BITNUM) | SUB_OPCODE)
78
79#define IPC_COMPOSE_HEADER( SetID, SubSet, Urgent, Data, Long ) ((UINT16)( \
80 (((UINT16)(SetID)) << IPC_HEADER_SETID_BITNUM) | \
81 (((UINT16)(SubSet)) << IPC_HEADER_SUBSET_BITNUM) | \
82 (((UINT16)(Data)) << IPC_HEADER_DATA_BITNUM)))
83
84#define IPC_COMPOSE_DATA_HEADER( ChID, CopyFlag, DataLen ) (((UINT32)(DataLen)) << 16)
85
86
87typedef struct AdspRingCtl {
88 /* TX ring buffer for CP , CP write , AP read */
89 unsigned int cp_wptr;
90 unsigned int ap_rptr;
91
92 /* RX ring buffer for CP , AP write , CP read */
93 unsigned int ap_wptr;
94 unsigned int cp_rptr;
95
96 /* physical address from AP's pespective*/
97 unsigned int rxring_base;
98 unsigned int txring_base;
99
100 unsigned int unitsz;
101 unsigned int unitnum;
102
103}AdspRingCtl;
104
105typedef struct AudioIpcHandle {
106 AdspRingCtl *ring_ctl;
107 unsigned int *tx_ring_buffer;
108 unsigned int *rx_ring_buffer;
109
110 unsigned int iir;
111}AudioIpcHandle;
112
113//#define ADSP_VE_ADDR (0xD6A01880)
114static void __iomem *rVe = NULL;
115
116//#define ADSP_RING_CTL_ADDR (0xD6A01000)
117static void __iomem *rRingCtrl = NULL;
118
119#define ADSP_RING_BUFFER_SIZE (1024)
120
121static unsigned int adsp_irq = 0;
122
123//platform_get_resource 0
124#define ADSP_DUMP_SQU_ADDR (0xd101c000)
125#define ADSP_DUMP_SQU_LENGTH (0x4000)
126static void __iomem *rDumpSQU = NULL;
127
128//platform_get_resource 1
129#define ADSP_DUMP_DTCM_ADDR (0xd6000000)
130#define ADSP_DUMP_DTCM_LENGTH (0x40000)
131static void __iomem *rDumpDTCM = NULL;
132
133//platform_get_resource 2
134#define ADSP_DUMP_SHM_ADDR (0xd6a00000)
135#define ADSP_DUMP_SHM_LENGTH (0x4000)
136static void __iomem *rDumpSHM = NULL;
137
138//platform_get_resource 3
139#define ITCM_ADDR (0xd6200000)
140#define ITCM_LENGTH (0x00010000)
141static void __iomem *rItcm = NULL;
142
143//platform_get_resource 4
144//#define IPC_AP2AUD_BASE 0xd401d100
145//#define APB_H2_IPC_CPU_DWR_ADDR (IPC_AP2AUD_BASE + 0x0)
146//#define APB_H2_IPC_CPU_WDR_ADDR (IPC_AP2AUD_BASE + 0x4)
147//#define APB_H2_IPC_CPU_ISRW_ADDR (IPC_AP2AUD_BASE + 0x8)
148//#define APB_H2_IPC_CPU_ICR_ADDR (IPC_AP2AUD_BASE + 0xc)
149//#define APB_H2_IPC_CPU_IIR_ADDR (IPC_AP2AUD_BASE + 0x10)
150//#define APB_H2_IPC_CPU_RDR_ADDR (IPC_AP2AUD_BASE + 0x14)
151static void __iomem *rIpcBASE = NULL;
152static void __iomem *rIpcDWR = NULL;
153static void __iomem *rIpcWDR = NULL;
154static void __iomem *rIpcISRW = NULL;
155static void __iomem *rIpcICR = NULL;
156static void __iomem *rIpcIIR = NULL;
157static void __iomem *rIpcRDR = NULL;
158
159//platform_get_resource 5
160static void __iomem *rSspaBase = NULL;
161//0xd401e178
162static void __iomem *rSspaClk = NULL;
163//0xd401e17c
164static void __iomem *rSspaFrm = NULL;
165//0xd401e180
166static void __iomem *rSspaTxd = NULL;
167//0xd401e184
168static void __iomem *rSspaRxd = NULL;
169
170//platform_get_resource 6
171//0xd6800014
172static void __iomem *rPc = NULL;
173
174//platform_get_resource 7
175//0xd6800048
176static void __iomem *rRls = NULL;
177
178//platform_get_resource 8
179//Can not platform_get_resource from dts
180//#define AP_IPC_CLK_RST (0xd4015090)
181static void __iomem *rClkRst = NULL;
182
183//platform_get_resource 9
184//0xd42828f0
185static void __iomem *rPwr = NULL;
186
187//should be ioremap earlier before adsp driver init
188#define REG_PMU_AUDIO_CLK_RES_CTRL (0xd428294c)
189static void __iomem *rClk = NULL;
190
191#define ADSP_DDR_LOAD_ADDR (0x8d80000)
192#define ADSP_DDR_LOAD_LENGTH (0x280000)
193
194#define ADSP_DDR_LOAD_ADDR_S (0x5f80000)
195#define ADSP_DDR_LOAD_LENGTH_S (0x80000)
196
197/* macro for register operation */
198#define reg_read(reg) *(volatile unsigned int *)(reg)
199#define reg_write(reg, val) *(volatile unsigned int *)(reg) = (val)
200#define reg_bit_set(reg, val) *(volatile unsigned int *)(reg) |= (1 << (val))
201#define reg_bit_clr(reg, val) *(volatile unsigned int *)(reg) &= ~(1 << (val))
202
203
204/******************************************************************************
205* Local variable definitions
206******************************************************************************/
207static AudioIpcHandle g_audio_ipc_handle = {
208 .ring_ctl = (AdspRingCtl *) 0,
209 .tx_ring_buffer = (unsigned int *)0,
210 .rx_ring_buffer = (unsigned int *)0,
211 .iir = 0
212};
213
214static struct mutex g_audio_ipc_sema;
215
216/******************************************************************************
217* function definitions
218******************************************************************************/
219static void adsp_ipc_clk_enable(void)
220{
221 //unsigned int val = 0;
222
223 //val = reg_read(rClkRst);
224 //val |= (0x3);
225 reg_write(rClkRst, 0x3);
226 return;
227}
228
229static void print_adsp_ipc_clk(void)
230{
231 unsigned int val = 0;
232
233 val = reg_read(rClkRst);
234
235 printk(KERN_INFO "reg[0x%x] = 0x%x", (unsigned int)rClkRst, val);
236}
237
238static unsigned int adsp_ipc_read_iir(void)
239{
240 reg_write(rIpcDWR, 0);//dump write on demand
241 return reg_read(rIpcIIR);
242}
243
244static void adsp_ipc_set_wdr(void)
245{
246 reg_write(rIpcWDR, 0x55AA6688);
247 return;
248}
249
250static void adsp_ipc_set_isrw(void)
251{
252 reg_bit_set(rIpcISRW, 8);
253 //reg_write(rIpcISRW, ADSP_IPC_INT_CHANNEL);
254 return;
255}
256
257static void adsp_ipc_clear(unsigned int cls)
258{
259 reg_write(rIpcICR, cls);
260 return;
261}
262
263#if 0 //keep this for test
264static unsigned int adsp_ipc_tx_available(void)
265{
266 unsigned int delta = g_audio_ipc_handle.ring_ctl->cp_wptr - g_audio_ipc_handle.ring_ctl->ap_rptr;
267
268 return g_audio_ipc_handle.ring_ctl->unitnum - delta;
269}
270#endif
271
272static unsigned int adsp_ipc_rx_available(void)
273{
274 return g_audio_ipc_handle.ring_ctl->ap_wptr - g_audio_ipc_handle.ring_ctl->cp_rptr;
275}
276
277#if 0 //keep this for test
278static void print_AdspRingCtl(void)
279{
280 if (NULL == g_audio_ipc_handle.ring_ctl) {
281 printk("g_audio_ipc_handle.ring_ctl:0x%x\n", (unsigned int)g_audio_ipc_handle.ring_ctl);
282
283 return;
284 }
285
286 printk(KERN_INFO "p_adsp_ring_ctl(0x%x)," \
287 "tx_ring_buffer:(0x%x)," \
288 "rx_ring_buffer:(0x%x)," \
289 "ap_wptr:(0x%x)," \
290 "cp_rptr:(0x%x)," \
291 "cp_wptr:(0x%x)," \
292 "ap_rptr:(0x%x)," \
293 "unitsz:(0x%x)," \
294 "unitnum:(0x%x)\n", \
295 (unsigned int)g_audio_ipc_handle.ring_ctl, \
296 (unsigned int)g_audio_ipc_handle.tx_ring_buffer, \
297 (unsigned int)g_audio_ipc_handle.rx_ring_buffer, \
298 g_audio_ipc_handle.ring_ctl->ap_wptr, \
299 g_audio_ipc_handle.ring_ctl->cp_rptr, \
300 g_audio_ipc_handle.ring_ctl->cp_wptr, \
301 g_audio_ipc_handle.ring_ctl->ap_rptr, \
302 g_audio_ipc_handle.ring_ctl->unitsz, \
303 g_audio_ipc_handle.ring_ctl->unitnum);
304
305 printk(KERN_INFO "rxring_base:(0x%x),txring_base:(0x%x)\n", \
306 g_audio_ipc_handle.ring_ctl->rxring_base, \
307 g_audio_ipc_handle.ring_ctl->txring_base);
308
309 return;
310}
311#endif
312
313extern void handle_audio_playback_data(u16 len, u32 *addr, u16 id);
314extern void handle_audio_record_data(u16 len, u32 *addr, u16 id);
315extern void handle_adsp_exception(void);
316extern int audio_report_adsp_pwr_to_cp(u16 onoff);
317static int b_evs_set = 0;
318static int b_adsp_pwr_on = 0;
319static int b_adsp_pm_cp = 0;
320static unsigned char sAdspVer[42];
321
322#define ENABLE_ADSP_PM 0
323#if ENABLE_ADSP_PM
324static void pwr_off_hw(void);
325static struct task_struct *adsp_pwr_off_taskref = NULL;
326static DEFINE_MUTEX(pwr_lock);
327
328static int power_off_adsp_task(void *data)
329{
330 msleep(1000);
331 pwr_off_hw();
332 if (b_adsp_pm_cp) {
333 audio_report_adsp_pwr_to_cp(0);
334 b_adsp_pm_cp = 0;
335 }
336 adsp_pwr_off_taskref = NULL;
337 return 0;
338}
339
340void start_power_off_adsp(void)
341{
342 printk(KERN_INFO "%s/%d\n", __FUNCTION__, __LINE__);
343 if (adsp_pwr_off_taskref == NULL) {
344 adsp_pwr_off_taskref = (struct task_struct *)kthread_run(power_off_adsp_task, NULL, "pwr_off_adsp");
345 }
346}
347#endif
348
349static void pwr_on_hw(void);
350static struct task_struct *adsp_pwr_on_taskref = NULL;
351
352static int power_on_adsp_task(void *data)
353{
354 pwr_on_hw();
355 audio_report_adsp_pwr_to_cp(1);
356 b_adsp_pm_cp = 1;
357 adsp_pwr_on_taskref = NULL;
358 return 0;
359}
360
361void start_power_on_adsp_for_cp(void)
362{
363 printk(KERN_INFO "%s/%d: onoff=%d\n", __FUNCTION__, __LINE__, b_adsp_pwr_on);
364 if (b_adsp_pwr_on) {
365 audio_report_adsp_pwr_to_cp(1);
366 b_adsp_pm_cp = 1;
367 return;
368 }
369 if (adsp_pwr_on_taskref == NULL) {
370 adsp_pwr_on_taskref = (struct task_struct *)kthread_run(power_on_adsp_task, NULL, "pwr_on_adsp");
371 }
372}
373
374EXPORT_SYMBOL_GPL(start_power_on_adsp_for_cp);
375
376
377void AdspIPCCmdProcess(void)
378{
379 UINT32 LocalBuf[3 + IPC_MAX_CMD_LENGTH / 4];
380 IpcSetParamsType CmdParams;
381 //IpcDataParamsType DataParams;
382 IpcDataParamsType *DataParamsPtr = 0;
383 AdspRingCtl *IpcBuf = g_audio_ipc_handle.ring_ctl;
384 UINT32 IPCsizeMask = IpcBuf->unitnum - 1;
385 //UINT32 *IPCCmdBuf = (UINT32 *) IpcBuf->rxring_base;
386 UINT32 *IPCCmdBuf = g_audio_ipc_handle.rx_ring_buffer;
387 void __iomem *rData = NULL;
388
389 //printk("rxring_base= 0x%x, cp_rptr 0x%x\n", IpcBuf->rxring_base, IpcBuf->cp_rptr);
390
391 while (IpcBuf->ap_wptr != IpcBuf->cp_rptr) {
392 UINT32 CopyLen;
393 int i, SetID;
394 UINT32 LocalOut = IpcBuf->cp_rptr;
395 union {
396 IpcCmdMsgHeaderType Cmd;
397 UINT32 Value;
398 } CmdHeader;
399
400 CmdHeader.Value = IPCCmdBuf[IPCsizeMask & LocalOut];
401
402 CopyLen = (sizeof(CmdHeader) + CmdHeader.Cmd.UserLength + 3) >> 2;
403 for (i = 0; i < MIN(CopyLen, sizeof(LocalBuf) / 4); i++) {
404 LocalBuf[i] = IPCCmdBuf[IPCsizeMask & LocalOut];
405 LocalOut++;
406 }
407 IpcBuf->cp_rptr = LocalOut;
408
409 //Check Msg header
410 if (!CmdHeader.Cmd.Header) {
411 printk(KERN_INFO "%s/%d: ADSP IPC CMD Header is NULL\n", __FUNCTION__, __LINE__);
412 handle_adsp_exception();
413 return;
414 }
415
416 //Parser Msg header & DataParamsPtr
417 CmdParams.SubOpcode = CmdHeader.Cmd.Header;
418 CmdParams.CmdMsgLength = CmdHeader.Cmd.UserLength;
419 CmdParams.CmdMsgPtr = &LocalBuf[1];
420 DataParamsPtr = 0;
421 if (IPC_DATA_BIT( CmdParams.SubOpcode )) {
422 DataParamsPtr = (IpcDataParamsType *)&LocalBuf[1];
423
424 CmdParams.CmdMsgPtr += sizeof(IpcDataParamsType) / sizeof(UINT32); //Msg skip IpcDataParamsType
425 CmdParams.CmdMsgLength -= sizeof(IpcDataParamsType);
426 }
427
428 //get SetID & subopcode
429 SetID = IPC_SET_ID( CmdParams.SubOpcode );
430 //CmdParams.SubOpcode = IPC_SUB_OPCODE( CmdParams.SubOpcode );
431
432#if ADSP_PRINT_IPC
433 printk("Receive: SetId:0x%x, SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.8x|%.8x|%.8x|%.8x|\n",
434 SetID, CmdParams.SubOpcode, CmdParams.CmdMsgLength,
435 LocalBuf[1], LocalBuf[2], LocalBuf[3], LocalBuf[4]);
436#endif
437
438#if 0
439 //Process subopcode
440 if (DataParamsPtr) { //for data channel
441 UINT8 *p = NULL;
442 //printk(KERN_INFO "%s/%d: 0x%x|%d\n", __FUNCTION__, __LINE__, (unsigned int)DataParamsPtr->Ptr, DataParamsPtr->Length);
443 rData = ioremap_nocache((unsigned int)DataParamsPtr->Ptr, DataParamsPtr->Length);
444 if (!rData) {
445 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
446 return;
447 }
448 p = (UINT8 *)rData;
449 printk(KERN_INFO "Receive: SubOpcode:0x%.4x len:%d data:|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|\n", \
450 CmdParams.SubOpcode, DataParamsPtr->Length, \
451 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++, \
452 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++);
453
454 //Process data
455 }
456#endif
457
458 switch (CmdParams.SubOpcode) {
459#if ENABLE_ADSP_PM
460 case POWER_OFF_REQ:
461 {
462 UINT16 *p = (UINT16 *)&LocalBuf[1];
463 printk("%s/%d: POWER_OFF_REQ: SubOpcode:0x%x\n", __FUNCTION__, __LINE__, CmdParams.SubOpcode);
464 if (b_adsp_pwr_on) {
465 start_power_off_adsp();
466 }
467 break;
468 }
469#endif
470 case DATA_REQ:
471 {
472 UINT16 *p = (UINT16 *)&LocalBuf[1];
473 //printk("%s/%d: DATA_REQ: StreamID:%d, DataLen:0x%x, DataAddr:0x%x\n", __FUNCTION__, __LINE__, p[0], p[1], LocalBuf[2]);
474 handle_audio_playback_data(p[1], (u32 *)LocalBuf[2], p[0]);
475 break;
476 }
477
478 case RECORD_DATA:
479 {
480 UINT16 *p = (UINT16 *)&LocalBuf[1];
481 //printk("%s/%d: RECORD_DATA: Length:0x%x, Ptr:0x%x, StreamID:%d\n", __FUNCTION__, __LINE__, p[1], LocalBuf[2], p[4]);
482 handle_audio_record_data(p[1], (u32 *)LocalBuf[2], p[4]);
483 break;
484 }
485
486 case VOICE_DEBUG_CONTROL:
487 {
488 if (!b_evs_set) {
489 memcpy(sAdspVer, CmdParams.CmdMsgPtr, 40);
490 sAdspVer[40] = '\0';
491 printk(KERN_INFO "ADSP Version: %s\n", sAdspVer);
492 b_evs_set = 1;
493 }
494 break;
495 }
496
497 case ADSP_EXCEPTION:
498 {
499 UINT8 *p = NULL;
500 printk("%s/%d: ADSP report exception\n", __FUNCTION__, __LINE__);
501 if (DataParamsPtr) { //for data channel
502 rData = ioremap_nocache((unsigned int)DataParamsPtr->Ptr, DataParamsPtr->Length);
503 if (!rData) {
504 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
505 return;
506 }
507 p = (UINT8 *)rData;
508 for (i = 0; i < (DataParamsPtr->Length + 15) / 16; i++) {
509#if 0
510 printk(KERN_INFO "|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|\n", \
511 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++, \
512 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++);
513#else
514 printk(KERN_INFO "|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|\n", \
515 *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7), \
516 *(p+8), *(p+9), *(p+10), *(p+11), *(p+12), *(p+13), *(p+14), *(p+15));
517 p += 16;
518#endif
519 }
520 handle_adsp_exception();
521 }
522 break;
523 }
524
525 default:
526 break;
527 }
528
529 if (DataParamsPtr) { //for data channel
530 if (rData) {
531 iounmap(rData);
532 }
533 }
534 }
535}
536
537//int gIpcIntDebug = 0;
538static irqreturn_t adsp_ipc_int_handler(int data, void *dev_id)
539{
540 //printk(KERN_INFO "%s:%d: \n", __FUNCTION__, __LINE__);
541 g_audio_ipc_handle.iir = adsp_ipc_read_iir();
542 adsp_ipc_clear(g_audio_ipc_handle.iir);
543 return IRQ_WAKE_THREAD;
544}
545
546static int b_phase2_inited = 0;
547static int adsp_ipc_init_phase2(void);
548irqreturn_t adsp_ipc_hisr(int irq, void *dev_id)
549{
550 unsigned int avail;
551
552 //print_AdspRingCtl();
553 //printk("adsp_ipc_hisr, g_audio_ipc_handle.iir:0x%x\n", g_audio_ipc_handle.iir);
554
555 if (!b_phase2_inited) {
556 b_phase2_inited = adsp_ipc_init_phase2();
557
558 if (!b_phase2_inited) {
559 return IRQ_HANDLED;
560 }
561 }
562
563 //unsigned int ipc_rdr = adsp_ipc_read_rdr();
564
565 avail = adsp_ipc_rx_available();
566
567 if (avail) {
568 AdspIPCCmdProcess();
569 }
570
571 //printk(KERN_INFO "%s/%d\n", __FUNCTION__, __LINE__);
572
573 //adsp_ipc_set_isrw();
574
575 return IRQ_HANDLED;
576}
577
578int adsp_ipc_init_phase1(void)
579{
580 int ret;
581
582 //AP ring_ctl addr is agreed in advance
583 if (!rRingCtrl) {
584 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
585 return 1;
586 }
587 g_audio_ipc_handle.ring_ctl = (AdspRingCtl *) rRingCtrl;
588
589 /*==================================================================*/
590 /* in case that CP reset,rx clear buffer and INT */
591 /*==================================================================*/
592 //adsp_ipc_clear(0xFFFFFFFF);
593
594 /*==================================================================*/
595 /* create semaphore for ring buffer */
596 /*==================================================================*/
597 mutex_init(&g_audio_ipc_sema);
598 ret = request_threaded_irq(adsp_irq, adsp_ipc_int_handler, adsp_ipc_hisr, \
599 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, \
600 "ipc_adsp2ap_int", NULL);
601 if (ret < 0) {
602 printk(KERN_INFO "%s/%d: request irq fail\n", __FUNCTION__, __LINE__);
603 return 3;
604 }
605 printk(KERN_INFO "%s/%d: ret=%d\n", __FUNCTION__, __LINE__, ret);
606
607 disable_irq(adsp_irq);
608 enable_irq(adsp_irq);
609
610 /*==================================================================*/
611 /* enable ipc clock in */
612 /*==================================================================*/
613 print_adsp_ipc_clk();
614 adsp_ipc_clk_enable();
615 print_adsp_ipc_clk();
616
617 mutex_lock(&g_audio_ipc_sema);
618
619 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
620
621 return 0;
622}
623
624static int adsp_ipc_init_phase2(void)
625{
626 //AP ring_ctl addr is from IPC reg
627 //g_audio_ipc_handle.ring_ctl = (AdspRingCtl *)adsp_ipc_read_rdr();
628 printk("%s/%d g_audio_ipc_handle.ring_ctl 0x%x\n", __FUNCTION__, __LINE__, (unsigned int)g_audio_ipc_handle.ring_ctl);
629
630 if (g_audio_ipc_handle.ring_ctl
631 && g_audio_ipc_handle.ring_ctl->rxring_base
632 && g_audio_ipc_handle.ring_ctl->txring_base) {
633
634 g_audio_ipc_handle.rx_ring_buffer = ioremap_nocache(g_audio_ipc_handle.ring_ctl->rxring_base, ADSP_RING_BUFFER_SIZE);
635 if (NULL == g_audio_ipc_handle.rx_ring_buffer) {
636 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
637 return 0;
638 }
639
640 g_audio_ipc_handle.tx_ring_buffer = ioremap_nocache(g_audio_ipc_handle.ring_ctl->txring_base, ADSP_RING_BUFFER_SIZE);
641 if (NULL == g_audio_ipc_handle.tx_ring_buffer) {
642 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
643 return 0;
644 }
645
646 mutex_unlock(&g_audio_ipc_sema); // after Adsp report the Version report, CP can send the IPC to Adsp
647 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
648 return 1;
649 }
650 else {
651 printk("adsp_ipc_init_phase1 Do Not Excute\n");
652 }
653
654 return 0;
655}
656
657static int PackIpcMsg(
658 UINT32 *Buf,
659 IpcSetIDType SetId,
660 IpcSetParamsType *IpcMsgParams,
661 IpcDataParamsType *IpcDataParams)
662{
663 Word32 CopyLen = 1;
664 Word32 MsgLen = (IpcMsgParams->CmdMsgLength + 1) >> 1;
665 {
666 union {
667 IpcCmdMsgHeaderType Msg;
668 UINT32 Value;
669 } IpcHeader;
670
671 IpcHeader.Msg.Header = IPC_COMPOSE_HEADER( SetId, IpcMsgParams->SubOpcode, 0, (IpcDataParams ? 1 : 0), 0 );
672 IpcHeader.Msg.UserLength = IpcMsgParams->CmdMsgLength * 2 + (IpcDataParams ? sizeof(IpcDataParamsType) : 0); //UserLength in bytes, without header size
673 *Buf++ = IpcHeader.Value; //32bit operation
674 }
675
676 if (IpcDataParams) {
677 *Buf++ = *((UINT32 *)(IpcDataParams)); // copy data header : ChId, CopyFlag and Length
678 *Buf++ = (UINT32)(IpcDataParams->Ptr); // Copy Ptr
679 CopyLen += 2;
680 }
681
682 CopyLen += MsgLen;
683 memcpy((short *)Buf, (short *)IpcMsgParams->CmdMsgPtr, MsgLen * 4);
684 return CopyLen;
685}
686
687IpcReturnCodeType IpcSendAdspMessageData(
688 IpcSetIDType SetId,
689 IpcSetParamsType *IpcMsgParams,
690 IpcDataParamsType *IpcDataParams)
691{
692 AdspRingCtl *IpcBuf = g_audio_ipc_handle.ring_ctl;
693 // IPCRegType *IpcReg = (IPCRegType *)(BX2_CP_IPC_BASE) ;
694 UINT32 LocalBuf[3 + IPC_MAX_CMD_LENGTH / 4];
695 //UINT32 currIMASK;
696 UINT32 CopyLen = PackIpcMsg(LocalBuf, SetId, IpcMsgParams, IpcDataParams);
697 IpcReturnCodeType ret = IPC_OK;
698
699 //UINT16 *p = (UINT16 *)LocalBuf;
700
701 //printk(KERN_INFO "%s/%d\n", __FUNCTION__, __LINE__);
702
703 if (!b_phase2_inited) {
704 printk(KERN_INFO "%s/%d: Adsp IPC is not ready\n", __FUNCTION__, __LINE__);
705 return IPC_ERROR;
706 }
707
708 //printk(KERN_INFO "CopyLen:%d, data:|%.4x %.4x|%.4x %.4x|%.4x %.4x|%.4x %.4x|%.4x %.4x|\n",
709 //CopyLen, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
710
711 //atom operation
712 mutex_lock(&g_audio_ipc_sema);
713
714 if ((IpcBuf->cp_wptr - IpcBuf->ap_rptr + CopyLen) <= IpcBuf->unitnum) { //enough space to fill
715 UINT32 IPCsizeMask = IpcBuf->unitnum - 1;
716 UINT32 Windex = IpcBuf->cp_wptr & IPCsizeMask;
717 //UINT32 *IPCMsgMEM = (UINT32 *)IpcBuf->txring_base;
718 UINT32 *IPCMsgMEM = g_audio_ipc_handle.tx_ring_buffer;
719 int i;
720 for (i = 0; i < CopyLen; i++) {
721 IPCMsgMEM[Windex++] = LocalBuf[i];
722 Windex &= IPCsizeMask;
723 }
724 IpcBuf->cp_wptr += CopyLen;
725 //for ARM use DSB, ISB before trigger int to DSP !!!!!!!!!!!!.
726 //issue_sync_barrier
727 //NOP
728 //DSB
729 //ISB
730 //NOP
731 //BX LR
732 __asm__ __volatile__ ("ISB");
733 __asm__ __volatile__ ("DSB"); //make sure the data is ready before DSP is informed.
734
735 //send IPC INT to Adsp
736 adsp_ipc_set_wdr();
737 adsp_ipc_set_isrw();
738 }
739 else {
740 printk("Send Adsp IPC CMD Overflow\n");
741 ret = IPC_MSG_QUEUE_OVERFLOW;
742 }
743
744 mutex_unlock(&g_audio_ipc_sema);
745 //printk(KERN_INFO "%s/%d Done.\n\n", __FUNCTION__, __LINE__);
746 return ret;
747}
748
749
750/******************************************************************************
751* Macro definitions
752******************************************************************************/
753//in short
754#define VOICE_START_COMMAND_LENGTH 7
755#define ADSP_SET_COMMAND_LENGTH 32
756
757
758/******************************************************************************
759* Local variable definitions
760******************************************************************************/
761static int is_adsp_inited = 0;
762static int is_dump_full_ddr = 0;
763
764int ap_send_adsp(u16 *msg, int msglen, int sub_cmd )
765{
766 IpcSetIDType SetId = 0;
767 IpcSetParamsType CmdParams;
768 IpcDataParamsType DataParams;
769 UINT8 CmdMsg[128] = { 0 };
770
771 //printk(KERN_INFO "send cmd to adsp\n");
772
773 memset(&CmdParams, 0, sizeof(IpcSetParamsType));
774 memset(&DataParams, 0, sizeof(IpcDataParamsType));
775
776 if (!is_adsp_inited) {
777 printk(KERN_INFO "%s/%d: adsp is not ready\n", __FUNCTION__, __LINE__);
778 return -EFAULT;
779 }
780
781#if ENABLE_ADSP_PM
782 mutex_lock(&pwr_lock);
783
784 if (!b_adsp_pwr_on) {
785 pwr_on_hw();
786 }
787
788 mutex_unlock(&pwr_lock);
789#endif
790
791 CmdParams.SubOpcode = sub_cmd;
792 CmdParams.CmdMsgLength = msglen;
793 if (CmdParams.CmdMsgLength < ADSP_SET_COMMAND_LENGTH * 2 - 3) {
794 if (DATA_INDICATION == sub_cmd) {
795 memcpy(CmdMsg, msg + sizeof(IpcDataParamsType) / 2, 2);
796 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
797 CmdParams.SubOpcode |= (0x1 << IPC_HEADER_DATA_BITNUM);
798 memcpy(&DataParams, msg, sizeof(IpcDataParamsType));
799#if ADSP_PRINT_IPC
800 printk(KERN_INFO "SetId:0x%x, SubOpcode:0x%x, CmdMsgLength:%d, DataParams.Length:0x%.4x, DataParams.Ptr:0x%.8x, CmdMsgPtr:0x%x\n",
801 SetId, CmdParams.SubOpcode, CmdParams.CmdMsgLength,
802 DataParams.Length, DataParams.Ptr, ((UINT16 *)CmdParams.CmdMsgPtr)[0]);
803#endif
804 IpcSendAdspMessageData(SetId, &CmdParams, &DataParams);
805 }
806 else {
807 memcpy(CmdMsg, msg, msglen * 2);
808 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
809#if ADSP_PRINT_IPC
810 printk(KERN_INFO "SetId:0x%x, SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.8x|%.8x|%.8x|%.8x|\n",
811 SetId, CmdParams.SubOpcode, CmdParams.CmdMsgLength,
812 CmdParams.CmdMsgPtr[0], CmdParams.CmdMsgPtr[1], CmdParams.CmdMsgPtr[2], CmdParams.CmdMsgPtr[3]);
813#endif
814 IpcSendAdspMessageData(SetId, &CmdParams, NULL);
815 }
816
817 return 0;
818 }
819 return -EFAULT;
820
821}
822
823EXPORT_SYMBOL_GPL(ap_send_adsp);
824
825
826/******************************************************************************
827* Macro definitions
828******************************************************************************/
829//#define AUDIODEBUG_LOG
830
831typedef unsigned short ApplicationID;
832typedef unsigned int IPC_DataChannelNumber;
833
834typedef struct {
835 unsigned short opCode;
836 unsigned short length;
837 unsigned char *pipe;
838}IPC_CmdMsgParams;
839
840typedef struct {
841 unsigned short setID;
842 unsigned short subOpCode;
843 bool allSubOpCodes;
844}OpCodeParams;
845
846typedef struct {
847 unsigned short opCode;
848 unsigned short cmdLength;
849 unsigned short *cmdData;
850}IPC_Command;
851
852typedef struct {
853 unsigned int dataChannelID;
854 unsigned int copyMode;
855 unsigned short dataSize;
856 unsigned int *dataSrcPtr;
857 unsigned int *dataDestPtr;
858}IPC_DataStructToSend;
859
860typedef struct {
861 unsigned int *dataPtr;
862 unsigned short dataSize;
863 unsigned int dataChannelID;
864}IPC_DataStructReceived;
865
866
867/******************************************************************************
868* Local variable definitions
869******************************************************************************/
870static int is_1901_E = 0;
871static int is_pmu_clk_inited = 0;
872
873
874/******************************************************************************
875* functions for load adsp
876******************************************************************************/
877#define ADSP_BIN_NAME_1 "/data/adsp.bin"
878#define ADSP_BIN_NAME_E "/lib/firmware/adsp.bin"
879#define ADSP_BIN_NAME_S "/lib/firmware/adsp_s.bin"
880#define ADSP_READ_SIZE (0x10000)
881
882#define ADSP_CHECK_IMAGE 1
883#if ADSP_CHECK_IMAGE
884#define ADSP_CHECK_SIZE (0x1000)
885#define ADSP_CHECK_COUNT 5
886#endif
887
888int enable_pmu_audio_clk(void)
889{
890 if (is_pmu_clk_inited) {
891 return 0;
892 }
893
894 if (!rClk) {
895 rClk = ioremap_nocache(REG_PMU_AUDIO_CLK_RES_CTRL, 4);
896 if (!rClk) {
897 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
898 return 1;
899 }
900 }
901
902 reg_write(rClk, reg_read(rClk) & ~8); //put bx2 in reset
903 reg_bit_set(rClk, 19); //bypass repaire
904 reg_bit_set(rClk, 27); //enable hw mode
905 reg_bit_set(rClk, 29); //trigger hw pwr on
906 printk(KERN_INFO "%s/%d: Done.\n", __FUNCTION__, __LINE__);
907
908 is_pmu_clk_inited = 1;
909
910 return 0;
911}
912
913static void pwr_on_hw(void)
914{
915 volatile unsigned int rdata;
916 int i;
917
918 if (b_adsp_pwr_on) {
919 return;
920 }
921
922 //Step 1 : Reset DSP
923 enable_pmu_audio_clk();
924
925 for (i = 0; i < 50; i++) {
926 printk(KERN_INFO "wait for audio power state (on) ...\n");
927 rdata = reg_read(rPwr);
928 //printk(KERN_INFO "pwr=0x%x\n", rdata);
929 if ((rdata & 0x800) != 0) {
930 break;
931 }
932 msleep(300);
933 }
934 printk(KERN_INFO "%s/%d: power on audio (hw mode) ok\n", __FUNCTION__, __LINE__);
935
936 // Step2 : AP Copy ITCM to (0xD6200000)
937 if (is_1901_E) {
938 memcpy(rItcm, __va(ADSP_DDR_LOAD_ADDR), ITCM_LENGTH);
939 }
940 else {
941 memcpy(rItcm, __va(ADSP_DDR_LOAD_ADDR_S), ITCM_LENGTH);
942 }
943
944 // Step3 : AP Set DSP PC= 0x10
945 reg_write(rPc, 0x10);
946
947 // Step4 : AP Release DSP
948 reg_bit_set(rClk, 3); //enable release audio aon reset
949 printk(KERN_INFO "%s/%d: release audio bx2 core\n", __FUNCTION__, __LINE__);
950 reg_write(rRls, 0xF); // enable axi dyn ckg
951
952 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
953 b_adsp_pwr_on = 1;
954}
955
956static void pwr_off_hw(void)
957{
958 volatile unsigned int rdata;
959 int i;
960
961 if (!b_adsp_pwr_on) {
962 return;
963 }
964
965 reg_bit_set(rClk, 27); //enable hw mode
966 printk(KERN_INFO "%s/%d: trigger power off audio (hw mode)\n", __FUNCTION__, __LINE__);
967 reg_bit_clr(rClk, 29); //trigger hw pwr off
968
969 for (i = 0; i < 50; i++) {
970 printk(KERN_INFO "wait for audio power state (off) ...\n");
971 rdata = reg_read(rPwr);
972 //printk(KERN_INFO "pwr=0x%x\n", rdata);
973 if ((rdata & 0x40) == 0) {
974 break;
975 }
976 msleep(300);
977 }
978
979 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
980 is_pmu_clk_inited = 0;
981 b_adsp_pwr_on = 0;
982}
983
984extern int audio_request_cp_down(void);
985
986static int ap_boot_adsp(void)
987{
988 struct file *fp;
989 mm_segment_t fs;
990 loff_t pos;
991 ssize_t readret;
992 unsigned char *pread;
993 void *ptr;
994
995#if ADSP_CHECK_IMAGE
996 unsigned char *pddr;
997 int b_check_fail = 0;
998 int i = 0;
999#endif
1000
1001 //Step 0 : Copy bin from Flash to DDR
1002 if (!rPc || !rRls || !rItcm) {
1003 printk(KERN_INFO "%s/%d: registers not ready for boot bx2\n", __FUNCTION__, __LINE__);
1004 return -1;
1005 }
1006
1007#if ADSP_CHECK_IMAGE
1008 for (i = 0; i < ADSP_CHECK_COUNT; i++) {
1009 pread = is_1901_E ? __va(ADSP_DDR_LOAD_ADDR) : __va(ADSP_DDR_LOAD_ADDR_S);
1010 printk(KERN_INFO "%s/%d: 0x%x\n", __FUNCTION__, __LINE__, (unsigned int)pread);
1011 b_check_fail = 0;
1012#endif
1013 fp = filp_open(ADSP_BIN_NAME_1, O_RDONLY, 0);
1014 if (IS_ERR(fp)) {
1015 if (is_1901_E) {
1016 fp = filp_open(ADSP_BIN_NAME_E, O_RDONLY, 0);
1017 }
1018 else {
1019 fp = filp_open(ADSP_BIN_NAME_S, O_RDONLY, 0);
1020 }
1021 if (IS_ERR(fp)) {
1022 printk(KERN_INFO "%s/%d: warning: open adsp bin fail, but can be ignored.\n", __FUNCTION__, __LINE__);
1023 return -2;
1024 }
1025 printk(KERN_INFO "%s/%d: load %s\n", __FUNCTION__, __LINE__, is_1901_E ? ADSP_BIN_NAME_E : ADSP_BIN_NAME_S);
1026 }
1027 else {
1028 printk(KERN_INFO "%s/%d: load %s\n", __FUNCTION__, __LINE__, ADSP_BIN_NAME_1);
1029 }
1030
1031 fs = get_fs();
1032 set_fs(KERNEL_DS);
1033
1034 pos = 0;
1035 do {
1036 readret = vfs_read(fp, pread, ADSP_READ_SIZE, &pos);
1037 //printk(KERN_INFO "read: 0x%x|%x|%x|%x| read=0x%x pos=0x%llx \n", pread[0], pread[1], pread[2], pread[3], readret, pos);
1038
1039 for (ptr = pread;
1040 (unsigned int)ptr < (unsigned int)(pread + readret);
1041 ptr += PAGE_SIZE) {
1042 flush_dcache_page(virt_to_page(ptr));
1043 }
1044
1045 pread += readret;
1046 }while (readret == ADSP_READ_SIZE);
1047
1048 printk(KERN_INFO "load adsp bin size: 0x%llx\n", pos);
1049 if (is_1901_E) {
1050 dma_sync_single_for_device(NULL, ADSP_DDR_LOAD_ADDR, ADSP_DDR_LOAD_LENGTH, DMA_FROM_DEVICE);
1051 }
1052 else {
1053 dma_sync_single_for_device(NULL, ADSP_DDR_LOAD_ADDR_S, ADSP_DDR_LOAD_LENGTH_S, DMA_FROM_DEVICE);
1054 }
1055
1056#if ADSP_CHECK_IMAGE
1057 pddr = is_1901_E ? __va(ADSP_DDR_LOAD_ADDR) : __va(ADSP_DDR_LOAD_ADDR_S);
1058
1059 pread = (char *)vmalloc(ADSP_CHECK_SIZE);
1060 if (!pread) {
1061 printk(KERN_INFO "%s/%d: vmalloc for adsp check ddr fail\n", __FUNCTION__, __LINE__);
1062 filp_close(fp, NULL);
1063 set_fs(fs);
1064 return -3;
1065 }
1066
1067 pos = 0;
1068 do {
1069 readret = vfs_read(fp, pread, ADSP_CHECK_SIZE, &pos);
1070
1071 if (memcmp(pread, pddr, readret)) {
1072 printk(KERN_INFO "adsp check ddr fail in 0x%llx, try %d more times\n", pos, ADSP_CHECK_COUNT - i - 1);
1073 b_check_fail = 1;
1074 break;
1075 }
1076
1077 pddr += readret;
1078 }while (readret == ADSP_CHECK_SIZE);
1079
1080 if (pread) {
1081 vfree(pread);
1082 }
1083#endif
1084
1085 filp_close(fp, NULL);
1086 set_fs(fs);
1087
1088#if ADSP_CHECK_IMAGE
1089 if (!b_check_fail) {
1090 printk(KERN_INFO "adsp check ddr: pass\n");
1091 break;
1092 }
1093
1094 msleep(3000);
1095}
1096
1097if (b_check_fail) {
1098 printk(KERN_INFO "adsp check ddr fail for %d times, the config of is_dump_full_ddr is %d, now forced to 1\n", i, is_dump_full_ddr);
1099 is_dump_full_ddr = 1;
1100 audio_request_cp_down();
1101 return -4;
1102}
1103#endif
1104
1105 pwr_on_hw();
1106 is_adsp_inited = 1;
1107
1108#if ENABLE_ADSP_PM
1109 msleep(1000);
1110 pwr_off_hw();
1111#endif
1112
1113 return 0;
1114}
1115
1116static int check_adsp_ddr(void)
1117{
1118 struct file *fp;
1119 mm_segment_t fs;
1120 loff_t pos;
1121 ssize_t readret;
1122 unsigned char *pread;
1123 unsigned char *pddr;
1124
1125 pread = is_1901_E ? __va(ADSP_DDR_LOAD_ADDR) : __va(ADSP_DDR_LOAD_ADDR_S);
1126 printk(KERN_INFO "%s/%d: 0x%x\n", __FUNCTION__, __LINE__, (unsigned int)pread);
1127
1128 fp = filp_open(ADSP_BIN_NAME_1, O_RDONLY, 0);
1129 if (IS_ERR(fp)) {
1130 if (is_1901_E) {
1131 fp = filp_open(ADSP_BIN_NAME_E, O_RDONLY, 0);
1132 }
1133 else {
1134 fp = filp_open(ADSP_BIN_NAME_S, O_RDONLY, 0);
1135 }
1136 if (IS_ERR(fp)) {
1137 printk(KERN_INFO "%s/%d: warning: open adsp bin fail, but can be ignored.\n", __FUNCTION__, __LINE__);
1138 return -2;
1139 }
1140 printk(KERN_INFO "%s/%d: check %s\n", __FUNCTION__, __LINE__, is_1901_E ? ADSP_BIN_NAME_E : ADSP_BIN_NAME_S);
1141 }
1142 else {
1143 printk(KERN_INFO "%s/%d: check %s\n", __FUNCTION__, __LINE__, ADSP_BIN_NAME_1);
1144 }
1145
1146 pddr = is_1901_E ? __va(ADSP_DDR_LOAD_ADDR) : __va(ADSP_DDR_LOAD_ADDR_S);
1147
1148 pread = (char *)vmalloc(ADSP_CHECK_SIZE);
1149 if (!pread) {
1150 printk(KERN_INFO "%s/%d: vmalloc for adsp check ddr fail\n", __FUNCTION__, __LINE__);
1151 filp_close(fp, NULL);
1152 return -3;
1153 }
1154
1155 fs = get_fs();
1156 set_fs(KERNEL_DS);
1157
1158 pos = 0;
1159 do {
1160 readret = vfs_read(fp, pread, ADSP_CHECK_SIZE, &pos);
1161
1162 if (memcmp(pread, pddr, readret)) {
1163 printk(KERN_INFO "adsp check ddr fail in 0x%llx, the config of is_dump_full_ddr is %d, now forced to 1\n", pos, is_dump_full_ddr);
1164 is_dump_full_ddr = 1;
1165 //audio_request_cp_down(); //here cp already to be down
1166 if (pread) {
1167 vfree(pread);
1168 }
1169 filp_close(fp, NULL);
1170 set_fs(fs);
1171 return -4;
1172 }
1173
1174 pddr += readret;
1175 }while (readret == ADSP_CHECK_SIZE);
1176
1177 if (pread) {
1178 vfree(pread);
1179 }
1180
1181 filp_close(fp, NULL);
1182 set_fs(fs);
1183
1184 printk(KERN_INFO "%s/%d: pass, the config of is_dump_full_ddr is %d\n", __FUNCTION__, __LINE__, is_dump_full_ddr);
1185
1186 return 0;
1187}
1188
1189static void ap_reset_adsp(void)
1190{
1191 reg_write(rClk, reg_read(rClk) & ~8); //put bx2 in reset
1192
1193 //is_adsp_inited = 1;
1194 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
1195}
1196
1197
1198/******************************************************************************
1199* functions for task
1200******************************************************************************/
1201#define CONFIG_ASR1901S_MEM_SIZE (256 * 1024 * 1024)
1202static struct task_struct *adsp_taskref = NULL;
1203extern bool cpu_is_asr190Xe(void);
1204
1205static int boot_adsp_task(void *data)
1206{
1207 //msleep(10000); //delay 10 seconds
1208 printk(KERN_INFO "%s/%d: platform is 1901%c\n", __FUNCTION__, __LINE__, is_1901_E ? 'E' : 'S');
1209
1210 if (ap_boot_adsp()) {
1211 //enable_pmu_audio_clk();
1212 return 1;
1213 }
1214 return 0;
1215}
1216
1217void start_boot_adsp(void)
1218{
1219 if (cpu_is_asr190Xe()) {
1220 is_1901_E = 1;
1221 }
1222 if ((cpu_is_asr1901_a0_plus() || cpu_is_asr1906()) && adsp_taskref == NULL) {
1223 adsp_taskref = (struct task_struct *)kthread_run(boot_adsp_task, NULL, "boot_adsp");
1224 }
1225}
1226
1227EXPORT_SYMBOL_GPL(start_boot_adsp);
1228EXPORT_SYMBOL_GPL(enable_pmu_audio_clk);
1229
1230
1231/******************************************************************************
1232* functions for task
1233******************************************************************************/
1234#define MFPR_SSPA_VALUE 0x1042
1235#define MFPR_SSPA_SET_COUNT 10
1236
1237void audio_enable_mfpr_sspa(void)
1238{
1239 volatile unsigned int rdata;
1240 int i;
1241
1242 for (i = 0; i < MFPR_SSPA_SET_COUNT; i++) {
1243 reg_write(rSspaClk, MFPR_SSPA_VALUE);
1244 rdata = reg_read(rSspaClk);
1245 if (MFPR_SSPA_VALUE == rdata) {
1246 break;
1247 }
1248 msleep(300);
1249 }
1250
1251 for (i = 0; i < MFPR_SSPA_SET_COUNT; i++) {
1252 reg_write(rSspaFrm, MFPR_SSPA_VALUE);
1253 rdata = reg_read(rSspaFrm);
1254 if (MFPR_SSPA_VALUE == rdata) {
1255 break;
1256 }
1257 msleep(300);
1258 }
1259
1260 for (i = 0; i < MFPR_SSPA_SET_COUNT; i++) {
1261 reg_write(rSspaTxd, MFPR_SSPA_VALUE);
1262 rdata = reg_read(rSspaTxd);
1263 if (MFPR_SSPA_VALUE == rdata) {
1264 break;
1265 }
1266 msleep(300);
1267 }
1268
1269 for (i = 0; i < MFPR_SSPA_SET_COUNT; i++) {
1270 reg_write(rSspaRxd, MFPR_SSPA_VALUE);
1271 rdata = reg_read(rSspaRxd);
1272 if (MFPR_SSPA_VALUE == rdata) {
1273 break;
1274 }
1275 msleep(300);
1276 }
1277}
1278
1279EXPORT_SYMBOL_GPL(audio_enable_mfpr_sspa);
1280
1281
1282/******************************************************************************
1283* functions for dump
1284******************************************************************************/
1285#define ADSP_DUMP_DDR_NAME "/data/adsp_ddr.dat"
1286#define ADSP_DUMP_SQU_NAME "/data/adsp_squ.dat"
1287#define ADSP_DUMP_DTCM_NAME "/data/adsp_dtcm.dat"
1288#define ADSP_DUMP_SHM_NAME "/data/adsp_shm.dat"
1289#define ADSP_WRITE_SIZE (0x4000)
1290
1291static void dump_memory(unsigned int type)
1292{
1293 struct file *fp;
1294 mm_segment_t fs;
1295 loff_t pos;
1296 ssize_t ret;
1297 unsigned char *pWrite;
1298 unsigned int length;
1299 int i;
1300
1301 switch (type) {
1302 case 1:
1303 printk(KERN_INFO "dump adsp ddr memory to %s\n", ADSP_DUMP_DDR_NAME);
1304 if (is_1901_E) {
1305 dma_sync_single_for_device(NULL, ADSP_DDR_LOAD_ADDR, ADSP_DDR_LOAD_LENGTH, DMA_FROM_DEVICE);
1306 pWrite = (unsigned char *)__va(ADSP_DDR_LOAD_ADDR);
1307 length = ADSP_DDR_LOAD_LENGTH;
1308 }
1309 else {
1310 dma_sync_single_for_device(NULL, ADSP_DDR_LOAD_ADDR_S, ADSP_DDR_LOAD_LENGTH_S, DMA_FROM_DEVICE);
1311 pWrite = (unsigned char *)__va(ADSP_DDR_LOAD_ADDR_S);
1312 length = ADSP_DDR_LOAD_LENGTH_S;
1313 }
1314 fp = filp_open(ADSP_DUMP_DDR_NAME, O_RDWR | O_CREAT | O_SYNC, 0644);
1315 break;
1316
1317 case 2:
1318 printk(KERN_INFO "dump adsp squ memory to %s\n", ADSP_DUMP_SQU_NAME);
1319 fp = filp_open(ADSP_DUMP_SQU_NAME, O_RDWR | O_CREAT | O_SYNC, 0644);
1320 pWrite = (unsigned char *)rDumpSQU;
1321 length = ADSP_DUMP_SQU_LENGTH;
1322 break;
1323
1324 case 3:
1325 printk(KERN_INFO "dump adsp dtcm memory to %s\n", ADSP_DUMP_DTCM_NAME);
1326#if ENABLE_ADSP_PM
1327 pwr_on_hw();
1328#endif
1329 fp = filp_open(ADSP_DUMP_DTCM_NAME, O_RDWR | O_CREAT | O_SYNC, 0644);
1330 pWrite = (unsigned char *)rDumpDTCM;
1331 length = ADSP_DUMP_DTCM_LENGTH;
1332 break;
1333
1334 case 4:
1335 printk(KERN_INFO "dump adsp shm memory to %s\n", ADSP_DUMP_SHM_NAME);
1336#if ENABLE_ADSP_PM
1337 pwr_on_hw();
1338#endif
1339 fp = filp_open(ADSP_DUMP_SHM_NAME, O_RDWR | O_CREAT | O_SYNC, 0644);
1340 pWrite = (unsigned char *)rDumpSHM;
1341 length = ADSP_DUMP_SHM_LENGTH;
1342 break;
1343
1344 default:
1345 printk(KERN_INFO "%s/%d: type invalid\n", __FUNCTION__, __LINE__);
1346 break;
1347 }
1348
1349 if (IS_ERR(fp)) {
1350 printk(KERN_INFO "%s/%d: open adsp dump file fail\n", __FUNCTION__, __LINE__);
1351 return;
1352 }
1353
1354 if (!pWrite) {
1355 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
1356 filp_close(fp, NULL);
1357 return;
1358 }
1359
1360 fs = get_fs();
1361 set_fs(KERNEL_DS);
1362
1363 //pos = 0;
1364 for (i = 0; i < length / ADSP_WRITE_SIZE; i++) {
1365 pos = fp->f_pos;
1366 ret = vfs_write(fp, pWrite, ADSP_WRITE_SIZE, &pos);
1367 //printk(KERN_INFO "write: 0x%x|%x|%x|%x| write=0x%x pos=0x%llx \n", pWrite[0], pWrite[1], pWrite[2], pWrite[3], ret, pos);
1368 fp->f_pos = pos;
1369 pWrite += ret;
1370 }
1371
1372 printk(KERN_INFO "dump adsp size: 0x%llx\n", pos);
1373
1374 set_fs(fs);
1375 filp_close(fp, NULL);
1376}
1377
1378static struct task_struct *adsp_exception_taskref = NULL;
1379
1380static int adsp_exception_task(void *data)
1381{
1382 msleep(300); //300 ms, in case CP does not receive the ADSP exception report, which can trigger CP assert
1383 ap_reset_adsp();
1384 check_adsp_ddr();
1385
1386 if (!is_dump_full_ddr) {
1387 if (is_1901_E) {
1388 memcpy(__va(ADSP_DDR_LOAD_ADDR), rDumpDTCM, ADSP_DUMP_DTCM_LENGTH);
1389 memcpy(__va(ADSP_DDR_LOAD_ADDR) + ADSP_DUMP_DTCM_LENGTH, rDumpSHM, ADSP_DUMP_SHM_LENGTH);
1390 }
1391 else {
1392 memcpy(__va(ADSP_DDR_LOAD_ADDR_S), rDumpDTCM, ADSP_DUMP_DTCM_LENGTH);
1393 memcpy(__va(ADSP_DDR_LOAD_ADDR_S) + ADSP_DUMP_DTCM_LENGTH, rDumpSHM, ADSP_DUMP_SHM_LENGTH);
1394 }
1395 }
1396
1397#if 0 //use ramp dump instead of write dump files to flash
1398 dump_memory(1);
1399 dump_memory(2);
1400 dump_memory(3);
1401 dump_memory(4);
1402#endif
1403
1404 printk(KERN_INFO "%s/%d: ADSP Version: %s\n", __FUNCTION__, __LINE__, sAdspVer);
1405
1406 return 0;
1407}
1408
1409void handle_adsp_exception(void)
1410{
1411 if ((cpu_is_asr1901_a0_plus() || cpu_is_asr1906()) && adsp_exception_taskref == NULL) {
1412 adsp_exception_taskref = (struct task_struct *)kthread_run(adsp_exception_task, NULL, "adsp_exception");
1413 }
1414}
1415
1416EXPORT_SYMBOL_GPL(handle_adsp_exception);
1417
1418
1419/******************************************************************************
1420* functions for debugfs
1421******************************************************************************/
1422#ifdef CONFIG_DEBUG_FS
1423static void *adsp_map_ddr;
1424static u32 adsp_map_len;
1425
1426static ssize_t adsp_rdp_squ_read(struct file *file, char __user *user_buf,
1427 size_t size, loff_t *ppos)
1428{
1429 int ret;
1430
1431 ret = simple_read_from_buffer(user_buf, size, ppos,
1432 rDumpSQU,
1433 ADSP_DUMP_SQU_LENGTH);
1434 return ret;
1435}
1436static const struct file_operations adsp_rdp_squ_fops = {
1437 .owner = THIS_MODULE,
1438 .open = simple_open,
1439 .read = adsp_rdp_squ_read,
1440};
1441
1442static ssize_t adsp_rdp_dtcm_read(struct file *file, char __user *user_buf,
1443 size_t size, loff_t *ppos)
1444{
1445 int ret;
1446
1447 ret = simple_read_from_buffer(user_buf, size, ppos,
1448 adsp_map_ddr,
1449 ADSP_DUMP_DTCM_LENGTH);
1450 return ret;
1451}
1452static const struct file_operations adsp_rdp_dtcm_fops = {
1453 .owner = THIS_MODULE,
1454 .open = simple_open,
1455 .read = adsp_rdp_dtcm_read,
1456};
1457
1458static ssize_t adsp_rdp_shm_read(struct file *file, char __user *user_buf,
1459 size_t size, loff_t *ppos)
1460{
1461 int ret;
1462
1463 ret = simple_read_from_buffer(user_buf, size, ppos,
1464 adsp_map_ddr + ADSP_DUMP_DTCM_LENGTH,
1465 ADSP_DUMP_SHM_LENGTH);
1466 return ret;
1467}
1468
1469static const struct file_operations adsp_rdp_shm_fops = {
1470 .owner = THIS_MODULE,
1471 .open = simple_open,
1472 .read = adsp_rdp_shm_read,
1473};
1474
1475static ssize_t adsp_rdp_ddr_read(struct file *file, char __user *user_buf,
1476 size_t size, loff_t *ppos)
1477{
1478 int ret;
1479
1480 ret = simple_read_from_buffer(user_buf, size, ppos,
1481 adsp_map_ddr,
1482 adsp_map_len);
1483 return ret;
1484}
1485static const struct file_operations adsp_rdp_ddr_fops = {
1486 .owner = THIS_MODULE,
1487 .open = simple_open,
1488 .read = adsp_rdp_ddr_read,
1489};
1490
1491#endif
1492
1493static struct dentry *adsp_control = NULL;
1494
1495static ssize_t debugfs_read(struct file *file, char __user *user_buf,
1496 size_t count, loff_t *ppos)
1497{
1498 printk(KERN_INFO "%s/%d.\n", __FUNCTION__, __LINE__);
1499 return 0;
1500}
1501
1502static ssize_t debugfs_write(struct file *file,
1503 const char __user *user_buf,
1504 size_t count, loff_t *ppos)
1505{
1506 char msg[10];
1507 int ret = 0;
1508 size_t tmp_count = 0;
1509
1510 memset(msg, 0x00, sizeof(msg));
1511 tmp_count = count;
1512
1513 if (tmp_count >= sizeof(msg)) {
1514 tmp_count = sizeof(msg) - 1;
1515 }
1516
1517 /* copy the content from user space to kernel space */
1518 ret = copy_from_user(msg, user_buf, tmp_count);
1519 if (ret) {
1520 printk(KERN_ALERT "copy from user fail \n");
1521 return -EFAULT;
1522 }
1523
1524 switch (msg[0]) {
1525 case '1': /* input command# echo 1 > /sys/kernel/debug/adsp */
1526 printk(KERN_INFO "input %c to dump adsp DDR memory to %s\n", msg[0], ADSP_DUMP_DDR_NAME);
1527 dump_memory(1);
1528 break;
1529
1530 case '2': /* input command# echo 2 > /sys/kernel/debug/adsp */
1531 printk(KERN_INFO "input %c to dump adsp SQU memory to %s\n", msg[0], ADSP_DUMP_SQU_NAME);
1532 dump_memory(2);
1533 break;
1534
1535 case '3': /* input command# echo 3 > /sys/kernel/debug/adsp */
1536 printk(KERN_INFO "input %c to dump adsp DTCM memory to %s\n", msg[0], ADSP_DUMP_DTCM_NAME);
1537 dump_memory(3);
1538 break;
1539
1540 case '4': /* input command# echo 4 > /sys/kernel/debug/adsp */
1541 printk(KERN_INFO "input %c to dump adsp share memory to %s\n", msg[0], ADSP_DUMP_SHM_NAME);
1542 dump_memory(4);
1543 break;
1544
1545 case '5': /* input command# echo 5 > /sys/kernel/debug/adsp */
1546 printk(KERN_INFO "input %c to dump all the adsp memory\n", msg[0]);
1547 dump_memory(1);
1548 dump_memory(2);
1549 dump_memory(3);
1550 dump_memory(4);
1551 break;
1552
1553 case '9': /* input command# echo 9 > /sys/kernel/debug/adsp */
1554 printk(KERN_INFO "input %c to power on adsp\n", msg[0]);
1555 pwr_on_hw();
1556 break;
1557
1558 case '0': /* input command# echo 0 > /sys/kernel/debug/adsp */
1559 printk(KERN_INFO "input %c to power off adsp\n", msg[0]);
1560 pwr_off_hw();
1561 break;
1562
1563 case 'h': /* input command# echo ? > /sys/kernel/debug/adsp */
1564 printk(KERN_INFO "\nUsage: echo <option> > /sys/kernel/debug/adsp\n");
1565 printk(KERN_INFO " 1 dump adsp DDR memory to %s\n", ADSP_DUMP_DDR_NAME);
1566 printk(KERN_INFO " 2 dump adsp SQU memory to %s\n", ADSP_DUMP_SHM_NAME);
1567 printk(KERN_INFO " 3 dump adsp DTCM memory to %s\n", ADSP_DUMP_DTCM_NAME);
1568 printk(KERN_INFO " 4 dump adsp share memory to %s\n", ADSP_DUMP_SHM_NAME);
1569 printk(KERN_INFO " 5 dump all the adsp memory\n");
1570 printk(KERN_INFO " 9 power on adsp\n");
1571 printk(KERN_INFO " 0 power off adsp\n");
1572 printk(KERN_INFO " h show help\n");
1573 break;
1574
1575 default: /* input command# */
1576 printk(KERN_INFO "input invalid.\n");
1577 break;
1578 }
1579
1580 return tmp_count;
1581}
1582
1583static const struct file_operations debugfs_ops = {
1584 .owner = THIS_MODULE,
1585 .open = simple_open,
1586 .read = debugfs_read,
1587 .write = debugfs_write,
1588};
1589
1590extern bool system_is_rdp_mode(void);
1591extern void *shm_map(phys_addr_t start, size_t size);
1592static inline int adsp_debugfs_init(void)
1593{
1594 if (cpu_is_asr190Xe()) {
1595 is_1901_E = 1;
1596 }
1597 printk(KERN_INFO "%s/%d: platform is 1901%c\n", __FUNCTION__, __LINE__, is_1901_E ? 'E' : 'S');
1598
1599 if (system_is_rdp_mode()) {
1600#ifdef CONFIG_DEBUG_FS
1601 struct dentry *adsp_dir = NULL;
1602 struct dentry *ads_buffer;
1603
1604 if (is_1901_E) {
1605 adsp_map_ddr = shm_map(ADSP_DDR_LOAD_ADDR, ADSP_DDR_LOAD_LENGTH);
1606 adsp_map_len = ADSP_DDR_LOAD_LENGTH;
1607 }
1608 else {
1609 adsp_map_ddr = shm_map(ADSP_DDR_LOAD_ADDR_S, ADSP_DDR_LOAD_LENGTH_S);
1610 adsp_map_len = ADSP_DDR_LOAD_LENGTH_S;
1611 }
1612
1613 adsp_dir = debugfs_create_dir("adsp", NULL);
1614 if (!adsp_dir || IS_ERR(adsp_dir)) {
1615 pr_err("adsp debugfs create directory failed\n");
1616 return -ENOENT;
1617 }
1618
1619 ads_buffer = debugfs_create_file("adsp_squ", 0664, adsp_dir, NULL, &adsp_rdp_squ_fops);
1620 if (!ads_buffer) {
1621 pr_err("create adsp_squ debugfs error!\n");
1622 return -ENOENT;
1623 }
1624
1625 ads_buffer = debugfs_create_file("adsp_dtcm", 0664, adsp_dir, NULL, &adsp_rdp_dtcm_fops);
1626 if (!ads_buffer) {
1627 pr_err("create adsp_dtcm debugfs error!\n");
1628 return -ENOENT;
1629 }
1630
1631 ads_buffer = debugfs_create_file("adsp_shm", 0664, adsp_dir, NULL, &adsp_rdp_shm_fops);
1632 if (!ads_buffer) {
1633 pr_err("create adsp_shm debugfs error!\n");
1634 return -ENOENT;
1635 }
1636
1637 ads_buffer = debugfs_create_file("adsp_ddr", 0664, adsp_dir, NULL, &adsp_rdp_ddr_fops);
1638 if (!ads_buffer) {
1639 pr_err("create adsp_ddr debugfs error!\n");
1640 return -ENOENT;
1641 }
1642#endif
1643 return 0;
1644 }
1645
1646 adsp_control = debugfs_create_file("adsp", S_IRUGO | S_IFREG, NULL, NULL, &debugfs_ops);
1647 if (adsp_control == NULL) {
1648 pr_err("create adsp debugfs error!\n");
1649 return -ENOENT;
1650 }
1651 else if (adsp_control == ERR_PTR(-ENODEV)) {
1652 pr_err("CONFIG_DEBUG_FS is not enabled!\n");
1653 return -ENOENT;
1654 }
1655
1656 return 0;
1657}
1658
1659static void adsp_debugfs_remove(void)
1660{
1661 if (NULL != adsp_control) {
1662 debugfs_remove_recursive(adsp_control);
1663 }
1664
1665 return;
1666}
1667
1668
1669/******************************************************************************
1670* functions for cdev
1671******************************************************************************/
1672#define AUDIO_DSP_MAGIC 'y'
1673#define ADSP_ENABLE _IO(AUDIO_DSP_MAGIC, 0x00)
1674#define ADSP_DISABLE _IO(AUDIO_DSP_MAGIC, 0x01)
1675#define ADSP_SET _IOW(AUDIO_DSP_MAGIC, 0x02, uint16_t[ADSP_SET_COMMAND_LENGTH])
1676#define ADSP_SEND_VE _IOW(AUDIO_DSP_MAGIC, 0x03, EnhanceParmsT)
1677#define ADSP_DUMP_FULL_DDR _IOR(AUDIO_DSP_MAGIC, 0x4, uint32_t)
1678#define ADSP_START_AUDIO_PATH _IOW(AUDIO_DSP_MAGIC, 0x05, uint16_t[VOICE_START_COMMAND_LENGTH + 2])
1679#define ADSP_END_AUDIO_PATH _IOW(AUDIO_DSP_MAGIC, 0x06, uint16_t[4])
1680
1681#define CTRL_BUFF_MAX_LEN 100
1682
1683static dev_t adsp_dev = 0;
1684static struct class *adsp_class;
1685static struct cdev adsp_cdev;
1686
1687
1688static long cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1689{
1690 u16 msg[CTRL_BUFF_MAX_LEN];
1691 EnhanceParmsT *pVe;
1692 IpcSetIDType SetId = 0;
1693 IpcSetParamsType CmdParams;
1694 IpcDataParamsType DataParams;
1695 UINT8 CmdMsg[128];
1696
1697 //printk(KERN_INFO "%s/%d, cmd = %d", __FUNCTION__, __LINE__, cmd);
1698
1699 memset(&CmdParams, 0, sizeof(IpcSetParamsType));
1700 memset(&DataParams, 0, sizeof(IpcDataParamsType));
1701
1702 switch (cmd) {
1703 case ADSP_ENABLE:
1704 printk(KERN_INFO "%s/%d: enable adsp\n", __FUNCTION__, __LINE__);
1705 break;
1706
1707 case ADSP_DISABLE:
1708 printk(KERN_INFO "%s/%d: disable adsp\n", __FUNCTION__, __LINE__);
1709 break;
1710
1711 case ADSP_SET:
1712 //printk(KERN_INFO "send cmd to adsp\n");
1713 if (!is_adsp_inited) {
1714 printk(KERN_INFO "%s/%d: adsp is not ready\n", __FUNCTION__, __LINE__);
1715 return -EFAULT;
1716 }
1717 if (copy_from_user(msg, (void __user *)arg, ADSP_SET_COMMAND_LENGTH * 2)) {
1718 return -EFAULT;
1719 }
1720 printk(KERN_INFO "|%.2x %.2x %.2x|%.4x %.4x|%.4x %.4x|%.4x %.4x|%.4x %.4x|\n",
1721 msg[0], msg[1], msg[2],
1722 msg[3], msg[4], msg[5], msg[6],
1723 msg[7], msg[8], msg[9], msg[10]);
1724 SetId = msg[0];
1725 CmdParams.SubOpcode = msg[1];
1726 CmdParams.CmdMsgLength = msg[2];
1727 if (CmdParams.CmdMsgLength < ADSP_SET_COMMAND_LENGTH * 2 - 3) {
1728 memcpy(CmdMsg, &msg[3], CmdParams.CmdMsgLength * 2);
1729 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
1730 printk(KERN_INFO "SetId:0x%x, SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.8x|%.8x|%.8x|%.8x|\n",
1731 SetId, CmdParams.SubOpcode, CmdParams.CmdMsgLength,
1732 CmdParams.CmdMsgPtr[0], CmdParams.CmdMsgPtr[1], CmdParams.CmdMsgPtr[2], CmdParams.CmdMsgPtr[3]);
1733 IpcSendAdspMessageData(SetId, &CmdParams, NULL);
1734 }
1735 break;
1736
1737 case ADSP_SEND_VE:
1738 printk(KERN_INFO "prepare ve for adsp\n");
1739 //AP ring_ctl addr is agreed in advance, and ve should be prepared before release adsp
1740 if (!rVe) {
1741 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
1742 return -EFAULT;
1743 }
1744 if (copy_from_user(rVe, (void __user *)arg, sizeof(EnhanceParmsT))) {
1745 return -EFAULT;
1746 }
1747 pVe = rVe;
1748 printk(KERN_INFO "%x|%x\n",
1749 pVe->VoiceParms.VoiceParmRX[1].NSRxConfig.NsParams.NoiseMatrix,
1750 pVe->VoiceParms.VoiceParmTX[0].NsTxConfig.NsParamsTx.NsParams.NoiseMatrix);
1751 break;
1752
1753 case ADSP_DUMP_FULL_DDR:
1754 printk(KERN_INFO "configure whether to dump full ddr\n");
1755 if (!is_adsp_inited) {
1756 printk(KERN_INFO "%s/%d: adsp is not ready\n", __FUNCTION__, __LINE__);
1757 return -EFAULT;
1758 }
1759 if (copy_from_user(&is_dump_full_ddr, (void __user *)arg, sizeof(int))) {
1760 return -EFAULT;
1761 }
1762 printk(KERN_INFO "is_dump_full_ddr = %x\n", is_dump_full_ddr);
1763 break;
1764
1765 case ADSP_START_AUDIO_PATH:
1766 printk(KERN_INFO "ADSP_START_VOICE_PATH\n");
1767 if (!is_adsp_inited) {
1768 printk(KERN_INFO "%s/%d: adsp is not ready\n", __FUNCTION__, __LINE__);
1769 return -EFAULT;
1770 }
1771 if (copy_from_user(msg, (void __user *)arg, (2 + VOICE_START_COMMAND_LENGTH) * 2)) {
1772 return -EFAULT;
1773 }
1774 //printk(KERN_INFO "0x%x|%x|%x|%x|%x|%x|%x|%x|%x|\n", msg[0], msg[1], msg[2], msg[3], msg[4], msg[5], msg[6], msg[7], msg[8]);
1775 SetId = 1;
1776
1777 CmdParams.SubOpcode = 0x05;
1778 CmdParams.CmdMsgLength = 4;
1779 memset(CmdMsg, 0, sizeof(CmdMsg));
1780 CmdMsg[0] = 0x06;
1781 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
1782 printk(KERN_INFO "SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|\n", \
1783 CmdParams.SubOpcode, CmdParams.CmdMsgLength, \
1784 CmdMsg[0], CmdMsg[1], CmdMsg[2], CmdMsg[3], CmdMsg[4], CmdMsg[5], CmdMsg[6], CmdMsg[7]);
1785 IpcSendAdspMessageData(SetId, &CmdParams, NULL);
1786
1787 CmdParams.SubOpcode = 0x09;
1788 CmdParams.CmdMsgLength = 2;
1789 memset(CmdMsg, 0, sizeof(CmdMsg));
1790 CmdMsg[0] = 0x01;
1791 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
1792 printk(KERN_INFO "SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|\n", \
1793 CmdParams.SubOpcode, CmdParams.CmdMsgLength, \
1794 CmdMsg[0], CmdMsg[1], CmdMsg[2], CmdMsg[3], CmdMsg[4], CmdMsg[5], CmdMsg[6], CmdMsg[7]);
1795 IpcSendAdspMessageData(SetId, &CmdParams, NULL);
1796
1797 CmdParams.SubOpcode = 0x06;
1798 CmdParams.CmdMsgLength = 2;
1799 memset(CmdMsg, 0, sizeof(CmdMsg));
1800 CmdMsg[0] = 0x01;
1801 CmdMsg[1] = 0x01;
1802 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
1803 printk(KERN_INFO "SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|\n", \
1804 CmdParams.SubOpcode, CmdParams.CmdMsgLength, \
1805 CmdMsg[0], CmdMsg[1], CmdMsg[2], CmdMsg[3], CmdMsg[4], CmdMsg[5], CmdMsg[6], CmdMsg[7]);
1806 IpcSendAdspMessageData(SetId, &CmdParams, NULL);
1807
1808 CmdParams.SubOpcode = 0x00;
1809 CmdParams.CmdMsgLength = 0x0C;
1810 memset(CmdMsg, 0, sizeof(CmdMsg));
1811 CmdMsg[0] = 0x06;
1812 CmdMsg[2] = 0x06;
1813 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
1814 printk(KERN_INFO "SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.2x %.2x %.2x %.2x|%.2x %.2x %.2x %.2x|\n", \
1815 CmdParams.SubOpcode, CmdParams.CmdMsgLength, \
1816 CmdMsg[0], CmdMsg[1], CmdMsg[2], CmdMsg[3], CmdMsg[4], CmdMsg[5], CmdMsg[6], CmdMsg[7]);
1817 IpcSendAdspMessageData(SetId, &CmdParams, NULL);
1818 break;
1819
1820 case ADSP_END_AUDIO_PATH:
1821 if (!is_adsp_inited) {
1822 printk(KERN_INFO "%s/%d: adsp is not ready\n", __FUNCTION__, __LINE__);
1823 return -EFAULT;
1824 }
1825 printk(KERN_INFO "ADSP_END_AUDIO_PATH\n");
1826 if (copy_from_user(msg, (void __user *)arg, 4 * 2)) {
1827 return -EFAULT;
1828 }
1829 printk(KERN_INFO "0x%x|%x|%x|%x|\n", msg[0], msg[1], msg[2], msg[3]);
1830 CmdParams.SubOpcode = msg[0];
1831 CmdParams.CmdMsgLength = msg[1];
1832 memcpy(CmdMsg, &msg[2], CmdParams.CmdMsgLength * 2);
1833 CmdParams.CmdMsgPtr = (UINT32 *)CmdMsg;
1834 printk(KERN_INFO "SubOpcode:0x%x, CmdMsgLength:0x%x, CmdMsg:|%.2x %.2x|\n", CmdParams.SubOpcode, CmdParams.CmdMsgLength, CmdParams.CmdMsgPtr[0], CmdParams.CmdMsgPtr[1]);
1835 IpcSendAdspMessageData(SetId, &CmdParams, NULL);
1836 break;
1837
1838 default:
1839 pr_info("Default\n");
1840 break;
1841 }
1842 return 0;
1843}
1844
1845static struct file_operations cdev_fops =
1846{
1847 .owner = THIS_MODULE,
1848 .open = simple_open,
1849 .unlocked_ioctl = cdev_ioctl,
1850};
1851
1852static int adsp_cdev_init(void)
1853{
1854 /*Allocating Major number*/
1855 if ((alloc_chrdev_region(&adsp_dev, 0, 1, "adsp_Dev")) < 0) {
1856 pr_err("Cannot allocate major number\n");
1857 return -1;
1858 }
1859 printk(KERN_INFO "%s/%d, Major = %d, Minor = %d\n", __FUNCTION__, __LINE__, MAJOR(adsp_dev), MINOR(adsp_dev));
1860
1861 /*Creating cdev structure*/
1862 cdev_init(&adsp_cdev, &cdev_fops);
1863
1864 /*Adding character device to the system*/
1865 if ((cdev_add(&adsp_cdev, adsp_dev, 1)) < 0) {
1866 pr_err("Cannot add the device to the system\n");
1867 unregister_chrdev_region(adsp_dev, 1);
1868 return -1;
1869 }
1870
1871 /*Creating struct class*/
1872 if ((adsp_class = class_create(THIS_MODULE, "adsp_class")) == NULL) {
1873 pr_err("Cannot create the struct class\n");
1874 unregister_chrdev_region(adsp_dev, 1);
1875 return -2;
1876 }
1877
1878 /*Creating device*/
1879 if ((device_create(adsp_class, NULL, adsp_dev, NULL, "audio_dsp")) == NULL) {
1880 pr_err("Cannot create the Device 1\n");
1881 class_destroy(adsp_class);
1882 unregister_chrdev_region(adsp_dev, 1);
1883 return -1;
1884 }
1885
1886 return 0;
1887}
1888
1889static void adsp_cdev_exit(void)
1890{
1891 device_destroy(adsp_class, adsp_dev);
1892 class_destroy(adsp_class);
1893 cdev_del(&adsp_cdev);
1894 unregister_chrdev_region(adsp_dev, 1);
1895 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
1896}
1897
1898
1899/******************************************************************************
1900* functions for platform_device
1901******************************************************************************/
1902static int adsp_plat_probe(struct platform_device *pdev)
1903{
1904 struct resource *res = NULL;
1905
1906 if (NULL == pdev) {
1907 printk(KERN_INFO "%s/%d: pdev is NULL.\n", __FUNCTION__, __LINE__);
1908 return -ENOENT;
1909 }
1910
1911 //MEM for dump SQU
1912 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1913 if (!res) {
1914 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
1915 return -ENXIO;
1916 }
1917 rDumpSQU = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
1918 if (!rDumpSQU) {
1919 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
1920 return -EIO;
1921 }
1922
1923 //MEM for dump DTCM
1924 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1925 if (!res) {
1926 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
1927 return -ENXIO;
1928 }
1929 rDumpDTCM = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
1930 if (!rDumpDTCM) {
1931 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
1932 return -EIO;
1933 }
1934
1935 //MEM for share memory
1936 res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
1937 if (!res) {
1938 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
1939 return -ENXIO;
1940 }
1941 rDumpSHM = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
1942 if (!rDumpSHM) {
1943 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
1944 return -EIO;
1945 }
1946 rRingCtrl = rDumpSHM + 0x1000;
1947 rVe = rDumpSHM + 0x1880;
1948
1949 if (!system_is_rdp_mode()) {
1950 //IRQ for IPC
1951 adsp_irq = platform_get_irq(pdev, 0);
1952 if (!adsp_irq) {
1953 printk(KERN_INFO "%s/%d: platform_get_irq fail\n", __FUNCTION__, __LINE__);
1954 return -ENXIO;
1955 }
1956 printk(KERN_INFO "%s/%d irq=0x%x.\n", __FUNCTION__, __LINE__, adsp_irq);
1957
1958 //MEM for ITCM
1959 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
1960 if (!res) {
1961 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
1962 return -ENXIO;
1963 }
1964 rItcm = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
1965 if (!rItcm) {
1966 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
1967 return -EIO;
1968 }
1969
1970 //Register for IPC
1971 res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
1972 if (!res) {
1973 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
1974 return -ENXIO;
1975 }
1976 rIpcBASE = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
1977 if (!rIpcBASE) {
1978 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
1979 return -EIO;
1980 }
1981 rIpcDWR = rIpcBASE;
1982 rIpcWDR = rIpcBASE + 0x4;
1983 rIpcISRW = rIpcBASE + 0x8;
1984 rIpcICR = rIpcBASE + 0xc;
1985 rIpcIIR = rIpcBASE + 0x10;
1986 rIpcRDR = rIpcBASE + 0x14;
1987
1988 //Register for SSPA
1989 res = platform_get_resource(pdev, IORESOURCE_MEM, 5);
1990 if (!res) {
1991 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
1992 return -ENXIO;
1993 }
1994 rSspaBase = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
1995 if (!rSspaBase) {
1996 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
1997 return -EIO;
1998 }
1999 rSspaClk = rSspaBase;
2000 rSspaFrm = rSspaBase + 0x4;
2001 rSspaTxd = rSspaBase + 0x8;
2002 rSspaRxd = rSspaBase + 0xc;
2003
2004 //Register for BX2
2005 res = platform_get_resource(pdev, IORESOURCE_MEM, 6);
2006 if (!res) {
2007 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
2008 return -ENXIO;
2009 }
2010 rPc = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
2011 if (!rPc) {
2012 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
2013 return -EIO;
2014 }
2015
2016 res = platform_get_resource(pdev, IORESOURCE_MEM, 7);
2017 if (!res) {
2018 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
2019 return -ENXIO;
2020 }
2021 rRls = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
2022 if (!rRls) {
2023 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
2024 return -EIO;
2025 }
2026
2027 res = platform_get_resource(pdev, IORESOURCE_MEM, 8);
2028 if (!res) {
2029 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
2030 return -ENXIO;
2031 }
2032 rClkRst = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
2033 if (!rClkRst) {
2034 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
2035 return -EIO;
2036 }
2037
2038 res = platform_get_resource(pdev, IORESOURCE_MEM, 9);
2039 if (!res) {
2040 printk(KERN_INFO "%s/%d: platform_get_resource fail\n", __FUNCTION__, __LINE__);
2041 return -ENXIO;
2042 }
2043 rPwr = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
2044 if (!rPwr) {
2045 printk(KERN_INFO "%s/%d: devm_ioremap_resource fail\n", __FUNCTION__, __LINE__);
2046 return -EIO;
2047 }
2048
2049 if (!rClk) {
2050 rClk = ioremap_nocache(REG_PMU_AUDIO_CLK_RES_CTRL, 4);
2051 if (!rClk) {
2052 printk(KERN_INFO "%s/%d: ioremap fail\n", __FUNCTION__, __LINE__);
2053 return -EIO;
2054 }
2055 }
2056 }
2057
2058 printk(KERN_INFO "squ :[%x-%x]-->[%x-%x]\ndtcm:[%x-%x]-->[%x-%x]\nitcm:[%x-%x]-->[%x-%x]\nshm :[%x-%x]-->[%x-%x]\n",
2059 ADSP_DUMP_SQU_ADDR, ADSP_DUMP_SQU_ADDR + ADSP_DUMP_SQU_LENGTH, (unsigned int)rDumpSQU, (unsigned int)rDumpSQU + ADSP_DUMP_SQU_LENGTH,
2060 ADSP_DUMP_DTCM_ADDR, ADSP_DUMP_DTCM_ADDR + ADSP_DUMP_DTCM_LENGTH, (unsigned int)rDumpDTCM, (unsigned int)rDumpDTCM + ADSP_DUMP_DTCM_LENGTH,
2061 ITCM_ADDR, ITCM_ADDR + ITCM_LENGTH, (unsigned int)rItcm, (unsigned int)rItcm + ITCM_LENGTH,
2062 ADSP_DUMP_SHM_ADDR, ADSP_DUMP_SHM_ADDR + ADSP_DUMP_SHM_LENGTH, (unsigned int)rDumpSHM, (unsigned int)rDumpSHM + ADSP_DUMP_SHM_LENGTH);
2063
2064 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
2065 return 0;
2066}
2067
2068static int adsp_plat_remove(struct platform_device *pdev)
2069{
2070 iounmap(rClk);
2071
2072 printk(KERN_INFO "%s/%d.\n", __FUNCTION__, __LINE__);
2073 return 0;
2074}
2075
2076static const struct of_device_id adsp_dt_ids[] = {
2077 { .compatible = "asr,adsp", },
2078 {},
2079};
2080MODULE_DEVICE_TABLE(of, adsp_dt_ids);
2081
2082static struct platform_driver adsp_driver = {
2083 .driver = {
2084 .name = "adsp",
2085 .owner = THIS_MODULE,
2086 .of_match_table = of_match_ptr(adsp_dt_ids),
2087 },
2088 .probe = adsp_plat_probe,
2089 .remove = adsp_plat_remove,
2090};
2091
2092
2093/******************************************************************************
2094* functions for module
2095******************************************************************************/
2096static int adspInit(void)
2097{
2098 printk(KERN_INFO "%s/%d.\n", __FUNCTION__, __LINE__);
2099
2100 if (cpu_is_asr1901_a0_plus() || cpu_is_asr1906()) {
2101 platform_driver_register(&adsp_driver);
2102 if (!system_is_rdp_mode()) {
2103 adsp_cdev_init();
2104 }
2105 adsp_debugfs_init();
2106 if (!system_is_rdp_mode()) {
2107 adsp_ipc_init_phase1();
2108 enable_pmu_audio_clk();
2109 }
2110 printk(KERN_INFO "%s/%d Done.\n", __FUNCTION__, __LINE__);
2111 }
2112
2113 return 0;
2114}
2115
2116static void adspUninit(void)
2117{
2118 printk(KERN_INFO "%s/%d.\n", __FUNCTION__, __LINE__);
2119
2120 if (cpu_is_asr1901_a0_plus() || cpu_is_asr1906()) {
2121 if (g_audio_ipc_handle.rx_ring_buffer) {
2122 iounmap(g_audio_ipc_handle.rx_ring_buffer);
2123 }
2124
2125 if (g_audio_ipc_handle.tx_ring_buffer) {
2126 iounmap(g_audio_ipc_handle.tx_ring_buffer);
2127 }
2128
2129 if (adsp_irq) {
2130 free_irq(adsp_irq, NULL);
2131 }
2132
2133 adsp_cdev_exit();
2134 adsp_debugfs_remove();
2135 }
2136}
2137
2138module_init(adspInit);
2139module_exit(adspUninit);
2140
2141MODULE_DESCRIPTION("Driver for ADSP");
2142MODULE_AUTHOR("yjgwang@asrmicro.com");
2143MODULE_LICENSE("GPL v2");