On Wed, 11 Jan 2017, Linus Walleij wrote: > The AB8500 GPADC driver is indeed a "general purpose ADC" driver, > and while the IIO subsystem did not exist when the driver was > first merged, it is never too late to clean things up and move it > to the right place. > > We have to cut a bunch of debugfs luggage to make this transition > swift, but all these files to is read out the raw values of the > ADC and the IIO subsystem already has a standard sysfs ABI for > doing exactly this: no debugfs is needed. > > We convert the present driver to IIO in the move. > > Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx> > --- > drivers/iio/adc/Kconfig | 7 + > drivers/iio/adc/Makefile | 1 + > drivers/{mfd => iio/adc}/ab8500-gpadc.c | 469 ++++++---- > drivers/mfd/Kconfig | 7 - > drivers/mfd/Makefile | 1 - > drivers/mfd/ab8500-debugfs.c | 1448 +++++-------------------------- > include/linux/mfd/abx500/ab8500-gpadc.h | 75 -- > 7 files changed, 511 insertions(+), 1497 deletions(-) > rename drivers/{mfd => iio/adc}/ab8500-gpadc.c (76%) > delete mode 100644 include/linux/mfd/abx500/ab8500-gpadc.h Ack for it being moved out of MFD. Acked-by: Lee Jones <lee.jones@xxxxxxxxxx> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > index 38bc319904c4..e524bdeb3e27 100644 > --- a/drivers/iio/adc/Kconfig > +++ b/drivers/iio/adc/Kconfig > @@ -5,6 +5,13 @@ > > menu "Analog to digital converters" > > +config AB8500_GPADC > + bool "ST-Ericsson AB8500 GPADC driver" > + depends on AB8500_CORE && REGULATOR_AB8500 > + default y > + help > + AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage > + > config AD_SIGMA_DELTA > tristate > select IIO_BUFFER > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile > index d36c4be8d1fc..025ec9a547a8 100644 > --- a/drivers/iio/adc/Makefile > +++ b/drivers/iio/adc/Makefile > @@ -3,6 +3,7 @@ > # > > # When adding new entries keep the list in alphabetical order > +obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o > obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o > obj-$(CONFIG_AD7266) += ad7266.o > obj-$(CONFIG_AD7291) += ad7291.o > diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c > similarity index 76% > rename from drivers/mfd/ab8500-gpadc.c > rename to drivers/iio/adc/ab8500-gpadc.c > index f4e94869d612..ba4e6f5a6cb9 100644 > --- a/drivers/mfd/ab8500-gpadc.c > +++ b/drivers/iio/adc/ab8500-gpadc.c > @@ -6,8 +6,11 @@ > * Author: Daniel Willerud <daniel.willerud@xxxxxxxxxxxxxx> > * Author: Johan Palsson <johan.palsson@xxxxxxxxxxxxxx> > * Author: M'boumba Cedric Madianga > + * Author: Linus Walleij <linus.walleij@xxxxxxxxxx> > */ > #include <linux/init.h> > +#include <linux/iio/iio.h> > +#include <linux/iio/sysfs.h> > #include <linux/device.h> > #include <linux/interrupt.h> > #include <linux/spinlock.h> > @@ -18,10 +21,48 @@ > #include <linux/regulator/consumer.h> > #include <linux/err.h> > #include <linux/slab.h> > -#include <linux/list.h> > #include <linux/mfd/abx500.h> > #include <linux/mfd/abx500/ab8500.h> > -#include <linux/mfd/abx500/ab8500-gpadc.h> > + > +/* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2 > + * and ADCHwSel[4:0] in GPADCCtrl3 ) */ > +#define BAT_CTRL 0x01 > +#define BTEMP_BALL 0x02 > +#define MAIN_CHARGER_V 0x03 > +#define ACC_DETECT1 0x04 > +#define ACC_DETECT2 0x05 > +#define ADC_AUX1 0x06 > +#define ADC_AUX2 0x07 > +#define MAIN_BAT_V 0x08 > +#define VBUS_V 0x09 > +#define MAIN_CHARGER_C 0x0A > +#define USB_CHARGER_C 0x0B > +#define BK_BAT_V 0x0C > +#define DIE_TEMP 0x0D > +#define USB_ID 0x0E > +#define XTAL_TEMP 0x12 > +#define VBAT_TRUE_MEAS 0x13 > +#define BAT_CTRL_AND_IBAT 0x1C > +#define VBAT_MEAS_AND_IBAT 0x1D > +#define VBAT_TRUE_MEAS_AND_IBAT 0x1E > +#define BAT_TEMP_AND_IBAT 0x1F > + > +/* Virtual channel used only for ibat convertion to ampere > + * Battery current conversion (ibat) cannot be requested as a single conversion > + * but it is always in combination with other input requests > + */ > +#define IBAT_VIRTUAL_CHANNEL 0xFF > + > +#define SAMPLE_1 1 > +#define SAMPLE_4 4 > +#define SAMPLE_8 8 > +#define SAMPLE_16 16 > +#define RISING_EDGE 0 > +#define FALLING_EDGE 1 > + > +/* Arbitrary ADC conversion type constants */ > +#define ADC_SW 0 > +#define ADC_HW 1 > > /* > * GPADC register offsets > @@ -140,11 +181,27 @@ struct adc_cal_data { > }; > > /** > + * struct ab8500_gpadc_chan_info - per-channel GPADC info > + * @name: name of the channel > + * @id: the internal AB8500 ID number for the channel > + */ > +struct ab8500_gpadc_chan_info { > + const char *name; > + u8 id; > + u8 avg_sample; > + u8 trig_edge; > + u8 trig_timer; > + u8 conv_type; > +}; > + > + > +/** > * struct ab8500_gpadc - AB8500 GPADC device information > * @dev: pointer to the struct device > - * @node: a list of AB8500 GPADCs, hence prepared for > - reentrance > - * @parent: pointer to the struct ab8500 > + * @ab8500: pointer to the struct ab8500 > + * @nchans: number of IIO channels > + * @chans: Internal channel information container > + * @iio_chans: IIO channels > * @ab8500_gpadc_complete: pointer to the struct completion, to indicate > * the completion of gpadc conversion > * @ab8500_gpadc_lock: structure of type mutex > @@ -157,8 +214,10 @@ struct adc_cal_data { > */ > struct ab8500_gpadc { > struct device *dev; > - struct list_head node; > - struct ab8500 *parent; > + struct ab8500 *ab8500; > + unsigned int nchans; > + struct ab8500_gpadc_chan_info *chans; > + struct iio_chan_spec *iio_chans; > struct completion ab8500_gpadc_complete; > struct mutex ab8500_gpadc_lock; > struct regulator *regu; > @@ -167,29 +226,27 @@ struct ab8500_gpadc { > struct adc_cal_data cal_data[NBR_CAL_INPUTS]; > }; > > -static LIST_HEAD(ab8500_gpadc_list); > - > -/** > - * ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC > - * (i.e. the first GPADC in the instance list) > - */ > -struct ab8500_gpadc *ab8500_gpadc_get(char *name) > +static struct ab8500_gpadc_chan_info * > +ab8500_gpadc_get_channel(struct ab8500_gpadc *gpadc, u8 chan) > { > - struct ab8500_gpadc *gpadc; > + struct ab8500_gpadc_chan_info *ch; > + int i; > > - list_for_each_entry(gpadc, &ab8500_gpadc_list, node) { > - if (!strcmp(name, dev_name(gpadc->dev))) > - return gpadc; > + for (i = 0; i < gpadc->nchans; i++) { > + ch = &gpadc->chans[i]; > + if (ch->id == chan) > + break; > } > + if (i == gpadc->nchans) > + return NULL; > > - return ERR_PTR(-ENOENT); > + return ch; > } > -EXPORT_SYMBOL(ab8500_gpadc_get); > > /** > * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage > */ > -int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, > +static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, > int ad_value) > { > int res; > @@ -294,70 +351,11 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, > } > return res; > } > -EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); > - > -/** > - * ab8500_gpadc_sw_hw_convert() - gpadc conversion > - * @channel: analog channel to be converted to digital data > - * @avg_sample: number of ADC sample to average > - * @trig_egde: selected ADC trig edge > - * @trig_timer: selected ADC trigger delay timer > - * @conv_type: selected conversion type (HW or SW conversion) > - * > - * This function converts the selected analog i/p to digital > - * data. > - */ > -int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel, > - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) > -{ > - int ad_value; > - int voltage; > - > - ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, > - trig_edge, trig_timer, conv_type); > - > - /* On failure retry a second time */ > - if (ad_value < 0) > - ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample, > - trig_edge, trig_timer, conv_type); > - if (ad_value < 0) { > - dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", > - channel); > - return ad_value; > - } > - > - voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); > - if (voltage < 0) > - dev_err(gpadc->dev, > - "GPADC to voltage conversion failed ch: %d AD: 0x%x\n", > - channel, ad_value); > - > - return voltage; > -} > -EXPORT_SYMBOL(ab8500_gpadc_sw_hw_convert); > - > -/** > - * ab8500_gpadc_read_raw() - gpadc read > - * @channel: analog channel to be read > - * @avg_sample: number of ADC sample to average > - * @trig_edge: selected trig edge > - * @trig_timer: selected ADC trigger delay timer > - * @conv_type: selected conversion type (HW or SW conversion) > - * > - * This function obtains the raw ADC value for an hardware conversion, > - * this then needs to be converted by calling ab8500_gpadc_ad_to_voltage() > - */ > -int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, > - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) > -{ > - return ab8500_gpadc_double_read_raw(gpadc, channel, avg_sample, > - trig_edge, trig_timer, conv_type, > - NULL); > -} > > -int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, > - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type, > - int *ibat) > +static int ab8500_gpadc_read(struct ab8500_gpadc *gpadc, u8 channel, > + u8 avg_sample, u8 trig_edge, > + u8 trig_timer, u8 conv_type, > + int *ibat) > { > int ret; > int looplimit = 0; > @@ -442,7 +440,7 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, > val_reg1 |= EN_BUF | EN_ICHAR; > break; > case BTEMP_BALL: > - if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { > + if (!is_ab8500_2p0_or_earlier(gpadc->ab8500)) { > val_reg1 |= EN_BUF | BTEMP_PULL_UP; > /* > * Delay might be needed for ABB8500 cut 3.0, if not, > @@ -593,7 +591,6 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, > "gpadc_conversion: Failed to AD convert channel %d\n", channel); > return ret; > } > -EXPORT_SYMBOL(ab8500_gpadc_read_raw); > > /** > * ab8500_bm_gpadcconvend_handler() - isr for gpadc conversion completion > @@ -605,9 +602,9 @@ EXPORT_SYMBOL(ab8500_gpadc_read_raw); > * can be read from the registers. > * Returns IRQ status(IRQ_HANDLED) > */ > -static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *_gpadc) > +static irqreturn_t ab8500_bm_gpadcconvend_handler(int irq, void *data) > { > - struct ab8500_gpadc *gpadc = _gpadc; > + struct ab8500_gpadc *gpadc = data; > > complete(&gpadc->ab8500_gpadc_complete); > > @@ -644,7 +641,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) > s64 V_gain, V_offset, V2A_gain, V2A_offset; > struct ab8500 *ab8500; > > - ab8500 = gpadc->parent; > + ab8500 = gpadc->ab8500; > > /* First we read all OTP registers and store the error code */ > for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { > @@ -868,10 +865,68 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) > gpadc->cal_data[ADC_INPUT_VBAT].offset); > } > > +static int ab8500_gpadc_read_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int *val, int *val2, long mask) > +{ > + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); > + const struct ab8500_gpadc_chan_info *ch; > + int raw_val; > + int processed; > + > + ch = ab8500_gpadc_get_channel(gpadc, chan->address); > + if (!ch) { > + dev_err(gpadc->dev, "no such channel %lu\n", > + chan->address); > + return -EINVAL; > + } > + > + dev_info(gpadc->dev, "read channel %d\n", ch->id); > + > + raw_val = ab8500_gpadc_read(gpadc, ch->id, ch->avg_sample, > + ch->trig_edge, ch->trig_timer, > + ch->conv_type, NULL); > + if (raw_val < 0) > + return raw_val; > + > + if (mask == IIO_CHAN_INFO_RAW) { > + *val = raw_val; > + return IIO_VAL_INT; > + } > + > + processed = ab8500_gpadc_ad_to_voltage(gpadc, ch->id, raw_val); > + if (processed < 0) > + return processed; > + > + /* Return millivolt or milliamps or millicentigrades */ > + *val = processed * 1000; > + return IIO_VAL_INT; > +} > + > +static int ab8500_gpadc_of_xlate(struct iio_dev *indio_dev, > + const struct of_phandle_args *iiospec) > +{ > + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); > + unsigned int i; > + > + for (i = 0; i < gpadc->nchans; i++) > + if (gpadc->iio_chans[i].channel == iiospec->args[0]) > + return i; > + > + return -EINVAL; > +} > + > +static const struct iio_info ab8500_gpadc_info = { > + .driver_module = THIS_MODULE, > + .of_xlate = ab8500_gpadc_of_xlate, > + .read_raw = ab8500_gpadc_read_raw, > +}; > + > #ifdef CONFIG_PM > static int ab8500_gpadc_runtime_suspend(struct device *dev) > { > - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); > + struct iio_dev *indio_dev = dev_get_drvdata(dev); > + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); > > regulator_disable(gpadc->regu); > return 0; > @@ -879,7 +934,8 @@ static int ab8500_gpadc_runtime_suspend(struct device *dev) > > static int ab8500_gpadc_runtime_resume(struct device *dev) > { > - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); > + struct iio_dev *indio_dev = dev_get_drvdata(dev); > + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); > int ret; > > ret = regulator_enable(gpadc->regu); > @@ -887,12 +943,11 @@ static int ab8500_gpadc_runtime_resume(struct device *dev) > dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret); > return ret; > } > -#endif > > -#ifdef CONFIG_PM_SLEEP > static int ab8500_gpadc_suspend(struct device *dev) > { > - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); > + struct iio_dev *indio_dev = dev_get_drvdata(dev); > + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); > > mutex_lock(&gpadc->ab8500_gpadc_lock); > > @@ -904,7 +959,8 @@ static int ab8500_gpadc_suspend(struct device *dev) > > static int ab8500_gpadc_resume(struct device *dev) > { > - struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); > + struct iio_dev *indio_dev = dev_get_drvdata(dev); > + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); > int ret; > > ret = regulator_enable(gpadc->regu); > @@ -919,114 +975,207 @@ static int ab8500_gpadc_resume(struct device *dev) > } > #endif > > +static int ab8500_gpadc_parse_channel(struct device *dev, > + struct device_node *np, > + struct ab8500_gpadc_chan_info *ch, > + struct iio_chan_spec *iio_chan) > +{ > + const char *name = np->name; > + u32 chan; > + int ret; > + > + ret = of_property_read_u32(np, "reg", &chan); > + if (ret) { > + dev_err(dev, "invalid channel number %s\n", name); > + return ret; > + } > + if (chan > BAT_TEMP_AND_IBAT) { > + dev_err(dev, "%s too big channel number %d\n", name, chan); > + return -EINVAL; > + } > + > + iio_chan->channel = chan; > + iio_chan->datasheet_name = name; > + iio_chan->indexed = 1; > + iio_chan->address = chan; > + iio_chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); > + /* All are voltages */ > + iio_chan->type = IIO_VOLTAGE; > + > + ch->id = chan; > + > + /* Sensible defaults */ > + ch->avg_sample = SAMPLE_16; > + ch->trig_edge = RISING_EDGE; > + ch->conv_type = ADC_SW; > + ch->trig_timer = 0; > + > + return 0; > +} > + > +static int ab8500_gpadc_parse_channels(struct ab8500_gpadc *gpadc, > + struct device_node *np) > +{ > + struct device_node *child; > + struct ab8500_gpadc_chan_info *ch; > + int i; > + > + gpadc->nchans = of_get_available_child_count(np); > + if (!gpadc->nchans) { > + dev_err(gpadc->dev, "no channel children\n"); > + return -ENODEV; > + } > + dev_info(gpadc->dev, "found %d ADC channels\n", gpadc->nchans); > + > + gpadc->iio_chans = devm_kcalloc(gpadc->dev, gpadc->nchans, > + sizeof(*gpadc->iio_chans), GFP_KERNEL); > + if (!gpadc->iio_chans) > + return -ENOMEM; > + > + gpadc->chans = devm_kcalloc(gpadc->dev, gpadc->nchans, > + sizeof(*gpadc->chans), GFP_KERNEL); > + if (!gpadc->chans) > + return -ENOMEM; > + > + i = 0; > + for_each_available_child_of_node(np, child) { > + struct iio_chan_spec *iio_chan; > + int ret; > + > + ch = &gpadc->chans[i]; > + iio_chan = &gpadc->iio_chans[i]; > + > + ret = ab8500_gpadc_parse_channel(gpadc->dev, child, ch, iio_chan); > + if (ret) { > + of_node_put(child); > + return ret; > + } > + i++; > + } > + > + return 0; > +} > + > static int ab8500_gpadc_probe(struct platform_device *pdev) > { > int ret = 0; > struct ab8500_gpadc *gpadc; > + struct iio_dev *indio_dev; > + struct device *dev = &pdev->dev; > + struct device_node *np = pdev->dev.of_node; > > - gpadc = devm_kzalloc(&pdev->dev, > - sizeof(struct ab8500_gpadc), GFP_KERNEL); > - if (!gpadc) > + indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc)); > + if (!indio_dev) > return -ENOMEM; > + platform_set_drvdata(pdev, indio_dev); > + gpadc = iio_priv(indio_dev); > + > + gpadc->dev = dev; > + gpadc->ab8500 = dev_get_drvdata(pdev->dev.parent); > + mutex_init(&gpadc->ab8500_gpadc_lock); > + > + ret = ab8500_gpadc_parse_channels(gpadc, np); > > gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END"); > - if (gpadc->irq_sw < 0) > - dev_err(gpadc->dev, "failed to get platform sw_conv_end irq\n"); > + if (gpadc->irq_sw < 0) { > + dev_err(dev, "failed to get platform sw_conv_end irq\n"); > + return gpadc->irq_sw; > + } > > gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END"); > - if (gpadc->irq_hw < 0) > - dev_err(gpadc->dev, "failed to get platform hw_conv_end irq\n"); > - > - gpadc->dev = &pdev->dev; > - gpadc->parent = dev_get_drvdata(pdev->dev.parent); > - mutex_init(&gpadc->ab8500_gpadc_lock); > + if (gpadc->irq_hw < 0) { > + dev_err(dev, "failed to get platform hw_conv_end irq\n"); > + return gpadc->irq_hw; > + } > > /* Initialize completion used to notify completion of conversion */ > init_completion(&gpadc->ab8500_gpadc_complete); > > /* Register interrupts */ > - if (gpadc->irq_sw >= 0) { > - ret = request_threaded_irq(gpadc->irq_sw, NULL, > - ab8500_bm_gpadcconvend_handler, > - IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, > - "ab8500-gpadc-sw", > - gpadc); > - if (ret < 0) { > - dev_err(gpadc->dev, > - "Failed to register interrupt irq: %d\n", > - gpadc->irq_sw); > - goto fail; > - } > + ret = devm_request_threaded_irq(dev, > + gpadc->irq_sw, NULL, > + ab8500_bm_gpadcconvend_handler, > + IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, > + "ab8500-gpadc-sw", > + gpadc); > + if (ret < 0) { > + dev_err(dev, > + "failed to request interrupt irq %d\n", > + gpadc->irq_sw); > + return ret; > } > > - if (gpadc->irq_hw >= 0) { > - ret = request_threaded_irq(gpadc->irq_hw, NULL, > - ab8500_bm_gpadcconvend_handler, > - IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, > - "ab8500-gpadc-hw", > - gpadc); > - if (ret < 0) { > - dev_err(gpadc->dev, > - "Failed to register interrupt irq: %d\n", > - gpadc->irq_hw); > - goto fail_irq; > - } > + ret = devm_request_threaded_irq(dev, > + gpadc->irq_hw, NULL, > + ab8500_bm_gpadcconvend_handler, > + IRQF_NO_SUSPEND | IRQF_SHARED | IRQF_ONESHOT, > + "ab8500-gpadc-hw", > + gpadc); > + if (ret < 0) { > + dev_err(dev, > + "Failed to register interrupt irq: %d\n", > + gpadc->irq_hw); > + return ret; > } > > - /* VTVout LDO used to power up ab8500-GPADC */ > - gpadc->regu = devm_regulator_get(&pdev->dev, "vddadc"); > + /* The VTVout LDO used to power the AB8500 GPADC */ > + gpadc->regu = devm_regulator_get(dev, "vddadc"); > if (IS_ERR(gpadc->regu)) { > ret = PTR_ERR(gpadc->regu); > - dev_err(gpadc->dev, "failed to get vtvout LDO\n"); > - goto fail_irq; > + dev_err(dev, "failed to get vtvout LDO\n"); > + return ret; > } > > - platform_set_drvdata(pdev, gpadc); > - > ret = regulator_enable(gpadc->regu); > if (ret) { > - dev_err(gpadc->dev, "Failed to enable vtvout LDO: %d\n", ret); > - goto fail_enable; > + dev_err(dev, "failed to enable vtvout LDO: %d\n", ret); > + return ret; > } > > - pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY); > - pm_runtime_use_autosuspend(gpadc->dev); > - pm_runtime_set_active(gpadc->dev); > - pm_runtime_enable(gpadc->dev); > + pm_runtime_set_autosuspend_delay(dev, GPADC_AUDOSUSPEND_DELAY); > + pm_runtime_use_autosuspend(dev); > + pm_runtime_set_active(dev); > + pm_runtime_enable(dev); > > ab8500_gpadc_read_calibration_data(gpadc); > - list_add_tail(&gpadc->node, &ab8500_gpadc_list); > - dev_dbg(gpadc->dev, "probe success\n"); > + > + indio_dev->dev.parent = dev; > + indio_dev->dev.of_node = np; > + indio_dev->name = "ab8500-gpadc"; > + indio_dev->modes = INDIO_DIRECT_MODE; > + indio_dev->info = &ab8500_gpadc_info; > + indio_dev->channels = gpadc->iio_chans; > + indio_dev->num_channels = gpadc->nchans; > + > + ret = iio_device_register(indio_dev); > + if (ret) > + goto out_dis_pm; > + > + dev_info(dev, "AB8500 GPADC initialized\n"); > > return 0; > > -fail_enable: > -fail_irq: > - free_irq(gpadc->irq_sw, gpadc); > - free_irq(gpadc->irq_hw, gpadc); > -fail: > +out_dis_pm: > + pm_runtime_get_sync(dev); > + pm_runtime_disable(dev); > + regulator_disable(gpadc->regu); > + pm_runtime_set_suspended(dev); > + pm_runtime_put_noidle(dev); > + > return ret; > } > > static int ab8500_gpadc_remove(struct platform_device *pdev) > { > - struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev); > + struct iio_dev *indio_dev = platform_get_drvdata(pdev); > + struct ab8500_gpadc *gpadc = iio_priv(indio_dev); > > - /* remove this gpadc entry from the list */ > - list_del(&gpadc->node); > - /* remove interrupt - completion of Sw ADC conversion */ > - if (gpadc->irq_sw >= 0) > - free_irq(gpadc->irq_sw, gpadc); > - if (gpadc->irq_hw >= 0) > - free_irq(gpadc->irq_hw, gpadc); > + iio_device_unregister(indio_dev); > > pm_runtime_get_sync(gpadc->dev); > pm_runtime_disable(gpadc->dev); > - > regulator_disable(gpadc->regu); > - > pm_runtime_set_suspended(gpadc->dev); > - > pm_runtime_put_noidle(gpadc->dev); > > return 0; > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > index 4ce3b6f11830..d64a2447c963 100644 > --- a/drivers/mfd/Kconfig > +++ b/drivers/mfd/Kconfig > @@ -1022,13 +1022,6 @@ config AB8500_DEBUG > Select this option if you want debug information using the debug > filesystem, debugfs. > > -config AB8500_GPADC > - bool "ST-Ericsson AB8500 GPADC driver" > - depends on AB8500_CORE && REGULATOR_AB8500 > - default y > - help > - AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage > - > config MFD_DB8500_PRCMU > bool "ST-Ericsson DB8500 Power Reset Control Management Unit" > depends on UX500_SOC_DB8500 > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index dda4d4f73ad7..9870e2b1777a 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -150,7 +150,6 @@ obj-$(CONFIG_ABX500_CORE) += abx500-core.o > obj-$(CONFIG_AB3100_CORE) += ab3100-core.o > obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o > obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o > -obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o > obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o > # ab8500-core need to come after db8500-prcmu (which provides the channel) > obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o > diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c > index c1c815241e02..cdb6cdc1002b 100644 > --- a/drivers/mfd/ab8500-debugfs.c > +++ b/drivers/mfd/ab8500-debugfs.c > @@ -84,7 +84,6 @@ > > #include <linux/mfd/abx500.h> > #include <linux/mfd/abx500/ab8500.h> > -#include <linux/mfd/abx500/ab8500-gpadc.h> > > #ifdef CONFIG_DEBUG_FS > #include <linux/string.h> > @@ -103,11 +102,6 @@ static int num_irqs; > static struct device_attribute **dev_attr; > static char **event_name; > > -static u8 avg_sample = SAMPLE_16; > -static u8 trig_edge = RISING_EDGE; > -static u8 conv_type = ADC_SW; > -static u8 trig_timer; > - > /** > * struct ab8500_reg_range > * @first: the first address of the range > @@ -152,7 +146,6 @@ static struct hwreg_cfg hwreg_cfg = { > }; > > #define AB8500_NAME_STRING "ab8500" > -#define AB8500_ADC_NAME_STRING "gpadc" > #define AB8500_NUM_BANKS AB8500_DEBUG_FIELD_LAST > > #define AB8500_REV_REG 0x80 > @@ -1670,1130 +1663,242 @@ static const struct file_operations ab8500_modem_fops = { > .owner = THIS_MODULE, > }; > > -static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p) > +/* > + * return length of an ASCII numerical value, 0 is string is not a > + * numerical value. > + * string shall start at value 1st char. > + * string can be tailed with \0 or space or newline chars only. > + * value can be decimal or hexadecimal (prefixed 0x or 0X). > + */ > +static int strval_len(char *b) > { > - int bat_ctrl_raw; > - int bat_ctrl_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - bat_ctrl_raw = ab8500_gpadc_read_raw(gpadc, BAT_CTRL, > - avg_sample, trig_edge, trig_timer, conv_type); > - bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, > - BAT_CTRL, bat_ctrl_raw); > - > - seq_printf(s, "%d,0x%X\n", bat_ctrl_convert, bat_ctrl_raw); > + char *s = b; > > - return 0; > + if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) { > + s += 2; > + for (; *s && (*s != ' ') && (*s != '\n'); s++) { > + if (!isxdigit(*s)) > + return 0; > + } > + } else { > + if (*s == '-') > + s++; > + for (; *s && (*s != ' ') && (*s != '\n'); s++) { > + if (!isdigit(*s)) > + return 0; > + } > + } > + return (int) (s-b); > } > > -static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file) > +/* > + * parse hwreg input data. > + * update global hwreg_cfg only if input data syntax is ok. > + */ > +static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg, > + struct device *dev) > { > - return single_open(file, ab8500_gpadc_bat_ctrl_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_bat_ctrl_fops = { > - .open = ab8500_gpadc_bat_ctrl_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > + uint write, val = 0; > + u8 regvalue; > + int ret; > + struct hwreg_cfg loc = { > + .bank = 0, /* default: invalid phys addr */ > + .addr = 0, /* default: invalid phys addr */ > + .fmt = 0, /* default: 32bit access, hex output */ > + .mask = 0xFFFFFFFF, /* default: no mask */ > + .shift = 0, /* default: no bit shift */ > + }; > > -static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p) > -{ > - int btemp_ball_raw; > - int btemp_ball_convert; > - struct ab8500_gpadc *gpadc; > + /* read or write ? */ > + if (!strncmp(b, "read ", 5)) { > + write = 0; > + b += 5; > + } else if (!strncmp(b, "write ", 6)) { > + write = 1; > + b += 6; > + } else > + return -EINVAL; > > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - btemp_ball_raw = ab8500_gpadc_read_raw(gpadc, BTEMP_BALL, > - avg_sample, trig_edge, trig_timer, conv_type); > - btemp_ball_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, > - btemp_ball_raw); > + /* OPTIONS -l|-w|-b -s -m -o */ > + while ((*b == ' ') || (*b == '-')) { > + if (*(b-1) != ' ') { > + b++; > + continue; > + } > + if ((!strncmp(b, "-d ", 3)) || > + (!strncmp(b, "-dec ", 5))) { > + b += (*(b+2) == ' ') ? 3 : 5; > + loc.fmt |= (1<<0); > + } else if ((!strncmp(b, "-h ", 3)) || > + (!strncmp(b, "-hex ", 5))) { > + b += (*(b+2) == ' ') ? 3 : 5; > + loc.fmt &= ~(1<<0); > + } else if ((!strncmp(b, "-m ", 3)) || > + (!strncmp(b, "-mask ", 6))) { > + b += (*(b+2) == ' ') ? 3 : 6; > + if (strval_len(b) == 0) > + return -EINVAL; > + ret = kstrtoul(b, 0, &loc.mask); > + if (ret) > + return ret; > + } else if ((!strncmp(b, "-s ", 3)) || > + (!strncmp(b, "-shift ", 7))) { > + b += (*(b+2) == ' ') ? 3 : 7; > + if (strval_len(b) == 0) > + return -EINVAL; > + ret = kstrtol(b, 0, &loc.shift); > + if (ret) > + return ret; > + } else { > + return -EINVAL; > + } > + } > + /* get arg BANK and ADDRESS */ > + if (strval_len(b) == 0) > + return -EINVAL; > + ret = kstrtouint(b, 0, &loc.bank); > + if (ret) > + return ret; > + while (*b == ' ') > + b++; > + if (strval_len(b) == 0) > + return -EINVAL; > + ret = kstrtoul(b, 0, &loc.addr); > + if (ret) > + return ret; > > - seq_printf(s, "%d,0x%X\n", btemp_ball_convert, btemp_ball_raw); > + if (write) { > + while (*b == ' ') > + b++; > + if (strval_len(b) == 0) > + return -EINVAL; > + ret = kstrtouint(b, 0, &val); > + if (ret) > + return ret; > + } > > - return 0; > -} > + /* args are ok, update target cfg (mainly for read) */ > + *cfg = loc; > > -static int ab8500_gpadc_btemp_ball_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8500_gpadc_btemp_ball_print, > - inode->i_private); > -} > +#ifdef ABB_HWREG_DEBUG > + pr_warn("HWREG request: %s, %s,\n", (write) ? "write" : "read", > + REG_FMT_DEC(cfg) ? "decimal" : "hexa"); > + pr_warn(" addr=0x%08X, mask=0x%X, shift=%d" "value=0x%X\n", > + cfg->addr, cfg->mask, cfg->shift, val); > +#endif > > -static const struct file_operations ab8500_gpadc_btemp_ball_fops = { > - .open = ab8500_gpadc_btemp_ball_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > + if (!write) > + return 0; > > -static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p) > -{ > - int main_charger_v_raw; > - int main_charger_v_convert; > - struct ab8500_gpadc *gpadc; > + ret = abx500_get_register_interruptible(dev, > + (u8)cfg->bank, (u8)cfg->addr, ®value); > + if (ret < 0) { > + dev_err(dev, "abx500_get_reg fail %d, %d\n", > + ret, __LINE__); > + return -EINVAL; > + } > > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - main_charger_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_V, > - avg_sample, trig_edge, trig_timer, conv_type); > - main_charger_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, > - MAIN_CHARGER_V, main_charger_v_raw); > + if (cfg->shift >= 0) { > + regvalue &= ~(cfg->mask << (cfg->shift)); > + val = (val & cfg->mask) << (cfg->shift); > + } else { > + regvalue &= ~(cfg->mask >> (-cfg->shift)); > + val = (val & cfg->mask) >> (-cfg->shift); > + } > + val = val | regvalue; > > - seq_printf(s, "%d,0x%X\n", main_charger_v_convert, main_charger_v_raw); > + ret = abx500_set_register_interruptible(dev, > + (u8)cfg->bank, (u8)cfg->addr, (u8)val); > + if (ret < 0) { > + pr_err("abx500_set_reg failed %d, %d", ret, __LINE__); > + return -EINVAL; > + } > > return 0; > } > > -static int ab8500_gpadc_main_charger_v_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8500_gpadc_main_charger_v_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_main_charger_v_fops = { > - .open = ab8500_gpadc_main_charger_v_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p) > +static ssize_t ab8500_hwreg_write(struct file *file, > + const char __user *user_buf, size_t count, loff_t *ppos) > { > - int acc_detect1_raw; > - int acc_detect1_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - acc_detect1_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT1, > - avg_sample, trig_edge, trig_timer, conv_type); > - acc_detect1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ACC_DETECT1, > - acc_detect1_raw); > - > - seq_printf(s, "%d,0x%X\n", acc_detect1_convert, acc_detect1_raw); > + struct device *dev = ((struct seq_file *)(file->private_data))->private; > + char buf[128]; > + int buf_size, ret; > > - return 0; > -} > + /* Get userspace string and assure termination */ > + buf_size = min(count, (sizeof(buf)-1)); > + if (copy_from_user(buf, user_buf, buf_size)) > + return -EFAULT; > + buf[buf_size] = 0; > > -static int ab8500_gpadc_acc_detect1_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8500_gpadc_acc_detect1_print, > - inode->i_private); > + /* get args and process */ > + ret = hwreg_common_write(buf, &hwreg_cfg, dev); > + return (ret) ? ret : buf_size; > } > > -static const struct file_operations ab8500_gpadc_acc_detect1_fops = { > - .open = ab8500_gpadc_acc_detect1_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p) > +/* > + * - irq subscribe/unsubscribe stuff > + */ > +static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p) > { > - int acc_detect2_raw; > - int acc_detect2_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - acc_detect2_raw = ab8500_gpadc_read_raw(gpadc, ACC_DETECT2, > - avg_sample, trig_edge, trig_timer, conv_type); > - acc_detect2_convert = ab8500_gpadc_ad_to_voltage(gpadc, > - ACC_DETECT2, acc_detect2_raw); > - > - seq_printf(s, "%d,0x%X\n", acc_detect2_convert, acc_detect2_raw); > + seq_printf(s, "%d\n", irq_first); > > return 0; > } > > -static int ab8500_gpadc_acc_detect2_open(struct inode *inode, > - struct file *file) > +static int ab8500_subscribe_unsubscribe_open(struct inode *inode, > + struct file *file) > { > - return single_open(file, ab8500_gpadc_acc_detect2_print, > + return single_open(file, ab8500_subscribe_unsubscribe_print, > inode->i_private); > } > > -static const struct file_operations ab8500_gpadc_acc_detect2_fops = { > - .open = ab8500_gpadc_acc_detect2_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p) > +/* > + * Userspace should use poll() on this file. When an event occur > + * the blocking poll will be released. > + */ > +static ssize_t show_irq(struct device *dev, > + struct device_attribute *attr, char *buf) > { > - int aux1_raw; > - int aux1_convert; > - struct ab8500_gpadc *gpadc; > + unsigned long name; > + unsigned int irq_index; > + int err; > > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - aux1_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX1, > - avg_sample, trig_edge, trig_timer, conv_type); > - aux1_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX1, > - aux1_raw); > + err = kstrtoul(attr->attr.name, 0, &name); > + if (err) > + return err; > > - seq_printf(s, "%d,0x%X\n", aux1_convert, aux1_raw); > + irq_index = name - irq_first; > + if (irq_index >= num_irqs) > + return -EINVAL; > > - return 0; > + return sprintf(buf, "%u\n", irq_count[irq_index]); > } > > -static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file) > +static ssize_t ab8500_subscribe_write(struct file *file, > + const char __user *user_buf, > + size_t count, loff_t *ppos) > { > - return single_open(file, ab8500_gpadc_aux1_print, inode->i_private); > -} > + struct device *dev = ((struct seq_file *)(file->private_data))->private; > + unsigned long user_val; > + int err; > + unsigned int irq_index; > > -static const struct file_operations ab8500_gpadc_aux1_fops = { > - .open = ab8500_gpadc_aux1_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > + err = kstrtoul_from_user(user_buf, count, 0, &user_val); > + if (err) > + return err; > > -static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p) > -{ > - int aux2_raw; > - int aux2_convert; > - struct ab8500_gpadc *gpadc; > + if (user_val < irq_first) { > + dev_err(dev, "debugfs error input < %d\n", irq_first); > + return -EINVAL; > + } > + if (user_val > irq_last) { > + dev_err(dev, "debugfs error input > %d\n", irq_last); > + return -EINVAL; > + } > > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - aux2_raw = ab8500_gpadc_read_raw(gpadc, ADC_AUX2, > - avg_sample, trig_edge, trig_timer, conv_type); > - aux2_convert = ab8500_gpadc_ad_to_voltage(gpadc, ADC_AUX2, > - aux2_raw); > - > - seq_printf(s, "%d,0x%X\n", aux2_convert, aux2_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_aux2_print, inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_aux2_fops = { > - .open = ab8500_gpadc_aux2_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p) > -{ > - int main_bat_v_raw; > - int main_bat_v_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - main_bat_v_raw = ab8500_gpadc_read_raw(gpadc, MAIN_BAT_V, > - avg_sample, trig_edge, trig_timer, conv_type); > - main_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, > - main_bat_v_raw); > - > - seq_printf(s, "%d,0x%X\n", main_bat_v_convert, main_bat_v_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_main_bat_v_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8500_gpadc_main_bat_v_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_main_bat_v_fops = { > - .open = ab8500_gpadc_main_bat_v_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p) > -{ > - int vbus_v_raw; > - int vbus_v_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - vbus_v_raw = ab8500_gpadc_read_raw(gpadc, VBUS_V, > - avg_sample, trig_edge, trig_timer, conv_type); > - vbus_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, VBUS_V, > - vbus_v_raw); > - > - seq_printf(s, "%d,0x%X\n", vbus_v_convert, vbus_v_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_vbus_v_fops = { > - .open = ab8500_gpadc_vbus_v_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p) > -{ > - int main_charger_c_raw; > - int main_charger_c_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - main_charger_c_raw = ab8500_gpadc_read_raw(gpadc, MAIN_CHARGER_C, > - avg_sample, trig_edge, trig_timer, conv_type); > - main_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, > - MAIN_CHARGER_C, main_charger_c_raw); > - > - seq_printf(s, "%d,0x%X\n", main_charger_c_convert, main_charger_c_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_main_charger_c_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8500_gpadc_main_charger_c_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_main_charger_c_fops = { > - .open = ab8500_gpadc_main_charger_c_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p) > -{ > - int usb_charger_c_raw; > - int usb_charger_c_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - usb_charger_c_raw = ab8500_gpadc_read_raw(gpadc, USB_CHARGER_C, > - avg_sample, trig_edge, trig_timer, conv_type); > - usb_charger_c_convert = ab8500_gpadc_ad_to_voltage(gpadc, > - USB_CHARGER_C, usb_charger_c_raw); > - > - seq_printf(s, "%d,0x%X\n", usb_charger_c_convert, usb_charger_c_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_usb_charger_c_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8500_gpadc_usb_charger_c_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_usb_charger_c_fops = { > - .open = ab8500_gpadc_usb_charger_c_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p) > -{ > - int bk_bat_v_raw; > - int bk_bat_v_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - bk_bat_v_raw = ab8500_gpadc_read_raw(gpadc, BK_BAT_V, > - avg_sample, trig_edge, trig_timer, conv_type); > - bk_bat_v_convert = ab8500_gpadc_ad_to_voltage(gpadc, > - BK_BAT_V, bk_bat_v_raw); > - > - seq_printf(s, "%d,0x%X\n", bk_bat_v_convert, bk_bat_v_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_bk_bat_v_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_bk_bat_v_fops = { > - .open = ab8500_gpadc_bk_bat_v_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p) > -{ > - int die_temp_raw; > - int die_temp_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - die_temp_raw = ab8500_gpadc_read_raw(gpadc, DIE_TEMP, > - avg_sample, trig_edge, trig_timer, conv_type); > - die_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, DIE_TEMP, > - die_temp_raw); > - > - seq_printf(s, "%d,0x%X\n", die_temp_convert, die_temp_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_die_temp_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_die_temp_fops = { > - .open = ab8500_gpadc_die_temp_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_usb_id_print(struct seq_file *s, void *p) > -{ > - int usb_id_raw; > - int usb_id_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - usb_id_raw = ab8500_gpadc_read_raw(gpadc, USB_ID, > - avg_sample, trig_edge, trig_timer, conv_type); > - usb_id_convert = ab8500_gpadc_ad_to_voltage(gpadc, USB_ID, > - usb_id_raw); > - > - seq_printf(s, "%d,0x%X\n", usb_id_convert, usb_id_raw); > - > - return 0; > -} > - > -static int ab8500_gpadc_usb_id_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_usb_id_print, inode->i_private); > -} > - > -static const struct file_operations ab8500_gpadc_usb_id_fops = { > - .open = ab8500_gpadc_usb_id_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8540_gpadc_xtal_temp_print(struct seq_file *s, void *p) > -{ > - int xtal_temp_raw; > - int xtal_temp_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - xtal_temp_raw = ab8500_gpadc_read_raw(gpadc, XTAL_TEMP, > - avg_sample, trig_edge, trig_timer, conv_type); > - xtal_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, XTAL_TEMP, > - xtal_temp_raw); > - > - seq_printf(s, "%d,0x%X\n", xtal_temp_convert, xtal_temp_raw); > - > - return 0; > -} > - > -static int ab8540_gpadc_xtal_temp_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8540_gpadc_xtal_temp_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8540_gpadc_xtal_temp_fops = { > - .open = ab8540_gpadc_xtal_temp_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p) > -{ > - int vbat_true_meas_raw; > - int vbat_true_meas_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - vbat_true_meas_raw = ab8500_gpadc_read_raw(gpadc, VBAT_TRUE_MEAS, > - avg_sample, trig_edge, trig_timer, conv_type); > - vbat_true_meas_convert = > - ab8500_gpadc_ad_to_voltage(gpadc, VBAT_TRUE_MEAS, > - vbat_true_meas_raw); > - > - seq_printf(s, "%d,0x%X\n", vbat_true_meas_convert, vbat_true_meas_raw); > - > - return 0; > -} > - > -static int ab8540_gpadc_vbat_true_meas_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8540_gpadc_vbat_true_meas_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8540_gpadc_vbat_true_meas_fops = { > - .open = ab8540_gpadc_vbat_true_meas_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8540_gpadc_bat_ctrl_and_ibat_print(struct seq_file *s, void *p) > -{ > - int bat_ctrl_raw; > - int bat_ctrl_convert; > - int ibat_raw; > - int ibat_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - bat_ctrl_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_CTRL_AND_IBAT, > - avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); > - > - bat_ctrl_convert = ab8500_gpadc_ad_to_voltage(gpadc, BAT_CTRL, > - bat_ctrl_raw); > - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, > - ibat_raw); > - > - seq_printf(s, > - "%d,0x%X\n" > - "%d,0x%X\n", > - bat_ctrl_convert, bat_ctrl_raw, > - ibat_convert, ibat_raw); > - > - return 0; > -} > - > -static int ab8540_gpadc_bat_ctrl_and_ibat_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8540_gpadc_bat_ctrl_and_ibat_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8540_gpadc_bat_ctrl_and_ibat_fops = { > - .open = ab8540_gpadc_bat_ctrl_and_ibat_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8540_gpadc_vbat_meas_and_ibat_print(struct seq_file *s, void *p) > -{ > - int vbat_meas_raw; > - int vbat_meas_convert; > - int ibat_raw; > - int ibat_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - vbat_meas_raw = ab8500_gpadc_double_read_raw(gpadc, VBAT_MEAS_AND_IBAT, > - avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); > - vbat_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, MAIN_BAT_V, > - vbat_meas_raw); > - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, > - ibat_raw); > - > - seq_printf(s, > - "%d,0x%X\n" > - "%d,0x%X\n", > - vbat_meas_convert, vbat_meas_raw, > - ibat_convert, ibat_raw); > - > - return 0; > -} > - > -static int ab8540_gpadc_vbat_meas_and_ibat_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8540_gpadc_vbat_meas_and_ibat_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = { > - .open = ab8540_gpadc_vbat_meas_and_ibat_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s, > - void *p) > -{ > - int vbat_true_meas_raw; > - int vbat_true_meas_convert; > - int ibat_raw; > - int ibat_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - vbat_true_meas_raw = ab8500_gpadc_double_read_raw(gpadc, > - VBAT_TRUE_MEAS_AND_IBAT, avg_sample, trig_edge, > - trig_timer, conv_type, &ibat_raw); > - vbat_true_meas_convert = ab8500_gpadc_ad_to_voltage(gpadc, > - VBAT_TRUE_MEAS, vbat_true_meas_raw); > - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, > - ibat_raw); > - > - seq_printf(s, > - "%d,0x%X\n" > - "%d,0x%X\n", > - vbat_true_meas_convert, vbat_true_meas_raw, > - ibat_convert, ibat_raw); > - > - return 0; > -} > - > -static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8540_gpadc_vbat_true_meas_and_ibat_print, > - inode->i_private); > -} > - > -static const struct file_operations > -ab8540_gpadc_vbat_true_meas_and_ibat_fops = { > - .open = ab8540_gpadc_vbat_true_meas_and_ibat_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8540_gpadc_bat_temp_and_ibat_print(struct seq_file *s, void *p) > -{ > - int bat_temp_raw; > - int bat_temp_convert; > - int ibat_raw; > - int ibat_convert; > - struct ab8500_gpadc *gpadc; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - bat_temp_raw = ab8500_gpadc_double_read_raw(gpadc, BAT_TEMP_AND_IBAT, > - avg_sample, trig_edge, trig_timer, conv_type, &ibat_raw); > - bat_temp_convert = ab8500_gpadc_ad_to_voltage(gpadc, BTEMP_BALL, > - bat_temp_raw); > - ibat_convert = ab8500_gpadc_ad_to_voltage(gpadc, IBAT_VIRTUAL_CHANNEL, > - ibat_raw); > - > - seq_printf(s, > - "%d,0x%X\n" > - "%d,0x%X\n", > - bat_temp_convert, bat_temp_raw, > - ibat_convert, ibat_raw); > - > - return 0; > -} > - > -static int ab8540_gpadc_bat_temp_and_ibat_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8540_gpadc_bat_temp_and_ibat_print, > - inode->i_private); > -} > - > -static const struct file_operations ab8540_gpadc_bat_temp_and_ibat_fops = { > - .open = ab8540_gpadc_bat_temp_and_ibat_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p) > -{ > - struct ab8500_gpadc *gpadc; > - u16 vmain_l, vmain_h, btemp_l, btemp_h; > - u16 vbat_l, vbat_h, ibat_l, ibat_h; > - > - gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); > - ab8540_gpadc_get_otp(gpadc, &vmain_l, &vmain_h, &btemp_l, &btemp_h, > - &vbat_l, &vbat_h, &ibat_l, &ibat_h); > - seq_printf(s, > - "VMAIN_L:0x%X\n" > - "VMAIN_H:0x%X\n" > - "BTEMP_L:0x%X\n" > - "BTEMP_H:0x%X\n" > - "VBAT_L:0x%X\n" > - "VBAT_H:0x%X\n" > - "IBAT_L:0x%X\n" > - "IBAT_H:0x%X\n", > - vmain_l, vmain_h, btemp_l, btemp_h, > - vbat_l, vbat_h, ibat_l, ibat_h); > - > - return 0; > -} > - > -static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8540_gpadc_otp_cal_print, inode->i_private); > -} > - > -static const struct file_operations ab8540_gpadc_otp_calib_fops = { > - .open = ab8540_gpadc_otp_cal_open, > - .read = seq_read, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p) > -{ > - seq_printf(s, "%d\n", avg_sample); > - > - return 0; > -} > - > -static int ab8500_gpadc_avg_sample_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_avg_sample_print, > - inode->i_private); > -} > - > -static ssize_t ab8500_gpadc_avg_sample_write(struct file *file, > - const char __user *user_buf, > - size_t count, loff_t *ppos) > -{ > - struct device *dev = ((struct seq_file *)(file->private_data))->private; > - unsigned long user_avg_sample; > - int err; > - > - err = kstrtoul_from_user(user_buf, count, 0, &user_avg_sample); > - if (err) > - return err; > - > - if ((user_avg_sample == SAMPLE_1) || (user_avg_sample == SAMPLE_4) > - || (user_avg_sample == SAMPLE_8) > - || (user_avg_sample == SAMPLE_16)) { > - avg_sample = (u8) user_avg_sample; > - } else { > - dev_err(dev, > - "debugfs err input: should be egal to 1, 4, 8 or 16\n"); > - return -EINVAL; > - } > - > - return count; > -} > - > -static const struct file_operations ab8500_gpadc_avg_sample_fops = { > - .open = ab8500_gpadc_avg_sample_open, > - .read = seq_read, > - .write = ab8500_gpadc_avg_sample_write, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_trig_edge_print(struct seq_file *s, void *p) > -{ > - seq_printf(s, "%d\n", trig_edge); > - > - return 0; > -} > - > -static int ab8500_gpadc_trig_edge_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_trig_edge_print, > - inode->i_private); > -} > - > -static ssize_t ab8500_gpadc_trig_edge_write(struct file *file, > - const char __user *user_buf, > - size_t count, loff_t *ppos) > -{ > - struct device *dev = ((struct seq_file *)(file->private_data))->private; > - unsigned long user_trig_edge; > - int err; > - > - err = kstrtoul_from_user(user_buf, count, 0, &user_trig_edge); > - if (err) > - return err; > - > - if ((user_trig_edge == RISING_EDGE) > - || (user_trig_edge == FALLING_EDGE)) { > - trig_edge = (u8) user_trig_edge; > - } else { > - dev_err(dev, "Wrong input:\n" > - "Enter 0. Rising edge\n" > - "Enter 1. Falling edge\n"); > - return -EINVAL; > - } > - > - return count; > -} > - > -static const struct file_operations ab8500_gpadc_trig_edge_fops = { > - .open = ab8500_gpadc_trig_edge_open, > - .read = seq_read, > - .write = ab8500_gpadc_trig_edge_write, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_trig_timer_print(struct seq_file *s, void *p) > -{ > - seq_printf(s, "%d\n", trig_timer); > - > - return 0; > -} > - > -static int ab8500_gpadc_trig_timer_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_trig_timer_print, > - inode->i_private); > -} > - > -static ssize_t ab8500_gpadc_trig_timer_write(struct file *file, > - const char __user *user_buf, > - size_t count, loff_t *ppos) > -{ > - struct device *dev = ((struct seq_file *)(file->private_data))->private; > - unsigned long user_trig_timer; > - int err; > - > - err = kstrtoul_from_user(user_buf, count, 0, &user_trig_timer); > - if (err) > - return err; > - > - if (user_trig_timer & ~0xFF) { > - dev_err(dev, > - "debugfs error input: should be between 0 to 255\n"); > - return -EINVAL; > - } > - > - trig_timer = (u8) user_trig_timer; > - > - return count; > -} > - > -static const struct file_operations ab8500_gpadc_trig_timer_fops = { > - .open = ab8500_gpadc_trig_timer_open, > - .read = seq_read, > - .write = ab8500_gpadc_trig_timer_write, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -static int ab8500_gpadc_conv_type_print(struct seq_file *s, void *p) > -{ > - seq_printf(s, "%d\n", conv_type); > - > - return 0; > -} > - > -static int ab8500_gpadc_conv_type_open(struct inode *inode, struct file *file) > -{ > - return single_open(file, ab8500_gpadc_conv_type_print, > - inode->i_private); > -} > - > -static ssize_t ab8500_gpadc_conv_type_write(struct file *file, > - const char __user *user_buf, > - size_t count, loff_t *ppos) > -{ > - struct device *dev = ((struct seq_file *)(file->private_data))->private; > - unsigned long user_conv_type; > - int err; > - > - err = kstrtoul_from_user(user_buf, count, 0, &user_conv_type); > - if (err) > - return err; > - > - if ((user_conv_type == ADC_SW) > - || (user_conv_type == ADC_HW)) { > - conv_type = (u8) user_conv_type; > - } else { > - dev_err(dev, "Wrong input:\n" > - "Enter 0. ADC SW conversion\n" > - "Enter 1. ADC HW conversion\n"); > - return -EINVAL; > - } > - > - return count; > -} > - > -static const struct file_operations ab8500_gpadc_conv_type_fops = { > - .open = ab8500_gpadc_conv_type_open, > - .read = seq_read, > - .write = ab8500_gpadc_conv_type_write, > - .llseek = seq_lseek, > - .release = single_release, > - .owner = THIS_MODULE, > -}; > - > -/* > - * return length of an ASCII numerical value, 0 is string is not a > - * numerical value. > - * string shall start at value 1st char. > - * string can be tailed with \0 or space or newline chars only. > - * value can be decimal or hexadecimal (prefixed 0x or 0X). > - */ > -static int strval_len(char *b) > -{ > - char *s = b; > - > - if ((*s == '0') && ((*(s+1) == 'x') || (*(s+1) == 'X'))) { > - s += 2; > - for (; *s && (*s != ' ') && (*s != '\n'); s++) { > - if (!isxdigit(*s)) > - return 0; > - } > - } else { > - if (*s == '-') > - s++; > - for (; *s && (*s != ' ') && (*s != '\n'); s++) { > - if (!isdigit(*s)) > - return 0; > - } > - } > - return (int) (s-b); > -} > - > -/* > - * parse hwreg input data. > - * update global hwreg_cfg only if input data syntax is ok. > - */ > -static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg, > - struct device *dev) > -{ > - uint write, val = 0; > - u8 regvalue; > - int ret; > - struct hwreg_cfg loc = { > - .bank = 0, /* default: invalid phys addr */ > - .addr = 0, /* default: invalid phys addr */ > - .fmt = 0, /* default: 32bit access, hex output */ > - .mask = 0xFFFFFFFF, /* default: no mask */ > - .shift = 0, /* default: no bit shift */ > - }; > - > - /* read or write ? */ > - if (!strncmp(b, "read ", 5)) { > - write = 0; > - b += 5; > - } else if (!strncmp(b, "write ", 6)) { > - write = 1; > - b += 6; > - } else > - return -EINVAL; > - > - /* OPTIONS -l|-w|-b -s -m -o */ > - while ((*b == ' ') || (*b == '-')) { > - if (*(b-1) != ' ') { > - b++; > - continue; > - } > - if ((!strncmp(b, "-d ", 3)) || > - (!strncmp(b, "-dec ", 5))) { > - b += (*(b+2) == ' ') ? 3 : 5; > - loc.fmt |= (1<<0); > - } else if ((!strncmp(b, "-h ", 3)) || > - (!strncmp(b, "-hex ", 5))) { > - b += (*(b+2) == ' ') ? 3 : 5; > - loc.fmt &= ~(1<<0); > - } else if ((!strncmp(b, "-m ", 3)) || > - (!strncmp(b, "-mask ", 6))) { > - b += (*(b+2) == ' ') ? 3 : 6; > - if (strval_len(b) == 0) > - return -EINVAL; > - ret = kstrtoul(b, 0, &loc.mask); > - if (ret) > - return ret; > - } else if ((!strncmp(b, "-s ", 3)) || > - (!strncmp(b, "-shift ", 7))) { > - b += (*(b+2) == ' ') ? 3 : 7; > - if (strval_len(b) == 0) > - return -EINVAL; > - ret = kstrtol(b, 0, &loc.shift); > - if (ret) > - return ret; > - } else { > - return -EINVAL; > - } > - } > - /* get arg BANK and ADDRESS */ > - if (strval_len(b) == 0) > - return -EINVAL; > - ret = kstrtouint(b, 0, &loc.bank); > - if (ret) > - return ret; > - while (*b == ' ') > - b++; > - if (strval_len(b) == 0) > - return -EINVAL; > - ret = kstrtoul(b, 0, &loc.addr); > - if (ret) > - return ret; > - > - if (write) { > - while (*b == ' ') > - b++; > - if (strval_len(b) == 0) > - return -EINVAL; > - ret = kstrtouint(b, 0, &val); > - if (ret) > - return ret; > - } > - > - /* args are ok, update target cfg (mainly for read) */ > - *cfg = loc; > - > -#ifdef ABB_HWREG_DEBUG > - pr_warn("HWREG request: %s, %s,\n", (write) ? "write" : "read", > - REG_FMT_DEC(cfg) ? "decimal" : "hexa"); > - pr_warn(" addr=0x%08X, mask=0x%X, shift=%d" "value=0x%X\n", > - cfg->addr, cfg->mask, cfg->shift, val); > -#endif > - > - if (!write) > - return 0; > - > - ret = abx500_get_register_interruptible(dev, > - (u8)cfg->bank, (u8)cfg->addr, ®value); > - if (ret < 0) { > - dev_err(dev, "abx500_get_reg fail %d, %d\n", > - ret, __LINE__); > - return -EINVAL; > - } > - > - if (cfg->shift >= 0) { > - regvalue &= ~(cfg->mask << (cfg->shift)); > - val = (val & cfg->mask) << (cfg->shift); > - } else { > - regvalue &= ~(cfg->mask >> (-cfg->shift)); > - val = (val & cfg->mask) >> (-cfg->shift); > - } > - val = val | regvalue; > - > - ret = abx500_set_register_interruptible(dev, > - (u8)cfg->bank, (u8)cfg->addr, (u8)val); > - if (ret < 0) { > - pr_err("abx500_set_reg failed %d, %d", ret, __LINE__); > - return -EINVAL; > - } > - > - return 0; > -} > - > -static ssize_t ab8500_hwreg_write(struct file *file, > - const char __user *user_buf, size_t count, loff_t *ppos) > -{ > - struct device *dev = ((struct seq_file *)(file->private_data))->private; > - char buf[128]; > - int buf_size, ret; > - > - /* Get userspace string and assure termination */ > - buf_size = min(count, (sizeof(buf)-1)); > - if (copy_from_user(buf, user_buf, buf_size)) > - return -EFAULT; > - buf[buf_size] = 0; > - > - /* get args and process */ > - ret = hwreg_common_write(buf, &hwreg_cfg, dev); > - return (ret) ? ret : buf_size; > -} > - > -/* > - * - irq subscribe/unsubscribe stuff > - */ > -static int ab8500_subscribe_unsubscribe_print(struct seq_file *s, void *p) > -{ > - seq_printf(s, "%d\n", irq_first); > - > - return 0; > -} > - > -static int ab8500_subscribe_unsubscribe_open(struct inode *inode, > - struct file *file) > -{ > - return single_open(file, ab8500_subscribe_unsubscribe_print, > - inode->i_private); > -} > - > -/* > - * Userspace should use poll() on this file. When an event occur > - * the blocking poll will be released. > - */ > -static ssize_t show_irq(struct device *dev, > - struct device_attribute *attr, char *buf) > -{ > - unsigned long name; > - unsigned int irq_index; > - int err; > - > - err = kstrtoul(attr->attr.name, 0, &name); > - if (err) > - return err; > - > - irq_index = name - irq_first; > - if (irq_index >= num_irqs) > - return -EINVAL; > - > - return sprintf(buf, "%u\n", irq_count[irq_index]); > -} > - > -static ssize_t ab8500_subscribe_write(struct file *file, > - const char __user *user_buf, > - size_t count, loff_t *ppos) > -{ > - struct device *dev = ((struct seq_file *)(file->private_data))->private; > - unsigned long user_val; > - int err; > - unsigned int irq_index; > - > - err = kstrtoul_from_user(user_buf, count, 0, &user_val); > - if (err) > - return err; > - > - if (user_val < irq_first) { > - dev_err(dev, "debugfs error input < %d\n", irq_first); > - return -EINVAL; > - } > - if (user_val > irq_last) { > - dev_err(dev, "debugfs error input > %d\n", irq_last); > - return -EINVAL; > - } > - > - irq_index = user_val - irq_first; > - if (irq_index >= num_irqs) > - return -EINVAL; > + irq_index = user_val - irq_first; > + if (irq_index >= num_irqs) > + return -EINVAL; > > /* > * This will create a sysfs file named <irq-nr> which userspace can > @@ -2939,7 +2044,6 @@ static const struct file_operations ab8500_hwreg_fops = { > }; > > static struct dentry *ab8500_dir; > -static struct dentry *ab8500_gpadc_dir; > > static int ab8500_debug_probe(struct platform_device *plf) > { > @@ -2991,11 +2095,6 @@ static int ab8500_debug_probe(struct platform_device *plf) > if (!ab8500_dir) > goto err; > > - ab8500_gpadc_dir = debugfs_create_dir(AB8500_ADC_NAME_STRING, > - ab8500_dir); > - if (!ab8500_gpadc_dir) > - goto err; > - > file = debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir, > &plf->dev, &ab8500_registers_fops); > if (!file) > @@ -3066,165 +2165,6 @@ static int ab8500_debug_probe(struct platform_device *plf) > if (!file) > goto err; > > - file = debugfs_create_file("bat_ctrl", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_bat_ctrl_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("btemp_ball", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, > - &plf->dev, &ab8500_gpadc_btemp_ball_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("main_charger_v", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_main_charger_v_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("acc_detect1", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_acc_detect1_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("acc_detect2", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_acc_detect2_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("adc_aux1", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_aux1_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("adc_aux2", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_aux2_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("main_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_main_bat_v_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("vbus_v", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_vbus_v_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("main_charger_c", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_main_charger_c_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("usb_charger_c", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, > - &plf->dev, &ab8500_gpadc_usb_charger_c_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("bk_bat_v", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_bk_bat_v_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("die_temp", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_die_temp_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("usb_id", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_usb_id_fops); > - if (!file) > - goto err; > - > - if (is_ab8540(ab8500)) { > - file = debugfs_create_file("xtal_temp", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8540_gpadc_xtal_temp_fops); > - if (!file) > - goto err; > - file = debugfs_create_file("vbattruemeas", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8540_gpadc_vbat_true_meas_fops); > - if (!file) > - goto err; > - file = debugfs_create_file("batctrl_and_ibat", > - (S_IRUGO | S_IWUGO), > - ab8500_gpadc_dir, > - &plf->dev, > - &ab8540_gpadc_bat_ctrl_and_ibat_fops); > - if (!file) > - goto err; > - file = debugfs_create_file("vbatmeas_and_ibat", > - (S_IRUGO | S_IWUGO), > - ab8500_gpadc_dir, &plf->dev, > - &ab8540_gpadc_vbat_meas_and_ibat_fops); > - if (!file) > - goto err; > - file = debugfs_create_file("vbattruemeas_and_ibat", > - (S_IRUGO | S_IWUGO), > - ab8500_gpadc_dir, > - &plf->dev, > - &ab8540_gpadc_vbat_true_meas_and_ibat_fops); > - if (!file) > - goto err; > - file = debugfs_create_file("battemp_and_ibat", > - (S_IRUGO | S_IWUGO), > - ab8500_gpadc_dir, > - &plf->dev, &ab8540_gpadc_bat_temp_and_ibat_fops); > - if (!file) > - goto err; > - file = debugfs_create_file("otp_calib", > - (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, > - &plf->dev, &ab8540_gpadc_otp_calib_fops); > - if (!file) > - goto err; > - } > - file = debugfs_create_file("avg_sample", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_avg_sample_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("trig_edge", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_trig_edge_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("trig_timer", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_trig_timer_fops); > - if (!file) > - goto err; > - > - file = debugfs_create_file("conv_type", (S_IRUGO | S_IWUSR | S_IWGRP), > - ab8500_gpadc_dir, &plf->dev, > - &ab8500_gpadc_conv_type_fops); > - if (!file) > - goto err; > - > return 0; > > err: > diff --git a/include/linux/mfd/abx500/ab8500-gpadc.h b/include/linux/mfd/abx500/ab8500-gpadc.h > deleted file mode 100644 > index 49ded001049b..000000000000 > --- a/include/linux/mfd/abx500/ab8500-gpadc.h > +++ /dev/null > @@ -1,75 +0,0 @@ > -/* > - * Copyright (C) 2010 ST-Ericsson SA > - * Licensed under GPLv2. > - * > - * Author: Arun R Murthy <arun.murthy@xxxxxxxxxxxxxx> > - * Author: Daniel Willerud <daniel.willerud@xxxxxxxxxxxxxx> > - * Author: M'boumba Cedric Madianga <cedric.madianga@xxxxxxxxxxxxxx> > - */ > - > -#ifndef _AB8500_GPADC_H > -#define _AB8500_GPADC_H > - > -/* GPADC source: From datasheet(ADCSwSel[4:0] in GPADCCtrl2 > - * and ADCHwSel[4:0] in GPADCCtrl3 ) */ > -#define BAT_CTRL 0x01 > -#define BTEMP_BALL 0x02 > -#define MAIN_CHARGER_V 0x03 > -#define ACC_DETECT1 0x04 > -#define ACC_DETECT2 0x05 > -#define ADC_AUX1 0x06 > -#define ADC_AUX2 0x07 > -#define MAIN_BAT_V 0x08 > -#define VBUS_V 0x09 > -#define MAIN_CHARGER_C 0x0A > -#define USB_CHARGER_C 0x0B > -#define BK_BAT_V 0x0C > -#define DIE_TEMP 0x0D > -#define USB_ID 0x0E > -#define XTAL_TEMP 0x12 > -#define VBAT_TRUE_MEAS 0x13 > -#define BAT_CTRL_AND_IBAT 0x1C > -#define VBAT_MEAS_AND_IBAT 0x1D > -#define VBAT_TRUE_MEAS_AND_IBAT 0x1E > -#define BAT_TEMP_AND_IBAT 0x1F > - > -/* Virtual channel used only for ibat convertion to ampere > - * Battery current conversion (ibat) cannot be requested as a single conversion > - * but it is always in combination with other input requests > - */ > -#define IBAT_VIRTUAL_CHANNEL 0xFF > - > -#define SAMPLE_1 1 > -#define SAMPLE_4 4 > -#define SAMPLE_8 8 > -#define SAMPLE_16 16 > -#define RISING_EDGE 0 > -#define FALLING_EDGE 1 > - > -/* Arbitrary ADC conversion type constants */ > -#define ADC_SW 0 > -#define ADC_HW 1 > - > -struct ab8500_gpadc; > - > -struct ab8500_gpadc *ab8500_gpadc_get(char *name); > -int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel, > - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type); > -static inline int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel) > -{ > - return ab8500_gpadc_sw_hw_convert(gpadc, channel, > - SAMPLE_16, 0, 0, ADC_SW); > -} > - > -int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, > - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type); > -int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, > - u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type, > - int *ibat); > -int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, > - u8 channel, int ad_value); > -void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc, > - u16 *vmain_l, u16 *vmain_h, u16 *btemp_l, u16 *btemp_h, > - u16 *vbat_l, u16 *vbat_h, u16 *ibat_l, u16 *ibat_h); > - > -#endif /* _AB8500_GPADC_H */ -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html