18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * RapidIO configuration space access support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2005 MontaVista Software, Inc.
68c2ecf20Sopenharmony_ci * Matt Porter <mporter@kernel.crashing.org>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/rio.h>
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/rio_drv.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci/*
158c2ecf20Sopenharmony_ci *  Wrappers for all RIO configuration access functions.  They just check
168c2ecf20Sopenharmony_ci *  alignment and call the low-level functions pointed to by rio_mport->ops.
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#define RIO_8_BAD 0
208c2ecf20Sopenharmony_ci#define RIO_16_BAD (offset & 1)
218c2ecf20Sopenharmony_ci#define RIO_32_BAD (offset & 3)
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/**
248c2ecf20Sopenharmony_ci * RIO_LOP_READ - Generate rio_local_read_config_* functions
258c2ecf20Sopenharmony_ci * @size: Size of configuration space read (8, 16, 32 bits)
268c2ecf20Sopenharmony_ci * @type: C type of value argument
278c2ecf20Sopenharmony_ci * @len: Length of configuration space read (1, 2, 4 bytes)
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * Generates rio_local_read_config_* functions used to access
308c2ecf20Sopenharmony_ci * configuration space registers on the local device.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci#define RIO_LOP_READ(size,type,len) \
338c2ecf20Sopenharmony_ciint __rio_local_read_config_##size \
348c2ecf20Sopenharmony_ci	(struct rio_mport *mport, u32 offset, type *value)		\
358c2ecf20Sopenharmony_ci{									\
368c2ecf20Sopenharmony_ci	int res;							\
378c2ecf20Sopenharmony_ci	u32 data = 0;							\
388c2ecf20Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
398c2ecf20Sopenharmony_ci	res = mport->ops->lcread(mport, mport->id, offset, len, &data);	\
408c2ecf20Sopenharmony_ci	*value = (type)data;						\
418c2ecf20Sopenharmony_ci	return res;							\
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/**
458c2ecf20Sopenharmony_ci * RIO_LOP_WRITE - Generate rio_local_write_config_* functions
468c2ecf20Sopenharmony_ci * @size: Size of configuration space write (8, 16, 32 bits)
478c2ecf20Sopenharmony_ci * @type: C type of value argument
488c2ecf20Sopenharmony_ci * @len: Length of configuration space write (1, 2, 4 bytes)
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci * Generates rio_local_write_config_* functions used to access
518c2ecf20Sopenharmony_ci * configuration space registers on the local device.
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_ci#define RIO_LOP_WRITE(size,type,len) \
548c2ecf20Sopenharmony_ciint __rio_local_write_config_##size \
558c2ecf20Sopenharmony_ci	(struct rio_mport *mport, u32 offset, type value)		\
568c2ecf20Sopenharmony_ci{									\
578c2ecf20Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
588c2ecf20Sopenharmony_ci	return mport->ops->lcwrite(mport, mport->id, offset, len, value);\
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ciRIO_LOP_READ(8, u8, 1)
628c2ecf20Sopenharmony_ciRIO_LOP_READ(16, u16, 2)
638c2ecf20Sopenharmony_ciRIO_LOP_READ(32, u32, 4)
648c2ecf20Sopenharmony_ciRIO_LOP_WRITE(8, u8, 1)
658c2ecf20Sopenharmony_ciRIO_LOP_WRITE(16, u16, 2)
668c2ecf20Sopenharmony_ciRIO_LOP_WRITE(32, u32, 4)
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_read_config_8);
698c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_read_config_16);
708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_read_config_32);
718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_write_config_8);
728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_write_config_16);
738c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_write_config_32);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/**
768c2ecf20Sopenharmony_ci * RIO_OP_READ - Generate rio_mport_read_config_* functions
778c2ecf20Sopenharmony_ci * @size: Size of configuration space read (8, 16, 32 bits)
788c2ecf20Sopenharmony_ci * @type: C type of value argument
798c2ecf20Sopenharmony_ci * @len: Length of configuration space read (1, 2, 4 bytes)
808c2ecf20Sopenharmony_ci *
818c2ecf20Sopenharmony_ci * Generates rio_mport_read_config_* functions used to access
828c2ecf20Sopenharmony_ci * configuration space registers on the local device.
838c2ecf20Sopenharmony_ci */
848c2ecf20Sopenharmony_ci#define RIO_OP_READ(size,type,len) \
858c2ecf20Sopenharmony_ciint rio_mport_read_config_##size \
868c2ecf20Sopenharmony_ci	(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value)	\
878c2ecf20Sopenharmony_ci{									\
888c2ecf20Sopenharmony_ci	int res;							\
898c2ecf20Sopenharmony_ci	u32 data = 0;							\
908c2ecf20Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
918c2ecf20Sopenharmony_ci	res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
928c2ecf20Sopenharmony_ci	*value = (type)data;						\
938c2ecf20Sopenharmony_ci	return res;							\
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/**
978c2ecf20Sopenharmony_ci * RIO_OP_WRITE - Generate rio_mport_write_config_* functions
988c2ecf20Sopenharmony_ci * @size: Size of configuration space write (8, 16, 32 bits)
998c2ecf20Sopenharmony_ci * @type: C type of value argument
1008c2ecf20Sopenharmony_ci * @len: Length of configuration space write (1, 2, 4 bytes)
1018c2ecf20Sopenharmony_ci *
1028c2ecf20Sopenharmony_ci * Generates rio_mport_write_config_* functions used to access
1038c2ecf20Sopenharmony_ci * configuration space registers on the local device.
1048c2ecf20Sopenharmony_ci */
1058c2ecf20Sopenharmony_ci#define RIO_OP_WRITE(size,type,len) \
1068c2ecf20Sopenharmony_ciint rio_mport_write_config_##size \
1078c2ecf20Sopenharmony_ci	(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value)	\
1088c2ecf20Sopenharmony_ci{									\
1098c2ecf20Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
1108c2ecf20Sopenharmony_ci	return mport->ops->cwrite(mport, mport->id, destid, hopcount,	\
1118c2ecf20Sopenharmony_ci			offset, len, value);				\
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ciRIO_OP_READ(8, u8, 1)
1158c2ecf20Sopenharmony_ciRIO_OP_READ(16, u16, 2)
1168c2ecf20Sopenharmony_ciRIO_OP_READ(32, u32, 4)
1178c2ecf20Sopenharmony_ciRIO_OP_WRITE(8, u8, 1)
1188c2ecf20Sopenharmony_ciRIO_OP_WRITE(16, u16, 2)
1198c2ecf20Sopenharmony_ciRIO_OP_WRITE(32, u32, 4)
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_read_config_8);
1228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_read_config_16);
1238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_read_config_32);
1248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_write_config_8);
1258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_write_config_16);
1268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_write_config_32);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci/**
1298c2ecf20Sopenharmony_ci * rio_mport_send_doorbell - Send a doorbell message
1308c2ecf20Sopenharmony_ci *
1318c2ecf20Sopenharmony_ci * @mport: RIO master port
1328c2ecf20Sopenharmony_ci * @destid: RIO device destination ID
1338c2ecf20Sopenharmony_ci * @data: Doorbell message data
1348c2ecf20Sopenharmony_ci *
1358c2ecf20Sopenharmony_ci * Send a doorbell message to a RIO device. The doorbell message
1368c2ecf20Sopenharmony_ci * has a 16-bit info field provided by the data argument.
1378c2ecf20Sopenharmony_ci */
1388c2ecf20Sopenharmony_ciint rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	return mport->ops->dsend(mport, mport->id, destid, data);
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_send_doorbell);
144