1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2 
3 #ifndef __IMX_COMMON_H__
4 #define __IMX_COMMON_H__
5 
6 #include <linux/clk.h>
7 #include <linux/of_platform.h>
8 #include <sound/sof/xtensa.h>
9 
10 #include "../sof-of-dev.h"
11 #include "../ops.h"
12 
13 #define EXCEPT_MAX_HDR_SIZE	0x400
14 #define IMX8_STACK_DUMP_SIZE 32
15 
16 /* chip_info refers to the data stored in struct sof_dev_desc's chip_info */
17 #define get_chip_info(sdev)\
18 	((const struct imx_chip_info *)((sdev)->pdata->desc->chip_info))
19 
20 /* chip_pdata refers to the data stored in struct imx_common_data's chip_pdata */
21 #define get_chip_pdata(sdev)\
22 	(((struct imx_common_data *)((sdev)->pdata->hw_pdata))->chip_pdata)
23 
24 /* can be used if:
25  *	1) The only supported IPC version is IPC3.
26  *	2) The default paths/FW name match values below.
27  *
28  * otherwise, just explicitly declare the structure
29  */
30 #define IMX_SOF_DEV_DESC(mach_name, of_machs,				\
31 			 mach_chip_info, mach_ops, mach_ops_init)	\
32 static struct sof_dev_desc sof_of_##mach_name##_desc = {		\
33 	.of_machines = of_machs,					\
34 	.chip_info = mach_chip_info,					\
35 	.ipc_supported_mask = BIT(SOF_IPC_TYPE_3),			\
36 	.ipc_default = SOF_IPC_TYPE_3,					\
37 	.default_fw_path = {						\
38 		[SOF_IPC_TYPE_3] = "imx/sof",				\
39 	},								\
40 	.default_tplg_path = {						\
41 		[SOF_IPC_TYPE_3] = "imx/sof-tplg",			\
42 	},								\
43 	.default_fw_filename = {					\
44 		[SOF_IPC_TYPE_3] = "sof-" #mach_name ".ri",		\
45 	},								\
46 	.ops = mach_ops,						\
47 	.ops_init = mach_ops_init,					\
48 }
49 
50 /* to be used alongside IMX_SOF_DEV_DESC() */
51 #define IMX_SOF_DEV_DESC_NAME(mach_name) sof_of_##mach_name##_desc
52 
53 /* dai driver entry w/ playback and capture caps. If one direction is missing
54  * then set the channels to 0.
55  */
56 #define IMX_SOF_DAI_DRV_ENTRY(dai_name, pb_cmin, pb_cmax, cap_cmin, cap_cmax)	\
57 {										\
58 	.name = dai_name,							\
59 	.playback = {								\
60 		.channels_min = pb_cmin,					\
61 		.channels_max = pb_cmax,					\
62 	},									\
63 	.capture = {								\
64 		.channels_min = cap_cmin,					\
65 		.channels_max = cap_cmax,					\
66 	},									\
67 }
68 
69 /* use if playback and capture have the same min/max channel count */
70 #define IMX_SOF_DAI_DRV_ENTRY_BIDIR(dai_name, cmin, cmax)\
71 	IMX_SOF_DAI_DRV_ENTRY(dai_name, cmin, cmax, cmin, cmax)
72 
73 struct imx_ipc_info {
74 	/* true if core is able to write a panic code to the debug box */
75 	bool has_panic_code;
76 	/* offset to mailbox in which firmware initially writes FW_READY */
77 	int boot_mbox_offset;
78 	/* offset to region at which the mailboxes start */
79 	int window_offset;
80 };
81 
82 struct imx_chip_ops {
83 	/* called after clocks and PDs are enabled */
84 	int (*probe)(struct snd_sof_dev *sdev);
85 	/* used directly by the SOF core */
86 	int (*core_kick)(struct snd_sof_dev *sdev);
87 	/* called during suspend()/remove() before clocks are disabled */
88 	int (*core_shutdown)(struct snd_sof_dev *sdev);
89 	/* used directly by the SOF core */
90 	int (*core_reset)(struct snd_sof_dev *sdev);
91 };
92 
93 struct imx_memory_info {
94 	const char *name;
95 	bool reserved;
96 };
97 
98 struct imx_chip_info {
99 	struct imx_ipc_info ipc_info;
100 	/* does the chip have a reserved memory region for DMA? */
101 	bool has_dma_reserved;
102 	struct imx_memory_info *memory;
103 	struct snd_soc_dai_driver *drv;
104 	int num_drv;
105 	/* optional */
106 	const struct imx_chip_ops *ops;
107 };
108 
109 struct imx_common_data {
110 	struct platform_device *ipc_dev;
111 	struct imx_dsp_ipc *ipc_handle;
112 	/* core may have no clocks */
113 	struct clk_bulk_data *clks;
114 	int clk_num;
115 	/* core may have no PDs */
116 	struct dev_pm_domain_list *pd_list;
117 	void *chip_pdata;
118 };
119 
120 static inline int imx_chip_core_kick(struct snd_sof_dev *sdev)
121 {
122 	const struct imx_chip_ops *ops = get_chip_info(sdev)->ops;
123 
124 	if (ops && ops->core_kick)
125 		return ops->core_kick(sdev);
126 
127 	return 0;
128 }
129 
130 static inline int imx_chip_core_shutdown(struct snd_sof_dev *sdev)
131 {
132 	const struct imx_chip_ops *ops = get_chip_info(sdev)->ops;
133 
134 	if (ops && ops->core_shutdown)
135 		return ops->core_shutdown(sdev);
136 
137 	return 0;
138 }
139 
140 static inline int imx_chip_core_reset(struct snd_sof_dev *sdev)
141 {
142 	const struct imx_chip_ops *ops = get_chip_info(sdev)->ops;
143 
144 	if (ops && ops->core_reset)
145 		return ops->core_reset(sdev);
146 
147 	return 0;
148 }
149 
150 static inline int imx_chip_probe(struct snd_sof_dev *sdev)
151 {
152 	const struct imx_chip_ops *ops = get_chip_info(sdev)->ops;
153 
154 	if (ops && ops->probe)
155 		return ops->probe(sdev);
156 
157 	return 0;
158 }
159 
160 void imx8_get_registers(struct snd_sof_dev *sdev,
161 			struct sof_ipc_dsp_oops_xtensa *xoops,
162 			struct sof_ipc_panic_info *panic_info,
163 			u32 *stack, size_t stack_words);
164 
165 void imx8_dump(struct snd_sof_dev *sdev, u32 flags);
166 
167 extern const struct snd_sof_dsp_ops sof_imx_ops;
168 
169 #endif
170