162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
262306a36Sopenharmony_ci/* Copyright 2013-2016 Freescale Semiconductor Inc.
362306a36Sopenharmony_ci * Copyright 2019 NXP
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#include <linux/fsl/mc.h>
662306a36Sopenharmony_ci#include "dpmac.h"
762306a36Sopenharmony_ci#include "dpmac-cmd.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/**
1062306a36Sopenharmony_ci * dpmac_open() - Open a control session for the specified object.
1162306a36Sopenharmony_ci * @mc_io:	Pointer to MC portal's I/O object
1262306a36Sopenharmony_ci * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
1362306a36Sopenharmony_ci * @dpmac_id:	DPMAC unique ID
1462306a36Sopenharmony_ci * @token:	Returned token; use in subsequent API calls
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * This function can be used to open a control session for an
1762306a36Sopenharmony_ci * already created object; an object may have been declared in
1862306a36Sopenharmony_ci * the DPL or by calling the dpmac_create function.
1962306a36Sopenharmony_ci * This function returns a unique authentication token,
2062306a36Sopenharmony_ci * associated with the specific object ID and the specific MC
2162306a36Sopenharmony_ci * portal; this token must be used in all subsequent commands for
2262306a36Sopenharmony_ci * this specific object
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Return:	'0' on Success; Error code otherwise.
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ciint dpmac_open(struct fsl_mc_io *mc_io,
2762306a36Sopenharmony_ci	       u32 cmd_flags,
2862306a36Sopenharmony_ci	       int dpmac_id,
2962306a36Sopenharmony_ci	       u16 *token)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	struct dpmac_cmd_open *cmd_params;
3262306a36Sopenharmony_ci	struct fsl_mc_command cmd = { 0 };
3362306a36Sopenharmony_ci	int err;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	/* prepare command */
3662306a36Sopenharmony_ci	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
3762306a36Sopenharmony_ci					  cmd_flags,
3862306a36Sopenharmony_ci					  0);
3962306a36Sopenharmony_ci	cmd_params = (struct dpmac_cmd_open *)cmd.params;
4062306a36Sopenharmony_ci	cmd_params->dpmac_id = cpu_to_le32(dpmac_id);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	/* send command to mc*/
4362306a36Sopenharmony_ci	err = mc_send_command(mc_io, &cmd);
4462306a36Sopenharmony_ci	if (err)
4562306a36Sopenharmony_ci		return err;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* retrieve response parameters */
4862306a36Sopenharmony_ci	*token = mc_cmd_hdr_read_token(&cmd);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	return err;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/**
5462306a36Sopenharmony_ci * dpmac_close() - Close the control session of the object
5562306a36Sopenharmony_ci * @mc_io:	Pointer to MC portal's I/O object
5662306a36Sopenharmony_ci * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
5762306a36Sopenharmony_ci * @token:	Token of DPMAC object
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci * After this function is called, no further operations are
6062306a36Sopenharmony_ci * allowed on the object without opening a new control session.
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * Return:	'0' on Success; Error code otherwise.
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_ciint dpmac_close(struct fsl_mc_io *mc_io,
6562306a36Sopenharmony_ci		u32 cmd_flags,
6662306a36Sopenharmony_ci		u16 token)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct fsl_mc_command cmd = { 0 };
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* prepare command */
7162306a36Sopenharmony_ci	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
7262306a36Sopenharmony_ci					  token);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/* send command to mc*/
7562306a36Sopenharmony_ci	return mc_send_command(mc_io, &cmd);
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/**
7962306a36Sopenharmony_ci * dpmac_get_attributes - Retrieve DPMAC attributes.
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * @mc_io:	Pointer to MC portal's I/O object
8262306a36Sopenharmony_ci * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
8362306a36Sopenharmony_ci * @token:	Token of DPMAC object
8462306a36Sopenharmony_ci * @attr:	Returned object's attributes
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci * Return:	'0' on Success; Error code otherwise.
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_ciint dpmac_get_attributes(struct fsl_mc_io *mc_io,
8962306a36Sopenharmony_ci			 u32 cmd_flags,
9062306a36Sopenharmony_ci			 u16 token,
9162306a36Sopenharmony_ci			 struct dpmac_attr *attr)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	struct dpmac_rsp_get_attributes *rsp_params;
9462306a36Sopenharmony_ci	struct fsl_mc_command cmd = { 0 };
9562306a36Sopenharmony_ci	int err;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	/* prepare command */
9862306a36Sopenharmony_ci	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
9962306a36Sopenharmony_ci					  cmd_flags,
10062306a36Sopenharmony_ci					  token);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	/* send command to mc*/
10362306a36Sopenharmony_ci	err = mc_send_command(mc_io, &cmd);
10462306a36Sopenharmony_ci	if (err)
10562306a36Sopenharmony_ci		return err;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* retrieve response parameters */
10862306a36Sopenharmony_ci	rsp_params = (struct dpmac_rsp_get_attributes *)cmd.params;
10962306a36Sopenharmony_ci	attr->eth_if = rsp_params->eth_if;
11062306a36Sopenharmony_ci	attr->link_type = rsp_params->link_type;
11162306a36Sopenharmony_ci	attr->id = le16_to_cpu(rsp_params->id);
11262306a36Sopenharmony_ci	attr->max_rate = le32_to_cpu(rsp_params->max_rate);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	return 0;
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/**
11862306a36Sopenharmony_ci * dpmac_set_link_state() - Set the Ethernet link status
11962306a36Sopenharmony_ci * @mc_io:      Pointer to opaque I/O object
12062306a36Sopenharmony_ci * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
12162306a36Sopenharmony_ci * @token:      Token of DPMAC object
12262306a36Sopenharmony_ci * @link_state: Link state configuration
12362306a36Sopenharmony_ci *
12462306a36Sopenharmony_ci * Return:      '0' on Success; Error code otherwise.
12562306a36Sopenharmony_ci */
12662306a36Sopenharmony_ciint dpmac_set_link_state(struct fsl_mc_io *mc_io,
12762306a36Sopenharmony_ci			 u32 cmd_flags,
12862306a36Sopenharmony_ci			 u16 token,
12962306a36Sopenharmony_ci			 struct dpmac_link_state *link_state)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	struct dpmac_cmd_set_link_state *cmd_params;
13262306a36Sopenharmony_ci	struct fsl_mc_command cmd = { 0 };
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/* prepare command */
13562306a36Sopenharmony_ci	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
13662306a36Sopenharmony_ci					  cmd_flags,
13762306a36Sopenharmony_ci					  token);
13862306a36Sopenharmony_ci	cmd_params = (struct dpmac_cmd_set_link_state *)cmd.params;
13962306a36Sopenharmony_ci	cmd_params->options = cpu_to_le64(link_state->options);
14062306a36Sopenharmony_ci	cmd_params->rate = cpu_to_le32(link_state->rate);
14162306a36Sopenharmony_ci	dpmac_set_field(cmd_params->state, STATE, link_state->up);
14262306a36Sopenharmony_ci	dpmac_set_field(cmd_params->state, STATE_VALID,
14362306a36Sopenharmony_ci			link_state->state_valid);
14462306a36Sopenharmony_ci	cmd_params->supported = cpu_to_le64(link_state->supported);
14562306a36Sopenharmony_ci	cmd_params->advertising = cpu_to_le64(link_state->advertising);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/* send command to mc*/
14862306a36Sopenharmony_ci	return mc_send_command(mc_io, &cmd);
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci/**
15262306a36Sopenharmony_ci * dpmac_get_counter() - Read a specific DPMAC counter
15362306a36Sopenharmony_ci * @mc_io:	Pointer to opaque I/O object
15462306a36Sopenharmony_ci * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
15562306a36Sopenharmony_ci * @token:	Token of DPMAC object
15662306a36Sopenharmony_ci * @id:		The requested counter ID
15762306a36Sopenharmony_ci * @value:	Returned counter value
15862306a36Sopenharmony_ci *
15962306a36Sopenharmony_ci * Return:	The requested counter; '0' otherwise.
16062306a36Sopenharmony_ci */
16162306a36Sopenharmony_ciint dpmac_get_counter(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
16262306a36Sopenharmony_ci		      enum dpmac_counter_id id, u64 *value)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct dpmac_cmd_get_counter *dpmac_cmd;
16562306a36Sopenharmony_ci	struct dpmac_rsp_get_counter *dpmac_rsp;
16662306a36Sopenharmony_ci	struct fsl_mc_command cmd = { 0 };
16762306a36Sopenharmony_ci	int err = 0;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
17062306a36Sopenharmony_ci					  cmd_flags,
17162306a36Sopenharmony_ci					  token);
17262306a36Sopenharmony_ci	dpmac_cmd = (struct dpmac_cmd_get_counter *)cmd.params;
17362306a36Sopenharmony_ci	dpmac_cmd->id = id;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	err = mc_send_command(mc_io, &cmd);
17662306a36Sopenharmony_ci	if (err)
17762306a36Sopenharmony_ci		return err;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	dpmac_rsp = (struct dpmac_rsp_get_counter *)cmd.params;
18062306a36Sopenharmony_ci	*value = le64_to_cpu(dpmac_rsp->counter);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	return 0;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/**
18662306a36Sopenharmony_ci * dpmac_get_api_version() - Get Data Path MAC version
18762306a36Sopenharmony_ci * @mc_io:	Pointer to MC portal's I/O object
18862306a36Sopenharmony_ci * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
18962306a36Sopenharmony_ci * @major_ver:	Major version of data path mac API
19062306a36Sopenharmony_ci * @minor_ver:	Minor version of data path mac API
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * Return:  '0' on Success; Error code otherwise.
19362306a36Sopenharmony_ci */
19462306a36Sopenharmony_ciint dpmac_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags,
19562306a36Sopenharmony_ci			  u16 *major_ver, u16 *minor_ver)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	struct dpmac_rsp_get_api_version *rsp_params;
19862306a36Sopenharmony_ci	struct fsl_mc_command cmd = { 0 };
19962306a36Sopenharmony_ci	int err;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION,
20262306a36Sopenharmony_ci					  cmd_flags,
20362306a36Sopenharmony_ci					  0);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	err = mc_send_command(mc_io, &cmd);
20662306a36Sopenharmony_ci	if (err)
20762306a36Sopenharmony_ci		return err;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	rsp_params = (struct dpmac_rsp_get_api_version *)cmd.params;
21062306a36Sopenharmony_ci	*major_ver = le16_to_cpu(rsp_params->major);
21162306a36Sopenharmony_ci	*minor_ver = le16_to_cpu(rsp_params->minor);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	return 0;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/**
21762306a36Sopenharmony_ci * dpmac_set_protocol() - Reconfigure the DPMAC protocol
21862306a36Sopenharmony_ci * @mc_io:      Pointer to opaque I/O object
21962306a36Sopenharmony_ci * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
22062306a36Sopenharmony_ci * @token:      Token of DPMAC object
22162306a36Sopenharmony_ci * @protocol:   New protocol for the DPMAC to be reconfigured in.
22262306a36Sopenharmony_ci *
22362306a36Sopenharmony_ci * Return:      '0' on Success; Error code otherwise.
22462306a36Sopenharmony_ci */
22562306a36Sopenharmony_ciint dpmac_set_protocol(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token,
22662306a36Sopenharmony_ci		       enum dpmac_eth_if protocol)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	struct dpmac_cmd_set_protocol *cmd_params;
22962306a36Sopenharmony_ci	struct fsl_mc_command cmd = { 0 };
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_PROTOCOL,
23262306a36Sopenharmony_ci					  cmd_flags, token);
23362306a36Sopenharmony_ci	cmd_params = (struct dpmac_cmd_set_protocol *)cmd.params;
23462306a36Sopenharmony_ci	cmd_params->eth_if = protocol;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	return mc_send_command(mc_io, &cmd);
23762306a36Sopenharmony_ci}
238