0001
0002
0003
0004
0005
0006 #include "iosm_ipc_protocol.h"
0007
0008
0009 #define IPC_PM_ACTIVE_TIMEOUT_MS (500)
0010
0011
0012
0013
0014 #define IPC_PM_SLEEP (0)
0015 #define CONSUME_STATE (0)
0016 #define IPC_PM_ACTIVE (1)
0017
0018 void ipc_pm_signal_hpda_doorbell(struct iosm_pm *ipc_pm, u32 identifier,
0019 bool host_slp_check)
0020 {
0021 if (host_slp_check && ipc_pm->host_pm_state != IPC_MEM_HOST_PM_ACTIVE &&
0022 ipc_pm->host_pm_state != IPC_MEM_HOST_PM_ACTIVE_WAIT) {
0023 ipc_pm->pending_hpda_update = true;
0024 dev_dbg(ipc_pm->dev,
0025 "Pend HPDA update set. Host PM_State: %d identifier:%d",
0026 ipc_pm->host_pm_state, identifier);
0027 return;
0028 }
0029
0030 if (!ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_IRQ, true)) {
0031 ipc_pm->pending_hpda_update = true;
0032 dev_dbg(ipc_pm->dev, "Pending HPDA update set. identifier:%d",
0033 identifier);
0034 return;
0035 }
0036 ipc_pm->pending_hpda_update = false;
0037
0038
0039 ipc_cp_irq_hpda_update(ipc_pm->pcie, identifier);
0040
0041 ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_IRQ, false);
0042 }
0043
0044
0045 static bool ipc_pm_link_activate(struct iosm_pm *ipc_pm)
0046 {
0047 if (ipc_pm->cp_state == IPC_MEM_DEV_PM_ACTIVE)
0048 return true;
0049
0050 if (ipc_pm->cp_state == IPC_MEM_DEV_PM_SLEEP) {
0051 if (ipc_pm->ap_state == IPC_MEM_DEV_PM_SLEEP) {
0052
0053 ipc_cp_irq_sleep_control(ipc_pm->pcie,
0054 IPC_MEM_DEV_PM_WAKEUP);
0055 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE_WAIT;
0056
0057 goto not_active;
0058 }
0059
0060 if (ipc_pm->ap_state == IPC_MEM_DEV_PM_ACTIVE_WAIT)
0061 goto not_active;
0062
0063 return true;
0064 }
0065
0066 not_active:
0067
0068 return false;
0069 }
0070
0071 bool ipc_pm_wait_for_device_active(struct iosm_pm *ipc_pm)
0072 {
0073 bool ret_val = false;
0074
0075 if (ipc_pm->ap_state != IPC_MEM_DEV_PM_ACTIVE) {
0076
0077 smp_mb__before_atomic();
0078
0079
0080
0081
0082 set_bit(0, &ipc_pm->host_sleep_pend);
0083
0084
0085 smp_mb__after_atomic();
0086
0087 if (!wait_for_completion_interruptible_timeout
0088 (&ipc_pm->host_sleep_complete,
0089 msecs_to_jiffies(IPC_PM_ACTIVE_TIMEOUT_MS))) {
0090 dev_err(ipc_pm->dev,
0091 "PM timeout. Expected State:%d. Actual: %d",
0092 IPC_MEM_DEV_PM_ACTIVE, ipc_pm->ap_state);
0093 goto active_timeout;
0094 }
0095 }
0096
0097 ret_val = true;
0098 active_timeout:
0099
0100 smp_mb__before_atomic();
0101
0102
0103
0104
0105 clear_bit(0, &ipc_pm->host_sleep_pend);
0106
0107
0108 smp_mb__after_atomic();
0109
0110 return ret_val;
0111 }
0112
0113 static void ipc_pm_on_link_sleep(struct iosm_pm *ipc_pm)
0114 {
0115
0116
0117
0118 ipc_pm->cp_state = IPC_MEM_DEV_PM_SLEEP;
0119 ipc_pm->ap_state = IPC_MEM_DEV_PM_SLEEP;
0120
0121 ipc_cp_irq_sleep_control(ipc_pm->pcie, IPC_MEM_DEV_PM_SLEEP);
0122 }
0123
0124 static void ipc_pm_on_link_wake(struct iosm_pm *ipc_pm, bool ack)
0125 {
0126 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE;
0127
0128 if (ack) {
0129 ipc_pm->cp_state = IPC_MEM_DEV_PM_ACTIVE;
0130
0131 ipc_cp_irq_sleep_control(ipc_pm->pcie, IPC_MEM_DEV_PM_ACTIVE);
0132
0133
0134 if (test_bit(CONSUME_STATE, &ipc_pm->host_sleep_pend))
0135 complete(&ipc_pm->host_sleep_complete);
0136 }
0137
0138
0139
0140
0141
0142
0143
0144 if (ipc_pm->pending_hpda_update &&
0145 ipc_pm->host_pm_state == IPC_MEM_HOST_PM_ACTIVE)
0146 ipc_pm_signal_hpda_doorbell(ipc_pm, IPC_HP_PM_TRIGGER, true);
0147 }
0148
0149 bool ipc_pm_trigger(struct iosm_pm *ipc_pm, enum ipc_pm_unit unit, bool active)
0150 {
0151 union ipc_pm_cond old_cond;
0152 union ipc_pm_cond new_cond;
0153 bool link_active;
0154
0155
0156 new_cond = ipc_pm->pm_cond;
0157 old_cond = ipc_pm->pm_cond;
0158
0159
0160 switch (unit) {
0161 case IPC_PM_UNIT_IRQ:
0162 new_cond.irq = active;
0163 break;
0164
0165 case IPC_PM_UNIT_LINK:
0166 new_cond.link = active;
0167 break;
0168
0169 case IPC_PM_UNIT_HS:
0170 new_cond.hs = active;
0171 break;
0172
0173 default:
0174 break;
0175 }
0176
0177
0178 if (old_cond.raw == new_cond.raw) {
0179
0180 link_active = old_cond.link == IPC_PM_ACTIVE;
0181 goto ret;
0182 }
0183
0184 ipc_pm->pm_cond = new_cond;
0185
0186 if (new_cond.link)
0187 ipc_pm_on_link_wake(ipc_pm, unit == IPC_PM_UNIT_LINK);
0188 else if (unit == IPC_PM_UNIT_LINK)
0189 ipc_pm_on_link_sleep(ipc_pm);
0190
0191 if (old_cond.link == IPC_PM_SLEEP && new_cond.raw) {
0192 link_active = ipc_pm_link_activate(ipc_pm);
0193 goto ret;
0194 }
0195
0196 link_active = old_cond.link == IPC_PM_ACTIVE;
0197
0198 ret:
0199 return link_active;
0200 }
0201
0202 bool ipc_pm_prepare_host_sleep(struct iosm_pm *ipc_pm)
0203 {
0204
0205 if (ipc_pm->host_pm_state != IPC_MEM_HOST_PM_ACTIVE) {
0206 dev_err(ipc_pm->dev, "host_pm_state=%d\tExpected to be: %d",
0207 ipc_pm->host_pm_state, IPC_MEM_HOST_PM_ACTIVE);
0208 return false;
0209 }
0210
0211 ipc_pm->host_pm_state = IPC_MEM_HOST_PM_SLEEP_WAIT_D3;
0212
0213 return true;
0214 }
0215
0216 bool ipc_pm_prepare_host_active(struct iosm_pm *ipc_pm)
0217 {
0218 if (ipc_pm->host_pm_state != IPC_MEM_HOST_PM_SLEEP) {
0219 dev_err(ipc_pm->dev, "host_pm_state=%d\tExpected to be: %d",
0220 ipc_pm->host_pm_state, IPC_MEM_HOST_PM_SLEEP);
0221 return false;
0222 }
0223
0224
0225 ipc_pm->host_pm_state = IPC_MEM_HOST_PM_ACTIVE_WAIT;
0226
0227 return true;
0228 }
0229
0230 void ipc_pm_set_s2idle_sleep(struct iosm_pm *ipc_pm, bool sleep)
0231 {
0232 if (sleep) {
0233 ipc_pm->ap_state = IPC_MEM_DEV_PM_SLEEP;
0234 ipc_pm->cp_state = IPC_MEM_DEV_PM_SLEEP;
0235 ipc_pm->device_sleep_notification = IPC_MEM_DEV_PM_SLEEP;
0236 } else {
0237 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE;
0238 ipc_pm->cp_state = IPC_MEM_DEV_PM_ACTIVE;
0239 ipc_pm->device_sleep_notification = IPC_MEM_DEV_PM_ACTIVE;
0240 ipc_pm->pm_cond.link = IPC_PM_ACTIVE;
0241 }
0242 }
0243
0244 bool ipc_pm_dev_slp_notification(struct iosm_pm *ipc_pm, u32 cp_pm_req)
0245 {
0246 if (cp_pm_req == ipc_pm->device_sleep_notification)
0247 return false;
0248
0249 ipc_pm->device_sleep_notification = cp_pm_req;
0250
0251
0252 switch (ipc_pm->cp_state) {
0253 case IPC_MEM_DEV_PM_ACTIVE:
0254 switch (cp_pm_req) {
0255 case IPC_MEM_DEV_PM_ACTIVE:
0256 break;
0257
0258 case IPC_MEM_DEV_PM_SLEEP:
0259
0260 ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_LINK, false);
0261 return true;
0262
0263 default:
0264 dev_err(ipc_pm->dev,
0265 "loc-pm=%d active: confused req-pm=%d",
0266 ipc_pm->cp_state, cp_pm_req);
0267 break;
0268 }
0269 break;
0270
0271 case IPC_MEM_DEV_PM_SLEEP:
0272 switch (cp_pm_req) {
0273 case IPC_MEM_DEV_PM_ACTIVE:
0274
0275 ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_LINK, true);
0276 break;
0277
0278 case IPC_MEM_DEV_PM_SLEEP:
0279 break;
0280
0281 default:
0282 dev_err(ipc_pm->dev,
0283 "loc-pm=%d sleep: confused req-pm=%d",
0284 ipc_pm->cp_state, cp_pm_req);
0285 break;
0286 }
0287 break;
0288
0289 default:
0290 dev_err(ipc_pm->dev, "confused loc-pm=%d, req-pm=%d",
0291 ipc_pm->cp_state, cp_pm_req);
0292 break;
0293 }
0294
0295 return false;
0296 }
0297
0298 void ipc_pm_init(struct iosm_protocol *ipc_protocol)
0299 {
0300 struct iosm_imem *ipc_imem = ipc_protocol->imem;
0301 struct iosm_pm *ipc_pm = &ipc_protocol->pm;
0302
0303 ipc_pm->pcie = ipc_imem->pcie;
0304 ipc_pm->dev = ipc_imem->dev;
0305
0306 ipc_pm->pm_cond.irq = IPC_PM_SLEEP;
0307 ipc_pm->pm_cond.hs = IPC_PM_SLEEP;
0308 ipc_pm->pm_cond.link = IPC_PM_ACTIVE;
0309
0310 ipc_pm->cp_state = IPC_MEM_DEV_PM_ACTIVE;
0311 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE;
0312 ipc_pm->host_pm_state = IPC_MEM_HOST_PM_ACTIVE;
0313
0314
0315
0316
0317 init_completion(&ipc_pm->host_sleep_complete);
0318
0319
0320 smp_mb__before_atomic();
0321
0322 clear_bit(0, &ipc_pm->host_sleep_pend);
0323
0324
0325 smp_mb__after_atomic();
0326 }
0327
0328 void ipc_pm_deinit(struct iosm_protocol *proto)
0329 {
0330 struct iosm_pm *ipc_pm = &proto->pm;
0331
0332 complete(&ipc_pm->host_sleep_complete);
0333 }