18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2011-2017, The Linux Foundation
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/slab.h>
78c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
88c2ecf20Sopenharmony_ci#include "slimbus.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/**
118c2ecf20Sopenharmony_ci * slim_msg_response() - Deliver Message response received from a device to the
128c2ecf20Sopenharmony_ci *			framework.
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * @ctrl: Controller handle
158c2ecf20Sopenharmony_ci * @reply: Reply received from the device
168c2ecf20Sopenharmony_ci * @len: Length of the reply
178c2ecf20Sopenharmony_ci * @tid: Transaction ID received with which framework can associate reply.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * Called by controller to inform framework about the response received.
208c2ecf20Sopenharmony_ci * This helps in making the API asynchronous, and controller-driver doesn't need
218c2ecf20Sopenharmony_ci * to manage 1 more table other than the one managed by framework mapping TID
228c2ecf20Sopenharmony_ci * with buffers
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_civoid slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	struct slim_msg_txn *txn;
278c2ecf20Sopenharmony_ci	struct slim_val_inf *msg;
288c2ecf20Sopenharmony_ci	unsigned long flags;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ctrl->txn_lock, flags);
318c2ecf20Sopenharmony_ci	txn = idr_find(&ctrl->tid_idr, tid);
328c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	if (txn == NULL)
358c2ecf20Sopenharmony_ci		return;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	msg = txn->msg;
388c2ecf20Sopenharmony_ci	if (msg == NULL || msg->rbuf == NULL) {
398c2ecf20Sopenharmony_ci		dev_err(ctrl->dev, "Got response to invalid TID:%d, len:%d\n",
408c2ecf20Sopenharmony_ci				tid, len);
418c2ecf20Sopenharmony_ci		return;
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	slim_free_txn_tid(ctrl, txn);
458c2ecf20Sopenharmony_ci	memcpy(msg->rbuf, reply, len);
468c2ecf20Sopenharmony_ci	if (txn->comp)
478c2ecf20Sopenharmony_ci		complete(txn->comp);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	/* Remove runtime-pm vote now that response was received for TID txn */
508c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(ctrl->dev);
518c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(ctrl->dev);
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_msg_response);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/**
568c2ecf20Sopenharmony_ci * slim_alloc_txn_tid() - Allocate a tid to txn
578c2ecf20Sopenharmony_ci *
588c2ecf20Sopenharmony_ci * @ctrl: Controller handle
598c2ecf20Sopenharmony_ci * @txn: transaction to be allocated with tid.
608c2ecf20Sopenharmony_ci *
618c2ecf20Sopenharmony_ci * Return: zero on success with valid txn->tid and error code on failures.
628c2ecf20Sopenharmony_ci */
638c2ecf20Sopenharmony_ciint slim_alloc_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	unsigned long flags;
668c2ecf20Sopenharmony_ci	int ret = 0;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ctrl->txn_lock, flags);
698c2ecf20Sopenharmony_ci	ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 1,
708c2ecf20Sopenharmony_ci				SLIM_MAX_TIDS, GFP_ATOMIC);
718c2ecf20Sopenharmony_ci	if (ret < 0) {
728c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&ctrl->txn_lock, flags);
738c2ecf20Sopenharmony_ci		return ret;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci	txn->tid = ret;
768c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
778c2ecf20Sopenharmony_ci	return 0;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_alloc_txn_tid);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/**
828c2ecf20Sopenharmony_ci * slim_free_txn_tid() - Freee tid of txn
838c2ecf20Sopenharmony_ci *
848c2ecf20Sopenharmony_ci * @ctrl: Controller handle
858c2ecf20Sopenharmony_ci * @txn: transaction whose tid should be freed
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_civoid slim_free_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	unsigned long flags;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ctrl->txn_lock, flags);
928c2ecf20Sopenharmony_ci	idr_remove(&ctrl->tid_idr, txn->tid);
938c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_free_txn_tid);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/**
988c2ecf20Sopenharmony_ci * slim_do_transfer() - Process a SLIMbus-messaging transaction
998c2ecf20Sopenharmony_ci *
1008c2ecf20Sopenharmony_ci * @ctrl: Controller handle
1018c2ecf20Sopenharmony_ci * @txn: Transaction to be sent over SLIMbus
1028c2ecf20Sopenharmony_ci *
1038c2ecf20Sopenharmony_ci * Called by controller to transmit messaging transactions not dealing with
1048c2ecf20Sopenharmony_ci * Interface/Value elements. (e.g. transmittting a message to assign logical
1058c2ecf20Sopenharmony_ci * address to a slave device
1068c2ecf20Sopenharmony_ci *
1078c2ecf20Sopenharmony_ci * Return: -ETIMEDOUT: If transmission of this message timed out
1088c2ecf20Sopenharmony_ci *	(e.g. due to bus lines not being clocked or driven by controller)
1098c2ecf20Sopenharmony_ci */
1108c2ecf20Sopenharmony_ciint slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	DECLARE_COMPLETION_ONSTACK(done);
1138c2ecf20Sopenharmony_ci	bool need_tid = false, clk_pause_msg = false;
1148c2ecf20Sopenharmony_ci	int ret, timeout;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	/*
1178c2ecf20Sopenharmony_ci	 * do not vote for runtime-PM if the transactions are part of clock
1188c2ecf20Sopenharmony_ci	 * pause sequence
1198c2ecf20Sopenharmony_ci	 */
1208c2ecf20Sopenharmony_ci	if (ctrl->sched.clk_state == SLIM_CLK_ENTERING_PAUSE &&
1218c2ecf20Sopenharmony_ci		(txn->mt == SLIM_MSG_MT_CORE &&
1228c2ecf20Sopenharmony_ci		 txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
1238c2ecf20Sopenharmony_ci		 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
1248c2ecf20Sopenharmony_ci		clk_pause_msg = true;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if (!clk_pause_msg) {
1278c2ecf20Sopenharmony_ci		ret = pm_runtime_get_sync(ctrl->dev);
1288c2ecf20Sopenharmony_ci		if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) {
1298c2ecf20Sopenharmony_ci			dev_err(ctrl->dev, "ctrl wrong state:%d, ret:%d\n",
1308c2ecf20Sopenharmony_ci				ctrl->sched.clk_state, ret);
1318c2ecf20Sopenharmony_ci			goto slim_xfer_err;
1328c2ecf20Sopenharmony_ci		}
1338c2ecf20Sopenharmony_ci	}
1348c2ecf20Sopenharmony_ci	/* Initialize tid to invalid value */
1358c2ecf20Sopenharmony_ci	txn->tid = 0;
1368c2ecf20Sopenharmony_ci	need_tid = slim_tid_txn(txn->mt, txn->mc);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	if (need_tid) {
1398c2ecf20Sopenharmony_ci		ret = slim_alloc_txn_tid(ctrl, txn);
1408c2ecf20Sopenharmony_ci		if (ret)
1418c2ecf20Sopenharmony_ci			return ret;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci		if (!txn->msg->comp)
1448c2ecf20Sopenharmony_ci			txn->comp = &done;
1458c2ecf20Sopenharmony_ci		else
1468c2ecf20Sopenharmony_ci			txn->comp = txn->comp;
1478c2ecf20Sopenharmony_ci	}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	ret = ctrl->xfer_msg(ctrl, txn);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	if (!ret && need_tid && !txn->msg->comp) {
1528c2ecf20Sopenharmony_ci		unsigned long ms = txn->rl + HZ;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci		timeout = wait_for_completion_timeout(txn->comp,
1558c2ecf20Sopenharmony_ci						      msecs_to_jiffies(ms));
1568c2ecf20Sopenharmony_ci		if (!timeout) {
1578c2ecf20Sopenharmony_ci			ret = -ETIMEDOUT;
1588c2ecf20Sopenharmony_ci			slim_free_txn_tid(ctrl, txn);
1598c2ecf20Sopenharmony_ci		}
1608c2ecf20Sopenharmony_ci	}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	if (ret)
1638c2ecf20Sopenharmony_ci		dev_err(ctrl->dev, "Tx:MT:0x%x, MC:0x%x, LA:0x%x failed:%d\n",
1648c2ecf20Sopenharmony_ci			txn->mt, txn->mc, txn->la, ret);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cislim_xfer_err:
1678c2ecf20Sopenharmony_ci	if (!clk_pause_msg && (txn->tid == 0  || ret == -ETIMEDOUT)) {
1688c2ecf20Sopenharmony_ci		/*
1698c2ecf20Sopenharmony_ci		 * remove runtime-pm vote if this was TX only, or
1708c2ecf20Sopenharmony_ci		 * if there was error during this transaction
1718c2ecf20Sopenharmony_ci		 */
1728c2ecf20Sopenharmony_ci		pm_runtime_mark_last_busy(ctrl->dev);
1738c2ecf20Sopenharmony_ci		pm_runtime_put_autosuspend(ctrl->dev);
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci	return ret;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_do_transfer);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic int slim_val_inf_sanity(struct slim_controller *ctrl,
1808c2ecf20Sopenharmony_ci			       struct slim_val_inf *msg, u8 mc)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	if (!msg || msg->num_bytes > 16 ||
1838c2ecf20Sopenharmony_ci	    (msg->start_offset + msg->num_bytes) > 0xC00)
1848c2ecf20Sopenharmony_ci		goto reterr;
1858c2ecf20Sopenharmony_ci	switch (mc) {
1868c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_REQUEST_VALUE:
1878c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_REQUEST_INFORMATION:
1888c2ecf20Sopenharmony_ci		if (msg->rbuf != NULL)
1898c2ecf20Sopenharmony_ci			return 0;
1908c2ecf20Sopenharmony_ci		break;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_CHANGE_VALUE:
1938c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_CLEAR_INFORMATION:
1948c2ecf20Sopenharmony_ci		if (msg->wbuf != NULL)
1958c2ecf20Sopenharmony_ci			return 0;
1968c2ecf20Sopenharmony_ci		break;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_REQUEST_CHANGE_VALUE:
1998c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION:
2008c2ecf20Sopenharmony_ci		if (msg->rbuf != NULL && msg->wbuf != NULL)
2018c2ecf20Sopenharmony_ci			return 0;
2028c2ecf20Sopenharmony_ci		break;
2038c2ecf20Sopenharmony_ci	}
2048c2ecf20Sopenharmony_cireterr:
2058c2ecf20Sopenharmony_ci	if (msg)
2068c2ecf20Sopenharmony_ci		dev_err(ctrl->dev, "Sanity check failed:msg:offset:0x%x, mc:%d\n",
2078c2ecf20Sopenharmony_ci			msg->start_offset, mc);
2088c2ecf20Sopenharmony_ci	return -EINVAL;
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic u16 slim_slicesize(int code)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	static const u8 sizetocode[16] = {
2148c2ecf20Sopenharmony_ci		0, 1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7
2158c2ecf20Sopenharmony_ci	};
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	code = clamp(code, 1, (int)ARRAY_SIZE(sizetocode));
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	return sizetocode[code - 1];
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/**
2238c2ecf20Sopenharmony_ci * slim_xfer_msg() - Transfer a value info message on slim device
2248c2ecf20Sopenharmony_ci *
2258c2ecf20Sopenharmony_ci * @sbdev: slim device to which this msg has to be transfered
2268c2ecf20Sopenharmony_ci * @msg: value info message pointer
2278c2ecf20Sopenharmony_ci * @mc: message code of the message
2288c2ecf20Sopenharmony_ci *
2298c2ecf20Sopenharmony_ci * Called by drivers which want to transfer a vlaue or info elements.
2308c2ecf20Sopenharmony_ci *
2318c2ecf20Sopenharmony_ci * Return: -ETIMEDOUT: If transmission of this message timed out
2328c2ecf20Sopenharmony_ci */
2338c2ecf20Sopenharmony_ciint slim_xfer_msg(struct slim_device *sbdev, struct slim_val_inf *msg,
2348c2ecf20Sopenharmony_ci		  u8 mc)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	DEFINE_SLIM_LDEST_TXN(txn_stack, mc, 6, sbdev->laddr, msg);
2378c2ecf20Sopenharmony_ci	struct slim_msg_txn *txn = &txn_stack;
2388c2ecf20Sopenharmony_ci	struct slim_controller *ctrl = sbdev->ctrl;
2398c2ecf20Sopenharmony_ci	int ret;
2408c2ecf20Sopenharmony_ci	u16 sl;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (!ctrl)
2438c2ecf20Sopenharmony_ci		return -EINVAL;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	ret = slim_val_inf_sanity(ctrl, msg, mc);
2468c2ecf20Sopenharmony_ci	if (ret)
2478c2ecf20Sopenharmony_ci		return ret;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	sl = slim_slicesize(msg->num_bytes);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	dev_dbg(ctrl->dev, "SB xfer msg:os:%x, len:%d, MC:%x, sl:%x\n",
2528c2ecf20Sopenharmony_ci		msg->start_offset, msg->num_bytes, mc, sl);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	txn->ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4));
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	switch (mc) {
2578c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_REQUEST_CHANGE_VALUE:
2588c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_CHANGE_VALUE:
2598c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION:
2608c2ecf20Sopenharmony_ci	case SLIM_MSG_MC_CLEAR_INFORMATION:
2618c2ecf20Sopenharmony_ci		txn->rl += msg->num_bytes;
2628c2ecf20Sopenharmony_ci	default:
2638c2ecf20Sopenharmony_ci		break;
2648c2ecf20Sopenharmony_ci	}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	if (slim_tid_txn(txn->mt, txn->mc))
2678c2ecf20Sopenharmony_ci		txn->rl++;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	return slim_do_transfer(ctrl, txn);
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_xfer_msg);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic void slim_fill_msg(struct slim_val_inf *msg, u32 addr,
2748c2ecf20Sopenharmony_ci			 size_t count, u8 *rbuf, u8 *wbuf)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	msg->start_offset = addr;
2778c2ecf20Sopenharmony_ci	msg->num_bytes = count;
2788c2ecf20Sopenharmony_ci	msg->rbuf = rbuf;
2798c2ecf20Sopenharmony_ci	msg->wbuf = wbuf;
2808c2ecf20Sopenharmony_ci	msg->comp = NULL;
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci/**
2848c2ecf20Sopenharmony_ci * slim_read() - Read SLIMbus value element
2858c2ecf20Sopenharmony_ci *
2868c2ecf20Sopenharmony_ci * @sdev: client handle.
2878c2ecf20Sopenharmony_ci * @addr:  address of value element to read.
2888c2ecf20Sopenharmony_ci * @count: number of bytes to read. Maximum bytes allowed are 16.
2898c2ecf20Sopenharmony_ci * @val: will return what the value element value was
2908c2ecf20Sopenharmony_ci *
2918c2ecf20Sopenharmony_ci * Return: -EINVAL for Invalid parameters, -ETIMEDOUT If transmission of
2928c2ecf20Sopenharmony_ci * this message timed out (e.g. due to bus lines not being clocked
2938c2ecf20Sopenharmony_ci * or driven by controller)
2948c2ecf20Sopenharmony_ci */
2958c2ecf20Sopenharmony_ciint slim_read(struct slim_device *sdev, u32 addr, size_t count, u8 *val)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	struct slim_val_inf msg;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	slim_fill_msg(&msg, addr, count, val, NULL);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	return slim_xfer_msg(sdev, &msg, SLIM_MSG_MC_REQUEST_VALUE);
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_read);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci/**
3068c2ecf20Sopenharmony_ci * slim_readb() - Read byte from SLIMbus value element
3078c2ecf20Sopenharmony_ci *
3088c2ecf20Sopenharmony_ci * @sdev: client handle.
3098c2ecf20Sopenharmony_ci * @addr:  address in the value element to read.
3108c2ecf20Sopenharmony_ci *
3118c2ecf20Sopenharmony_ci * Return: byte value of value element.
3128c2ecf20Sopenharmony_ci */
3138c2ecf20Sopenharmony_ciint slim_readb(struct slim_device *sdev, u32 addr)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	int ret;
3168c2ecf20Sopenharmony_ci	u8 buf;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	ret = slim_read(sdev, addr, 1, &buf);
3198c2ecf20Sopenharmony_ci	if (ret < 0)
3208c2ecf20Sopenharmony_ci		return ret;
3218c2ecf20Sopenharmony_ci	else
3228c2ecf20Sopenharmony_ci		return buf;
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_readb);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci/**
3278c2ecf20Sopenharmony_ci * slim_write() - Write SLIMbus value element
3288c2ecf20Sopenharmony_ci *
3298c2ecf20Sopenharmony_ci * @sdev: client handle.
3308c2ecf20Sopenharmony_ci * @addr:  address in the value element to write.
3318c2ecf20Sopenharmony_ci * @count: number of bytes to write. Maximum bytes allowed are 16.
3328c2ecf20Sopenharmony_ci * @val: value to write to value element
3338c2ecf20Sopenharmony_ci *
3348c2ecf20Sopenharmony_ci * Return: -EINVAL for Invalid parameters, -ETIMEDOUT If transmission of
3358c2ecf20Sopenharmony_ci * this message timed out (e.g. due to bus lines not being clocked
3368c2ecf20Sopenharmony_ci * or driven by controller)
3378c2ecf20Sopenharmony_ci */
3388c2ecf20Sopenharmony_ciint slim_write(struct slim_device *sdev, u32 addr, size_t count, u8 *val)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	struct slim_val_inf msg;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	slim_fill_msg(&msg, addr, count,  NULL, val);
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	return slim_xfer_msg(sdev, &msg, SLIM_MSG_MC_CHANGE_VALUE);
3458c2ecf20Sopenharmony_ci}
3468c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_write);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci/**
3498c2ecf20Sopenharmony_ci * slim_writeb() - Write byte to SLIMbus value element
3508c2ecf20Sopenharmony_ci *
3518c2ecf20Sopenharmony_ci * @sdev: client handle.
3528c2ecf20Sopenharmony_ci * @addr:  address of value element to write.
3538c2ecf20Sopenharmony_ci * @value: value to write to value element
3548c2ecf20Sopenharmony_ci *
3558c2ecf20Sopenharmony_ci * Return: -EINVAL for Invalid parameters, -ETIMEDOUT If transmission of
3568c2ecf20Sopenharmony_ci * this message timed out (e.g. due to bus lines not being clocked
3578c2ecf20Sopenharmony_ci * or driven by controller)
3588c2ecf20Sopenharmony_ci *
3598c2ecf20Sopenharmony_ci */
3608c2ecf20Sopenharmony_ciint slim_writeb(struct slim_device *sdev, u32 addr, u8 value)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	return slim_write(sdev, addr, 1, &value);
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(slim_writeb);
365