1 /*
2  * Copyright (c) 2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __INTEL_DAI_DRIVER_SSP_H__
8 #define __INTEL_DAI_DRIVER_SSP_H__
9 
10 #define SSP_IP_VER_1_0 0x10000 /* cAVS */
11 #define SSP_IP_VER_1_5 0x10500 /* ACE15 */
12 #define SSP_IP_VER_2_0 0x20000 /* ACE20 */
13 #define SSP_IP_VER_3_0 0x30000 /* ACE30 */
14 
15 /* SSP IP version defined by CONFIG_SOC*/
16 #if defined(CONFIG_SOC_SERIES_INTEL_ADSP_CAVS)
17 #define SSP_IP_VER SSP_IP_VER_1_0
18 #elif defined(CONFIG_SOC_INTEL_ACE15_MTPM)
19 #define SSP_IP_VER SSP_IP_VER_1_5
20 #elif defined(CONFIG_SOC_INTEL_ACE20_LNL)
21 #define SSP_IP_VER SSP_IP_VER_2_0
22 #elif defined(CONFIG_SOC_INTEL_ACE30)
23 #define SSP_IP_VER SSP_IP_VER_3_0
24 #else
25 #error "Unknown SSP IP"
26 #endif
27 
28 #include <stdint.h>
29 #include <zephyr/drivers/dai.h>
30 #include "dai-params-intel-ipc3.h"
31 #include "dai-params-intel-ipc4.h"
32 
33 #define DAI_INTEL_SSP_MASK(b_hi, b_lo)	\
34 	(((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo))
35 #define DAI_INTEL_SSP_SET_BIT(b, x)		(((x) & 1) << (b))
36 #define DAI_INTEL_SSP_SET_BITS(b_hi, b_lo, x)	\
37 	(((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo))
38 #define DAI_INTEL_SSP_GET_BIT(b, x) \
39 	(((x) & (1ULL << (b))) >> (b))
40 #define DAI_INTEL_SSP_GET_BITS(b_hi, b_lo, x) \
41 	(((x) & MASK(b_hi, b_lo)) >> (b_lo))
42 #define DAI_INTEL_SSP_IS_BIT_SET(reg, bit)	(((reg >> bit) & (0x1)) != 0)
43 
44 /* ssp_freq array constants */
45 #define DAI_INTEL_SSP_NUM_FREQ			3
46 #define DAI_INTEL_SSP_MAX_FREQ_INDEX		(DAI_INTEL_SSP_NUM_FREQ - 1)
47 #define DAI_INTEL_SSP_DEFAULT_IDX		1
48 
49 /* the SSP port fifo depth */
50 #define DAI_INTEL_SSP_FIFO_DEPTH		32
51 
52 /* the watermark for the SSP fifo depth setting */
53 #define DAI_INTEL_SSP_FIFO_WATERMARK		8
54 
55 /* minimal SSP port delay in cycles */
56 #define DAI_INTEL_SSP_PLATFORM_DELAY		1600
57 /* minimal SSP port delay in useconds */
58 #define DAI_INTEL_SSP_PLATFORM_DELAY_US		42
59 #define DAI_INTEL_SSP_PLATFORM_DEFAULT_DELAY	12
60 #define DAI_INTEL_SSP_DEFAULT_TRY_TIMES		8
61 
62 /** \brief Number of SSP MCLKs available */
63 #define DAI_INTEL_SSP_NUM_MCLK			2
64 
65 #define DAI_INTEL_SSP_CLOCK_XTAL_OSCILLATOR	0x0
66 #define DAI_INTEL_SSP_CLOCK_AUDIO_CARDINAL	0x1
67 #define DAI_INTEL_SSP_CLOCK_PLL_FIXED		0x2
68 
69 #if defined(CONFIG_SOC_INTEL_ACE15_MTPM) || defined(CONFIG_SOC_SERIES_INTEL_ADSP_CAVS)
70 #include "ssp_regs_v1.h"
71 #elif defined(CONFIG_SOC_INTEL_ACE20_LNL)
72 #include "ssp_regs_v2.h"
73 #elif defined(CONFIG_SOC_INTEL_ACE30)
74 #include "ssp_regs_v3.h"
75 #else
76 #error "Missing ssp definitions"
77 #endif
78 
79 #if SSP_IP_VER == SSP_IP_VER_1_0
80 /** \brief BCLKs can be driven by multiple sources - M/N or XTAL directly.
81  *	   Even in the case of M/N, the actual clock source can be XTAL,
82  *	   Audio cardinal clock (24.576) or 96 MHz PLL.
83  *	   The MN block is not really the source of clocks, but rather
84  *	   an intermediate component.
85  *	   Input for source is shared by all outputs coming from that source
86  *	   and once it's in use, it can be adjusted only with dividers.
87  *	   In order to change input, the source should not be in use, that's why
88  *	   it's necessary to keep track of BCLKs sources to know when it's safe
89  *	   to change shared input clock.
90  */
91 enum bclk_source {
92 	MN_BCLK_SOURCE_NONE = 0, /**< port is not using any clock */
93 	MN_BCLK_SOURCE_MN, /**< port is using clock driven by M/N */
94 	MN_BCLK_SOURCE_XTAL, /**< port is using XTAL directly */
95 };
96 #endif
97 
98 struct dai_intel_ssp_mn {
99 	uint32_t base;
100 	/**< keep track of which MCLKs are in use to know when it's safe to
101 	 * change shared clock
102 	 */
103 	int mclk_sources_ref[DAI_INTEL_SSP_NUM_MCLK];
104 	int mclk_rate[DAI_INTEL_SSP_NUM_MCLK];
105 	int mclk_source_clock;
106 
107 #if SSP_IP_VER == SSP_IP_VER_1_0
108 	enum bclk_source bclk_sources[(CONFIG_DAI_INTEL_SSP_NUM_BASE +
109 				       CONFIG_DAI_INTEL_SSP_NUM_EXT)];
110 	int bclk_source_mn_clock;
111 #endif
112 
113 	struct k_spinlock lock; /**< lock mechanism */
114 };
115 
116 struct dai_intel_ssp_freq_table {
117 	uint32_t freq;
118 	uint32_t ticks_per_msec;
119 };
120 
121 struct dai_intel_ssp_plat_fifo_data {
122 	uint32_t offset;
123 	uint32_t width;
124 	uint32_t depth;
125 	uint32_t watermark;
126 	uint32_t handshake;
127 };
128 
129 struct dai_intel_ssp_plat_data {
130 	uint32_t ssp_index;
131 	int acquire_count;
132 	bool is_initialized;
133 	bool is_power_en;
134 	uint32_t base;
135 	uint32_t ip_base;
136 	uint32_t shim_base;
137 #if SSP_IP_VER > SSP_IP_VER_1_5
138 	uint32_t hdamlssp_base;
139 	uint32_t i2svss_base;
140 	uint32_t link_clock;
141 #endif
142 	int irq;
143 	const char *irq_name;
144 	uint32_t flags;
145 	struct dai_intel_ssp_plat_fifo_data fifo[2];
146 	struct dai_intel_ssp_mn *mn_inst;
147 	struct dai_intel_ssp_freq_table *ftable;
148 	uint32_t *fsources;
149 	uint32_t clk_active;
150 	struct dai_intel_ipc3_ssp_params params;
151 };
152 
153 struct dai_intel_ssp_pdata {
154 	uint32_t sscr0;
155 	uint32_t sscr1;
156 	uint32_t psp;
157 	struct dai_config config;
158 	struct dai_properties props;
159 };
160 
161 struct dai_intel_ssp {
162 	uint32_t dai_index;
163 	uint32_t ssp_index;
164 	uint32_t tdm_slot_group;
165 	uint32_t state[2];
166 	struct k_spinlock lock;	/**< locking mechanism */
167 	int sref;		/**< simple ref counter, guarded by lock */
168 	struct dai_intel_ssp_plat_data *ssp_plat_data;
169 	void *priv_data;
170 };
171 
172 #endif
173