staticvoid cyttsp_hard_reset(struct cyttsp *ts)
{ if (ts->reset_gpio) { /* * According to the CY8CTMA340 datasheet page 21, the external * reset pulse width should be >= 1 ms. The datasheet does not * specify how long we have to wait after reset but a vendor * tree specifies 5 ms here.
*/
gpiod_set_value_cansleep(ts->reset_gpio, 1);
usleep_range(1000, 2000);
gpiod_set_value_cansleep(ts->reset_gpio, 0);
usleep_range(5000, 6000);
}
}
staticint cyttsp_soft_reset(struct cyttsp *ts)
{ int retval;
/* wait for interrupt to set ready completion */
reinit_completion(&ts->bl_ready);
ts->state = CY_BL_STATE;
enable_irq(ts->irq);
retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE); if (retval) {
dev_err(ts->dev, "failed to send soft reset\n"); goto out;
}
if (!wait_for_completion_timeout(&ts->bl_ready,
msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX))) {
dev_err(ts->dev, "timeout waiting for soft reset\n");
retval = -EIO;
}
if (unlikely(ts->state == CY_BL_STATE)) {
complete(&ts->bl_ready); goto out;
}
/* Get touch data from CYTTSP device */
error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(struct cyttsp_xydata), &ts->xy_data); if (error) goto out;
/* provide flow control handshake */
error = cyttsp_handshake(ts); if (error) goto out;
if (unlikely(ts->state == CY_IDLE_STATE)) goto out;
if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) { /* * TTSP device has reset back to bootloader mode. * Restore to operational mode.
*/
error = cyttsp_exit_bl_mode(ts); if (error) {
dev_err(ts->dev, "Could not return to operational mode, err: %d\n",
error);
ts->state = CY_IDLE_STATE;
}
} else {
cyttsp_report_tchdata(ts);
}
out: return IRQ_HANDLED;
}
staticint cyttsp_power_on(struct cyttsp *ts)
{ int error;
error = cyttsp_soft_reset(ts); if (error) return error;
error = cyttsp_load_bl_regs(ts); if (error) return error;
if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
IS_VALID_APP(ts->bl_data.bl_status)) {
error = cyttsp_exit_bl_mode(ts); if (error) {
dev_err(ts->dev, "failed to exit bootloader mode\n"); return error;
}
}
if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE ||
IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) { return -ENODEV;
}
error = cyttsp_set_sysinfo_mode(ts); if (error) return error;
error = cyttsp_set_sysinfo_regs(ts); if (error) return error;
error = cyttsp_set_operational_mode(ts); if (error) return error;
/* init active distance */
error = cyttsp_act_dist_setup(ts); if (error) return error;
ts->state = CY_ACTIVE_STATE;
return 0;
}
staticint cyttsp_enable(struct cyttsp *ts)
{ int error;
/* * The device firmware can wake on an I2C or SPI memory slave * address match. So just reading a register is sufficient to * wake up the device. The first read attempt will fail but it * will wake it up making the second read attempt successful.
*/
error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->xy_data), &ts->xy_data); if (error) return error;
if (GET_HSTMODE(ts->xy_data.hst_mode)) return -EIO;
enable_irq(ts->irq);
return 0;
}
staticint cyttsp_disable(struct cyttsp *ts)
{ int error;
error = ttsp_send_command(ts, CY_LOW_POWER_MODE); if (error) return error;
ret = device_property_read_u8_array(dev, "bootloader-key",
ts->bl_keys, CY_NUM_BL_KEYS); if (ret) {
dev_err(dev, "bootloader-key property could not be retrieved\n"); return ret;
}
if (!device_property_read_u32(dev, "active-distance", &dt_value)) { if (dt_value > 15) {
dev_err(dev, "active-distance (%u) must be [0-15]\n",
dt_value); return -EINVAL;
}
ts->act_dist &= ~CY_ACT_DIST_MASK;
ts->act_dist |= dt_value;
}
if (!device_property_read_u32(dev, "active-interval-ms", &dt_value)) { if (dt_value > 255) {
dev_err(dev, "active-interval-ms (%u) must be [0-255]\n",
dt_value); return -EINVAL;
}
ts->act_intrvl = dt_value;
}
if (!device_property_read_u32(dev, "lowpower-interval-ms", &dt_value)) { if (dt_value > 2550) {
dev_err(dev, "lowpower-interval-ms (%u) must be [0-2550]\n",
dt_value); return -EINVAL;
} /* Register value is expressed in 0.01s / bit */
ts->lp_intrvl = dt_value / 10;
}
if (!device_property_read_u32(dev, "touch-timeout-ms", &dt_value)) { if (dt_value > 2550) {
dev_err(dev, "touch-timeout-ms (%u) must be [0-2550]\n",
dt_value); return -EINVAL;
} /* Register value is expressed in 0.01s / bit */
ts->tch_tmout = dt_value / 10;
}
return 0;
}
struct cyttsp *cyttsp_probe(conststruct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size)
{ /* * VCPIN is the analog voltage supply * VDD is the digital voltage supply
*/ staticconstchar * const supplies[] = { "vcpin", "vdd" }; struct cyttsp *ts; struct input_dev *input_dev; int error;
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); /* One byte for width 0..255 so this is the limit */
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
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.