162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * RapidIO configuration space access support
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2005 MontaVista Software, Inc.
662306a36Sopenharmony_ci * Matt Porter <mporter@kernel.crashing.org>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/rio.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/rio_drv.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci *  Wrappers for all RIO configuration access functions.  They just check
1662306a36Sopenharmony_ci *  alignment and call the low-level functions pointed to by rio_mport->ops.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define RIO_8_BAD 0
2062306a36Sopenharmony_ci#define RIO_16_BAD (offset & 1)
2162306a36Sopenharmony_ci#define RIO_32_BAD (offset & 3)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/**
2462306a36Sopenharmony_ci * RIO_LOP_READ - Generate rio_local_read_config_* functions
2562306a36Sopenharmony_ci * @size: Size of configuration space read (8, 16, 32 bits)
2662306a36Sopenharmony_ci * @type: C type of value argument
2762306a36Sopenharmony_ci * @len: Length of configuration space read (1, 2, 4 bytes)
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * Generates rio_local_read_config_* functions used to access
3062306a36Sopenharmony_ci * configuration space registers on the local device.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci#define RIO_LOP_READ(size,type,len) \
3362306a36Sopenharmony_ciint __rio_local_read_config_##size \
3462306a36Sopenharmony_ci	(struct rio_mport *mport, u32 offset, type *value)		\
3562306a36Sopenharmony_ci{									\
3662306a36Sopenharmony_ci	int res;							\
3762306a36Sopenharmony_ci	u32 data = 0;							\
3862306a36Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
3962306a36Sopenharmony_ci	res = mport->ops->lcread(mport, mport->id, offset, len, &data);	\
4062306a36Sopenharmony_ci	*value = (type)data;						\
4162306a36Sopenharmony_ci	return res;							\
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/**
4562306a36Sopenharmony_ci * RIO_LOP_WRITE - Generate rio_local_write_config_* functions
4662306a36Sopenharmony_ci * @size: Size of configuration space write (8, 16, 32 bits)
4762306a36Sopenharmony_ci * @type: C type of value argument
4862306a36Sopenharmony_ci * @len: Length of configuration space write (1, 2, 4 bytes)
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci * Generates rio_local_write_config_* functions used to access
5162306a36Sopenharmony_ci * configuration space registers on the local device.
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_ci#define RIO_LOP_WRITE(size,type,len) \
5462306a36Sopenharmony_ciint __rio_local_write_config_##size \
5562306a36Sopenharmony_ci	(struct rio_mport *mport, u32 offset, type value)		\
5662306a36Sopenharmony_ci{									\
5762306a36Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
5862306a36Sopenharmony_ci	return mport->ops->lcwrite(mport, mport->id, offset, len, value);\
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciRIO_LOP_READ(8, u8, 1)
6262306a36Sopenharmony_ciRIO_LOP_READ(16, u16, 2)
6362306a36Sopenharmony_ciRIO_LOP_READ(32, u32, 4)
6462306a36Sopenharmony_ciRIO_LOP_WRITE(8, u8, 1)
6562306a36Sopenharmony_ciRIO_LOP_WRITE(16, u16, 2)
6662306a36Sopenharmony_ciRIO_LOP_WRITE(32, u32, 4)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_read_config_8);
6962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_read_config_16);
7062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_read_config_32);
7162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_write_config_8);
7262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_write_config_16);
7362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__rio_local_write_config_32);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/**
7662306a36Sopenharmony_ci * RIO_OP_READ - Generate rio_mport_read_config_* functions
7762306a36Sopenharmony_ci * @size: Size of configuration space read (8, 16, 32 bits)
7862306a36Sopenharmony_ci * @type: C type of value argument
7962306a36Sopenharmony_ci * @len: Length of configuration space read (1, 2, 4 bytes)
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * Generates rio_mport_read_config_* functions used to access
8262306a36Sopenharmony_ci * configuration space registers on the local device.
8362306a36Sopenharmony_ci */
8462306a36Sopenharmony_ci#define RIO_OP_READ(size,type,len) \
8562306a36Sopenharmony_ciint rio_mport_read_config_##size \
8662306a36Sopenharmony_ci	(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value)	\
8762306a36Sopenharmony_ci{									\
8862306a36Sopenharmony_ci	int res;							\
8962306a36Sopenharmony_ci	u32 data = 0;							\
9062306a36Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
9162306a36Sopenharmony_ci	res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
9262306a36Sopenharmony_ci	*value = (type)data;						\
9362306a36Sopenharmony_ci	return res;							\
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/**
9762306a36Sopenharmony_ci * RIO_OP_WRITE - Generate rio_mport_write_config_* functions
9862306a36Sopenharmony_ci * @size: Size of configuration space write (8, 16, 32 bits)
9962306a36Sopenharmony_ci * @type: C type of value argument
10062306a36Sopenharmony_ci * @len: Length of configuration space write (1, 2, 4 bytes)
10162306a36Sopenharmony_ci *
10262306a36Sopenharmony_ci * Generates rio_mport_write_config_* functions used to access
10362306a36Sopenharmony_ci * configuration space registers on the local device.
10462306a36Sopenharmony_ci */
10562306a36Sopenharmony_ci#define RIO_OP_WRITE(size,type,len) \
10662306a36Sopenharmony_ciint rio_mport_write_config_##size \
10762306a36Sopenharmony_ci	(struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value)	\
10862306a36Sopenharmony_ci{									\
10962306a36Sopenharmony_ci	if (RIO_##size##_BAD) return RIO_BAD_SIZE;			\
11062306a36Sopenharmony_ci	return mport->ops->cwrite(mport, mport->id, destid, hopcount,	\
11162306a36Sopenharmony_ci			offset, len, value);				\
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ciRIO_OP_READ(8, u8, 1)
11562306a36Sopenharmony_ciRIO_OP_READ(16, u16, 2)
11662306a36Sopenharmony_ciRIO_OP_READ(32, u32, 4)
11762306a36Sopenharmony_ciRIO_OP_WRITE(8, u8, 1)
11862306a36Sopenharmony_ciRIO_OP_WRITE(16, u16, 2)
11962306a36Sopenharmony_ciRIO_OP_WRITE(32, u32, 4)
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_read_config_8);
12262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_read_config_16);
12362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_read_config_32);
12462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_write_config_8);
12562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_write_config_16);
12662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_write_config_32);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/**
12962306a36Sopenharmony_ci * rio_mport_send_doorbell - Send a doorbell message
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * @mport: RIO master port
13262306a36Sopenharmony_ci * @destid: RIO device destination ID
13362306a36Sopenharmony_ci * @data: Doorbell message data
13462306a36Sopenharmony_ci *
13562306a36Sopenharmony_ci * Send a doorbell message to a RIO device. The doorbell message
13662306a36Sopenharmony_ci * has a 16-bit info field provided by the data argument.
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_ciint rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	return mport->ops->dsend(mport, mport->id, destid, data);
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rio_mport_send_doorbell);
144