diff options
| -rw-r--r-- | drivers/spi/spi-topcliff-pch.c | 93 |
1 files changed, 66 insertions, 27 deletions
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 1d23f3831866..6a80749391db 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 | ||
| @@ -58,6 +60,7 @@ | |||
| 58 | #define PCH_SLEEP_TIME 10 | 60 | #define PCH_SLEEP_TIME 10 |
| 59 | 61 | ||
| 60 | #define SSN_LOW 0x02U | 62 | #define SSN_LOW 0x02U |
| 63 | #define SSN_HIGH 0x03U | ||
| 61 | #define SSN_NO_CONTROL 0x00U | 64 | #define SSN_NO_CONTROL 0x00U |
| 62 | #define PCH_MAX_CS 0xFF | 65 | #define PCH_MAX_CS 0xFF |
| 63 | #define PCI_DEVICE_ID_GE_SPI 0x8816 | 66 | #define PCI_DEVICE_ID_GE_SPI 0x8816 |
| @@ -316,16 +319,19 @@ static void pch_spi_handler_sub(struct pch_spi_data *data, u32 reg_spsr_val, | |||
| 316 | 319 | ||
| 317 | /* if transfer complete interrupt */ | 320 | /* if transfer complete interrupt */ |
| 318 | if (reg_spsr_val & SPSR_FI_BIT) { | 321 | if (reg_spsr_val & SPSR_FI_BIT) { |
| 319 | if (tx_index < bpw_len) | 322 | if ((tx_index == bpw_len) && (rx_index == tx_index)) { |
| 323 | /* disable interrupts */ | ||
| 324 | pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); | ||
| 325 | |||
| 326 | /* transfer is completed; | ||
| 327 | inform pch_spi_process_messages */ | ||
| 328 | data->transfer_complete = true; | ||
| 329 | data->transfer_active = false; | ||
| 330 | wake_up(&data->wait); | ||
| 331 | } else { | ||
| 320 | dev_err(&data->master->dev, | 332 | dev_err(&data->master->dev, |
| 321 | "%s : Transfer is not completed", __func__); | 333 | "%s : Transfer is not completed", __func__); |
| 322 | /* disable interrupts */ | 334 | } |
| 323 | pch_spi_setclr_reg(data->master, PCH_SPCR, 0, PCH_ALL); | ||
| 324 | |||
| 325 | /* transfer is completed;inform pch_spi_process_messages */ | ||
| 326 | data->transfer_complete = true; | ||
| 327 | data->transfer_active = false; | ||
| 328 | wake_up(&data->wait); | ||
| 329 | } | 335 | } |
| 330 | } | 336 | } |
| 331 | 337 | ||
| @@ -348,16 +354,26 @@ static irqreturn_t pch_spi_handler(int irq, void *dev_id) | |||
| 348 | "%s returning due to suspend\n", __func__); | 354 | "%s returning due to suspend\n", __func__); |
| 349 | return IRQ_NONE; | 355 | return IRQ_NONE; |
| 350 | } | 356 | } |
| 351 | if (data->use_dma) | ||
| 352 | return IRQ_NONE; | ||
| 353 | 357 | ||
| 354 | io_remap_addr = data->io_remap_addr; | 358 | io_remap_addr = data->io_remap_addr; |
| 355 | spsr = io_remap_addr + PCH_SPSR; | 359 | spsr = io_remap_addr + PCH_SPSR; |
| 356 | 360 | ||
| 357 | reg_spsr_val = ioread32(spsr); | 361 | reg_spsr_val = ioread32(spsr); |
| 358 | 362 | ||
| 359 | if (reg_spsr_val & SPSR_ORF_BIT) | 363 | if (reg_spsr_val & SPSR_ORF_BIT) { |
| 360 | dev_err(&board_dat->pdev->dev, "%s Over run error", __func__); | 364 | dev_err(&board_dat->pdev->dev, "%s Over run error\n", __func__); |
| 365 | if (data->current_msg->complete != 0) { | ||
| 366 | data->transfer_complete = true; | ||
| 367 | data->current_msg->status = -EIO; | ||
| 368 | data->current_msg->complete(data->current_msg->context); | ||
| 369 | data->bcurrent_msg_processing = false; | ||
| 370 | data->current_msg = NULL; | ||
| 371 | data->cur_trans = NULL; | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | if (data->use_dma) | ||
| 376 | return IRQ_NONE; | ||
| 361 | 377 | ||
| 362 | /* Check if the interrupt is for SPI device */ | 378 | /* Check if the interrupt is for SPI device */ |
| 363 | if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) { | 379 | if (reg_spsr_val & (SPSR_FI_BIT | SPSR_RFI_BIT)) { |
| @@ -756,10 +772,6 @@ static void pch_spi_set_ir(struct pch_spi_data *data) | |||
| 756 | 772 | ||
| 757 | wait_event_interruptible(data->wait, data->transfer_complete); | 773 | wait_event_interruptible(data->wait, data->transfer_complete); |
| 758 | 774 | ||
| 759 | pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); | ||
| 760 | dev_dbg(&data->master->dev, | ||
| 761 | "%s:no more control over SSN-writing 0 to SSNXCR.", __func__); | ||
| 762 | |||
| 763 | /* clear all interrupts */ | 775 | /* clear all interrupts */ |
| 764 | pch_spi_writereg(data->master, PCH_SPSR, | 776 | pch_spi_writereg(data->master, PCH_SPSR, |
| 765 | pch_spi_readreg(data->master, PCH_SPSR)); | 777 | pch_spi_readreg(data->master, PCH_SPSR)); |
| @@ -815,10 +827,11 @@ static void pch_spi_copy_rx_data_for_dma(struct pch_spi_data *data, int bpw) | |||
| 815 | } | 827 | } |
| 816 | } | 828 | } |
| 817 | 829 | ||
| 818 | static void pch_spi_start_transfer(struct pch_spi_data *data) | 830 | static int pch_spi_start_transfer(struct pch_spi_data *data) |
| 819 | { | 831 | { |
| 820 | struct pch_spi_dma_ctrl *dma; | 832 | struct pch_spi_dma_ctrl *dma; |
| 821 | unsigned long flags; | 833 | unsigned long flags; |
| 834 | int rtn; | ||
| 822 | 835 | ||
| 823 | dma = &data->dma; | 836 | dma = &data->dma; |
| 824 | 837 | ||
| @@ -833,19 +846,23 @@ static void pch_spi_start_transfer(struct pch_spi_data *data) | |||
| 833 | initiating the transfer. */ | 846 | initiating the transfer. */ |
| 834 | dev_dbg(&data->master->dev, | 847 | dev_dbg(&data->master->dev, |
| 835 | "%s:waiting for transfer to get over\n", __func__); | 848 | "%s:waiting for transfer to get over\n", __func__); |
| 836 | wait_event_interruptible(data->wait, data->transfer_complete); | 849 | rtn = wait_event_interruptible_timeout(data->wait, |
| 850 | data->transfer_complete, | ||
| 851 | msecs_to_jiffies(2 * HZ)); | ||
| 837 | 852 | ||
| 838 | dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent, | 853 | dma_sync_sg_for_cpu(&data->master->dev, dma->sg_rx_p, dma->nent, |
| 839 | DMA_FROM_DEVICE); | 854 | DMA_FROM_DEVICE); |
| 855 | |||
| 856 | dma_sync_sg_for_cpu(&data->master->dev, dma->sg_tx_p, dma->nent, | ||
| 857 | DMA_FROM_DEVICE); | ||
| 858 | memset(data->dma.tx_buf_virt, 0, PAGE_SIZE); | ||
| 859 | |||
| 840 | async_tx_ack(dma->desc_rx); | 860 | async_tx_ack(dma->desc_rx); |
| 841 | async_tx_ack(dma->desc_tx); | 861 | async_tx_ack(dma->desc_tx); |
| 842 | kfree(dma->sg_tx_p); | 862 | kfree(dma->sg_tx_p); |
| 843 | kfree(dma->sg_rx_p); | 863 | kfree(dma->sg_rx_p); |
| 844 | 864 | ||
| 845 | spin_lock_irqsave(&data->lock, flags); | 865 | spin_lock_irqsave(&data->lock, flags); |
| 846 | pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); | ||
| 847 | dev_dbg(&data->master->dev, | ||
| 848 | "%s:no more control over SSN-writing 0 to SSNXCR.", __func__); | ||
| 849 | 866 | ||
| 850 | /* clear fifo threshold, disable interrupts, disable SPI transfer */ | 867 | /* clear fifo threshold, disable interrupts, disable SPI transfer */ |
| 851 | pch_spi_setclr_reg(data->master, PCH_SPCR, 0, | 868 | pch_spi_setclr_reg(data->master, PCH_SPCR, 0, |
| @@ -858,6 +875,8 @@ static void pch_spi_start_transfer(struct pch_spi_data *data) | |||
| 858 | pch_spi_clear_fifo(data->master); | 875 | pch_spi_clear_fifo(data->master); |
| 859 | 876 | ||
| 860 | spin_unlock_irqrestore(&data->lock, flags); | 877 | spin_unlock_irqrestore(&data->lock, flags); |
| 878 | |||
| 879 | return rtn; | ||
| 861 | } | 880 | } |
| 862 | 881 | ||
| 863 | static void pch_dma_rx_complete(void *arg) | 882 | static void pch_dma_rx_complete(void *arg) |
| @@ -1023,8 +1042,7 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) | |||
| 1023 | /* set receive fifo threshold and transmit fifo threshold */ | 1042 | /* set receive fifo threshold and transmit fifo threshold */ |
| 1024 | pch_spi_setclr_reg(data->master, PCH_SPCR, | 1043 | pch_spi_setclr_reg(data->master, PCH_SPCR, |
| 1025 | ((size - 1) << SPCR_RFIC_FIELD) | | 1044 | ((size - 1) << SPCR_RFIC_FIELD) | |
| 1026 | ((PCH_MAX_FIFO_DEPTH - PCH_DMA_TRANS_SIZE) << | 1045 | (PCH_TX_THOLD << SPCR_TFIC_FIELD), |
| 1027 | SPCR_TFIC_FIELD), | ||
| 1028 | MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS); | 1046 | MASK_RFIC_SPCR_BITS | MASK_TFIC_SPCR_BITS); |
| 1029 | 1047 | ||
| 1030 | spin_unlock_irqrestore(&data->lock, flags); | 1048 | spin_unlock_irqrestore(&data->lock, flags); |
| @@ -1035,13 +1053,20 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) | |||
| 1035 | /* offset, length setting */ | 1053 | /* offset, length setting */ |
| 1036 | sg = dma->sg_rx_p; | 1054 | sg = dma->sg_rx_p; |
| 1037 | for (i = 0; i < num; i++, sg++) { | 1055 | for (i = 0; i < num; i++, sg++) { |
| 1038 | if (i == 0) { | 1056 | if (i == (num - 2)) { |
| 1039 | sg->offset = 0; | 1057 | sg->offset = size * i; |
| 1058 | sg->offset = sg->offset * (*bpw / 8); | ||
| 1040 | 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, |
| 1041 | sg->offset); | 1060 | sg->offset); |
| 1042 | 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; | ||
| 1043 | } else { | 1068 | } else { |
| 1044 | sg->offset = rem + size * (i - 1); | 1069 | sg->offset = size * i; |
| 1045 | sg->offset = sg->offset * (*bpw / 8); | 1070 | sg->offset = sg->offset * (*bpw / 8); |
| 1046 | 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, |
| 1047 | sg->offset); | 1072 | sg->offset); |
| @@ -1065,6 +1090,16 @@ static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) | |||
| 1065 | dma->desc_rx = desc_rx; | 1090 | dma->desc_rx = desc_rx; |
| 1066 | 1091 | ||
| 1067 | /* 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 | |||
| 1068 | dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); | 1103 | dma->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC); |
| 1069 | sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ | 1104 | sg_init_table(dma->sg_tx_p, num); /* Initialize SG table */ |
| 1070 | /* offset, length setting */ | 1105 | /* offset, length setting */ |
| @@ -1162,6 +1197,7 @@ static void pch_spi_process_messages(struct work_struct *pwork) | |||
| 1162 | if (data->use_dma) | 1197 | if (data->use_dma) |
| 1163 | pch_spi_request_dma(data, | 1198 | pch_spi_request_dma(data, |
| 1164 | data->current_msg->spi->bits_per_word); | 1199 | data->current_msg->spi->bits_per_word); |
| 1200 | pch_spi_writereg(data->master, PCH_SSNXCR, SSN_NO_CONTROL); | ||
| 1165 | do { | 1201 | do { |
| 1166 | /* If we are already processing a message get the next | 1202 | /* If we are already processing a message get the next |
| 1167 | transfer structure from the message otherwise retrieve | 1203 | transfer structure from the message otherwise retrieve |
| @@ -1184,7 +1220,8 @@ static void pch_spi_process_messages(struct work_struct *pwork) | |||
| 1184 | 1220 | ||
| 1185 | if (data->use_dma) { | 1221 | if (data->use_dma) { |
| 1186 | pch_spi_handle_dma(data, &bpw); | 1222 | pch_spi_handle_dma(data, &bpw); |
| 1187 | pch_spi_start_transfer(data); | 1223 | if (!pch_spi_start_transfer(data)) |
| 1224 | goto out; | ||
| 1188 | pch_spi_copy_rx_data_for_dma(data, bpw); | 1225 | pch_spi_copy_rx_data_for_dma(data, bpw); |
| 1189 | } else { | 1226 | } else { |
| 1190 | pch_spi_set_tx(data, &bpw); | 1227 | pch_spi_set_tx(data, &bpw); |
| @@ -1222,6 +1259,8 @@ static void pch_spi_process_messages(struct work_struct *pwork) | |||
| 1222 | 1259 | ||
| 1223 | } while (data->cur_trans != NULL); | 1260 | } while (data->cur_trans != NULL); |
| 1224 | 1261 | ||
| 1262 | out: | ||
| 1263 | pch_spi_writereg(data->master, PCH_SSNXCR, SSN_HIGH); | ||
| 1225 | if (data->use_dma) | 1264 | if (data->use_dma) |
| 1226 | pch_spi_release_dma(data); | 1265 | pch_spi_release_dma(data); |
| 1227 | } | 1266 | } |
