diff options
author | nhcao <nhcao@marvell.com> | 2012-08-21 20:43:51 +0800 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2019-07-22 19:39:58 +0200 |
commit | cc8c8aabf008867eebbb671563b5e8d90a01c239 (patch) | |
tree | c707cb693fcc2774a410d9e721ac45f4b547c173 | |
parent | 284fc1d7f952f508977c4f198f3c36a2eaa354b8 (diff) | |
download | linux-mmp3-dell-ariel-cc8c8aabf008867eebbb671563b5e8d90a01c239.tar.gz |
audio: zsp: add IPC for frequency change
1. Add IPC for frequency change done signal.
2. Refine zsp registers names
3. add handling for frequency change, and add a test case for it.
Change-Id: I6e9c852b3c5eb25894f614087ba1a1acd65c8458
Signed-off-by: Henry Zhao <xzhao10@marvell.com>
Signed-off-by: nhcao <nhcao@marvell.com>
-rw-r--r-- | arch/arm/mach-mmp/include/mach/mmp-zsp.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-mmp/include/mach/regs-zsp.h | 36 | ||||
-rw-r--r-- | arch/arm/mach-mmp/mmp3.c | 76 | ||||
-rw-r--r-- | drivers/char/mmp_zmq.c | 10 | ||||
-rw-r--r-- | drivers/char/mmp_zsp.c | 126 |
5 files changed, 198 insertions, 52 deletions
diff --git a/arch/arm/mach-mmp/include/mach/mmp-zsp.h b/arch/arm/mach-mmp/include/mach/mmp-zsp.h index 44b64bdb9b003f..a40b8d50e840c5 100644 --- a/arch/arm/mach-mmp/include/mach/mmp-zsp.h +++ b/arch/arm/mach-mmp/include/mach/mmp-zsp.h @@ -90,6 +90,7 @@ enum ipc_client_id{ IPC_TEST_ID = 0x5, IPC_IPM_ID = 0x6, IPC_SOFT_RESET_ID = 0x7, + IPC_FREQ_DONE_ID = 0x8, IPC_MAX_NUM, }; @@ -111,6 +112,7 @@ struct mmp_zsp_platform_device *zsp_get_devop(void); int zsp_mmap_datawnd(struct vm_area_struct *vma); int zsp_set_clock_preference(u32 opmask, struct mmp_zsp_clkcfg * pcfg); +int zsp_freq_test(int dumponly); #ifdef __cplusplus } #endif diff --git a/arch/arm/mach-mmp/include/mach/regs-zsp.h b/arch/arm/mach-mmp/include/mach/regs-zsp.h index 2781e1f1448225..59f00f1ab88a50 100644 --- a/arch/arm/mach-mmp/include/mach/regs-zsp.h +++ b/arch/arm/mach-mmp/include/mach/regs-zsp.h @@ -48,8 +48,8 @@ * THE BIT DEFINES */ /* zsp boot vector */ -#define ZSP_CONFIG_SVTADDR_ZSP_SVTADDR_MSK (0xffffff << 8) -#define ZSP_CONFIG_SVTADDR_ZSP_SVTADDR_BASE 8 +#define ZSP_AUD_CTRL_REG_2_ZSP_SVTADDR_MSK (0xffffff << 8) +#define ZSP_AUD_CTRL_REG_2_ZSP_SVTADDR_BASE 8 /* ZSP halt */ #define ZSP_CONFIG_DBG_Z_HALT (1 << 4) /* ZSP external breakpoint */ @@ -125,17 +125,27 @@ /*ZSP INT_STATUS1 0x0210 ZSP INT_STATUS1 */ /*Bit(s) ZSPINT_STATUS1_RSRV_31_13 reserved */ #elif defined(CONFIG_CPU_MMP3) -#define ZSP_AUD_CONFIG_REG ZSP_REG(0x0000) -#define ZSP_TIM_13M_CLK_RES ZSP_REG(0x003C) -#define ZSP_CORE_FREQ_CHG ZSP_REG(0x0018) -#define ZSP_CORE_CLK_RES ZSP_REG(0x0028) -#define ZSP_CTRL_REG ZSP_REG(0x0054) -#define ZSP_CONFIG_SVTADDR ZSP_REG(0x0058) -#define ZSP_APB_CLK_RES ZSP_REG(0x002C) -#define ZSP_SSP_CLK_RES ZSP_REG(0x0030) -#define ZSP_SLIM_CLK_RES ZSP_REG(0x0044) -#define ZSP_SLIM_CLK_RES_2 ZSP_REG(0x0050) -#define ZSP_AUX_CORE_INT_STATUS ZSP_REG(0x0008) +#define ZSP_AUD_CONFIG ZSP_REG(0x0000) +#define ZSP_AUX_CORE_PRID ZSP_REG(0x0004) +#define ZSP_AUX_CORE_INT_ST ZSP_REG(0x0008) +#define ZSP_AUD_CORE_IPC ZSP_REG(0x000C) +#define ZSP_APPS_CORE_IPC ZSP_REG(0x0010) +#define ZSP_AUD_INT_MSK ZSP_REG(0x0014) +#define ZSP_AUD_CORE_FREQ_CHG ZSP_REG(0x0018) +#define ZSP_AUD_D1D0_WAKEUP_MSK ZSP_REG(0x001C) +#define ZSP_AUD_D1D0G_WAKEUP_MSK ZSP_REG(0x0020) +#define ZSP_AUD_D0CG2D1_ENTRY_MSK ZSP_REG(0x0024) +#define ZSP_AUD_DSA_CORE_CLK_RES ZSP_REG(0x0028) +#define ZSP_AUD_DSA_APB_CLK_RES ZSP_REG(0x002C) +#define ZSP_AUD_SSP_CLK_RES ZSP_REG(0x0030) +#define ZSP_AUD_TIM_13M_CLK_RES ZSP_REG(0x003C) +#define ZSP_AUD_TIM_32K_CLK_RES ZSP_REG(0x0040) +#define ZSP_AUD_SLIM_CLK_RES ZSP_REG(0x0044) +#define ZSP_XCORE_ADDR_TRANS ZSP_REG(0x0048) +#define ZSP_XCORE_ADDR_TRANS_CTRL ZSP_REG(0x004C) +#define ZSP_AUD_SLIM_CLK_RES_2 ZSP_REG(0x0050) +#define ZSP_AUD_CTRL_REG ZSP_REG(0x0054) +#define ZSP_AUD_CTRL_REG_2 ZSP_REG(0x0058) #define ZSP_DTCM_START 0xC6080000 #define ZSP_DATA_OFFSET 0x00000000 diff --git a/arch/arm/mach-mmp/mmp3.c b/arch/arm/mach-mmp/mmp3.c index 7956c471d9989a..49e9d8bb53d009 100644 --- a/arch/arm/mach-mmp/mmp3.c +++ b/arch/arm/mach-mmp/mmp3.c @@ -1097,7 +1097,7 @@ static void mmp_zsp_domain_on(int spd, int src, int asclk) __raw_writel(value, APMU_ISLD_DSPA_CTRL); udelay(10); /* enable dummy clocks for SRAMs */ - value = readl(APMU_ISLD_DSPA_CTRL); + value = __raw_readl(APMU_ISLD_DSPA_CTRL); value |= (0x1 << 4); __raw_writel(value, APMU_ISLD_DSPA_CTRL); udelay(300); @@ -1153,41 +1153,43 @@ static void mmp_zsp_domain_on(int spd, int src, int asclk) } aud_pwr_status.aud_pll_cnt++; + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x0, 0x4); + udelay(100); + /* switch to audio PLL, divide 1*/ + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x0, 0x30); + __raw_modify(ZSP_AUD_CORE_FREQ_CHG, 0xE, 0x0); + /* enable divider*/ + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x0, 0x8); + /* enabled core clock and release reset*/ + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x4, 0x0); + udelay(10); + __raw_modify(ZSP_AUD_CORE_FREQ_CHG, 0x0, 0x1); + udelay(10); + do { + value = readl(ZSP_AUD_CORE_FREQ_CHG); + udelay(10); + } while ((value & 0x1) != 0); + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x0, 0x3); + /* timer clock, src Audio PLL, div 12 */ - __raw_modify(ZSP_TIM_13M_CLK_RES, 0x0, 0x64); + __raw_modify(ZSP_AUD_TIM_13M_CLK_RES, 0x0, 0x64); udelay(10); /* enable and release reset*/ - __raw_modify(ZSP_TIM_13M_CLK_RES, 0x0, 0x3); + __raw_modify(ZSP_AUD_TIM_13M_CLK_RES, 0x0, 0x3); /* set SSPA to fast audio PLL with M/N divider */ - __raw_modify(ZSP_SSP_CLK_RES, 0x0, 0x30000); - __raw_modify(ZSP_SLIM_CLK_RES, 0xFFFFFFFF, 0x00100100); - __raw_modify(ZSP_SLIM_CLK_RES_2, 0x3FFFFFFF, 0xC0010002); - __raw_modify(ZSP_SLIM_CLK_RES, 0x0, 0xE); + __raw_modify(ZSP_AUD_SSP_CLK_RES, 0x0, 0x30000); + __raw_modify(ZSP_AUD_SLIM_CLK_RES, 0xFFFFFFFF, 0x00100100); + __raw_modify(ZSP_AUD_SLIM_CLK_RES_2, 0x3FFFFFFF, 0xC0010002); + __raw_modify(ZSP_AUD_SLIM_CLK_RES, 0x0, 0xE); /* config ZSP core peripherals */ - __raw_modify(ZSP_CTRL_REG, 0xFFFFFFF, 0x141B05); + __raw_modify(ZSP_AUD_CTRL_REG, 0xFFFFFFF, 0x141B05); udelay(100); - __raw_modify(ZSP_CTRL_REG, 0x0, 0x18); + __raw_modify(ZSP_AUD_CTRL_REG, 0x0, 0x18); udelay(10); aud_pwr_status.zsp_cnt++; - __raw_modify(ZSP_CORE_CLK_RES, 0x3, 0x4); - udelay(100); - /* switch to audio PLL, divide 1*/ - __raw_modify(ZSP_CORE_CLK_RES, 0x0, 0x30); - __raw_modify(ZSP_CORE_FREQ_CHG, 0xE, 0x0); - /* enable divider*/ - __raw_modify(ZSP_CORE_CLK_RES, 0x0, 0x8); - /* enabled core clock and release reset*/ - __raw_modify(ZSP_CORE_CLK_RES, 0x4, 0x3); - udelay(10); - __raw_modify(ZSP_CORE_FREQ_CHG, 0x0, 0x1); - udelay(10); - do { - value = readl(ZSP_CORE_FREQ_CHG); - udelay(10); - } while ((value & 0x1) != 0); return; } @@ -1198,21 +1200,21 @@ static void mmp_zsp_domain_halt(void) aud_pwr_status.zsp_cnt--; if (aud_pwr_status.zsp_cnt == 0) { /* reset audio peripheral */ - __raw_modify(ZSP_CORE_CLK_RES, 0x3, 0x4); + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x0, 0x4); udelay(100); /* switch to pll1*/ - __raw_modify(ZSP_CORE_CLK_RES, 0x30, 0x0); + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x30, 0x0); /* set divider 2*/ - __raw_modify(ZSP_CORE_FREQ_CHG, 0xE, 0x4); + __raw_modify(ZSP_AUD_CORE_FREQ_CHG, 0xE, 0x4); /* enable divider*/ - __raw_modify(ZSP_CORE_CLK_RES, 0x0, 0x8); + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x0, 0x8); /* enabled core clock and release reset*/ - __raw_modify(ZSP_CORE_CLK_RES, 0x4, 0x3); + __raw_modify(ZSP_AUD_DSA_CORE_CLK_RES, 0x4, 0x0); udelay(10); - __raw_modify(ZSP_CORE_FREQ_CHG, 0x0, 0x1); + __raw_modify(ZSP_AUD_CORE_FREQ_CHG, 0x0, 0x1); udelay(10); do { - value = readl(ZSP_CORE_FREQ_CHG); + value = readl(ZSP_AUD_CORE_FREQ_CHG); udelay(10); } while ((value & 0x1) != 0); } @@ -1258,18 +1260,18 @@ static void mmp_zsp_start_core(void) { int value; - writel(0x0000, ZSP_CONFIG_SVTADDR); + writel(0x0000, ZSP_AUD_CTRL_REG_2); udelay(5); - value = readl(ZSP_CTRL_REG); + value = readl(ZSP_AUD_CTRL_REG); value &= ~0x2; - writel(value, ZSP_CTRL_REG); + writel(value, ZSP_AUD_CTRL_REG); udelay(100); /* release reset */ - value = readl(ZSP_CTRL_REG); + value = readl(ZSP_AUD_CTRL_REG); value |= 0x2; - writel(value, ZSP_CTRL_REG); + writel(value, ZSP_AUD_CTRL_REG); udelay(10); } diff --git a/drivers/char/mmp_zmq.c b/drivers/char/mmp_zmq.c index d6bfb0ae5e4d14..91c265900063e4 100644 --- a/drivers/char/mmp_zmq.c +++ b/drivers/char/mmp_zmq.c @@ -2972,7 +2972,17 @@ static void zmq_diagnose_clk(u32 flags) } static void zmq_diagnoze(zmq_instance_t * pins, char op) { + int cnt; + int ret; + u32 value; switch (op) { + case 'q': + ret = 0; + for (cnt = 0; cnt < 100; cnt++) { + ret = zsp_freq_test(ret); + udelay(200); + } + break; case 'a': zmq_diagnose_session_control(pins); break; diff --git a/drivers/char/mmp_zsp.c b/drivers/char/mmp_zsp.c index 8fd754241a0a40..a37425f791082b 100644 --- a/drivers/char/mmp_zsp.c +++ b/drivers/char/mmp_zsp.c @@ -51,7 +51,6 @@ #define IPC_ICR 0x000C #define IPC_IIR 0x0010 - #define pzipc_readl(pszp, off) \ __raw_readl(pzsp->_ipc_regs_base + (off)) #define pzipc_writel(pzsp, off, v) \ @@ -95,6 +94,7 @@ typedef struct { struct mutex _floadlock; volatile bool _ready; volatile bool _zspup; + volatile bool _zspfreqdone; zsp_ipc_cft_t _ipcmap[IPC_MAX_NUM]; void *pbuffer; void *pbuffer_aligned; @@ -105,7 +105,8 @@ typedef struct { static zsp_device_t gs_zsp = { NULL, NULL, false, NULL, NULL, NULL, - 0, 0, 0, 0, NULL, 0, 0, 0, NULL, 0, 0, -1, {0}, {{1},}, false, false, + 0, 0, 0, 0, NULL, 0, 0, 0, NULL, 0, 0, -1, {0}, + {{1},}, false, false, false, { /*client id */ /* interrupt bit*/ /* handler */ {IPC_HANDSHAKE_ID, IPC_INTERRUPT_BIT_0_0, NULL}, @@ -115,6 +116,8 @@ static zsp_device_t gs_zsp = { {IPC_PORT_FLOWCONTROL_ID, IPC_INTERRUPT_BIT_0_4, NULL}, {IPC_TEST_ID, IPC_INTERRUPT_BIT_0_5, NULL}, {IPC_IPM_ID, IPC_INTERRUPT_BIT_2_9, NULL}, + {IPC_SOFT_RESET_ID, IPC_INTERRUPT_BIT_3_10, NULL}, + {IPC_FREQ_DONE_ID, IPC_INTERRUPT_BIT_0_6, NULL}, /* TBD */ }, NULL, NULL, 0, 0, false @@ -185,6 +188,14 @@ static irqreturn_t zsp_ap_handshake_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t zsp_freq_done_isr(int irq, void *dev_id) +{ + zsp_device_t * pzsp = (zsp_device_t *)dev_id; + + pzsp->_zspfreqdone = true; + + return IRQ_HANDLED; +} static irqreturn_t zsp_dmem_req_isr(int irq, void *dev_id) { zsp_device_t * pzsp; @@ -383,6 +394,12 @@ static int zsp_doreset(struct platform_device *pdev, int timeout_ms) { return -EINVAL; } + ret = pzipc_add_isr(IPC_FREQ_DONE_ID, zsp_freq_done_isr); + if (PZIPC_RC_OK != ret) { + printk(KERN_ERR "%s: cannot register freq_done\n", __func__); + return -EINVAL; + } + pzsp->_zspup = false; zsp_start_core(pzsp); @@ -808,6 +825,111 @@ static void __exit zsp_exit(void) } +#define __raw_modify(addr, toclear, toset) \ + do { \ + volatile unsigned int tval; \ + tval = __raw_readl(addr); \ + tval &= ~toclear; \ + tval |= toset; \ + __raw_writel(tval, (addr)); \ + tval = __raw_readl(addr); \ + udelay(100); \ + } while (0) + +void dump_aux_regs(void) +{ + u32 value; + + value = readl(ZSP_AUD_CONFIG); + printk(KERN_ERR "ZSP_AUD_CONFIG: 0x%08X\n", value); + + value = readl(ZSP_AUX_CORE_PRID); + printk(KERN_ERR "ZSP_AUX_CORE_PRID: 0x%08X\n", value); + + value = readl(ZSP_AUX_CORE_INT_ST); + printk(KERN_ERR "ZSP_AUX_CORE_INT_ST: 0x%08X\n", value); + + value = readl(ZSP_AUD_CORE_IPC); + printk(KERN_ERR "ZSP_AUD_CORE_IPC: 0x%08X\n", value); + + value = readl(ZSP_APPS_CORE_IPC); + printk(KERN_ERR "ZSP_APPS_CORE_IPC: 0x%08X\n", value); + + value = readl(ZSP_AUD_INT_MSK); + printk(KERN_ERR "ZSP_AUD_INT_MSK: 0x%08X\n", value); + + value = readl(ZSP_AUD_CORE_FREQ_CHG); + printk(KERN_ERR "ZSP_AUD_CORE_FREQ_CHG: 0x%08X\n", value); + + value = readl(ZSP_AUD_D1D0_WAKEUP_MSK); + printk(KERN_ERR "ZSP_AUD_D1D0_WAKEUP_MSK: 0x%08X\n", value); + + value = readl(ZSP_AUD_D1D0G_WAKEUP_MSK); + printk(KERN_ERR "ZSP_AUD_D1D0G_WAKEUP_MSK: 0x%08X\n", value); + + value = readl(ZSP_AUD_D0CG2D1_ENTRY_MSK); + printk(KERN_ERR "ZSP_AUD_D0CG2D1_ENTRY_MSK: 0x%08X\n", value); + + value = readl(ZSP_AUD_DSA_CORE_CLK_RES); + printk(KERN_ERR "ZSP_AUD_DSA_CORE_CLK_RES: 0x%08X\n", value); + + value = readl(ZSP_AUD_DSA_APB_CLK_RES); + printk(KERN_ERR "ZSP_AUD_DSA_APB_CLK_RES: 0x%08X\n", value); + + value = readl(ZSP_AUD_SSP_CLK_RES); + printk(KERN_ERR "ZSP_AUD_SSP_CLK_RES: 0x%08X\n", value); + + value = readl(ZSP_AUD_TIM_13M_CLK_RES); + printk(KERN_ERR "ZSP_AUD_TIM_13M_CLK_RES: 0x%08X\n", value); + + value = readl(ZSP_AUD_TIM_32K_CLK_RES); + printk(KERN_ERR "ZSP_AUD_TIM_32K_CLK_RES: 0x%08X\n", value); + + value = readl(ZSP_AUD_SLIM_CLK_RES); + printk(KERN_ERR "ZSP_AUD_SLIM_CLK_RES: 0x%08X\n", value); + + value = readl(ZSP_XCORE_ADDR_TRANS); + printk(KERN_ERR "ZSP_XCORE_ADDR_TRANS: 0x%08X\n", value); + + value = readl(ZSP_XCORE_ADDR_TRANS_CTRL); + printk(KERN_ERR "ZSP_XCORE_ADDR_TRANS_CTRL: 0x%08X\n", value); + + value = readl(ZSP_AUD_SLIM_CLK_RES_2); + printk(KERN_ERR "ZSP_AUD_SLIM_CLK_RES_2: 0x%08X\n", value); + + value = readl(ZSP_AUD_CTRL_REG); + printk(KERN_ERR "ZSP_AUD_CTRL_REG: 0x%08X\n", value); + + value = readl(ZSP_AUD_CTRL_REG_2); + printk(KERN_ERR "ZSP_AUD_CTRL_REG_2: 0x%08X\n\n", value); + + return; +} + +int zsp_freq_test(int dumponly) +{ + u32 value, loop; + zsp_device_t *pzsp = &gs_zsp; + + pzipc_set_interrupt(IPC_TEST_ID); + + loop = 1000; + while (loop > 0) { + if (pzsp->_zspfreqdone) { + pzsp->_zspfreqdone = false; + value = __raw_readl(ZSP_AUD_DSA_CORE_CLK_RES); + break; + } + loop--; + udelay(100); + } + if (loop == 0) + return 1; + + return 0; +} +EXPORT_SYMBOL(zsp_freq_test); + module_init(zsp_init); module_exit(zsp_exit); |