#include <linux/cleanup.h>
#include <linux/dev_printk.h>
#include <linux/string.h>
#include <linux/types.h>
#include "chan.h"
#include "core.h"
int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index)
{
struct zl3073x_chan *chan = &zldev->chan[index];
int rc;
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MON_STATUS(index),
&chan->mon_status);
if (rc)
return rc;
return zl3073x_read_u8(zldev, ZL_REG_DPLL_REFSEL_STATUS(index),
&chan->refsel_status);
}
int zl3073x_chan_state_fetch(struct zl3073x_dev *zldev, u8 index)
{
struct zl3073x_chan *chan = &zldev->chan[index];
int rc, i;
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MODE_REFSEL(index),
&chan->mode_refsel);
if (rc)
return rc;
dev_dbg(zldev->dev, "DPLL%u mode: %u, ref: %u\n", index,
zl3073x_chan_mode_get(chan), zl3073x_chan_ref_get(chan));
rc = zl3073x_chan_state_update(zldev, index);
if (rc)
return rc;
dev_dbg(zldev->dev,
"DPLL%u lock_state: %u, ho: %u, sel_state: %u, sel_ref: %u\n",
index, zl3073x_chan_lock_state_get(chan),
zl3073x_chan_is_ho_ready(chan) ? 1 : 0,
zl3073x_chan_refsel_state_get(chan),
zl3073x_chan_refsel_ref_get(chan));
guard(mutex)(&zldev->multiop_lock);
rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_RD,
ZL_REG_DPLL_MB_MASK, BIT(index));
if (rc)
return rc;
for (i = 0; i < ARRAY_SIZE(chan->ref_prio); i++) {
rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_REF_PRIO(i),
&chan->ref_prio[i]);
if (rc)
return rc;
}
return 0;
}
const struct zl3073x_chan *zl3073x_chan_state_get(struct zl3073x_dev *zldev,
u8 index)
{
return &zldev->chan[index];
}
int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index,
const struct zl3073x_chan *chan)
{
struct zl3073x_chan *dchan = &zldev->chan[index];
int rc, i;
if (!memcmp(&dchan->cfg, &chan->cfg, sizeof(chan->cfg)))
return 0;
if (dchan->mode_refsel != chan->mode_refsel) {
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MODE_REFSEL(index),
chan->mode_refsel);
if (rc)
return rc;
dchan->mode_refsel = chan->mode_refsel;
}
if (!memcmp(dchan->ref_prio, chan->ref_prio, sizeof(chan->ref_prio))) {
dchan->cfg = chan->cfg;
return 0;
}
guard(mutex)(&zldev->multiop_lock);
rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_RD,
ZL_REG_DPLL_MB_MASK, BIT(index));
if (rc)
return rc;
for (i = 0; i < ARRAY_SIZE(chan->ref_prio); i++) {
if (dchan->ref_prio[i] != chan->ref_prio[i]) {
rc = zl3073x_write_u8(zldev,
ZL_REG_DPLL_REF_PRIO(i),
chan->ref_prio[i]);
if (rc)
return rc;
}
}
rc = zl3073x_mb_op(zldev, ZL_REG_DPLL_MB_SEM, ZL_DPLL_MB_SEM_WR,
ZL_REG_DPLL_MB_MASK, BIT(index));
if (rc)
return rc;
dchan->cfg = chan->cfg;
return 0;
}