aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorSeungwon Jeon <tgih.jun@samsung.com>2013-06-26 13:09:27 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-06-28 16:02:41 -0400
commit2fbd009b40967fc54b7eb3580372736862291a06 (patch)
tree8179e88b35c7a59d221957b3ef57af3d960345bc /drivers/scsi
parentb873a27538dff59e77c15eaf23bdf7e6be7d36e9 (diff)
[SCSI] ufs: amend interrupt configuration
It makes interrupt setting more flexible especially for disabling. And wrong bit mask is fixed for ver 1.0. [17:16] is added for mask. Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com> Tested-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Santosh Y <santoshsy@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ufs/ufshcd.c84
-rw-r--r--drivers/scsi/ufs/ufshcd.h4
-rw-r--r--drivers/scsi/ufs/ufshci.h5
3 files changed, 64 insertions, 29 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 871c2f0568ae..1f1e08518555 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -35,6 +35,10 @@
35 35
36#include "ufshcd.h" 36#include "ufshcd.h"
37 37
38#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\
39 UTP_TASK_REQ_COMPL |\
40 UFSHCD_ERROR_MASK)
41
38enum { 42enum {
39 UFSHCD_MAX_CHANNEL = 0, 43 UFSHCD_MAX_CHANNEL = 0,
40 UFSHCD_MAX_ID = 1, 44 UFSHCD_MAX_ID = 1,
@@ -64,6 +68,20 @@ enum {
64}; 68};
65 69
66/** 70/**
71 * ufshcd_get_intr_mask - Get the interrupt bit mask
72 * @hba - Pointer to adapter instance
73 *
74 * Returns interrupt bit mask per version
75 */
76static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
77{
78 if (hba->ufs_version == UFSHCI_VERSION_10)
79 return INTERRUPT_MASK_ALL_VER_10;
80 else
81 return INTERRUPT_MASK_ALL_VER_11;
82}
83
84/**
67 * ufshcd_get_ufs_version - Get the UFS version supported by the HBA 85 * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
68 * @hba - Pointer to adapter instance 86 * @hba - Pointer to adapter instance
69 * 87 *
@@ -389,25 +407,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
389} 407}
390 408
391/** 409/**
392 * ufshcd_int_config - enable/disable interrupts 410 * ufshcd_enable_intr - enable interrupts
393 * @hba: per adapter instance 411 * @hba: per adapter instance
394 * @option: interrupt option 412 * @intrs: interrupt bits
395 */ 413 */
396static void ufshcd_int_config(struct ufs_hba *hba, u32 option) 414static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
397{ 415{
398 switch (option) { 416 u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
399 case UFSHCD_INT_ENABLE: 417
400 ufshcd_writel(hba, hba->int_enable_mask, REG_INTERRUPT_ENABLE); 418 if (hba->ufs_version == UFSHCI_VERSION_10) {
401 break; 419 u32 rw;
402 case UFSHCD_INT_DISABLE: 420 rw = set & INTERRUPT_MASK_RW_VER_10;
403 if (hba->ufs_version == UFSHCI_VERSION_10) 421 set = rw | ((set ^ intrs) & intrs);
404 ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_10, 422 } else {
405 REG_INTERRUPT_ENABLE); 423 set |= intrs;
406 else 424 }
407 ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_11, 425
408 REG_INTERRUPT_ENABLE); 426 ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
409 break; 427}
428
429/**
430 * ufshcd_disable_intr - disable interrupts
431 * @hba: per adapter instance
432 * @intrs: interrupt bits
433 */
434static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
435{
436 u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
437
438 if (hba->ufs_version == UFSHCI_VERSION_10) {
439 u32 rw;
440 rw = (set & INTERRUPT_MASK_RW_VER_10) &
441 ~(intrs & INTERRUPT_MASK_RW_VER_10);
442 set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
443
444 } else {
445 set &= ~intrs;
410 } 446 }
447
448 ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
411} 449}
412 450
413/** 451/**
@@ -709,8 +747,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
709 uic_cmd->argument3 = 0; 747 uic_cmd->argument3 = 0;
710 748
711 /* enable UIC related interrupts */ 749 /* enable UIC related interrupts */
712 hba->int_enable_mask |= UIC_COMMAND_COMPL; 750 ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
713 ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
714 751
715 /* sending UIC commands to controller */ 752 /* sending UIC commands to controller */
716 ufshcd_send_uic_command(hba, uic_cmd); 753 ufshcd_send_uic_command(hba, uic_cmd);
@@ -757,13 +794,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
757 } 794 }
758 795
759 /* Enable required interrupts */ 796 /* Enable required interrupts */
760 hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL | 797 ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
761 UIC_ERROR |
762 UTP_TASK_REQ_COMPL |
763 DEVICE_FATAL_ERROR |
764 CONTROLLER_FATAL_ERROR |
765 SYSTEM_BUS_FATAL_ERROR);
766 ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
767 798
768 /* Configure interrupt aggregation */ 799 /* Configure interrupt aggregation */
769 ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG); 800 ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
@@ -1570,7 +1601,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
1570void ufshcd_remove(struct ufs_hba *hba) 1601void ufshcd_remove(struct ufs_hba *hba)
1571{ 1602{
1572 /* disable interrupts */ 1603 /* disable interrupts */
1573 ufshcd_int_config(hba, UFSHCD_INT_DISABLE); 1604 ufshcd_disable_intr(hba, hba->intr_mask);
1574 1605
1575 ufshcd_hba_stop(hba); 1606 ufshcd_hba_stop(hba);
1576 ufshcd_hba_free(hba); 1607 ufshcd_hba_free(hba);
@@ -1628,6 +1659,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle,
1628 /* Get UFS version supported by the controller */ 1659 /* Get UFS version supported by the controller */
1629 hba->ufs_version = ufshcd_get_ufs_version(hba); 1660 hba->ufs_version = ufshcd_get_ufs_version(hba);
1630 1661
1662 /* Get Interrupt bit mask per version */
1663 hba->intr_mask = ufshcd_get_intr_mask(hba);
1664
1631 /* Allocate memory for host memory space */ 1665 /* Allocate memory for host memory space */
1632 err = ufshcd_memory_alloc(hba); 1666 err = ufshcd_memory_alloc(hba);
1633 if (err) { 1667 if (err) {
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 807dd2d740d4..4213600b89d6 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -139,7 +139,7 @@ struct ufshcd_lrb {
139 * @ufshcd_tm_wait_queue: wait queue for task management 139 * @ufshcd_tm_wait_queue: wait queue for task management
140 * @tm_condition: condition variable for task management 140 * @tm_condition: condition variable for task management
141 * @ufshcd_state: UFSHCD states 141 * @ufshcd_state: UFSHCD states
142 * @int_enable_mask: Interrupt Mask Bits 142 * @intr_mask: Interrupt Mask Bits
143 * @uic_workq: Work queue for UIC completion handling 143 * @uic_workq: Work queue for UIC completion handling
144 * @feh_workq: Work queue for fatal controller error handling 144 * @feh_workq: Work queue for fatal controller error handling
145 * @errors: HBA errors 145 * @errors: HBA errors
@@ -176,7 +176,7 @@ struct ufs_hba {
176 unsigned long tm_condition; 176 unsigned long tm_condition;
177 177
178 u32 ufshcd_state; 178 u32 ufshcd_state;
179 u32 int_enable_mask; 179 u32 intr_mask;
180 180
181 /* Work Queues */ 181 /* Work Queues */
182 struct work_struct uic_workq; 182 struct work_struct uic_workq;
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 0c164847a3ef..d5c5f1482d7d 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -232,10 +232,11 @@ enum {
232/* Interrupt disable masks */ 232/* Interrupt disable masks */
233enum { 233enum {
234 /* Interrupt disable mask for UFSHCI v1.0 */ 234 /* Interrupt disable mask for UFSHCI v1.0 */
235 INTERRUPT_DISABLE_MASK_10 = 0xFFFF, 235 INTERRUPT_MASK_ALL_VER_10 = 0x30FFF,
236 INTERRUPT_MASK_RW_VER_10 = 0x30000,
236 237
237 /* Interrupt disable mask for UFSHCI v1.1 */ 238 /* Interrupt disable mask for UFSHCI v1.1 */
238 INTERRUPT_DISABLE_MASK_11 = 0x0, 239 INTERRUPT_MASK_ALL_VER_11 = 0x31FFF,
239}; 240};
240 241
241/* 242/*