xref: /linux/sound/soc/intel/atom/sst/sst_acpi.c (revision 4e95bc268b915c3a19ec8b9110f61e4ea41a1ed0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * sst_acpi.c - SST (LPE) driver init file for ACPI enumeration.
4  *
5  * Copyright (c) 2013, Intel Corporation.
6  *
7  *  Authors:	Ramesh Babu K V <Ramesh.Babu@intel.com>
8  *  Authors:	Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
9  */
10 
11 #include <linux/module.h>
12 #include <linux/fs.h>
13 #include <linux/interrupt.h>
14 #include <linux/slab.h>
15 #include <linux/io.h>
16 #include <linux/platform_device.h>
17 #include <linux/firmware.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/pm_qos.h>
20 #include <linux/dmi.h>
21 #include <linux/acpi.h>
22 #include <asm/platform_sst_audio.h>
23 #include <sound/core.h>
24 #include <sound/soc.h>
25 #include <sound/compress_driver.h>
26 #include <acpi/acbuffer.h>
27 #include <acpi/platform/acenv.h>
28 #include <acpi/platform/aclinux.h>
29 #include <acpi/actypes.h>
30 #include <acpi/acpi_bus.h>
31 #include <asm/cpu_device_id.h>
32 #include <asm/iosf_mbi.h>
33 #include <sound/soc-acpi.h>
34 #include <sound/soc-acpi-intel-match.h>
35 #include "../sst-mfld-platform.h"
36 #include "../../common/sst-dsp.h"
37 #include "sst.h"
38 
39 /* LPE viewpoint addresses */
40 #define SST_BYT_IRAM_PHY_START	0xff2c0000
41 #define SST_BYT_IRAM_PHY_END	0xff2d4000
42 #define SST_BYT_DRAM_PHY_START	0xff300000
43 #define SST_BYT_DRAM_PHY_END	0xff320000
44 #define SST_BYT_IMR_VIRT_START	0xc0000000 /* virtual addr in LPE */
45 #define SST_BYT_IMR_VIRT_END	0xc01fffff
46 #define SST_BYT_SHIM_PHY_ADDR	0xff340000
47 #define SST_BYT_MBOX_PHY_ADDR	0xff344000
48 #define SST_BYT_DMA0_PHY_ADDR	0xff298000
49 #define SST_BYT_DMA1_PHY_ADDR	0xff29c000
50 #define SST_BYT_SSP0_PHY_ADDR	0xff2a0000
51 #define SST_BYT_SSP2_PHY_ADDR	0xff2a2000
52 
53 #define BYT_FW_MOD_TABLE_OFFSET	0x80000
54 #define BYT_FW_MOD_TABLE_SIZE	0x100
55 #define BYT_FW_MOD_OFFSET	(BYT_FW_MOD_TABLE_OFFSET + BYT_FW_MOD_TABLE_SIZE)
56 
57 static const struct sst_info byt_fwparse_info = {
58 	.use_elf	= false,
59 	.max_streams	= 25,
60 	.iram_start	= SST_BYT_IRAM_PHY_START,
61 	.iram_end	= SST_BYT_IRAM_PHY_END,
62 	.iram_use	= true,
63 	.dram_start	= SST_BYT_DRAM_PHY_START,
64 	.dram_end	= SST_BYT_DRAM_PHY_END,
65 	.dram_use	= true,
66 	.imr_start	= SST_BYT_IMR_VIRT_START,
67 	.imr_end	= SST_BYT_IMR_VIRT_END,
68 	.imr_use	= true,
69 	.mailbox_start	= SST_BYT_MBOX_PHY_ADDR,
70 	.num_probes	= 0,
71 	.lpe_viewpt_rqd  = true,
72 };
73 
74 static const struct sst_ipc_info byt_ipc_info = {
75 	.ipc_offset = 0,
76 	.mbox_recv_off = 0x400,
77 };
78 
79 static const struct sst_lib_dnld_info  byt_lib_dnld_info = {
80 	.mod_base           = SST_BYT_IMR_VIRT_START,
81 	.mod_end            = SST_BYT_IMR_VIRT_END,
82 	.mod_table_offset   = BYT_FW_MOD_TABLE_OFFSET,
83 	.mod_table_size     = BYT_FW_MOD_TABLE_SIZE,
84 	.mod_ddr_dnld       = false,
85 };
86 
87 static const struct sst_res_info byt_rvp_res_info = {
88 	.shim_offset = 0x140000,
89 	.shim_size = 0x000100,
90 	.shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
91 	.ssp0_offset = 0xa0000,
92 	.ssp0_size = 0x1000,
93 	.dma0_offset = 0x98000,
94 	.dma0_size = 0x4000,
95 	.dma1_offset = 0x9c000,
96 	.dma1_size = 0x4000,
97 	.iram_offset = 0x0c0000,
98 	.iram_size = 0x14000,
99 	.dram_offset = 0x100000,
100 	.dram_size = 0x28000,
101 	.mbox_offset = 0x144000,
102 	.mbox_size = 0x1000,
103 	.acpi_lpe_res_index = 0,
104 	.acpi_ddr_index = 2,
105 	.acpi_ipc_irq_index = 5,
106 };
107 
108 /* BYTCR has different BIOS from BYT */
109 static const struct sst_res_info bytcr_res_info = {
110 	.shim_offset = 0x140000,
111 	.shim_size = 0x000100,
112 	.shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
113 	.ssp0_offset = 0xa0000,
114 	.ssp0_size = 0x1000,
115 	.dma0_offset = 0x98000,
116 	.dma0_size = 0x4000,
117 	.dma1_offset = 0x9c000,
118 	.dma1_size = 0x4000,
119 	.iram_offset = 0x0c0000,
120 	.iram_size = 0x14000,
121 	.dram_offset = 0x100000,
122 	.dram_size = 0x28000,
123 	.mbox_offset = 0x144000,
124 	.mbox_size = 0x1000,
125 	.acpi_lpe_res_index = 0,
126 	.acpi_ddr_index = 2,
127 	.acpi_ipc_irq_index = 0
128 };
129 
130 static struct sst_platform_info byt_rvp_platform_data = {
131 	.probe_data = &byt_fwparse_info,
132 	.ipc_info = &byt_ipc_info,
133 	.lib_info = &byt_lib_dnld_info,
134 	.res_info = &byt_rvp_res_info,
135 	.platform = "sst-mfld-platform",
136 	.streams_lost_on_suspend = true,
137 };
138 
139 /* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail,
140  * so pdata is same as Baytrail, minus the streams_lost_on_suspend quirk.
141  */
142 static struct sst_platform_info chv_platform_data = {
143 	.probe_data = &byt_fwparse_info,
144 	.ipc_info = &byt_ipc_info,
145 	.lib_info = &byt_lib_dnld_info,
146 	.res_info = &byt_rvp_res_info,
147 	.platform = "sst-mfld-platform",
148 };
149 
150 static int sst_platform_get_resources(struct intel_sst_drv *ctx)
151 {
152 	struct resource *rsrc;
153 	struct platform_device *pdev = to_platform_device(ctx->dev);
154 
155 	/* All ACPI resource request here */
156 	/* Get Shim addr */
157 	rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
158 					ctx->pdata->res_info->acpi_lpe_res_index);
159 	if (!rsrc) {
160 		dev_err(ctx->dev, "Invalid SHIM base from IFWI\n");
161 		return -EIO;
162 	}
163 	dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start,
164 					(unsigned int)resource_size(rsrc));
165 
166 	ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset;
167 	ctx->iram_end =  ctx->iram_base + ctx->pdata->res_info->iram_size - 1;
168 	dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base);
169 	ctx->iram = devm_ioremap_nocache(ctx->dev, ctx->iram_base,
170 					 ctx->pdata->res_info->iram_size);
171 	if (!ctx->iram) {
172 		dev_err(ctx->dev, "unable to map IRAM\n");
173 		return -EIO;
174 	}
175 
176 	ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset;
177 	ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1;
178 	dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base);
179 	ctx->dram = devm_ioremap_nocache(ctx->dev, ctx->dram_base,
180 					 ctx->pdata->res_info->dram_size);
181 	if (!ctx->dram) {
182 		dev_err(ctx->dev, "unable to map DRAM\n");
183 		return -EIO;
184 	}
185 
186 	ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset;
187 	dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add);
188 	ctx->shim = devm_ioremap_nocache(ctx->dev, ctx->shim_phy_add,
189 					ctx->pdata->res_info->shim_size);
190 	if (!ctx->shim) {
191 		dev_err(ctx->dev, "unable to map SHIM\n");
192 		return -EIO;
193 	}
194 
195 	/* reassign physical address to LPE viewpoint address */
196 	ctx->shim_phy_add = ctx->pdata->res_info->shim_phy_addr;
197 
198 	/* Get mailbox addr */
199 	ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset;
200 	dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add);
201 	ctx->mailbox = devm_ioremap_nocache(ctx->dev, ctx->mailbox_add,
202 					    ctx->pdata->res_info->mbox_size);
203 	if (!ctx->mailbox) {
204 		dev_err(ctx->dev, "unable to map mailbox\n");
205 		return -EIO;
206 	}
207 
208 	/* reassign physical address to LPE viewpoint address */
209 	ctx->mailbox_add = ctx->info.mailbox_start;
210 
211 	rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
212 					ctx->pdata->res_info->acpi_ddr_index);
213 	if (!rsrc) {
214 		dev_err(ctx->dev, "Invalid DDR base from IFWI\n");
215 		return -EIO;
216 	}
217 	ctx->ddr_base = rsrc->start;
218 	ctx->ddr_end = rsrc->end;
219 	dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base);
220 	ctx->ddr = devm_ioremap_nocache(ctx->dev, ctx->ddr_base,
221 					resource_size(rsrc));
222 	if (!ctx->ddr) {
223 		dev_err(ctx->dev, "unable to map DDR\n");
224 		return -EIO;
225 	}
226 
227 	/* Find the IRQ */
228 	ctx->irq_num = platform_get_irq(pdev,
229 				ctx->pdata->res_info->acpi_ipc_irq_index);
230 	if (ctx->irq_num <= 0)
231 		return ctx->irq_num < 0 ? ctx->irq_num : -EIO;
232 
233 	return 0;
234 }
235 
236 static int is_byt(void)
237 {
238 	bool status = false;
239 	static const struct x86_cpu_id cpu_ids[] = {
240 		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
241 		{}
242 	};
243 	if (x86_match_cpu(cpu_ids))
244 		status = true;
245 	return status;
246 }
247 
248 static bool is_byt_cr(struct platform_device *pdev)
249 {
250 	struct device *dev = &pdev->dev;
251 	int status = 0;
252 
253 	if (!is_byt())
254 		return false;
255 
256 	if (iosf_mbi_available()) {
257 		u32 bios_status;
258 		status = iosf_mbi_read(BT_MBI_UNIT_PMC, /* 0x04 PUNIT */
259 				       MBI_REG_READ, /* 0x10 */
260 				       0x006, /* BIOS_CONFIG */
261 				       &bios_status);
262 
263 		if (status) {
264 			dev_err(dev, "could not read PUNIT BIOS_CONFIG\n");
265 		} else {
266 			/* bits 26:27 mirror PMIC options */
267 			bios_status = (bios_status >> 26) & 3;
268 
269 			if (bios_status == 1 || bios_status == 3) {
270 				dev_info(dev, "Detected Baytrail-CR platform\n");
271 				return true;
272 			}
273 
274 			dev_info(dev, "BYT-CR not detected\n");
275 		}
276 	} else {
277 		dev_info(dev, "IOSF_MBI not available, no BYT-CR detection\n");
278 	}
279 
280 	if (platform_get_resource(pdev, IORESOURCE_IRQ, 5) == NULL) {
281 		/*
282 		 * Some devices detected as BYT-T have only a single IRQ listed,
283 		 * causing platform_get_irq with index 5 to return -ENXIO.
284 		 * The correct IRQ in this case is at index 0, as on BYT-CR.
285 		 */
286 		dev_info(dev, "Falling back to Baytrail-CR platform\n");
287 		return true;
288 	}
289 
290 	return false;
291 }
292 
293 
294 static int sst_acpi_probe(struct platform_device *pdev)
295 {
296 	struct device *dev = &pdev->dev;
297 	int ret = 0;
298 	struct intel_sst_drv *ctx;
299 	const struct acpi_device_id *id;
300 	struct snd_soc_acpi_mach *mach;
301 	struct platform_device *mdev;
302 	struct platform_device *plat_dev;
303 	struct sst_platform_info *pdata;
304 	unsigned int dev_id;
305 
306 	id = acpi_match_device(dev->driver->acpi_match_table, dev);
307 	if (!id)
308 		return -ENODEV;
309 	dev_dbg(dev, "for %s\n", id->id);
310 
311 	mach = (struct snd_soc_acpi_mach *)id->driver_data;
312 	mach = snd_soc_acpi_find_machine(mach);
313 	if (mach == NULL) {
314 		dev_err(dev, "No matching machine driver found\n");
315 		return -ENODEV;
316 	}
317 
318 	if (is_byt())
319 		mach->pdata = &byt_rvp_platform_data;
320 	else
321 		mach->pdata = &chv_platform_data;
322 	pdata = mach->pdata;
323 
324 	ret = kstrtouint(id->id, 16, &dev_id);
325 	if (ret < 0) {
326 		dev_err(dev, "Unique device id conversion error: %d\n", ret);
327 		return ret;
328 	}
329 
330 	dev_dbg(dev, "ACPI device id: %x\n", dev_id);
331 
332 	ret = sst_alloc_drv_context(&ctx, dev, dev_id);
333 	if (ret < 0)
334 		return ret;
335 
336 	if (is_byt_cr(pdev)) {
337 		/* override resource info */
338 		byt_rvp_platform_data.res_info = &bytcr_res_info;
339 	}
340 
341 	/* update machine parameters */
342 	mach->mach_params.acpi_ipc_irq_index =
343 		pdata->res_info->acpi_ipc_irq_index;
344 
345 	plat_dev = platform_device_register_data(dev, pdata->platform, -1,
346 						NULL, 0);
347 	if (IS_ERR(plat_dev)) {
348 		dev_err(dev, "Failed to create machine device: %s\n",
349 			pdata->platform);
350 		return PTR_ERR(plat_dev);
351 	}
352 
353 	/*
354 	 * Create platform device for sst machine driver,
355 	 * pass machine info as pdata
356 	 */
357 	mdev = platform_device_register_data(dev, mach->drv_name, -1,
358 					(const void *)mach, sizeof(*mach));
359 	if (IS_ERR(mdev)) {
360 		dev_err(dev, "Failed to create machine device: %s\n",
361 			mach->drv_name);
362 		return PTR_ERR(mdev);
363 	}
364 
365 	/* Fill sst platform data */
366 	ctx->pdata = pdata;
367 	strcpy(ctx->firmware_name, mach->fw_filename);
368 
369 	ret = sst_platform_get_resources(ctx);
370 	if (ret)
371 		return ret;
372 
373 	ret = sst_context_init(ctx);
374 	if (ret < 0)
375 		return ret;
376 
377 	sst_configure_runtime_pm(ctx);
378 	platform_set_drvdata(pdev, ctx);
379 	return ret;
380 }
381 
382 /**
383 * intel_sst_remove - remove function
384 *
385 * @pdev:	platform device structure
386 *
387 * This function is called by OS when a device is unloaded
388 * This frees the interrupt etc
389 */
390 static int sst_acpi_remove(struct platform_device *pdev)
391 {
392 	struct intel_sst_drv *ctx;
393 
394 	ctx = platform_get_drvdata(pdev);
395 	sst_context_cleanup(ctx);
396 	platform_set_drvdata(pdev, NULL);
397 	return 0;
398 }
399 
400 static const struct acpi_device_id sst_acpi_ids[] = {
401 	{ "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
402 	{ "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines},
403 	{ },
404 };
405 
406 MODULE_DEVICE_TABLE(acpi, sst_acpi_ids);
407 
408 static struct platform_driver sst_acpi_driver = {
409 	.driver = {
410 		.name			= "intel_sst_acpi",
411 		.acpi_match_table	= ACPI_PTR(sst_acpi_ids),
412 		.pm			= &intel_sst_pm,
413 	},
414 	.probe	= sst_acpi_probe,
415 	.remove	= sst_acpi_remove,
416 };
417 
418 module_platform_driver(sst_acpi_driver);
419 
420 MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine ACPI Driver");
421 MODULE_AUTHOR("Ramesh Babu K V");
422 MODULE_AUTHOR("Omair Mohammed Abdullah");
423 MODULE_LICENSE("GPL v2");
424 MODULE_ALIAS("sst");
425