Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Manivannan Sadhasivam | 597 | 100.00% | 6 | 100.00% |
Total | 597 | 6 |
// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2022 Linaro Ltd. * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> */ #include <linux/errno.h> #include <linux/mhi_ep.h> #include "internal.h" bool __must_check mhi_ep_check_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state cur_mhi_state, enum mhi_state mhi_state) { if (mhi_state == MHI_STATE_SYS_ERR) return true; /* Allowed in any state */ if (mhi_state == MHI_STATE_READY) return cur_mhi_state == MHI_STATE_RESET; if (mhi_state == MHI_STATE_M0) return cur_mhi_state == MHI_STATE_M3 || cur_mhi_state == MHI_STATE_READY; if (mhi_state == MHI_STATE_M3) return cur_mhi_state == MHI_STATE_M0; return false; } int mhi_ep_set_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state mhi_state) { struct device *dev = &mhi_cntrl->mhi_dev->dev; if (!mhi_ep_check_mhi_state(mhi_cntrl, mhi_cntrl->mhi_state, mhi_state)) { dev_err(dev, "MHI state change to %s from %s is not allowed!\n", mhi_state_str(mhi_state), mhi_state_str(mhi_cntrl->mhi_state)); return -EACCES; } /* TODO: Add support for M1 and M2 states */ if (mhi_state == MHI_STATE_M1 || mhi_state == MHI_STATE_M2) { dev_err(dev, "MHI state (%s) not supported\n", mhi_state_str(mhi_state)); return -EOPNOTSUPP; } mhi_ep_mmio_masked_write(mhi_cntrl, EP_MHISTATUS, MHISTATUS_MHISTATE_MASK, mhi_state); mhi_cntrl->mhi_state = mhi_state; if (mhi_state == MHI_STATE_READY) mhi_ep_mmio_masked_write(mhi_cntrl, EP_MHISTATUS, MHISTATUS_READY_MASK, 1); if (mhi_state == MHI_STATE_SYS_ERR) mhi_ep_mmio_masked_write(mhi_cntrl, EP_MHISTATUS, MHISTATUS_SYSERR_MASK, 1); return 0; } int mhi_ep_set_m0_state(struct mhi_ep_cntrl *mhi_cntrl) { struct device *dev = &mhi_cntrl->mhi_dev->dev; enum mhi_state old_state; int ret; /* If MHI is in M3, resume suspended channels */ mutex_lock(&mhi_cntrl->state_lock); old_state = mhi_cntrl->mhi_state; if (old_state == MHI_STATE_M3) mhi_ep_resume_channels(mhi_cntrl); ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_M0); if (ret) { mhi_ep_handle_syserr(mhi_cntrl); goto err_unlock; } /* Signal host that the device moved to M0 */ ret = mhi_ep_send_state_change_event(mhi_cntrl, MHI_STATE_M0); if (ret) { dev_err(dev, "Failed sending M0 state change event\n"); goto err_unlock; } if (old_state == MHI_STATE_READY) { /* Send AMSS EE event to host */ ret = mhi_ep_send_ee_event(mhi_cntrl, MHI_EE_AMSS); if (ret) { dev_err(dev, "Failed sending AMSS EE event\n"); goto err_unlock; } } err_unlock: mutex_unlock(&mhi_cntrl->state_lock); return ret; } int mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl) { struct device *dev = &mhi_cntrl->mhi_dev->dev; int ret; mutex_lock(&mhi_cntrl->state_lock); ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_M3); if (ret) { mhi_ep_handle_syserr(mhi_cntrl); goto err_unlock; } mhi_ep_suspend_channels(mhi_cntrl); /* Signal host that the device moved to M3 */ ret = mhi_ep_send_state_change_event(mhi_cntrl, MHI_STATE_M3); if (ret) { dev_err(dev, "Failed sending M3 state change event\n"); goto err_unlock; } err_unlock: mutex_unlock(&mhi_cntrl->state_lock); return ret; } int mhi_ep_set_ready_state(struct mhi_ep_cntrl *mhi_cntrl) { struct device *dev = &mhi_cntrl->mhi_dev->dev; enum mhi_state mhi_state; int ret, is_ready; mutex_lock(&mhi_cntrl->state_lock); /* Ensure that the MHISTATUS is set to RESET by host */ mhi_state = mhi_ep_mmio_masked_read(mhi_cntrl, EP_MHISTATUS, MHISTATUS_MHISTATE_MASK); is_ready = mhi_ep_mmio_masked_read(mhi_cntrl, EP_MHISTATUS, MHISTATUS_READY_MASK); if (mhi_state != MHI_STATE_RESET || is_ready) { dev_err(dev, "READY state transition failed. MHI host not in RESET state\n"); ret = -EIO; goto err_unlock; } ret = mhi_ep_set_mhi_state(mhi_cntrl, MHI_STATE_READY); if (ret) mhi_ep_handle_syserr(mhi_cntrl); err_unlock: mutex_unlock(&mhi_cntrl->state_lock); return ret; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1