diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-10-09 00:52:23 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-10-09 01:01:21 -0400 |
commit | e8f462d202026d8e99f553ed5a09422321226ac9 (patch) | |
tree | e5351b7855cf9ec60120468e36381af286277aa1 /drivers/input/touchscreen | |
parent | 2d517cab01075610a615ebda0a1c16ba3fb081ae (diff) |
Input: ads7846 - fix cache line sharing issue
We had a report a while back that the ads7846 driver had some issues
when used with DMA-based SPI controllers (like atmel_spi) on systems
where main memory is not DMA-coherent (most non-x86 boards). Allocate
memory potentially used for DMA separately to avoid cache line issues.
Reported-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 6020a7dcce33..b9b7fc6ff1eb 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -69,6 +69,17 @@ struct ts_event { | |||
69 | int ignore; | 69 | int ignore; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* | ||
73 | * We allocate this separately to avoid cache line sharing issues when | ||
74 | * driver is used with DMA-based SPI controllers (like atmel_spi) on | ||
75 | * systems where main memory is not DMA-coherent (most non-x86 boards). | ||
76 | */ | ||
77 | struct ads7846_packet { | ||
78 | u8 read_x, read_y, read_z1, read_z2, pwrdown; | ||
79 | u16 dummy; /* for the pwrdown read */ | ||
80 | struct ts_event tc; | ||
81 | }; | ||
82 | |||
72 | struct ads7846 { | 83 | struct ads7846 { |
73 | struct input_dev *input; | 84 | struct input_dev *input; |
74 | char phys[32]; | 85 | char phys[32]; |
@@ -86,9 +97,7 @@ struct ads7846 { | |||
86 | u16 x_plate_ohms; | 97 | u16 x_plate_ohms; |
87 | u16 pressure_max; | 98 | u16 pressure_max; |
88 | 99 | ||
89 | u8 read_x, read_y, read_z1, read_z2, pwrdown; | 100 | struct ads7846_packet *packet; |
90 | u16 dummy; /* for the pwrdown read */ | ||
91 | struct ts_event tc; | ||
92 | 101 | ||
93 | struct spi_transfer xfer[18]; | 102 | struct spi_transfer xfer[18]; |
94 | struct spi_message msg[5]; | 103 | struct spi_message msg[5]; |
@@ -513,16 +522,17 @@ static int get_pendown_state(struct ads7846 *ts) | |||
513 | static void ads7846_rx(void *ads) | 522 | static void ads7846_rx(void *ads) |
514 | { | 523 | { |
515 | struct ads7846 *ts = ads; | 524 | struct ads7846 *ts = ads; |
525 | struct ads7846_packet *packet = ts->packet; | ||
516 | unsigned Rt; | 526 | unsigned Rt; |
517 | u16 x, y, z1, z2; | 527 | u16 x, y, z1, z2; |
518 | 528 | ||
519 | /* ads7846_rx_val() did in-place conversion (including byteswap) from | 529 | /* ads7846_rx_val() did in-place conversion (including byteswap) from |
520 | * on-the-wire format as part of debouncing to get stable readings. | 530 | * on-the-wire format as part of debouncing to get stable readings. |
521 | */ | 531 | */ |
522 | x = ts->tc.x; | 532 | x = packet->tc.x; |
523 | y = ts->tc.y; | 533 | y = packet->tc.y; |
524 | z1 = ts->tc.z1; | 534 | z1 = packet->tc.z1; |
525 | z2 = ts->tc.z2; | 535 | z2 = packet->tc.z2; |
526 | 536 | ||
527 | /* range filtering */ | 537 | /* range filtering */ |
528 | if (x == MAX_12BIT) | 538 | if (x == MAX_12BIT) |
@@ -546,10 +556,10 @@ static void ads7846_rx(void *ads) | |||
546 | * the maximum. Don't report it to user space, repeat at least | 556 | * the maximum. Don't report it to user space, repeat at least |
547 | * once more the measurement | 557 | * once more the measurement |
548 | */ | 558 | */ |
549 | if (ts->tc.ignore || Rt > ts->pressure_max) { | 559 | if (packet->tc.ignore || Rt > ts->pressure_max) { |
550 | #ifdef VERBOSE | 560 | #ifdef VERBOSE |
551 | pr_debug("%s: ignored %d pressure %d\n", | 561 | pr_debug("%s: ignored %d pressure %d\n", |
552 | ts->spi->dev.bus_id, ts->tc.ignore, Rt); | 562 | ts->spi->dev.bus_id, packet->tc.ignore, Rt); |
553 | #endif | 563 | #endif |
554 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 564 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
555 | HRTIMER_MODE_REL); | 565 | HRTIMER_MODE_REL); |
@@ -642,6 +652,7 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val) | |||
642 | static void ads7846_rx_val(void *ads) | 652 | static void ads7846_rx_val(void *ads) |
643 | { | 653 | { |
644 | struct ads7846 *ts = ads; | 654 | struct ads7846 *ts = ads; |
655 | struct ads7846_packet *packet = ts->packet; | ||
645 | struct spi_message *m; | 656 | struct spi_message *m; |
646 | struct spi_transfer *t; | 657 | struct spi_transfer *t; |
647 | int val; | 658 | int val; |
@@ -661,7 +672,7 @@ static void ads7846_rx_val(void *ads) | |||
661 | case ADS7846_FILTER_REPEAT: | 672 | case ADS7846_FILTER_REPEAT: |
662 | break; | 673 | break; |
663 | case ADS7846_FILTER_IGNORE: | 674 | case ADS7846_FILTER_IGNORE: |
664 | ts->tc.ignore = 1; | 675 | packet->tc.ignore = 1; |
665 | /* Last message will contain ads7846_rx() as the | 676 | /* Last message will contain ads7846_rx() as the |
666 | * completion function. | 677 | * completion function. |
667 | */ | 678 | */ |
@@ -669,7 +680,7 @@ static void ads7846_rx_val(void *ads) | |||
669 | break; | 680 | break; |
670 | case ADS7846_FILTER_OK: | 681 | case ADS7846_FILTER_OK: |
671 | *(u16 *)t->rx_buf = val; | 682 | *(u16 *)t->rx_buf = val; |
672 | ts->tc.ignore = 0; | 683 | packet->tc.ignore = 0; |
673 | m = &ts->msg[++ts->msg_idx]; | 684 | m = &ts->msg[++ts->msg_idx]; |
674 | break; | 685 | break; |
675 | default: | 686 | default: |
@@ -774,7 +785,6 @@ static void ads7846_disable(struct ads7846 *ts) | |||
774 | /* we know the chip's in lowpower mode since we always | 785 | /* we know the chip's in lowpower mode since we always |
775 | * leave it that way after every request | 786 | * leave it that way after every request |
776 | */ | 787 | */ |
777 | |||
778 | } | 788 | } |
779 | 789 | ||
780 | /* Must be called with ts->lock held */ | 790 | /* Must be called with ts->lock held */ |
@@ -850,6 +860,7 @@ static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts) | |||
850 | static int __devinit ads7846_probe(struct spi_device *spi) | 860 | static int __devinit ads7846_probe(struct spi_device *spi) |
851 | { | 861 | { |
852 | struct ads7846 *ts; | 862 | struct ads7846 *ts; |
863 | struct ads7846_packet *packet; | ||
853 | struct input_dev *input_dev; | 864 | struct input_dev *input_dev; |
854 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 865 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
855 | struct spi_message *m; | 866 | struct spi_message *m; |
@@ -885,14 +896,16 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
885 | return err; | 896 | return err; |
886 | 897 | ||
887 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); | 898 | ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); |
899 | packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL); | ||
888 | input_dev = input_allocate_device(); | 900 | input_dev = input_allocate_device(); |
889 | if (!ts || !input_dev) { | 901 | if (!ts || !packet || !input_dev) { |
890 | err = -ENOMEM; | 902 | err = -ENOMEM; |
891 | goto err_free_mem; | 903 | goto err_free_mem; |
892 | } | 904 | } |
893 | 905 | ||
894 | dev_set_drvdata(&spi->dev, ts); | 906 | dev_set_drvdata(&spi->dev, ts); |
895 | 907 | ||
908 | ts->packet = packet; | ||
896 | ts->spi = spi; | 909 | ts->spi = spi; |
897 | ts->input = input_dev; | 910 | ts->input = input_dev; |
898 | ts->vref_mv = pdata->vref_mv; | 911 | ts->vref_mv = pdata->vref_mv; |
@@ -964,13 +977,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
964 | spi_message_init(m); | 977 | spi_message_init(m); |
965 | 978 | ||
966 | /* y- still on; turn on only y+ (and ADC) */ | 979 | /* y- still on; turn on only y+ (and ADC) */ |
967 | ts->read_y = READ_Y(vref); | 980 | packet->read_y = READ_Y(vref); |
968 | x->tx_buf = &ts->read_y; | 981 | x->tx_buf = &packet->read_y; |
969 | x->len = 1; | 982 | x->len = 1; |
970 | spi_message_add_tail(x, m); | 983 | spi_message_add_tail(x, m); |
971 | 984 | ||
972 | x++; | 985 | x++; |
973 | x->rx_buf = &ts->tc.y; | 986 | x->rx_buf = &packet->tc.y; |
974 | x->len = 2; | 987 | x->len = 2; |
975 | spi_message_add_tail(x, m); | 988 | spi_message_add_tail(x, m); |
976 | 989 | ||
@@ -982,12 +995,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
982 | x->delay_usecs = pdata->settle_delay_usecs; | 995 | x->delay_usecs = pdata->settle_delay_usecs; |
983 | 996 | ||
984 | x++; | 997 | x++; |
985 | x->tx_buf = &ts->read_y; | 998 | x->tx_buf = &packet->read_y; |
986 | x->len = 1; | 999 | x->len = 1; |
987 | spi_message_add_tail(x, m); | 1000 | spi_message_add_tail(x, m); |
988 | 1001 | ||
989 | x++; | 1002 | x++; |
990 | x->rx_buf = &ts->tc.y; | 1003 | x->rx_buf = &packet->tc.y; |
991 | x->len = 2; | 1004 | x->len = 2; |
992 | spi_message_add_tail(x, m); | 1005 | spi_message_add_tail(x, m); |
993 | } | 1006 | } |
@@ -1000,13 +1013,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1000 | 1013 | ||
1001 | /* turn y- off, x+ on, then leave in lowpower */ | 1014 | /* turn y- off, x+ on, then leave in lowpower */ |
1002 | x++; | 1015 | x++; |
1003 | ts->read_x = READ_X(vref); | 1016 | packet->read_x = READ_X(vref); |
1004 | x->tx_buf = &ts->read_x; | 1017 | x->tx_buf = &packet->read_x; |
1005 | x->len = 1; | 1018 | x->len = 1; |
1006 | spi_message_add_tail(x, m); | 1019 | spi_message_add_tail(x, m); |
1007 | 1020 | ||
1008 | x++; | 1021 | x++; |
1009 | x->rx_buf = &ts->tc.x; | 1022 | x->rx_buf = &packet->tc.x; |
1010 | x->len = 2; | 1023 | x->len = 2; |
1011 | spi_message_add_tail(x, m); | 1024 | spi_message_add_tail(x, m); |
1012 | 1025 | ||
@@ -1015,12 +1028,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1015 | x->delay_usecs = pdata->settle_delay_usecs; | 1028 | x->delay_usecs = pdata->settle_delay_usecs; |
1016 | 1029 | ||
1017 | x++; | 1030 | x++; |
1018 | x->tx_buf = &ts->read_x; | 1031 | x->tx_buf = &packet->read_x; |
1019 | x->len = 1; | 1032 | x->len = 1; |
1020 | spi_message_add_tail(x, m); | 1033 | spi_message_add_tail(x, m); |
1021 | 1034 | ||
1022 | x++; | 1035 | x++; |
1023 | x->rx_buf = &ts->tc.x; | 1036 | x->rx_buf = &packet->tc.x; |
1024 | x->len = 2; | 1037 | x->len = 2; |
1025 | spi_message_add_tail(x, m); | 1038 | spi_message_add_tail(x, m); |
1026 | } | 1039 | } |
@@ -1034,13 +1047,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1034 | spi_message_init(m); | 1047 | spi_message_init(m); |
1035 | 1048 | ||
1036 | x++; | 1049 | x++; |
1037 | ts->read_z1 = READ_Z1(vref); | 1050 | packet->read_z1 = READ_Z1(vref); |
1038 | x->tx_buf = &ts->read_z1; | 1051 | x->tx_buf = &packet->read_z1; |
1039 | x->len = 1; | 1052 | x->len = 1; |
1040 | spi_message_add_tail(x, m); | 1053 | spi_message_add_tail(x, m); |
1041 | 1054 | ||
1042 | x++; | 1055 | x++; |
1043 | x->rx_buf = &ts->tc.z1; | 1056 | x->rx_buf = &packet->tc.z1; |
1044 | x->len = 2; | 1057 | x->len = 2; |
1045 | spi_message_add_tail(x, m); | 1058 | spi_message_add_tail(x, m); |
1046 | 1059 | ||
@@ -1049,12 +1062,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1049 | x->delay_usecs = pdata->settle_delay_usecs; | 1062 | x->delay_usecs = pdata->settle_delay_usecs; |
1050 | 1063 | ||
1051 | x++; | 1064 | x++; |
1052 | x->tx_buf = &ts->read_z1; | 1065 | x->tx_buf = &packet->read_z1; |
1053 | x->len = 1; | 1066 | x->len = 1; |
1054 | spi_message_add_tail(x, m); | 1067 | spi_message_add_tail(x, m); |
1055 | 1068 | ||
1056 | x++; | 1069 | x++; |
1057 | x->rx_buf = &ts->tc.z1; | 1070 | x->rx_buf = &packet->tc.z1; |
1058 | x->len = 2; | 1071 | x->len = 2; |
1059 | spi_message_add_tail(x, m); | 1072 | spi_message_add_tail(x, m); |
1060 | } | 1073 | } |
@@ -1066,13 +1079,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1066 | spi_message_init(m); | 1079 | spi_message_init(m); |
1067 | 1080 | ||
1068 | x++; | 1081 | x++; |
1069 | ts->read_z2 = READ_Z2(vref); | 1082 | packet->read_z2 = READ_Z2(vref); |
1070 | x->tx_buf = &ts->read_z2; | 1083 | x->tx_buf = &packet->read_z2; |
1071 | x->len = 1; | 1084 | x->len = 1; |
1072 | spi_message_add_tail(x, m); | 1085 | spi_message_add_tail(x, m); |
1073 | 1086 | ||
1074 | x++; | 1087 | x++; |
1075 | x->rx_buf = &ts->tc.z2; | 1088 | x->rx_buf = &packet->tc.z2; |
1076 | x->len = 2; | 1089 | x->len = 2; |
1077 | spi_message_add_tail(x, m); | 1090 | spi_message_add_tail(x, m); |
1078 | 1091 | ||
@@ -1081,12 +1094,12 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1081 | x->delay_usecs = pdata->settle_delay_usecs; | 1094 | x->delay_usecs = pdata->settle_delay_usecs; |
1082 | 1095 | ||
1083 | x++; | 1096 | x++; |
1084 | x->tx_buf = &ts->read_z2; | 1097 | x->tx_buf = &packet->read_z2; |
1085 | x->len = 1; | 1098 | x->len = 1; |
1086 | spi_message_add_tail(x, m); | 1099 | spi_message_add_tail(x, m); |
1087 | 1100 | ||
1088 | x++; | 1101 | x++; |
1089 | x->rx_buf = &ts->tc.z2; | 1102 | x->rx_buf = &packet->tc.z2; |
1090 | x->len = 2; | 1103 | x->len = 2; |
1091 | spi_message_add_tail(x, m); | 1104 | spi_message_add_tail(x, m); |
1092 | } | 1105 | } |
@@ -1100,13 +1113,13 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1100 | spi_message_init(m); | 1113 | spi_message_init(m); |
1101 | 1114 | ||
1102 | x++; | 1115 | x++; |
1103 | ts->pwrdown = PWRDOWN; | 1116 | packet->pwrdown = PWRDOWN; |
1104 | x->tx_buf = &ts->pwrdown; | 1117 | x->tx_buf = &packet->pwrdown; |
1105 | x->len = 1; | 1118 | x->len = 1; |
1106 | spi_message_add_tail(x, m); | 1119 | spi_message_add_tail(x, m); |
1107 | 1120 | ||
1108 | x++; | 1121 | x++; |
1109 | x->rx_buf = &ts->dummy; | 1122 | x->rx_buf = &packet->dummy; |
1110 | x->len = 2; | 1123 | x->len = 2; |
1111 | CS_CHANGE(*x); | 1124 | CS_CHANGE(*x); |
1112 | spi_message_add_tail(x, m); | 1125 | spi_message_add_tail(x, m); |
@@ -1159,6 +1172,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1159 | ts->filter_cleanup(ts->filter_data); | 1172 | ts->filter_cleanup(ts->filter_data); |
1160 | err_free_mem: | 1173 | err_free_mem: |
1161 | input_free_device(input_dev); | 1174 | input_free_device(input_dev); |
1175 | kfree(packet); | ||
1162 | kfree(ts); | 1176 | kfree(ts); |
1163 | return err; | 1177 | return err; |
1164 | } | 1178 | } |
@@ -1184,6 +1198,7 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
1184 | if (ts->filter_cleanup) | 1198 | if (ts->filter_cleanup) |
1185 | ts->filter_cleanup(ts->filter_data); | 1199 | ts->filter_cleanup(ts->filter_data); |
1186 | 1200 | ||
1201 | kfree(ts->packet); | ||
1187 | kfree(ts); | 1202 | kfree(ts); |
1188 | 1203 | ||
1189 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | 1204 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); |