xref: /openbmc/linux/drivers/slimbus/messaging.c (revision 8ebc80a25f9d9bf7a8e368b266d5b740c485c362)
1afbdcc7cSSagar Dharia // SPDX-License-Identifier: GPL-2.0
2afbdcc7cSSagar Dharia /*
3afbdcc7cSSagar Dharia  * Copyright (c) 2011-2017, The Linux Foundation
4afbdcc7cSSagar Dharia  */
5afbdcc7cSSagar Dharia 
6afbdcc7cSSagar Dharia #include <linux/slab.h>
74b14e62aSSagar Dharia #include <linux/pm_runtime.h>
8afbdcc7cSSagar Dharia #include "slimbus.h"
9afbdcc7cSSagar Dharia 
10afbdcc7cSSagar Dharia /**
11afbdcc7cSSagar Dharia  * slim_msg_response() - Deliver Message response received from a device to the
12afbdcc7cSSagar Dharia  *			framework.
13afbdcc7cSSagar Dharia  *
14afbdcc7cSSagar Dharia  * @ctrl: Controller handle
15afbdcc7cSSagar Dharia  * @reply: Reply received from the device
16afbdcc7cSSagar Dharia  * @len: Length of the reply
17afbdcc7cSSagar Dharia  * @tid: Transaction ID received with which framework can associate reply.
18afbdcc7cSSagar Dharia  *
19afbdcc7cSSagar Dharia  * Called by controller to inform framework about the response received.
20afbdcc7cSSagar Dharia  * This helps in making the API asynchronous, and controller-driver doesn't need
21afbdcc7cSSagar Dharia  * to manage 1 more table other than the one managed by framework mapping TID
22afbdcc7cSSagar Dharia  * with buffers
23afbdcc7cSSagar Dharia  */
slim_msg_response(struct slim_controller * ctrl,u8 * reply,u8 tid,u8 len)24afbdcc7cSSagar Dharia void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len)
25afbdcc7cSSagar Dharia {
26afbdcc7cSSagar Dharia 	struct slim_msg_txn *txn;
27afbdcc7cSSagar Dharia 	struct slim_val_inf *msg;
28afbdcc7cSSagar Dharia 	unsigned long flags;
29afbdcc7cSSagar Dharia 
30afbdcc7cSSagar Dharia 	spin_lock_irqsave(&ctrl->txn_lock, flags);
31afbdcc7cSSagar Dharia 	txn = idr_find(&ctrl->tid_idr, tid);
32afbdcc7cSSagar Dharia 	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
33d3062a21SSrinivas Kandagatla 
34d3062a21SSrinivas Kandagatla 	if (txn == NULL)
35afbdcc7cSSagar Dharia 		return;
36afbdcc7cSSagar Dharia 
37afbdcc7cSSagar Dharia 	msg = txn->msg;
38afbdcc7cSSagar Dharia 	if (msg == NULL || msg->rbuf == NULL) {
39afbdcc7cSSagar Dharia 		dev_err(ctrl->dev, "Got response to invalid TID:%d, len:%d\n",
40afbdcc7cSSagar Dharia 				tid, len);
41afbdcc7cSSagar Dharia 		return;
42afbdcc7cSSagar Dharia 	}
43afbdcc7cSSagar Dharia 
44d3062a21SSrinivas Kandagatla 	slim_free_txn_tid(ctrl, txn);
45afbdcc7cSSagar Dharia 	memcpy(msg->rbuf, reply, len);
46afbdcc7cSSagar Dharia 	if (txn->comp)
47afbdcc7cSSagar Dharia 		complete(txn->comp);
484b14e62aSSagar Dharia 
494b14e62aSSagar Dharia 	/* Remove runtime-pm vote now that response was received for TID txn */
504b14e62aSSagar Dharia 	pm_runtime_mark_last_busy(ctrl->dev);
514b14e62aSSagar Dharia 	pm_runtime_put_autosuspend(ctrl->dev);
52afbdcc7cSSagar Dharia }
53afbdcc7cSSagar Dharia EXPORT_SYMBOL_GPL(slim_msg_response);
54afbdcc7cSSagar Dharia 
55afbdcc7cSSagar Dharia /**
56d3062a21SSrinivas Kandagatla  * slim_alloc_txn_tid() - Allocate a tid to txn
57d3062a21SSrinivas Kandagatla  *
58d3062a21SSrinivas Kandagatla  * @ctrl: Controller handle
59d3062a21SSrinivas Kandagatla  * @txn: transaction to be allocated with tid.
60d3062a21SSrinivas Kandagatla  *
61d3062a21SSrinivas Kandagatla  * Return: zero on success with valid txn->tid and error code on failures.
62d3062a21SSrinivas Kandagatla  */
slim_alloc_txn_tid(struct slim_controller * ctrl,struct slim_msg_txn * txn)63d3062a21SSrinivas Kandagatla int slim_alloc_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
64d3062a21SSrinivas Kandagatla {
65d3062a21SSrinivas Kandagatla 	unsigned long flags;
66d3062a21SSrinivas Kandagatla 	int ret = 0;
67d3062a21SSrinivas Kandagatla 
68d3062a21SSrinivas Kandagatla 	spin_lock_irqsave(&ctrl->txn_lock, flags);
699659281cSSrinivas Kandagatla 	ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 1,
70d3062a21SSrinivas Kandagatla 				SLIM_MAX_TIDS, GFP_ATOMIC);
71d3062a21SSrinivas Kandagatla 	if (ret < 0) {
72d3062a21SSrinivas Kandagatla 		spin_unlock_irqrestore(&ctrl->txn_lock, flags);
73d3062a21SSrinivas Kandagatla 		return ret;
74d3062a21SSrinivas Kandagatla 	}
75d3062a21SSrinivas Kandagatla 	txn->tid = ret;
76d3062a21SSrinivas Kandagatla 	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
77d3062a21SSrinivas Kandagatla 	return 0;
78d3062a21SSrinivas Kandagatla }
79d3062a21SSrinivas Kandagatla EXPORT_SYMBOL_GPL(slim_alloc_txn_tid);
80d3062a21SSrinivas Kandagatla 
81d3062a21SSrinivas Kandagatla /**
8289e1ec77SJulia Lawall  * slim_free_txn_tid() - Free tid of txn
83d3062a21SSrinivas Kandagatla  *
84d3062a21SSrinivas Kandagatla  * @ctrl: Controller handle
85d3062a21SSrinivas Kandagatla  * @txn: transaction whose tid should be freed
86d3062a21SSrinivas Kandagatla  */
slim_free_txn_tid(struct slim_controller * ctrl,struct slim_msg_txn * txn)87d3062a21SSrinivas Kandagatla void slim_free_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
88d3062a21SSrinivas Kandagatla {
89d3062a21SSrinivas Kandagatla 	unsigned long flags;
90d3062a21SSrinivas Kandagatla 
91d3062a21SSrinivas Kandagatla 	spin_lock_irqsave(&ctrl->txn_lock, flags);
92d3062a21SSrinivas Kandagatla 	idr_remove(&ctrl->tid_idr, txn->tid);
93d3062a21SSrinivas Kandagatla 	spin_unlock_irqrestore(&ctrl->txn_lock, flags);
94d3062a21SSrinivas Kandagatla }
95d3062a21SSrinivas Kandagatla EXPORT_SYMBOL_GPL(slim_free_txn_tid);
96d3062a21SSrinivas Kandagatla 
97d3062a21SSrinivas Kandagatla /**
98afbdcc7cSSagar Dharia  * slim_do_transfer() - Process a SLIMbus-messaging transaction
99afbdcc7cSSagar Dharia  *
100afbdcc7cSSagar Dharia  * @ctrl: Controller handle
101afbdcc7cSSagar Dharia  * @txn: Transaction to be sent over SLIMbus
102afbdcc7cSSagar Dharia  *
103afbdcc7cSSagar Dharia  * Called by controller to transmit messaging transactions not dealing with
10489e1ec77SJulia Lawall  * Interface/Value elements. (e.g. transmitting a message to assign logical
105afbdcc7cSSagar Dharia  * address to a slave device
106afbdcc7cSSagar Dharia  *
107afbdcc7cSSagar Dharia  * Return: -ETIMEDOUT: If transmission of this message timed out
108afbdcc7cSSagar Dharia  *	(e.g. due to bus lines not being clocked or driven by controller)
109afbdcc7cSSagar Dharia  */
slim_do_transfer(struct slim_controller * ctrl,struct slim_msg_txn * txn)110afbdcc7cSSagar Dharia int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
111afbdcc7cSSagar Dharia {
112afbdcc7cSSagar Dharia 	DECLARE_COMPLETION_ONSTACK(done);
1134b14e62aSSagar Dharia 	bool need_tid = false, clk_pause_msg = false;
114d3062a21SSrinivas Kandagatla 	int ret, timeout;
115afbdcc7cSSagar Dharia 
1164b14e62aSSagar Dharia 	/*
1174b14e62aSSagar Dharia 	 * do not vote for runtime-PM if the transactions are part of clock
1184b14e62aSSagar Dharia 	 * pause sequence
1194b14e62aSSagar Dharia 	 */
1204b14e62aSSagar Dharia 	if (ctrl->sched.clk_state == SLIM_CLK_ENTERING_PAUSE &&
1214b14e62aSSagar Dharia 		(txn->mt == SLIM_MSG_MT_CORE &&
1224b14e62aSSagar Dharia 		 txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
1234b14e62aSSagar Dharia 		 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
1244b14e62aSSagar Dharia 		clk_pause_msg = true;
1254b14e62aSSagar Dharia 
1264b14e62aSSagar Dharia 	if (!clk_pause_msg) {
1274b14e62aSSagar Dharia 		ret = pm_runtime_get_sync(ctrl->dev);
1284b14e62aSSagar Dharia 		if (ctrl->sched.clk_state != SLIM_CLK_ACTIVE) {
1294b14e62aSSagar Dharia 			dev_err(ctrl->dev, "ctrl wrong state:%d, ret:%d\n",
1304b14e62aSSagar Dharia 				ctrl->sched.clk_state, ret);
1314b14e62aSSagar Dharia 			goto slim_xfer_err;
1324b14e62aSSagar Dharia 		}
1334b14e62aSSagar Dharia 	}
134a263c1ffSSrinivas Kandagatla 	/* Initialize tid to invalid value */
135a263c1ffSSrinivas Kandagatla 	txn->tid = 0;
136afbdcc7cSSagar Dharia 	need_tid = slim_tid_txn(txn->mt, txn->mc);
137afbdcc7cSSagar Dharia 
138afbdcc7cSSagar Dharia 	if (need_tid) {
139d3062a21SSrinivas Kandagatla 		ret = slim_alloc_txn_tid(ctrl, txn);
140d3062a21SSrinivas Kandagatla 		if (ret)
141d3062a21SSrinivas Kandagatla 			return ret;
142afbdcc7cSSagar Dharia 
143afbdcc7cSSagar Dharia 		if (!txn->msg->comp)
144afbdcc7cSSagar Dharia 			txn->comp = &done;
145afbdcc7cSSagar Dharia 		else
146afbdcc7cSSagar Dharia 			txn->comp = txn->comp;
147afbdcc7cSSagar Dharia 	}
148afbdcc7cSSagar Dharia 
149afbdcc7cSSagar Dharia 	ret = ctrl->xfer_msg(ctrl, txn);
150*faac8e89SVisweswara Tanuku 	if (ret == -ETIMEDOUT) {
151*faac8e89SVisweswara Tanuku 		slim_free_txn_tid(ctrl, txn);
152*faac8e89SVisweswara Tanuku 	} else if (!ret && need_tid && !txn->msg->comp) {
153afbdcc7cSSagar Dharia 		unsigned long ms = txn->rl + HZ;
154afbdcc7cSSagar Dharia 
155afbdcc7cSSagar Dharia 		timeout = wait_for_completion_timeout(txn->comp,
156afbdcc7cSSagar Dharia 						      msecs_to_jiffies(ms));
157afbdcc7cSSagar Dharia 		if (!timeout) {
158afbdcc7cSSagar Dharia 			ret = -ETIMEDOUT;
159d3062a21SSrinivas Kandagatla 			slim_free_txn_tid(ctrl, txn);
160afbdcc7cSSagar Dharia 		}
161afbdcc7cSSagar Dharia 	}
162afbdcc7cSSagar Dharia 
163afbdcc7cSSagar Dharia 	if (ret)
164afbdcc7cSSagar Dharia 		dev_err(ctrl->dev, "Tx:MT:0x%x, MC:0x%x, LA:0x%x failed:%d\n",
165afbdcc7cSSagar Dharia 			txn->mt, txn->mc, txn->la, ret);
166afbdcc7cSSagar Dharia 
1674b14e62aSSagar Dharia slim_xfer_err:
168a263c1ffSSrinivas Kandagatla 	if (!clk_pause_msg && (txn->tid == 0  || ret == -ETIMEDOUT)) {
1694b14e62aSSagar Dharia 		/*
1704b14e62aSSagar Dharia 		 * remove runtime-pm vote if this was TX only, or
1714b14e62aSSagar Dharia 		 * if there was error during this transaction
1724b14e62aSSagar Dharia 		 */
1734b14e62aSSagar Dharia 		pm_runtime_mark_last_busy(ctrl->dev);
174057ba872SSrinivas Kandagatla 		pm_runtime_put_autosuspend(ctrl->dev);
1754b14e62aSSagar Dharia 	}
176afbdcc7cSSagar Dharia 	return ret;
177afbdcc7cSSagar Dharia }
178afbdcc7cSSagar Dharia EXPORT_SYMBOL_GPL(slim_do_transfer);
179afbdcc7cSSagar Dharia 
slim_val_inf_sanity(struct slim_controller * ctrl,struct slim_val_inf * msg,u8 mc)180afbdcc7cSSagar Dharia static int slim_val_inf_sanity(struct slim_controller *ctrl,
181afbdcc7cSSagar Dharia 			       struct slim_val_inf *msg, u8 mc)
182afbdcc7cSSagar Dharia {
183afbdcc7cSSagar Dharia 	if (!msg || msg->num_bytes > 16 ||
184afbdcc7cSSagar Dharia 	    (msg->start_offset + msg->num_bytes) > 0xC00)
185afbdcc7cSSagar Dharia 		goto reterr;
186afbdcc7cSSagar Dharia 	switch (mc) {
187afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_REQUEST_VALUE:
188afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_REQUEST_INFORMATION:
189afbdcc7cSSagar Dharia 		if (msg->rbuf != NULL)
190afbdcc7cSSagar Dharia 			return 0;
191afbdcc7cSSagar Dharia 		break;
192afbdcc7cSSagar Dharia 
193afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_CHANGE_VALUE:
194afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_CLEAR_INFORMATION:
195afbdcc7cSSagar Dharia 		if (msg->wbuf != NULL)
196afbdcc7cSSagar Dharia 			return 0;
197afbdcc7cSSagar Dharia 		break;
198afbdcc7cSSagar Dharia 
199afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_REQUEST_CHANGE_VALUE:
200afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION:
201afbdcc7cSSagar Dharia 		if (msg->rbuf != NULL && msg->wbuf != NULL)
202afbdcc7cSSagar Dharia 			return 0;
203afbdcc7cSSagar Dharia 		break;
204afbdcc7cSSagar Dharia 	}
205afbdcc7cSSagar Dharia reterr:
2067dde60c0SColin Ian King 	if (msg)
207afbdcc7cSSagar Dharia 		dev_err(ctrl->dev, "Sanity check failed:msg:offset:0x%x, mc:%d\n",
208afbdcc7cSSagar Dharia 			msg->start_offset, mc);
209afbdcc7cSSagar Dharia 	return -EINVAL;
210afbdcc7cSSagar Dharia }
211afbdcc7cSSagar Dharia 
slim_slicesize(int code)212afbdcc7cSSagar Dharia static u16 slim_slicesize(int code)
213afbdcc7cSSagar Dharia {
214afbdcc7cSSagar Dharia 	static const u8 sizetocode[16] = {
215afbdcc7cSSagar Dharia 		0, 1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7
216afbdcc7cSSagar Dharia 	};
217afbdcc7cSSagar Dharia 
218e33bbe69SGeert Uytterhoeven 	code = clamp(code, 1, (int)ARRAY_SIZE(sizetocode));
219afbdcc7cSSagar Dharia 
220afbdcc7cSSagar Dharia 	return sizetocode[code - 1];
221afbdcc7cSSagar Dharia }
222afbdcc7cSSagar Dharia 
223afbdcc7cSSagar Dharia /**
224afbdcc7cSSagar Dharia  * slim_xfer_msg() - Transfer a value info message on slim device
225afbdcc7cSSagar Dharia  *
226afbdcc7cSSagar Dharia  * @sbdev: slim device to which this msg has to be transfered
227afbdcc7cSSagar Dharia  * @msg: value info message pointer
228afbdcc7cSSagar Dharia  * @mc: message code of the message
229afbdcc7cSSagar Dharia  *
230afbdcc7cSSagar Dharia  * Called by drivers which want to transfer a vlaue or info elements.
231afbdcc7cSSagar Dharia  *
232afbdcc7cSSagar Dharia  * Return: -ETIMEDOUT: If transmission of this message timed out
233afbdcc7cSSagar Dharia  */
slim_xfer_msg(struct slim_device * sbdev,struct slim_val_inf * msg,u8 mc)234afbdcc7cSSagar Dharia int slim_xfer_msg(struct slim_device *sbdev, struct slim_val_inf *msg,
235afbdcc7cSSagar Dharia 		  u8 mc)
236afbdcc7cSSagar Dharia {
237afbdcc7cSSagar Dharia 	DEFINE_SLIM_LDEST_TXN(txn_stack, mc, 6, sbdev->laddr, msg);
238afbdcc7cSSagar Dharia 	struct slim_msg_txn *txn = &txn_stack;
239afbdcc7cSSagar Dharia 	struct slim_controller *ctrl = sbdev->ctrl;
240afbdcc7cSSagar Dharia 	int ret;
241afbdcc7cSSagar Dharia 	u16 sl;
242afbdcc7cSSagar Dharia 
243afbdcc7cSSagar Dharia 	if (!ctrl)
244afbdcc7cSSagar Dharia 		return -EINVAL;
245afbdcc7cSSagar Dharia 
246afbdcc7cSSagar Dharia 	ret = slim_val_inf_sanity(ctrl, msg, mc);
247afbdcc7cSSagar Dharia 	if (ret)
248afbdcc7cSSagar Dharia 		return ret;
249afbdcc7cSSagar Dharia 
250afbdcc7cSSagar Dharia 	sl = slim_slicesize(msg->num_bytes);
251afbdcc7cSSagar Dharia 
252afbdcc7cSSagar Dharia 	dev_dbg(ctrl->dev, "SB xfer msg:os:%x, len:%d, MC:%x, sl:%x\n",
253afbdcc7cSSagar Dharia 		msg->start_offset, msg->num_bytes, mc, sl);
254afbdcc7cSSagar Dharia 
255afbdcc7cSSagar Dharia 	txn->ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4));
256afbdcc7cSSagar Dharia 
257afbdcc7cSSagar Dharia 	switch (mc) {
258afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_REQUEST_CHANGE_VALUE:
259afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_CHANGE_VALUE:
260afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION:
261afbdcc7cSSagar Dharia 	case SLIM_MSG_MC_CLEAR_INFORMATION:
262afbdcc7cSSagar Dharia 		txn->rl += msg->num_bytes;
26350df9842SGustavo A. R. Silva 		break;
264afbdcc7cSSagar Dharia 	default:
265afbdcc7cSSagar Dharia 		break;
266afbdcc7cSSagar Dharia 	}
267afbdcc7cSSagar Dharia 
268afbdcc7cSSagar Dharia 	if (slim_tid_txn(txn->mt, txn->mc))
269afbdcc7cSSagar Dharia 		txn->rl++;
270afbdcc7cSSagar Dharia 
271afbdcc7cSSagar Dharia 	return slim_do_transfer(ctrl, txn);
272afbdcc7cSSagar Dharia }
273afbdcc7cSSagar Dharia EXPORT_SYMBOL_GPL(slim_xfer_msg);
274afbdcc7cSSagar Dharia 
slim_fill_msg(struct slim_val_inf * msg,u32 addr,size_t count,u8 * rbuf,u8 * wbuf)275afbdcc7cSSagar Dharia static void slim_fill_msg(struct slim_val_inf *msg, u32 addr,
276afbdcc7cSSagar Dharia 			 size_t count, u8 *rbuf, u8 *wbuf)
277afbdcc7cSSagar Dharia {
278afbdcc7cSSagar Dharia 	msg->start_offset = addr;
279afbdcc7cSSagar Dharia 	msg->num_bytes = count;
280afbdcc7cSSagar Dharia 	msg->rbuf = rbuf;
281afbdcc7cSSagar Dharia 	msg->wbuf = wbuf;
282ffa2d921SSrinivas Kandagatla 	msg->comp = NULL;
283afbdcc7cSSagar Dharia }
284afbdcc7cSSagar Dharia 
285afbdcc7cSSagar Dharia /**
286afbdcc7cSSagar Dharia  * slim_read() - Read SLIMbus value element
287afbdcc7cSSagar Dharia  *
288afbdcc7cSSagar Dharia  * @sdev: client handle.
289afbdcc7cSSagar Dharia  * @addr:  address of value element to read.
290afbdcc7cSSagar Dharia  * @count: number of bytes to read. Maximum bytes allowed are 16.
291afbdcc7cSSagar Dharia  * @val: will return what the value element value was
292afbdcc7cSSagar Dharia  *
293afbdcc7cSSagar Dharia  * Return: -EINVAL for Invalid parameters, -ETIMEDOUT If transmission of
294afbdcc7cSSagar Dharia  * this message timed out (e.g. due to bus lines not being clocked
295afbdcc7cSSagar Dharia  * or driven by controller)
296afbdcc7cSSagar Dharia  */
slim_read(struct slim_device * sdev,u32 addr,size_t count,u8 * val)297afbdcc7cSSagar Dharia int slim_read(struct slim_device *sdev, u32 addr, size_t count, u8 *val)
298afbdcc7cSSagar Dharia {
299afbdcc7cSSagar Dharia 	struct slim_val_inf msg;
300afbdcc7cSSagar Dharia 
301afbdcc7cSSagar Dharia 	slim_fill_msg(&msg, addr, count, val, NULL);
302afbdcc7cSSagar Dharia 
303afbdcc7cSSagar Dharia 	return slim_xfer_msg(sdev, &msg, SLIM_MSG_MC_REQUEST_VALUE);
304afbdcc7cSSagar Dharia }
305afbdcc7cSSagar Dharia EXPORT_SYMBOL_GPL(slim_read);
306afbdcc7cSSagar Dharia 
307afbdcc7cSSagar Dharia /**
308afbdcc7cSSagar Dharia  * slim_readb() - Read byte from SLIMbus value element
309afbdcc7cSSagar Dharia  *
310afbdcc7cSSagar Dharia  * @sdev: client handle.
311afbdcc7cSSagar Dharia  * @addr:  address in the value element to read.
312afbdcc7cSSagar Dharia  *
313afbdcc7cSSagar Dharia  * Return: byte value of value element.
314afbdcc7cSSagar Dharia  */
slim_readb(struct slim_device * sdev,u32 addr)315afbdcc7cSSagar Dharia int slim_readb(struct slim_device *sdev, u32 addr)
316afbdcc7cSSagar Dharia {
317afbdcc7cSSagar Dharia 	int ret;
318afbdcc7cSSagar Dharia 	u8 buf;
319afbdcc7cSSagar Dharia 
320afbdcc7cSSagar Dharia 	ret = slim_read(sdev, addr, 1, &buf);
321afbdcc7cSSagar Dharia 	if (ret < 0)
322afbdcc7cSSagar Dharia 		return ret;
323afbdcc7cSSagar Dharia 	else
324afbdcc7cSSagar Dharia 		return buf;
325afbdcc7cSSagar Dharia }
326afbdcc7cSSagar Dharia EXPORT_SYMBOL_GPL(slim_readb);
327afbdcc7cSSagar Dharia 
328afbdcc7cSSagar Dharia /**
329afbdcc7cSSagar Dharia  * slim_write() - Write SLIMbus value element
330afbdcc7cSSagar Dharia  *
331afbdcc7cSSagar Dharia  * @sdev: client handle.
332afbdcc7cSSagar Dharia  * @addr:  address in the value element to write.
333afbdcc7cSSagar Dharia  * @count: number of bytes to write. Maximum bytes allowed are 16.
334afbdcc7cSSagar Dharia  * @val: value to write to value element
335afbdcc7cSSagar Dharia  *
336afbdcc7cSSagar Dharia  * Return: -EINVAL for Invalid parameters, -ETIMEDOUT If transmission of
337afbdcc7cSSagar Dharia  * this message timed out (e.g. due to bus lines not being clocked
338afbdcc7cSSagar Dharia  * or driven by controller)
339afbdcc7cSSagar Dharia  */
slim_write(struct slim_device * sdev,u32 addr,size_t count,u8 * val)340afbdcc7cSSagar Dharia int slim_write(struct slim_device *sdev, u32 addr, size_t count, u8 *val)
341afbdcc7cSSagar Dharia {
342afbdcc7cSSagar Dharia 	struct slim_val_inf msg;
343afbdcc7cSSagar Dharia 
3448134d271SSrinivas Kandagatla 	slim_fill_msg(&msg, addr, count,  NULL, val);
345afbdcc7cSSagar Dharia 
346afbdcc7cSSagar Dharia 	return slim_xfer_msg(sdev, &msg, SLIM_MSG_MC_CHANGE_VALUE);
347afbdcc7cSSagar Dharia }
348afbdcc7cSSagar Dharia EXPORT_SYMBOL_GPL(slim_write);
349afbdcc7cSSagar Dharia 
350afbdcc7cSSagar Dharia /**
351afbdcc7cSSagar Dharia  * slim_writeb() - Write byte to SLIMbus value element
352afbdcc7cSSagar Dharia  *
353afbdcc7cSSagar Dharia  * @sdev: client handle.
354afbdcc7cSSagar Dharia  * @addr:  address of value element to write.
355afbdcc7cSSagar Dharia  * @value: value to write to value element
356afbdcc7cSSagar Dharia  *
357afbdcc7cSSagar Dharia  * Return: -EINVAL for Invalid parameters, -ETIMEDOUT If transmission of
358afbdcc7cSSagar Dharia  * this message timed out (e.g. due to bus lines not being clocked
359afbdcc7cSSagar Dharia  * or driven by controller)
360afbdcc7cSSagar Dharia  *
361afbdcc7cSSagar Dharia  */
slim_writeb(struct slim_device * sdev,u32 addr,u8 value)362afbdcc7cSSagar Dharia int slim_writeb(struct slim_device *sdev, u32 addr, u8 value)
363afbdcc7cSSagar Dharia {
364afbdcc7cSSagar Dharia 	return slim_write(sdev, addr, 1, &value);
365afbdcc7cSSagar Dharia }
366afbdcc7cSSagar Dharia EXPORT_SYMBOL_GPL(slim_writeb);
367