aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi-topcliff-pch.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index 4b32fd7d0570..4fdb83a765d8 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -196,6 +196,7 @@ struct pch_spi_data {
196 struct pch_spi_dma_ctrl dma; 196 struct pch_spi_dma_ctrl dma;
197 int use_dma; 197 int use_dma;
198 u8 irq_reg_sts; 198 u8 irq_reg_sts;
199 int save_total_len;
199}; 200};
200 201
201/** 202/**
@@ -823,11 +824,13 @@ static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw)
823 rx_dma_buf = data->dma.rx_buf_virt; 824 rx_dma_buf = data->dma.rx_buf_virt;
824 for (j = 0; j < data->bpw_len; j++) 825 for (j = 0; j < data->bpw_len; j++)
825 *rx_buf++ = *rx_dma_buf++ & 0xFF; 826 *rx_buf++ = *rx_dma_buf++ & 0xFF;
827 data->cur_trans->rx_buf = rx_buf;
826 } else { 828 } else {
827 rx_sbuf = data->cur_trans->rx_buf; 829 rx_sbuf = data->cur_trans->rx_buf;
828 rx_dma_sbuf = data->dma.rx_buf_virt; 830 rx_dma_sbuf = data->dma.rx_buf_virt;
829 for (j = 0; j < data->bpw_len; j++) 831 for (j = 0; j < data->bpw_len; j++)
830 *rx_sbuf++ = *rx_dma_sbuf++; 832 *rx_sbuf++ = *rx_dma_sbuf++;
833 data->cur_trans->rx_buf = rx_sbuf;
831 } 834 }
832} 835}
833 836
@@ -853,6 +856,9 @@ static int pch_spi_start_transfer(struct pch_spi_data *data)
853 rtn = wait_event_interruptible_timeout(data->wait, 856 rtn = wait_event_interruptible_timeout(data->wait,
854 data->transfer_complete, 857 data->transfer_complete,
855 msecs_to_jiffies(2 * HZ)); 858 msecs_to_jiffies(2 * HZ));
859 if (!rtn)
860 dev_err(&data->master->dev,
861 "%s wait-event timeout\n", __func__);
856 862
857 dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent, 863 dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent,
858 DMA_FROM_DEVICE); 864 DMA_FROM_DEVICE);
@@ -989,6 +995,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
989 int i; 995 int i;
990 int size; 996 int size;
991 int rem; 997 int rem;
998 int head;
992 unsigned long flags; 999 unsigned long flags;
993 struct pch_spi_dma_ctrl *dma; 1000 struct pch_spi_dma_ctrl *dma;
994 1001
@@ -1017,6 +1024,11 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
1017 } 1024 }
1018 data->bpw_len = data->cur_trans->len / (*bpw / 8); 1025 data->bpw_len = data->cur_trans->len / (*bpw / 8);
1019 1026
1027 if (data->bpw_len > PCH_BUF_SIZE) {
1028 data->bpw_len = PCH_BUF_SIZE;
1029 data->cur_trans->len -= PCH_BUF_SIZE;
1030 }
1031
1020 /* copy Tx Data */ 1032 /* copy Tx Data */
1021 if (data->cur_trans->tx_buf != NULL) { 1033 if (data->cur_trans->tx_buf != NULL) {
1022 if (*bpw == 8) { 1034 if (*bpw == 8) {
@@ -1031,10 +1043,17 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
1031 *tx_dma_sbuf++ = *tx_sbuf++; 1043 *tx_dma_sbuf++ = *tx_sbuf++;
1032 } 1044 }
1033 } 1045 }
1046
1047 /* Calculate Rx parameter for DMA transmitting */
1034 if (data->bpw_len > PCH_DMA_TRANS_SIZE) { 1048 if (data->bpw_len > PCH_DMA_TRANS_SIZE) {
1035 num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1; 1049 if (data->bpw_len % PCH_DMA_TRANS_SIZE) {
1050 num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1;
1051 rem = data->bpw_len % PCH_DMA_TRANS_SIZE;
1052 } else {
1053 num = data->bpw_len / PCH_DMA_TRANS_SIZE;
1054 rem = PCH_DMA_TRANS_SIZE;
1055 }
1036 size = PCH_DMA_TRANS_SIZE; 1056 size = PCH_DMA_TRANS_SIZE;
1037 rem = data->bpw_len % PCH_DMA_TRANS_SIZE;
1038 } else { 1057 } else {
1039 num = 1; 1058 num = 1;
1040 size = data->bpw_len; 1059 size = data->bpw_len;
@@ -1094,15 +1113,23 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
1094 dma->nent = num; 1113 dma->nent = num;
1095 dma->desc_rx = desc_rx; 1114 dma->desc_rx = desc_rx;
1096 1115
1097 /* TX */ 1116 /* Calculate Tx parameter for DMA transmitting */
1098 if (data->bpw_len > PCH_DMA_TRANS_SIZE) { 1117 if (data->bpw_len > PCH_MAX_FIFO_DEPTH) {
1099 num = data->bpw_len / PCH_DMA_TRANS_SIZE; 1118 head = PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE;
1119 if (data->bpw_len % PCH_DMA_TRANS_SIZE > 4) {
1120 num = data->bpw_len / PCH_DMA_TRANS_SIZE + 1;
1121 rem = data->bpw_len % PCH_DMA_TRANS_SIZE - head;
1122 } else {
1123 num = data->bpw_len / PCH_DMA_TRANS_SIZE;
1124 rem = data->bpw_len % PCH_DMA_TRANS_SIZE +
1125 PCH_DMA_TRANS_SIZE - head;
1126 }
1100 size = PCH_DMA_TRANS_SIZE; 1127 size = PCH_DMA_TRANS_SIZE;
1101 rem = 16;
1102 } else { 1128 } else {
1103 num = 1; 1129 num = 1;
1104 size = data->bpw_len; 1130 size = data->bpw_len;
1105 rem = data->bpw_len; 1131 rem = data->bpw_len;
1132 head = 0;
1106 } 1133 }
1107 1134
1108 dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); 1135 dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
@@ -1112,11 +1139,17 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw)
1112 for (i = 0; i < num; i++, sg++) { 1139 for (i = 0; i < num; i++, sg++) {
1113 if (i == 0) { 1140 if (i == 0) {
1114 sg->offset = 0; 1141 sg->offset = 0;
1142 sg_set_page(sg, virt_to_page(dma->tx_buf_virt), size + head,
1143 sg->offset);
1144 sg_dma_len(sg) = size + head;
1145 } else if (i == (num - 1)) {
1146 sg->offset = head + size * i;
1147 sg->offset = sg->offset * (*bpw / 8);
1115 sg_set_page(sg, virt_to_page(dma->tx_buf_virt), rem, 1148 sg_set_page(sg, virt_to_page(dma->tx_buf_virt), rem,
1116 sg->offset); 1149 sg->offset);
1117 sg_dma_len(sg) = rem; 1150 sg_dma_len(sg) = rem;
1118 } else { 1151 } else {
1119 sg->offset = rem + size * (i - 1); 1152 sg->offset = head + size * i;
1120 sg->offset = sg->offset * (*bpw / 8); 1153 sg->offset = sg->offset * (*bpw / 8);
1121 sg_set_page(sg, virt_to_page(dma->tx_buf_virt), size, 1154 sg_set_page(sg, virt_to_page(dma->tx_buf_virt), size,
1122 sg->offset); 1155 sg->offset);
@@ -1204,6 +1237,7 @@ static void pch_spi_process_messages(struct work_struct *pwork)
1204 data->current_msg->spi->bits_per_word); 1237 data->current_msg->spi->bits_per_word);
1205 pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); 1238 pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL);
1206 do { 1239 do {
1240 int cnt;
1207 /* If we are already processing a message get the next 1241 /* If we are already processing a message get the next
1208 transfer structure from the message otherwise retrieve 1242 transfer structure from the message otherwise retrieve
1209 the 1st transfer request from the message. */ 1243 the 1st transfer request from the message. */
@@ -1223,11 +1257,20 @@ static void pch_spi_process_messages(struct work_struct *pwork)
1223 } 1257 }
1224 spin_unlock(&data->lock); 1258 spin_unlock(&data->lock);
1225 1259
1260 if (!data->cur_trans->len)
1261 goto out;
1262 cnt = (data->cur_trans->len - 1) / PCH_BUF_SIZE + 1;
1263 data->save_total_len = data->cur_trans->len;
1226 if (data->use_dma) { 1264 if (data->use_dma) {
1227 pch_spi_handle_dma(data, &bpw); 1265 int i;
1228 if (!pch_spi_start_transfer(data)) 1266 char *save_rx_buf = data->cur_trans->rx_buf;
1229 goto out; 1267 for (i = 0; i < cnt; i ++) {
1230 pch_spi_copy_rx_data_for_dma(data, bpw); 1268 pch_spi_handle_dma(data, &bpw);
1269 if (!pch_spi_start_transfer(data))
1270 goto out;
1271 pch_spi_copy_rx_data_for_dma(data, bpw);
1272 }
1273 data->cur_trans->rx_buf = save_rx_buf;
1231 } else { 1274 } else {
1232 pch_spi_set_tx(data, &bpw); 1275 pch_spi_set_tx(data, &bpw);
1233 pch_spi_set_ir(data); 1276 pch_spi_set_ir(data);
@@ -1238,6 +1281,7 @@ static void pch_spi_process_messages(struct work_struct *pwork)
1238 data->pkt_tx_buff = NULL; 1281 data->pkt_tx_buff = NULL;
1239 } 1282 }
1240 /* increment message count */ 1283 /* increment message count */
1284 data->cur_trans->len = data->save_total_len;
1241 data->current_msg->actual_length += data->cur_trans->len; 1285 data->current_msg->actual_length += data->cur_trans->len;
1242 1286
1243 dev_dbg(&data->master->dev, 1287 dev_dbg(&data->master->dev,