18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * ST Microelectronics MFD: stmpe's driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) ST-Ericsson SA 2010
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/err.h>
118c2ecf20Sopenharmony_ci#include <linux/gpio.h>
128c2ecf20Sopenharmony_ci#include <linux/export.h>
138c2ecf20Sopenharmony_ci#include <linux/kernel.h>
148c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
158c2ecf20Sopenharmony_ci#include <linux/irq.h>
168c2ecf20Sopenharmony_ci#include <linux/irqdomain.h>
178c2ecf20Sopenharmony_ci#include <linux/of.h>
188c2ecf20Sopenharmony_ci#include <linux/of_gpio.h>
198c2ecf20Sopenharmony_ci#include <linux/pm.h>
208c2ecf20Sopenharmony_ci#include <linux/slab.h>
218c2ecf20Sopenharmony_ci#include <linux/mfd/core.h>
228c2ecf20Sopenharmony_ci#include <linux/delay.h>
238c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
248c2ecf20Sopenharmony_ci#include "stmpe.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/**
278c2ecf20Sopenharmony_ci * struct stmpe_platform_data - STMPE platform data
288c2ecf20Sopenharmony_ci * @id: device id to distinguish between multiple STMPEs on the same board
298c2ecf20Sopenharmony_ci * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*)
308c2ecf20Sopenharmony_ci * @irq_trigger: IRQ trigger to use for the interrupt to the host
318c2ecf20Sopenharmony_ci * @autosleep: bool to enable/disable stmpe autosleep
328c2ecf20Sopenharmony_ci * @autosleep_timeout: inactivity timeout in milliseconds for autosleep
338c2ecf20Sopenharmony_ci * @irq_over_gpio: true if gpio is used to get irq
348c2ecf20Sopenharmony_ci * @irq_gpio: gpio number over which irq will be requested (significant only if
358c2ecf20Sopenharmony_ci *	      irq_over_gpio is true)
368c2ecf20Sopenharmony_ci */
378c2ecf20Sopenharmony_cistruct stmpe_platform_data {
388c2ecf20Sopenharmony_ci	int id;
398c2ecf20Sopenharmony_ci	unsigned int blocks;
408c2ecf20Sopenharmony_ci	unsigned int irq_trigger;
418c2ecf20Sopenharmony_ci	bool autosleep;
428c2ecf20Sopenharmony_ci	bool irq_over_gpio;
438c2ecf20Sopenharmony_ci	int irq_gpio;
448c2ecf20Sopenharmony_ci	int autosleep_timeout;
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	return stmpe->variant->enable(stmpe, blocks, true);
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic int __stmpe_disable(struct stmpe *stmpe, unsigned int blocks)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	return stmpe->variant->enable(stmpe, blocks, false);
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic int __stmpe_reg_read(struct stmpe *stmpe, u8 reg)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	int ret;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	ret = stmpe->ci->read_byte(stmpe, reg);
628c2ecf20Sopenharmony_ci	if (ret < 0)
638c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "failed to read reg %#x: %d\n", reg, ret);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	return ret;
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	int ret;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	ret = stmpe->ci->write_byte(stmpe, reg, val);
778c2ecf20Sopenharmony_ci	if (ret < 0)
788c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "failed to write reg %#x: %d\n", reg, ret);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	return ret;
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistatic int __stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	int ret;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	ret = __stmpe_reg_read(stmpe, reg);
888c2ecf20Sopenharmony_ci	if (ret < 0)
898c2ecf20Sopenharmony_ci		return ret;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	ret &= ~mask;
928c2ecf20Sopenharmony_ci	ret |= val;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return __stmpe_reg_write(stmpe, reg, ret);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length,
988c2ecf20Sopenharmony_ci			      u8 *values)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	int ret;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	ret = stmpe->ci->read_block(stmpe, reg, length, values);
1038c2ecf20Sopenharmony_ci	if (ret < 0)
1048c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "failed to read regs %#x: %d\n", reg, ret);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret);
1078c2ecf20Sopenharmony_ci	stmpe_dump_bytes("stmpe rd: ", values, length);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	return ret;
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
1138c2ecf20Sopenharmony_ci			const u8 *values)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	int ret;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length);
1188c2ecf20Sopenharmony_ci	stmpe_dump_bytes("stmpe wr: ", values, length);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	ret = stmpe->ci->write_block(stmpe, reg, length, values);
1218c2ecf20Sopenharmony_ci	if (ret < 0)
1228c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "failed to write regs %#x: %d\n", reg, ret);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	return ret;
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci/**
1288c2ecf20Sopenharmony_ci * stmpe_enable - enable blocks on an STMPE device
1298c2ecf20Sopenharmony_ci * @stmpe:	Device to work on
1308c2ecf20Sopenharmony_ci * @blocks:	Mask of blocks (enum stmpe_block values) to enable
1318c2ecf20Sopenharmony_ci */
1328c2ecf20Sopenharmony_ciint stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	int ret;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
1378c2ecf20Sopenharmony_ci	ret = __stmpe_enable(stmpe, blocks);
1388c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	return ret;
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_enable);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/**
1458c2ecf20Sopenharmony_ci * stmpe_disable - disable blocks on an STMPE device
1468c2ecf20Sopenharmony_ci * @stmpe:	Device to work on
1478c2ecf20Sopenharmony_ci * @blocks:	Mask of blocks (enum stmpe_block values) to enable
1488c2ecf20Sopenharmony_ci */
1498c2ecf20Sopenharmony_ciint stmpe_disable(struct stmpe *stmpe, unsigned int blocks)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	int ret;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
1548c2ecf20Sopenharmony_ci	ret = __stmpe_disable(stmpe, blocks);
1558c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	return ret;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_disable);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci/**
1628c2ecf20Sopenharmony_ci * stmpe_reg_read() - read a single STMPE register
1638c2ecf20Sopenharmony_ci * @stmpe:	Device to read from
1648c2ecf20Sopenharmony_ci * @reg:	Register to read
1658c2ecf20Sopenharmony_ci */
1668c2ecf20Sopenharmony_ciint stmpe_reg_read(struct stmpe *stmpe, u8 reg)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	int ret;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
1718c2ecf20Sopenharmony_ci	ret = __stmpe_reg_read(stmpe, reg);
1728c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	return ret;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_reg_read);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci/**
1798c2ecf20Sopenharmony_ci * stmpe_reg_write() - write a single STMPE register
1808c2ecf20Sopenharmony_ci * @stmpe:	Device to write to
1818c2ecf20Sopenharmony_ci * @reg:	Register to write
1828c2ecf20Sopenharmony_ci * @val:	Value to write
1838c2ecf20Sopenharmony_ci */
1848c2ecf20Sopenharmony_ciint stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	int ret;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
1898c2ecf20Sopenharmony_ci	ret = __stmpe_reg_write(stmpe, reg, val);
1908c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	return ret;
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_reg_write);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci/**
1978c2ecf20Sopenharmony_ci * stmpe_set_bits() - set the value of a bitfield in a STMPE register
1988c2ecf20Sopenharmony_ci * @stmpe:	Device to write to
1998c2ecf20Sopenharmony_ci * @reg:	Register to write
2008c2ecf20Sopenharmony_ci * @mask:	Mask of bits to set
2018c2ecf20Sopenharmony_ci * @val:	Value to set
2028c2ecf20Sopenharmony_ci */
2038c2ecf20Sopenharmony_ciint stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	int ret;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
2088c2ecf20Sopenharmony_ci	ret = __stmpe_set_bits(stmpe, reg, mask, val);
2098c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	return ret;
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_set_bits);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci/**
2168c2ecf20Sopenharmony_ci * stmpe_block_read() - read multiple STMPE registers
2178c2ecf20Sopenharmony_ci * @stmpe:	Device to read from
2188c2ecf20Sopenharmony_ci * @reg:	First register
2198c2ecf20Sopenharmony_ci * @length:	Number of registers
2208c2ecf20Sopenharmony_ci * @values:	Buffer to write to
2218c2ecf20Sopenharmony_ci */
2228c2ecf20Sopenharmony_ciint stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	int ret;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
2278c2ecf20Sopenharmony_ci	ret = __stmpe_block_read(stmpe, reg, length, values);
2288c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	return ret;
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_block_read);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci/**
2358c2ecf20Sopenharmony_ci * stmpe_block_write() - write multiple STMPE registers
2368c2ecf20Sopenharmony_ci * @stmpe:	Device to write to
2378c2ecf20Sopenharmony_ci * @reg:	First register
2388c2ecf20Sopenharmony_ci * @length:	Number of registers
2398c2ecf20Sopenharmony_ci * @values:	Values to write
2408c2ecf20Sopenharmony_ci */
2418c2ecf20Sopenharmony_ciint stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length,
2428c2ecf20Sopenharmony_ci		      const u8 *values)
2438c2ecf20Sopenharmony_ci{
2448c2ecf20Sopenharmony_ci	int ret;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
2478c2ecf20Sopenharmony_ci	ret = __stmpe_block_write(stmpe, reg, length, values);
2488c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	return ret;
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_block_write);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci/**
2558c2ecf20Sopenharmony_ci * stmpe_set_altfunc()- set the alternate function for STMPE pins
2568c2ecf20Sopenharmony_ci * @stmpe:	Device to configure
2578c2ecf20Sopenharmony_ci * @pins:	Bitmask of pins to affect
2588c2ecf20Sopenharmony_ci * @block:	block to enable alternate functions for
2598c2ecf20Sopenharmony_ci *
2608c2ecf20Sopenharmony_ci * @pins is assumed to have a bit set for each of the bits whose alternate
2618c2ecf20Sopenharmony_ci * function is to be changed, numbered according to the GPIOXY numbers.
2628c2ecf20Sopenharmony_ci *
2638c2ecf20Sopenharmony_ci * If the GPIO module is not enabled, this function automatically enables it in
2648c2ecf20Sopenharmony_ci * order to perform the change.
2658c2ecf20Sopenharmony_ci */
2668c2ecf20Sopenharmony_ciint stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	struct stmpe_variant_info *variant = stmpe->variant;
2698c2ecf20Sopenharmony_ci	u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB];
2708c2ecf20Sopenharmony_ci	int af_bits = variant->af_bits;
2718c2ecf20Sopenharmony_ci	int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8);
2728c2ecf20Sopenharmony_ci	int mask = (1 << af_bits) - 1;
2738c2ecf20Sopenharmony_ci	u8 regs[8];
2748c2ecf20Sopenharmony_ci	int af, afperreg, ret;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	if (!variant->get_altfunc)
2778c2ecf20Sopenharmony_ci		return 0;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	afperreg = 8 / af_bits;
2808c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO);
2838c2ecf20Sopenharmony_ci	if (ret < 0)
2848c2ecf20Sopenharmony_ci		goto out;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	ret = __stmpe_block_read(stmpe, regaddr, numregs, regs);
2878c2ecf20Sopenharmony_ci	if (ret < 0)
2888c2ecf20Sopenharmony_ci		goto out;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	af = variant->get_altfunc(stmpe, block);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	while (pins) {
2938c2ecf20Sopenharmony_ci		int pin = __ffs(pins);
2948c2ecf20Sopenharmony_ci		int regoffset = numregs - (pin / afperreg) - 1;
2958c2ecf20Sopenharmony_ci		int pos = (pin % afperreg) * (8 / afperreg);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci		regs[regoffset] &= ~(mask << pos);
2988c2ecf20Sopenharmony_ci		regs[regoffset] |= af << pos;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci		pins &= ~(1 << pin);
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	ret = __stmpe_block_write(stmpe, regaddr, numregs, regs);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ciout:
3068c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
3078c2ecf20Sopenharmony_ci	return ret;
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_set_altfunc);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci/*
3128c2ecf20Sopenharmony_ci * GPIO (all variants)
3138c2ecf20Sopenharmony_ci */
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic struct resource stmpe_gpio_resources[] = {
3168c2ecf20Sopenharmony_ci	/* Start and end filled dynamically */
3178c2ecf20Sopenharmony_ci	{
3188c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
3198c2ecf20Sopenharmony_ci	},
3208c2ecf20Sopenharmony_ci};
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic const struct mfd_cell stmpe_gpio_cell = {
3238c2ecf20Sopenharmony_ci	.name		= "stmpe-gpio",
3248c2ecf20Sopenharmony_ci	.of_compatible	= "st,stmpe-gpio",
3258c2ecf20Sopenharmony_ci	.resources	= stmpe_gpio_resources,
3268c2ecf20Sopenharmony_ci	.num_resources	= ARRAY_SIZE(stmpe_gpio_resources),
3278c2ecf20Sopenharmony_ci};
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic const struct mfd_cell stmpe_gpio_cell_noirq = {
3308c2ecf20Sopenharmony_ci	.name		= "stmpe-gpio",
3318c2ecf20Sopenharmony_ci	.of_compatible	= "st,stmpe-gpio",
3328c2ecf20Sopenharmony_ci	/* gpio cell resources consist of an irq only so no resources here */
3338c2ecf20Sopenharmony_ci};
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci/*
3368c2ecf20Sopenharmony_ci * Keypad (1601, 2401, 2403)
3378c2ecf20Sopenharmony_ci */
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic struct resource stmpe_keypad_resources[] = {
3408c2ecf20Sopenharmony_ci	{
3418c2ecf20Sopenharmony_ci		.name	= "KEYPAD",
3428c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
3438c2ecf20Sopenharmony_ci	},
3448c2ecf20Sopenharmony_ci	{
3458c2ecf20Sopenharmony_ci		.name	= "KEYPAD_OVER",
3468c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
3478c2ecf20Sopenharmony_ci	},
3488c2ecf20Sopenharmony_ci};
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic const struct mfd_cell stmpe_keypad_cell = {
3518c2ecf20Sopenharmony_ci	.name		= "stmpe-keypad",
3528c2ecf20Sopenharmony_ci	.of_compatible  = "st,stmpe-keypad",
3538c2ecf20Sopenharmony_ci	.resources	= stmpe_keypad_resources,
3548c2ecf20Sopenharmony_ci	.num_resources	= ARRAY_SIZE(stmpe_keypad_resources),
3558c2ecf20Sopenharmony_ci};
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci/*
3588c2ecf20Sopenharmony_ci * PWM (1601, 2401, 2403)
3598c2ecf20Sopenharmony_ci */
3608c2ecf20Sopenharmony_cistatic struct resource stmpe_pwm_resources[] = {
3618c2ecf20Sopenharmony_ci	{
3628c2ecf20Sopenharmony_ci		.name	= "PWM0",
3638c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
3648c2ecf20Sopenharmony_ci	},
3658c2ecf20Sopenharmony_ci	{
3668c2ecf20Sopenharmony_ci		.name	= "PWM1",
3678c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
3688c2ecf20Sopenharmony_ci	},
3698c2ecf20Sopenharmony_ci	{
3708c2ecf20Sopenharmony_ci		.name	= "PWM2",
3718c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
3728c2ecf20Sopenharmony_ci	},
3738c2ecf20Sopenharmony_ci};
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_cistatic const struct mfd_cell stmpe_pwm_cell = {
3768c2ecf20Sopenharmony_ci	.name		= "stmpe-pwm",
3778c2ecf20Sopenharmony_ci	.of_compatible  = "st,stmpe-pwm",
3788c2ecf20Sopenharmony_ci	.resources	= stmpe_pwm_resources,
3798c2ecf20Sopenharmony_ci	.num_resources	= ARRAY_SIZE(stmpe_pwm_resources),
3808c2ecf20Sopenharmony_ci};
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci/*
3838c2ecf20Sopenharmony_ci * STMPE801
3848c2ecf20Sopenharmony_ci */
3858c2ecf20Sopenharmony_cistatic const u8 stmpe801_regs[] = {
3868c2ecf20Sopenharmony_ci	[STMPE_IDX_CHIP_ID]	= STMPE801_REG_CHIP_ID,
3878c2ecf20Sopenharmony_ci	[STMPE_IDX_ICR_LSB]	= STMPE801_REG_SYS_CTRL,
3888c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_LSB]	= STMPE801_REG_GPIO_MP_STA,
3898c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_LSB]	= STMPE801_REG_GPIO_SET_PIN,
3908c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_LSB]	= STMPE801_REG_GPIO_SET_PIN,
3918c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_LSB]	= STMPE801_REG_GPIO_DIR,
3928c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_LSB] = STMPE801_REG_GPIO_INT_EN,
3938c2ecf20Sopenharmony_ci	[STMPE_IDX_ISGPIOR_MSB] = STMPE801_REG_GPIO_INT_STA,
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci};
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic struct stmpe_variant_block stmpe801_blocks[] = {
3988c2ecf20Sopenharmony_ci	{
3998c2ecf20Sopenharmony_ci		.cell	= &stmpe_gpio_cell,
4008c2ecf20Sopenharmony_ci		.irq	= 0,
4018c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_GPIO,
4028c2ecf20Sopenharmony_ci	},
4038c2ecf20Sopenharmony_ci};
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_cistatic struct stmpe_variant_block stmpe801_blocks_noirq[] = {
4068c2ecf20Sopenharmony_ci	{
4078c2ecf20Sopenharmony_ci		.cell	= &stmpe_gpio_cell_noirq,
4088c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_GPIO,
4098c2ecf20Sopenharmony_ci	},
4108c2ecf20Sopenharmony_ci};
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cistatic int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks,
4138c2ecf20Sopenharmony_ci			   bool enable)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_GPIO)
4168c2ecf20Sopenharmony_ci		return 0;
4178c2ecf20Sopenharmony_ci	else
4188c2ecf20Sopenharmony_ci		return -EINVAL;
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe801 = {
4228c2ecf20Sopenharmony_ci	.name		= "stmpe801",
4238c2ecf20Sopenharmony_ci	.id_val		= STMPE801_ID,
4248c2ecf20Sopenharmony_ci	.id_mask	= 0xffff,
4258c2ecf20Sopenharmony_ci	.num_gpios	= 8,
4268c2ecf20Sopenharmony_ci	.regs		= stmpe801_regs,
4278c2ecf20Sopenharmony_ci	.blocks		= stmpe801_blocks,
4288c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe801_blocks),
4298c2ecf20Sopenharmony_ci	.num_irqs	= STMPE801_NR_INTERNAL_IRQS,
4308c2ecf20Sopenharmony_ci	.enable		= stmpe801_enable,
4318c2ecf20Sopenharmony_ci};
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe801_noirq = {
4348c2ecf20Sopenharmony_ci	.name		= "stmpe801",
4358c2ecf20Sopenharmony_ci	.id_val		= STMPE801_ID,
4368c2ecf20Sopenharmony_ci	.id_mask	= 0xffff,
4378c2ecf20Sopenharmony_ci	.num_gpios	= 8,
4388c2ecf20Sopenharmony_ci	.regs		= stmpe801_regs,
4398c2ecf20Sopenharmony_ci	.blocks		= stmpe801_blocks_noirq,
4408c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe801_blocks_noirq),
4418c2ecf20Sopenharmony_ci	.enable		= stmpe801_enable,
4428c2ecf20Sopenharmony_ci};
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci/*
4458c2ecf20Sopenharmony_ci * Touchscreen (STMPE811 or STMPE610)
4468c2ecf20Sopenharmony_ci */
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_cistatic struct resource stmpe_ts_resources[] = {
4498c2ecf20Sopenharmony_ci	{
4508c2ecf20Sopenharmony_ci		.name	= "TOUCH_DET",
4518c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
4528c2ecf20Sopenharmony_ci	},
4538c2ecf20Sopenharmony_ci	{
4548c2ecf20Sopenharmony_ci		.name	= "FIFO_TH",
4558c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
4568c2ecf20Sopenharmony_ci	},
4578c2ecf20Sopenharmony_ci};
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_cistatic const struct mfd_cell stmpe_ts_cell = {
4608c2ecf20Sopenharmony_ci	.name		= "stmpe-ts",
4618c2ecf20Sopenharmony_ci	.of_compatible	= "st,stmpe-ts",
4628c2ecf20Sopenharmony_ci	.resources	= stmpe_ts_resources,
4638c2ecf20Sopenharmony_ci	.num_resources	= ARRAY_SIZE(stmpe_ts_resources),
4648c2ecf20Sopenharmony_ci};
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci/*
4678c2ecf20Sopenharmony_ci * ADC (STMPE811)
4688c2ecf20Sopenharmony_ci */
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_cistatic struct resource stmpe_adc_resources[] = {
4718c2ecf20Sopenharmony_ci	{
4728c2ecf20Sopenharmony_ci		.name	= "STMPE_TEMP_SENS",
4738c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
4748c2ecf20Sopenharmony_ci	},
4758c2ecf20Sopenharmony_ci	{
4768c2ecf20Sopenharmony_ci		.name	= "STMPE_ADC",
4778c2ecf20Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
4788c2ecf20Sopenharmony_ci	},
4798c2ecf20Sopenharmony_ci};
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic const struct mfd_cell stmpe_adc_cell = {
4828c2ecf20Sopenharmony_ci	.name		= "stmpe-adc",
4838c2ecf20Sopenharmony_ci	.of_compatible	= "st,stmpe-adc",
4848c2ecf20Sopenharmony_ci	.resources	= stmpe_adc_resources,
4858c2ecf20Sopenharmony_ci	.num_resources	= ARRAY_SIZE(stmpe_adc_resources),
4868c2ecf20Sopenharmony_ci};
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci/*
4898c2ecf20Sopenharmony_ci * STMPE811 or STMPE610
4908c2ecf20Sopenharmony_ci */
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_cistatic const u8 stmpe811_regs[] = {
4938c2ecf20Sopenharmony_ci	[STMPE_IDX_CHIP_ID]	= STMPE811_REG_CHIP_ID,
4948c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL]	= STMPE811_REG_SYS_CTRL,
4958c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL2]	= STMPE811_REG_SYS_CTRL2,
4968c2ecf20Sopenharmony_ci	[STMPE_IDX_ICR_LSB]	= STMPE811_REG_INT_CTRL,
4978c2ecf20Sopenharmony_ci	[STMPE_IDX_IER_LSB]	= STMPE811_REG_INT_EN,
4988c2ecf20Sopenharmony_ci	[STMPE_IDX_ISR_MSB]	= STMPE811_REG_INT_STA,
4998c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_LSB]	= STMPE811_REG_GPIO_MP_STA,
5008c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_LSB]	= STMPE811_REG_GPIO_SET_PIN,
5018c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_LSB]	= STMPE811_REG_GPIO_CLR_PIN,
5028c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_LSB]	= STMPE811_REG_GPIO_DIR,
5038c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_LSB]	= STMPE811_REG_GPIO_RE,
5048c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_LSB]	= STMPE811_REG_GPIO_FE,
5058c2ecf20Sopenharmony_ci	[STMPE_IDX_GPAFR_U_MSB]	= STMPE811_REG_GPIO_AF,
5068c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_LSB]	= STMPE811_REG_GPIO_INT_EN,
5078c2ecf20Sopenharmony_ci	[STMPE_IDX_ISGPIOR_MSB]	= STMPE811_REG_GPIO_INT_STA,
5088c2ecf20Sopenharmony_ci	[STMPE_IDX_GPEDR_LSB]	= STMPE811_REG_GPIO_ED,
5098c2ecf20Sopenharmony_ci};
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic struct stmpe_variant_block stmpe811_blocks[] = {
5128c2ecf20Sopenharmony_ci	{
5138c2ecf20Sopenharmony_ci		.cell	= &stmpe_gpio_cell,
5148c2ecf20Sopenharmony_ci		.irq	= STMPE811_IRQ_GPIOC,
5158c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_GPIO,
5168c2ecf20Sopenharmony_ci	},
5178c2ecf20Sopenharmony_ci	{
5188c2ecf20Sopenharmony_ci		.cell	= &stmpe_ts_cell,
5198c2ecf20Sopenharmony_ci		.irq	= STMPE811_IRQ_TOUCH_DET,
5208c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_TOUCHSCREEN,
5218c2ecf20Sopenharmony_ci	},
5228c2ecf20Sopenharmony_ci	{
5238c2ecf20Sopenharmony_ci		.cell	= &stmpe_adc_cell,
5248c2ecf20Sopenharmony_ci		.irq	= STMPE811_IRQ_TEMP_SENS,
5258c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_ADC,
5268c2ecf20Sopenharmony_ci	},
5278c2ecf20Sopenharmony_ci};
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_cistatic int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
5308c2ecf20Sopenharmony_ci			   bool enable)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	unsigned int mask = 0;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_GPIO)
5358c2ecf20Sopenharmony_ci		mask |= STMPE811_SYS_CTRL2_GPIO_OFF;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_ADC)
5388c2ecf20Sopenharmony_ci		mask |= STMPE811_SYS_CTRL2_ADC_OFF;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_TOUCHSCREEN)
5418c2ecf20Sopenharmony_ci		mask |= STMPE811_SYS_CTRL2_TSC_OFF;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2], mask,
5448c2ecf20Sopenharmony_ci				enable ? 0 : mask);
5458c2ecf20Sopenharmony_ci}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ciint stmpe811_adc_common_init(struct stmpe *stmpe)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	int ret;
5508c2ecf20Sopenharmony_ci	u8 adc_ctrl1, adc_ctrl1_mask;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) |
5538c2ecf20Sopenharmony_ci		    STMPE_MOD_12B(stmpe->mod_12b) |
5548c2ecf20Sopenharmony_ci		    STMPE_REF_SEL(stmpe->ref_sel);
5558c2ecf20Sopenharmony_ci	adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) |
5568c2ecf20Sopenharmony_ci			 STMPE_REF_SEL(0xff);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL1,
5598c2ecf20Sopenharmony_ci			adc_ctrl1_mask, adc_ctrl1);
5608c2ecf20Sopenharmony_ci	if (ret) {
5618c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "Could not setup ADC\n");
5628c2ecf20Sopenharmony_ci		return ret;
5638c2ecf20Sopenharmony_ci	}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL2,
5668c2ecf20Sopenharmony_ci			STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq));
5678c2ecf20Sopenharmony_ci	if (ret) {
5688c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "Could not setup ADC\n");
5698c2ecf20Sopenharmony_ci		return ret;
5708c2ecf20Sopenharmony_ci	}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	return 0;
5738c2ecf20Sopenharmony_ci}
5748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe811_adc_common_init);
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_cistatic int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
5778c2ecf20Sopenharmony_ci{
5788c2ecf20Sopenharmony_ci	/* 0 for touchscreen, 1 for GPIO */
5798c2ecf20Sopenharmony_ci	return block != STMPE_BLOCK_TOUCHSCREEN;
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe811 = {
5838c2ecf20Sopenharmony_ci	.name		= "stmpe811",
5848c2ecf20Sopenharmony_ci	.id_val		= 0x0811,
5858c2ecf20Sopenharmony_ci	.id_mask	= 0xffff,
5868c2ecf20Sopenharmony_ci	.num_gpios	= 8,
5878c2ecf20Sopenharmony_ci	.af_bits	= 1,
5888c2ecf20Sopenharmony_ci	.regs		= stmpe811_regs,
5898c2ecf20Sopenharmony_ci	.blocks		= stmpe811_blocks,
5908c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe811_blocks),
5918c2ecf20Sopenharmony_ci	.num_irqs	= STMPE811_NR_INTERNAL_IRQS,
5928c2ecf20Sopenharmony_ci	.enable		= stmpe811_enable,
5938c2ecf20Sopenharmony_ci	.get_altfunc	= stmpe811_get_altfunc,
5948c2ecf20Sopenharmony_ci};
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci/* Similar to 811, except number of gpios */
5978c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe610 = {
5988c2ecf20Sopenharmony_ci	.name		= "stmpe610",
5998c2ecf20Sopenharmony_ci	.id_val		= 0x0811,
6008c2ecf20Sopenharmony_ci	.id_mask	= 0xffff,
6018c2ecf20Sopenharmony_ci	.num_gpios	= 6,
6028c2ecf20Sopenharmony_ci	.af_bits	= 1,
6038c2ecf20Sopenharmony_ci	.regs		= stmpe811_regs,
6048c2ecf20Sopenharmony_ci	.blocks		= stmpe811_blocks,
6058c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe811_blocks),
6068c2ecf20Sopenharmony_ci	.num_irqs	= STMPE811_NR_INTERNAL_IRQS,
6078c2ecf20Sopenharmony_ci	.enable		= stmpe811_enable,
6088c2ecf20Sopenharmony_ci	.get_altfunc	= stmpe811_get_altfunc,
6098c2ecf20Sopenharmony_ci};
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci/*
6128c2ecf20Sopenharmony_ci * STMPE1600
6138c2ecf20Sopenharmony_ci * Compared to all others STMPE variant, LSB and MSB regs are located in this
6148c2ecf20Sopenharmony_ci * order :	LSB   addr
6158c2ecf20Sopenharmony_ci *		MSB   addr + 1
6168c2ecf20Sopenharmony_ci * As there is only 2 * 8bits registers for GPMR/GPSR/IEGPIOPR, CSB index is MSB registers
6178c2ecf20Sopenharmony_ci */
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic const u8 stmpe1600_regs[] = {
6208c2ecf20Sopenharmony_ci	[STMPE_IDX_CHIP_ID]	= STMPE1600_REG_CHIP_ID,
6218c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL]	= STMPE1600_REG_SYS_CTRL,
6228c2ecf20Sopenharmony_ci	[STMPE_IDX_ICR_LSB]	= STMPE1600_REG_SYS_CTRL,
6238c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_LSB]	= STMPE1600_REG_GPMR_LSB,
6248c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_CSB]	= STMPE1600_REG_GPMR_MSB,
6258c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_LSB]	= STMPE1600_REG_GPSR_LSB,
6268c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_CSB]	= STMPE1600_REG_GPSR_MSB,
6278c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_LSB]	= STMPE1600_REG_GPSR_LSB,
6288c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_CSB]	= STMPE1600_REG_GPSR_MSB,
6298c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_LSB]	= STMPE1600_REG_GPDR_LSB,
6308c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_CSB]	= STMPE1600_REG_GPDR_MSB,
6318c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1600_REG_IEGPIOR_LSB,
6328c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_CSB]	= STMPE1600_REG_IEGPIOR_MSB,
6338c2ecf20Sopenharmony_ci	[STMPE_IDX_ISGPIOR_LSB]	= STMPE1600_REG_ISGPIOR_LSB,
6348c2ecf20Sopenharmony_ci};
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cistatic struct stmpe_variant_block stmpe1600_blocks[] = {
6378c2ecf20Sopenharmony_ci	{
6388c2ecf20Sopenharmony_ci		.cell	= &stmpe_gpio_cell,
6398c2ecf20Sopenharmony_ci		.irq	= 0,
6408c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_GPIO,
6418c2ecf20Sopenharmony_ci	},
6428c2ecf20Sopenharmony_ci};
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_cistatic int stmpe1600_enable(struct stmpe *stmpe, unsigned int blocks,
6458c2ecf20Sopenharmony_ci			   bool enable)
6468c2ecf20Sopenharmony_ci{
6478c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_GPIO)
6488c2ecf20Sopenharmony_ci		return 0;
6498c2ecf20Sopenharmony_ci	else
6508c2ecf20Sopenharmony_ci		return -EINVAL;
6518c2ecf20Sopenharmony_ci}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe1600 = {
6548c2ecf20Sopenharmony_ci	.name		= "stmpe1600",
6558c2ecf20Sopenharmony_ci	.id_val		= STMPE1600_ID,
6568c2ecf20Sopenharmony_ci	.id_mask	= 0xffff,
6578c2ecf20Sopenharmony_ci	.num_gpios	= 16,
6588c2ecf20Sopenharmony_ci	.af_bits	= 0,
6598c2ecf20Sopenharmony_ci	.regs		= stmpe1600_regs,
6608c2ecf20Sopenharmony_ci	.blocks		= stmpe1600_blocks,
6618c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe1600_blocks),
6628c2ecf20Sopenharmony_ci	.num_irqs	= STMPE1600_NR_INTERNAL_IRQS,
6638c2ecf20Sopenharmony_ci	.enable		= stmpe1600_enable,
6648c2ecf20Sopenharmony_ci};
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci/*
6678c2ecf20Sopenharmony_ci * STMPE1601
6688c2ecf20Sopenharmony_ci */
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_cistatic const u8 stmpe1601_regs[] = {
6718c2ecf20Sopenharmony_ci	[STMPE_IDX_CHIP_ID]	= STMPE1601_REG_CHIP_ID,
6728c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL]	= STMPE1601_REG_SYS_CTRL,
6738c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL2]	= STMPE1601_REG_SYS_CTRL2,
6748c2ecf20Sopenharmony_ci	[STMPE_IDX_ICR_LSB]	= STMPE1601_REG_ICR_LSB,
6758c2ecf20Sopenharmony_ci	[STMPE_IDX_IER_MSB]	= STMPE1601_REG_IER_MSB,
6768c2ecf20Sopenharmony_ci	[STMPE_IDX_IER_LSB]	= STMPE1601_REG_IER_LSB,
6778c2ecf20Sopenharmony_ci	[STMPE_IDX_ISR_MSB]	= STMPE1601_REG_ISR_MSB,
6788c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_LSB]	= STMPE1601_REG_GPIO_MP_LSB,
6798c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_CSB]	= STMPE1601_REG_GPIO_MP_MSB,
6808c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_LSB]	= STMPE1601_REG_GPIO_SET_LSB,
6818c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_CSB]	= STMPE1601_REG_GPIO_SET_MSB,
6828c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_LSB]	= STMPE1601_REG_GPIO_CLR_LSB,
6838c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_CSB]	= STMPE1601_REG_GPIO_CLR_MSB,
6848c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_LSB]	= STMPE1601_REG_GPIO_SET_DIR_LSB,
6858c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_CSB]	= STMPE1601_REG_GPIO_SET_DIR_MSB,
6868c2ecf20Sopenharmony_ci	[STMPE_IDX_GPEDR_LSB]	= STMPE1601_REG_GPIO_ED_LSB,
6878c2ecf20Sopenharmony_ci	[STMPE_IDX_GPEDR_CSB]	= STMPE1601_REG_GPIO_ED_MSB,
6888c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_LSB]	= STMPE1601_REG_GPIO_RE_LSB,
6898c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_CSB]	= STMPE1601_REG_GPIO_RE_MSB,
6908c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_LSB]	= STMPE1601_REG_GPIO_FE_LSB,
6918c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_CSB]	= STMPE1601_REG_GPIO_FE_MSB,
6928c2ecf20Sopenharmony_ci	[STMPE_IDX_GPPUR_LSB]	= STMPE1601_REG_GPIO_PU_LSB,
6938c2ecf20Sopenharmony_ci	[STMPE_IDX_GPAFR_U_MSB]	= STMPE1601_REG_GPIO_AF_U_MSB,
6948c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1601_REG_INT_EN_GPIO_MASK_LSB,
6958c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_CSB]	= STMPE1601_REG_INT_EN_GPIO_MASK_MSB,
6968c2ecf20Sopenharmony_ci	[STMPE_IDX_ISGPIOR_MSB]	= STMPE1601_REG_INT_STA_GPIO_MSB,
6978c2ecf20Sopenharmony_ci};
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_cistatic struct stmpe_variant_block stmpe1601_blocks[] = {
7008c2ecf20Sopenharmony_ci	{
7018c2ecf20Sopenharmony_ci		.cell	= &stmpe_gpio_cell,
7028c2ecf20Sopenharmony_ci		.irq	= STMPE1601_IRQ_GPIOC,
7038c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_GPIO,
7048c2ecf20Sopenharmony_ci	},
7058c2ecf20Sopenharmony_ci	{
7068c2ecf20Sopenharmony_ci		.cell	= &stmpe_keypad_cell,
7078c2ecf20Sopenharmony_ci		.irq	= STMPE1601_IRQ_KEYPAD,
7088c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_KEYPAD,
7098c2ecf20Sopenharmony_ci	},
7108c2ecf20Sopenharmony_ci	{
7118c2ecf20Sopenharmony_ci		.cell	= &stmpe_pwm_cell,
7128c2ecf20Sopenharmony_ci		.irq	= STMPE1601_IRQ_PWM0,
7138c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_PWM,
7148c2ecf20Sopenharmony_ci	},
7158c2ecf20Sopenharmony_ci};
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci/* supported autosleep timeout delay (in msecs) */
7188c2ecf20Sopenharmony_cistatic const int stmpe_autosleep_delay[] = {
7198c2ecf20Sopenharmony_ci	4, 16, 32, 64, 128, 256, 512, 1024,
7208c2ecf20Sopenharmony_ci};
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_cistatic int stmpe_round_timeout(int timeout)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	int i;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) {
7278c2ecf20Sopenharmony_ci		if (stmpe_autosleep_delay[i] >= timeout)
7288c2ecf20Sopenharmony_ci			return i;
7298c2ecf20Sopenharmony_ci	}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	/*
7328c2ecf20Sopenharmony_ci	 * requests for delays longer than supported should not return the
7338c2ecf20Sopenharmony_ci	 * longest supported delay
7348c2ecf20Sopenharmony_ci	 */
7358c2ecf20Sopenharmony_ci	return -EINVAL;
7368c2ecf20Sopenharmony_ci}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_cistatic int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout)
7398c2ecf20Sopenharmony_ci{
7408c2ecf20Sopenharmony_ci	int ret;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	if (!stmpe->variant->enable_autosleep)
7438c2ecf20Sopenharmony_ci		return -ENOSYS;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->lock);
7468c2ecf20Sopenharmony_ci	ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout);
7478c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->lock);
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	return ret;
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci/*
7538c2ecf20Sopenharmony_ci * Both stmpe 1601/2403 support same layout for autosleep
7548c2ecf20Sopenharmony_ci */
7558c2ecf20Sopenharmony_cistatic int stmpe1601_autosleep(struct stmpe *stmpe,
7568c2ecf20Sopenharmony_ci		int autosleep_timeout)
7578c2ecf20Sopenharmony_ci{
7588c2ecf20Sopenharmony_ci	int ret, timeout;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	/* choose the best available timeout */
7618c2ecf20Sopenharmony_ci	timeout = stmpe_round_timeout(autosleep_timeout);
7628c2ecf20Sopenharmony_ci	if (timeout < 0) {
7638c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "invalid timeout\n");
7648c2ecf20Sopenharmony_ci		return timeout;
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2],
7688c2ecf20Sopenharmony_ci			STMPE1601_AUTOSLEEP_TIMEOUT_MASK,
7698c2ecf20Sopenharmony_ci			timeout);
7708c2ecf20Sopenharmony_ci	if (ret < 0)
7718c2ecf20Sopenharmony_ci		return ret;
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2],
7748c2ecf20Sopenharmony_ci			STPME1601_AUTOSLEEP_ENABLE,
7758c2ecf20Sopenharmony_ci			STPME1601_AUTOSLEEP_ENABLE);
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_cistatic int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks,
7798c2ecf20Sopenharmony_ci			    bool enable)
7808c2ecf20Sopenharmony_ci{
7818c2ecf20Sopenharmony_ci	unsigned int mask = 0;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_GPIO)
7848c2ecf20Sopenharmony_ci		mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO;
7858c2ecf20Sopenharmony_ci	else
7868c2ecf20Sopenharmony_ci		mask &= ~STMPE1601_SYS_CTRL_ENABLE_GPIO;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_KEYPAD)
7898c2ecf20Sopenharmony_ci		mask |= STMPE1601_SYS_CTRL_ENABLE_KPC;
7908c2ecf20Sopenharmony_ci	else
7918c2ecf20Sopenharmony_ci		mask &= ~STMPE1601_SYS_CTRL_ENABLE_KPC;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_PWM)
7948c2ecf20Sopenharmony_ci		mask |= STMPE1601_SYS_CTRL_ENABLE_SPWM;
7958c2ecf20Sopenharmony_ci	else
7968c2ecf20Sopenharmony_ci		mask &= ~STMPE1601_SYS_CTRL_ENABLE_SPWM;
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], mask,
7998c2ecf20Sopenharmony_ci				enable ? mask : 0);
8008c2ecf20Sopenharmony_ci}
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_cistatic int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
8038c2ecf20Sopenharmony_ci{
8048c2ecf20Sopenharmony_ci	switch (block) {
8058c2ecf20Sopenharmony_ci	case STMPE_BLOCK_PWM:
8068c2ecf20Sopenharmony_ci		return 2;
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	case STMPE_BLOCK_KEYPAD:
8098c2ecf20Sopenharmony_ci		return 1;
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci	case STMPE_BLOCK_GPIO:
8128c2ecf20Sopenharmony_ci	default:
8138c2ecf20Sopenharmony_ci		return 0;
8148c2ecf20Sopenharmony_ci	}
8158c2ecf20Sopenharmony_ci}
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe1601 = {
8188c2ecf20Sopenharmony_ci	.name		= "stmpe1601",
8198c2ecf20Sopenharmony_ci	.id_val		= 0x0210,
8208c2ecf20Sopenharmony_ci	.id_mask	= 0xfff0,	/* at least 0x0210 and 0x0212 */
8218c2ecf20Sopenharmony_ci	.num_gpios	= 16,
8228c2ecf20Sopenharmony_ci	.af_bits	= 2,
8238c2ecf20Sopenharmony_ci	.regs		= stmpe1601_regs,
8248c2ecf20Sopenharmony_ci	.blocks		= stmpe1601_blocks,
8258c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe1601_blocks),
8268c2ecf20Sopenharmony_ci	.num_irqs	= STMPE1601_NR_INTERNAL_IRQS,
8278c2ecf20Sopenharmony_ci	.enable		= stmpe1601_enable,
8288c2ecf20Sopenharmony_ci	.get_altfunc	= stmpe1601_get_altfunc,
8298c2ecf20Sopenharmony_ci	.enable_autosleep	= stmpe1601_autosleep,
8308c2ecf20Sopenharmony_ci};
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci/*
8338c2ecf20Sopenharmony_ci * STMPE1801
8348c2ecf20Sopenharmony_ci */
8358c2ecf20Sopenharmony_cistatic const u8 stmpe1801_regs[] = {
8368c2ecf20Sopenharmony_ci	[STMPE_IDX_CHIP_ID]	= STMPE1801_REG_CHIP_ID,
8378c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL]	= STMPE1801_REG_SYS_CTRL,
8388c2ecf20Sopenharmony_ci	[STMPE_IDX_ICR_LSB]	= STMPE1801_REG_INT_CTRL_LOW,
8398c2ecf20Sopenharmony_ci	[STMPE_IDX_IER_LSB]	= STMPE1801_REG_INT_EN_MASK_LOW,
8408c2ecf20Sopenharmony_ci	[STMPE_IDX_ISR_LSB]	= STMPE1801_REG_INT_STA_LOW,
8418c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_LSB]	= STMPE1801_REG_GPIO_MP_LOW,
8428c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_CSB]	= STMPE1801_REG_GPIO_MP_MID,
8438c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_MSB]	= STMPE1801_REG_GPIO_MP_HIGH,
8448c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_LSB]	= STMPE1801_REG_GPIO_SET_LOW,
8458c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_CSB]	= STMPE1801_REG_GPIO_SET_MID,
8468c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_MSB]	= STMPE1801_REG_GPIO_SET_HIGH,
8478c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_LSB]	= STMPE1801_REG_GPIO_CLR_LOW,
8488c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_CSB]	= STMPE1801_REG_GPIO_CLR_MID,
8498c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_MSB]	= STMPE1801_REG_GPIO_CLR_HIGH,
8508c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_LSB]	= STMPE1801_REG_GPIO_SET_DIR_LOW,
8518c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_CSB]	= STMPE1801_REG_GPIO_SET_DIR_MID,
8528c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_MSB]	= STMPE1801_REG_GPIO_SET_DIR_HIGH,
8538c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_LSB]	= STMPE1801_REG_GPIO_RE_LOW,
8548c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_CSB]	= STMPE1801_REG_GPIO_RE_MID,
8558c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_MSB]	= STMPE1801_REG_GPIO_RE_HIGH,
8568c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_LSB]	= STMPE1801_REG_GPIO_FE_LOW,
8578c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_CSB]	= STMPE1801_REG_GPIO_FE_MID,
8588c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_MSB]	= STMPE1801_REG_GPIO_FE_HIGH,
8598c2ecf20Sopenharmony_ci	[STMPE_IDX_GPPUR_LSB]	= STMPE1801_REG_GPIO_PULL_UP_LOW,
8608c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_LSB]	= STMPE1801_REG_INT_EN_GPIO_MASK_LOW,
8618c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_CSB]	= STMPE1801_REG_INT_EN_GPIO_MASK_MID,
8628c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_MSB]	= STMPE1801_REG_INT_EN_GPIO_MASK_HIGH,
8638c2ecf20Sopenharmony_ci	[STMPE_IDX_ISGPIOR_MSB]	= STMPE1801_REG_INT_STA_GPIO_HIGH,
8648c2ecf20Sopenharmony_ci};
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_cistatic struct stmpe_variant_block stmpe1801_blocks[] = {
8678c2ecf20Sopenharmony_ci	{
8688c2ecf20Sopenharmony_ci		.cell	= &stmpe_gpio_cell,
8698c2ecf20Sopenharmony_ci		.irq	= STMPE1801_IRQ_GPIOC,
8708c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_GPIO,
8718c2ecf20Sopenharmony_ci	},
8728c2ecf20Sopenharmony_ci	{
8738c2ecf20Sopenharmony_ci		.cell	= &stmpe_keypad_cell,
8748c2ecf20Sopenharmony_ci		.irq	= STMPE1801_IRQ_KEYPAD,
8758c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_KEYPAD,
8768c2ecf20Sopenharmony_ci	},
8778c2ecf20Sopenharmony_ci};
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_cistatic int stmpe1801_enable(struct stmpe *stmpe, unsigned int blocks,
8808c2ecf20Sopenharmony_ci			    bool enable)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	unsigned int mask = 0;
8838c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_GPIO)
8848c2ecf20Sopenharmony_ci		mask |= STMPE1801_MSK_INT_EN_GPIO;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_KEYPAD)
8878c2ecf20Sopenharmony_ci		mask |= STMPE1801_MSK_INT_EN_KPC;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	return __stmpe_set_bits(stmpe, STMPE1801_REG_INT_EN_MASK_LOW, mask,
8908c2ecf20Sopenharmony_ci				enable ? mask : 0);
8918c2ecf20Sopenharmony_ci}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_cistatic int stmpe_reset(struct stmpe *stmpe)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	u16 id_val = stmpe->variant->id_val;
8968c2ecf20Sopenharmony_ci	unsigned long timeout;
8978c2ecf20Sopenharmony_ci	int ret = 0;
8988c2ecf20Sopenharmony_ci	u8 reset_bit;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	if (id_val == STMPE811_ID)
9018c2ecf20Sopenharmony_ci		/* STMPE801 and STMPE610 use bit 1 of SYS_CTRL register */
9028c2ecf20Sopenharmony_ci		reset_bit = STMPE811_SYS_CTRL_RESET;
9038c2ecf20Sopenharmony_ci	else
9048c2ecf20Sopenharmony_ci		/* all other STMPE variant use bit 7 of SYS_CTRL register */
9058c2ecf20Sopenharmony_ci		reset_bit = STMPE_SYS_CTRL_RESET;
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL],
9088c2ecf20Sopenharmony_ci			       reset_bit, reset_bit);
9098c2ecf20Sopenharmony_ci	if (ret < 0)
9108c2ecf20Sopenharmony_ci		return ret;
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	msleep(10);
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(100);
9158c2ecf20Sopenharmony_ci	while (time_before(jiffies, timeout)) {
9168c2ecf20Sopenharmony_ci		ret = __stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL]);
9178c2ecf20Sopenharmony_ci		if (ret < 0)
9188c2ecf20Sopenharmony_ci			return ret;
9198c2ecf20Sopenharmony_ci		if (!(ret & reset_bit))
9208c2ecf20Sopenharmony_ci			return 0;
9218c2ecf20Sopenharmony_ci		usleep_range(100, 200);
9228c2ecf20Sopenharmony_ci	}
9238c2ecf20Sopenharmony_ci	return -EIO;
9248c2ecf20Sopenharmony_ci}
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe1801 = {
9278c2ecf20Sopenharmony_ci	.name		= "stmpe1801",
9288c2ecf20Sopenharmony_ci	.id_val		= STMPE1801_ID,
9298c2ecf20Sopenharmony_ci	.id_mask	= 0xfff0,
9308c2ecf20Sopenharmony_ci	.num_gpios	= 18,
9318c2ecf20Sopenharmony_ci	.af_bits	= 0,
9328c2ecf20Sopenharmony_ci	.regs		= stmpe1801_regs,
9338c2ecf20Sopenharmony_ci	.blocks		= stmpe1801_blocks,
9348c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe1801_blocks),
9358c2ecf20Sopenharmony_ci	.num_irqs	= STMPE1801_NR_INTERNAL_IRQS,
9368c2ecf20Sopenharmony_ci	.enable		= stmpe1801_enable,
9378c2ecf20Sopenharmony_ci	/* stmpe1801 do not have any gpio alternate function */
9388c2ecf20Sopenharmony_ci	.get_altfunc	= NULL,
9398c2ecf20Sopenharmony_ci};
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci/*
9428c2ecf20Sopenharmony_ci * STMPE24XX
9438c2ecf20Sopenharmony_ci */
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_cistatic const u8 stmpe24xx_regs[] = {
9468c2ecf20Sopenharmony_ci	[STMPE_IDX_CHIP_ID]	= STMPE24XX_REG_CHIP_ID,
9478c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL]	= STMPE24XX_REG_SYS_CTRL,
9488c2ecf20Sopenharmony_ci	[STMPE_IDX_SYS_CTRL2]	= STMPE24XX_REG_SYS_CTRL2,
9498c2ecf20Sopenharmony_ci	[STMPE_IDX_ICR_LSB]	= STMPE24XX_REG_ICR_LSB,
9508c2ecf20Sopenharmony_ci	[STMPE_IDX_IER_MSB]	= STMPE24XX_REG_IER_MSB,
9518c2ecf20Sopenharmony_ci	[STMPE_IDX_IER_LSB]	= STMPE24XX_REG_IER_LSB,
9528c2ecf20Sopenharmony_ci	[STMPE_IDX_ISR_MSB]	= STMPE24XX_REG_ISR_MSB,
9538c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_LSB]	= STMPE24XX_REG_GPMR_LSB,
9548c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_CSB]	= STMPE24XX_REG_GPMR_CSB,
9558c2ecf20Sopenharmony_ci	[STMPE_IDX_GPMR_MSB]	= STMPE24XX_REG_GPMR_MSB,
9568c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_LSB]	= STMPE24XX_REG_GPSR_LSB,
9578c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_CSB]	= STMPE24XX_REG_GPSR_CSB,
9588c2ecf20Sopenharmony_ci	[STMPE_IDX_GPSR_MSB]	= STMPE24XX_REG_GPSR_MSB,
9598c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_LSB]	= STMPE24XX_REG_GPCR_LSB,
9608c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_CSB]	= STMPE24XX_REG_GPCR_CSB,
9618c2ecf20Sopenharmony_ci	[STMPE_IDX_GPCR_MSB]	= STMPE24XX_REG_GPCR_MSB,
9628c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_LSB]	= STMPE24XX_REG_GPDR_LSB,
9638c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_CSB]	= STMPE24XX_REG_GPDR_CSB,
9648c2ecf20Sopenharmony_ci	[STMPE_IDX_GPDR_MSB]	= STMPE24XX_REG_GPDR_MSB,
9658c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_LSB]	= STMPE24XX_REG_GPRER_LSB,
9668c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_CSB]	= STMPE24XX_REG_GPRER_CSB,
9678c2ecf20Sopenharmony_ci	[STMPE_IDX_GPRER_MSB]	= STMPE24XX_REG_GPRER_MSB,
9688c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_LSB]	= STMPE24XX_REG_GPFER_LSB,
9698c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_CSB]	= STMPE24XX_REG_GPFER_CSB,
9708c2ecf20Sopenharmony_ci	[STMPE_IDX_GPFER_MSB]	= STMPE24XX_REG_GPFER_MSB,
9718c2ecf20Sopenharmony_ci	[STMPE_IDX_GPPUR_LSB]	= STMPE24XX_REG_GPPUR_LSB,
9728c2ecf20Sopenharmony_ci	[STMPE_IDX_GPPDR_LSB]	= STMPE24XX_REG_GPPDR_LSB,
9738c2ecf20Sopenharmony_ci	[STMPE_IDX_GPAFR_U_MSB]	= STMPE24XX_REG_GPAFR_U_MSB,
9748c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_LSB]	= STMPE24XX_REG_IEGPIOR_LSB,
9758c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_CSB]	= STMPE24XX_REG_IEGPIOR_CSB,
9768c2ecf20Sopenharmony_ci	[STMPE_IDX_IEGPIOR_MSB]	= STMPE24XX_REG_IEGPIOR_MSB,
9778c2ecf20Sopenharmony_ci	[STMPE_IDX_ISGPIOR_MSB]	= STMPE24XX_REG_ISGPIOR_MSB,
9788c2ecf20Sopenharmony_ci	[STMPE_IDX_GPEDR_LSB]	= STMPE24XX_REG_GPEDR_LSB,
9798c2ecf20Sopenharmony_ci	[STMPE_IDX_GPEDR_CSB]	= STMPE24XX_REG_GPEDR_CSB,
9808c2ecf20Sopenharmony_ci	[STMPE_IDX_GPEDR_MSB]	= STMPE24XX_REG_GPEDR_MSB,
9818c2ecf20Sopenharmony_ci};
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_cistatic struct stmpe_variant_block stmpe24xx_blocks[] = {
9848c2ecf20Sopenharmony_ci	{
9858c2ecf20Sopenharmony_ci		.cell	= &stmpe_gpio_cell,
9868c2ecf20Sopenharmony_ci		.irq	= STMPE24XX_IRQ_GPIOC,
9878c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_GPIO,
9888c2ecf20Sopenharmony_ci	},
9898c2ecf20Sopenharmony_ci	{
9908c2ecf20Sopenharmony_ci		.cell	= &stmpe_keypad_cell,
9918c2ecf20Sopenharmony_ci		.irq	= STMPE24XX_IRQ_KEYPAD,
9928c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_KEYPAD,
9938c2ecf20Sopenharmony_ci	},
9948c2ecf20Sopenharmony_ci	{
9958c2ecf20Sopenharmony_ci		.cell	= &stmpe_pwm_cell,
9968c2ecf20Sopenharmony_ci		.irq	= STMPE24XX_IRQ_PWM0,
9978c2ecf20Sopenharmony_ci		.block	= STMPE_BLOCK_PWM,
9988c2ecf20Sopenharmony_ci	},
9998c2ecf20Sopenharmony_ci};
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_cistatic int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks,
10028c2ecf20Sopenharmony_ci			    bool enable)
10038c2ecf20Sopenharmony_ci{
10048c2ecf20Sopenharmony_ci	unsigned int mask = 0;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_GPIO)
10078c2ecf20Sopenharmony_ci		mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO;
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	if (blocks & STMPE_BLOCK_KEYPAD)
10108c2ecf20Sopenharmony_ci		mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], mask,
10138c2ecf20Sopenharmony_ci				enable ? mask : 0);
10148c2ecf20Sopenharmony_ci}
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_cistatic int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
10178c2ecf20Sopenharmony_ci{
10188c2ecf20Sopenharmony_ci	switch (block) {
10198c2ecf20Sopenharmony_ci	case STMPE_BLOCK_ROTATOR:
10208c2ecf20Sopenharmony_ci		return 2;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	case STMPE_BLOCK_KEYPAD:
10238c2ecf20Sopenharmony_ci	case STMPE_BLOCK_PWM:
10248c2ecf20Sopenharmony_ci		return 1;
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	case STMPE_BLOCK_GPIO:
10278c2ecf20Sopenharmony_ci	default:
10288c2ecf20Sopenharmony_ci		return 0;
10298c2ecf20Sopenharmony_ci	}
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe2401 = {
10338c2ecf20Sopenharmony_ci	.name		= "stmpe2401",
10348c2ecf20Sopenharmony_ci	.id_val		= 0x0101,
10358c2ecf20Sopenharmony_ci	.id_mask	= 0xffff,
10368c2ecf20Sopenharmony_ci	.num_gpios	= 24,
10378c2ecf20Sopenharmony_ci	.af_bits	= 2,
10388c2ecf20Sopenharmony_ci	.regs		= stmpe24xx_regs,
10398c2ecf20Sopenharmony_ci	.blocks		= stmpe24xx_blocks,
10408c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe24xx_blocks),
10418c2ecf20Sopenharmony_ci	.num_irqs	= STMPE24XX_NR_INTERNAL_IRQS,
10428c2ecf20Sopenharmony_ci	.enable		= stmpe24xx_enable,
10438c2ecf20Sopenharmony_ci	.get_altfunc	= stmpe24xx_get_altfunc,
10448c2ecf20Sopenharmony_ci};
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_cistatic struct stmpe_variant_info stmpe2403 = {
10478c2ecf20Sopenharmony_ci	.name		= "stmpe2403",
10488c2ecf20Sopenharmony_ci	.id_val		= 0x0120,
10498c2ecf20Sopenharmony_ci	.id_mask	= 0xffff,
10508c2ecf20Sopenharmony_ci	.num_gpios	= 24,
10518c2ecf20Sopenharmony_ci	.af_bits	= 2,
10528c2ecf20Sopenharmony_ci	.regs		= stmpe24xx_regs,
10538c2ecf20Sopenharmony_ci	.blocks		= stmpe24xx_blocks,
10548c2ecf20Sopenharmony_ci	.num_blocks	= ARRAY_SIZE(stmpe24xx_blocks),
10558c2ecf20Sopenharmony_ci	.num_irqs	= STMPE24XX_NR_INTERNAL_IRQS,
10568c2ecf20Sopenharmony_ci	.enable		= stmpe24xx_enable,
10578c2ecf20Sopenharmony_ci	.get_altfunc	= stmpe24xx_get_altfunc,
10588c2ecf20Sopenharmony_ci	.enable_autosleep	= stmpe1601_autosleep, /* same as stmpe1601 */
10598c2ecf20Sopenharmony_ci};
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_cistatic struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = {
10628c2ecf20Sopenharmony_ci	[STMPE610]	= &stmpe610,
10638c2ecf20Sopenharmony_ci	[STMPE801]	= &stmpe801,
10648c2ecf20Sopenharmony_ci	[STMPE811]	= &stmpe811,
10658c2ecf20Sopenharmony_ci	[STMPE1600]	= &stmpe1600,
10668c2ecf20Sopenharmony_ci	[STMPE1601]	= &stmpe1601,
10678c2ecf20Sopenharmony_ci	[STMPE1801]	= &stmpe1801,
10688c2ecf20Sopenharmony_ci	[STMPE2401]	= &stmpe2401,
10698c2ecf20Sopenharmony_ci	[STMPE2403]	= &stmpe2403,
10708c2ecf20Sopenharmony_ci};
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci/*
10738c2ecf20Sopenharmony_ci * These devices can be connected in a 'no-irq' configuration - the irq pin
10748c2ecf20Sopenharmony_ci * is not used and the device cannot interrupt the CPU. Here we only list
10758c2ecf20Sopenharmony_ci * devices which support this configuration - the driver will fail probing
10768c2ecf20Sopenharmony_ci * for any devices not listed here which are configured in this way.
10778c2ecf20Sopenharmony_ci */
10788c2ecf20Sopenharmony_cistatic struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = {
10798c2ecf20Sopenharmony_ci	[STMPE801]	= &stmpe801_noirq,
10808c2ecf20Sopenharmony_ci};
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_cistatic irqreturn_t stmpe_irq(int irq, void *data)
10838c2ecf20Sopenharmony_ci{
10848c2ecf20Sopenharmony_ci	struct stmpe *stmpe = data;
10858c2ecf20Sopenharmony_ci	struct stmpe_variant_info *variant = stmpe->variant;
10868c2ecf20Sopenharmony_ci	int num = DIV_ROUND_UP(variant->num_irqs, 8);
10878c2ecf20Sopenharmony_ci	u8 israddr;
10888c2ecf20Sopenharmony_ci	u8 isr[3];
10898c2ecf20Sopenharmony_ci	int ret;
10908c2ecf20Sopenharmony_ci	int i;
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	if (variant->id_val == STMPE801_ID ||
10938c2ecf20Sopenharmony_ci	    variant->id_val == STMPE1600_ID) {
10948c2ecf20Sopenharmony_ci		int base = irq_find_mapping(stmpe->domain, 0);
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci		handle_nested_irq(base);
10978c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
10988c2ecf20Sopenharmony_ci	}
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	if (variant->id_val == STMPE1801_ID)
11018c2ecf20Sopenharmony_ci		israddr = stmpe->regs[STMPE_IDX_ISR_LSB];
11028c2ecf20Sopenharmony_ci	else
11038c2ecf20Sopenharmony_ci		israddr = stmpe->regs[STMPE_IDX_ISR_MSB];
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	ret = stmpe_block_read(stmpe, israddr, num, isr);
11068c2ecf20Sopenharmony_ci	if (ret < 0)
11078c2ecf20Sopenharmony_ci		return IRQ_NONE;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
11108c2ecf20Sopenharmony_ci		int bank = num - i - 1;
11118c2ecf20Sopenharmony_ci		u8 status = isr[i];
11128c2ecf20Sopenharmony_ci		u8 clear;
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci		status &= stmpe->ier[bank];
11158c2ecf20Sopenharmony_ci		if (!status)
11168c2ecf20Sopenharmony_ci			continue;
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci		clear = status;
11198c2ecf20Sopenharmony_ci		while (status) {
11208c2ecf20Sopenharmony_ci			int bit = __ffs(status);
11218c2ecf20Sopenharmony_ci			int line = bank * 8 + bit;
11228c2ecf20Sopenharmony_ci			int nestedirq = irq_find_mapping(stmpe->domain, line);
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci			handle_nested_irq(nestedirq);
11258c2ecf20Sopenharmony_ci			status &= ~(1 << bit);
11268c2ecf20Sopenharmony_ci		}
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci		stmpe_reg_write(stmpe, israddr + i, clear);
11298c2ecf20Sopenharmony_ci	}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
11328c2ecf20Sopenharmony_ci}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_cistatic void stmpe_irq_lock(struct irq_data *data)
11358c2ecf20Sopenharmony_ci{
11368c2ecf20Sopenharmony_ci	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	mutex_lock(&stmpe->irq_lock);
11398c2ecf20Sopenharmony_ci}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_cistatic void stmpe_irq_sync_unlock(struct irq_data *data)
11428c2ecf20Sopenharmony_ci{
11438c2ecf20Sopenharmony_ci	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
11448c2ecf20Sopenharmony_ci	struct stmpe_variant_info *variant = stmpe->variant;
11458c2ecf20Sopenharmony_ci	int num = DIV_ROUND_UP(variant->num_irqs, 8);
11468c2ecf20Sopenharmony_ci	int i;
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	for (i = 0; i < num; i++) {
11498c2ecf20Sopenharmony_ci		u8 new = stmpe->ier[i];
11508c2ecf20Sopenharmony_ci		u8 old = stmpe->oldier[i];
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci		if (new == old)
11538c2ecf20Sopenharmony_ci			continue;
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci		stmpe->oldier[i] = new;
11568c2ecf20Sopenharmony_ci		stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB + i], new);
11578c2ecf20Sopenharmony_ci	}
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	mutex_unlock(&stmpe->irq_lock);
11608c2ecf20Sopenharmony_ci}
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_cistatic void stmpe_irq_mask(struct irq_data *data)
11638c2ecf20Sopenharmony_ci{
11648c2ecf20Sopenharmony_ci	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
11658c2ecf20Sopenharmony_ci	int offset = data->hwirq;
11668c2ecf20Sopenharmony_ci	int regoffset = offset / 8;
11678c2ecf20Sopenharmony_ci	int mask = 1 << (offset % 8);
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	stmpe->ier[regoffset] &= ~mask;
11708c2ecf20Sopenharmony_ci}
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_cistatic void stmpe_irq_unmask(struct irq_data *data)
11738c2ecf20Sopenharmony_ci{
11748c2ecf20Sopenharmony_ci	struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
11758c2ecf20Sopenharmony_ci	int offset = data->hwirq;
11768c2ecf20Sopenharmony_ci	int regoffset = offset / 8;
11778c2ecf20Sopenharmony_ci	int mask = 1 << (offset % 8);
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	stmpe->ier[regoffset] |= mask;
11808c2ecf20Sopenharmony_ci}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_cistatic struct irq_chip stmpe_irq_chip = {
11838c2ecf20Sopenharmony_ci	.name			= "stmpe",
11848c2ecf20Sopenharmony_ci	.irq_bus_lock		= stmpe_irq_lock,
11858c2ecf20Sopenharmony_ci	.irq_bus_sync_unlock	= stmpe_irq_sync_unlock,
11868c2ecf20Sopenharmony_ci	.irq_mask		= stmpe_irq_mask,
11878c2ecf20Sopenharmony_ci	.irq_unmask		= stmpe_irq_unmask,
11888c2ecf20Sopenharmony_ci};
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_cistatic int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
11918c2ecf20Sopenharmony_ci                                irq_hw_number_t hwirq)
11928c2ecf20Sopenharmony_ci{
11938c2ecf20Sopenharmony_ci	struct stmpe *stmpe = d->host_data;
11948c2ecf20Sopenharmony_ci	struct irq_chip *chip = NULL;
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	if (stmpe->variant->id_val != STMPE801_ID)
11978c2ecf20Sopenharmony_ci		chip = &stmpe_irq_chip;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	irq_set_chip_data(virq, stmpe);
12008c2ecf20Sopenharmony_ci	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
12018c2ecf20Sopenharmony_ci	irq_set_nested_thread(virq, 1);
12028c2ecf20Sopenharmony_ci	irq_set_noprobe(virq);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	return 0;
12058c2ecf20Sopenharmony_ci}
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_cistatic void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
12088c2ecf20Sopenharmony_ci{
12098c2ecf20Sopenharmony_ci		irq_set_chip_and_handler(virq, NULL, NULL);
12108c2ecf20Sopenharmony_ci		irq_set_chip_data(virq, NULL);
12118c2ecf20Sopenharmony_ci}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_cistatic const struct irq_domain_ops stmpe_irq_ops = {
12148c2ecf20Sopenharmony_ci        .map    = stmpe_irq_map,
12158c2ecf20Sopenharmony_ci        .unmap  = stmpe_irq_unmap,
12168c2ecf20Sopenharmony_ci        .xlate  = irq_domain_xlate_twocell,
12178c2ecf20Sopenharmony_ci};
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_cistatic int stmpe_irq_init(struct stmpe *stmpe, struct device_node *np)
12208c2ecf20Sopenharmony_ci{
12218c2ecf20Sopenharmony_ci	int base = 0;
12228c2ecf20Sopenharmony_ci	int num_irqs = stmpe->variant->num_irqs;
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	stmpe->domain = irq_domain_add_simple(np, num_irqs, base,
12258c2ecf20Sopenharmony_ci					      &stmpe_irq_ops, stmpe);
12268c2ecf20Sopenharmony_ci	if (!stmpe->domain) {
12278c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "Failed to create irqdomain\n");
12288c2ecf20Sopenharmony_ci		return -ENOSYS;
12298c2ecf20Sopenharmony_ci	}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	return 0;
12328c2ecf20Sopenharmony_ci}
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_cistatic int stmpe_chip_init(struct stmpe *stmpe)
12358c2ecf20Sopenharmony_ci{
12368c2ecf20Sopenharmony_ci	unsigned int irq_trigger = stmpe->pdata->irq_trigger;
12378c2ecf20Sopenharmony_ci	int autosleep_timeout = stmpe->pdata->autosleep_timeout;
12388c2ecf20Sopenharmony_ci	struct stmpe_variant_info *variant = stmpe->variant;
12398c2ecf20Sopenharmony_ci	u8 icr = 0;
12408c2ecf20Sopenharmony_ci	unsigned int id;
12418c2ecf20Sopenharmony_ci	u8 data[2];
12428c2ecf20Sopenharmony_ci	int ret;
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID],
12458c2ecf20Sopenharmony_ci			       ARRAY_SIZE(data), data);
12468c2ecf20Sopenharmony_ci	if (ret < 0)
12478c2ecf20Sopenharmony_ci		return ret;
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	id = (data[0] << 8) | data[1];
12508c2ecf20Sopenharmony_ci	if ((id & variant->id_mask) != variant->id_val) {
12518c2ecf20Sopenharmony_ci		dev_err(stmpe->dev, "unknown chip id: %#x\n", id);
12528c2ecf20Sopenharmony_ci		return -EINVAL;
12538c2ecf20Sopenharmony_ci	}
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id);
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	/* Disable all modules -- subdrivers should enable what they need. */
12588c2ecf20Sopenharmony_ci	ret = stmpe_disable(stmpe, ~0);
12598c2ecf20Sopenharmony_ci	if (ret)
12608c2ecf20Sopenharmony_ci		return ret;
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	ret =  stmpe_reset(stmpe);
12638c2ecf20Sopenharmony_ci	if (ret < 0)
12648c2ecf20Sopenharmony_ci		return ret;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	if (stmpe->irq >= 0) {
12678c2ecf20Sopenharmony_ci		if (id == STMPE801_ID || id == STMPE1600_ID)
12688c2ecf20Sopenharmony_ci			icr = STMPE_SYS_CTRL_INT_EN;
12698c2ecf20Sopenharmony_ci		else
12708c2ecf20Sopenharmony_ci			icr = STMPE_ICR_LSB_GIM;
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci		/* STMPE801 and STMPE1600 don't support Edge interrupts */
12738c2ecf20Sopenharmony_ci		if (id != STMPE801_ID && id != STMPE1600_ID) {
12748c2ecf20Sopenharmony_ci			if (irq_trigger == IRQF_TRIGGER_FALLING ||
12758c2ecf20Sopenharmony_ci					irq_trigger == IRQF_TRIGGER_RISING)
12768c2ecf20Sopenharmony_ci				icr |= STMPE_ICR_LSB_EDGE;
12778c2ecf20Sopenharmony_ci		}
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci		if (irq_trigger == IRQF_TRIGGER_RISING ||
12808c2ecf20Sopenharmony_ci				irq_trigger == IRQF_TRIGGER_HIGH) {
12818c2ecf20Sopenharmony_ci			if (id == STMPE801_ID || id == STMPE1600_ID)
12828c2ecf20Sopenharmony_ci				icr |= STMPE_SYS_CTRL_INT_HI;
12838c2ecf20Sopenharmony_ci			else
12848c2ecf20Sopenharmony_ci				icr |= STMPE_ICR_LSB_HIGH;
12858c2ecf20Sopenharmony_ci		}
12868c2ecf20Sopenharmony_ci	}
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	if (stmpe->pdata->autosleep) {
12898c2ecf20Sopenharmony_ci		ret = stmpe_autosleep(stmpe, autosleep_timeout);
12908c2ecf20Sopenharmony_ci		if (ret)
12918c2ecf20Sopenharmony_ci			return ret;
12928c2ecf20Sopenharmony_ci	}
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr);
12958c2ecf20Sopenharmony_ci}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_cistatic int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell)
12988c2ecf20Sopenharmony_ci{
12998c2ecf20Sopenharmony_ci	return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
13008c2ecf20Sopenharmony_ci			       NULL, 0, stmpe->domain);
13018c2ecf20Sopenharmony_ci}
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_cistatic int stmpe_devices_init(struct stmpe *stmpe)
13048c2ecf20Sopenharmony_ci{
13058c2ecf20Sopenharmony_ci	struct stmpe_variant_info *variant = stmpe->variant;
13068c2ecf20Sopenharmony_ci	unsigned int platform_blocks = stmpe->pdata->blocks;
13078c2ecf20Sopenharmony_ci	int ret = -EINVAL;
13088c2ecf20Sopenharmony_ci	int i, j;
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	for (i = 0; i < variant->num_blocks; i++) {
13118c2ecf20Sopenharmony_ci		struct stmpe_variant_block *block = &variant->blocks[i];
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci		if (!(platform_blocks & block->block))
13148c2ecf20Sopenharmony_ci			continue;
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci		for (j = 0; j < block->cell->num_resources; j++) {
13178c2ecf20Sopenharmony_ci			struct resource *res =
13188c2ecf20Sopenharmony_ci				(struct resource *) &block->cell->resources[j];
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci			/* Dynamically fill in a variant's IRQ. */
13218c2ecf20Sopenharmony_ci			if (res->flags & IORESOURCE_IRQ)
13228c2ecf20Sopenharmony_ci				res->start = res->end = block->irq + j;
13238c2ecf20Sopenharmony_ci		}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci		platform_blocks &= ~block->block;
13268c2ecf20Sopenharmony_ci		ret = stmpe_add_device(stmpe, block->cell);
13278c2ecf20Sopenharmony_ci		if (ret)
13288c2ecf20Sopenharmony_ci			return ret;
13298c2ecf20Sopenharmony_ci	}
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	if (platform_blocks)
13328c2ecf20Sopenharmony_ci		dev_warn(stmpe->dev,
13338c2ecf20Sopenharmony_ci			 "platform wants blocks (%#x) not present on variant",
13348c2ecf20Sopenharmony_ci			 platform_blocks);
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci	return ret;
13378c2ecf20Sopenharmony_ci}
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_cistatic void stmpe_of_probe(struct stmpe_platform_data *pdata,
13408c2ecf20Sopenharmony_ci			   struct device_node *np)
13418c2ecf20Sopenharmony_ci{
13428c2ecf20Sopenharmony_ci	struct device_node *child;
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	pdata->id = of_alias_get_id(np, "stmpe-i2c");
13458c2ecf20Sopenharmony_ci	if (pdata->id < 0)
13468c2ecf20Sopenharmony_ci		pdata->id = -1;
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci	pdata->irq_gpio = of_get_named_gpio_flags(np, "irq-gpio", 0,
13498c2ecf20Sopenharmony_ci				&pdata->irq_trigger);
13508c2ecf20Sopenharmony_ci	if (gpio_is_valid(pdata->irq_gpio))
13518c2ecf20Sopenharmony_ci		pdata->irq_over_gpio = 1;
13528c2ecf20Sopenharmony_ci	else
13538c2ecf20Sopenharmony_ci		pdata->irq_trigger = IRQF_TRIGGER_NONE;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	of_property_read_u32(np, "st,autosleep-timeout",
13568c2ecf20Sopenharmony_ci			&pdata->autosleep_timeout);
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ci	pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
13618c2ecf20Sopenharmony_ci		if (of_node_name_eq(child, "stmpe_gpio")) {
13628c2ecf20Sopenharmony_ci			pdata->blocks |= STMPE_BLOCK_GPIO;
13638c2ecf20Sopenharmony_ci		} else if (of_node_name_eq(child, "stmpe_keypad")) {
13648c2ecf20Sopenharmony_ci			pdata->blocks |= STMPE_BLOCK_KEYPAD;
13658c2ecf20Sopenharmony_ci		} else if (of_node_name_eq(child, "stmpe_touchscreen")) {
13668c2ecf20Sopenharmony_ci			pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
13678c2ecf20Sopenharmony_ci		} else if (of_node_name_eq(child, "stmpe_adc")) {
13688c2ecf20Sopenharmony_ci			pdata->blocks |= STMPE_BLOCK_ADC;
13698c2ecf20Sopenharmony_ci		} else if (of_node_name_eq(child, "stmpe_pwm")) {
13708c2ecf20Sopenharmony_ci			pdata->blocks |= STMPE_BLOCK_PWM;
13718c2ecf20Sopenharmony_ci		} else if (of_node_name_eq(child, "stmpe_rotator")) {
13728c2ecf20Sopenharmony_ci			pdata->blocks |= STMPE_BLOCK_ROTATOR;
13738c2ecf20Sopenharmony_ci		}
13748c2ecf20Sopenharmony_ci	}
13758c2ecf20Sopenharmony_ci}
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci/* Called from client specific probe routines */
13788c2ecf20Sopenharmony_ciint stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
13798c2ecf20Sopenharmony_ci{
13808c2ecf20Sopenharmony_ci	struct stmpe_platform_data *pdata;
13818c2ecf20Sopenharmony_ci	struct device_node *np = ci->dev->of_node;
13828c2ecf20Sopenharmony_ci	struct stmpe *stmpe;
13838c2ecf20Sopenharmony_ci	int ret;
13848c2ecf20Sopenharmony_ci	u32 val;
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL);
13878c2ecf20Sopenharmony_ci	if (!pdata)
13888c2ecf20Sopenharmony_ci		return -ENOMEM;
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	stmpe_of_probe(pdata, np);
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	if (of_find_property(np, "interrupts", NULL) == NULL)
13938c2ecf20Sopenharmony_ci		ci->irq = -1;
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL);
13968c2ecf20Sopenharmony_ci	if (!stmpe)
13978c2ecf20Sopenharmony_ci		return -ENOMEM;
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	mutex_init(&stmpe->irq_lock);
14008c2ecf20Sopenharmony_ci	mutex_init(&stmpe->lock);
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	if (!of_property_read_u32(np, "st,sample-time", &val))
14038c2ecf20Sopenharmony_ci		stmpe->sample_time = val;
14048c2ecf20Sopenharmony_ci	if (!of_property_read_u32(np, "st,mod-12b", &val))
14058c2ecf20Sopenharmony_ci		stmpe->mod_12b = val;
14068c2ecf20Sopenharmony_ci	if (!of_property_read_u32(np, "st,ref-sel", &val))
14078c2ecf20Sopenharmony_ci		stmpe->ref_sel = val;
14088c2ecf20Sopenharmony_ci	if (!of_property_read_u32(np, "st,adc-freq", &val))
14098c2ecf20Sopenharmony_ci		stmpe->adc_freq = val;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	stmpe->dev = ci->dev;
14128c2ecf20Sopenharmony_ci	stmpe->client = ci->client;
14138c2ecf20Sopenharmony_ci	stmpe->pdata = pdata;
14148c2ecf20Sopenharmony_ci	stmpe->ci = ci;
14158c2ecf20Sopenharmony_ci	stmpe->partnum = partnum;
14168c2ecf20Sopenharmony_ci	stmpe->variant = stmpe_variant_info[partnum];
14178c2ecf20Sopenharmony_ci	stmpe->regs = stmpe->variant->regs;
14188c2ecf20Sopenharmony_ci	stmpe->num_gpios = stmpe->variant->num_gpios;
14198c2ecf20Sopenharmony_ci	stmpe->vcc = devm_regulator_get_optional(ci->dev, "vcc");
14208c2ecf20Sopenharmony_ci	if (!IS_ERR(stmpe->vcc)) {
14218c2ecf20Sopenharmony_ci		ret = regulator_enable(stmpe->vcc);
14228c2ecf20Sopenharmony_ci		if (ret)
14238c2ecf20Sopenharmony_ci			dev_warn(ci->dev, "failed to enable VCC supply\n");
14248c2ecf20Sopenharmony_ci	}
14258c2ecf20Sopenharmony_ci	stmpe->vio = devm_regulator_get_optional(ci->dev, "vio");
14268c2ecf20Sopenharmony_ci	if (!IS_ERR(stmpe->vio)) {
14278c2ecf20Sopenharmony_ci		ret = regulator_enable(stmpe->vio);
14288c2ecf20Sopenharmony_ci		if (ret)
14298c2ecf20Sopenharmony_ci			dev_warn(ci->dev, "failed to enable VIO supply\n");
14308c2ecf20Sopenharmony_ci	}
14318c2ecf20Sopenharmony_ci	dev_set_drvdata(stmpe->dev, stmpe);
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci	if (ci->init)
14348c2ecf20Sopenharmony_ci		ci->init(stmpe);
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	if (pdata->irq_over_gpio) {
14378c2ecf20Sopenharmony_ci		ret = devm_gpio_request_one(ci->dev, pdata->irq_gpio,
14388c2ecf20Sopenharmony_ci				GPIOF_DIR_IN, "stmpe");
14398c2ecf20Sopenharmony_ci		if (ret) {
14408c2ecf20Sopenharmony_ci			dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n",
14418c2ecf20Sopenharmony_ci					ret);
14428c2ecf20Sopenharmony_ci			return ret;
14438c2ecf20Sopenharmony_ci		}
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci		stmpe->irq = gpio_to_irq(pdata->irq_gpio);
14468c2ecf20Sopenharmony_ci	} else {
14478c2ecf20Sopenharmony_ci		stmpe->irq = ci->irq;
14488c2ecf20Sopenharmony_ci	}
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	if (stmpe->irq < 0) {
14518c2ecf20Sopenharmony_ci		/* use alternate variant info for no-irq mode, if supported */
14528c2ecf20Sopenharmony_ci		dev_info(stmpe->dev,
14538c2ecf20Sopenharmony_ci			"%s configured in no-irq mode by platform data\n",
14548c2ecf20Sopenharmony_ci			stmpe->variant->name);
14558c2ecf20Sopenharmony_ci		if (!stmpe_noirq_variant_info[stmpe->partnum]) {
14568c2ecf20Sopenharmony_ci			dev_err(stmpe->dev,
14578c2ecf20Sopenharmony_ci				"%s does not support no-irq mode!\n",
14588c2ecf20Sopenharmony_ci				stmpe->variant->name);
14598c2ecf20Sopenharmony_ci			return -ENODEV;
14608c2ecf20Sopenharmony_ci		}
14618c2ecf20Sopenharmony_ci		stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum];
14628c2ecf20Sopenharmony_ci	} else if (pdata->irq_trigger == IRQF_TRIGGER_NONE) {
14638c2ecf20Sopenharmony_ci		pdata->irq_trigger = irq_get_trigger_type(stmpe->irq);
14648c2ecf20Sopenharmony_ci	}
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_ci	ret = stmpe_chip_init(stmpe);
14678c2ecf20Sopenharmony_ci	if (ret)
14688c2ecf20Sopenharmony_ci		return ret;
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	if (stmpe->irq >= 0) {
14718c2ecf20Sopenharmony_ci		ret = stmpe_irq_init(stmpe, np);
14728c2ecf20Sopenharmony_ci		if (ret)
14738c2ecf20Sopenharmony_ci			return ret;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci		ret = devm_request_threaded_irq(ci->dev, stmpe->irq, NULL,
14768c2ecf20Sopenharmony_ci				stmpe_irq, pdata->irq_trigger | IRQF_ONESHOT,
14778c2ecf20Sopenharmony_ci				"stmpe", stmpe);
14788c2ecf20Sopenharmony_ci		if (ret) {
14798c2ecf20Sopenharmony_ci			dev_err(stmpe->dev, "failed to request IRQ: %d\n",
14808c2ecf20Sopenharmony_ci					ret);
14818c2ecf20Sopenharmony_ci			return ret;
14828c2ecf20Sopenharmony_ci		}
14838c2ecf20Sopenharmony_ci	}
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	ret = stmpe_devices_init(stmpe);
14868c2ecf20Sopenharmony_ci	if (!ret)
14878c2ecf20Sopenharmony_ci		return 0;
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	dev_err(stmpe->dev, "failed to add children\n");
14908c2ecf20Sopenharmony_ci	mfd_remove_devices(stmpe->dev);
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	return ret;
14938c2ecf20Sopenharmony_ci}
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ciint stmpe_remove(struct stmpe *stmpe)
14968c2ecf20Sopenharmony_ci{
14978c2ecf20Sopenharmony_ci	if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio))
14988c2ecf20Sopenharmony_ci		regulator_disable(stmpe->vio);
14998c2ecf20Sopenharmony_ci	if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc))
15008c2ecf20Sopenharmony_ci		regulator_disable(stmpe->vcc);
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	__stmpe_disable(stmpe, STMPE_BLOCK_ADC);
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	mfd_remove_devices(stmpe->dev);
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	return 0;
15078c2ecf20Sopenharmony_ci}
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
15108c2ecf20Sopenharmony_cistatic int stmpe_suspend(struct device *dev)
15118c2ecf20Sopenharmony_ci{
15128c2ecf20Sopenharmony_ci	struct stmpe *stmpe = dev_get_drvdata(dev);
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	if (stmpe->irq >= 0 && device_may_wakeup(dev))
15158c2ecf20Sopenharmony_ci		enable_irq_wake(stmpe->irq);
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	return 0;
15188c2ecf20Sopenharmony_ci}
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_cistatic int stmpe_resume(struct device *dev)
15218c2ecf20Sopenharmony_ci{
15228c2ecf20Sopenharmony_ci	struct stmpe *stmpe = dev_get_drvdata(dev);
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	if (stmpe->irq >= 0 && device_may_wakeup(dev))
15258c2ecf20Sopenharmony_ci		disable_irq_wake(stmpe->irq);
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	return 0;
15288c2ecf20Sopenharmony_ci}
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ciconst struct dev_pm_ops stmpe_dev_pm_ops = {
15318c2ecf20Sopenharmony_ci	.suspend	= stmpe_suspend,
15328c2ecf20Sopenharmony_ci	.resume		= stmpe_resume,
15338c2ecf20Sopenharmony_ci};
15348c2ecf20Sopenharmony_ci#endif
1535