Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bb025d4 authored by Taku Izumi's avatar Taku Izumi Committed by David S. Miller
Browse files

fjes: ES information acquisition routine



This patch adds ES information acquisition routine.
ES information can be retrieved issuing information
request command. ES information includes which
receiver is same zone.

Signed-off-by: default avatarTaku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2fcbca68
Loading
Loading
Loading
Loading
+101 −0
Original line number Diff line number Diff line
@@ -351,6 +351,107 @@ void fjes_hw_exit(struct fjes_hw *hw)
	fjes_hw_cleanup(hw);
}

static enum fjes_dev_command_response_e
fjes_hw_issue_request_command(struct fjes_hw *hw,
			      enum fjes_dev_command_request_type type)
{
	enum fjes_dev_command_response_e ret = FJES_CMD_STATUS_UNKNOWN;
	union REG_CR cr;
	union REG_CS cs;
	int timeout;

	cr.reg = 0;
	cr.bits.req_start = 1;
	cr.bits.req_code = type;
	wr32(XSCT_CR, cr.reg);
	cr.reg = rd32(XSCT_CR);

	if (cr.bits.error == 0) {
		timeout = FJES_COMMAND_REQ_TIMEOUT * 1000;
		cs.reg = rd32(XSCT_CS);

		while ((cs.bits.complete != 1) && timeout > 0) {
			msleep(1000);
			cs.reg = rd32(XSCT_CS);
			timeout -= 1000;
		}

		if (cs.bits.complete == 1)
			ret = FJES_CMD_STATUS_NORMAL;
		else if (timeout <= 0)
			ret = FJES_CMD_STATUS_TIMEOUT;

	} else {
		switch (cr.bits.err_info) {
		case FJES_CMD_REQ_ERR_INFO_PARAM:
			ret = FJES_CMD_STATUS_ERROR_PARAM;
			break;
		case FJES_CMD_REQ_ERR_INFO_STATUS:
			ret = FJES_CMD_STATUS_ERROR_STATUS;
			break;
		default:
			ret = FJES_CMD_STATUS_UNKNOWN;
			break;
		}
	}

	return ret;
}

int fjes_hw_request_info(struct fjes_hw *hw)
{
	union fjes_device_command_req *req_buf = hw->hw_info.req_buf;
	union fjes_device_command_res *res_buf = hw->hw_info.res_buf;
	enum fjes_dev_command_response_e ret;
	int result;

	memset(req_buf, 0, hw->hw_info.req_buf_size);
	memset(res_buf, 0, hw->hw_info.res_buf_size);

	req_buf->info.length = FJES_DEV_COMMAND_INFO_REQ_LEN;

	res_buf->info.length = 0;
	res_buf->info.code = 0;

	ret = fjes_hw_issue_request_command(hw, FJES_CMD_REQ_INFO);

	result = 0;

	if (FJES_DEV_COMMAND_INFO_RES_LEN((*hw->hw_info.max_epid)) !=
		res_buf->info.length) {
		result = -ENOMSG;
	} else if (ret == FJES_CMD_STATUS_NORMAL) {
		switch (res_buf->info.code) {
		case FJES_CMD_REQ_RES_CODE_NORMAL:
			result = 0;
			break;
		default:
			result = -EPERM;
			break;
		}
	} else {
		switch (ret) {
		case FJES_CMD_STATUS_UNKNOWN:
			result = -EPERM;
			break;
		case FJES_CMD_STATUS_TIMEOUT:
			result = -EBUSY;
			break;
		case FJES_CMD_STATUS_ERROR_PARAM:
			result = -EPERM;
			break;
		case FJES_CMD_STATUS_ERROR_STATUS:
			result = -EPERM;
			break;
		default:
			result = -EPERM;
			break;
		}
	}

	return result;
}

void fjes_hw_set_irqmask(struct fjes_hw *hw,
			 enum REG_ICTL_MASK intr_mask, bool mask)
{
+24 −0
Original line number Diff line number Diff line
@@ -34,6 +34,12 @@ struct fjes_hw;
#define EP_BUFFER_INFO_SIZE 4096

#define FJES_DEVICE_RESET_TIMEOUT  ((17 + 1) * 3) /* sec */
#define FJES_COMMAND_REQ_TIMEOUT  (5 + 1) /* sec */

#define FJES_CMD_REQ_ERR_INFO_PARAM  (0x0001)
#define FJES_CMD_REQ_ERR_INFO_STATUS (0x0002)

#define FJES_CMD_REQ_RES_CODE_NORMAL (0)

#define EP_BUFFER_SIZE \
	(((sizeof(union ep_buffer_info) + (128 * (64 * 1024))) \
@@ -50,6 +56,7 @@ struct fjes_hw;
	((size) - sizeof(struct esmem_frame) - \
	(ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN))

#define FJES_DEV_COMMAND_INFO_REQ_LEN	(4)
#define FJES_DEV_COMMAND_INFO_RES_LEN(epnum) (8 + 2 * (epnum))
#define FJES_DEV_COMMAND_SHARE_BUFFER_REQ_LEN(txb, rxb) \
	(24 + (8 * ((txb) / EP_BUFFER_INFO_SIZE + (rxb) / EP_BUFFER_INFO_SIZE)))
@@ -124,6 +131,13 @@ union fjes_device_command_res {
	} stop_trace;
};

/* request command type */
enum fjes_dev_command_request_type {
	FJES_CMD_REQ_INFO		= 0x0001,
	FJES_CMD_REQ_SHARE_BUFFER	= 0x0002,
	FJES_CMD_REQ_UNSHARE_BUFFER	= 0x0004,
};

/* parameter for command control */
struct fjes_device_command_param {
	u32 req_len;
@@ -133,6 +147,15 @@ struct fjes_device_command_param {
	phys_addr_t share_start;
};

/* error code for command control */
enum fjes_dev_command_response_e {
	FJES_CMD_STATUS_UNKNOWN,
	FJES_CMD_STATUS_NORMAL,
	FJES_CMD_STATUS_TIMEOUT,
	FJES_CMD_STATUS_ERROR_PARAM,
	FJES_CMD_STATUS_ERROR_STATUS,
};

/* EP buffer information */
union ep_buffer_info {
	u8 raw[EP_BUFFER_INFO_SIZE];
@@ -243,6 +266,7 @@ struct fjes_hw {
int fjes_hw_init(struct fjes_hw *);
void fjes_hw_exit(struct fjes_hw *);
int fjes_hw_reset(struct fjes_hw *);
int fjes_hw_request_info(struct fjes_hw *);

void fjes_hw_init_command_registers(struct fjes_hw *,
				    struct fjes_device_command_param *);
+23 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@
#define XSCT_DCTL           0x0010  /* Device Control */

/* Command Control registers */
#define XSCT_CR             0x0020  /* Command request */
#define XSCT_CS             0x0024  /* Command status */
#define XSCT_SHSTSAL        0x0028  /* Share status address Low */
#define XSCT_SHSTSAH        0x002C  /* Share status address High */

@@ -78,6 +80,27 @@ union REG_DCTL {
	__le32 reg;
};

/* Command Control registers */
union REG_CR {
	struct {
		__le32 req_code:16;
		__le32 err_info:14;
		__le32 error:1;
		__le32 req_start:1;
	} bits;
	__le32 reg;
};

union REG_CS {
	struct {
		__le32 req_code:16;
		__le32 rsv0:14;
		__le32 busy:1;
		__le32 complete:1;
	} bits;
	__le32 reg;
};

enum REG_ICTL_MASK {
	REG_ICTL_MASK_INFO_UPDATE     = 1 << 20,
	REG_ICTL_MASK_DEV_STOP_REQ    = 1 << 19,