#ifndef _ZL3073X_CORE_H
#define _ZL3073X_CORE_H
#include <linux/bitfield.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include "out.h"
#include "ref.h"
#include "regs.h"
#include "synth.h"
struct device;
struct regmap;
struct zl3073x_dpll;
#define ZL3073X_MAX_CHANNELS 5
#define ZL3073X_NUM_REFS 10
#define ZL3073X_NUM_OUTS 10
#define ZL3073X_NUM_SYNTHS 5
#define ZL3073X_NUM_INPUT_PINS ZL3073X_NUM_REFS
#define ZL3073X_NUM_OUTPUT_PINS (ZL3073X_NUM_OUTS * 2)
#define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \
ZL3073X_NUM_OUTPUT_PINS)
struct zl3073x_dev {
struct device *dev;
struct regmap *regmap;
struct mutex multiop_lock;
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
struct zl3073x_out out[ZL3073X_NUM_OUTS];
struct zl3073x_synth synth[ZL3073X_NUM_SYNTHS];
struct list_head dplls;
struct kthread_worker *kworker;
struct kthread_delayed_work work;
u64 clock_id;
u8 phase_avg_factor;
};
struct zl3073x_chip_info {
const u16 *ids;
size_t num_ids;
int num_channels;
};
extern const struct zl3073x_chip_info zl30731_chip_info;
extern const struct zl3073x_chip_info zl30732_chip_info;
extern const struct zl3073x_chip_info zl30733_chip_info;
extern const struct zl3073x_chip_info zl30734_chip_info;
extern const struct zl3073x_chip_info zl30735_chip_info;
extern const struct regmap_config zl3073x_regmap_config;
struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
int zl3073x_dev_probe(struct zl3073x_dev *zldev,
const struct zl3073x_chip_info *chip_info);
int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full);
void zl3073x_dev_stop(struct zl3073x_dev *zldev);
static inline u8 zl3073x_dev_phase_avg_factor_get(struct zl3073x_dev *zldev)
{
return zldev->phase_avg_factor;
}
int zl3073x_dev_phase_avg_factor_set(struct zl3073x_dev *zldev, u8 factor);
struct zl3073x_hwreg_seq_item {
u32 addr;
u32 value;
u32 mask;
u32 wait;
};
#define HWREG_SEQ_ITEM(_addr, _value, _mask, _wait) \
{ \
.addr = _addr, \
.value = FIELD_PREP_CONST(_mask, _value), \
.mask = _mask, \
.wait = _wait, \
}
int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val,
unsigned int mask_reg, u16 mask_val);
int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask);
int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val);
int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val);
int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val);
int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val);
int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val);
int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val);
int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val);
int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val);
int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value);
int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value);
int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value,
u32 mask);
int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
const struct zl3073x_hwreg_seq_item *seq,
size_t num_items);
int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
static inline bool
zl3073x_is_n_pin(u8 id)
{
return id & 1;
}
static inline bool
zl3073x_is_p_pin(u8 id)
{
return !zl3073x_is_n_pin(id);
}
static inline u8
zl3073x_input_pin_ref_get(u8 id)
{
return id;
}
static inline u8
zl3073x_output_pin_out_get(u8 id)
{
return id / 2;
}
static inline u32
zl3073x_dev_ref_freq_get(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_ref *ref = zl3073x_ref_state_get(zldev, index);
return zl3073x_ref_freq_get(ref);
}
static inline bool
zl3073x_dev_ref_is_diff(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_ref *ref = zl3073x_ref_state_get(zldev, index);
return zl3073x_ref_is_diff(ref);
}
static inline bool
zl3073x_dev_ref_is_status_ok(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_ref *ref = zl3073x_ref_state_get(zldev, index);
return zl3073x_ref_is_status_ok(ref);
}
static inline u32
zl3073x_dev_synth_freq_get(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_synth *synth;
synth = zl3073x_synth_state_get(zldev, index);
return zl3073x_synth_freq_get(synth);
}
static inline u8
zl3073x_dev_out_synth_get(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
return zl3073x_out_synth_get(out);
}
static inline bool
zl3073x_dev_out_is_enabled(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
const struct zl3073x_synth *synth;
u8 synth_id;
synth_id = zl3073x_out_synth_get(out);
synth = zl3073x_synth_state_get(zldev, synth_id);
return zl3073x_synth_is_enabled(synth) && zl3073x_out_is_enabled(out);
}
static inline
u8 zl3073x_dev_out_dpll_get(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
const struct zl3073x_synth *synth;
u8 synth_id;
synth_id = zl3073x_out_synth_get(out);
synth = zl3073x_synth_state_get(zldev, synth_id);
return zl3073x_synth_dpll_get(synth);
}
static inline u32
zl3073x_dev_output_pin_freq_get(struct zl3073x_dev *zldev, u8 id)
{
const struct zl3073x_synth *synth;
const struct zl3073x_out *out;
u8 out_id;
u32 freq;
out_id = zl3073x_output_pin_out_get(id);
out = zl3073x_out_state_get(zldev, out_id);
synth = zl3073x_synth_state_get(zldev, zl3073x_out_synth_get(out));
freq = zl3073x_synth_freq_get(synth) / out->div;
if (zl3073x_out_is_ndiv(out) && zl3073x_is_n_pin(id))
freq /= out->esync_n_period;
return freq;
}
static inline bool
zl3073x_dev_out_is_diff(struct zl3073x_dev *zldev, u8 index)
{
const struct zl3073x_out *out = zl3073x_out_state_get(zldev, index);
return zl3073x_out_is_diff(out);
}
static inline bool
zl3073x_dev_output_pin_is_enabled(struct zl3073x_dev *zldev, u8 id)
{
u8 out_id = zl3073x_output_pin_out_get(id);
const struct zl3073x_out *out;
out = zl3073x_out_state_get(zldev, out_id);
if (!zl3073x_dev_out_is_enabled(zldev, out_id))
return false;
switch (zl3073x_out_signal_format_get(out)) {
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED:
return false;
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P:
if (zl3073x_is_n_pin(id))
return false;
break;
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N:
if (zl3073x_is_p_pin(id))
return false;
break;
default:
break;
}
return true;
}
#endif