/**
 * Will setup clocks, GPIOs, and regulators to correctly initialize the touch
 * sensor to be ready for work.
 *
 * In the correct order according to the sensor spec this function will
 * enable/disable regulators, SPI platform clocks, and reset line, all to set
 * the sensor in a correct power on or off state "electrical" wise.
 *
 * @see  spi_prepare_set
 * @note This function will not send any commands to the sensor it will only
 *       control it "electrically".
 */
static int device_prepare(struct  fpc1020_data *fpc1020, bool enable)
{
	int rc = 0;
	int error = 0;

	mutex_lock(&fpc1020->lock);
	if (enable && !fpc1020->prepared) {
		spi_bus_lock(fpc1020->spi->master);
		fpc1020->prepared = true;

		dev_info(&fpc1020->spi->dev, "%s: power on!!!!\n", __func__);

		error = fpc1020_io_regulator_configure(fpc1020);
		if (error) {
			dev_err(&fpc1020->spi->dev,
				"fpc1020_probe - io regulator configuration failed.\n");
		}

		error = fpc1020_io_regulator_set(fpc1020, true);
		if (error) {
			dev_err(&fpc1020->spi->dev,
				"fpc1020_probe - io regulator enable failed.\n");
		}

		usleep_range(100, 1000);

		rc = spi_set_fabric(fpc1020, true);
		if (rc)
			goto exit_3;

		usleep_range(100, 200);

#if defined(CONFIG_QSEECOM)
		rc = set_pipe_ownership(fpc1020, true);
		if (rc)
			goto exit_5;
#endif
	} else if (!enable && fpc1020->prepared) {
#if defined(CONFIG_QSEECOM)
		(void)set_pipe_ownership(fpc1020, false);
exit_5:
#endif

		(void)spi_set_fabric(fpc1020, false);
exit_3:
		(void)select_pin_ctl(fpc1020, "fpc1020_cs_high");
		(void)select_pin_ctl(fpc1020, "fpc1020_reset_reset");
		usleep_range(100, 1000);
		(void)select_pin_ctl(fpc1020, "fpc1020_cs_low");

		fpc1020->prepared = false;
		spi_bus_unlock(fpc1020->spi->master);
	}
	mutex_unlock(&fpc1020->lock);

	return rc;
}
/**
 * Will indicate to the SPI driver that a message is soon to be delivered over
 * it.
 *
 * Exactly what fabric resources are requested is up to the SPI device driver.
 *
 * @see spi_set_fabric
 */
static ssize_t fabric_vote_set(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{
	struct  fpc1145_data *fpc1145 = dev_get_drvdata(dev);
	int rc = spi_set_fabric(fpc1145, *buf == '1');
	return rc ? rc : count;
}
/**
 * Will setup clocks, GPIOs, and regulators to correctly initialize the touch
 * sensor to be ready for work.
 *
 * In the correct order according to the sensor spec this function will
 * enable/disable regulators, SPI platform clocks, and reset line, all to set
 * the sensor in a correct power on or off state "electrical" wise.
 *
 * @see  spi_prepare_set
 * @note This function will not send any commands to the sensor it will only
 *       control it "electrically".
 */
static int device_prepare(struct  fpc1145_data *fpc1145, bool enable)
{
	int rc;

	mutex_lock(&fpc1145->lock);
	if (enable && !fpc1145->prepared) {
		spi_bus_lock(fpc1145->spi->master);
		fpc1145->prepared = true;
		select_pin_ctl(fpc1145, "fpc1145_reset_reset");

		rc = vreg_setup(fpc1145, "vcc_spi", true);
		if (rc)
			goto exit;

		rc = vreg_setup(fpc1145, "vdd_io", true);
		if (rc)
			goto exit_1;

		rc = vreg_setup(fpc1145, "vdd_ana", true);
		if (rc)
			goto exit_2;

		usleep_range(100, 1000);

		rc = spi_set_fabric(fpc1145, true);
		if (rc)
			goto exit_3;
		rc = set_clks(fpc1145, true);
		if (rc)
			goto exit_4;

		(void)select_pin_ctl(fpc1145, "fpc1145_cs_high");
		(void)select_pin_ctl(fpc1145, "fpc1145_reset_active");
		usleep_range(100, 200);
		(void)select_pin_ctl(fpc1145, "fpc1145_cs_active");

		rc = set_pipe_ownership(fpc1145, true);
		if (rc)
			goto exit_5;
	} else if (!enable && fpc1145->prepared) {
		rc = 0;
		(void)set_pipe_ownership(fpc1145, false);
exit_5:
		(void)set_clks(fpc1145, false);
exit_4:
		(void)spi_set_fabric(fpc1145, false);
exit_3:
		(void)select_pin_ctl(fpc1145, "fpc1145_cs_high");
		(void)select_pin_ctl(fpc1145, "fpc1145_reset_reset");
		usleep_range(FPC1145_VREG_SETUP_US,
				FPC1145_VREG_SETUP_US + 100);

		(void)select_pin_ctl(fpc1145, "fpc1145_cs_low");
		usleep_range(FPC1145_VREG_SETUP_US,
				FPC1145_VREG_SETUP_US + 100);

exit_2:
		(void)vreg_setup(fpc1145, "vdd_ana", false);
exit_1:
		(void)vreg_setup(fpc1145, "vdd_io", false);
exit:
		(void)vreg_setup(fpc1145, "vcc_spi", false);
		fpc1145->prepared = false;
		spi_bus_unlock(fpc1145->spi->master);
	} else {
		rc = 0;
	}
	mutex_unlock(&fpc1145->lock);
	return rc;
}
static int device_prepare(struct  fpc1020_data *fpc1020, bool enable)
{
	int rc;

	mutex_lock(&fpc1020->lock);
	if (enable && !fpc1020->prepared) {
		spi_bus_lock(fpc1020->spi->master);
		fpc1020->prepared = true;
		/* select_pin_ctl(fpc1020, "fpc1020_reset_reset"); */

		/*
		rc = vreg_setup(fpc1020, "vcc_spi", true);
		if (rc)
			goto exit;

		rc = vreg_setup(fpc1020, "vdd_io", true);
		if (rc)
			goto exit_1;

		rc = vreg_setup(fpc1020, "vdd_ana", true);
		if (rc)
			goto exit_2;
		*/
		usleep_range(100, 1000);

		rc = spi_set_fabric(fpc1020, true);
		if (rc)
			goto exit_3;
		rc = set_clks(fpc1020, true);
		if (rc)
			goto exit_4;

		/* (void)select_pin_ctl(fpc1020, "fpc1020_cs_high"); */
		/* (void)select_pin_ctl(fpc1020, "fpc1020_reset_active"); */
		usleep_range(100, 200);
		/* (void)select_pin_ctl(fpc1020, "fpc1020_cs_active"); */

#if defined(SUPPORT_TRUSTZONE)
		rc = set_pipe_ownership(fpc1020, true);
		if (rc)
			goto exit_5;
#endif
	} else if (!enable && fpc1020->prepared) {
		rc = 0;
#if defined(SUPPORT_TRUSTZONE)
		(void)set_pipe_ownership(fpc1020, false);
exit_5:
#endif
		(void)set_clks(fpc1020, false);
exit_4:
		(void)spi_set_fabric(fpc1020, false);
exit_3:
		(void)select_pin_ctl(fpc1020, "fpc1020_cs_high");
		(void)select_pin_ctl(fpc1020, "fpc1020_reset_reset");
		usleep_range(100, 1000);
/*
		(void)vreg_setup(fpc1020, "vdd_ana", false);
exit_2:
		(void)vreg_setup(fpc1020, "vdd_io", false);
exit_1:
		(void)vreg_setup(fpc1020, "vcc_spi", false);
exit:
*/
		(void)select_pin_ctl(fpc1020, "fpc1020_cs_low");

		fpc1020->prepared = false;
		spi_bus_unlock(fpc1020->spi->master);
	} else {
		rc = 0;
	}
	mutex_unlock(&fpc1020->lock);
	return rc;
}