aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomoya MORINAGA <tomoya-linux@dsn.okisemi.com>2011-09-06 04:16:38 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-10-04 12:10:50 -0400
commitf3e03e2eb0bcd9266720695b82a523e6bc526ff7 (patch)
tree12184b7ed8bea50f0ca10ff44c7f37e5c1bb0e07 /drivers
parent25e803f9c339a070cd7361e853aebde11b1f9217 (diff)
spi-topcliff-pch: Fix overrun issue
We found that adding load, Rx data sometimes drops.(with DMA transfer mode) The cause is that before starting Rx-DMA processing, Tx-DMA processing starts. This causes FIFO overrun occurs. This patch fixes the issue by modifying FIFO tx-threshold and DMA descriptor size like below. Current this patch Rx-descriptor 4Byte+12Byte*341 --> 12Byte*340-4Byte-12Byte Rx-threshold (Not modified) Tx-descriptor 4Byte+12Byte*341 --> 16Byte-12Byte*340 Rx-threshold 12Byte --> 2Byte Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/spi-topcliff-pch.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index c8efa757fda..6a80749391d 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -50,6 +50,8 @@
50#define PCH_RX_THOLD 7 50#define PCH_RX_THOLD 7
51#define PCH_RX_THOLD_MAX 15 51#define PCH_RX_THOLD_MAX 15
52 52
53#define PCH_TX_THOLD 2
54
53#define PCH_MAX_BAUDRATE 5000000 55#define PCH_MAX_BAUDRATE 5000000
54#define PCH_MAX_FIFO_DEPTH 16 56#define PCH_MAX_FIFO_DEPTH 16
55 57
@@ -1040,8 +1042,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
1040 /* set receive fifo threshold and transmit fifo threshold */ 1042 /* set receive fifo threshold and transmit fifo threshold */
1041 pch_spi_setclr_reg(data->master, PCH_SPCR, 1043 pch_spi_setclr_reg(data->master, PCH_SPCR,
1042 ((size - 1) << SPCR_RFIC_FIELD) | 1044 ((size - 1) << SPCR_RFIC_FIELD) |
1043 ((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) << 1045 (PCH_TX_THOLD << SPCR_TFIC_FIELD),
1044 SPCR_TFIC_FIELD),
1045 MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS); 1046 MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS);
1046 1047
1047 spin_unlock_irqrestore(&data->lock, flags); 1048 spin_unlock_irqrestore(&data->lock, flags);
@@ -1052,13 +1053,20 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
1052 /* offset, length setting */ 1053 /* offset, length setting */
1053 sg = dma->sg_rx_p; 1054 sg = dma->sg_rx_p;
1054 for (i = 0; i < num; i++, sg++) { 1055 for (i = 0; i < num; i++, sg++) {
1055 if (i == 0) { 1056 if (i == (num - 2)) {
1056 sg->offset = 0; 1057 sg->offset = size * i;
1058 sg->offset = sg->offset * (*bpw / 8);
1057 sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem, 1059 sg_set_page(sg, virt_to_page(dma->rx_buf_virt), rem,
1058 sg->offset); 1060 sg->offset);
1059 sg_dma_len(sg) = rem; 1061 sg_dma_len(sg) = rem;
1062 } else if (i == (num - 1)) {
1063 sg->offset = size * (i - 1) + rem;
1064 sg->offset = sg->offset * (*bpw / 8);
1065 sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size,
1066 sg->offset);
1067 sg_dma_len(sg) = size;
1060 } else { 1068 } else {
1061 sg->offset = rem + size * (i - 1); 1069 sg->offset = size * i;
1062 sg->offset = sg->offset * (*bpw / 8); 1070 sg->offset = sg->offset * (*bpw / 8);
1063 sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size, 1071 sg_set_page(sg, virt_to_page(dma->rx_buf_virt), size,
1064 sg->offset); 1072 sg->offset);
@@ -1082,6 +1090,16 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
1082 dma->desc_rx = desc_rx; 1090 dma->desc_rx = desc_rx;
1083 1091
1084 /* TX */ 1092 /* TX */
1093 if (data->bpw_len > PCH_DMA_TRANS_SIZE) {
1094 num = data->bpw_len / PCH_DMA_TRANS_SIZE;
1095 size = PCH_DMA_TRANS_SIZE;
1096 rem = 16;
1097 } else {
1098 num = 1;
1099 size = data->bpw_len;
1100 rem = data->bpw_len;
1101 }
1102
1085 dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); 1103 dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
1086 sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ 1104 sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */
1087 /* offset, length setting */ 1105 /* offset, length setting */