linux/drivers/iio/adc/xilinx-ams.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Xilinx AMS driver
 *
 *  Copyright (C) 2021 Xilinx, Inc.
 *
 *  Manish Narani <[email protected]>
 *  Rajnikant Bhojani <[email protected]>
 */

#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/devm-helpers.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/overflow.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>

#include <linux/iio/events.h>
#include <linux/iio/iio.h>

/* AMS registers definitions */
#define AMS_ISR_0
#define AMS_ISR_1
#define AMS_IER_0
#define AMS_IER_1
#define AMS_IDR_0
#define AMS_IDR_1
#define AMS_PS_CSTS
#define AMS_PL_CSTS

#define AMS_VCC_PSPLL0
#define AMS_VCC_PSPLL3
#define AMS_VCCINT
#define AMS_VCCBRAM
#define AMS_VCCAUX
#define AMS_PSDDRPLL
#define AMS_PSINTFPDDR

#define AMS_VCC_PSPLL0_CH
#define AMS_VCC_PSPLL3_CH
#define AMS_VCCINT_CH
#define AMS_VCCBRAM_CH
#define AMS_VCCAUX_CH
#define AMS_PSDDRPLL_CH
#define AMS_PSINTFPDDR_CH

#define AMS_REG_CONFIG0
#define AMS_REG_CONFIG1
#define AMS_REG_CONFIG3
#define AMS_REG_CONFIG4
#define AMS_REG_SEQ_CH0
#define AMS_REG_SEQ_CH1
#define AMS_REG_SEQ_CH2

#define AMS_VUSER0_MASK
#define AMS_VUSER1_MASK
#define AMS_VUSER2_MASK
#define AMS_VUSER3_MASK

#define AMS_TEMP
#define AMS_SUPPLY1
#define AMS_SUPPLY2
#define AMS_VP_VN
#define AMS_VREFP
#define AMS_VREFN
#define AMS_SUPPLY3
#define AMS_SUPPLY4
#define AMS_SUPPLY5
#define AMS_SUPPLY6
#define AMS_SUPPLY7
#define AMS_SUPPLY8
#define AMS_SUPPLY9
#define AMS_SUPPLY10
#define AMS_VCCAMS
#define AMS_TEMP_REMOTE

#define AMS_REG_VAUX(x)

#define AMS_PS_RESET_VALUE
#define AMS_PL_RESET_VALUE

#define AMS_CONF0_CHANNEL_NUM_MASK

#define AMS_CONF1_SEQ_MASK
#define AMS_CONF1_SEQ_DEFAULT
#define AMS_CONF1_SEQ_CONTINUOUS
#define AMS_CONF1_SEQ_SINGLE_CHANNEL

#define AMS_REG_SEQ0_MASK
#define AMS_REG_SEQ2_MASK
#define AMS_REG_SEQ1_MASK

#define AMS_PS_SEQ_MASK
#define AMS_PL_SEQ_MASK

#define AMS_ALARM_TEMP
#define AMS_ALARM_SUPPLY1
#define AMS_ALARM_SUPPLY2
#define AMS_ALARM_SUPPLY3
#define AMS_ALARM_SUPPLY4
#define AMS_ALARM_SUPPLY5
#define AMS_ALARM_SUPPLY6
#define AMS_ALARM_SUPPLY7
#define AMS_ALARM_SUPPLY8
#define AMS_ALARM_SUPPLY9
#define AMS_ALARM_SUPPLY10
#define AMS_ALARM_VCCAMS
#define AMS_ALARM_TEMP_REMOTE
#define AMS_ALARM_THRESHOLD_OFF_10
#define AMS_ALARM_THRESHOLD_OFF_20

#define AMS_ALARM_THR_DIRECT_MASK
#define AMS_ALARM_THR_MIN
#define AMS_ALARM_THR_MAX

#define AMS_ALARM_MASK
#define AMS_NO_OF_ALARMS
#define AMS_PL_ALARM_START
#define AMS_PL_ALARM_MASK
#define AMS_ISR0_ALARM_MASK
#define AMS_ISR1_ALARM_MASK
#define AMS_ISR1_EOC_MASK
#define AMS_ISR1_INTR_MASK
#define AMS_ISR0_ALARM_2_TO_0_MASK
#define AMS_ISR0_ALARM_6_TO_3_MASK
#define AMS_ISR0_ALARM_12_TO_7_MASK
#define AMS_CONF1_ALARM_2_TO_0_MASK
#define AMS_CONF1_ALARM_6_TO_3_MASK
#define AMS_CONF1_ALARM_12_TO_7_MASK
#define AMS_REGCFG1_ALARM_MASK
#define AMS_REGCFG3_ALARM_MASK

#define AMS_PS_CSTS_PS_READY
#define AMS_PL_CSTS_ACCESS_MASK

#define AMS_PL_MAX_FIXED_CHANNEL
#define AMS_PL_MAX_EXT_CHANNEL

#define AMS_INIT_POLL_TIME_US
#define AMS_INIT_TIMEOUT_US
#define AMS_UNMASK_TIMEOUT_MS

/*
 * Following scale and offset value is derived from
 * UG580 (v1.7) December 20, 2016
 */
#define AMS_SUPPLY_SCALE_1VOLT_mV
#define AMS_SUPPLY_SCALE_3VOLT_mV
#define AMS_SUPPLY_SCALE_6VOLT_mV
#define AMS_SUPPLY_SCALE_DIV_BIT

#define AMS_TEMP_SCALE
#define AMS_TEMP_SCALE_DIV_BIT
#define AMS_TEMP_OFFSET

enum ams_alarm_bit {};

enum ams_seq {};

enum ams_ps_pl_seq {};

#define AMS_PS_SEQ_MAX
#define AMS_SEQ(x)
#define PS_SEQ(x)
#define PL_SEQ(x)
#define AMS_CTRL_SEQ_BASE

#define AMS_CHAN_TEMP(_scan_index, _addr, _name)

#define AMS_CHAN_VOLTAGE(_scan_index, _addr, _alarm, _name)

#define AMS_PS_CHAN_TEMP(_scan_index, _addr, _name)
#define AMS_PS_CHAN_VOLTAGE(_scan_index, _addr, _name)

#define AMS_PL_CHAN_TEMP(_scan_index, _addr, _name)
#define AMS_PL_CHAN_VOLTAGE(_scan_index, _addr, _alarm, _name)
#define AMS_PL_AUX_CHAN_VOLTAGE(_auxno)
#define AMS_CTRL_CHAN_VOLTAGE(_scan_index, _addr, _name)

/**
 * struct ams - This structure contains necessary state for xilinx-ams to operate
 * @base: physical base address of device
 * @ps_base: physical base address of PS device
 * @pl_base: physical base address of PL device
 * @clk: clocks associated with the device
 * @dev: pointer to device struct
 * @lock: to handle multiple user interaction
 * @intr_lock: to protect interrupt mask values
 * @alarm_mask: alarm configuration
 * @current_masked_alarm: currently masked due to alarm
 * @intr_mask: interrupt configuration
 * @ams_unmask_work: re-enables event once the event condition disappears
 *
 */
struct ams {};

static inline void ams_ps_update_reg(struct ams *ams, unsigned int offset,
				     u32 mask, u32 data)
{}

static inline void ams_pl_update_reg(struct ams *ams, unsigned int offset,
				     u32 mask, u32 data)
{}

static void ams_update_intrmask(struct ams *ams, u64 mask, u64 val)
{}

static void ams_disable_all_alarms(struct ams *ams)
{}

static void ams_update_ps_alarm(struct ams *ams, unsigned long alarm_mask)
{}

static void ams_update_pl_alarm(struct ams *ams, unsigned long alarm_mask)
{}

static void ams_update_alarm(struct ams *ams, unsigned long alarm_mask)
{}

static void ams_enable_channel_sequence(struct iio_dev *indio_dev)
{}

static int ams_init_device(struct ams *ams)
{}

static int ams_read_label(struct iio_dev *indio_dev,
			  struct iio_chan_spec const *chan, char *label)
{}

static int ams_enable_single_channel(struct ams *ams, unsigned int offset)
{}

static int ams_read_vcc_reg(struct ams *ams, unsigned int offset, u32 *data)
{}

static int ams_get_ps_scale(int address)
{}

static int ams_get_pl_scale(struct ams *ams, int address)
{}

static int ams_get_ctrl_scale(int address)
{}

static int ams_read_raw(struct iio_dev *indio_dev,
			struct iio_chan_spec const *chan,
			int *val, int *val2, long mask)
{}

static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir)
{}

static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
							u32 event)
{}

static int ams_get_alarm_mask(int scan_index)
{}

static int ams_read_event_config(struct iio_dev *indio_dev,
				 const struct iio_chan_spec *chan,
				 enum iio_event_type type,
				 enum iio_event_direction dir)
{}

static int ams_write_event_config(struct iio_dev *indio_dev,
				  const struct iio_chan_spec *chan,
				  enum iio_event_type type,
				  enum iio_event_direction dir,
				  int state)
{}

static int ams_read_event_value(struct iio_dev *indio_dev,
				const struct iio_chan_spec *chan,
				enum iio_event_type type,
				enum iio_event_direction dir,
				enum iio_event_info info, int *val, int *val2)
{}

static int ams_write_event_value(struct iio_dev *indio_dev,
				 const struct iio_chan_spec *chan,
				 enum iio_event_type type,
				 enum iio_event_direction dir,
				 enum iio_event_info info, int val, int val2)
{}

static void ams_handle_event(struct iio_dev *indio_dev, u32 event)
{}

static void ams_handle_events(struct iio_dev *indio_dev, unsigned long events)
{}

/**
 * ams_unmask_worker - ams alarm interrupt unmask worker
 * @work: work to be done
 *
 * The ZynqMP threshold interrupts are level sensitive. Since we can't make the
 * threshold condition go way from within the interrupt handler, this means as
 * soon as a threshold condition is present we would enter the interrupt handler
 * again and again. To work around this we mask all active threshold interrupts
 * in the interrupt handler and start a timer. In this timer we poll the
 * interrupt status and only if the interrupt is inactive we unmask it again.
 */
static void ams_unmask_worker(struct work_struct *work)
{}

static irqreturn_t ams_irq(int irq, void *data)
{}

static const struct iio_event_spec ams_temp_events[] =;

static const struct iio_event_spec ams_voltage_events[] =;

static const struct iio_chan_spec ams_ps_channels[] =;

static const struct iio_chan_spec ams_pl_channels[] =;

static const struct iio_chan_spec ams_ctrl_channels[] =;

static int ams_get_ext_chan(struct fwnode_handle *chan_node,
			    struct iio_chan_spec *channels, int num_channels)
{}

static void ams_iounmap_ps(void *data)
{}

static void ams_iounmap_pl(void *data)
{}

static int ams_init_module(struct iio_dev *indio_dev,
			   struct fwnode_handle *fwnode,
			   struct iio_chan_spec *channels)
{}

static int ams_parse_firmware(struct iio_dev *indio_dev)
{}

static const struct iio_info iio_ams_info =;

static const struct of_device_id ams_of_match_table[] =;
MODULE_DEVICE_TABLE(of, ams_of_match_table);

static int ams_probe(struct platform_device *pdev)
{}

static int ams_suspend(struct device *dev)
{}

static int ams_resume(struct device *dev)
{}

static DEFINE_SIMPLE_DEV_PM_OPS(ams_pm_ops, ams_suspend, ams_resume);

static struct platform_driver ams_driver =;
module_platform_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_AUTHOR();