// SPDX-License-Identifier: GPL-2.0-only /* * * TWL4030 MADC module driver-This driver monitors the real time * conversion of analog signals like battery temperature, * battery type, battery level etc. * * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/ * J Keerthy <[email protected]> * * Based on twl4030-madc.c * Copyright (C) 2008 Nokia Corporation * Mikko Ylinen <[email protected]> * * Amit Kucheria <[email protected]> */ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/slab.h> #include <linux/mfd/twl.h> #include <linux/stddef.h> #include <linux/mutex.h> #include <linux/bitops.h> #include <linux/jiffies.h> #include <linux/types.h> #include <linux/gfp.h> #include <linux/err.h> #include <linux/regulator/consumer.h> #include <linux/iio/iio.h> #define TWL4030_MADC_MAX_CHANNELS … #define TWL4030_MADC_CTRL1 … #define TWL4030_MADC_CTRL2 … #define TWL4030_MADC_RTSELECT_LSB … #define TWL4030_MADC_SW1SELECT_LSB … #define TWL4030_MADC_SW2SELECT_LSB … #define TWL4030_MADC_RTAVERAGE_LSB … #define TWL4030_MADC_SW1AVERAGE_LSB … #define TWL4030_MADC_SW2AVERAGE_LSB … #define TWL4030_MADC_CTRL_SW1 … #define TWL4030_MADC_CTRL_SW2 … #define TWL4030_MADC_RTCH0_LSB … #define TWL4030_MADC_GPCH0_LSB … #define TWL4030_MADC_MADCON … #define TWL4030_MADC_BUSY … /* MADC conversion completion */ #define TWL4030_MADC_EOC_SW … /* MADC SWx start conversion */ #define TWL4030_MADC_SW_START … #define TWL4030_MADC_ADCIN0 … #define TWL4030_MADC_ADCIN1 … #define TWL4030_MADC_ADCIN2 … #define TWL4030_MADC_ADCIN3 … #define TWL4030_MADC_ADCIN4 … #define TWL4030_MADC_ADCIN5 … #define TWL4030_MADC_ADCIN6 … #define TWL4030_MADC_ADCIN7 … #define TWL4030_MADC_ADCIN8 … #define TWL4030_MADC_ADCIN9 … #define TWL4030_MADC_ADCIN10 … #define TWL4030_MADC_ADCIN11 … #define TWL4030_MADC_ADCIN12 … #define TWL4030_MADC_ADCIN13 … #define TWL4030_MADC_ADCIN14 … #define TWL4030_MADC_ADCIN15 … /* Fixed channels */ #define TWL4030_MADC_BTEMP … #define TWL4030_MADC_VBUS … #define TWL4030_MADC_VBKB … #define TWL4030_MADC_ICHG … #define TWL4030_MADC_VCHG … #define TWL4030_MADC_VBAT … /* Step size and prescaler ratio */ #define TEMP_STEP_SIZE … #define TEMP_PSR_R … #define CURR_STEP_SIZE … #define CURR_PSR_R1 … #define CURR_PSR_R2 … #define TWL4030_BCI_BCICTL1 … #define TWL4030_BCI_CGAIN … #define TWL4030_BCI_MESBAT … #define TWL4030_BCI_TYPEN … #define TWL4030_BCI_ITHEN … #define REG_BCICTL2 … #define TWL4030_BCI_ITHSENS … /* Register and bits for GPBR1 register */ #define TWL4030_REG_GPBR1 … #define TWL4030_GPBR1_MADC_HFCLK_EN … #define TWL4030_USB_SEL_MADC_MCPC … #define TWL4030_USB_CARKIT_ANA_CTRL … struct twl4030_madc_conversion_method { … }; /** * struct twl4030_madc_request - madc request packet for channel conversion * @channels: 16 bit bitmap for individual channels * @do_avg: sample the input channel for 4 consecutive cycles * @method: RT, SW1, SW2 * @type: Polling or interrupt based method * @active: Flag if request is active * @result_pending: Flag from irq handler, that result is ready * @raw: Return raw value, do not convert it * @rbuf: Result buffer */ struct twl4030_madc_request { … }; enum conversion_methods { … }; enum sample_type { … }; /** * struct twl4030_madc_data - a container for madc info * @dev: Pointer to device structure for madc * @lock: Mutex protecting this data structure * @usb3v1: Pointer to bias regulator for madc * @requests: Array of request struct corresponding to SW1, SW2 and RT * @use_second_irq: IRQ selection (main or co-processor) * @imr: Interrupt mask register of MADC * @isr: Interrupt status register of MADC */ struct twl4030_madc_data { … }; static int twl4030_madc_conversion(struct twl4030_madc_request *req); static int twl4030_madc_read(struct iio_dev *iio_dev, const struct iio_chan_spec *chan, int *val, int *val2, long mask) { … } static const struct iio_info twl4030_madc_iio_info = …; #define TWL4030_ADC_CHANNEL(_channel, _type, _name) … static const struct iio_chan_spec twl4030_madc_iio_channels[] = …; static struct twl4030_madc_data *twl4030_madc; static const struct s16_fract twl4030_divider_ratios[16] = …; /* Conversion table from -3 to 55 degrees Celcius */ static int twl4030_therm_tbl[] = …; /* * Structure containing the registers * of different conversion methods supported by MADC. * Hardware or RT real time conversion request initiated by external host * processor for RT Signal conversions. * External host processors can also request for non RT conversions * SW1 and SW2 software conversions also called asynchronous or GPC request. */ static const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = …; /** * twl4030_madc_channel_raw_read() - Function to read a particular channel value * @madc: pointer to struct twl4030_madc_data * @reg: lsb of ADC Channel * * Return: 0 on success, an error code otherwise. */ static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg) { … } /* * Return battery temperature in degrees Celsius * Or < 0 on failure. */ static int twl4030battery_temperature(int raw_volt) { … } static int twl4030battery_current(int raw_volt) { … } /* * Function to read channel values * @madc - pointer to twl4030_madc_data struct * @reg_base - Base address of the first channel * @Channels - 16 bit bitmap. If the bit is set, channel's value is read * @buf - The channel values are stored here. if read fails error * @raw - Return raw values without conversion * value is stored * Returns the number of successfully read channels. */ static int twl4030_madc_read_channels(struct twl4030_madc_data *madc, u8 reg_base, unsigned long channels, int *buf, bool raw) { … } /* * Disables irq. * @madc - pointer to twl4030_madc_data struct * @id - irq number to be disabled * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2 * corresponding to RT, SW1, SW2 conversion requests. * Returns error if i2c read/write fails. */ static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id) { … } static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc) { … } /* * Function which enables the madc conversion * by writing to the control register. * @madc - pointer to twl4030_madc_data struct * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1 * corresponding to RT SW1 or SW2 conversion methods. * Returns 0 if succeeds else a negative error value */ static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc, int conv_method) { … } /* * Function that waits for conversion to be ready * @madc - pointer to twl4030_madc_data struct * @timeout_ms - timeout value in milliseconds * @status_reg - ctrl register * returns 0 if succeeds else a negative error value */ static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc, unsigned int timeout_ms, u8 status_reg) { … } /* * An exported function which can be called from other kernel drivers. * @req twl4030_madc_request structure * req->rbuf will be filled with read values of channels based on the * channel index. If a particular channel reading fails there will * be a negative error value in the corresponding array element. * returns 0 if succeeds else error value */ static int twl4030_madc_conversion(struct twl4030_madc_request *req) { … } /** * twl4030_madc_set_current_generator() - setup bias current * * @madc: pointer to twl4030_madc_data struct * @chan: can be one of the two values: * 0 - Enables bias current for main battery type reading * 1 - Enables bias current for main battery temperature sensing * @on: enable or disable chan. * * Function to enable or disable bias current for * main battery type reading or temperature sensing */ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc, int chan, int on) { … } /* * Function that sets MADC software power on bit to enable MADC * @madc - pointer to twl4030_madc_data struct * @on - Enable or disable MADC software power on bit. * returns error if i2c read/write fails else 0 */ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on) { … } /* * Initialize MADC and request for threaded irq */ static int twl4030_madc_probe(struct platform_device *pdev) { … } static void twl4030_madc_remove(struct platform_device *pdev) { … } static const struct of_device_id twl_madc_of_match[] = …; MODULE_DEVICE_TABLE(of, twl_madc_of_match); static struct platform_driver twl4030_madc_driver = …; module_platform_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_AUTHOR(…) …; MODULE_ALIAS(…) …;