Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2011-2017, The Linux Foundation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include "slimbus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * slim_ctrl_clk_pause() - Called by slimbus controller to enter/exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *			   'clock pause'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * @ctrl: controller requesting bus to be paused or woken up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * @wakeup: Wakeup this controller from clock pause.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * @restart: Restart time value per spec used for clock pause. This value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *	isn't used when controller is to be woken up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * Slimbus specification needs this sequence to turn-off clocks for the bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * The sequence involves sending 3 broadcast messages (reconfiguration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * sequence) to inform all devices on the bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * To exit clock-pause, controller typically wakes up active framer device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * This API executes clock pause reconfiguration sequence if wakeup is false.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * If wakeup is true, controller's wakeup is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * For entering clock-pause, -EBUSY is returned if a message txn in pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	struct slim_sched *sched = &ctrl->sched;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	struct slim_val_inf msg = {0, 0, NULL, NULL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_MC_BEGIN_RECONFIGURATION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 				3, SLIM_LA_MANAGER, &msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	if (wakeup == false && restart > SLIM_CLK_UNSPECIFIED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	mutex_lock(&sched->m_reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	if (wakeup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		if (sched->clk_state == SLIM_CLK_ACTIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 			mutex_unlock(&sched->m_reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		 * Fine-tune calculation based on clock gear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		 * message-bandwidth after bandwidth management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		ret = wait_for_completion_timeout(&sched->pause_comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 				msecs_to_jiffies(100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			mutex_unlock(&sched->m_reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 			pr_err("Previous clock pause did not finish");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 			return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		 * Slimbus framework will call controller wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		 * Controller should make sure that it sets active framer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		 * out of clock pause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		if (sched->clk_state == SLIM_CLK_PAUSED && ctrl->wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 			ret = ctrl->wakeup(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			sched->clk_state = SLIM_CLK_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		mutex_unlock(&sched->m_reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	/* already paused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (ctrl->sched.clk_state == SLIM_CLK_PAUSED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		mutex_unlock(&sched->m_reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	spin_lock_irqsave(&ctrl->txn_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	for (i = 0; i < SLIM_MAX_TIDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		/* Pending response for a message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		if (idr_find(&ctrl->tid_idr, i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			spin_unlock_irqrestore(&ctrl->txn_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 			mutex_unlock(&sched->m_reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	sched->clk_state = SLIM_CLK_ENTERING_PAUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	/* clock pause sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	ret = slim_do_transfer(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		goto clk_pause_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	txn.mc = SLIM_MSG_MC_NEXT_PAUSE_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	txn.rl = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	msg.num_bytes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	msg.wbuf = &restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	ret = slim_do_transfer(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		goto clk_pause_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	txn.mc = SLIM_MSG_MC_RECONFIGURE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	txn.rl = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	msg.num_bytes = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	msg.wbuf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	ret = slim_do_transfer(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) clk_pause_ret:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		sched->clk_state = SLIM_CLK_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		sched->clk_state = SLIM_CLK_PAUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		complete(&sched->pause_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	mutex_unlock(&sched->m_reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) EXPORT_SYMBOL_GPL(slim_ctrl_clk_pause);