Lines Matching +full:pm +full:- +full:bus

1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 // Copyright(c) 2015-22 Intel Corporation.
22 #include "bus.h"
32 * flags reused in each byte, with master0 using the ls-byte, etc.
77 if (slave->id.part_id == wake_capable_list[i].part_id && in is_wake_capable()
78 slave->id.mfg_id == wake_capable_list[i].mfg_id) in is_wake_capable()
83 static int generic_bpt_send_async(struct sdw_bus *bus, struct sdw_slave *slave, in generic_bpt_send_async() argument
86 struct sdw_cdns *cdns = bus_to_cdns(bus); in generic_bpt_send_async()
89 if (sdw->link_res->hw_ops->bpt_send_async) in generic_bpt_send_async()
90 return sdw->link_res->hw_ops->bpt_send_async(sdw, slave, msg); in generic_bpt_send_async()
91 return -EOPNOTSUPP; in generic_bpt_send_async()
94 static int generic_bpt_wait(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg) in generic_bpt_wait() argument
96 struct sdw_cdns *cdns = bus_to_cdns(bus); in generic_bpt_wait()
99 if (sdw->link_res->hw_ops->bpt_wait) in generic_bpt_wait()
100 return sdw->link_res->hw_ops->bpt_wait(sdw, slave, msg); in generic_bpt_wait()
101 return -EOPNOTSUPP; in generic_bpt_wait()
104 static int generic_pre_bank_switch(struct sdw_bus *bus) in generic_pre_bank_switch() argument
106 struct sdw_cdns *cdns = bus_to_cdns(bus); in generic_pre_bank_switch()
109 return sdw->link_res->hw_ops->pre_bank_switch(sdw); in generic_pre_bank_switch()
112 static int generic_post_bank_switch(struct sdw_bus *bus) in generic_post_bank_switch() argument
114 struct sdw_cdns *cdns = bus_to_cdns(bus); in generic_post_bank_switch()
117 return sdw->link_res->hw_ops->post_bank_switch(sdw); in generic_post_bank_switch()
120 static void generic_new_peripheral_assigned(struct sdw_bus *bus, in generic_new_peripheral_assigned() argument
124 struct sdw_cdns *cdns = bus_to_cdns(bus); in generic_new_peripheral_assigned()
128 bool wake_capable = slave->prop.wake_capable || is_wake_capable(slave); in generic_new_peripheral_assigned()
135 dev_num_max = SDW_INTEL_DEV_NUM_IDA_MIN - 1; in generic_new_peripheral_assigned()
140 dev_err(bus->dev, "%s: invalid dev_num %d, wake supported %d\n", in generic_new_peripheral_assigned()
141 __func__, dev_num, slave->prop.wake_capable); in generic_new_peripheral_assigned()
145 if (sdw->link_res->hw_ops->program_sdi && wake_capable) in generic_new_peripheral_assigned()
146 sdw->link_res->hw_ops->program_sdi(sdw, dev_num); in generic_new_peripheral_assigned()
149 static int sdw_master_read_intel_prop(struct sdw_bus *bus) in sdw_master_read_intel_prop() argument
151 struct sdw_master_prop *prop = &bus->prop; in sdw_master_read_intel_prop()
159 "mipi-sdw-link-%d-subproperties", bus->link_id); in sdw_master_read_intel_prop()
161 link = device_get_named_child_node(bus->dev, name); in sdw_master_read_intel_prop()
163 dev_err(bus->dev, "Master node %s not found\n", name); in sdw_master_read_intel_prop()
164 return -EIO; in sdw_master_read_intel_prop()
168 "intel-sdw-ip-clock", in sdw_master_read_intel_prop()
169 &prop->mclk_freq); in sdw_master_read_intel_prop()
172 /* use kernel parameter for BIOS or board work-arounds */ in sdw_master_read_intel_prop()
173 prop->mclk_freq /= mclk_divider; in sdw_master_read_intel_prop()
175 /* the values reported by BIOS are the 2x clock, not the bus clock */ in sdw_master_read_intel_prop()
176 prop->mclk_freq /= 2; in sdw_master_read_intel_prop()
179 "intel-quirk-mask", in sdw_master_read_intel_prop()
183 prop->hw_disabled = true; in sdw_master_read_intel_prop()
185 prop->quirks = SDW_MASTER_QUIRKS_CLEAR_INITIAL_CLASH | in sdw_master_read_intel_prop()
188 intel_prop = devm_kzalloc(bus->dev, sizeof(*intel_prop), GFP_KERNEL); in sdw_master_read_intel_prop()
191 return -ENOMEM; in sdw_master_read_intel_prop()
195 intel_prop->clde = 0x0; in sdw_master_read_intel_prop()
196 intel_prop->doaise2 = 0x0; in sdw_master_read_intel_prop()
197 intel_prop->dodse2 = 0x0; in sdw_master_read_intel_prop()
198 intel_prop->clds = 0x0; in sdw_master_read_intel_prop()
199 intel_prop->clss = 0x0; in sdw_master_read_intel_prop()
200 intel_prop->doaise = 0x1; in sdw_master_read_intel_prop()
201 intel_prop->doais = 0x3; in sdw_master_read_intel_prop()
202 intel_prop->dodse = 0x0; in sdw_master_read_intel_prop()
203 intel_prop->dods = 0x1; in sdw_master_read_intel_prop()
206 "intel-sdw-clde", in sdw_master_read_intel_prop()
207 &intel_prop->clde); in sdw_master_read_intel_prop()
209 "intel-sdw-doaise2", in sdw_master_read_intel_prop()
210 &intel_prop->doaise2); in sdw_master_read_intel_prop()
212 "intel-sdw-dodse2", in sdw_master_read_intel_prop()
213 &intel_prop->dodse2); in sdw_master_read_intel_prop()
215 "intel-sdw-clds", in sdw_master_read_intel_prop()
216 &intel_prop->clds); in sdw_master_read_intel_prop()
218 "intel-sdw-clss", in sdw_master_read_intel_prop()
219 &intel_prop->clss); in sdw_master_read_intel_prop()
221 "intel-sdw-doaise", in sdw_master_read_intel_prop()
222 &intel_prop->doaise); in sdw_master_read_intel_prop()
224 "intel-sdw-doais", in sdw_master_read_intel_prop()
225 &intel_prop->doais); in sdw_master_read_intel_prop()
227 "intel-sdw-dodse", in sdw_master_read_intel_prop()
228 &intel_prop->dodse); in sdw_master_read_intel_prop()
230 "intel-sdw-dods", in sdw_master_read_intel_prop()
231 &intel_prop->dods); in sdw_master_read_intel_prop()
232 bus->vendor_specific_prop = intel_prop; in sdw_master_read_intel_prop()
234 dev_dbg(bus->dev, "doaise %#x doais %#x dodse %#x dods %#x\n", in sdw_master_read_intel_prop()
235 intel_prop->doaise, in sdw_master_read_intel_prop()
236 intel_prop->doais, in sdw_master_read_intel_prop()
237 intel_prop->dodse, in sdw_master_read_intel_prop()
238 intel_prop->dods); in sdw_master_read_intel_prop()
245 static int intel_prop_read(struct sdw_bus *bus) in intel_prop_read() argument
248 sdw_master_read_prop(bus); in intel_prop_read()
250 /* read Intel-specific properties */ in intel_prop_read()
251 sdw_master_read_intel_prop(bus); in intel_prop_read()
258 static int intel_get_device_num_ida(struct sdw_bus *bus, struct sdw_slave *slave) in intel_get_device_num_ida() argument
262 if (slave->prop.wake_capable || is_wake_capable(slave)) in intel_get_device_num_ida()
267 bit = find_first_zero_bit(slave->bus->assigned, SDW_MAX_DEVICES); in intel_get_device_num_ida()
269 return -ENODEV; in intel_get_device_num_ida()
274 static void intel_put_device_num_ida(struct sdw_bus *bus, struct sdw_slave *slave) in intel_put_device_num_ida() argument
276 if (slave->prop.wake_capable || is_wake_capable(slave)) in intel_put_device_num_ida()
277 ida_free(&intel_peripheral_ida, slave->dev_num); in intel_put_device_num_ida()
304 struct device *dev = &auxdev->dev; in intel_link_probe()
308 struct sdw_bus *bus; in intel_link_probe() local
313 return -ENOMEM; in intel_link_probe()
315 cdns = &sdw->cdns; in intel_link_probe()
316 bus = &cdns->bus; in intel_link_probe()
318 sdw->instance = auxdev->id; in intel_link_probe()
319 sdw->link_res = &ldev->link_res; in intel_link_probe()
320 cdns->dev = dev; in intel_link_probe()
321 cdns->registers = sdw->link_res->registers; in intel_link_probe()
322 cdns->ip_offset = sdw->link_res->ip_offset; in intel_link_probe()
323 cdns->instance = sdw->instance; in intel_link_probe()
324 cdns->msg_count = 0; in intel_link_probe()
327 bus->controller_id = 0; in intel_link_probe()
329 bus->link_id = auxdev->id; in intel_link_probe()
330 bus->clk_stop_timeout = 1; in intel_link_probe()
333 * paranoia check: make sure ACPI-reported number of links is aligned with in intel_link_probe()
341 if (ret <= sdw->instance) { in intel_link_probe()
342 dev_err(dev, "%s: invalid link id %d, link count %d\n", __func__, auxdev->id, ret); in intel_link_probe()
343 return -EINVAL; in intel_link_probe()
349 bus->ops = &sdw_intel_ops; in intel_link_probe()
355 sdw->cdns.bus.compute_params = sdw_compute_params; in intel_link_probe()
357 ret = sdw_bus_master_add(bus, dev, dev->fwnode); in intel_link_probe()
363 if (bus->prop.hw_disabled) in intel_link_probe()
366 bus->link_id); in intel_link_probe()
371 bus->prop.err_threshold = 0; in intel_link_probe()
378 struct device *dev = &auxdev->dev; in intel_link_startup()
381 struct sdw_bus *bus = &cdns->bus; in intel_link_startup() local
387 if (bus->prop.hw_disabled) { in intel_link_startup()
390 sdw->instance); in intel_link_startup()
394 link_flags = md_flags >> (bus->link_id * 8); in intel_link_startup()
397 dev_dbg(dev, "Multi-link is disabled\n"); in intel_link_startup()
400 * hardware-based synchronization is required regardless in intel_link_startup()
401 * of the number of segments used by a stream: SSP-based in intel_link_startup()
402 * synchronization is gated by gsync when the multi-master in intel_link_startup()
405 bus->hw_sync_min_links = 1; in intel_link_startup()
407 bus->multi_link = multi_link; in intel_link_startup()
423 /* Enable runtime PM */ in intel_link_startup()
433 pm_runtime_resume(bus->dev); in intel_link_startup()
436 /* start bus */ in intel_link_startup()
439 dev_err(dev, "bus start failed: %d\n", ret); in intel_link_startup()
443 clock_stop_quirks = sdw->link_res->clock_stop_quirks; in intel_link_startup()
458 * The runtime PM status of Slave devices is "Unsupported" in intel_link_startup()
460 * there are no Slave devices populated or if the power-on is in intel_link_startup()
464 * Conditionally force the pm_runtime core to re-evaluate the in intel_link_startup()
471 pm_runtime_mark_last_busy(bus->dev); in intel_link_startup()
476 sdw->startup_done = true; in intel_link_startup()
492 struct sdw_bus *bus = &cdns->bus; in intel_link_remove() local
499 if (!bus->prop.hw_disabled) { in intel_link_remove()
501 cancel_delayed_work_sync(&cdns->attach_dwork); in intel_link_remove()
504 sdw_bus_master_delete(bus); in intel_link_remove()
509 struct device *dev = &auxdev->dev; in intel_link_process_wakeen_event()
511 struct sdw_bus *bus; in intel_link_process_wakeen_event() local
514 bus = &sdw->cdns.bus; in intel_link_process_wakeen_event()
516 if (bus->prop.hw_disabled || !sdw->startup_done) { in intel_link_process_wakeen_event()
517 dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n", in intel_link_process_wakeen_event()
518 bus->link_id); in intel_link_process_wakeen_event()
529 * resume the Master, which will generate a bus reset and result in in intel_link_process_wakeen_event()
530 * Slaves re-attaching and be re-enumerated. The SoundWire physical in intel_link_process_wakeen_event()
541 * PM calls
549 if (!slave->probed) { in intel_resume_child_device()
553 if (!slave->dev_num_sticky) { in intel_resume_child_device()
554 dev_dbg(dev, "skipping device, never detected on bus\n"); in intel_resume_child_device()
571 struct sdw_bus *bus = &cdns->bus; in intel_pm_prepare() local
575 if (bus->prop.hw_disabled || !sdw->startup_done) { in intel_pm_prepare()
576 dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n", in intel_pm_prepare()
577 bus->link_id); in intel_pm_prepare()
581 clock_stop_quirks = sdw->link_res->clock_stop_quirks; in intel_pm_prepare()
584 pm_runtime_suspended(dev->parent) && in intel_pm_prepare()
590 * The only solution is to resume the entire bus to full power in intel_pm_prepare()
610 * Continue resuming the entire bus (parent + child devices) to exit in intel_pm_prepare()
612 * this is a no-op. in intel_pm_prepare()
615 * of code to handle an Intel-specific corner case. It is simpler in in intel_pm_prepare()
618 ret = device_for_each_child(bus->dev, NULL, intel_resume_child_device); in intel_pm_prepare()
631 struct sdw_bus *bus = &cdns->bus; in intel_suspend() local
635 if (bus->prop.hw_disabled || !sdw->startup_done) { in intel_suspend()
636 dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n", in intel_suspend()
637 bus->link_id); in intel_suspend()
641 /* Prevent runtime PM from racing with the code below. */ in intel_suspend()
647 clock_stop_quirks = sdw->link_res->clock_stop_quirks; in intel_suspend()
652 if (pm_runtime_status_suspended(dev->parent)) { in intel_suspend()
668 dev_err(dev, "%s: cannot stop bus: %d\n", __func__, ret); in intel_suspend()
679 struct sdw_bus *bus = &cdns->bus; in intel_suspend_runtime() local
683 if (bus->prop.hw_disabled || !sdw->startup_done) { in intel_suspend_runtime()
684 dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n", in intel_suspend_runtime()
685 bus->link_id); in intel_suspend_runtime()
689 clock_stop_quirks = sdw->link_res->clock_stop_quirks; in intel_suspend_runtime()
694 dev_err(dev, "%s: cannot stop bus during teardown: %d\n", in intel_suspend_runtime()
701 dev_err(dev, "%s: cannot stop bus during clock_stop: %d\n", in intel_suspend_runtime()
708 ret = -EINVAL; in intel_suspend_runtime()
718 struct sdw_bus *bus = &cdns->bus; in intel_resume() local
721 if (bus->prop.hw_disabled || !sdw->startup_done) { in intel_resume()
722 dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n", in intel_resume()
723 bus->link_id); in intel_resume()
737 sdw_clear_slave_status(bus, SDW_UNATTACH_REQUEST_MASTER_RESET); in intel_resume()
741 dev_err(dev, "cannot start bus during resume\n"); in intel_resume()
747 * Runtime PM has been disabled in intel_suspend(), so set the status in intel_resume()
748 * to active because the device has just been resumed and re-enable in intel_resume()
749 * runtime PM. in intel_resume()
764 pm_runtime_mark_last_busy(bus->dev); in intel_resume()
774 struct sdw_bus *bus = &cdns->bus; in intel_resume_runtime() local
778 if (bus->prop.hw_disabled || !sdw->startup_done) { in intel_resume_runtime()
779 dev_dbg(dev, "SoundWire master %d is disabled or not-started, ignoring\n", in intel_resume_runtime()
780 bus->link_id); in intel_resume_runtime()
787 clock_stop_quirks = sdw->link_res->clock_stop_quirks; in intel_resume_runtime()
800 sdw_clear_slave_status(bus, SDW_UNATTACH_REQUEST_MASTER_RESET); in intel_resume_runtime()
804 dev_err(dev, "%s: cannot start bus after teardown: %d\n", __func__, ret); in intel_resume_runtime()
812 dev_err(dev, "%s: power_up failed after bus reset: %d\n", __func__, ret); in intel_resume_runtime()
818 dev_err(dev, "%s: cannot start bus after reset: %d\n", __func__, ret); in intel_resume_runtime()
834 dev_err(dev, "%s: cannot start bus after clock stop: %d\n", __func__, ret); in intel_resume_runtime()
841 ret = -EINVAL; in intel_resume_runtime()
864 .pm = &intel_pm,