diff options
Diffstat (limited to 'drivers/iio/adc/exynos_adc.c')
| -rw-r--r-- | drivers/iio/adc/exynos_adc.c | 286 | 
1 files changed, 4 insertions, 282 deletions
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 4614cf848535..1484adff00df 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -19,11 +19,9 @@  #include <linux/clk.h>  #include <linux/completion.h>  #include <linux/of.h> -#include <linux/of_irq.h>  #include <linux/regulator/consumer.h>  #include <linux/of_platform.h>  #include <linux/err.h> -#include <linux/input.h>  #include <linux/iio/iio.h>  #include <linux/iio/machine.h> @@ -31,21 +29,14 @@  #include <linux/mfd/syscon.h>  #include <linux/regmap.h> -#include <linux/platform_data/touchscreen-s3c2410.h> -  /* S3C/EXYNOS4412/5250 ADC_V1 registers definitions */  #define ADC_V1_CON(x)		((x) + 0x00) -#define ADC_V1_TSC(x)		((x) + 0x04)  #define ADC_V1_DLY(x)		((x) + 0x08)  #define ADC_V1_DATX(x)		((x) + 0x0C)  #define ADC_V1_DATY(x)		((x) + 0x10)  #define ADC_V1_UPDN(x)		((x) + 0x14)  #define ADC_V1_INTCLR(x)	((x) + 0x18)  #define ADC_V1_MUX(x)		((x) + 0x1c) -#define ADC_V1_CLRINTPNDNUP(x)	((x) + 0x20) - -/* S3C2410 ADC registers definitions */ -#define ADC_S3C2410_MUX(x)	((x) + 0x18)  /* Future ADC_V2 registers definitions */  #define ADC_V2_CON1(x)		((x) + 0x00) @@ -61,13 +52,8 @@  #define ADC_V1_CON_PRSCLV(x)	(((x) & 0xFF) << 6)  #define ADC_V1_CON_STANDBY	(1u << 2) -/* Bit definitions for S3C2410 ADC */ +/* Bit definitions for S3C2410 / S3C6410 ADC */  #define ADC_S3C2410_CON_SELMUX(x) (((x) & 7) << 3) -#define ADC_S3C2410_DATX_MASK	0x3FF -#define ADC_S3C2416_CON_RES_SEL	(1u << 3) - -/* touch screen always uses channel 0 */ -#define ADC_S3C2410_MUX_TS	0  /* ADCTSC Register Bits */  #define ADC_S3C2443_TSC_UD_SEN		(1u << 8) @@ -75,8 +61,6 @@  #define ADC_S3C2410_TSC_YP_SEN		(1u << 6)  #define ADC_S3C2410_TSC_XM_SEN		(1u << 5)  #define ADC_S3C2410_TSC_XP_SEN		(1u << 4) -#define ADC_S3C2410_TSC_PULL_UP_DISABLE	(1u << 3) -#define ADC_S3C2410_TSC_AUTO_PST	(1u << 2)  #define ADC_S3C2410_TSC_XY_PST(x)	(((x) & 0x3) << 0)  #define ADC_TSC_WAIT4INT (ADC_S3C2410_TSC_YM_SEN | \ @@ -84,12 +68,6 @@  			 ADC_S3C2410_TSC_XP_SEN | \  			 ADC_S3C2410_TSC_XY_PST(3)) -#define ADC_TSC_AUTOPST	(ADC_S3C2410_TSC_YM_SEN | \ -			 ADC_S3C2410_TSC_YP_SEN | \ -			 ADC_S3C2410_TSC_XP_SEN | \ -			 ADC_S3C2410_TSC_AUTO_PST | \ -			 ADC_S3C2410_TSC_XY_PST(0)) -  /* Bit definitions for ADC_V2 */  #define ADC_V2_CON1_SOFT_RESET	(1u << 2) @@ -121,14 +99,11 @@  struct exynos_adc {  	struct exynos_adc_data	*data;  	struct device		*dev; -	struct input_dev	*input;  	void __iomem		*regs;  	struct regmap		*pmu_map;  	struct clk		*clk;  	struct clk		*sclk;  	unsigned int		irq; -	unsigned int		tsirq; -	unsigned int		delay;  	struct regulator	*vdd;  	struct completion	completion; @@ -136,12 +111,6 @@ struct exynos_adc {  	u32			value;  	unsigned int            version; -	bool			ts_enabled; - -	bool			read_ts; -	u32			ts_x; -	u32			ts_y; -  	/*  	 * Lock to protect from potential concurrent access to the  	 * completion callback during a manual conversion. For this driver @@ -241,7 +210,7 @@ static void exynos_adc_v1_init_hw(struct exynos_adc *info)  	writel(con1, ADC_V1_CON(info->regs));  	/* set touchscreen delay */ -	writel(info->delay, ADC_V1_DLY(info->regs)); +	writel(10000, ADC_V1_DLY(info->regs));  }  static void exynos_adc_v1_exit_hw(struct exynos_adc *info) @@ -307,53 +276,6 @@ static const struct exynos_adc_data exynos_adc_s5pv210_data = {  	.start_conv	= exynos_adc_v1_start_conv,  }; -static void exynos_adc_s3c2416_start_conv(struct exynos_adc *info, -					  unsigned long addr) -{ -	u32 con1; - -	/* Enable 12 bit ADC resolution */ -	con1 = readl(ADC_V1_CON(info->regs)); -	con1 |= ADC_S3C2416_CON_RES_SEL; -	writel(con1, ADC_V1_CON(info->regs)); - -	/* Select channel for S3C2416 */ -	writel(addr, ADC_S3C2410_MUX(info->regs)); - -	con1 = readl(ADC_V1_CON(info->regs)); -	writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs)); -} - -static struct exynos_adc_data const exynos_adc_s3c2416_data = { -	.num_channels	= MAX_ADC_V1_CHANNELS, -	.mask		= ADC_DATX_MASK,	/* 12 bit ADC resolution */ - -	.init_hw	= exynos_adc_v1_init_hw, -	.exit_hw	= exynos_adc_v1_exit_hw, -	.start_conv	= exynos_adc_s3c2416_start_conv, -}; - -static void exynos_adc_s3c2443_start_conv(struct exynos_adc *info, -					  unsigned long addr) -{ -	u32 con1; - -	/* Select channel for S3C2433 */ -	writel(addr, ADC_S3C2410_MUX(info->regs)); - -	con1 = readl(ADC_V1_CON(info->regs)); -	writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs)); -} - -static struct exynos_adc_data const exynos_adc_s3c2443_data = { -	.num_channels	= MAX_ADC_V1_CHANNELS, -	.mask		= ADC_S3C2410_DATX_MASK, /* 10 bit ADC resolution */ - -	.init_hw	= exynos_adc_v1_init_hw, -	.exit_hw	= exynos_adc_v1_exit_hw, -	.start_conv	= exynos_adc_s3c2443_start_conv, -}; -  static void exynos_adc_s3c64xx_start_conv(struct exynos_adc *info,  					  unsigned long addr)  { @@ -365,15 +287,6 @@ static void exynos_adc_s3c64xx_start_conv(struct exynos_adc *info,  	writel(con1 | ADC_CON_EN_START, ADC_V1_CON(info->regs));  } -static struct exynos_adc_data const exynos_adc_s3c24xx_data = { -	.num_channels	= MAX_ADC_V1_CHANNELS, -	.mask		= ADC_S3C2410_DATX_MASK, /* 10 bit ADC resolution */ - -	.init_hw	= exynos_adc_v1_init_hw, -	.exit_hw	= exynos_adc_v1_exit_hw, -	.start_conv	= exynos_adc_s3c64xx_start_conv, -}; -  static struct exynos_adc_data const exynos_adc_s3c64xx_data = {  	.num_channels	= MAX_ADC_V1_CHANNELS,  	.mask		= ADC_DATX_MASK,	/* 12 bit ADC resolution */ @@ -486,18 +399,6 @@ static const struct exynos_adc_data exynos7_adc_data = {  static const struct of_device_id exynos_adc_match[] = {  	{ -		.compatible = "samsung,s3c2410-adc", -		.data = &exynos_adc_s3c24xx_data, -	}, { -		.compatible = "samsung,s3c2416-adc", -		.data = &exynos_adc_s3c2416_data, -	}, { -		.compatible = "samsung,s3c2440-adc", -		.data = &exynos_adc_s3c24xx_data, -	}, { -		.compatible = "samsung,s3c2443-adc", -		.data = &exynos_adc_s3c2443_data, -	}, {  		.compatible = "samsung,s3c6410-adc",  		.data = &exynos_adc_s3c64xx_data,  	}, { @@ -580,55 +481,13 @@ static int exynos_read_raw(struct iio_dev *indio_dev,  	return ret;  } -static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y) -{ -	struct exynos_adc *info = iio_priv(indio_dev); -	unsigned long time_left; -	int ret; - -	mutex_lock(&info->lock); -	info->read_ts = true; - -	reinit_completion(&info->completion); - -	writel(ADC_S3C2410_TSC_PULL_UP_DISABLE | ADC_TSC_AUTOPST, -	       ADC_V1_TSC(info->regs)); - -	/* Select the ts channel to be used and Trigger conversion */ -	info->data->start_conv(info, ADC_S3C2410_MUX_TS); - -	time_left = wait_for_completion_timeout(&info->completion, -						EXYNOS_ADC_TIMEOUT); -	if (time_left == 0) { -		dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); -		if (info->data->init_hw) -			info->data->init_hw(info); -		ret = -ETIMEDOUT; -	} else { -		*x = info->ts_x; -		*y = info->ts_y; -		ret = 0; -	} - -	info->read_ts = false; -	mutex_unlock(&info->lock); - -	return ret; -} -  static irqreturn_t exynos_adc_isr(int irq, void *dev_id)  {  	struct exynos_adc *info = dev_id;  	u32 mask = info->data->mask;  	/* Read value */ -	if (info->read_ts) { -		info->ts_x = readl(ADC_V1_DATX(info->regs)); -		info->ts_y = readl(ADC_V1_DATY(info->regs)); -		writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs)); -	} else { -		info->value = readl(ADC_V1_DATX(info->regs)) & mask; -	} +	info->value = readl(ADC_V1_DATX(info->regs)) & mask;  	/* clear irq */  	if (info->data->clear_irq) @@ -639,46 +498,6 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id)  	return IRQ_HANDLED;  } -/* - * Here we (ab)use a threaded interrupt handler to stay running - * for as long as the touchscreen remains pressed, we report - * a new event with the latest data and then sleep until the - * next timer tick. This mirrors the behavior of the old - * driver, with much less code. - */ -static irqreturn_t exynos_ts_isr(int irq, void *dev_id) -{ -	struct exynos_adc *info = dev_id; -	struct iio_dev *dev = dev_get_drvdata(info->dev); -	u32 x, y; -	bool pressed; -	int ret; - -	while (READ_ONCE(info->ts_enabled)) { -		ret = exynos_read_s3c64xx_ts(dev, &x, &y); -		if (ret == -ETIMEDOUT) -			break; - -		pressed = x & y & ADC_DATX_PRESSED; -		if (!pressed) { -			input_report_key(info->input, BTN_TOUCH, 0); -			input_sync(info->input); -			break; -		} - -		input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK); -		input_report_abs(info->input, ABS_Y, y & ADC_DATY_MASK); -		input_report_key(info->input, BTN_TOUCH, 1); -		input_sync(info->input); - -		usleep_range(1000, 1100); -	} - -	writel(0, ADC_V1_CLRINTPNDNUP(info->regs)); - -	return IRQ_HANDLED; -} -  static int exynos_adc_reg_access(struct iio_dev *indio_dev,  			      unsigned reg, unsigned writeval,  			      unsigned *readval) @@ -730,78 +549,17 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)  	return 0;  } -static int exynos_adc_ts_open(struct input_dev *dev) -{ -	struct exynos_adc *info = input_get_drvdata(dev); - -	WRITE_ONCE(info->ts_enabled, true); -	enable_irq(info->tsirq); - -	return 0; -} - -static void exynos_adc_ts_close(struct input_dev *dev) -{ -	struct exynos_adc *info = input_get_drvdata(dev); - -	WRITE_ONCE(info->ts_enabled, false); -	disable_irq(info->tsirq); -} - -static int exynos_adc_ts_init(struct exynos_adc *info) -{ -	int ret; - -	if (info->tsirq <= 0) -		return -ENODEV; - -	info->input = input_allocate_device(); -	if (!info->input) -		return -ENOMEM; - -	info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); -	info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - -	input_set_abs_params(info->input, ABS_X, 0, 0x3FF, 0, 0); -	input_set_abs_params(info->input, ABS_Y, 0, 0x3FF, 0, 0); - -	info->input->name = "S3C24xx TouchScreen"; -	info->input->id.bustype = BUS_HOST; -	info->input->open = exynos_adc_ts_open; -	info->input->close = exynos_adc_ts_close; - -	input_set_drvdata(info->input, info); - -	ret = input_register_device(info->input); -	if (ret) { -		input_free_device(info->input); -		return ret; -	} - -	ret = request_threaded_irq(info->tsirq, NULL, exynos_ts_isr, -				   IRQF_ONESHOT | IRQF_NO_AUTOEN, -				   "touchscreen", info); -	if (ret) -		input_unregister_device(info->input); - -	return ret; -} -  static int exynos_adc_probe(struct platform_device *pdev)  {  	struct exynos_adc *info = NULL;  	struct device_node *np = pdev->dev.of_node; -	struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev);  	struct iio_dev *indio_dev = NULL; -	bool has_ts = false;  	int ret;  	int irq;  	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct exynos_adc)); -	if (!indio_dev) { -		dev_err(&pdev->dev, "failed allocating iio device\n"); +	if (!indio_dev)  		return -ENOMEM; -	}  	info = iio_priv(indio_dev); @@ -826,27 +584,10 @@ static int exynos_adc_probe(struct platform_device *pdev)  		}  	} -	/* leave out any TS related code if unreachable */ -	if (IS_REACHABLE(CONFIG_INPUT)) { -		has_ts = of_property_read_bool(pdev->dev.of_node, -					       "has-touchscreen") || pdata; -	} -  	irq = platform_get_irq(pdev, 0);  	if (irq < 0)  		return irq;  	info->irq = irq; - -	if (has_ts) { -		irq = platform_get_irq(pdev, 1); -		if (irq == -EPROBE_DEFER) -			return irq; - -		info->tsirq = irq; -	} else { -		info->tsirq = -1; -	} -  	info->dev = &pdev->dev;  	init_completion(&info->completion); @@ -910,16 +651,6 @@ static int exynos_adc_probe(struct platform_device *pdev)  	if (info->data->init_hw)  		info->data->init_hw(info); -	if (pdata) -		info->delay = pdata->delay; -	else -		info->delay = 10000; - -	if (has_ts) -		ret = exynos_adc_ts_init(info); -	if (ret) -		goto err_iio; -  	ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);  	if (ret < 0) {  		dev_err(&pdev->dev, "failed adding child nodes\n"); @@ -931,11 +662,6 @@ static int exynos_adc_probe(struct platform_device *pdev)  err_of_populate:  	device_for_each_child(&indio_dev->dev, NULL,  				exynos_adc_remove_devices); -	if (has_ts) { -		input_unregister_device(info->input); -		free_irq(info->tsirq, info); -	} -err_iio:  	iio_device_unregister(indio_dev);  err_irq:  	free_irq(info->irq, info); @@ -955,10 +681,6 @@ static void exynos_adc_remove(struct platform_device *pdev)  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);  	struct exynos_adc *info = iio_priv(indio_dev); -	if (IS_REACHABLE(CONFIG_INPUT) && info->input) { -		free_irq(info->tsirq, info); -		input_unregister_device(info->input); -	}  	device_for_each_child(&indio_dev->dev, NULL,  				exynos_adc_remove_devices);  	iio_device_unregister(indio_dev);  | 
