162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ST Microelectronics MFD: stmpe's driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) ST-Ericsson SA 2010 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/err.h> 1162306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1262306a36Sopenharmony_ci#include <linux/export.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci#include <linux/irq.h> 1662306a36Sopenharmony_ci#include <linux/irqdomain.h> 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/pm.h> 1962306a36Sopenharmony_ci#include <linux/slab.h> 2062306a36Sopenharmony_ci#include <linux/mfd/core.h> 2162306a36Sopenharmony_ci#include <linux/delay.h> 2262306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 2362306a36Sopenharmony_ci#include "stmpe.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/** 2662306a36Sopenharmony_ci * struct stmpe_platform_data - STMPE platform data 2762306a36Sopenharmony_ci * @id: device id to distinguish between multiple STMPEs on the same board 2862306a36Sopenharmony_ci * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) 2962306a36Sopenharmony_ci * @irq_trigger: IRQ trigger to use for the interrupt to the host 3062306a36Sopenharmony_ci * @autosleep: bool to enable/disable stmpe autosleep 3162306a36Sopenharmony_ci * @autosleep_timeout: inactivity timeout in milliseconds for autosleep 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_cistruct stmpe_platform_data { 3462306a36Sopenharmony_ci int id; 3562306a36Sopenharmony_ci unsigned int blocks; 3662306a36Sopenharmony_ci unsigned int irq_trigger; 3762306a36Sopenharmony_ci bool autosleep; 3862306a36Sopenharmony_ci int autosleep_timeout; 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci return stmpe->variant->enable(stmpe, blocks, true); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic int __stmpe_disable(struct stmpe *stmpe, unsigned int blocks) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci return stmpe->variant->enable(stmpe, blocks, false); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int __stmpe_reg_read(struct stmpe *stmpe, u8 reg) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci int ret; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci ret = stmpe->ci->read_byte(stmpe, reg); 5662306a36Sopenharmony_ci if (ret < 0) 5762306a36Sopenharmony_ci dev_err(stmpe->dev, "failed to read reg %#x: %d\n", reg, ret); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci dev_vdbg(stmpe->dev, "rd: reg %#x => data %#x\n", reg, ret); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return ret; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int __stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int ret; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci dev_vdbg(stmpe->dev, "wr: reg %#x <= %#x\n", reg, val); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci ret = stmpe->ci->write_byte(stmpe, reg, val); 7162306a36Sopenharmony_ci if (ret < 0) 7262306a36Sopenharmony_ci dev_err(stmpe->dev, "failed to write reg %#x: %d\n", reg, ret); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci return ret; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int __stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci int ret; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci ret = __stmpe_reg_read(stmpe, reg); 8262306a36Sopenharmony_ci if (ret < 0) 8362306a36Sopenharmony_ci return ret; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci ret &= ~mask; 8662306a36Sopenharmony_ci ret |= val; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return __stmpe_reg_write(stmpe, reg, ret); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int __stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, 9262306a36Sopenharmony_ci u8 *values) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci int ret; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci ret = stmpe->ci->read_block(stmpe, reg, length, values); 9762306a36Sopenharmony_ci if (ret < 0) 9862306a36Sopenharmony_ci dev_err(stmpe->dev, "failed to read regs %#x: %d\n", reg, ret); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci dev_vdbg(stmpe->dev, "rd: reg %#x (%d) => ret %#x\n", reg, length, ret); 10162306a36Sopenharmony_ci stmpe_dump_bytes("stmpe rd: ", values, length); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic int __stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, 10762306a36Sopenharmony_ci const u8 *values) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci int ret; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci dev_vdbg(stmpe->dev, "wr: regs %#x (%d)\n", reg, length); 11262306a36Sopenharmony_ci stmpe_dump_bytes("stmpe wr: ", values, length); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci ret = stmpe->ci->write_block(stmpe, reg, length, values); 11562306a36Sopenharmony_ci if (ret < 0) 11662306a36Sopenharmony_ci dev_err(stmpe->dev, "failed to write regs %#x: %d\n", reg, ret); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return ret; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci/** 12262306a36Sopenharmony_ci * stmpe_enable - enable blocks on an STMPE device 12362306a36Sopenharmony_ci * @stmpe: Device to work on 12462306a36Sopenharmony_ci * @blocks: Mask of blocks (enum stmpe_block values) to enable 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ciint stmpe_enable(struct stmpe *stmpe, unsigned int blocks) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci int ret; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 13162306a36Sopenharmony_ci ret = __stmpe_enable(stmpe, blocks); 13262306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci return ret; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_enable); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/** 13962306a36Sopenharmony_ci * stmpe_disable - disable blocks on an STMPE device 14062306a36Sopenharmony_ci * @stmpe: Device to work on 14162306a36Sopenharmony_ci * @blocks: Mask of blocks (enum stmpe_block values) to enable 14262306a36Sopenharmony_ci */ 14362306a36Sopenharmony_ciint stmpe_disable(struct stmpe *stmpe, unsigned int blocks) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci int ret; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 14862306a36Sopenharmony_ci ret = __stmpe_disable(stmpe, blocks); 14962306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return ret; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_disable); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/** 15662306a36Sopenharmony_ci * stmpe_reg_read() - read a single STMPE register 15762306a36Sopenharmony_ci * @stmpe: Device to read from 15862306a36Sopenharmony_ci * @reg: Register to read 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ciint stmpe_reg_read(struct stmpe *stmpe, u8 reg) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci int ret; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 16562306a36Sopenharmony_ci ret = __stmpe_reg_read(stmpe, reg); 16662306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci return ret; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_reg_read); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/** 17362306a36Sopenharmony_ci * stmpe_reg_write() - write a single STMPE register 17462306a36Sopenharmony_ci * @stmpe: Device to write to 17562306a36Sopenharmony_ci * @reg: Register to write 17662306a36Sopenharmony_ci * @val: Value to write 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_ciint stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci int ret; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 18362306a36Sopenharmony_ci ret = __stmpe_reg_write(stmpe, reg, val); 18462306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci return ret; 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_reg_write); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/** 19162306a36Sopenharmony_ci * stmpe_set_bits() - set the value of a bitfield in a STMPE register 19262306a36Sopenharmony_ci * @stmpe: Device to write to 19362306a36Sopenharmony_ci * @reg: Register to write 19462306a36Sopenharmony_ci * @mask: Mask of bits to set 19562306a36Sopenharmony_ci * @val: Value to set 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ciint stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci int ret; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 20262306a36Sopenharmony_ci ret = __stmpe_set_bits(stmpe, reg, mask, val); 20362306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return ret; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_set_bits); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/** 21062306a36Sopenharmony_ci * stmpe_block_read() - read multiple STMPE registers 21162306a36Sopenharmony_ci * @stmpe: Device to read from 21262306a36Sopenharmony_ci * @reg: First register 21362306a36Sopenharmony_ci * @length: Number of registers 21462306a36Sopenharmony_ci * @values: Buffer to write to 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_ciint stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci int ret; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 22162306a36Sopenharmony_ci ret = __stmpe_block_read(stmpe, reg, length, values); 22262306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return ret; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_block_read); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci/** 22962306a36Sopenharmony_ci * stmpe_block_write() - write multiple STMPE registers 23062306a36Sopenharmony_ci * @stmpe: Device to write to 23162306a36Sopenharmony_ci * @reg: First register 23262306a36Sopenharmony_ci * @length: Number of registers 23362306a36Sopenharmony_ci * @values: Values to write 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ciint stmpe_block_write(struct stmpe *stmpe, u8 reg, u8 length, 23662306a36Sopenharmony_ci const u8 *values) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci int ret; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 24162306a36Sopenharmony_ci ret = __stmpe_block_write(stmpe, reg, length, values); 24262306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return ret; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_block_write); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/** 24962306a36Sopenharmony_ci * stmpe_set_altfunc()- set the alternate function for STMPE pins 25062306a36Sopenharmony_ci * @stmpe: Device to configure 25162306a36Sopenharmony_ci * @pins: Bitmask of pins to affect 25262306a36Sopenharmony_ci * @block: block to enable alternate functions for 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * @pins is assumed to have a bit set for each of the bits whose alternate 25562306a36Sopenharmony_ci * function is to be changed, numbered according to the GPIOXY numbers. 25662306a36Sopenharmony_ci * 25762306a36Sopenharmony_ci * If the GPIO module is not enabled, this function automatically enables it in 25862306a36Sopenharmony_ci * order to perform the change. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ciint stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci struct stmpe_variant_info *variant = stmpe->variant; 26362306a36Sopenharmony_ci u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; 26462306a36Sopenharmony_ci int af_bits = variant->af_bits; 26562306a36Sopenharmony_ci int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); 26662306a36Sopenharmony_ci int mask = (1 << af_bits) - 1; 26762306a36Sopenharmony_ci u8 regs[8]; 26862306a36Sopenharmony_ci int af, afperreg, ret; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (!variant->get_altfunc) 27162306a36Sopenharmony_ci return 0; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci afperreg = 8 / af_bits; 27462306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); 27762306a36Sopenharmony_ci if (ret < 0) 27862306a36Sopenharmony_ci goto out; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci ret = __stmpe_block_read(stmpe, regaddr, numregs, regs); 28162306a36Sopenharmony_ci if (ret < 0) 28262306a36Sopenharmony_ci goto out; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci af = variant->get_altfunc(stmpe, block); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci while (pins) { 28762306a36Sopenharmony_ci int pin = __ffs(pins); 28862306a36Sopenharmony_ci int regoffset = numregs - (pin / afperreg) - 1; 28962306a36Sopenharmony_ci int pos = (pin % afperreg) * (8 / afperreg); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci regs[regoffset] &= ~(mask << pos); 29262306a36Sopenharmony_ci regs[regoffset] |= af << pos; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci pins &= ~(1 << pin); 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci ret = __stmpe_block_write(stmpe, regaddr, numregs, regs); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ciout: 30062306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 30162306a36Sopenharmony_ci return ret; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe_set_altfunc); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci/* 30662306a36Sopenharmony_ci * GPIO (all variants) 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic struct resource stmpe_gpio_resources[] = { 31062306a36Sopenharmony_ci /* Start and end filled dynamically */ 31162306a36Sopenharmony_ci { 31262306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 31362306a36Sopenharmony_ci }, 31462306a36Sopenharmony_ci}; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic const struct mfd_cell stmpe_gpio_cell = { 31762306a36Sopenharmony_ci .name = "stmpe-gpio", 31862306a36Sopenharmony_ci .of_compatible = "st,stmpe-gpio", 31962306a36Sopenharmony_ci .resources = stmpe_gpio_resources, 32062306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(stmpe_gpio_resources), 32162306a36Sopenharmony_ci}; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic const struct mfd_cell stmpe_gpio_cell_noirq = { 32462306a36Sopenharmony_ci .name = "stmpe-gpio", 32562306a36Sopenharmony_ci .of_compatible = "st,stmpe-gpio", 32662306a36Sopenharmony_ci /* gpio cell resources consist of an irq only so no resources here */ 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci/* 33062306a36Sopenharmony_ci * Keypad (1601, 2401, 2403) 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic struct resource stmpe_keypad_resources[] = { 33462306a36Sopenharmony_ci /* Start and end filled dynamically */ 33562306a36Sopenharmony_ci { 33662306a36Sopenharmony_ci .name = "KEYPAD", 33762306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 33862306a36Sopenharmony_ci }, 33962306a36Sopenharmony_ci { 34062306a36Sopenharmony_ci .name = "KEYPAD_OVER", 34162306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 34262306a36Sopenharmony_ci }, 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic const struct mfd_cell stmpe_keypad_cell = { 34662306a36Sopenharmony_ci .name = "stmpe-keypad", 34762306a36Sopenharmony_ci .of_compatible = "st,stmpe-keypad", 34862306a36Sopenharmony_ci .resources = stmpe_keypad_resources, 34962306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(stmpe_keypad_resources), 35062306a36Sopenharmony_ci}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci/* 35362306a36Sopenharmony_ci * PWM (1601, 2401, 2403) 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_cistatic struct resource stmpe_pwm_resources[] = { 35662306a36Sopenharmony_ci /* Start and end filled dynamically */ 35762306a36Sopenharmony_ci { 35862306a36Sopenharmony_ci .name = "PWM0", 35962306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 36062306a36Sopenharmony_ci }, 36162306a36Sopenharmony_ci { 36262306a36Sopenharmony_ci .name = "PWM1", 36362306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 36462306a36Sopenharmony_ci }, 36562306a36Sopenharmony_ci { 36662306a36Sopenharmony_ci .name = "PWM2", 36762306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 36862306a36Sopenharmony_ci }, 36962306a36Sopenharmony_ci}; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistatic const struct mfd_cell stmpe_pwm_cell = { 37262306a36Sopenharmony_ci .name = "stmpe-pwm", 37362306a36Sopenharmony_ci .of_compatible = "st,stmpe-pwm", 37462306a36Sopenharmony_ci .resources = stmpe_pwm_resources, 37562306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(stmpe_pwm_resources), 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci/* 37962306a36Sopenharmony_ci * STMPE801 38062306a36Sopenharmony_ci */ 38162306a36Sopenharmony_cistatic const u8 stmpe801_regs[] = { 38262306a36Sopenharmony_ci [STMPE_IDX_CHIP_ID] = STMPE801_REG_CHIP_ID, 38362306a36Sopenharmony_ci [STMPE_IDX_ICR_LSB] = STMPE801_REG_SYS_CTRL, 38462306a36Sopenharmony_ci [STMPE_IDX_GPMR_LSB] = STMPE801_REG_GPIO_MP_STA, 38562306a36Sopenharmony_ci [STMPE_IDX_GPSR_LSB] = STMPE801_REG_GPIO_SET_PIN, 38662306a36Sopenharmony_ci [STMPE_IDX_GPCR_LSB] = STMPE801_REG_GPIO_SET_PIN, 38762306a36Sopenharmony_ci [STMPE_IDX_GPDR_LSB] = STMPE801_REG_GPIO_DIR, 38862306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_LSB] = STMPE801_REG_GPIO_INT_EN, 38962306a36Sopenharmony_ci [STMPE_IDX_ISGPIOR_MSB] = STMPE801_REG_GPIO_INT_STA, 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci}; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic struct stmpe_variant_block stmpe801_blocks[] = { 39462306a36Sopenharmony_ci { 39562306a36Sopenharmony_ci .cell = &stmpe_gpio_cell, 39662306a36Sopenharmony_ci .irq = 0, 39762306a36Sopenharmony_ci .block = STMPE_BLOCK_GPIO, 39862306a36Sopenharmony_ci }, 39962306a36Sopenharmony_ci}; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic struct stmpe_variant_block stmpe801_blocks_noirq[] = { 40262306a36Sopenharmony_ci { 40362306a36Sopenharmony_ci .cell = &stmpe_gpio_cell_noirq, 40462306a36Sopenharmony_ci .block = STMPE_BLOCK_GPIO, 40562306a36Sopenharmony_ci }, 40662306a36Sopenharmony_ci}; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic int stmpe801_enable(struct stmpe *stmpe, unsigned int blocks, 40962306a36Sopenharmony_ci bool enable) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_GPIO) 41262306a36Sopenharmony_ci return 0; 41362306a36Sopenharmony_ci else 41462306a36Sopenharmony_ci return -EINVAL; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe801 = { 41862306a36Sopenharmony_ci .name = "stmpe801", 41962306a36Sopenharmony_ci .id_val = STMPE801_ID, 42062306a36Sopenharmony_ci .id_mask = 0xffff, 42162306a36Sopenharmony_ci .num_gpios = 8, 42262306a36Sopenharmony_ci .regs = stmpe801_regs, 42362306a36Sopenharmony_ci .blocks = stmpe801_blocks, 42462306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe801_blocks), 42562306a36Sopenharmony_ci .num_irqs = STMPE801_NR_INTERNAL_IRQS, 42662306a36Sopenharmony_ci .enable = stmpe801_enable, 42762306a36Sopenharmony_ci}; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe801_noirq = { 43062306a36Sopenharmony_ci .name = "stmpe801", 43162306a36Sopenharmony_ci .id_val = STMPE801_ID, 43262306a36Sopenharmony_ci .id_mask = 0xffff, 43362306a36Sopenharmony_ci .num_gpios = 8, 43462306a36Sopenharmony_ci .regs = stmpe801_regs, 43562306a36Sopenharmony_ci .blocks = stmpe801_blocks_noirq, 43662306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe801_blocks_noirq), 43762306a36Sopenharmony_ci .enable = stmpe801_enable, 43862306a36Sopenharmony_ci}; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci/* 44162306a36Sopenharmony_ci * Touchscreen (STMPE811 or STMPE610) 44262306a36Sopenharmony_ci */ 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic struct resource stmpe_ts_resources[] = { 44562306a36Sopenharmony_ci /* Start and end filled dynamically */ 44662306a36Sopenharmony_ci { 44762306a36Sopenharmony_ci .name = "TOUCH_DET", 44862306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 44962306a36Sopenharmony_ci }, 45062306a36Sopenharmony_ci { 45162306a36Sopenharmony_ci .name = "FIFO_TH", 45262306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 45362306a36Sopenharmony_ci }, 45462306a36Sopenharmony_ci}; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic const struct mfd_cell stmpe_ts_cell = { 45762306a36Sopenharmony_ci .name = "stmpe-ts", 45862306a36Sopenharmony_ci .of_compatible = "st,stmpe-ts", 45962306a36Sopenharmony_ci .resources = stmpe_ts_resources, 46062306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(stmpe_ts_resources), 46162306a36Sopenharmony_ci}; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci/* 46462306a36Sopenharmony_ci * ADC (STMPE811) 46562306a36Sopenharmony_ci */ 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic struct resource stmpe_adc_resources[] = { 46862306a36Sopenharmony_ci /* Start and end filled dynamically */ 46962306a36Sopenharmony_ci { 47062306a36Sopenharmony_ci .name = "STMPE_TEMP_SENS", 47162306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 47262306a36Sopenharmony_ci }, 47362306a36Sopenharmony_ci { 47462306a36Sopenharmony_ci .name = "STMPE_ADC", 47562306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 47662306a36Sopenharmony_ci }, 47762306a36Sopenharmony_ci}; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_cistatic const struct mfd_cell stmpe_adc_cell = { 48062306a36Sopenharmony_ci .name = "stmpe-adc", 48162306a36Sopenharmony_ci .of_compatible = "st,stmpe-adc", 48262306a36Sopenharmony_ci .resources = stmpe_adc_resources, 48362306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(stmpe_adc_resources), 48462306a36Sopenharmony_ci}; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci/* 48762306a36Sopenharmony_ci * STMPE811 or STMPE610 48862306a36Sopenharmony_ci */ 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic const u8 stmpe811_regs[] = { 49162306a36Sopenharmony_ci [STMPE_IDX_CHIP_ID] = STMPE811_REG_CHIP_ID, 49262306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL] = STMPE811_REG_SYS_CTRL, 49362306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL2] = STMPE811_REG_SYS_CTRL2, 49462306a36Sopenharmony_ci [STMPE_IDX_ICR_LSB] = STMPE811_REG_INT_CTRL, 49562306a36Sopenharmony_ci [STMPE_IDX_IER_LSB] = STMPE811_REG_INT_EN, 49662306a36Sopenharmony_ci [STMPE_IDX_ISR_MSB] = STMPE811_REG_INT_STA, 49762306a36Sopenharmony_ci [STMPE_IDX_GPMR_LSB] = STMPE811_REG_GPIO_MP_STA, 49862306a36Sopenharmony_ci [STMPE_IDX_GPSR_LSB] = STMPE811_REG_GPIO_SET_PIN, 49962306a36Sopenharmony_ci [STMPE_IDX_GPCR_LSB] = STMPE811_REG_GPIO_CLR_PIN, 50062306a36Sopenharmony_ci [STMPE_IDX_GPDR_LSB] = STMPE811_REG_GPIO_DIR, 50162306a36Sopenharmony_ci [STMPE_IDX_GPRER_LSB] = STMPE811_REG_GPIO_RE, 50262306a36Sopenharmony_ci [STMPE_IDX_GPFER_LSB] = STMPE811_REG_GPIO_FE, 50362306a36Sopenharmony_ci [STMPE_IDX_GPAFR_U_MSB] = STMPE811_REG_GPIO_AF, 50462306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_LSB] = STMPE811_REG_GPIO_INT_EN, 50562306a36Sopenharmony_ci [STMPE_IDX_ISGPIOR_MSB] = STMPE811_REG_GPIO_INT_STA, 50662306a36Sopenharmony_ci [STMPE_IDX_GPEDR_LSB] = STMPE811_REG_GPIO_ED, 50762306a36Sopenharmony_ci}; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_cistatic struct stmpe_variant_block stmpe811_blocks[] = { 51062306a36Sopenharmony_ci { 51162306a36Sopenharmony_ci .cell = &stmpe_gpio_cell, 51262306a36Sopenharmony_ci .irq = STMPE811_IRQ_GPIOC, 51362306a36Sopenharmony_ci .block = STMPE_BLOCK_GPIO, 51462306a36Sopenharmony_ci }, 51562306a36Sopenharmony_ci { 51662306a36Sopenharmony_ci .cell = &stmpe_ts_cell, 51762306a36Sopenharmony_ci .irq = STMPE811_IRQ_TOUCH_DET, 51862306a36Sopenharmony_ci .block = STMPE_BLOCK_TOUCHSCREEN, 51962306a36Sopenharmony_ci }, 52062306a36Sopenharmony_ci { 52162306a36Sopenharmony_ci .cell = &stmpe_adc_cell, 52262306a36Sopenharmony_ci .irq = STMPE811_IRQ_TEMP_SENS, 52362306a36Sopenharmony_ci .block = STMPE_BLOCK_ADC, 52462306a36Sopenharmony_ci }, 52562306a36Sopenharmony_ci}; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, 52862306a36Sopenharmony_ci bool enable) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci unsigned int mask = 0; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_GPIO) 53362306a36Sopenharmony_ci mask |= STMPE811_SYS_CTRL2_GPIO_OFF; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_ADC) 53662306a36Sopenharmony_ci mask |= STMPE811_SYS_CTRL2_ADC_OFF; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_TOUCHSCREEN) 53962306a36Sopenharmony_ci mask |= STMPE811_SYS_CTRL2_TSC_OFF; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2], mask, 54262306a36Sopenharmony_ci enable ? 0 : mask); 54362306a36Sopenharmony_ci} 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ciint stmpe811_adc_common_init(struct stmpe *stmpe) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci int ret; 54862306a36Sopenharmony_ci u8 adc_ctrl1, adc_ctrl1_mask; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) | 55162306a36Sopenharmony_ci STMPE_MOD_12B(stmpe->mod_12b) | 55262306a36Sopenharmony_ci STMPE_REF_SEL(stmpe->ref_sel); 55362306a36Sopenharmony_ci adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) | 55462306a36Sopenharmony_ci STMPE_REF_SEL(0xff); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL1, 55762306a36Sopenharmony_ci adc_ctrl1_mask, adc_ctrl1); 55862306a36Sopenharmony_ci if (ret) { 55962306a36Sopenharmony_ci dev_err(stmpe->dev, "Could not setup ADC\n"); 56062306a36Sopenharmony_ci return ret; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL2, 56462306a36Sopenharmony_ci STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq)); 56562306a36Sopenharmony_ci if (ret) { 56662306a36Sopenharmony_ci dev_err(stmpe->dev, "Could not setup ADC\n"); 56762306a36Sopenharmony_ci return ret; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci return 0; 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stmpe811_adc_common_init); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci /* 0 for touchscreen, 1 for GPIO */ 57762306a36Sopenharmony_ci return block != STMPE_BLOCK_TOUCHSCREEN; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe811 = { 58162306a36Sopenharmony_ci .name = "stmpe811", 58262306a36Sopenharmony_ci .id_val = 0x0811, 58362306a36Sopenharmony_ci .id_mask = 0xffff, 58462306a36Sopenharmony_ci .num_gpios = 8, 58562306a36Sopenharmony_ci .af_bits = 1, 58662306a36Sopenharmony_ci .regs = stmpe811_regs, 58762306a36Sopenharmony_ci .blocks = stmpe811_blocks, 58862306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe811_blocks), 58962306a36Sopenharmony_ci .num_irqs = STMPE811_NR_INTERNAL_IRQS, 59062306a36Sopenharmony_ci .enable = stmpe811_enable, 59162306a36Sopenharmony_ci .get_altfunc = stmpe811_get_altfunc, 59262306a36Sopenharmony_ci}; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci/* Similar to 811, except number of gpios */ 59562306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe610 = { 59662306a36Sopenharmony_ci .name = "stmpe610", 59762306a36Sopenharmony_ci .id_val = 0x0811, 59862306a36Sopenharmony_ci .id_mask = 0xffff, 59962306a36Sopenharmony_ci .num_gpios = 6, 60062306a36Sopenharmony_ci .af_bits = 1, 60162306a36Sopenharmony_ci .regs = stmpe811_regs, 60262306a36Sopenharmony_ci .blocks = stmpe811_blocks, 60362306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe811_blocks), 60462306a36Sopenharmony_ci .num_irqs = STMPE811_NR_INTERNAL_IRQS, 60562306a36Sopenharmony_ci .enable = stmpe811_enable, 60662306a36Sopenharmony_ci .get_altfunc = stmpe811_get_altfunc, 60762306a36Sopenharmony_ci}; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci/* 61062306a36Sopenharmony_ci * STMPE1600 61162306a36Sopenharmony_ci * Compared to all others STMPE variant, LSB and MSB regs are located in this 61262306a36Sopenharmony_ci * order : LSB addr 61362306a36Sopenharmony_ci * MSB addr + 1 61462306a36Sopenharmony_ci * As there is only 2 * 8bits registers for GPMR/GPSR/IEGPIOPR, CSB index is MSB registers 61562306a36Sopenharmony_ci */ 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_cistatic const u8 stmpe1600_regs[] = { 61862306a36Sopenharmony_ci [STMPE_IDX_CHIP_ID] = STMPE1600_REG_CHIP_ID, 61962306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL] = STMPE1600_REG_SYS_CTRL, 62062306a36Sopenharmony_ci [STMPE_IDX_ICR_LSB] = STMPE1600_REG_SYS_CTRL, 62162306a36Sopenharmony_ci [STMPE_IDX_GPMR_LSB] = STMPE1600_REG_GPMR_LSB, 62262306a36Sopenharmony_ci [STMPE_IDX_GPMR_CSB] = STMPE1600_REG_GPMR_MSB, 62362306a36Sopenharmony_ci [STMPE_IDX_GPSR_LSB] = STMPE1600_REG_GPSR_LSB, 62462306a36Sopenharmony_ci [STMPE_IDX_GPSR_CSB] = STMPE1600_REG_GPSR_MSB, 62562306a36Sopenharmony_ci [STMPE_IDX_GPCR_LSB] = STMPE1600_REG_GPSR_LSB, 62662306a36Sopenharmony_ci [STMPE_IDX_GPCR_CSB] = STMPE1600_REG_GPSR_MSB, 62762306a36Sopenharmony_ci [STMPE_IDX_GPDR_LSB] = STMPE1600_REG_GPDR_LSB, 62862306a36Sopenharmony_ci [STMPE_IDX_GPDR_CSB] = STMPE1600_REG_GPDR_MSB, 62962306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_LSB] = STMPE1600_REG_IEGPIOR_LSB, 63062306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_CSB] = STMPE1600_REG_IEGPIOR_MSB, 63162306a36Sopenharmony_ci [STMPE_IDX_ISGPIOR_LSB] = STMPE1600_REG_ISGPIOR_LSB, 63262306a36Sopenharmony_ci}; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_cistatic struct stmpe_variant_block stmpe1600_blocks[] = { 63562306a36Sopenharmony_ci { 63662306a36Sopenharmony_ci .cell = &stmpe_gpio_cell, 63762306a36Sopenharmony_ci .irq = 0, 63862306a36Sopenharmony_ci .block = STMPE_BLOCK_GPIO, 63962306a36Sopenharmony_ci }, 64062306a36Sopenharmony_ci}; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic int stmpe1600_enable(struct stmpe *stmpe, unsigned int blocks, 64362306a36Sopenharmony_ci bool enable) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_GPIO) 64662306a36Sopenharmony_ci return 0; 64762306a36Sopenharmony_ci else 64862306a36Sopenharmony_ci return -EINVAL; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe1600 = { 65262306a36Sopenharmony_ci .name = "stmpe1600", 65362306a36Sopenharmony_ci .id_val = STMPE1600_ID, 65462306a36Sopenharmony_ci .id_mask = 0xffff, 65562306a36Sopenharmony_ci .num_gpios = 16, 65662306a36Sopenharmony_ci .af_bits = 0, 65762306a36Sopenharmony_ci .regs = stmpe1600_regs, 65862306a36Sopenharmony_ci .blocks = stmpe1600_blocks, 65962306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe1600_blocks), 66062306a36Sopenharmony_ci .num_irqs = STMPE1600_NR_INTERNAL_IRQS, 66162306a36Sopenharmony_ci .enable = stmpe1600_enable, 66262306a36Sopenharmony_ci}; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci/* 66562306a36Sopenharmony_ci * STMPE1601 66662306a36Sopenharmony_ci */ 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic const u8 stmpe1601_regs[] = { 66962306a36Sopenharmony_ci [STMPE_IDX_CHIP_ID] = STMPE1601_REG_CHIP_ID, 67062306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL] = STMPE1601_REG_SYS_CTRL, 67162306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL2] = STMPE1601_REG_SYS_CTRL2, 67262306a36Sopenharmony_ci [STMPE_IDX_ICR_LSB] = STMPE1601_REG_ICR_LSB, 67362306a36Sopenharmony_ci [STMPE_IDX_IER_MSB] = STMPE1601_REG_IER_MSB, 67462306a36Sopenharmony_ci [STMPE_IDX_IER_LSB] = STMPE1601_REG_IER_LSB, 67562306a36Sopenharmony_ci [STMPE_IDX_ISR_MSB] = STMPE1601_REG_ISR_MSB, 67662306a36Sopenharmony_ci [STMPE_IDX_GPMR_LSB] = STMPE1601_REG_GPIO_MP_LSB, 67762306a36Sopenharmony_ci [STMPE_IDX_GPMR_CSB] = STMPE1601_REG_GPIO_MP_MSB, 67862306a36Sopenharmony_ci [STMPE_IDX_GPSR_LSB] = STMPE1601_REG_GPIO_SET_LSB, 67962306a36Sopenharmony_ci [STMPE_IDX_GPSR_CSB] = STMPE1601_REG_GPIO_SET_MSB, 68062306a36Sopenharmony_ci [STMPE_IDX_GPCR_LSB] = STMPE1601_REG_GPIO_CLR_LSB, 68162306a36Sopenharmony_ci [STMPE_IDX_GPCR_CSB] = STMPE1601_REG_GPIO_CLR_MSB, 68262306a36Sopenharmony_ci [STMPE_IDX_GPDR_LSB] = STMPE1601_REG_GPIO_SET_DIR_LSB, 68362306a36Sopenharmony_ci [STMPE_IDX_GPDR_CSB] = STMPE1601_REG_GPIO_SET_DIR_MSB, 68462306a36Sopenharmony_ci [STMPE_IDX_GPEDR_LSB] = STMPE1601_REG_GPIO_ED_LSB, 68562306a36Sopenharmony_ci [STMPE_IDX_GPEDR_CSB] = STMPE1601_REG_GPIO_ED_MSB, 68662306a36Sopenharmony_ci [STMPE_IDX_GPRER_LSB] = STMPE1601_REG_GPIO_RE_LSB, 68762306a36Sopenharmony_ci [STMPE_IDX_GPRER_CSB] = STMPE1601_REG_GPIO_RE_MSB, 68862306a36Sopenharmony_ci [STMPE_IDX_GPFER_LSB] = STMPE1601_REG_GPIO_FE_LSB, 68962306a36Sopenharmony_ci [STMPE_IDX_GPFER_CSB] = STMPE1601_REG_GPIO_FE_MSB, 69062306a36Sopenharmony_ci [STMPE_IDX_GPPUR_LSB] = STMPE1601_REG_GPIO_PU_LSB, 69162306a36Sopenharmony_ci [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB, 69262306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB, 69362306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_CSB] = STMPE1601_REG_INT_EN_GPIO_MASK_MSB, 69462306a36Sopenharmony_ci [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB, 69562306a36Sopenharmony_ci}; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic struct stmpe_variant_block stmpe1601_blocks[] = { 69862306a36Sopenharmony_ci { 69962306a36Sopenharmony_ci .cell = &stmpe_gpio_cell, 70062306a36Sopenharmony_ci .irq = STMPE1601_IRQ_GPIOC, 70162306a36Sopenharmony_ci .block = STMPE_BLOCK_GPIO, 70262306a36Sopenharmony_ci }, 70362306a36Sopenharmony_ci { 70462306a36Sopenharmony_ci .cell = &stmpe_keypad_cell, 70562306a36Sopenharmony_ci .irq = STMPE1601_IRQ_KEYPAD, 70662306a36Sopenharmony_ci .block = STMPE_BLOCK_KEYPAD, 70762306a36Sopenharmony_ci }, 70862306a36Sopenharmony_ci { 70962306a36Sopenharmony_ci .cell = &stmpe_pwm_cell, 71062306a36Sopenharmony_ci .irq = STMPE1601_IRQ_PWM0, 71162306a36Sopenharmony_ci .block = STMPE_BLOCK_PWM, 71262306a36Sopenharmony_ci }, 71362306a36Sopenharmony_ci}; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci/* supported autosleep timeout delay (in msecs) */ 71662306a36Sopenharmony_cistatic const int stmpe_autosleep_delay[] = { 71762306a36Sopenharmony_ci 4, 16, 32, 64, 128, 256, 512, 1024, 71862306a36Sopenharmony_ci}; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic int stmpe_round_timeout(int timeout) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci int i; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) { 72562306a36Sopenharmony_ci if (stmpe_autosleep_delay[i] >= timeout) 72662306a36Sopenharmony_ci return i; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* 73062306a36Sopenharmony_ci * requests for delays longer than supported should not return the 73162306a36Sopenharmony_ci * longest supported delay 73262306a36Sopenharmony_ci */ 73362306a36Sopenharmony_ci return -EINVAL; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic int stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci int ret; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci if (!stmpe->variant->enable_autosleep) 74162306a36Sopenharmony_ci return -ENOSYS; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci mutex_lock(&stmpe->lock); 74462306a36Sopenharmony_ci ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout); 74562306a36Sopenharmony_ci mutex_unlock(&stmpe->lock); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci return ret; 74862306a36Sopenharmony_ci} 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci/* 75162306a36Sopenharmony_ci * Both stmpe 1601/2403 support same layout for autosleep 75262306a36Sopenharmony_ci */ 75362306a36Sopenharmony_cistatic int stmpe1601_autosleep(struct stmpe *stmpe, 75462306a36Sopenharmony_ci int autosleep_timeout) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci int ret, timeout; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci /* choose the best available timeout */ 75962306a36Sopenharmony_ci timeout = stmpe_round_timeout(autosleep_timeout); 76062306a36Sopenharmony_ci if (timeout < 0) { 76162306a36Sopenharmony_ci dev_err(stmpe->dev, "invalid timeout\n"); 76262306a36Sopenharmony_ci return timeout; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2], 76662306a36Sopenharmony_ci STMPE1601_AUTOSLEEP_TIMEOUT_MASK, 76762306a36Sopenharmony_ci timeout); 76862306a36Sopenharmony_ci if (ret < 0) 76962306a36Sopenharmony_ci return ret; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2], 77262306a36Sopenharmony_ci STPME1601_AUTOSLEEP_ENABLE, 77362306a36Sopenharmony_ci STPME1601_AUTOSLEEP_ENABLE); 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cistatic int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks, 77762306a36Sopenharmony_ci bool enable) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci unsigned int mask = 0; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_GPIO) 78262306a36Sopenharmony_ci mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO; 78362306a36Sopenharmony_ci else 78462306a36Sopenharmony_ci mask &= ~STMPE1601_SYS_CTRL_ENABLE_GPIO; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_KEYPAD) 78762306a36Sopenharmony_ci mask |= STMPE1601_SYS_CTRL_ENABLE_KPC; 78862306a36Sopenharmony_ci else 78962306a36Sopenharmony_ci mask &= ~STMPE1601_SYS_CTRL_ENABLE_KPC; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_PWM) 79262306a36Sopenharmony_ci mask |= STMPE1601_SYS_CTRL_ENABLE_SPWM; 79362306a36Sopenharmony_ci else 79462306a36Sopenharmony_ci mask &= ~STMPE1601_SYS_CTRL_ENABLE_SPWM; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], mask, 79762306a36Sopenharmony_ci enable ? mask : 0); 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_cistatic int stmpe1601_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci switch (block) { 80362306a36Sopenharmony_ci case STMPE_BLOCK_PWM: 80462306a36Sopenharmony_ci return 2; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci case STMPE_BLOCK_KEYPAD: 80762306a36Sopenharmony_ci return 1; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci case STMPE_BLOCK_GPIO: 81062306a36Sopenharmony_ci default: 81162306a36Sopenharmony_ci return 0; 81262306a36Sopenharmony_ci } 81362306a36Sopenharmony_ci} 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe1601 = { 81662306a36Sopenharmony_ci .name = "stmpe1601", 81762306a36Sopenharmony_ci .id_val = 0x0210, 81862306a36Sopenharmony_ci .id_mask = 0xfff0, /* at least 0x0210 and 0x0212 */ 81962306a36Sopenharmony_ci .num_gpios = 16, 82062306a36Sopenharmony_ci .af_bits = 2, 82162306a36Sopenharmony_ci .regs = stmpe1601_regs, 82262306a36Sopenharmony_ci .blocks = stmpe1601_blocks, 82362306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe1601_blocks), 82462306a36Sopenharmony_ci .num_irqs = STMPE1601_NR_INTERNAL_IRQS, 82562306a36Sopenharmony_ci .enable = stmpe1601_enable, 82662306a36Sopenharmony_ci .get_altfunc = stmpe1601_get_altfunc, 82762306a36Sopenharmony_ci .enable_autosleep = stmpe1601_autosleep, 82862306a36Sopenharmony_ci}; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci/* 83162306a36Sopenharmony_ci * STMPE1801 83262306a36Sopenharmony_ci */ 83362306a36Sopenharmony_cistatic const u8 stmpe1801_regs[] = { 83462306a36Sopenharmony_ci [STMPE_IDX_CHIP_ID] = STMPE1801_REG_CHIP_ID, 83562306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL] = STMPE1801_REG_SYS_CTRL, 83662306a36Sopenharmony_ci [STMPE_IDX_ICR_LSB] = STMPE1801_REG_INT_CTRL_LOW, 83762306a36Sopenharmony_ci [STMPE_IDX_IER_LSB] = STMPE1801_REG_INT_EN_MASK_LOW, 83862306a36Sopenharmony_ci [STMPE_IDX_ISR_LSB] = STMPE1801_REG_INT_STA_LOW, 83962306a36Sopenharmony_ci [STMPE_IDX_GPMR_LSB] = STMPE1801_REG_GPIO_MP_LOW, 84062306a36Sopenharmony_ci [STMPE_IDX_GPMR_CSB] = STMPE1801_REG_GPIO_MP_MID, 84162306a36Sopenharmony_ci [STMPE_IDX_GPMR_MSB] = STMPE1801_REG_GPIO_MP_HIGH, 84262306a36Sopenharmony_ci [STMPE_IDX_GPSR_LSB] = STMPE1801_REG_GPIO_SET_LOW, 84362306a36Sopenharmony_ci [STMPE_IDX_GPSR_CSB] = STMPE1801_REG_GPIO_SET_MID, 84462306a36Sopenharmony_ci [STMPE_IDX_GPSR_MSB] = STMPE1801_REG_GPIO_SET_HIGH, 84562306a36Sopenharmony_ci [STMPE_IDX_GPCR_LSB] = STMPE1801_REG_GPIO_CLR_LOW, 84662306a36Sopenharmony_ci [STMPE_IDX_GPCR_CSB] = STMPE1801_REG_GPIO_CLR_MID, 84762306a36Sopenharmony_ci [STMPE_IDX_GPCR_MSB] = STMPE1801_REG_GPIO_CLR_HIGH, 84862306a36Sopenharmony_ci [STMPE_IDX_GPDR_LSB] = STMPE1801_REG_GPIO_SET_DIR_LOW, 84962306a36Sopenharmony_ci [STMPE_IDX_GPDR_CSB] = STMPE1801_REG_GPIO_SET_DIR_MID, 85062306a36Sopenharmony_ci [STMPE_IDX_GPDR_MSB] = STMPE1801_REG_GPIO_SET_DIR_HIGH, 85162306a36Sopenharmony_ci [STMPE_IDX_GPRER_LSB] = STMPE1801_REG_GPIO_RE_LOW, 85262306a36Sopenharmony_ci [STMPE_IDX_GPRER_CSB] = STMPE1801_REG_GPIO_RE_MID, 85362306a36Sopenharmony_ci [STMPE_IDX_GPRER_MSB] = STMPE1801_REG_GPIO_RE_HIGH, 85462306a36Sopenharmony_ci [STMPE_IDX_GPFER_LSB] = STMPE1801_REG_GPIO_FE_LOW, 85562306a36Sopenharmony_ci [STMPE_IDX_GPFER_CSB] = STMPE1801_REG_GPIO_FE_MID, 85662306a36Sopenharmony_ci [STMPE_IDX_GPFER_MSB] = STMPE1801_REG_GPIO_FE_HIGH, 85762306a36Sopenharmony_ci [STMPE_IDX_GPPUR_LSB] = STMPE1801_REG_GPIO_PULL_UP_LOW, 85862306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_LSB] = STMPE1801_REG_INT_EN_GPIO_MASK_LOW, 85962306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_CSB] = STMPE1801_REG_INT_EN_GPIO_MASK_MID, 86062306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_MSB] = STMPE1801_REG_INT_EN_GPIO_MASK_HIGH, 86162306a36Sopenharmony_ci [STMPE_IDX_ISGPIOR_MSB] = STMPE1801_REG_INT_STA_GPIO_HIGH, 86262306a36Sopenharmony_ci}; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cistatic struct stmpe_variant_block stmpe1801_blocks[] = { 86562306a36Sopenharmony_ci { 86662306a36Sopenharmony_ci .cell = &stmpe_gpio_cell, 86762306a36Sopenharmony_ci .irq = STMPE1801_IRQ_GPIOC, 86862306a36Sopenharmony_ci .block = STMPE_BLOCK_GPIO, 86962306a36Sopenharmony_ci }, 87062306a36Sopenharmony_ci { 87162306a36Sopenharmony_ci .cell = &stmpe_keypad_cell, 87262306a36Sopenharmony_ci .irq = STMPE1801_IRQ_KEYPAD, 87362306a36Sopenharmony_ci .block = STMPE_BLOCK_KEYPAD, 87462306a36Sopenharmony_ci }, 87562306a36Sopenharmony_ci}; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_cistatic int stmpe1801_enable(struct stmpe *stmpe, unsigned int blocks, 87862306a36Sopenharmony_ci bool enable) 87962306a36Sopenharmony_ci{ 88062306a36Sopenharmony_ci unsigned int mask = 0; 88162306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_GPIO) 88262306a36Sopenharmony_ci mask |= STMPE1801_MSK_INT_EN_GPIO; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_KEYPAD) 88562306a36Sopenharmony_ci mask |= STMPE1801_MSK_INT_EN_KPC; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci return __stmpe_set_bits(stmpe, STMPE1801_REG_INT_EN_MASK_LOW, mask, 88862306a36Sopenharmony_ci enable ? mask : 0); 88962306a36Sopenharmony_ci} 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_cistatic int stmpe_reset(struct stmpe *stmpe) 89262306a36Sopenharmony_ci{ 89362306a36Sopenharmony_ci u16 id_val = stmpe->variant->id_val; 89462306a36Sopenharmony_ci unsigned long timeout; 89562306a36Sopenharmony_ci int ret = 0; 89662306a36Sopenharmony_ci u8 reset_bit; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci if (id_val == STMPE811_ID) 89962306a36Sopenharmony_ci /* STMPE801 and STMPE610 use bit 1 of SYS_CTRL register */ 90062306a36Sopenharmony_ci reset_bit = STMPE811_SYS_CTRL_RESET; 90162306a36Sopenharmony_ci else 90262306a36Sopenharmony_ci /* all other STMPE variant use bit 7 of SYS_CTRL register */ 90362306a36Sopenharmony_ci reset_bit = STMPE_SYS_CTRL_RESET; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], 90662306a36Sopenharmony_ci reset_bit, reset_bit); 90762306a36Sopenharmony_ci if (ret < 0) 90862306a36Sopenharmony_ci return ret; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci msleep(10); 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(100); 91362306a36Sopenharmony_ci while (time_before(jiffies, timeout)) { 91462306a36Sopenharmony_ci ret = __stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL]); 91562306a36Sopenharmony_ci if (ret < 0) 91662306a36Sopenharmony_ci return ret; 91762306a36Sopenharmony_ci if (!(ret & reset_bit)) 91862306a36Sopenharmony_ci return 0; 91962306a36Sopenharmony_ci usleep_range(100, 200); 92062306a36Sopenharmony_ci } 92162306a36Sopenharmony_ci return -EIO; 92262306a36Sopenharmony_ci} 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe1801 = { 92562306a36Sopenharmony_ci .name = "stmpe1801", 92662306a36Sopenharmony_ci .id_val = STMPE1801_ID, 92762306a36Sopenharmony_ci .id_mask = 0xfff0, 92862306a36Sopenharmony_ci .num_gpios = 18, 92962306a36Sopenharmony_ci .af_bits = 0, 93062306a36Sopenharmony_ci .regs = stmpe1801_regs, 93162306a36Sopenharmony_ci .blocks = stmpe1801_blocks, 93262306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe1801_blocks), 93362306a36Sopenharmony_ci .num_irqs = STMPE1801_NR_INTERNAL_IRQS, 93462306a36Sopenharmony_ci .enable = stmpe1801_enable, 93562306a36Sopenharmony_ci /* stmpe1801 do not have any gpio alternate function */ 93662306a36Sopenharmony_ci .get_altfunc = NULL, 93762306a36Sopenharmony_ci}; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci/* 94062306a36Sopenharmony_ci * STMPE24XX 94162306a36Sopenharmony_ci */ 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_cistatic const u8 stmpe24xx_regs[] = { 94462306a36Sopenharmony_ci [STMPE_IDX_CHIP_ID] = STMPE24XX_REG_CHIP_ID, 94562306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL] = STMPE24XX_REG_SYS_CTRL, 94662306a36Sopenharmony_ci [STMPE_IDX_SYS_CTRL2] = STMPE24XX_REG_SYS_CTRL2, 94762306a36Sopenharmony_ci [STMPE_IDX_ICR_LSB] = STMPE24XX_REG_ICR_LSB, 94862306a36Sopenharmony_ci [STMPE_IDX_IER_MSB] = STMPE24XX_REG_IER_MSB, 94962306a36Sopenharmony_ci [STMPE_IDX_IER_LSB] = STMPE24XX_REG_IER_LSB, 95062306a36Sopenharmony_ci [STMPE_IDX_ISR_MSB] = STMPE24XX_REG_ISR_MSB, 95162306a36Sopenharmony_ci [STMPE_IDX_GPMR_LSB] = STMPE24XX_REG_GPMR_LSB, 95262306a36Sopenharmony_ci [STMPE_IDX_GPMR_CSB] = STMPE24XX_REG_GPMR_CSB, 95362306a36Sopenharmony_ci [STMPE_IDX_GPMR_MSB] = STMPE24XX_REG_GPMR_MSB, 95462306a36Sopenharmony_ci [STMPE_IDX_GPSR_LSB] = STMPE24XX_REG_GPSR_LSB, 95562306a36Sopenharmony_ci [STMPE_IDX_GPSR_CSB] = STMPE24XX_REG_GPSR_CSB, 95662306a36Sopenharmony_ci [STMPE_IDX_GPSR_MSB] = STMPE24XX_REG_GPSR_MSB, 95762306a36Sopenharmony_ci [STMPE_IDX_GPCR_LSB] = STMPE24XX_REG_GPCR_LSB, 95862306a36Sopenharmony_ci [STMPE_IDX_GPCR_CSB] = STMPE24XX_REG_GPCR_CSB, 95962306a36Sopenharmony_ci [STMPE_IDX_GPCR_MSB] = STMPE24XX_REG_GPCR_MSB, 96062306a36Sopenharmony_ci [STMPE_IDX_GPDR_LSB] = STMPE24XX_REG_GPDR_LSB, 96162306a36Sopenharmony_ci [STMPE_IDX_GPDR_CSB] = STMPE24XX_REG_GPDR_CSB, 96262306a36Sopenharmony_ci [STMPE_IDX_GPDR_MSB] = STMPE24XX_REG_GPDR_MSB, 96362306a36Sopenharmony_ci [STMPE_IDX_GPRER_LSB] = STMPE24XX_REG_GPRER_LSB, 96462306a36Sopenharmony_ci [STMPE_IDX_GPRER_CSB] = STMPE24XX_REG_GPRER_CSB, 96562306a36Sopenharmony_ci [STMPE_IDX_GPRER_MSB] = STMPE24XX_REG_GPRER_MSB, 96662306a36Sopenharmony_ci [STMPE_IDX_GPFER_LSB] = STMPE24XX_REG_GPFER_LSB, 96762306a36Sopenharmony_ci [STMPE_IDX_GPFER_CSB] = STMPE24XX_REG_GPFER_CSB, 96862306a36Sopenharmony_ci [STMPE_IDX_GPFER_MSB] = STMPE24XX_REG_GPFER_MSB, 96962306a36Sopenharmony_ci [STMPE_IDX_GPPUR_LSB] = STMPE24XX_REG_GPPUR_LSB, 97062306a36Sopenharmony_ci [STMPE_IDX_GPPDR_LSB] = STMPE24XX_REG_GPPDR_LSB, 97162306a36Sopenharmony_ci [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB, 97262306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB, 97362306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_CSB] = STMPE24XX_REG_IEGPIOR_CSB, 97462306a36Sopenharmony_ci [STMPE_IDX_IEGPIOR_MSB] = STMPE24XX_REG_IEGPIOR_MSB, 97562306a36Sopenharmony_ci [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB, 97662306a36Sopenharmony_ci [STMPE_IDX_GPEDR_LSB] = STMPE24XX_REG_GPEDR_LSB, 97762306a36Sopenharmony_ci [STMPE_IDX_GPEDR_CSB] = STMPE24XX_REG_GPEDR_CSB, 97862306a36Sopenharmony_ci [STMPE_IDX_GPEDR_MSB] = STMPE24XX_REG_GPEDR_MSB, 97962306a36Sopenharmony_ci}; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cistatic struct stmpe_variant_block stmpe24xx_blocks[] = { 98262306a36Sopenharmony_ci { 98362306a36Sopenharmony_ci .cell = &stmpe_gpio_cell, 98462306a36Sopenharmony_ci .irq = STMPE24XX_IRQ_GPIOC, 98562306a36Sopenharmony_ci .block = STMPE_BLOCK_GPIO, 98662306a36Sopenharmony_ci }, 98762306a36Sopenharmony_ci { 98862306a36Sopenharmony_ci .cell = &stmpe_keypad_cell, 98962306a36Sopenharmony_ci .irq = STMPE24XX_IRQ_KEYPAD, 99062306a36Sopenharmony_ci .block = STMPE_BLOCK_KEYPAD, 99162306a36Sopenharmony_ci }, 99262306a36Sopenharmony_ci { 99362306a36Sopenharmony_ci .cell = &stmpe_pwm_cell, 99462306a36Sopenharmony_ci .irq = STMPE24XX_IRQ_PWM0, 99562306a36Sopenharmony_ci .block = STMPE_BLOCK_PWM, 99662306a36Sopenharmony_ci }, 99762306a36Sopenharmony_ci}; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_cistatic int stmpe24xx_enable(struct stmpe *stmpe, unsigned int blocks, 100062306a36Sopenharmony_ci bool enable) 100162306a36Sopenharmony_ci{ 100262306a36Sopenharmony_ci unsigned int mask = 0; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_GPIO) 100562306a36Sopenharmony_ci mask |= STMPE24XX_SYS_CTRL_ENABLE_GPIO; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (blocks & STMPE_BLOCK_KEYPAD) 100862306a36Sopenharmony_ci mask |= STMPE24XX_SYS_CTRL_ENABLE_KPC; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci return __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL], mask, 101162306a36Sopenharmony_ci enable ? mask : 0); 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_cistatic int stmpe24xx_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) 101562306a36Sopenharmony_ci{ 101662306a36Sopenharmony_ci switch (block) { 101762306a36Sopenharmony_ci case STMPE_BLOCK_ROTATOR: 101862306a36Sopenharmony_ci return 2; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci case STMPE_BLOCK_KEYPAD: 102162306a36Sopenharmony_ci case STMPE_BLOCK_PWM: 102262306a36Sopenharmony_ci return 1; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci case STMPE_BLOCK_GPIO: 102562306a36Sopenharmony_ci default: 102662306a36Sopenharmony_ci return 0; 102762306a36Sopenharmony_ci } 102862306a36Sopenharmony_ci} 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe2401 = { 103162306a36Sopenharmony_ci .name = "stmpe2401", 103262306a36Sopenharmony_ci .id_val = 0x0101, 103362306a36Sopenharmony_ci .id_mask = 0xffff, 103462306a36Sopenharmony_ci .num_gpios = 24, 103562306a36Sopenharmony_ci .af_bits = 2, 103662306a36Sopenharmony_ci .regs = stmpe24xx_regs, 103762306a36Sopenharmony_ci .blocks = stmpe24xx_blocks, 103862306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), 103962306a36Sopenharmony_ci .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, 104062306a36Sopenharmony_ci .enable = stmpe24xx_enable, 104162306a36Sopenharmony_ci .get_altfunc = stmpe24xx_get_altfunc, 104262306a36Sopenharmony_ci}; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_cistatic struct stmpe_variant_info stmpe2403 = { 104562306a36Sopenharmony_ci .name = "stmpe2403", 104662306a36Sopenharmony_ci .id_val = 0x0120, 104762306a36Sopenharmony_ci .id_mask = 0xffff, 104862306a36Sopenharmony_ci .num_gpios = 24, 104962306a36Sopenharmony_ci .af_bits = 2, 105062306a36Sopenharmony_ci .regs = stmpe24xx_regs, 105162306a36Sopenharmony_ci .blocks = stmpe24xx_blocks, 105262306a36Sopenharmony_ci .num_blocks = ARRAY_SIZE(stmpe24xx_blocks), 105362306a36Sopenharmony_ci .num_irqs = STMPE24XX_NR_INTERNAL_IRQS, 105462306a36Sopenharmony_ci .enable = stmpe24xx_enable, 105562306a36Sopenharmony_ci .get_altfunc = stmpe24xx_get_altfunc, 105662306a36Sopenharmony_ci .enable_autosleep = stmpe1601_autosleep, /* same as stmpe1601 */ 105762306a36Sopenharmony_ci}; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_cistatic struct stmpe_variant_info *stmpe_variant_info[STMPE_NBR_PARTS] = { 106062306a36Sopenharmony_ci [STMPE610] = &stmpe610, 106162306a36Sopenharmony_ci [STMPE801] = &stmpe801, 106262306a36Sopenharmony_ci [STMPE811] = &stmpe811, 106362306a36Sopenharmony_ci [STMPE1600] = &stmpe1600, 106462306a36Sopenharmony_ci [STMPE1601] = &stmpe1601, 106562306a36Sopenharmony_ci [STMPE1801] = &stmpe1801, 106662306a36Sopenharmony_ci [STMPE2401] = &stmpe2401, 106762306a36Sopenharmony_ci [STMPE2403] = &stmpe2403, 106862306a36Sopenharmony_ci}; 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci/* 107162306a36Sopenharmony_ci * These devices can be connected in a 'no-irq' configuration - the irq pin 107262306a36Sopenharmony_ci * is not used and the device cannot interrupt the CPU. Here we only list 107362306a36Sopenharmony_ci * devices which support this configuration - the driver will fail probing 107462306a36Sopenharmony_ci * for any devices not listed here which are configured in this way. 107562306a36Sopenharmony_ci */ 107662306a36Sopenharmony_cistatic struct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = { 107762306a36Sopenharmony_ci [STMPE801] = &stmpe801_noirq, 107862306a36Sopenharmony_ci}; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_cistatic irqreturn_t stmpe_irq(int irq, void *data) 108162306a36Sopenharmony_ci{ 108262306a36Sopenharmony_ci struct stmpe *stmpe = data; 108362306a36Sopenharmony_ci struct stmpe_variant_info *variant = stmpe->variant; 108462306a36Sopenharmony_ci int num = DIV_ROUND_UP(variant->num_irqs, 8); 108562306a36Sopenharmony_ci u8 israddr; 108662306a36Sopenharmony_ci u8 isr[3]; 108762306a36Sopenharmony_ci int ret; 108862306a36Sopenharmony_ci int i; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci if (variant->id_val == STMPE801_ID || 109162306a36Sopenharmony_ci variant->id_val == STMPE1600_ID) { 109262306a36Sopenharmony_ci int base = irq_find_mapping(stmpe->domain, 0); 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci handle_nested_irq(base); 109562306a36Sopenharmony_ci return IRQ_HANDLED; 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci if (variant->id_val == STMPE1801_ID) 109962306a36Sopenharmony_ci israddr = stmpe->regs[STMPE_IDX_ISR_LSB]; 110062306a36Sopenharmony_ci else 110162306a36Sopenharmony_ci israddr = stmpe->regs[STMPE_IDX_ISR_MSB]; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci ret = stmpe_block_read(stmpe, israddr, num, isr); 110462306a36Sopenharmony_ci if (ret < 0) 110562306a36Sopenharmony_ci return IRQ_NONE; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci for (i = 0; i < num; i++) { 110862306a36Sopenharmony_ci int bank = num - i - 1; 110962306a36Sopenharmony_ci u8 status = isr[i]; 111062306a36Sopenharmony_ci u8 clear; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci status &= stmpe->ier[bank]; 111362306a36Sopenharmony_ci if (!status) 111462306a36Sopenharmony_ci continue; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci clear = status; 111762306a36Sopenharmony_ci while (status) { 111862306a36Sopenharmony_ci int bit = __ffs(status); 111962306a36Sopenharmony_ci int line = bank * 8 + bit; 112062306a36Sopenharmony_ci int nestedirq = irq_find_mapping(stmpe->domain, line); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci handle_nested_irq(nestedirq); 112362306a36Sopenharmony_ci status &= ~(1 << bit); 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci stmpe_reg_write(stmpe, israddr + i, clear); 112762306a36Sopenharmony_ci } 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci return IRQ_HANDLED; 113062306a36Sopenharmony_ci} 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_cistatic void stmpe_irq_lock(struct irq_data *data) 113362306a36Sopenharmony_ci{ 113462306a36Sopenharmony_ci struct stmpe *stmpe = irq_data_get_irq_chip_data(data); 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci mutex_lock(&stmpe->irq_lock); 113762306a36Sopenharmony_ci} 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_cistatic void stmpe_irq_sync_unlock(struct irq_data *data) 114062306a36Sopenharmony_ci{ 114162306a36Sopenharmony_ci struct stmpe *stmpe = irq_data_get_irq_chip_data(data); 114262306a36Sopenharmony_ci struct stmpe_variant_info *variant = stmpe->variant; 114362306a36Sopenharmony_ci int num = DIV_ROUND_UP(variant->num_irqs, 8); 114462306a36Sopenharmony_ci int i; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci for (i = 0; i < num; i++) { 114762306a36Sopenharmony_ci u8 new = stmpe->ier[i]; 114862306a36Sopenharmony_ci u8 old = stmpe->oldier[i]; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci if (new == old) 115162306a36Sopenharmony_ci continue; 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci stmpe->oldier[i] = new; 115462306a36Sopenharmony_ci stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_IER_LSB + i], new); 115562306a36Sopenharmony_ci } 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci mutex_unlock(&stmpe->irq_lock); 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_cistatic void stmpe_irq_mask(struct irq_data *data) 116162306a36Sopenharmony_ci{ 116262306a36Sopenharmony_ci struct stmpe *stmpe = irq_data_get_irq_chip_data(data); 116362306a36Sopenharmony_ci int offset = data->hwirq; 116462306a36Sopenharmony_ci int regoffset = offset / 8; 116562306a36Sopenharmony_ci int mask = 1 << (offset % 8); 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci stmpe->ier[regoffset] &= ~mask; 116862306a36Sopenharmony_ci} 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_cistatic void stmpe_irq_unmask(struct irq_data *data) 117162306a36Sopenharmony_ci{ 117262306a36Sopenharmony_ci struct stmpe *stmpe = irq_data_get_irq_chip_data(data); 117362306a36Sopenharmony_ci int offset = data->hwirq; 117462306a36Sopenharmony_ci int regoffset = offset / 8; 117562306a36Sopenharmony_ci int mask = 1 << (offset % 8); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci stmpe->ier[regoffset] |= mask; 117862306a36Sopenharmony_ci} 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_cistatic struct irq_chip stmpe_irq_chip = { 118162306a36Sopenharmony_ci .name = "stmpe", 118262306a36Sopenharmony_ci .irq_bus_lock = stmpe_irq_lock, 118362306a36Sopenharmony_ci .irq_bus_sync_unlock = stmpe_irq_sync_unlock, 118462306a36Sopenharmony_ci .irq_mask = stmpe_irq_mask, 118562306a36Sopenharmony_ci .irq_unmask = stmpe_irq_unmask, 118662306a36Sopenharmony_ci}; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_cistatic int stmpe_irq_map(struct irq_domain *d, unsigned int virq, 118962306a36Sopenharmony_ci irq_hw_number_t hwirq) 119062306a36Sopenharmony_ci{ 119162306a36Sopenharmony_ci struct stmpe *stmpe = d->host_data; 119262306a36Sopenharmony_ci struct irq_chip *chip = NULL; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci if (stmpe->variant->id_val != STMPE801_ID) 119562306a36Sopenharmony_ci chip = &stmpe_irq_chip; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci irq_set_chip_data(virq, stmpe); 119862306a36Sopenharmony_ci irq_set_chip_and_handler(virq, chip, handle_edge_irq); 119962306a36Sopenharmony_ci irq_set_nested_thread(virq, 1); 120062306a36Sopenharmony_ci irq_set_noprobe(virq); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci return 0; 120362306a36Sopenharmony_ci} 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_cistatic void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq) 120662306a36Sopenharmony_ci{ 120762306a36Sopenharmony_ci irq_set_chip_and_handler(virq, NULL, NULL); 120862306a36Sopenharmony_ci irq_set_chip_data(virq, NULL); 120962306a36Sopenharmony_ci} 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_cistatic const struct irq_domain_ops stmpe_irq_ops = { 121262306a36Sopenharmony_ci .map = stmpe_irq_map, 121362306a36Sopenharmony_ci .unmap = stmpe_irq_unmap, 121462306a36Sopenharmony_ci .xlate = irq_domain_xlate_twocell, 121562306a36Sopenharmony_ci}; 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cistatic int stmpe_irq_init(struct stmpe *stmpe, struct device_node *np) 121862306a36Sopenharmony_ci{ 121962306a36Sopenharmony_ci int base = 0; 122062306a36Sopenharmony_ci int num_irqs = stmpe->variant->num_irqs; 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci stmpe->domain = irq_domain_add_simple(np, num_irqs, base, 122362306a36Sopenharmony_ci &stmpe_irq_ops, stmpe); 122462306a36Sopenharmony_ci if (!stmpe->domain) { 122562306a36Sopenharmony_ci dev_err(stmpe->dev, "Failed to create irqdomain\n"); 122662306a36Sopenharmony_ci return -ENOSYS; 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci return 0; 123062306a36Sopenharmony_ci} 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_cistatic int stmpe_chip_init(struct stmpe *stmpe) 123362306a36Sopenharmony_ci{ 123462306a36Sopenharmony_ci unsigned int irq_trigger = stmpe->pdata->irq_trigger; 123562306a36Sopenharmony_ci int autosleep_timeout = stmpe->pdata->autosleep_timeout; 123662306a36Sopenharmony_ci struct stmpe_variant_info *variant = stmpe->variant; 123762306a36Sopenharmony_ci u8 icr = 0; 123862306a36Sopenharmony_ci unsigned int id; 123962306a36Sopenharmony_ci u8 data[2]; 124062306a36Sopenharmony_ci int ret; 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci ret = stmpe_block_read(stmpe, stmpe->regs[STMPE_IDX_CHIP_ID], 124362306a36Sopenharmony_ci ARRAY_SIZE(data), data); 124462306a36Sopenharmony_ci if (ret < 0) 124562306a36Sopenharmony_ci return ret; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci id = (data[0] << 8) | data[1]; 124862306a36Sopenharmony_ci if ((id & variant->id_mask) != variant->id_val) { 124962306a36Sopenharmony_ci dev_err(stmpe->dev, "unknown chip id: %#x\n", id); 125062306a36Sopenharmony_ci return -EINVAL; 125162306a36Sopenharmony_ci } 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci dev_info(stmpe->dev, "%s detected, chip id: %#x\n", variant->name, id); 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci /* Disable all modules -- subdrivers should enable what they need. */ 125662306a36Sopenharmony_ci ret = stmpe_disable(stmpe, ~0); 125762306a36Sopenharmony_ci if (ret) 125862306a36Sopenharmony_ci return ret; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci ret = stmpe_reset(stmpe); 126162306a36Sopenharmony_ci if (ret < 0) 126262306a36Sopenharmony_ci return ret; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci if (stmpe->irq >= 0) { 126562306a36Sopenharmony_ci if (id == STMPE801_ID || id == STMPE1600_ID) 126662306a36Sopenharmony_ci icr = STMPE_SYS_CTRL_INT_EN; 126762306a36Sopenharmony_ci else 126862306a36Sopenharmony_ci icr = STMPE_ICR_LSB_GIM; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci /* STMPE801 and STMPE1600 don't support Edge interrupts */ 127162306a36Sopenharmony_ci if (id != STMPE801_ID && id != STMPE1600_ID) { 127262306a36Sopenharmony_ci if (irq_trigger == IRQF_TRIGGER_FALLING || 127362306a36Sopenharmony_ci irq_trigger == IRQF_TRIGGER_RISING) 127462306a36Sopenharmony_ci icr |= STMPE_ICR_LSB_EDGE; 127562306a36Sopenharmony_ci } 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci if (irq_trigger == IRQF_TRIGGER_RISING || 127862306a36Sopenharmony_ci irq_trigger == IRQF_TRIGGER_HIGH) { 127962306a36Sopenharmony_ci if (id == STMPE801_ID || id == STMPE1600_ID) 128062306a36Sopenharmony_ci icr |= STMPE_SYS_CTRL_INT_HI; 128162306a36Sopenharmony_ci else 128262306a36Sopenharmony_ci icr |= STMPE_ICR_LSB_HIGH; 128362306a36Sopenharmony_ci } 128462306a36Sopenharmony_ci } 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci if (stmpe->pdata->autosleep) { 128762306a36Sopenharmony_ci ret = stmpe_autosleep(stmpe, autosleep_timeout); 128862306a36Sopenharmony_ci if (ret) 128962306a36Sopenharmony_ci return ret; 129062306a36Sopenharmony_ci } 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr); 129362306a36Sopenharmony_ci} 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_cistatic int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell) 129662306a36Sopenharmony_ci{ 129762306a36Sopenharmony_ci return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1, 129862306a36Sopenharmony_ci NULL, 0, stmpe->domain); 129962306a36Sopenharmony_ci} 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_cistatic int stmpe_devices_init(struct stmpe *stmpe) 130262306a36Sopenharmony_ci{ 130362306a36Sopenharmony_ci struct stmpe_variant_info *variant = stmpe->variant; 130462306a36Sopenharmony_ci unsigned int platform_blocks = stmpe->pdata->blocks; 130562306a36Sopenharmony_ci int ret = -EINVAL; 130662306a36Sopenharmony_ci int i, j; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci for (i = 0; i < variant->num_blocks; i++) { 130962306a36Sopenharmony_ci struct stmpe_variant_block *block = &variant->blocks[i]; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci if (!(platform_blocks & block->block)) 131262306a36Sopenharmony_ci continue; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci for (j = 0; j < block->cell->num_resources; j++) { 131562306a36Sopenharmony_ci struct resource *res = 131662306a36Sopenharmony_ci (struct resource *) &block->cell->resources[j]; 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci /* Dynamically fill in a variant's IRQ. */ 131962306a36Sopenharmony_ci if (res->flags & IORESOURCE_IRQ) 132062306a36Sopenharmony_ci res->start = res->end = block->irq + j; 132162306a36Sopenharmony_ci } 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci platform_blocks &= ~block->block; 132462306a36Sopenharmony_ci ret = stmpe_add_device(stmpe, block->cell); 132562306a36Sopenharmony_ci if (ret) 132662306a36Sopenharmony_ci return ret; 132762306a36Sopenharmony_ci } 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci if (platform_blocks) 133062306a36Sopenharmony_ci dev_warn(stmpe->dev, 133162306a36Sopenharmony_ci "platform wants blocks (%#x) not present on variant", 133262306a36Sopenharmony_ci platform_blocks); 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci return ret; 133562306a36Sopenharmony_ci} 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_cistatic void stmpe_of_probe(struct stmpe_platform_data *pdata, 133862306a36Sopenharmony_ci struct device_node *np) 133962306a36Sopenharmony_ci{ 134062306a36Sopenharmony_ci struct device_node *child; 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci pdata->id = of_alias_get_id(np, "stmpe-i2c"); 134362306a36Sopenharmony_ci if (pdata->id < 0) 134462306a36Sopenharmony_ci pdata->id = -1; 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci of_property_read_u32(np, "st,autosleep-timeout", 134762306a36Sopenharmony_ci &pdata->autosleep_timeout); 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci pdata->autosleep = (pdata->autosleep_timeout) ? true : false; 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci for_each_available_child_of_node(np, child) { 135262306a36Sopenharmony_ci if (of_device_is_compatible(child, stmpe_gpio_cell.of_compatible)) 135362306a36Sopenharmony_ci pdata->blocks |= STMPE_BLOCK_GPIO; 135462306a36Sopenharmony_ci else if (of_device_is_compatible(child, stmpe_keypad_cell.of_compatible)) 135562306a36Sopenharmony_ci pdata->blocks |= STMPE_BLOCK_KEYPAD; 135662306a36Sopenharmony_ci else if (of_device_is_compatible(child, stmpe_ts_cell.of_compatible)) 135762306a36Sopenharmony_ci pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN; 135862306a36Sopenharmony_ci else if (of_device_is_compatible(child, stmpe_adc_cell.of_compatible)) 135962306a36Sopenharmony_ci pdata->blocks |= STMPE_BLOCK_ADC; 136062306a36Sopenharmony_ci else if (of_device_is_compatible(child, stmpe_pwm_cell.of_compatible)) 136162306a36Sopenharmony_ci pdata->blocks |= STMPE_BLOCK_PWM; 136262306a36Sopenharmony_ci } 136362306a36Sopenharmony_ci} 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci/* Called from client specific probe routines */ 136662306a36Sopenharmony_ciint stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) 136762306a36Sopenharmony_ci{ 136862306a36Sopenharmony_ci struct stmpe_platform_data *pdata; 136962306a36Sopenharmony_ci struct device_node *np = ci->dev->of_node; 137062306a36Sopenharmony_ci struct stmpe *stmpe; 137162306a36Sopenharmony_ci struct gpio_desc *irq_gpio; 137262306a36Sopenharmony_ci int ret; 137362306a36Sopenharmony_ci u32 val; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); 137662306a36Sopenharmony_ci if (!pdata) 137762306a36Sopenharmony_ci return -ENOMEM; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci stmpe_of_probe(pdata, np); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci if (!of_property_present(np, "interrupts")) 138262306a36Sopenharmony_ci ci->irq = -1; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci stmpe = devm_kzalloc(ci->dev, sizeof(struct stmpe), GFP_KERNEL); 138562306a36Sopenharmony_ci if (!stmpe) 138662306a36Sopenharmony_ci return -ENOMEM; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci mutex_init(&stmpe->irq_lock); 138962306a36Sopenharmony_ci mutex_init(&stmpe->lock); 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,sample-time", &val)) 139262306a36Sopenharmony_ci stmpe->sample_time = val; 139362306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,mod-12b", &val)) 139462306a36Sopenharmony_ci stmpe->mod_12b = val; 139562306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,ref-sel", &val)) 139662306a36Sopenharmony_ci stmpe->ref_sel = val; 139762306a36Sopenharmony_ci if (!of_property_read_u32(np, "st,adc-freq", &val)) 139862306a36Sopenharmony_ci stmpe->adc_freq = val; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci stmpe->dev = ci->dev; 140162306a36Sopenharmony_ci stmpe->client = ci->client; 140262306a36Sopenharmony_ci stmpe->pdata = pdata; 140362306a36Sopenharmony_ci stmpe->ci = ci; 140462306a36Sopenharmony_ci stmpe->partnum = partnum; 140562306a36Sopenharmony_ci stmpe->variant = stmpe_variant_info[partnum]; 140662306a36Sopenharmony_ci stmpe->regs = stmpe->variant->regs; 140762306a36Sopenharmony_ci stmpe->num_gpios = stmpe->variant->num_gpios; 140862306a36Sopenharmony_ci stmpe->vcc = devm_regulator_get_optional(ci->dev, "vcc"); 140962306a36Sopenharmony_ci if (!IS_ERR(stmpe->vcc)) { 141062306a36Sopenharmony_ci ret = regulator_enable(stmpe->vcc); 141162306a36Sopenharmony_ci if (ret) 141262306a36Sopenharmony_ci dev_warn(ci->dev, "failed to enable VCC supply\n"); 141362306a36Sopenharmony_ci } 141462306a36Sopenharmony_ci stmpe->vio = devm_regulator_get_optional(ci->dev, "vio"); 141562306a36Sopenharmony_ci if (!IS_ERR(stmpe->vio)) { 141662306a36Sopenharmony_ci ret = regulator_enable(stmpe->vio); 141762306a36Sopenharmony_ci if (ret) 141862306a36Sopenharmony_ci dev_warn(ci->dev, "failed to enable VIO supply\n"); 141962306a36Sopenharmony_ci } 142062306a36Sopenharmony_ci dev_set_drvdata(stmpe->dev, stmpe); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci if (ci->init) 142362306a36Sopenharmony_ci ci->init(stmpe); 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci irq_gpio = devm_gpiod_get_optional(ci->dev, "irq", GPIOD_ASIS); 142662306a36Sopenharmony_ci ret = PTR_ERR_OR_ZERO(irq_gpio); 142762306a36Sopenharmony_ci if (ret) { 142862306a36Sopenharmony_ci dev_err(stmpe->dev, "failed to request IRQ GPIO: %d\n", ret); 142962306a36Sopenharmony_ci return ret; 143062306a36Sopenharmony_ci } 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci if (irq_gpio) { 143362306a36Sopenharmony_ci stmpe->irq = gpiod_to_irq(irq_gpio); 143462306a36Sopenharmony_ci pdata->irq_trigger = gpiod_is_active_low(irq_gpio) ? 143562306a36Sopenharmony_ci IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH; 143662306a36Sopenharmony_ci } else { 143762306a36Sopenharmony_ci stmpe->irq = ci->irq; 143862306a36Sopenharmony_ci pdata->irq_trigger = IRQF_TRIGGER_NONE; 143962306a36Sopenharmony_ci } 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci if (stmpe->irq < 0) { 144262306a36Sopenharmony_ci /* use alternate variant info for no-irq mode, if supported */ 144362306a36Sopenharmony_ci dev_info(stmpe->dev, 144462306a36Sopenharmony_ci "%s configured in no-irq mode by platform data\n", 144562306a36Sopenharmony_ci stmpe->variant->name); 144662306a36Sopenharmony_ci if (!stmpe_noirq_variant_info[stmpe->partnum]) { 144762306a36Sopenharmony_ci dev_err(stmpe->dev, 144862306a36Sopenharmony_ci "%s does not support no-irq mode!\n", 144962306a36Sopenharmony_ci stmpe->variant->name); 145062306a36Sopenharmony_ci return -ENODEV; 145162306a36Sopenharmony_ci } 145262306a36Sopenharmony_ci stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum]; 145362306a36Sopenharmony_ci } else if (pdata->irq_trigger == IRQF_TRIGGER_NONE) { 145462306a36Sopenharmony_ci pdata->irq_trigger = irq_get_trigger_type(stmpe->irq); 145562306a36Sopenharmony_ci } 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci ret = stmpe_chip_init(stmpe); 145862306a36Sopenharmony_ci if (ret) 145962306a36Sopenharmony_ci return ret; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci if (stmpe->irq >= 0) { 146262306a36Sopenharmony_ci ret = stmpe_irq_init(stmpe, np); 146362306a36Sopenharmony_ci if (ret) 146462306a36Sopenharmony_ci return ret; 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci ret = devm_request_threaded_irq(ci->dev, stmpe->irq, NULL, 146762306a36Sopenharmony_ci stmpe_irq, pdata->irq_trigger | IRQF_ONESHOT, 146862306a36Sopenharmony_ci "stmpe", stmpe); 146962306a36Sopenharmony_ci if (ret) { 147062306a36Sopenharmony_ci dev_err(stmpe->dev, "failed to request IRQ: %d\n", 147162306a36Sopenharmony_ci ret); 147262306a36Sopenharmony_ci return ret; 147362306a36Sopenharmony_ci } 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci ret = stmpe_devices_init(stmpe); 147762306a36Sopenharmony_ci if (!ret) 147862306a36Sopenharmony_ci return 0; 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci dev_err(stmpe->dev, "failed to add children\n"); 148162306a36Sopenharmony_ci mfd_remove_devices(stmpe->dev); 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci return ret; 148462306a36Sopenharmony_ci} 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_civoid stmpe_remove(struct stmpe *stmpe) 148762306a36Sopenharmony_ci{ 148862306a36Sopenharmony_ci if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio)) 148962306a36Sopenharmony_ci regulator_disable(stmpe->vio); 149062306a36Sopenharmony_ci if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc)) 149162306a36Sopenharmony_ci regulator_disable(stmpe->vcc); 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci __stmpe_disable(stmpe, STMPE_BLOCK_ADC); 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci mfd_remove_devices(stmpe->dev); 149662306a36Sopenharmony_ci} 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_cistatic int stmpe_suspend(struct device *dev) 149962306a36Sopenharmony_ci{ 150062306a36Sopenharmony_ci struct stmpe *stmpe = dev_get_drvdata(dev); 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci if (stmpe->irq >= 0 && device_may_wakeup(dev)) 150362306a36Sopenharmony_ci enable_irq_wake(stmpe->irq); 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci return 0; 150662306a36Sopenharmony_ci} 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_cistatic int stmpe_resume(struct device *dev) 150962306a36Sopenharmony_ci{ 151062306a36Sopenharmony_ci struct stmpe *stmpe = dev_get_drvdata(dev); 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci if (stmpe->irq >= 0 && device_may_wakeup(dev)) 151362306a36Sopenharmony_ci disable_irq_wake(stmpe->irq); 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci return 0; 151662306a36Sopenharmony_ci} 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ciEXPORT_GPL_SIMPLE_DEV_PM_OPS(stmpe_dev_pm_ops, 151962306a36Sopenharmony_ci stmpe_suspend, stmpe_resume); 1520