1d62a7d41SVinod Koul // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2d62a7d41SVinod Koul // Copyright(c) 2015-17 Intel Corporation.
3d62a7d41SVinod Koul 
4d62a7d41SVinod Koul /*
5d62a7d41SVinod Koul  * SDW Intel Init Routines
6d62a7d41SVinod Koul  *
7d62a7d41SVinod Koul  * Initializes and creates SDW devices based on ACPI and Hardware values
8d62a7d41SVinod Koul  */
9d62a7d41SVinod Koul 
10d62a7d41SVinod Koul #include <linux/acpi.h>
114abbd783SPaul Gortmaker #include <linux/export.h>
123fc40449SVinod Koul #include <linux/io.h>
134abbd783SPaul Gortmaker #include <linux/module.h>
14d62a7d41SVinod Koul #include <linux/platform_device.h>
15d62a7d41SVinod Koul #include <linux/soundwire/sdw_intel.h>
16b6109dd6SPierre-Louis Bossart #include "cadence_master.h"
17d62a7d41SVinod Koul #include "intel.h"
18d62a7d41SVinod Koul 
196f11586fSPierre-Louis Bossart #define SDW_LINK_TYPE		4 /* from Intel ACPI documentation */
20d62a7d41SVinod Koul #define SDW_MAX_LINKS		4
21d62a7d41SVinod Koul #define SDW_SHIM_LCAP		0x0
22d62a7d41SVinod Koul #define SDW_SHIM_BASE		0x2C000
23d62a7d41SVinod Koul #define SDW_ALH_BASE		0x2C800
24d62a7d41SVinod Koul #define SDW_LINK_BASE		0x30000
25d62a7d41SVinod Koul #define SDW_LINK_SIZE		0x10000
26d62a7d41SVinod Koul 
276d2c6669SPierre-Louis Bossart static int ctrl_link_mask;
286d2c6669SPierre-Louis Bossart module_param_named(sdw_link_mask, ctrl_link_mask, int, 0444);
2950302fc7SPierre-Louis Bossart MODULE_PARM_DESC(sdw_link_mask, "Intel link mask (one bit per link)");
3050302fc7SPierre-Louis Bossart 
316d2c6669SPierre-Louis Bossart static bool is_link_enabled(struct fwnode_handle *fw_node, int i)
326d2c6669SPierre-Louis Bossart {
336d2c6669SPierre-Louis Bossart 	struct fwnode_handle *link;
346d2c6669SPierre-Louis Bossart 	char name[32];
356d2c6669SPierre-Louis Bossart 	u32 quirk_mask = 0;
366d2c6669SPierre-Louis Bossart 
376d2c6669SPierre-Louis Bossart 	/* Find master handle */
386d2c6669SPierre-Louis Bossart 	snprintf(name, sizeof(name),
396d2c6669SPierre-Louis Bossart 		 "mipi-sdw-link-%d-subproperties", i);
406d2c6669SPierre-Louis Bossart 
416d2c6669SPierre-Louis Bossart 	link = fwnode_get_named_child_node(fw_node, name);
426d2c6669SPierre-Louis Bossart 	if (!link)
436d2c6669SPierre-Louis Bossart 		return false;
446d2c6669SPierre-Louis Bossart 
456d2c6669SPierre-Louis Bossart 	fwnode_property_read_u32(link,
466d2c6669SPierre-Louis Bossart 				 "intel-quirk-mask",
476d2c6669SPierre-Louis Bossart 				 &quirk_mask);
486d2c6669SPierre-Louis Bossart 
496d2c6669SPierre-Louis Bossart 	if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
506d2c6669SPierre-Louis Bossart 		return false;
516d2c6669SPierre-Louis Bossart 
526d2c6669SPierre-Louis Bossart 	return true;
536d2c6669SPierre-Louis Bossart }
546d2c6669SPierre-Louis Bossart 
556d2c6669SPierre-Louis Bossart static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx)
56d62a7d41SVinod Koul {
57f98f690fSPierre-Louis Bossart 	struct sdw_intel_link_res *link = ctx->links;
586d2c6669SPierre-Louis Bossart 	u32 link_mask;
59d62a7d41SVinod Koul 	int i;
60d62a7d41SVinod Koul 
61d62a7d41SVinod Koul 	if (!link)
62d62a7d41SVinod Koul 		return 0;
63d62a7d41SVinod Koul 
646d2c6669SPierre-Louis Bossart 	link_mask = ctx->link_mask;
656d2c6669SPierre-Louis Bossart 
666d2c6669SPierre-Louis Bossart 	for (i = 0; i < ctx->count; i++, link++) {
676d2c6669SPierre-Louis Bossart 		if (!(link_mask & BIT(i)))
686d2c6669SPierre-Louis Bossart 			continue;
696d2c6669SPierre-Louis Bossart 
70d62a7d41SVinod Koul 		if (link->pdev)
71d62a7d41SVinod Koul 			platform_device_unregister(link->pdev);
72d62a7d41SVinod Koul 	}
73d62a7d41SVinod Koul 
74d62a7d41SVinod Koul 	return 0;
75d62a7d41SVinod Koul }
76d62a7d41SVinod Koul 
776d2c6669SPierre-Louis Bossart static int
786d2c6669SPierre-Louis Bossart sdw_intel_scan_controller(struct sdw_intel_acpi_info *info)
79d62a7d41SVinod Koul {
80d62a7d41SVinod Koul 	struct acpi_device *adev;
81d62a7d41SVinod Koul 	int ret, i;
82d62a7d41SVinod Koul 	u8 count;
83d62a7d41SVinod Koul 
846d2c6669SPierre-Louis Bossart 	if (acpi_bus_get_device(info->handle, &adev))
856d2c6669SPierre-Louis Bossart 		return -EINVAL;
86d62a7d41SVinod Koul 
87d62a7d41SVinod Koul 	/* Found controller, find links supported */
88d62a7d41SVinod Koul 	count = 0;
89d62a7d41SVinod Koul 	ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev),
90d62a7d41SVinod Koul 					    "mipi-sdw-master-count", &count, 1);
91d62a7d41SVinod Koul 
926d2c6669SPierre-Louis Bossart 	/*
936d2c6669SPierre-Louis Bossart 	 * In theory we could check the number of links supported in
946d2c6669SPierre-Louis Bossart 	 * hardware, but in that step we cannot assume SoundWire IP is
956d2c6669SPierre-Louis Bossart 	 * powered.
966d2c6669SPierre-Louis Bossart 	 *
976d2c6669SPierre-Louis Bossart 	 * In addition, if the BIOS doesn't even provide this
986d2c6669SPierre-Louis Bossart 	 * 'master-count' property then all the inits based on link
996d2c6669SPierre-Louis Bossart 	 * masks will fail as well.
1006d2c6669SPierre-Louis Bossart 	 *
1016d2c6669SPierre-Louis Bossart 	 * We will check the hardware capabilities in the startup() step
1026d2c6669SPierre-Louis Bossart 	 */
1036d2c6669SPierre-Louis Bossart 
104d62a7d41SVinod Koul 	if (ret) {
105d62a7d41SVinod Koul 		dev_err(&adev->dev,
106d62a7d41SVinod Koul 			"Failed to read mipi-sdw-master-count: %d\n", ret);
1076d2c6669SPierre-Louis Bossart 		return -EINVAL;
108d62a7d41SVinod Koul 	}
109d62a7d41SVinod Koul 
110d62a7d41SVinod Koul 	/* Check count is within bounds */
111d62a7d41SVinod Koul 	if (count > SDW_MAX_LINKS) {
112d62a7d41SVinod Koul 		dev_err(&adev->dev, "Link count %d exceeds max %d\n",
113d62a7d41SVinod Koul 			count, SDW_MAX_LINKS);
1146d2c6669SPierre-Louis Bossart 		return -EINVAL;
1156f7219feSGuennadi Liakhovetski 	}
1166f7219feSGuennadi Liakhovetski 
1176f7219feSGuennadi Liakhovetski 	if (!count) {
118432732b8SPierre-Louis Bossart 		dev_warn(&adev->dev, "No SoundWire links detected\n");
1196d2c6669SPierre-Louis Bossart 		return -EINVAL;
1206d2c6669SPierre-Louis Bossart 	}
1216d2c6669SPierre-Louis Bossart 	dev_dbg(&adev->dev, "ACPI reports %d SDW Link devices\n", count);
1226d2c6669SPierre-Louis Bossart 
1236d2c6669SPierre-Louis Bossart 	info->count = count;
1246d2c6669SPierre-Louis Bossart 	info->link_mask = 0;
1256d2c6669SPierre-Louis Bossart 
1266d2c6669SPierre-Louis Bossart 	for (i = 0; i < count; i++) {
1276d2c6669SPierre-Louis Bossart 		if (ctrl_link_mask && !(ctrl_link_mask & BIT(i))) {
1286d2c6669SPierre-Louis Bossart 			dev_dbg(&adev->dev,
1296d2c6669SPierre-Louis Bossart 				"Link %d masked, will not be enabled\n", i);
1306d2c6669SPierre-Louis Bossart 			continue;
131d62a7d41SVinod Koul 		}
132d62a7d41SVinod Koul 
1336d2c6669SPierre-Louis Bossart 		if (!is_link_enabled(acpi_fwnode_handle(adev), i)) {
1346d2c6669SPierre-Louis Bossart 			dev_dbg(&adev->dev,
1356d2c6669SPierre-Louis Bossart 				"Link %d not selected in firmware\n", i);
1366d2c6669SPierre-Louis Bossart 			continue;
1376d2c6669SPierre-Louis Bossart 		}
1386d2c6669SPierre-Louis Bossart 
1396d2c6669SPierre-Louis Bossart 		info->link_mask |= BIT(i);
1406d2c6669SPierre-Louis Bossart 	}
1416d2c6669SPierre-Louis Bossart 
1426d2c6669SPierre-Louis Bossart 	return 0;
1436d2c6669SPierre-Louis Bossart }
1446d2c6669SPierre-Louis Bossart 
14512b16146SPierre-Louis Bossart #define HDA_DSP_REG_ADSPIC2             (0x10)
14612b16146SPierre-Louis Bossart #define HDA_DSP_REG_ADSPIS2             (0x14)
14712b16146SPierre-Louis Bossart #define HDA_DSP_REG_ADSPIC2_SNDW        BIT(5)
14812b16146SPierre-Louis Bossart 
14912b16146SPierre-Louis Bossart /**
15012b16146SPierre-Louis Bossart  * sdw_intel_enable_irq() - enable/disable Intel SoundWire IRQ
15112b16146SPierre-Louis Bossart  * @mmio_base: The mmio base of the control register
15212b16146SPierre-Louis Bossart  * @enable: true if enable
15312b16146SPierre-Louis Bossart  */
15412b16146SPierre-Louis Bossart void sdw_intel_enable_irq(void __iomem *mmio_base, bool enable)
15512b16146SPierre-Louis Bossart {
15612b16146SPierre-Louis Bossart 	u32 val;
15712b16146SPierre-Louis Bossart 
15812b16146SPierre-Louis Bossart 	val = readl(mmio_base + HDA_DSP_REG_ADSPIC2);
15912b16146SPierre-Louis Bossart 
16012b16146SPierre-Louis Bossart 	if (enable)
16112b16146SPierre-Louis Bossart 		val |= HDA_DSP_REG_ADSPIC2_SNDW;
16212b16146SPierre-Louis Bossart 	else
16312b16146SPierre-Louis Bossart 		val &= ~HDA_DSP_REG_ADSPIC2_SNDW;
16412b16146SPierre-Louis Bossart 
16512b16146SPierre-Louis Bossart 	writel(val, mmio_base + HDA_DSP_REG_ADSPIC2);
16612b16146SPierre-Louis Bossart }
1678459cea7SPierre-Louis Bossart EXPORT_SYMBOL_NS(sdw_intel_enable_irq, SOUNDWIRE_INTEL_INIT);
16812b16146SPierre-Louis Bossart 
1696d2c6669SPierre-Louis Bossart static struct sdw_intel_ctx
1706d2c6669SPierre-Louis Bossart *sdw_intel_probe_controller(struct sdw_intel_res *res)
1716d2c6669SPierre-Louis Bossart {
1726d2c6669SPierre-Louis Bossart 	struct platform_device_info pdevinfo;
1736d2c6669SPierre-Louis Bossart 	struct platform_device *pdev;
1746d2c6669SPierre-Louis Bossart 	struct sdw_intel_link_res *link;
1756d2c6669SPierre-Louis Bossart 	struct sdw_intel_ctx *ctx;
1766d2c6669SPierre-Louis Bossart 	struct acpi_device *adev;
1776d2c6669SPierre-Louis Bossart 	u32 link_mask;
1786d2c6669SPierre-Louis Bossart 	int count;
1796d2c6669SPierre-Louis Bossart 	int i;
1806d2c6669SPierre-Louis Bossart 
1816d2c6669SPierre-Louis Bossart 	if (!res)
1826d2c6669SPierre-Louis Bossart 		return NULL;
1836d2c6669SPierre-Louis Bossart 
1846d2c6669SPierre-Louis Bossart 	if (acpi_bus_get_device(res->handle, &adev))
1856d2c6669SPierre-Louis Bossart 		return NULL;
1866d2c6669SPierre-Louis Bossart 
1876d2c6669SPierre-Louis Bossart 	if (!res->count)
1886d2c6669SPierre-Louis Bossart 		return NULL;
1896d2c6669SPierre-Louis Bossart 
1906d2c6669SPierre-Louis Bossart 	count = res->count;
191d62a7d41SVinod Koul 	dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count);
192d62a7d41SVinod Koul 
193dd906cc6SPierre-Louis Bossart 	ctx = devm_kzalloc(&adev->dev, sizeof(*ctx), GFP_KERNEL);
194d62a7d41SVinod Koul 	if (!ctx)
195d62a7d41SVinod Koul 		return NULL;
196d62a7d41SVinod Koul 
197d62a7d41SVinod Koul 	ctx->count = count;
198dd906cc6SPierre-Louis Bossart 	ctx->links = devm_kcalloc(&adev->dev, ctx->count,
199dd906cc6SPierre-Louis Bossart 				  sizeof(*ctx->links), GFP_KERNEL);
200d62a7d41SVinod Koul 	if (!ctx->links)
201dd906cc6SPierre-Louis Bossart 		return NULL;
202d62a7d41SVinod Koul 
2036d2c6669SPierre-Louis Bossart 	ctx->count = count;
2046d2c6669SPierre-Louis Bossart 	ctx->mmio_base = res->mmio_base;
2056d2c6669SPierre-Louis Bossart 	ctx->link_mask = res->link_mask;
2066d2c6669SPierre-Louis Bossart 	ctx->handle = res->handle;
2074a17c441SPierre-Louis Bossart 	mutex_init(&ctx->shim_lock);
2086d2c6669SPierre-Louis Bossart 
209d62a7d41SVinod Koul 	link = ctx->links;
2106d2c6669SPierre-Louis Bossart 	link_mask = ctx->link_mask;
211d62a7d41SVinod Koul 
212d62a7d41SVinod Koul 	/* Create SDW Master devices */
2136d2c6669SPierre-Louis Bossart 	for (i = 0; i < count; i++, link++) {
2149cd1c5a7SPierre-Louis Bossart 		if (!(link_mask & BIT(i))) {
21550302fc7SPierre-Louis Bossart 			dev_dbg(&adev->dev,
21650302fc7SPierre-Louis Bossart 				"Link %d masked, will not be enabled\n", i);
21750302fc7SPierre-Louis Bossart 			continue;
21850302fc7SPierre-Louis Bossart 		}
21950302fc7SPierre-Louis Bossart 
2206d2c6669SPierre-Louis Bossart 		link->mmio_base = res->mmio_base;
221f98f690fSPierre-Louis Bossart 		link->registers = res->mmio_base + SDW_LINK_BASE
222d62a7d41SVinod Koul 			+ (SDW_LINK_SIZE * i);
223f98f690fSPierre-Louis Bossart 		link->shim = res->mmio_base + SDW_SHIM_BASE;
224f98f690fSPierre-Louis Bossart 		link->alh = res->mmio_base + SDW_ALH_BASE;
225d62a7d41SVinod Koul 
226f98f690fSPierre-Louis Bossart 		link->ops = res->ops;
2274b206d34SRander Wang 		link->dev = res->dev;
228c46302ecSVinod Koul 
2294a17c441SPierre-Louis Bossart 		link->shim_lock = &ctx->shim_lock;
2304a17c441SPierre-Louis Bossart 		link->shim_mask = &ctx->shim_mask;
2314a17c441SPierre-Louis Bossart 
232d62a7d41SVinod Koul 		memset(&pdevinfo, 0, sizeof(pdevinfo));
233d62a7d41SVinod Koul 
234d62a7d41SVinod Koul 		pdevinfo.parent = res->parent;
2356d2c6669SPierre-Louis Bossart 		pdevinfo.name = "intel-sdw";
236d62a7d41SVinod Koul 		pdevinfo.id = i;
237d62a7d41SVinod Koul 		pdevinfo.fwnode = acpi_fwnode_handle(adev);
2384ab34412SPierre-Louis Bossart 		pdevinfo.data = link;
2394ab34412SPierre-Louis Bossart 		pdevinfo.size_data = sizeof(*link);
240d62a7d41SVinod Koul 
241d62a7d41SVinod Koul 		pdev = platform_device_register_full(&pdevinfo);
242d62a7d41SVinod Koul 		if (IS_ERR(pdev)) {
243d62a7d41SVinod Koul 			dev_err(&adev->dev,
244d62a7d41SVinod Koul 				"platform device creation failed: %ld\n",
245d62a7d41SVinod Koul 				PTR_ERR(pdev));
2466d2c6669SPierre-Louis Bossart 			goto err;
247d62a7d41SVinod Koul 		}
248d62a7d41SVinod Koul 		link->pdev = pdev;
249d62a7d41SVinod Koul 	}
250d62a7d41SVinod Koul 
251d62a7d41SVinod Koul 	return ctx;
252d62a7d41SVinod Koul 
2536d2c6669SPierre-Louis Bossart err:
254dd906cc6SPierre-Louis Bossart 	ctx->count = i;
2556d2c6669SPierre-Louis Bossart 	sdw_intel_cleanup(ctx);
256d62a7d41SVinod Koul 	return NULL;
257d62a7d41SVinod Koul }
258d62a7d41SVinod Koul 
2596d2c6669SPierre-Louis Bossart static int
2606d2c6669SPierre-Louis Bossart sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
2616d2c6669SPierre-Louis Bossart {
2626d2c6669SPierre-Louis Bossart 	struct acpi_device *adev;
2636d2c6669SPierre-Louis Bossart 	struct sdw_intel_link_res *link;
2646d2c6669SPierre-Louis Bossart 	u32 caps;
2656d2c6669SPierre-Louis Bossart 	u32 link_mask;
2666d2c6669SPierre-Louis Bossart 	int i;
2676d2c6669SPierre-Louis Bossart 
2686d2c6669SPierre-Louis Bossart 	if (acpi_bus_get_device(ctx->handle, &adev))
2696d2c6669SPierre-Louis Bossart 		return -EINVAL;
2706d2c6669SPierre-Louis Bossart 
2716d2c6669SPierre-Louis Bossart 	/* Check SNDWLCAP.LCOUNT */
2726d2c6669SPierre-Louis Bossart 	caps = ioread32(ctx->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
2736d2c6669SPierre-Louis Bossart 	caps &= GENMASK(2, 0);
2746d2c6669SPierre-Louis Bossart 
2756d2c6669SPierre-Louis Bossart 	/* Check HW supported vs property value */
2766d2c6669SPierre-Louis Bossart 	if (caps < ctx->count) {
2776d2c6669SPierre-Louis Bossart 		dev_err(&adev->dev,
2786d2c6669SPierre-Louis Bossart 			"BIOS master count is larger than hardware capabilities\n");
2796d2c6669SPierre-Louis Bossart 		return -EINVAL;
2806d2c6669SPierre-Louis Bossart 	}
2816d2c6669SPierre-Louis Bossart 
2826d2c6669SPierre-Louis Bossart 	if (!ctx->links)
2836d2c6669SPierre-Louis Bossart 		return -EINVAL;
2846d2c6669SPierre-Louis Bossart 
2856d2c6669SPierre-Louis Bossart 	link = ctx->links;
2866d2c6669SPierre-Louis Bossart 	link_mask = ctx->link_mask;
2876d2c6669SPierre-Louis Bossart 
2886d2c6669SPierre-Louis Bossart 	/* Startup SDW Master devices */
2896d2c6669SPierre-Louis Bossart 	for (i = 0; i < ctx->count; i++, link++) {
2906d2c6669SPierre-Louis Bossart 		if (!(link_mask & BIT(i)))
2916d2c6669SPierre-Louis Bossart 			continue;
2926d2c6669SPierre-Louis Bossart 
2936d2c6669SPierre-Louis Bossart 		intel_master_startup(link->pdev);
2946d2c6669SPierre-Louis Bossart 	}
2956d2c6669SPierre-Louis Bossart 
2966d2c6669SPierre-Louis Bossart 	return 0;
2976d2c6669SPierre-Louis Bossart }
2986d2c6669SPierre-Louis Bossart 
299d62a7d41SVinod Koul static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level,
300d62a7d41SVinod Koul 				     void *cdata, void **return_value)
301d62a7d41SVinod Koul {
3026d2c6669SPierre-Louis Bossart 	struct sdw_intel_acpi_info *info = cdata;
303d62a7d41SVinod Koul 	struct acpi_device *adev;
3046f11586fSPierre-Louis Bossart 	acpi_status status;
3056f11586fSPierre-Louis Bossart 	u64 adr;
3066f11586fSPierre-Louis Bossart 
3076f11586fSPierre-Louis Bossart 	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
3086f11586fSPierre-Louis Bossart 	if (ACPI_FAILURE(status))
3096f11586fSPierre-Louis Bossart 		return AE_OK; /* keep going */
310d62a7d41SVinod Koul 
311d62a7d41SVinod Koul 	if (acpi_bus_get_device(handle, &adev)) {
312e1c815f4SVinod Koul 		pr_err("%s: Couldn't find ACPI handle\n", __func__);
313d62a7d41SVinod Koul 		return AE_NOT_FOUND;
314d62a7d41SVinod Koul 	}
315d62a7d41SVinod Koul 
3166d2c6669SPierre-Louis Bossart 	info->handle = handle;
3176f11586fSPierre-Louis Bossart 
3186f11586fSPierre-Louis Bossart 	/*
3196f11586fSPierre-Louis Bossart 	 * On some Intel platforms, multiple children of the HDAS
3206f11586fSPierre-Louis Bossart 	 * device can be found, but only one of them is the SoundWire
3216f11586fSPierre-Louis Bossart 	 * controller. The SNDW device is always exposed with
3226f11586fSPierre-Louis Bossart 	 * Name(_ADR, 0x40000000), with bits 31..28 representing the
3236f11586fSPierre-Louis Bossart 	 * SoundWire link so filter accordingly
3246f11586fSPierre-Louis Bossart 	 */
3256f11586fSPierre-Louis Bossart 	if ((adr & GENMASK(31, 28)) >> 28 != SDW_LINK_TYPE)
3266f11586fSPierre-Louis Bossart 		return AE_OK; /* keep going */
3276f11586fSPierre-Louis Bossart 
3286f11586fSPierre-Louis Bossart 	/* device found, stop namespace walk */
3296f11586fSPierre-Louis Bossart 	return AE_CTRL_TERMINATE;
330d62a7d41SVinod Koul }
331d62a7d41SVinod Koul 
332d62a7d41SVinod Koul /**
3336d2c6669SPierre-Louis Bossart  * sdw_intel_acpi_scan() - SoundWire Intel init routine
334d62a7d41SVinod Koul  * @parent_handle: ACPI parent handle
3356d2c6669SPierre-Louis Bossart  * @info: description of what firmware/DSDT tables expose
336d62a7d41SVinod Koul  *
3376d2c6669SPierre-Louis Bossart  * This scans the namespace and queries firmware to figure out which
3386d2c6669SPierre-Louis Bossart  * links to enable. A follow-up use of sdw_intel_probe() and
3396d2c6669SPierre-Louis Bossart  * sdw_intel_startup() is required for creation of devices and bus
3406d2c6669SPierre-Louis Bossart  * startup
341d62a7d41SVinod Koul  */
3426d2c6669SPierre-Louis Bossart int sdw_intel_acpi_scan(acpi_handle *parent_handle,
3436d2c6669SPierre-Louis Bossart 			struct sdw_intel_acpi_info *info)
344d62a7d41SVinod Koul {
345d62a7d41SVinod Koul 	acpi_status status;
346d62a7d41SVinod Koul 
347d62a7d41SVinod Koul 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
348d62a7d41SVinod Koul 				     parent_handle, 1,
349d62a7d41SVinod Koul 				     sdw_intel_acpi_cb,
3506d2c6669SPierre-Louis Bossart 				     NULL, info, NULL);
351d62a7d41SVinod Koul 	if (ACPI_FAILURE(status))
3526d2c6669SPierre-Louis Bossart 		return -ENODEV;
353d62a7d41SVinod Koul 
3546d2c6669SPierre-Louis Bossart 	return sdw_intel_scan_controller(info);
355d62a7d41SVinod Koul }
3568459cea7SPierre-Louis Bossart EXPORT_SYMBOL_NS(sdw_intel_acpi_scan, SOUNDWIRE_INTEL_INIT);
357d62a7d41SVinod Koul 
358d62a7d41SVinod Koul /**
3596d2c6669SPierre-Louis Bossart  * sdw_intel_probe() - SoundWire Intel probe routine
3606d2c6669SPierre-Louis Bossart  * @res: resource data
3616d2c6669SPierre-Louis Bossart  *
3626d2c6669SPierre-Louis Bossart  * This registers a platform device for each Master handled by the controller,
3636d2c6669SPierre-Louis Bossart  * and SoundWire Master and Slave devices will be created by the platform
3646d2c6669SPierre-Louis Bossart  * device probe. All the information necessary is stored in the context, and
3656d2c6669SPierre-Louis Bossart  * the res argument pointer can be freed after this step.
3666d2c6669SPierre-Louis Bossart  * This function will be called after sdw_intel_acpi_scan() by SOF probe.
3676d2c6669SPierre-Louis Bossart  */
3686d2c6669SPierre-Louis Bossart struct sdw_intel_ctx
3696d2c6669SPierre-Louis Bossart *sdw_intel_probe(struct sdw_intel_res *res)
3706d2c6669SPierre-Louis Bossart {
3716d2c6669SPierre-Louis Bossart 	return sdw_intel_probe_controller(res);
3726d2c6669SPierre-Louis Bossart }
3738459cea7SPierre-Louis Bossart EXPORT_SYMBOL_NS(sdw_intel_probe, SOUNDWIRE_INTEL_INIT);
3746d2c6669SPierre-Louis Bossart 
3756d2c6669SPierre-Louis Bossart /**
3766d2c6669SPierre-Louis Bossart  * sdw_intel_startup() - SoundWire Intel startup
3776d2c6669SPierre-Louis Bossart  * @ctx: SoundWire context allocated in the probe
3786d2c6669SPierre-Louis Bossart  *
3796d2c6669SPierre-Louis Bossart  * Startup Intel SoundWire controller. This function will be called after
3806d2c6669SPierre-Louis Bossart  * Intel Audio DSP is powered up.
3816d2c6669SPierre-Louis Bossart  */
3826d2c6669SPierre-Louis Bossart int sdw_intel_startup(struct sdw_intel_ctx *ctx)
3836d2c6669SPierre-Louis Bossart {
3846d2c6669SPierre-Louis Bossart 	return sdw_intel_startup_controller(ctx);
3856d2c6669SPierre-Louis Bossart }
3868459cea7SPierre-Louis Bossart EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT);
3876d2c6669SPierre-Louis Bossart /**
388d62a7d41SVinod Koul  * sdw_intel_exit() - SoundWire Intel exit
3896d2c6669SPierre-Louis Bossart  * @ctx: SoundWire context allocated in the probe
390d62a7d41SVinod Koul  *
391d62a7d41SVinod Koul  * Delete the controller instances created and cleanup
392d62a7d41SVinod Koul  */
393f98f690fSPierre-Louis Bossart void sdw_intel_exit(struct sdw_intel_ctx *ctx)
394d62a7d41SVinod Koul {
3956d2c6669SPierre-Louis Bossart 	sdw_intel_cleanup(ctx);
396d62a7d41SVinod Koul }
3978459cea7SPierre-Louis Bossart EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT);
398d62a7d41SVinod Koul 
399d62a7d41SVinod Koul MODULE_LICENSE("Dual BSD/GPL");
400d62a7d41SVinod Koul MODULE_DESCRIPTION("Intel Soundwire Init Library");
401