1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // Copyright(c) 2015-2023 Intel Corporation. All rights reserved. 3 4 #include <linux/acpi.h> 5 #include <linux/soundwire/sdw_registers.h> 6 #include <linux/soundwire/sdw.h> 7 #include <linux/soundwire/sdw_intel.h> 8 #include "cadence_master.h" 9 #include "bus.h" 10 #include "intel.h" 11 12 int intel_start_bus(struct sdw_intel *sdw) 13 { 14 struct device *dev = sdw->cdns.dev; 15 struct sdw_cdns *cdns = &sdw->cdns; 16 struct sdw_bus *bus = &cdns->bus; 17 int ret; 18 19 ret = sdw_cdns_enable_interrupt(cdns, true); 20 if (ret < 0) { 21 dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret); 22 return ret; 23 } 24 25 /* 26 * follow recommended programming flows to avoid timeouts when 27 * gsync is enabled 28 */ 29 if (bus->multi_link) 30 sdw_intel_sync_arm(sdw); 31 32 ret = sdw_cdns_init(cdns); 33 if (ret < 0) { 34 dev_err(dev, "%s: unable to initialize Cadence IP: %d\n", __func__, ret); 35 goto err_interrupt; 36 } 37 38 ret = sdw_cdns_exit_reset(cdns); 39 if (ret < 0) { 40 dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret); 41 goto err_interrupt; 42 } 43 44 if (bus->multi_link) { 45 ret = sdw_intel_sync_go(sdw); 46 if (ret < 0) { 47 dev_err(dev, "%s: sync go failed: %d\n", __func__, ret); 48 goto err_interrupt; 49 } 50 } 51 sdw_cdns_check_self_clearing_bits(cdns, __func__, 52 true, INTEL_MASTER_RESET_ITERATIONS); 53 54 return 0; 55 56 err_interrupt: 57 sdw_cdns_enable_interrupt(cdns, false); 58 return ret; 59 } 60 61 int intel_start_bus_after_reset(struct sdw_intel *sdw) 62 { 63 struct device *dev = sdw->cdns.dev; 64 struct sdw_cdns *cdns = &sdw->cdns; 65 struct sdw_bus *bus = &cdns->bus; 66 bool clock_stop0; 67 int status; 68 int ret; 69 70 /* 71 * An exception condition occurs for the CLK_STOP_BUS_RESET 72 * case if one or more masters remain active. In this condition, 73 * all the masters are powered on for they are in the same power 74 * domain. Master can preserve its context for clock stop0, so 75 * there is no need to clear slave status and reset bus. 76 */ 77 clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns); 78 79 if (!clock_stop0) { 80 81 /* 82 * make sure all Slaves are tagged as UNATTACHED and 83 * provide reason for reinitialization 84 */ 85 86 status = SDW_UNATTACH_REQUEST_MASTER_RESET; 87 sdw_clear_slave_status(bus, status); 88 89 ret = sdw_cdns_enable_interrupt(cdns, true); 90 if (ret < 0) { 91 dev_err(dev, "cannot enable interrupts during resume\n"); 92 return ret; 93 } 94 95 /* 96 * follow recommended programming flows to avoid 97 * timeouts when gsync is enabled 98 */ 99 if (bus->multi_link) 100 sdw_intel_sync_arm(sdw); 101 102 /* 103 * Re-initialize the IP since it was powered-off 104 */ 105 sdw_cdns_init(&sdw->cdns); 106 107 } else { 108 ret = sdw_cdns_enable_interrupt(cdns, true); 109 if (ret < 0) { 110 dev_err(dev, "cannot enable interrupts during resume\n"); 111 return ret; 112 } 113 } 114 115 ret = sdw_cdns_clock_restart(cdns, !clock_stop0); 116 if (ret < 0) { 117 dev_err(dev, "unable to restart clock during resume\n"); 118 goto err_interrupt; 119 } 120 121 if (!clock_stop0) { 122 ret = sdw_cdns_exit_reset(cdns); 123 if (ret < 0) { 124 dev_err(dev, "unable to exit bus reset sequence during resume\n"); 125 goto err_interrupt; 126 } 127 128 if (bus->multi_link) { 129 ret = sdw_intel_sync_go(sdw); 130 if (ret < 0) { 131 dev_err(sdw->cdns.dev, "sync go failed during resume\n"); 132 goto err_interrupt; 133 } 134 } 135 } 136 sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS); 137 138 return 0; 139 140 err_interrupt: 141 sdw_cdns_enable_interrupt(cdns, false); 142 return ret; 143 } 144 145 void intel_check_clock_stop(struct sdw_intel *sdw) 146 { 147 struct device *dev = sdw->cdns.dev; 148 bool clock_stop0; 149 150 clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns); 151 if (!clock_stop0) 152 dev_err(dev, "%s: invalid configuration, clock was not stopped\n", __func__); 153 } 154 155 int intel_start_bus_after_clock_stop(struct sdw_intel *sdw) 156 { 157 struct device *dev = sdw->cdns.dev; 158 struct sdw_cdns *cdns = &sdw->cdns; 159 int ret; 160 161 ret = sdw_cdns_enable_interrupt(cdns, true); 162 if (ret < 0) { 163 dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret); 164 return ret; 165 } 166 167 ret = sdw_cdns_clock_restart(cdns, false); 168 if (ret < 0) { 169 dev_err(dev, "%s: unable to restart clock: %d\n", __func__, ret); 170 sdw_cdns_enable_interrupt(cdns, false); 171 return ret; 172 } 173 174 sdw_cdns_check_self_clearing_bits(cdns, "intel_resume_runtime no_quirks", 175 true, INTEL_MASTER_RESET_ITERATIONS); 176 177 return 0; 178 } 179 180 int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop) 181 { 182 struct device *dev = sdw->cdns.dev; 183 struct sdw_cdns *cdns = &sdw->cdns; 184 bool wake_enable = false; 185 int ret; 186 187 if (clock_stop) { 188 ret = sdw_cdns_clock_stop(cdns, true); 189 if (ret < 0) 190 dev_err(dev, "%s: cannot stop clock: %d\n", __func__, ret); 191 else 192 wake_enable = true; 193 } 194 195 ret = sdw_cdns_enable_interrupt(cdns, false); 196 if (ret < 0) { 197 dev_err(dev, "%s: cannot disable interrupts: %d\n", __func__, ret); 198 return ret; 199 } 200 201 ret = sdw_intel_link_power_down(sdw); 202 if (ret) { 203 dev_err(dev, "%s: Link power down failed: %d\n", __func__, ret); 204 return ret; 205 } 206 207 sdw_intel_shim_wake(sdw, wake_enable); 208 209 return 0; 210 } 211 212 /* 213 * bank switch routines 214 */ 215 216 int intel_pre_bank_switch(struct sdw_intel *sdw) 217 { 218 struct sdw_cdns *cdns = &sdw->cdns; 219 struct sdw_bus *bus = &cdns->bus; 220 221 /* Write to register only for multi-link */ 222 if (!bus->multi_link) 223 return 0; 224 225 sdw_intel_sync_arm(sdw); 226 227 return 0; 228 } 229 230 int intel_post_bank_switch(struct sdw_intel *sdw) 231 { 232 struct sdw_cdns *cdns = &sdw->cdns; 233 struct sdw_bus *bus = &cdns->bus; 234 int ret = 0; 235 236 /* Write to register only for multi-link */ 237 if (!bus->multi_link) 238 return 0; 239 240 mutex_lock(sdw->link_res->shim_lock); 241 242 /* 243 * post_bank_switch() ops is called from the bus in loop for 244 * all the Masters in the steam with the expectation that 245 * we trigger the bankswitch for the only first Master in the list 246 * and do nothing for the other Masters 247 * 248 * So, set the SYNCGO bit only if CMDSYNC bit is set for any Master. 249 */ 250 if (sdw_intel_sync_check_cmdsync_unlocked(sdw)) 251 ret = sdw_intel_sync_go_unlocked(sdw); 252 253 mutex_unlock(sdw->link_res->shim_lock); 254 255 if (ret < 0) 256 dev_err(sdw->cdns.dev, "Post bank switch failed: %d\n", ret); 257 258 return ret; 259 } 260