1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2022 Linaro Ltd.
4 * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
7 #include <linux/errno.h>
8 #include <linux/mhi_ep.h>
11 bool __must_check
mhi_ep_check_mhi_state(struct mhi_ep_cntrl
*mhi_cntrl
,
12 enum mhi_state cur_mhi_state
,
13 enum mhi_state mhi_state
)
15 if (mhi_state
== MHI_STATE_SYS_ERR
)
16 return true; /* Allowed in any state */
18 if (mhi_state
== MHI_STATE_READY
)
19 return cur_mhi_state
== MHI_STATE_RESET
;
21 if (mhi_state
== MHI_STATE_M0
)
22 return cur_mhi_state
== MHI_STATE_M3
|| cur_mhi_state
== MHI_STATE_READY
;
24 if (mhi_state
== MHI_STATE_M3
)
25 return cur_mhi_state
== MHI_STATE_M0
;
30 int mhi_ep_set_mhi_state(struct mhi_ep_cntrl
*mhi_cntrl
, enum mhi_state mhi_state
)
32 struct device
*dev
= &mhi_cntrl
->mhi_dev
->dev
;
34 if (!mhi_ep_check_mhi_state(mhi_cntrl
, mhi_cntrl
->mhi_state
, mhi_state
)) {
35 dev_err(dev
, "MHI state change to %s from %s is not allowed!\n",
36 mhi_state_str(mhi_state
),
37 mhi_state_str(mhi_cntrl
->mhi_state
));
41 /* TODO: Add support for M1 and M2 states */
42 if (mhi_state
== MHI_STATE_M1
|| mhi_state
== MHI_STATE_M2
) {
43 dev_err(dev
, "MHI state (%s) not supported\n", mhi_state_str(mhi_state
));
47 mhi_ep_mmio_masked_write(mhi_cntrl
, EP_MHISTATUS
, MHISTATUS_MHISTATE_MASK
, mhi_state
);
48 mhi_cntrl
->mhi_state
= mhi_state
;
50 if (mhi_state
== MHI_STATE_READY
)
51 mhi_ep_mmio_masked_write(mhi_cntrl
, EP_MHISTATUS
, MHISTATUS_READY_MASK
, 1);
53 if (mhi_state
== MHI_STATE_SYS_ERR
)
54 mhi_ep_mmio_masked_write(mhi_cntrl
, EP_MHISTATUS
, MHISTATUS_SYSERR_MASK
, 1);
59 int mhi_ep_set_m0_state(struct mhi_ep_cntrl
*mhi_cntrl
)
61 struct device
*dev
= &mhi_cntrl
->mhi_dev
->dev
;
62 enum mhi_state old_state
;
65 /* If MHI is in M3, resume suspended channels */
66 mutex_lock(&mhi_cntrl
->state_lock
);
68 old_state
= mhi_cntrl
->mhi_state
;
69 if (old_state
== MHI_STATE_M3
)
70 mhi_ep_resume_channels(mhi_cntrl
);
72 ret
= mhi_ep_set_mhi_state(mhi_cntrl
, MHI_STATE_M0
);
74 mhi_ep_handle_syserr(mhi_cntrl
);
78 /* Signal host that the device moved to M0 */
79 ret
= mhi_ep_send_state_change_event(mhi_cntrl
, MHI_STATE_M0
);
81 dev_err(dev
, "Failed sending M0 state change event\n");
85 if (old_state
== MHI_STATE_READY
) {
86 /* Send AMSS EE event to host */
87 ret
= mhi_ep_send_ee_event(mhi_cntrl
, MHI_EE_AMSS
);
89 dev_err(dev
, "Failed sending AMSS EE event\n");
95 mutex_unlock(&mhi_cntrl
->state_lock
);
100 int mhi_ep_set_m3_state(struct mhi_ep_cntrl
*mhi_cntrl
)
102 struct device
*dev
= &mhi_cntrl
->mhi_dev
->dev
;
105 mutex_lock(&mhi_cntrl
->state_lock
);
107 ret
= mhi_ep_set_mhi_state(mhi_cntrl
, MHI_STATE_M3
);
109 mhi_ep_handle_syserr(mhi_cntrl
);
113 mhi_ep_suspend_channels(mhi_cntrl
);
115 /* Signal host that the device moved to M3 */
116 ret
= mhi_ep_send_state_change_event(mhi_cntrl
, MHI_STATE_M3
);
118 dev_err(dev
, "Failed sending M3 state change event\n");
123 mutex_unlock(&mhi_cntrl
->state_lock
);
128 int mhi_ep_set_ready_state(struct mhi_ep_cntrl
*mhi_cntrl
)
130 struct device
*dev
= &mhi_cntrl
->mhi_dev
->dev
;
131 enum mhi_state mhi_state
;
134 mutex_lock(&mhi_cntrl
->state_lock
);
136 /* Ensure that the MHISTATUS is set to RESET by host */
137 mhi_state
= mhi_ep_mmio_masked_read(mhi_cntrl
, EP_MHISTATUS
, MHISTATUS_MHISTATE_MASK
);
138 is_ready
= mhi_ep_mmio_masked_read(mhi_cntrl
, EP_MHISTATUS
, MHISTATUS_READY_MASK
);
140 if (mhi_state
!= MHI_STATE_RESET
|| is_ready
) {
141 dev_err(dev
, "READY state transition failed. MHI host not in RESET state\n");
146 ret
= mhi_ep_set_mhi_state(mhi_cntrl
, MHI_STATE_READY
);
148 mhi_ep_handle_syserr(mhi_cntrl
);
151 mutex_unlock(&mhi_cntrl
->state_lock
);