xref: /OK3568_Linux_fs/kernel/drivers/soundwire/intel_init.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2*4882a593Smuzhiyun // Copyright(c) 2015-17 Intel Corporation.
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun  * SDW Intel Init Routines
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Initializes and creates SDW devices based on ACPI and Hardware values
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/acpi.h>
11*4882a593Smuzhiyun #include <linux/export.h>
12*4882a593Smuzhiyun #include <linux/interrupt.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/pm_runtime.h>
17*4882a593Smuzhiyun #include <linux/soundwire/sdw_intel.h>
18*4882a593Smuzhiyun #include "cadence_master.h"
19*4882a593Smuzhiyun #include "intel.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define SDW_LINK_TYPE		4 /* from Intel ACPI documentation */
22*4882a593Smuzhiyun #define SDW_MAX_LINKS		4
23*4882a593Smuzhiyun #define SDW_SHIM_LCAP		0x0
24*4882a593Smuzhiyun #define SDW_SHIM_BASE		0x2C000
25*4882a593Smuzhiyun #define SDW_ALH_BASE		0x2C800
26*4882a593Smuzhiyun #define SDW_LINK_BASE		0x30000
27*4882a593Smuzhiyun #define SDW_LINK_SIZE		0x10000
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun static int ctrl_link_mask;
30*4882a593Smuzhiyun module_param_named(sdw_link_mask, ctrl_link_mask, int, 0444);
31*4882a593Smuzhiyun MODULE_PARM_DESC(sdw_link_mask, "Intel link mask (one bit per link)");
32*4882a593Smuzhiyun 
is_link_enabled(struct fwnode_handle * fw_node,int i)33*4882a593Smuzhiyun static bool is_link_enabled(struct fwnode_handle *fw_node, int i)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	struct fwnode_handle *link;
36*4882a593Smuzhiyun 	char name[32];
37*4882a593Smuzhiyun 	u32 quirk_mask = 0;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	/* Find master handle */
40*4882a593Smuzhiyun 	snprintf(name, sizeof(name),
41*4882a593Smuzhiyun 		 "mipi-sdw-link-%d-subproperties", i);
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	link = fwnode_get_named_child_node(fw_node, name);
44*4882a593Smuzhiyun 	if (!link)
45*4882a593Smuzhiyun 		return false;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	fwnode_property_read_u32(link,
48*4882a593Smuzhiyun 				 "intel-quirk-mask",
49*4882a593Smuzhiyun 				 &quirk_mask);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
52*4882a593Smuzhiyun 		return false;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	return true;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
sdw_intel_cleanup(struct sdw_intel_ctx * ctx)57*4882a593Smuzhiyun static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	struct sdw_intel_link_res *link = ctx->links;
60*4882a593Smuzhiyun 	u32 link_mask;
61*4882a593Smuzhiyun 	int i;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (!link)
64*4882a593Smuzhiyun 		return 0;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	link_mask = ctx->link_mask;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	for (i = 0; i < ctx->count; i++, link++) {
69*4882a593Smuzhiyun 		if (!(link_mask & BIT(i)))
70*4882a593Smuzhiyun 			continue;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 		if (link->pdev) {
73*4882a593Smuzhiyun 			pm_runtime_disable(&link->pdev->dev);
74*4882a593Smuzhiyun 			platform_device_unregister(link->pdev);
75*4882a593Smuzhiyun 		}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 		if (!link->clock_stop_quirks)
78*4882a593Smuzhiyun 			pm_runtime_put_noidle(link->dev);
79*4882a593Smuzhiyun 	}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	return 0;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun static int
sdw_intel_scan_controller(struct sdw_intel_acpi_info * info)85*4882a593Smuzhiyun sdw_intel_scan_controller(struct sdw_intel_acpi_info *info)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun 	struct acpi_device *adev;
88*4882a593Smuzhiyun 	int ret, i;
89*4882a593Smuzhiyun 	u8 count;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	if (acpi_bus_get_device(info->handle, &adev))
92*4882a593Smuzhiyun 		return -EINVAL;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	/* Found controller, find links supported */
95*4882a593Smuzhiyun 	count = 0;
96*4882a593Smuzhiyun 	ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev),
97*4882a593Smuzhiyun 					    "mipi-sdw-master-count", &count, 1);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	/*
100*4882a593Smuzhiyun 	 * In theory we could check the number of links supported in
101*4882a593Smuzhiyun 	 * hardware, but in that step we cannot assume SoundWire IP is
102*4882a593Smuzhiyun 	 * powered.
103*4882a593Smuzhiyun 	 *
104*4882a593Smuzhiyun 	 * In addition, if the BIOS doesn't even provide this
105*4882a593Smuzhiyun 	 * 'master-count' property then all the inits based on link
106*4882a593Smuzhiyun 	 * masks will fail as well.
107*4882a593Smuzhiyun 	 *
108*4882a593Smuzhiyun 	 * We will check the hardware capabilities in the startup() step
109*4882a593Smuzhiyun 	 */
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if (ret) {
112*4882a593Smuzhiyun 		dev_err(&adev->dev,
113*4882a593Smuzhiyun 			"Failed to read mipi-sdw-master-count: %d\n", ret);
114*4882a593Smuzhiyun 		return -EINVAL;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	/* Check count is within bounds */
118*4882a593Smuzhiyun 	if (count > SDW_MAX_LINKS) {
119*4882a593Smuzhiyun 		dev_err(&adev->dev, "Link count %d exceeds max %d\n",
120*4882a593Smuzhiyun 			count, SDW_MAX_LINKS);
121*4882a593Smuzhiyun 		return -EINVAL;
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	if (!count) {
125*4882a593Smuzhiyun 		dev_warn(&adev->dev, "No SoundWire links detected\n");
126*4882a593Smuzhiyun 		return -EINVAL;
127*4882a593Smuzhiyun 	}
128*4882a593Smuzhiyun 	dev_dbg(&adev->dev, "ACPI reports %d SDW Link devices\n", count);
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	info->count = count;
131*4882a593Smuzhiyun 	info->link_mask = 0;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
134*4882a593Smuzhiyun 		if (ctrl_link_mask && !(ctrl_link_mask & BIT(i))) {
135*4882a593Smuzhiyun 			dev_dbg(&adev->dev,
136*4882a593Smuzhiyun 				"Link %d masked, will not be enabled\n", i);
137*4882a593Smuzhiyun 			continue;
138*4882a593Smuzhiyun 		}
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		if (!is_link_enabled(acpi_fwnode_handle(adev), i)) {
141*4882a593Smuzhiyun 			dev_dbg(&adev->dev,
142*4882a593Smuzhiyun 				"Link %d not selected in firmware\n", i);
143*4882a593Smuzhiyun 			continue;
144*4882a593Smuzhiyun 		}
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 		info->link_mask |= BIT(i);
147*4882a593Smuzhiyun 	}
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun #define HDA_DSP_REG_ADSPIC2             (0x10)
153*4882a593Smuzhiyun #define HDA_DSP_REG_ADSPIS2             (0x14)
154*4882a593Smuzhiyun #define HDA_DSP_REG_ADSPIC2_SNDW        BIT(5)
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /**
157*4882a593Smuzhiyun  * sdw_intel_enable_irq() - enable/disable Intel SoundWire IRQ
158*4882a593Smuzhiyun  * @mmio_base: The mmio base of the control register
159*4882a593Smuzhiyun  * @enable: true if enable
160*4882a593Smuzhiyun  */
sdw_intel_enable_irq(void __iomem * mmio_base,bool enable)161*4882a593Smuzhiyun void sdw_intel_enable_irq(void __iomem *mmio_base, bool enable)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	u32 val;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	val = readl(mmio_base + HDA_DSP_REG_ADSPIC2);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	if (enable)
168*4882a593Smuzhiyun 		val |= HDA_DSP_REG_ADSPIC2_SNDW;
169*4882a593Smuzhiyun 	else
170*4882a593Smuzhiyun 		val &= ~HDA_DSP_REG_ADSPIC2_SNDW;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	writel(val, mmio_base + HDA_DSP_REG_ADSPIC2);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun EXPORT_SYMBOL_NS(sdw_intel_enable_irq, SOUNDWIRE_INTEL_INIT);
175*4882a593Smuzhiyun 
sdw_intel_thread(int irq,void * dev_id)176*4882a593Smuzhiyun irqreturn_t sdw_intel_thread(int irq, void *dev_id)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct sdw_intel_ctx *ctx = dev_id;
179*4882a593Smuzhiyun 	struct sdw_intel_link_res *link;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	list_for_each_entry(link, &ctx->link_list, list)
182*4882a593Smuzhiyun 		sdw_cdns_irq(irq, link->cdns);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	sdw_intel_enable_irq(ctx->mmio_base, true);
185*4882a593Smuzhiyun 	return IRQ_HANDLED;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun static struct sdw_intel_ctx
sdw_intel_probe_controller(struct sdw_intel_res * res)190*4882a593Smuzhiyun *sdw_intel_probe_controller(struct sdw_intel_res *res)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun 	struct platform_device_info pdevinfo;
193*4882a593Smuzhiyun 	struct platform_device *pdev;
194*4882a593Smuzhiyun 	struct sdw_intel_link_res *link;
195*4882a593Smuzhiyun 	struct sdw_intel_ctx *ctx;
196*4882a593Smuzhiyun 	struct acpi_device *adev;
197*4882a593Smuzhiyun 	struct sdw_slave *slave;
198*4882a593Smuzhiyun 	struct list_head *node;
199*4882a593Smuzhiyun 	struct sdw_bus *bus;
200*4882a593Smuzhiyun 	u32 link_mask;
201*4882a593Smuzhiyun 	int num_slaves = 0;
202*4882a593Smuzhiyun 	int count;
203*4882a593Smuzhiyun 	int i;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	if (!res)
206*4882a593Smuzhiyun 		return NULL;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	if (acpi_bus_get_device(res->handle, &adev))
209*4882a593Smuzhiyun 		return NULL;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	if (!res->count)
212*4882a593Smuzhiyun 		return NULL;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	count = res->count;
215*4882a593Smuzhiyun 	dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	ctx = devm_kzalloc(&adev->dev, sizeof(*ctx), GFP_KERNEL);
218*4882a593Smuzhiyun 	if (!ctx)
219*4882a593Smuzhiyun 		return NULL;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	ctx->count = count;
222*4882a593Smuzhiyun 	ctx->links = devm_kcalloc(&adev->dev, ctx->count,
223*4882a593Smuzhiyun 				  sizeof(*ctx->links), GFP_KERNEL);
224*4882a593Smuzhiyun 	if (!ctx->links)
225*4882a593Smuzhiyun 		return NULL;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	ctx->count = count;
228*4882a593Smuzhiyun 	ctx->mmio_base = res->mmio_base;
229*4882a593Smuzhiyun 	ctx->link_mask = res->link_mask;
230*4882a593Smuzhiyun 	ctx->handle = res->handle;
231*4882a593Smuzhiyun 	mutex_init(&ctx->shim_lock);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	link = ctx->links;
234*4882a593Smuzhiyun 	link_mask = ctx->link_mask;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ctx->link_list);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	/* Create SDW Master devices */
239*4882a593Smuzhiyun 	for (i = 0; i < count; i++, link++) {
240*4882a593Smuzhiyun 		if (!(link_mask & BIT(i))) {
241*4882a593Smuzhiyun 			dev_dbg(&adev->dev,
242*4882a593Smuzhiyun 				"Link %d masked, will not be enabled\n", i);
243*4882a593Smuzhiyun 			continue;
244*4882a593Smuzhiyun 		}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 		link->mmio_base = res->mmio_base;
247*4882a593Smuzhiyun 		link->registers = res->mmio_base + SDW_LINK_BASE
248*4882a593Smuzhiyun 			+ (SDW_LINK_SIZE * i);
249*4882a593Smuzhiyun 		link->shim = res->mmio_base + SDW_SHIM_BASE;
250*4882a593Smuzhiyun 		link->alh = res->mmio_base + SDW_ALH_BASE;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 		link->ops = res->ops;
253*4882a593Smuzhiyun 		link->dev = res->dev;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		link->clock_stop_quirks = res->clock_stop_quirks;
256*4882a593Smuzhiyun 		link->shim_lock = &ctx->shim_lock;
257*4882a593Smuzhiyun 		link->shim_mask = &ctx->shim_mask;
258*4882a593Smuzhiyun 		link->link_mask = link_mask;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 		memset(&pdevinfo, 0, sizeof(pdevinfo));
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 		pdevinfo.parent = res->parent;
263*4882a593Smuzhiyun 		pdevinfo.name = "intel-sdw";
264*4882a593Smuzhiyun 		pdevinfo.id = i;
265*4882a593Smuzhiyun 		pdevinfo.fwnode = acpi_fwnode_handle(adev);
266*4882a593Smuzhiyun 		pdevinfo.data = link;
267*4882a593Smuzhiyun 		pdevinfo.size_data = sizeof(*link);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		pdev = platform_device_register_full(&pdevinfo);
270*4882a593Smuzhiyun 		if (IS_ERR(pdev)) {
271*4882a593Smuzhiyun 			dev_err(&adev->dev,
272*4882a593Smuzhiyun 				"platform device creation failed: %ld\n",
273*4882a593Smuzhiyun 				PTR_ERR(pdev));
274*4882a593Smuzhiyun 			goto err;
275*4882a593Smuzhiyun 		}
276*4882a593Smuzhiyun 		link->pdev = pdev;
277*4882a593Smuzhiyun 		link->cdns = platform_get_drvdata(pdev);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 		list_add_tail(&link->list, &ctx->link_list);
280*4882a593Smuzhiyun 		bus = &link->cdns->bus;
281*4882a593Smuzhiyun 		/* Calculate number of slaves */
282*4882a593Smuzhiyun 		list_for_each(node, &bus->slaves)
283*4882a593Smuzhiyun 			num_slaves++;
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	ctx->ids = devm_kcalloc(&adev->dev, num_slaves,
287*4882a593Smuzhiyun 				sizeof(*ctx->ids), GFP_KERNEL);
288*4882a593Smuzhiyun 	if (!ctx->ids)
289*4882a593Smuzhiyun 		goto err;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	ctx->num_slaves = num_slaves;
292*4882a593Smuzhiyun 	i = 0;
293*4882a593Smuzhiyun 	list_for_each_entry(link, &ctx->link_list, list) {
294*4882a593Smuzhiyun 		bus = &link->cdns->bus;
295*4882a593Smuzhiyun 		list_for_each_entry(slave, &bus->slaves, node) {
296*4882a593Smuzhiyun 			ctx->ids[i].id = slave->id;
297*4882a593Smuzhiyun 			ctx->ids[i].link_id = bus->link_id;
298*4882a593Smuzhiyun 			i++;
299*4882a593Smuzhiyun 		}
300*4882a593Smuzhiyun 	}
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	return ctx;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun err:
305*4882a593Smuzhiyun 	ctx->count = i;
306*4882a593Smuzhiyun 	sdw_intel_cleanup(ctx);
307*4882a593Smuzhiyun 	return NULL;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun static int
sdw_intel_startup_controller(struct sdw_intel_ctx * ctx)311*4882a593Smuzhiyun sdw_intel_startup_controller(struct sdw_intel_ctx *ctx)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	struct acpi_device *adev;
314*4882a593Smuzhiyun 	struct sdw_intel_link_res *link;
315*4882a593Smuzhiyun 	u32 caps;
316*4882a593Smuzhiyun 	u32 link_mask;
317*4882a593Smuzhiyun 	int i;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	if (acpi_bus_get_device(ctx->handle, &adev))
320*4882a593Smuzhiyun 		return -EINVAL;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	/* Check SNDWLCAP.LCOUNT */
323*4882a593Smuzhiyun 	caps = ioread32(ctx->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
324*4882a593Smuzhiyun 	caps &= GENMASK(2, 0);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* Check HW supported vs property value */
327*4882a593Smuzhiyun 	if (caps < ctx->count) {
328*4882a593Smuzhiyun 		dev_err(&adev->dev,
329*4882a593Smuzhiyun 			"BIOS master count is larger than hardware capabilities\n");
330*4882a593Smuzhiyun 		return -EINVAL;
331*4882a593Smuzhiyun 	}
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	if (!ctx->links)
334*4882a593Smuzhiyun 		return -EINVAL;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	link = ctx->links;
337*4882a593Smuzhiyun 	link_mask = ctx->link_mask;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	/* Startup SDW Master devices */
340*4882a593Smuzhiyun 	for (i = 0; i < ctx->count; i++, link++) {
341*4882a593Smuzhiyun 		if (!(link_mask & BIT(i)))
342*4882a593Smuzhiyun 			continue;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 		intel_master_startup(link->pdev);
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 		if (!link->clock_stop_quirks) {
347*4882a593Smuzhiyun 			/*
348*4882a593Smuzhiyun 			 * we need to prevent the parent PCI device
349*4882a593Smuzhiyun 			 * from entering pm_runtime suspend, so that
350*4882a593Smuzhiyun 			 * power rails to the SoundWire IP are not
351*4882a593Smuzhiyun 			 * turned off.
352*4882a593Smuzhiyun 			 */
353*4882a593Smuzhiyun 			pm_runtime_get_noresume(link->dev);
354*4882a593Smuzhiyun 		}
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	return 0;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
sdw_intel_acpi_cb(acpi_handle handle,u32 level,void * cdata,void ** return_value)360*4882a593Smuzhiyun static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level,
361*4882a593Smuzhiyun 				     void *cdata, void **return_value)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	struct sdw_intel_acpi_info *info = cdata;
364*4882a593Smuzhiyun 	struct acpi_device *adev;
365*4882a593Smuzhiyun 	acpi_status status;
366*4882a593Smuzhiyun 	u64 adr;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
369*4882a593Smuzhiyun 	if (ACPI_FAILURE(status))
370*4882a593Smuzhiyun 		return AE_OK; /* keep going */
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	if (acpi_bus_get_device(handle, &adev)) {
373*4882a593Smuzhiyun 		pr_err("%s: Couldn't find ACPI handle\n", __func__);
374*4882a593Smuzhiyun 		return AE_NOT_FOUND;
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	info->handle = handle;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	/*
380*4882a593Smuzhiyun 	 * On some Intel platforms, multiple children of the HDAS
381*4882a593Smuzhiyun 	 * device can be found, but only one of them is the SoundWire
382*4882a593Smuzhiyun 	 * controller. The SNDW device is always exposed with
383*4882a593Smuzhiyun 	 * Name(_ADR, 0x40000000), with bits 31..28 representing the
384*4882a593Smuzhiyun 	 * SoundWire link so filter accordingly
385*4882a593Smuzhiyun 	 */
386*4882a593Smuzhiyun 	if (FIELD_GET(GENMASK(31, 28), adr) != SDW_LINK_TYPE)
387*4882a593Smuzhiyun 		return AE_OK; /* keep going */
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	/* device found, stop namespace walk */
390*4882a593Smuzhiyun 	return AE_CTRL_TERMINATE;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun /**
394*4882a593Smuzhiyun  * sdw_intel_acpi_scan() - SoundWire Intel init routine
395*4882a593Smuzhiyun  * @parent_handle: ACPI parent handle
396*4882a593Smuzhiyun  * @info: description of what firmware/DSDT tables expose
397*4882a593Smuzhiyun  *
398*4882a593Smuzhiyun  * This scans the namespace and queries firmware to figure out which
399*4882a593Smuzhiyun  * links to enable. A follow-up use of sdw_intel_probe() and
400*4882a593Smuzhiyun  * sdw_intel_startup() is required for creation of devices and bus
401*4882a593Smuzhiyun  * startup
402*4882a593Smuzhiyun  */
sdw_intel_acpi_scan(acpi_handle * parent_handle,struct sdw_intel_acpi_info * info)403*4882a593Smuzhiyun int sdw_intel_acpi_scan(acpi_handle *parent_handle,
404*4882a593Smuzhiyun 			struct sdw_intel_acpi_info *info)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun 	acpi_status status;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	info->handle = NULL;
409*4882a593Smuzhiyun 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
410*4882a593Smuzhiyun 				     parent_handle, 1,
411*4882a593Smuzhiyun 				     sdw_intel_acpi_cb,
412*4882a593Smuzhiyun 				     NULL, info, NULL);
413*4882a593Smuzhiyun 	if (ACPI_FAILURE(status) || info->handle == NULL)
414*4882a593Smuzhiyun 		return -ENODEV;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	return sdw_intel_scan_controller(info);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun EXPORT_SYMBOL_NS(sdw_intel_acpi_scan, SOUNDWIRE_INTEL_INIT);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun /**
421*4882a593Smuzhiyun  * sdw_intel_probe() - SoundWire Intel probe routine
422*4882a593Smuzhiyun  * @res: resource data
423*4882a593Smuzhiyun  *
424*4882a593Smuzhiyun  * This registers a platform device for each Master handled by the controller,
425*4882a593Smuzhiyun  * and SoundWire Master and Slave devices will be created by the platform
426*4882a593Smuzhiyun  * device probe. All the information necessary is stored in the context, and
427*4882a593Smuzhiyun  * the res argument pointer can be freed after this step.
428*4882a593Smuzhiyun  * This function will be called after sdw_intel_acpi_scan() by SOF probe.
429*4882a593Smuzhiyun  */
430*4882a593Smuzhiyun struct sdw_intel_ctx
sdw_intel_probe(struct sdw_intel_res * res)431*4882a593Smuzhiyun *sdw_intel_probe(struct sdw_intel_res *res)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun 	return sdw_intel_probe_controller(res);
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun EXPORT_SYMBOL_NS(sdw_intel_probe, SOUNDWIRE_INTEL_INIT);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun /**
438*4882a593Smuzhiyun  * sdw_intel_startup() - SoundWire Intel startup
439*4882a593Smuzhiyun  * @ctx: SoundWire context allocated in the probe
440*4882a593Smuzhiyun  *
441*4882a593Smuzhiyun  * Startup Intel SoundWire controller. This function will be called after
442*4882a593Smuzhiyun  * Intel Audio DSP is powered up.
443*4882a593Smuzhiyun  */
sdw_intel_startup(struct sdw_intel_ctx * ctx)444*4882a593Smuzhiyun int sdw_intel_startup(struct sdw_intel_ctx *ctx)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun 	return sdw_intel_startup_controller(ctx);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT);
449*4882a593Smuzhiyun /**
450*4882a593Smuzhiyun  * sdw_intel_exit() - SoundWire Intel exit
451*4882a593Smuzhiyun  * @ctx: SoundWire context allocated in the probe
452*4882a593Smuzhiyun  *
453*4882a593Smuzhiyun  * Delete the controller instances created and cleanup
454*4882a593Smuzhiyun  */
sdw_intel_exit(struct sdw_intel_ctx * ctx)455*4882a593Smuzhiyun void sdw_intel_exit(struct sdw_intel_ctx *ctx)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	sdw_intel_cleanup(ctx);
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT);
460*4882a593Smuzhiyun 
sdw_intel_process_wakeen_event(struct sdw_intel_ctx * ctx)461*4882a593Smuzhiyun void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun 	struct sdw_intel_link_res *link;
464*4882a593Smuzhiyun 	u32 link_mask;
465*4882a593Smuzhiyun 	int i;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	if (!ctx->links)
468*4882a593Smuzhiyun 		return;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	link = ctx->links;
471*4882a593Smuzhiyun 	link_mask = ctx->link_mask;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	/* Startup SDW Master devices */
474*4882a593Smuzhiyun 	for (i = 0; i < ctx->count; i++, link++) {
475*4882a593Smuzhiyun 		if (!(link_mask & BIT(i)))
476*4882a593Smuzhiyun 			continue;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 		intel_master_process_wakeen_event(link->pdev);
479*4882a593Smuzhiyun 	}
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT);
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
484*4882a593Smuzhiyun MODULE_DESCRIPTION("Intel Soundwire Init Library");
485