text: // SPDX-License-Identifier: GPL-2.0-only
  /*
   * These are the two Sharp GP2AP002 variants supported by this driver:
   * GP2AP002A00F Ambient Light and Proximity Sensor
   * GP2AP002S00F Proximity Sensor
   *
   * Copyright (C) 2020 Linaro Ltd.
   * Author: Linus Walleij <linus.walleij@linaro.org>
   *
   * Based partly on the code in Sony Ericssons GP2AP00200F driver by
   * Courtney Cavin and Oskar Andero in drivers/input/misc/gp2ap002a00f.c
   * Based partly on a Samsung misc driver submitted by
   * Donggeun Kim & Minkyu Kang in 2011:
   * https://lore.kernel.org/lkml/1315556546-7445-1-git-send-email-dg77.kim@samsung.com/
   * Based partly on a submission by
   * Jonathan Bakker and Paweł Chmiel in january 2019:
   * https://lore.kernel.org/linux-input/20190125175045.22576-1-pawel.mikolaj.chmiel@gmail.com/
   * Based partly on code from the Samsung GT-S7710 by <mjchen@sta.samsung.com>
   * Based partly on the code in LG Electronics GP2AP00200F driver by
   * Kenobi Lee <sungyoung.lee@lge.com> and EunYoung Cho <ey.cho@lge.com>
   */
  #include <linux/module.h>
  #include <linux/i2c.h>
  #include <linux/regmap.h>
  #include <linux/iio/iio.h>
  #include <linux/iio/sysfs.h>
  #include <linux/iio/events.h>
  #include <linux/iio/consumer.h> /* To get our ADC channel */
  #include <linux/iio/types.h> /* To deal with our ADC channel */
  #include <linux/init.h>
  #include <linux/delay.h>
  #include <linux/regulator/consumer.h>
  #include <linux/pm_runtime.h>
  #include <linux/interrupt.h>
  #include <linux/bits.h>
  #include <linux/math64.h>
  #include <linux/pm.h>
  
  #define GP2AP002_PROX_CHANNEL 0
  #define GP2AP002_ALS_CHANNEL 1
  
  /* ------------------------------------------------------------------------ */
  /* ADDRESS SYMBOL             DATA                                 Init R/W */
  /*                   D7    D6    D5    D4    D3    D2    D1    D0           */
  /* ------------------------------------------------------------------------ */
  /*    0      PROX     X     X     X     X     X     X     X    VO  H'00   R */
  /*    1      GAIN     X     X     X     X  LED0     X     X     X  H'00   W */
  /*    2       HYS  HYSD HYSC1 HYSC0     X HYSF3 HYSF2 HYSF1 HYSF0  H'00   W */
  /*    3     CYCLE     X     X CYCL2 CYCL1 CYCL0  OSC2     X     X  H'00   W */
  /*    4     OPMOD     X     X     X   ASD     X     X  VCON   SSD  H'00   W */
  /*    6       CON     X     X     X OCON1 OCON0     X     X     X  H'00   W */
  /* ------------------------------------------------------------------------ */
  /* VO   :Proximity sensing result(0: no detection, 1: detection)            */
  /* LED0 :Select switch for LED driver's On-registence(0:2x higher, 1:normal)*/
  /* HYSD/HYSF :Adjusts the receiver sensitivity                              */
  /* OSC  :Select switch internal clocl frequency hoppling(0:effective)       */
  /* CYCL :Determine the detection cycle(typically 8ms, up to 128x)           */
  /* SSD  :Software Shutdown function(0:shutdown, 1:operating)                */
  /* VCON :VOUT output method control(0:normal, 1:interrupt)                  */
  /* ASD  :Select switch for analog sleep function(0:ineffective, 1:effective)*/
  /* OCON :Select switch for enabling/disabling VOUT (00:enable, 11:disable)  */
  
  #define GP2AP002_PROX				0x00
  #define GP2AP002_GAIN				0x01
  #define GP2AP002_HYS				0x02
  #define GP2AP002_CYCLE				0x03
  #define GP2AP002_OPMOD				0x04
  #define GP2AP002_CON				0x06
  
  #define GP2AP002_PROX_VO_DETECT			BIT(0)
  
  /* Setting this bit to 0 means 2x higher LED resistance */
  #define GP2AP002_GAIN_LED_NORMAL		BIT(3)
  
  /*
   * These bits adjusts the proximity sensitivity, determining characteristics
   * of the detection distance and its hysteresis.
   */
  #define GP2AP002_HYS_HYSD_SHIFT		7
  #define GP2AP002_HYS_HYSD_MASK		BIT(7)
  #define GP2AP002_HYS_HYSC_SHIFT		5
  #define GP2AP002_HYS_HYSC_MASK		GENMASK(6, 5)
  #define GP2AP002_HYS_HYSF_SHIFT		0
  #define GP2AP002_HYS_HYSF_MASK		GENMASK(3, 0)
  #define GP2AP002_HYS_MASK		(GP2AP002_HYS_HYSD_MASK | \
  					 GP2AP002_HYS_HYSC_MASK | \
  					 GP2AP002_HYS_HYSF_MASK)
  
  /*
   * These values determine the detection cycle response time
   * 0: 8ms, 1: 16ms, 2: 32ms, 3: 64ms, 4: 128ms,
   * 5: 256ms, 6: 512ms, 7: 1024ms
   */
  #define GP2AP002_CYCLE_CYCL_SHIFT	3
  #define GP2AP002_CYCLE_CYCL_MASK	GENMASK(5, 3)
  
  /*
   * Select switch for internal clock frequency hopping
   *	0: effective,
   *	1: ineffective
   */
  #define GP2AP002_CYCLE_OSC_EFFECTIVE	0
  #define GP2AP002_CYCLE_OSC_INEFFECTIVE	BIT(2)
  #define GP2AP002_CYCLE_OSC_MASK		BIT(2)
  
  /* Analog sleep effective */
  #define GP2AP002_OPMOD_ASD		BIT(4)
  /* Enable chip */
  #define GP2AP002_OPMOD_SSD_OPERATING	BIT(0)
  /* IRQ mode */
  #define GP2AP002_OPMOD_VCON_IRQ		BIT(1)
  #define GP2AP002_OPMOD_MASK		(BIT(0) | BIT(1) | BIT(4))
  
  /*
   * Select switch for enabling/disabling Vout pin
   * 0: enable
   * 2: force to go Low
   * 3: force to go High
   */
  #define GP2AP002_CON_OCON_SHIFT		3
  #define GP2AP002_CON_OCON_ENABLE	(0x0 << GP2AP002_CON_OCON_SHIFT)
  #define GP2AP002_CON_OCON_LOW		(0x2 << GP2AP002_CON_OCON_SHIFT)
  #define GP2AP002_CON_OCON_HIGH		(0x3 << GP2AP002_CON_OCON_SHIFT)
  #define GP2AP002_CON_OCON_MASK		(0x3 << GP2AP002_CON_OCON_SHIFT)
  
  /**
   * struct gp2ap002 - GP2AP002 state
   * @map: regmap pointer for the i2c regmap
   * @dev: pointer to parent device
   * @vdd: regulator controlling VDD
   * @vio: regulator controlling VIO
   * @alsout: IIO ADC channel to convert the ALSOUT signal
   * @hys_far: hysteresis control from device tree
   * @hys_close: hysteresis control from device tree
   * @is_gp2ap002s00f: this is the GP2AP002F variant of the chip
   * @irq: the IRQ line used by this device
   * @enabled: we cannot read the status of the hardware so we need to
   * keep track of whether the event is enabled using this state variable
   */
  struct gp2ap002 {
  	struct regmap *map;
  	struct device *dev;
  	struct regulator *vdd;
  	struct regulator *vio;
  	struct iio_channel *alsout;
  	u8 hys_far;
  	u8 hys_close;
  	bool is_gp2ap002s00f;
  	int irq;
  	bool enabled;
  };
  
  static irqreturn_t gp2ap002_prox_irq(int irq, void *d)
  {
  	struct iio_dev *indio_dev = d;
  	struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
  	u64 ev;
  	int val;
  	int ret;
  
  	ret = regmap_read(gp2ap002->map, GP2AP002_PROX, &val);
  	if (ret) {
  		dev_err(gp2ap002->dev, "error reading proximity\n");
  		goto err_retrig;
  	}
  
  	if (val & GP2AP002_PROX_VO_DETECT) {
  		/* Close */
  		dev_dbg(gp2ap002->dev, "close\n");
  		ret = regmap_write(gp2ap002->map, GP2AP002_HYS,
  				   gp2ap002->hys_far);
  		if (ret)
  			dev_err(gp2ap002->dev,
  				"error setting up proximity hysteresis\n");
  		ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, GP2AP002_PROX_CHANNEL,
  					IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING);
  	} else {
  		/* Far */
  		dev_dbg(gp2ap002->dev, "far\n");
  		ret = regmap_write(gp2ap002->map, GP2AP002_HYS,
  				   gp2ap002->hys_close);
  		if (ret)
  			dev_err(gp2ap002->dev,
  				"error setting up proximity hysteresis\n");
  		ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, GP2AP002_PROX_CHANNEL,
  					IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING);
  	}
  	iio_push_event(indio_dev, ev, iio_get_time_ns(indio_dev));
  
  	/*
  	 * After changing hysteresis, we need to wait for one detection
  	 * cycle to see if anything changed, or we will just trigger the
  	 * previous interrupt again. A detection cycle depends on the CYCLE
  	 * register, we are hard-coding ~8 ms in probe() so wait some more
  	 * than this, 20-30 ms.
  	 */
  	usleep_range(20000, 30000);
  
  err_retrig:
  	ret = regmap_write(gp2ap002->map, GP2AP002_CON,
  			   GP2AP002_CON_OCON_ENABLE);
  	if (ret)
  		dev_err(gp2ap002->dev, "error setting up VOUT control\n");
  
  	return IRQ_HANDLED;
  }
  
  /*
   * This array maps current and lux.
   *
   * Ambient light sensing range is 3 to 55000 lux.
   *
   * This mapping is based on the following formula.
   * illuminance = 10 ^ (current[mA] / 10)
   *
   * When the ADC measures 0, return 0 lux.
   */
  static const u16 gp2ap002_illuminance_table[] = {
  	0, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32, 40, 50, 63, 79,
  	100, 126, 158, 200, 251, 316, 398, 501, 631, 794, 1000, 1259, 1585,
  	1995, 2512, 3162, 3981, 5012, 6310, 7943, 10000, 12589, 15849, 19953,
  	25119, 31623, 39811, 50119,
  };
  
  static int gp2ap002_get_lux(struct gp2ap002 *gp2ap002)
  {
  	int ret, res;
  	u16 lux;
  
  	ret = iio_read_channel_processed(gp2ap002->alsout, &res);
  	if (ret < 0)
  		return ret;
  
  	dev_dbg(gp2ap002->dev, "read %d mA from ADC\n", res);
  
  	/* ensure we don't under/overflow */
  	res = clamp(res, 0, (int)ARRAY_SIZE(gp2ap002_illuminance_table) - 1);
  	lux = gp2ap002_illuminance_table[res];
  
  	return (int)lux;
  }
  
  static int gp2ap002_read_raw(struct iio_dev *indio_dev,
  			   struct iio_chan_spec const *chan,
  			   int *val, int *val2, long mask)
  {
  	struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
  	int ret;
  
  	switch (mask) {
  	case IIO_CHAN_INFO_RAW:
  		switch (chan->type) {
  		case IIO_LIGHT:
  			ret = gp2ap002_get_lux(gp2ap002);
  			if (ret < 0)
  				return ret;
  			*val = ret;
  			return IIO_VAL_INT;
  		default:
  			return -EINVAL;
  		}
  	default:
  		return -EINVAL;
  	}
  }
  
  static int gp2ap002_init(struct gp2ap002 *gp2ap002)
  {
  	int ret;
  
  	/* Set up the IR LED resistance */
  	ret = regmap_write(gp2ap002->map, GP2AP002_GAIN,
  			   GP2AP002_GAIN_LED_NORMAL);
  	if (ret) {
  		dev_err(gp2ap002->dev, "error setting up LED gain\n");
  		return ret;
  	}
  	ret = regmap_write(gp2ap002->map, GP2AP002_HYS, gp2ap002->hys_far);
  	if (ret) {
  		dev_err(gp2ap002->dev,
  			"error setting up proximity hysteresis\n");
  		return ret;
  	}
  
  	/* Disable internal frequency hopping */
  	ret = regmap_write(gp2ap002->map, GP2AP002_CYCLE,
  			   GP2AP002_CYCLE_OSC_INEFFECTIVE);
  	if (ret) {
  		dev_err(gp2ap002->dev,
  			"error setting up internal frequency hopping\n");
  		return ret;
  	}
  
  	/* Enable chip and IRQ, disable analog sleep */
  	ret = regmap_write(gp2ap002->map, GP2AP002_OPMOD,
  			   GP2AP002_OPMOD_SSD_OPERATING |
  			   GP2AP002_OPMOD_VCON_IRQ);
  	if (ret) {
  		dev_err(gp2ap002->dev, "error setting up operation mode\n");
  		return ret;
  	}
  
  	/* Interrupt on VOUT enabled */
  	ret = regmap_write(gp2ap002->map, GP2AP002_CON,
  			   GP2AP002_CON_OCON_ENABLE);
  	if (ret)
  		dev_err(gp2ap002->dev, "error setting up VOUT control\n");
  
  	return ret;
  }
  
  static int gp2ap002_read_event_config(struct iio_dev *indio_dev,
  				      const struct iio_chan_spec *chan,
  				      enum iio_event_type type,
  				      enum iio_event_direction dir)
  {
  	struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
  
  	/*
  	 * We just keep track of this internally, as it is not possible to
  	 * query the hardware.
  	 */
  	return gp2ap002->enabled;
  }
  
  static int gp2ap002_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)
  {
  	struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
  
  	if (state) {
  		/*
  		 * This will bring the regulators up (unless they are on
  		 * already) and reintialize the sensor by using runtime_pm
  		 * callbacks.
  		 */
  		pm_runtime_get_sync(gp2ap002->dev);
  		gp2ap002->enabled = true;
  	} else {
  		pm_runtime_mark_last_busy(gp2ap002->dev);
  		pm_runtime_put_autosuspend(gp2ap002->dev);
  		gp2ap002->enabled = false;
  	}
  
  	return 0;
  }
  
  static const struct iio_info gp2ap002_info = {
  	.read_raw = gp2ap002_read_raw,
  	.read_event_config = gp2ap002_read_event_config,
  	.write_event_config = gp2ap002_write_event_config,
  };
  
  static const struct iio_event_spec gp2ap002_events[] = {
  	{
  		.type = IIO_EV_TYPE_THRESH,
  		.dir = IIO_EV_DIR_EITHER,
  		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
  	},
  };
  
  static const struct iio_chan_spec gp2ap002_channels[] = {
  	{
  		.type = IIO_PROXIMITY,
  		.event_spec = gp2ap002_events,
  		.num_event_specs = ARRAY_SIZE(gp2ap002_events),
  	},
  	{
  		.type = IIO_LIGHT,
  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  		.channel = GP2AP002_ALS_CHANNEL,
  	},
  };
  
  /*
   * We need a special regmap because this hardware expects to
   * write single bytes to registers but read a 16bit word on some
   * variants and discard the lower 8 bits so combine
   * i2c_smbus_read_word_data() with i2c_smbus_write_byte_data()
   * selectively like this.
   */
  static int gp2ap002_regmap_i2c_read(void *context, unsigned int reg,
  				    unsigned int *val)
  {
  	struct device *dev = context;
  	struct i2c_client *i2c = to_i2c_client(dev);
  	int ret;
  
  	ret = i2c_smbus_read_word_data(i2c, reg);
  	if (ret < 0)
  		return ret;
  
  	*val = (ret >> 8) & 0xFF;
  
  	return 0;
  }
  
  static int gp2ap002_regmap_i2c_write(void *context, unsigned int reg,
  				     unsigned int val)
  {
  	struct device *dev = context;
  	struct i2c_client *i2c = to_i2c_client(dev);
  
  	return i2c_smbus_write_byte_data(i2c, reg, val);
  }
  
  static struct regmap_bus gp2ap002_regmap_bus = {
  	.reg_read = gp2ap002_regmap_i2c_read,
  	.reg_write = gp2ap002_regmap_i2c_write,
  };
  
  static int gp2ap002_probe(struct i2c_client *client,
  			  const struct i2c_device_id *id)
  {
  	struct gp2ap002 *gp2ap002;
  	struct iio_dev *indio_dev;
  	struct device *dev = &client->dev;
  	enum iio_chan_type ch_type;
  	static const struct regmap_config config = {
  		.reg_bits = 8,
  		.val_bits = 8,
  		.max_register = GP2AP002_CON,
  	};
  	struct regmap *regmap;
  	int num_chan;
  	const char *compat;
  	u8 val;
  	int ret;
  
  	indio_dev = devm_iio_device_alloc(dev, sizeof(*gp2ap002));
  	if (!indio_dev)
  		return -ENOMEM;
  	i2c_set_clientdata(client, indio_dev);
  
  	gp2ap002 = iio_priv(indio_dev);
  	gp2ap002->dev = dev;
  
  	/*
  	 * Check the device compatible like this makes it possible to use
  	 * ACPI PRP0001 for registering the sensor using device tree
  	 * properties.
  	 */
  	ret = device_property_read_string(dev, "compatible", &compat);
  	if (ret) {
  		dev_err(dev, "cannot check compatible\n");
  		return ret;
  	}
  	gp2ap002->is_gp2ap002s00f = !strcmp(compat, "sharp,gp2ap002s00f");
  
  	regmap = devm_regmap_init(dev, &gp2ap002_regmap_bus, dev, &config);
  	if (IS_ERR(regmap)) {
  		dev_err(dev, "Failed to register i2c regmap %d\n",
  			(int)PTR_ERR(regmap));
  		return PTR_ERR(regmap);
  	}
  	gp2ap002->map = regmap;
  
  	/*
  	 * The hysteresis settings are coded into the device tree as values
  	 * to be written into the hysteresis register. The datasheet defines
  	 * modes "A", "B1" and "B2" with fixed values to be use but vendor
  	 * code trees for actual devices are tweaking these values and refer to
  	 * modes named things like "B1.5". To be able to support any devices,
  	 * we allow passing an arbitrary hysteresis setting for "near" and
  	 * "far".
  	 */
  
  	/* Check the device tree for the IR LED hysteresis */
  	ret = device_property_read_u8(dev, "sharp,proximity-far-hysteresis",
  				      &val);
  	if (ret) {
  		dev_err(dev, "failed to obtain proximity far setting\n");
  		return ret;
  	}
  	dev_dbg(dev, "proximity far setting %02x\n", val);
  	gp2ap002->hys_far = val;
  
  	ret = device_property_read_u8(dev, "sharp,proximity-close-hysteresis",
  				      &val);
  	if (ret) {
  		dev_err(dev, "failed to obtain proximity close setting\n");
  		return ret;
  	}
  	dev_dbg(dev, "proximity close setting %02x\n", val);
  	gp2ap002->hys_close = val;
  
  	/* The GP2AP002A00F has a light sensor too */
  	if (!gp2ap002->is_gp2ap002s00f) {
  		gp2ap002->alsout = devm_iio_channel_get(dev, "alsout");
  		if (IS_ERR(gp2ap002->alsout)) {
  			if (PTR_ERR(gp2ap002->alsout) == -ENODEV) {
  				dev_err(dev, "no ADC, deferring...\n");
  				return -EPROBE_DEFER;
  			}
  			dev_err(dev, "failed to get ALSOUT ADC channel\n");
  			return PTR_ERR(gp2ap002->alsout);
  		}
  		ret = iio_get_channel_type(gp2ap002->alsout, &ch_type);
  		if (ret < 0)
  			return ret;
  		if (ch_type != IIO_CURRENT) {
  			dev_err(dev,
  				"wrong type of IIO channel specified for ALSOUT\n");
  			return -EINVAL;
  		}
  	}
  
  	gp2ap002->vdd = devm_regulator_get(dev, "vdd");
  	if (IS_ERR(gp2ap002->vdd)) {
  		dev_err(dev, "failed to get VDD regulator\n");
  		return PTR_ERR(gp2ap002->vdd);
  	}
  	gp2ap002->vio = devm_regulator_get(dev, "vio");
  	if (IS_ERR(gp2ap002->vio)) {
  		dev_err(dev, "failed to get VIO regulator\n");
  		return PTR_ERR(gp2ap002->vio);
  	}
  
  	/* Operating voltage 2.4V .. 3.6V according to datasheet */
  	ret = regulator_set_voltage(gp2ap002->vdd, 2400000, 3600000);
  	if (ret) {
  		dev_err(dev, "failed to sett VDD voltage\n");
  		return ret;
  	}
  
  	/* VIO should be between 1.65V and VDD */
  	ret = regulator_get_voltage(gp2ap002->vdd);
  	if (ret < 0) {
  		dev_err(dev, "failed to get VDD voltage\n");
  		return ret;
  	}
  	ret = regulator_set_voltage(gp2ap002->vio, 1650000, ret);
  	if (ret) {
  		dev_err(dev, "failed to set VIO voltage\n");
  		return ret;
  	}
  
  	ret = regulator_enable(gp2ap002->vdd);
  	if (ret) {
  		dev_err(dev, "failed to enable VDD regulator\n");
  		return ret;
  	}
  	ret = regulator_enable(gp2ap002->vio);
  	if (ret) {
  		dev_err(dev, "failed to enable VIO regulator\n");
  		goto out_disable_vdd;
  	}
  
  	msleep(20);
  
  	/*
  	 * Initialize the device and signal to runtime PM that now we are
  	 * definately up and using power.
  	 */
  	ret = gp2ap002_init(gp2ap002);
  	if (ret) {
  		dev_err(dev, "initialization failed\n");
  		goto out_disable_vio;
  	}
  	pm_runtime_get_noresume(dev);
  	pm_runtime_set_active(dev);
  	pm_runtime_enable(dev);
  	gp2ap002->enabled = false;
  
  	ret = devm_request_threaded_irq(dev, client->irq, NULL,
  					gp2ap002_prox_irq, IRQF_ONESHOT,
  					"gp2ap002", indio_dev);
  	if (ret) {
  		dev_err(dev, "unable to request IRQ\n");
  		goto out_disable_vio;
  	}
  	gp2ap002->irq = client->irq;
  
  	/*
  	 * As the device takes 20 ms + regulator delay to come up with a fresh
  	 * measurement after power-on, do not shut it down unnecessarily.
  	 * Set autosuspend to a one second.
  	 */
  	pm_runtime_set_autosuspend_delay(dev, 1000);
  	pm_runtime_use_autosuspend(dev);
  	pm_runtime_put(dev);
  
  	indio_dev->dev.parent = dev;
  	indio_dev->info = &gp2ap002_info;
  	indio_dev->name = "gp2ap002";
  	indio_dev->channels = gp2ap002_channels;
  	/* Skip light channel for the proximity-only sensor */
  	num_chan = ARRAY_SIZE(gp2ap002_channels);
  	if (gp2ap002->is_gp2ap002s00f)
  		num_chan--;
  	indio_dev->num_channels = num_chan;
  	indio_dev->modes = INDIO_DIRECT_MODE;
  
  	ret = iio_device_register(indio_dev);
  	if (ret)
  		goto out_disable_pm;
  	dev_dbg(dev, "Sharp GP2AP002 probed successfully\n");
  
  	return 0;
  
  out_disable_pm:
  	pm_runtime_put_noidle(dev);
  	pm_runtime_disable(dev);
  out_disable_vio:
  	regulator_disable(gp2ap002->vio);
  out_disable_vdd:
  	regulator_disable(gp2ap002->vdd);
  	return ret;
  }
  
  static int gp2ap002_remove(struct i2c_client *client)
  {
  	struct iio_dev *indio_dev = i2c_get_clientdata(client);
  	struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
  	struct device *dev = &client->dev;
  
  	pm_runtime_get_sync(dev);
  	pm_runtime_put_noidle(dev);
  	pm_runtime_disable(dev);
  	iio_device_unregister(indio_dev);
  	regulator_disable(gp2ap002->vio);
  	regulator_disable(gp2ap002->vdd);
  
  	return 0;
  }
  
  static int __maybe_unused gp2ap002_runtime_suspend(struct device *dev)
  {
  	struct iio_dev *indio_dev = dev_get_drvdata(dev);
  	struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
  	int ret;
  
  	/* Deactivate the IRQ */
  	disable_irq(gp2ap002->irq);
  
  	/* Disable chip and IRQ, everything off */
  	ret = regmap_write(gp2ap002->map, GP2AP002_OPMOD, 0x00);
  	if (ret) {
  		dev_err(gp2ap002->dev, "error setting up operation mode\n");
  		return ret;
  	}
  	/*
  	 * As these regulators may be shared, at least we are now in
  	 * sleep even if the regulators aren't really turned off.
  	 */
  	regulator_disable(gp2ap002->vio);
  	regulator_disable(gp2ap002->vdd);
  
  	return 0;
  }
  
  static int __maybe_unused gp2ap002_runtime_resume(struct device *dev)
  {
  	struct iio_dev *indio_dev = dev_get_drvdata(dev);
  	struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
  	int ret;
  
  	ret = regulator_enable(gp2ap002->vdd);
  	if (ret) {
  		dev_err(dev, "failed to enable VDD regulator in resume path\n");
  		return ret;
  	}
  	ret = regulator_enable(gp2ap002->vio);
  	if (ret) {
  		dev_err(dev, "failed to enable VIO regulator in resume path\n");
  		return ret;
  	}
  
  	msleep(20);
  
  	ret = gp2ap002_init(gp2ap002);
  	if (ret) {
  		dev_err(dev, "re-initialization failed\n");
  		return ret;
  	}
  
  	/* Re-activate the IRQ */
  	enable_irq(gp2ap002->irq);
  
  	return 0;
  }
  
  static const struct dev_pm_ops gp2ap002_dev_pm_ops = {
  	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
  				pm_runtime_force_resume)
  	SET_RUNTIME_PM_OPS(gp2ap002_runtime_suspend,
  			   gp2ap002_runtime_resume, NULL)
  };
  
  static const struct i2c_device_id gp2ap002_id_table[] = {
  	{ "gp2ap002", 0 },
  	{ },
  };
  MODULE_DEVICE_TABLE(i2c, gp2ap002_id_table);
  
  static const struct of_device_id gp2ap002_of_match[] = {
  	{ .compatible = "sharp,gp2ap002a00f" },
  	{ .compatible = "sharp,gp2ap002s00f" },
  	{ },
  };
  MODULE_DEVICE_TABLE(of, gp2ap002_of_match);
  
  static struct i2c_driver gp2ap002_driver = {
  	.driver = {
  		.name = "gp2ap002",
  		.of_match_table = gp2ap002_of_match,
  		.pm = &gp2ap002_dev_pm_ops,
  	},
  	.probe = gp2ap002_probe,
  	.remove = gp2ap002_remove,
  	.id_table = gp2ap002_id_table,
  };
  module_i2c_driver(gp2ap002_driver);
  
  MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
  MODULE_DESCRIPTION("GP2AP002 ambient light and proximity sensor driver");
  MODULE_LICENSE("GPL v2");
  