misc: xilinx_sdfec: Add ability to get/set config

- Add capability to get SD-FEC config data using ioctl
XSDFEC_GET_CONFIG.

- Add capability to set SD-FEC data order using ioctl
SDFEC_SET_ORDER.

- Add capability to set SD-FEC bypass option using ioctl
XSDFEC_SET_BYPASS.

- Add capability to set SD-FEC active state using ioctl
XSDFEC_IS_ACTIVE.

Tested-by: Dragan Cvetic <dragan.cvetic@xilinx.com>
Signed-off-by: Derek Kiernan <derek.kiernan@xilinx.com>
Signed-off-by: Dragan Cvetic <dragan.cvetic@xilinx.com>
Link: https://lore.kernel.org/r/1564216438-322406-5-git-send-email-dragan.cvetic@xilinx.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Dragan Cvetic
2019-07-27 09:33:54 +01:00
committed by Greg Kroah-Hartman
parent 20ec628e80
commit 77dd39d924
2 changed files with 145 additions and 0 deletions

View File

@@ -273,6 +273,17 @@ static void update_config_from_hw(struct xsdfec_dev *xsdfec)
xsdfec->state = XSDFEC_STOPPED;
}
static int xsdfec_get_config(struct xsdfec_dev *xsdfec, void __user *arg)
{
int err;
err = copy_to_user(arg, &xsdfec->config, sizeof(xsdfec->config));
if (err)
err = -EFAULT;
return err;
}
static int xsdfec_set_turbo(struct xsdfec_dev *xsdfec, void __user *arg)
{
struct xsdfec_turbo turbo;
@@ -591,6 +602,71 @@ err_out:
return ret;
}
static int xsdfec_set_order(struct xsdfec_dev *xsdfec, void __user *arg)
{
bool order_invalid;
enum xsdfec_order order;
int err;
err = get_user(order, (enum xsdfec_order *)arg);
if (err)
return -EFAULT;
order_invalid = (order != XSDFEC_MAINTAIN_ORDER) &&
(order != XSDFEC_OUT_OF_ORDER);
if (order_invalid)
return -EINVAL;
/* Verify Device has not started */
if (xsdfec->state == XSDFEC_STARTED)
return -EIO;
xsdfec_regwrite(xsdfec, XSDFEC_ORDER_ADDR, order);
xsdfec->config.order = order;
return 0;
}
static int xsdfec_set_bypass(struct xsdfec_dev *xsdfec, bool __user *arg)
{
bool bypass;
int err;
err = get_user(bypass, arg);
if (err)
return -EFAULT;
/* Verify Device has not started */
if (xsdfec->state == XSDFEC_STARTED)
return -EIO;
if (bypass)
xsdfec_regwrite(xsdfec, XSDFEC_BYPASS_ADDR, 1);
else
xsdfec_regwrite(xsdfec, XSDFEC_BYPASS_ADDR, 0);
xsdfec->config.bypass = bypass;
return 0;
}
static int xsdfec_is_active(struct xsdfec_dev *xsdfec, bool __user *arg)
{
u32 reg_value;
bool is_active;
int err;
reg_value = xsdfec_regread(xsdfec, XSDFEC_ACTIVE_ADDR);
/* using a double ! operator instead of casting */
is_active = !!(reg_value & XSDFEC_IS_ACTIVITY_SET);
err = put_user(is_active, arg);
if (err)
return -EFAULT;
return err;
}
static u32
xsdfec_translate_axis_width_cfg_val(enum xsdfec_axis_width axis_width_cfg)
{
@@ -681,6 +757,9 @@ static long xsdfec_dev_ioctl(struct file *fptr, unsigned int cmd,
}
switch (cmd) {
case XSDFEC_GET_CONFIG:
rval = xsdfec_get_config(xsdfec, arg);
break;
case XSDFEC_SET_TURBO:
rval = xsdfec_set_turbo(xsdfec, arg);
break;
@@ -690,6 +769,15 @@ static long xsdfec_dev_ioctl(struct file *fptr, unsigned int cmd,
case XSDFEC_ADD_LDPC_CODE_PARAMS:
rval = xsdfec_add_ldpc(xsdfec, arg);
break;
case XSDFEC_SET_ORDER:
rval = xsdfec_set_order(xsdfec, arg);
break;
case XSDFEC_SET_BYPASS:
rval = xsdfec_set_bypass(xsdfec, arg);
break;
case XSDFEC_IS_ACTIVE:
rval = xsdfec_is_active(xsdfec, (bool __user *)arg);
break;
default:
/* Should not get here */
break;