/** * struct stmpe_platform_data - STMPE platform data * @id: device id to distinguish between multiple STMPEs on the same board * @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*) * @irq_trigger: IRQ trigger to use for the interrupt to the host * @autosleep: bool to enable/disable stmpe autosleep * @autosleep_timeout: inactivity timeout in milliseconds for autosleep
*/ struct stmpe_platform_data { int id; unsignedint blocks; unsignedint irq_trigger; bool autosleep; int autosleep_timeout;
};
ret = stmpe->ci->write_block(stmpe, reg, length, values); if (ret < 0)
dev_err(stmpe->dev, "failed to write regs %#x: %d\n", reg, ret);
return ret;
}
/** * stmpe_enable - enable blocks on an STMPE device * @stmpe: Device to work on * @blocks: Mask of blocks (enum stmpe_block values) to enable
*/ int stmpe_enable(struct stmpe *stmpe, unsignedint blocks)
{ int ret;
mutex_lock(&stmpe->lock);
ret = __stmpe_enable(stmpe, blocks);
mutex_unlock(&stmpe->lock);
return ret;
}
EXPORT_SYMBOL_GPL(stmpe_enable);
/** * stmpe_disable - disable blocks on an STMPE device * @stmpe: Device to work on * @blocks: Mask of blocks (enum stmpe_block values) to enable
*/ int stmpe_disable(struct stmpe *stmpe, unsignedint blocks)
{ int ret;
mutex_lock(&stmpe->lock);
ret = __stmpe_disable(stmpe, blocks);
mutex_unlock(&stmpe->lock);
return ret;
}
EXPORT_SYMBOL_GPL(stmpe_disable);
/** * stmpe_reg_read() - read a single STMPE register * @stmpe: Device to read from * @reg: Register to read
*/ int stmpe_reg_read(struct stmpe *stmpe, u8 reg)
{ int ret;
mutex_lock(&stmpe->lock);
ret = __stmpe_reg_read(stmpe, reg);
mutex_unlock(&stmpe->lock);
return ret;
}
EXPORT_SYMBOL_GPL(stmpe_reg_read);
/** * stmpe_reg_write() - write a single STMPE register * @stmpe: Device to write to * @reg: Register to write * @val: Value to write
*/ int stmpe_reg_write(struct stmpe *stmpe, u8 reg, u8 val)
{ int ret;
mutex_lock(&stmpe->lock);
ret = __stmpe_reg_write(stmpe, reg, val);
mutex_unlock(&stmpe->lock);
return ret;
}
EXPORT_SYMBOL_GPL(stmpe_reg_write);
/** * stmpe_set_bits() - set the value of a bitfield in a STMPE register * @stmpe: Device to write to * @reg: Register to write * @mask: Mask of bits to set * @val: Value to set
*/ int stmpe_set_bits(struct stmpe *stmpe, u8 reg, u8 mask, u8 val)
{ int ret;
mutex_lock(&stmpe->lock);
ret = __stmpe_set_bits(stmpe, reg, mask, val);
mutex_unlock(&stmpe->lock);
return ret;
}
EXPORT_SYMBOL_GPL(stmpe_set_bits);
/** * stmpe_block_read() - read multiple STMPE registers * @stmpe: Device to read from * @reg: First register * @length: Number of registers * @values: Buffer to write to
*/ int stmpe_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values)
{ int ret;
mutex_lock(&stmpe->lock);
ret = __stmpe_block_read(stmpe, reg, length, values);
mutex_unlock(&stmpe->lock);
/** * stmpe_set_altfunc()- set the alternate function for STMPE pins * @stmpe: Device to configure * @pins: Bitmask of pins to affect * @block: block to enable alternate functions for * * @pins is assumed to have a bit set for each of the bits whose alternate * function is to be changed, numbered according to the GPIOXY numbers. * * If the GPIO module is not enabled, this function automatically enables it in * order to perform the change.
*/ int stmpe_set_altfunc(struct stmpe *stmpe, u32 pins, enum stmpe_block block)
{ struct stmpe_variant_info *variant = stmpe->variant;
u8 regaddr = stmpe->regs[STMPE_IDX_GPAFR_U_MSB]; int af_bits = variant->af_bits; int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8); int mask = (1 << af_bits) - 1;
u8 regs[8]; int af, afperreg, ret;
if (!variant->get_altfunc) return 0;
afperreg = 8 / af_bits;
mutex_lock(&stmpe->lock);
ret = __stmpe_enable(stmpe, STMPE_BLOCK_GPIO); if (ret < 0) goto out;
ret = __stmpe_block_read(stmpe, regaddr, numregs, regs); if (ret < 0) goto out;
af = variant->get_altfunc(stmpe, block);
while (pins) { int pin = __ffs(pins); int regoffset = numregs - (pin / afperreg) - 1; int pos = (pin % afperreg) * (8 / afperreg);
regs[regoffset] &= ~(mask << pos);
regs[regoffset] |= af << pos;
pins &= ~(1 << pin);
}
ret = __stmpe_block_write(stmpe, regaddr, numregs, regs);
staticconststruct mfd_cell stmpe_gpio_cell_noirq = {
.name = "stmpe-gpio",
.of_compatible = "st,stmpe-gpio", /* gpio cell resources consist of an irq only so no resources here */
};
/* * STMPE1600 * Compared to all others STMPE variant, LSB and MSB regs are located in this * order : LSB addr * MSB addr + 1 * As there is only 2 * 8bits registers for GPMR/GPSR/IEGPIOPR, CSB index is MSB registers
*/
staticint stmpe_round_timeout(int timeout)
{ int i;
for (i = 0; i < ARRAY_SIZE(stmpe_autosleep_delay); i++) { if (stmpe_autosleep_delay[i] >= timeout) return i;
}
/* * requests for delays longer than supported should not return the * longest supported delay
*/ return -EINVAL;
}
staticint stmpe_autosleep(struct stmpe *stmpe, int autosleep_timeout)
{ int ret;
if (!stmpe->variant->enable_autosleep) return -ENOSYS;
mutex_lock(&stmpe->lock);
ret = stmpe->variant->enable_autosleep(stmpe, autosleep_timeout);
mutex_unlock(&stmpe->lock);
return ret;
}
/* * Both stmpe 1601/2403 support same layout for autosleep
*/ staticint stmpe1601_autosleep(struct stmpe *stmpe, int autosleep_timeout)
{ int ret, timeout;
/* choose the best available timeout */
timeout = stmpe_round_timeout(autosleep_timeout); if (timeout < 0) {
dev_err(stmpe->dev, "invalid timeout\n"); return timeout;
}
ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL2],
STMPE1601_AUTOSLEEP_TIMEOUT_MASK,
timeout); if (ret < 0) return ret;
staticint stmpe_reset(struct stmpe *stmpe)
{
u16 id_val = stmpe->variant->id_val; unsignedlong timeout; int ret = 0;
u8 reset_bit;
if (id_val == STMPE811_ID) /* STMPE801 and STMPE610 use bit 1 of SYS_CTRL register */
reset_bit = STMPE811_SYS_CTRL_RESET; else /* all other STMPE variant use bit 7 of SYS_CTRL register */
reset_bit = STMPE_SYS_CTRL_RESET;
ret = __stmpe_set_bits(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL],
reset_bit, reset_bit); if (ret < 0) return ret;
msleep(10);
timeout = jiffies + msecs_to_jiffies(100); while (time_before(jiffies, timeout)) {
ret = __stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_SYS_CTRL]); if (ret < 0) return ret; if (!(ret & reset_bit)) return 0;
usleep_range(100, 200);
} return -EIO;
}
staticstruct stmpe_variant_info stmpe1801 = {
.name = "stmpe1801",
.id_val = STMPE1801_ID,
.id_mask = 0xfff0,
.num_gpios = 18,
.af_bits = 0,
.regs = stmpe1801_regs,
.blocks = stmpe1801_blocks,
.num_blocks = ARRAY_SIZE(stmpe1801_blocks),
.num_irqs = STMPE1801_NR_INTERNAL_IRQS,
.enable = stmpe1801_enable, /* stmpe1801 do not have any gpio alternate function */
.get_altfunc = NULL,
};
/* * These devices can be connected in a 'no-irq' configuration - the irq pin * is not used and the device cannot interrupt the CPU. Here we only list * devices which support this configuration - the driver will fail probing * for any devices not listed here which are configured in this way.
*/ staticstruct stmpe_variant_info *stmpe_noirq_variant_info[STMPE_NBR_PARTS] = {
[STMPE801] = &stmpe801_noirq,
};
static irqreturn_t stmpe_irq(int irq, void *data)
{ struct stmpe *stmpe = data; struct stmpe_variant_info *variant = stmpe->variant; int num = DIV_ROUND_UP(variant->num_irqs, 8);
u8 israddr;
u8 isr[3]; int ret; int i;
if (variant->id_val == STMPE801_ID ||
variant->id_val == STMPE1600_ID) { int base = irq_find_mapping(stmpe->domain, 0);
/* Disable all modules -- subdrivers should enable what they need. */
ret = stmpe_disable(stmpe, ~0); if (ret) return ret;
ret = stmpe_reset(stmpe); if (ret < 0) return ret;
if (stmpe->irq >= 0) { if (id == STMPE801_ID || id == STMPE1600_ID)
icr = STMPE_SYS_CTRL_INT_EN; else
icr = STMPE_ICR_LSB_GIM;
/* STMPE801 and STMPE1600 don't support Edge interrupts */ if (id != STMPE801_ID && id != STMPE1600_ID) { if (irq_trigger == IRQF_TRIGGER_FALLING ||
irq_trigger == IRQF_TRIGGER_RISING)
icr |= STMPE_ICR_LSB_EDGE;
}
if (irq_trigger == IRQF_TRIGGER_RISING ||
irq_trigger == IRQF_TRIGGER_HIGH) { if (id == STMPE801_ID || id == STMPE1600_ID)
icr |= STMPE_SYS_CTRL_INT_HI; else
icr |= STMPE_ICR_LSB_HIGH;
}
}
if (stmpe->pdata->autosleep) {
ret = stmpe_autosleep(stmpe, autosleep_timeout); if (ret) return ret;
}
if (stmpe->irq < 0) { /* use alternate variant info for no-irq mode, if supported */
dev_info(stmpe->dev, "%s configured in no-irq mode by platform data\n",
stmpe->variant->name); if (!stmpe_noirq_variant_info[stmpe->partnum]) {
dev_err(stmpe->dev, "%s does not support no-irq mode!\n",
stmpe->variant->name); return -ENODEV;
}
stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum];
} elseif (pdata->irq_trigger == IRQF_TRIGGER_NONE) {
pdata->irq_trigger = irq_get_trigger_type(stmpe->irq);
}
ret = stmpe_chip_init(stmpe); if (ret) return ret;
if (stmpe->irq >= 0) {
ret = stmpe_irq_init(stmpe, np); if (ret) return ret;
ret = devm_request_threaded_irq(ci->dev, stmpe->irq, NULL,
stmpe_irq, pdata->irq_trigger | IRQF_ONESHOT, "stmpe", stmpe); if (ret) {
dev_err(stmpe->dev, "failed to request IRQ: %d\n",
ret); return ret;
}
}
ret = stmpe_devices_init(stmpe); if (!ret) return 0;
dev_err(stmpe->dev, "failed to add children\n");
mfd_remove_devices(stmpe->dev);
return ret;
}
void stmpe_remove(struct stmpe *stmpe)
{ if (stmpe->domain)
irq_domain_remove(stmpe->domain);
if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio))
regulator_disable(stmpe->vio); if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc))
regulator_disable(stmpe->vcc);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.