linux/drivers/iio/adc/palmas_gpadc.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * palmas-adc.c -- TI PALMAS GPADC.
 *
 * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
 *
 * Author: Pradeep Goudagunta <[email protected]>
 */

#include <linux/module.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/mfd/palmas.h>
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>

#define MOD_NAME
#define PALMAS_ADC_CONVERSION_TIMEOUT
#define PALMAS_TO_BE_CALCULATED
#define PALMAS_GPADC_TRIMINVALID

struct palmas_gpadc_info {};

#define PALMAS_ADC_INFO(_chan, _x1, _x2, _v1, _v2, _t1, _t2, _is_uncalibrated)

static struct palmas_gpadc_info palmas_gpadc_info[] =;

struct palmas_adc_event {};

struct palmas_gpadc_thresholds {};

/*
 * struct palmas_gpadc - the palmas_gpadc structure
 * @ch0_current:	channel 0 current source setting
 *			0: 0 uA
 *			1: 5 uA
 *			2: 15 uA
 *			3: 20 uA
 * @ch3_current:	channel 0 current source setting
 *			0: 0 uA
 *			1: 10 uA
 *			2: 400 uA
 *			3: 800 uA
 * @extended_delay:	enable the gpadc extended delay mode
 * @auto_conversion_period:	define the auto_conversion_period
 * @lock:	Lock to protect the device state during a potential concurrent
 *		read access from userspace. Reading a raw value requires a sequence
 *		of register writes, then a wait for a completion callback,
 *		and finally a register read, during which userspace could issue
 *		another read request. This lock protects a read access from
 *		ocurring before another one has finished.
 *
 * This is the palmas_gpadc structure to store run-time information
 * and pointers for this driver instance.
 */
struct palmas_gpadc {};

static struct palmas_adc_event *palmas_gpadc_get_event(struct palmas_gpadc *adc,
						       int adc_chan,
						       enum iio_event_direction dir)
{}

static bool palmas_gpadc_channel_is_freerunning(struct palmas_gpadc *adc,
						int adc_chan)
{}

/*
 * GPADC lock issue in AUTO mode.
 * Impact: In AUTO mode, GPADC conversion can be locked after disabling AUTO
 *	   mode feature.
 * Details:
 *	When the AUTO mode is the only conversion mode enabled, if the AUTO
 *	mode feature is disabled with bit GPADC_AUTO_CTRL.  AUTO_CONV1_EN = 0
 *	or bit GPADC_AUTO_CTRL.  AUTO_CONV0_EN = 0 during a conversion, the
 *	conversion mechanism can be seen as locked meaning that all following
 *	conversion will give 0 as a result.  Bit GPADC_STATUS.GPADC_AVAILABLE
 *	will stay at 0 meaning that GPADC is busy.  An RT conversion can unlock
 *	the GPADC.
 *
 * Workaround(s):
 *	To avoid the lock mechanism, the workaround to follow before any stop
 *	conversion request is:
 *	Force the GPADC state machine to be ON by using the GPADC_CTRL1.
 *		GPADC_FORCE bit = 1
 *	Shutdown the GPADC AUTO conversion using
 *		GPADC_AUTO_CTRL.SHUTDOWN_CONV[01] = 0.
 *	After 100us, force the GPADC state machine to be OFF by using the
 *		GPADC_CTRL1.  GPADC_FORCE bit = 0
 */

static int palmas_disable_auto_conversion(struct palmas_gpadc *adc)
{}

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

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

static int palmas_gpadc_start_mask_interrupt(struct palmas_gpadc *adc,
						bool mask)
{}

static int palmas_gpadc_enable(struct palmas_gpadc *adc, int adc_chan,
			       int enable)
{}

static int palmas_gpadc_read_prepare(struct palmas_gpadc *adc, int adc_chan)
{}

static void palmas_gpadc_read_done(struct palmas_gpadc *adc, int adc_chan)
{}

static int palmas_gpadc_calibrate(struct palmas_gpadc *adc, int adc_chan)
{}

static int palmas_gpadc_start_conversion(struct palmas_gpadc *adc, int adc_chan)
{}

static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,
						int adc_chan, int val)
{}

/*
 * The high and low threshold values are calculated based on the advice given
 * in TI Application Report SLIA087A, "Guide to Using the GPADC in PS65903x,
 * TPS65917-Q1, TPS65919-Q1, and TPS65916 Devices". This document recommend
 * taking ADC tolerances into account and is based on the device integral non-
 * linearity (INL), offset error and gain error:
 *
 *   raw high threshold = (ideal threshold + INL) * gain error + offset error
 *
 * The gain error include both gain error, as specified in the datasheet, and
 * the gain error drift. These paramenters vary depending on device and whether
 * the channel is calibrated (trimmed) or not.
 */
static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,
						 const int gain_error,
						 const int offset_error)
{}

/*
 * The values below are taken from the datasheet of TWL6035, TWL6037.
 * todo: get max INL, gain error, and offset error from OF.
 */
static int palmas_gpadc_get_high_threshold_raw(struct palmas_gpadc *adc,
					       struct palmas_adc_event *ev)
{}

/*
 * The values below are taken from the datasheet of TWL6035, TWL6037.
 * todo: get min INL, gain error, and offset error from OF.
 */
static int palmas_gpadc_get_low_threshold_raw(struct palmas_gpadc *adc,
					      struct palmas_adc_event *ev)
{}

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

static int palmas_gpadc_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 palmas_adc_configure_events(struct palmas_gpadc *adc);
static int palmas_adc_reset_events(struct palmas_gpadc *adc);

static int palmas_gpadc_reconfigure_event_channels(struct palmas_gpadc *adc)
{}

static int palmas_gpadc_enable_event_config(struct palmas_gpadc *adc,
					    const struct iio_chan_spec *chan,
					    enum iio_event_direction dir)
{}

static int palmas_gpadc_disable_event_config(struct palmas_gpadc *adc,
					     const struct iio_chan_spec *chan,
					     enum iio_event_direction dir)
{}

static int palmas_gpadc_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 palmas_gpadc_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 palmas_gpadc_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 const struct iio_info palmas_gpadc_iio_info =;

static const struct iio_event_spec palmas_gpadc_events[] =;

#define PALMAS_ADC_CHAN_IIO(chan, _type, chan_info)

static const struct iio_chan_spec palmas_gpadc_iio_channel[] =;

static int palmas_gpadc_get_adc_dt_data(struct platform_device *pdev,
	struct palmas_gpadc_platform_data **gpadc_pdata)
{}

static void palmas_gpadc_reset(void *data)
{}

static int palmas_gpadc_probe(struct platform_device *pdev)
{}

static int palmas_adc_configure_events(struct palmas_gpadc *adc)
{}

static int palmas_adc_reset_events(struct palmas_gpadc *adc)
{}

static int palmas_gpadc_suspend(struct device *dev)
{}

static int palmas_gpadc_resume(struct device *dev)
{
	struct iio_dev *indio_dev = dev_get_drvdata(dev);
	struct palmas_gpadc *adc = iio_priv(indio_dev);

	if (!device_may_wakeup(dev))
		return 0;

	if (adc->event0.enabled)
		disable_irq_wake(adc->irq_auto_0);

	if (adc->event1.enabled)
		disable_irq_wake(adc->irq_auto_1);

	return 0;
};

static DEFINE_SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_gpadc_suspend,
				palmas_gpadc_resume);

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

static struct platform_driver palmas_gpadc_driver =;
module_platform_driver();

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