diff options
| -rw-r--r-- | drivers/input/touchscreen/tsc2005.c | 100 |
1 files changed, 81 insertions, 19 deletions
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 7a7653390187..5a15919ec4c7 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c | |||
| @@ -146,7 +146,7 @@ struct tsc2005 { | |||
| 146 | void (*set_reset)(bool enable); | 146 | void (*set_reset)(bool enable); |
| 147 | }; | 147 | }; |
| 148 | 148 | ||
| 149 | static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd) | 149 | static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd) |
| 150 | { | 150 | { |
| 151 | u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd; | 151 | u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd; |
| 152 | struct spi_transfer xfer = { | 152 | struct spi_transfer xfer = { |
| @@ -155,13 +155,22 @@ static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd) | |||
| 155 | .bits_per_word = 8, | 155 | .bits_per_word = 8, |
| 156 | }; | 156 | }; |
| 157 | struct spi_message msg; | 157 | struct spi_message msg; |
| 158 | int error; | ||
| 158 | 159 | ||
| 159 | spi_message_init(&msg); | 160 | spi_message_init(&msg); |
| 160 | spi_message_add_tail(&xfer, &msg); | 161 | spi_message_add_tail(&xfer, &msg); |
| 161 | spi_sync(ts->spi, &msg); | 162 | |
| 163 | error = spi_sync(ts->spi, &msg); | ||
| 164 | if (error) { | ||
| 165 | dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n", | ||
| 166 | __func__, cmd, error); | ||
| 167 | return error; | ||
| 168 | } | ||
| 169 | |||
| 170 | return 0; | ||
| 162 | } | 171 | } |
| 163 | 172 | ||
| 164 | static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) | 173 | static int tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) |
| 165 | { | 174 | { |
| 166 | u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value; | 175 | u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value; |
| 167 | struct spi_transfer xfer = { | 176 | struct spi_transfer xfer = { |
| @@ -170,10 +179,20 @@ static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value) | |||
| 170 | .bits_per_word = 24, | 179 | .bits_per_word = 24, |
| 171 | }; | 180 | }; |
| 172 | struct spi_message msg; | 181 | struct spi_message msg; |
| 182 | int error; | ||
| 173 | 183 | ||
| 174 | spi_message_init(&msg); | 184 | spi_message_init(&msg); |
| 175 | spi_message_add_tail(&xfer, &msg); | 185 | spi_message_add_tail(&xfer, &msg); |
| 176 | spi_sync(ts->spi, &msg); | 186 | |
| 187 | error = spi_sync(ts->spi, &msg); | ||
| 188 | if (error) { | ||
| 189 | dev_err(&ts->spi->dev, | ||
| 190 | "%s: failed, register: %x, value: %x, error: %d\n", | ||
| 191 | __func__, reg, value, error); | ||
| 192 | return error; | ||
| 193 | } | ||
| 194 | |||
| 195 | return 0; | ||
| 177 | } | 196 | } |
| 178 | 197 | ||
| 179 | static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) | 198 | static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) |
| @@ -188,18 +207,23 @@ static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last) | |||
| 188 | rd->spi_xfer.cs_change = !last; | 207 | rd->spi_xfer.cs_change = !last; |
| 189 | } | 208 | } |
| 190 | 209 | ||
| 191 | static void tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) | 210 | static int tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value) |
| 192 | { | 211 | { |
| 193 | struct tsc2005_spi_rd spi_rd; | 212 | struct tsc2005_spi_rd spi_rd; |
| 194 | struct spi_message msg; | 213 | struct spi_message msg; |
| 214 | int error; | ||
| 195 | 215 | ||
| 196 | tsc2005_setup_read(&spi_rd, reg, true); | 216 | tsc2005_setup_read(&spi_rd, reg, true); |
| 197 | 217 | ||
| 198 | spi_message_init(&msg); | 218 | spi_message_init(&msg); |
| 199 | spi_message_add_tail(&spi_rd.spi_xfer, &msg); | 219 | spi_message_add_tail(&spi_rd.spi_xfer, &msg); |
| 200 | spi_sync(ts->spi, &msg); | 220 | |
| 221 | error = spi_sync(ts->spi, &msg); | ||
| 222 | if (error) | ||
| 223 | return error; | ||
| 201 | 224 | ||
| 202 | *value = spi_rd.spi_rx; | 225 | *value = spi_rd.spi_rx; |
| 226 | return 0; | ||
| 203 | } | 227 | } |
| 204 | 228 | ||
| 205 | static void tsc2005_update_pen_state(struct tsc2005 *ts, | 229 | static void tsc2005_update_pen_state(struct tsc2005 *ts, |
| @@ -232,6 +256,7 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) | |||
| 232 | unsigned int pressure; | 256 | unsigned int pressure; |
| 233 | u32 x, y; | 257 | u32 x, y; |
| 234 | u32 z1, z2; | 258 | u32 z1, z2; |
| 259 | int error; | ||
| 235 | 260 | ||
| 236 | mutex_lock(&ts->mutex); | 261 | mutex_lock(&ts->mutex); |
| 237 | 262 | ||
| @@ -239,7 +264,10 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts) | |||
| 239 | goto out; | 264 | goto out; |
| 240 | 265 | ||
| 241 | /* read the coordinates */ | 266 | /* read the coordinates */ |
| 242 | spi_sync(ts->spi, &ts->spi_read_msg); | 267 | error = spi_sync(ts->spi, &ts->spi_read_msg); |
| 268 | if (unlikely(error)) | ||
| 269 | goto out; | ||
| 270 | |||
| 243 | x = ts->spi_x.spi_rx; | 271 | x = ts->spi_x.spi_rx; |
| 244 | y = ts->spi_y.spi_rx; | 272 | y = ts->spi_y.spi_rx; |
| 245 | z1 = ts->spi_z1.spi_rx; | 273 | z1 = ts->spi_z1.spi_rx; |
| @@ -392,7 +420,8 @@ static ssize_t tsc2005_selftest_show(struct device *dev, | |||
| 392 | u16 temp_high; | 420 | u16 temp_high; |
| 393 | u16 temp_high_orig; | 421 | u16 temp_high_orig; |
| 394 | u16 temp_high_test; | 422 | u16 temp_high_test; |
| 395 | unsigned int result; | 423 | bool success = true; |
| 424 | int error; | ||
| 396 | 425 | ||
| 397 | mutex_lock(&ts->mutex); | 426 | mutex_lock(&ts->mutex); |
| 398 | 427 | ||
| @@ -400,34 +429,65 @@ static ssize_t tsc2005_selftest_show(struct device *dev, | |||
| 400 | * Test TSC2005 communications via temp high register. | 429 | * Test TSC2005 communications via temp high register. |
| 401 | */ | 430 | */ |
| 402 | tsc2005_disable(ts); | 431 | tsc2005_disable(ts); |
| 403 | result = 1; | 432 | |
| 404 | tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); | 433 | error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); |
| 434 | if (error) { | ||
| 435 | dev_warn(dev, "selftest failed: read error %d\n", error); | ||
| 436 | success = false; | ||
| 437 | goto out; | ||
| 438 | } | ||
| 439 | |||
| 405 | temp_high_test = (temp_high_orig - 1) & MAX_12BIT; | 440 | temp_high_test = (temp_high_orig - 1) & MAX_12BIT; |
| 406 | tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test); | 441 | |
| 407 | tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); | 442 | error = tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test); |
| 443 | if (error) { | ||
| 444 | dev_warn(dev, "selftest failed: write error %d\n", error); | ||
| 445 | success = false; | ||
| 446 | goto out; | ||
| 447 | } | ||
| 448 | |||
| 449 | error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); | ||
| 450 | if (error) { | ||
| 451 | dev_warn(dev, "selftest failed: read error %d after write\n", | ||
| 452 | error); | ||
| 453 | success = false; | ||
| 454 | goto out; | ||
| 455 | } | ||
| 456 | |||
| 408 | if (temp_high != temp_high_test) { | 457 | if (temp_high != temp_high_test) { |
| 409 | dev_warn(dev, "selftest failed: %d != %d\n", | 458 | dev_warn(dev, "selftest failed: %d != %d\n", |
| 410 | temp_high, temp_high_test); | 459 | temp_high, temp_high_test); |
| 411 | result = 0; | 460 | success = false; |
| 412 | } | 461 | } |
| 413 | 462 | ||
| 414 | /* hardware reset */ | 463 | /* hardware reset */ |
| 415 | ts->set_reset(false); | 464 | ts->set_reset(false); |
| 416 | usleep_range(100, 500); /* only 10us required */ | 465 | usleep_range(100, 500); /* only 10us required */ |
| 417 | ts->set_reset(true); | 466 | ts->set_reset(true); |
| 418 | tsc2005_enable(ts); | 467 | |
| 468 | if (!success) | ||
| 469 | goto out; | ||
| 419 | 470 | ||
| 420 | /* test that the reset really happened */ | 471 | /* test that the reset really happened */ |
| 421 | tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); | 472 | error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high); |
| 473 | if (error) { | ||
| 474 | dev_warn(dev, "selftest failed: read error %d after reset\n", | ||
| 475 | error); | ||
| 476 | success = false; | ||
| 477 | goto out; | ||
| 478 | } | ||
| 479 | |||
| 422 | if (temp_high != temp_high_orig) { | 480 | if (temp_high != temp_high_orig) { |
| 423 | dev_warn(dev, "selftest failed after reset: %d != %d\n", | 481 | dev_warn(dev, "selftest failed after reset: %d != %d\n", |
| 424 | temp_high, temp_high_orig); | 482 | temp_high, temp_high_orig); |
| 425 | result = 0; | 483 | success = false; |
| 426 | } | 484 | } |
| 427 | 485 | ||
| 486 | out: | ||
| 487 | tsc2005_enable(ts); | ||
| 428 | mutex_unlock(&ts->mutex); | 488 | mutex_unlock(&ts->mutex); |
| 429 | 489 | ||
| 430 | return sprintf(buf, "%u\n", result); | 490 | return sprintf(buf, "%d\n", success); |
| 431 | } | 491 | } |
| 432 | 492 | ||
| 433 | static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL); | 493 | static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL); |
| @@ -469,6 +529,7 @@ static void tsc2005_esd_timer(unsigned long data) | |||
| 469 | static void tsc2005_esd_work(struct work_struct *work) | 529 | static void tsc2005_esd_work(struct work_struct *work) |
| 470 | { | 530 | { |
| 471 | struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); | 531 | struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); |
| 532 | int error; | ||
| 472 | u16 r; | 533 | u16 r; |
| 473 | 534 | ||
| 474 | mutex_lock(&ts->mutex); | 535 | mutex_lock(&ts->mutex); |
| @@ -480,8 +541,9 @@ static void tsc2005_esd_work(struct work_struct *work) | |||
| 480 | * If we cannot read our known value from configuration register 0 then | 541 | * If we cannot read our known value from configuration register 0 then |
| 481 | * reset the controller as if from power-up and start scanning again. | 542 | * reset the controller as if from power-up and start scanning again. |
| 482 | */ | 543 | */ |
| 483 | tsc2005_read(ts, TSC2005_REG_CFR0, &r); | 544 | error = tsc2005_read(ts, TSC2005_REG_CFR0, &r); |
| 484 | if ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK) { | 545 | if (error || |
| 546 | ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) { | ||
| 485 | dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); | 547 | dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); |
| 486 | ts->set_reset(false); | 548 | ts->set_reset(false); |
| 487 | tsc2005_update_pen_state(ts, 0, 0, 0); | 549 | tsc2005_update_pen_state(ts, 0, 0, 0); |
