aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeungwon Jeon <tgih.jun@samsung.com>2013-08-31 12:10:22 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-09-06 19:06:40 -0400
commit53b3d9c3fdda94d14392dd221c67e24700b1fed6 (patch)
treea5198f3de41a71b6f2461fbf9687289254e0eaae
parent12b4fdb4f6bccb5459a2f75fbe0eab253bfceab4 (diff)
[SCSI] ufs: add operation for the uic power mode change
Setting PA_PWRMode using DME_SET triggers the power mode change. And then the result will be given by the HCS.UPMCRS. This operation should be done atomically. Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com> Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org> Tested-by: Yaniv Gardi <ygardi@codeaurora.org> Signed-off-by: Santosh Y <santoshsy@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/ufs/ufshcd.c84
-rw-r--r--drivers/scsi/ufs/ufshcd.h3
-rw-r--r--drivers/scsi/ufs/ufshci.h12
-rw-r--r--drivers/scsi/ufs/unipro.h130
4 files changed, 225 insertions, 4 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a4ce6c462614..1788d9cc571b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -36,9 +36,11 @@
36#include <linux/async.h> 36#include <linux/async.h>
37 37
38#include "ufshcd.h" 38#include "ufshcd.h"
39#include "unipro.h"
39 40
40#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ 41#define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\
41 UTP_TASK_REQ_COMPL |\ 42 UTP_TASK_REQ_COMPL |\
43 UIC_POWER_MODE |\
42 UFSHCD_ERROR_MASK) 44 UFSHCD_ERROR_MASK)
43/* UIC command timeout, unit: ms */ 45/* UIC command timeout, unit: ms */
44#define UIC_CMD_TIMEOUT 500 46#define UIC_CMD_TIMEOUT 500
@@ -470,6 +472,18 @@ static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
470} 472}
471 473
472/** 474/**
475 * ufshcd_get_upmcrs - Get the power mode change request status
476 * @hba: Pointer to adapter instance
477 *
478 * This function gets the UPMCRS field of HCS register
479 * Returns value of UPMCRS field
480 */
481static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
482{
483 return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) >> 8) & 0x7;
484}
485
486/**
473 * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers 487 * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
474 * @hba: per adapter instance 488 * @hba: per adapter instance
475 * @uic_cmd: UIC command 489 * @uic_cmd: UIC command
@@ -1460,6 +1474,64 @@ out:
1460EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr); 1474EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
1461 1475
1462/** 1476/**
1477 * ufshcd_uic_change_pwr_mode - Perform the UIC power mode chage
1478 * using DME_SET primitives.
1479 * @hba: per adapter instance
1480 * @mode: powr mode value
1481 *
1482 * Returns 0 on success, non-zero value on failure
1483 */
1484int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode)
1485{
1486 struct uic_command uic_cmd = {0};
1487 struct completion pwr_done;
1488 unsigned long flags;
1489 u8 status;
1490 int ret;
1491
1492 uic_cmd.command = UIC_CMD_DME_SET;
1493 uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE);
1494 uic_cmd.argument3 = mode;
1495 init_completion(&pwr_done);
1496
1497 mutex_lock(&hba->uic_cmd_mutex);
1498
1499 spin_lock_irqsave(hba->host->host_lock, flags);
1500 hba->pwr_done = &pwr_done;
1501 spin_unlock_irqrestore(hba->host->host_lock, flags);
1502 ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
1503 if (ret) {
1504 dev_err(hba->dev,
1505 "pwr mode change with mode 0x%x uic error %d\n",
1506 mode, ret);
1507 goto out;
1508 }
1509
1510 if (!wait_for_completion_timeout(hba->pwr_done,
1511 msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
1512 dev_err(hba->dev,
1513 "pwr mode change with mode 0x%x completion timeout\n",
1514 mode);
1515 ret = -ETIMEDOUT;
1516 goto out;
1517 }
1518
1519 status = ufshcd_get_upmcrs(hba);
1520 if (status != PWR_LOCAL) {
1521 dev_err(hba->dev,
1522 "pwr mode change failed, host umpcrs:0x%x\n",
1523 status);
1524 ret = (status != PWR_OK) ? status : -1;
1525 }
1526out:
1527 spin_lock_irqsave(hba->host->host_lock, flags);
1528 hba->pwr_done = NULL;
1529 spin_unlock_irqrestore(hba->host->host_lock, flags);
1530 mutex_unlock(&hba->uic_cmd_mutex);
1531 return ret;
1532}
1533
1534/**
1463 * ufshcd_complete_dev_init() - checks device readiness 1535 * ufshcd_complete_dev_init() - checks device readiness
1464 * hba: per-adapter instance 1536 * hba: per-adapter instance
1465 * 1537 *
@@ -1988,16 +2060,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
1988/** 2060/**
1989 * ufshcd_uic_cmd_compl - handle completion of uic command 2061 * ufshcd_uic_cmd_compl - handle completion of uic command
1990 * @hba: per adapter instance 2062 * @hba: per adapter instance
2063 * @intr_status: interrupt status generated by the controller
1991 */ 2064 */
1992static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) 2065static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
1993{ 2066{
1994 if (hba->active_uic_cmd) { 2067 if ((intr_status & UIC_COMMAND_COMPL) && hba->active_uic_cmd) {
1995 hba->active_uic_cmd->argument2 |= 2068 hba->active_uic_cmd->argument2 |=
1996 ufshcd_get_uic_cmd_result(hba); 2069 ufshcd_get_uic_cmd_result(hba);
1997 hba->active_uic_cmd->argument3 = 2070 hba->active_uic_cmd->argument3 =
1998 ufshcd_get_dme_attr_val(hba); 2071 ufshcd_get_dme_attr_val(hba);
1999 complete(&hba->active_uic_cmd->done); 2072 complete(&hba->active_uic_cmd->done);
2000 } 2073 }
2074
2075 if ((intr_status & UIC_POWER_MODE) && hba->pwr_done)
2076 complete(hba->pwr_done);
2001} 2077}
2002 2078
2003/** 2079/**
@@ -2343,8 +2419,8 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
2343 if (hba->errors) 2419 if (hba->errors)
2344 ufshcd_err_handler(hba); 2420 ufshcd_err_handler(hba);
2345 2421
2346 if (intr_status & UIC_COMMAND_COMPL) 2422 if (intr_status & UFSHCD_UIC_MASK)
2347 ufshcd_uic_cmd_compl(hba); 2423 ufshcd_uic_cmd_compl(hba, intr_status);
2348 2424
2349 if (intr_status & UTP_TASK_REQ_COMPL) 2425 if (intr_status & UTP_TASK_REQ_COMPL)
2350 ufshcd_tmc_handler(hba); 2426 ufshcd_tmc_handler(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 648ab16d379c..577679a2d189 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -175,6 +175,7 @@ struct ufs_dev_cmd {
175 * @active_uic_cmd: handle of active UIC command 175 * @active_uic_cmd: handle of active UIC command
176 * @uic_cmd_mutex: mutex for uic command 176 * @uic_cmd_mutex: mutex for uic command
177 * @ufshcd_tm_wait_queue: wait queue for task management 177 * @ufshcd_tm_wait_queue: wait queue for task management
178 * @pwr_done: completion for power mode change
178 * @tm_condition: condition variable for task management 179 * @tm_condition: condition variable for task management
179 * @ufshcd_state: UFSHCD states 180 * @ufshcd_state: UFSHCD states
180 * @intr_mask: Interrupt Mask Bits 181 * @intr_mask: Interrupt Mask Bits
@@ -219,6 +220,8 @@ struct ufs_hba {
219 wait_queue_head_t ufshcd_tm_wait_queue; 220 wait_queue_head_t ufshcd_tm_wait_queue;
220 unsigned long tm_condition; 221 unsigned long tm_condition;
221 222
223 struct completion *pwr_done;
224
222 u32 ufshcd_state; 225 u32 ufshcd_state;
223 u32 intr_mask; 226 u32 intr_mask;
224 u16 ee_ctrl_mask; 227 u16 ee_ctrl_mask;
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 1e1fe2668181..0475c6619a68 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -124,6 +124,9 @@ enum {
124#define CONTROLLER_FATAL_ERROR UFS_BIT(16) 124#define CONTROLLER_FATAL_ERROR UFS_BIT(16)
125#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17) 125#define SYSTEM_BUS_FATAL_ERROR UFS_BIT(17)
126 126
127#define UFSHCD_UIC_MASK (UIC_COMMAND_COMPL |\
128 UIC_POWER_MODE)
129
127#define UFSHCD_ERROR_MASK (UIC_ERROR |\ 130#define UFSHCD_ERROR_MASK (UIC_ERROR |\
128 DEVICE_FATAL_ERROR |\ 131 DEVICE_FATAL_ERROR |\
129 CONTROLLER_FATAL_ERROR |\ 132 CONTROLLER_FATAL_ERROR |\
@@ -142,6 +145,15 @@ enum {
142#define DEVICE_ERROR_INDICATOR UFS_BIT(5) 145#define DEVICE_ERROR_INDICATOR UFS_BIT(5)
143#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) 146#define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8)
144 147
148enum {
149 PWR_OK = 0x0,
150 PWR_LOCAL = 0x01,
151 PWR_REMOTE = 0x02,
152 PWR_BUSY = 0x03,
153 PWR_ERROR_CAP = 0x04,
154 PWR_FATAL_ERROR = 0x05,
155};
156
145/* HCE - Host Controller Enable 34h */ 157/* HCE - Host Controller Enable 34h */
146#define CONTROLLER_ENABLE UFS_BIT(0) 158#define CONTROLLER_ENABLE UFS_BIT(0)
147#define CONTROLLER_DISABLE 0x0 159#define CONTROLLER_DISABLE 0x0
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
new file mode 100644
index 000000000000..3a710eb3ec20
--- /dev/null
+++ b/drivers/scsi/ufs/unipro.h
@@ -0,0 +1,130 @@
1/*
2 * drivers/scsi/ufs/unipro.h
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef _UNIPRO_H_
13#define _UNIPRO_H_
14
15/*
16 * PHY Adpater attributes
17 */
18#define PA_ACTIVETXDATALANES 0x1560
19#define PA_ACTIVERXDATALANES 0x1580
20#define PA_TXTRAILINGCLOCKS 0x1564
21#define PA_PHY_TYPE 0x1500
22#define PA_AVAILTXDATALANES 0x1520
23#define PA_AVAILRXDATALANES 0x1540
24#define PA_MINRXTRAILINGCLOCKS 0x1543
25#define PA_TXPWRSTATUS 0x1567
26#define PA_RXPWRSTATUS 0x1582
27#define PA_TXFORCECLOCK 0x1562
28#define PA_TXPWRMODE 0x1563
29#define PA_LEGACYDPHYESCDL 0x1570
30#define PA_MAXTXSPEEDFAST 0x1521
31#define PA_MAXTXSPEEDSLOW 0x1522
32#define PA_MAXRXSPEEDFAST 0x1541
33#define PA_MAXRXSPEEDSLOW 0x1542
34#define PA_TXLINKSTARTUPHS 0x1544
35#define PA_TXSPEEDFAST 0x1565
36#define PA_TXSPEEDSLOW 0x1566
37#define PA_REMOTEVERINFO 0x15A0
38#define PA_TXGEAR 0x1568
39#define PA_TXTERMINATION 0x1569
40#define PA_HSSERIES 0x156A
41#define PA_PWRMODE 0x1571
42#define PA_RXGEAR 0x1583
43#define PA_RXTERMINATION 0x1584
44#define PA_MAXRXPWMGEAR 0x1586
45#define PA_MAXRXHSGEAR 0x1587
46#define PA_RXHSUNTERMCAP 0x15A5
47#define PA_RXLSTERMCAP 0x15A6
48#define PA_PACPREQTIMEOUT 0x1590
49#define PA_PACPREQEOBTIMEOUT 0x1591
50#define PA_HIBERN8TIME 0x15A7
51#define PA_LOCALVERINFO 0x15A9
52#define PA_TACTIVATE 0x15A8
53#define PA_PACPFRAMECOUNT 0x15C0
54#define PA_PACPERRORCOUNT 0x15C1
55#define PA_PHYTESTCONTROL 0x15C2
56#define PA_PWRMODEUSERDATA0 0x15B0
57#define PA_PWRMODEUSERDATA1 0x15B1
58#define PA_PWRMODEUSERDATA2 0x15B2
59#define PA_PWRMODEUSERDATA3 0x15B3
60#define PA_PWRMODEUSERDATA4 0x15B4
61#define PA_PWRMODEUSERDATA5 0x15B5
62#define PA_PWRMODEUSERDATA6 0x15B6
63#define PA_PWRMODEUSERDATA7 0x15B7
64#define PA_PWRMODEUSERDATA8 0x15B8
65#define PA_PWRMODEUSERDATA9 0x15B9
66#define PA_PWRMODEUSERDATA10 0x15BA
67#define PA_PWRMODEUSERDATA11 0x15BB
68#define PA_CONNECTEDTXDATALANES 0x1561
69#define PA_CONNECTEDRXDATALANES 0x1581
70#define PA_LOGICALLANEMAP 0x15A1
71#define PA_SLEEPNOCONFIGTIME 0x15A2
72#define PA_STALLNOCONFIGTIME 0x15A3
73#define PA_SAVECONFIGTIME 0x15A4
74
75/*
76 * Data Link Layer Attributes
77 */
78#define DL_TC0TXFCTHRESHOLD 0x2040
79#define DL_FC0PROTTIMEOUTVAL 0x2041
80#define DL_TC0REPLAYTIMEOUTVAL 0x2042
81#define DL_AFC0REQTIMEOUTVAL 0x2043
82#define DL_AFC0CREDITTHRESHOLD 0x2044
83#define DL_TC0OUTACKTHRESHOLD 0x2045
84#define DL_TC1TXFCTHRESHOLD 0x2060
85#define DL_FC1PROTTIMEOUTVAL 0x2061
86#define DL_TC1REPLAYTIMEOUTVAL 0x2062
87#define DL_AFC1REQTIMEOUTVAL 0x2063
88#define DL_AFC1CREDITTHRESHOLD 0x2064
89#define DL_TC1OUTACKTHRESHOLD 0x2065
90#define DL_TXPREEMPTIONCAP 0x2000
91#define DL_TC0TXMAXSDUSIZE 0x2001
92#define DL_TC0RXINITCREDITVAL 0x2002
93#define DL_TC0TXBUFFERSIZE 0x2005
94#define DL_PEERTC0PRESENT 0x2046
95#define DL_PEERTC0RXINITCREVAL 0x2047
96#define DL_TC1TXMAXSDUSIZE 0x2003
97#define DL_TC1RXINITCREDITVAL 0x2004
98#define DL_TC1TXBUFFERSIZE 0x2006
99#define DL_PEERTC1PRESENT 0x2066
100#define DL_PEERTC1RXINITCREVAL 0x2067
101
102/*
103 * Network Layer Attributes
104 */
105#define N_DEVICEID 0x3000
106#define N_DEVICEID_VALID 0x3001
107#define N_TC0TXMAXSDUSIZE 0x3020
108#define N_TC1TXMAXSDUSIZE 0x3021
109
110/*
111 * Transport Layer Attributes
112 */
113#define T_NUMCPORTS 0x4000
114#define T_NUMTESTFEATURES 0x4001
115#define T_CONNECTIONSTATE 0x4020
116#define T_PEERDEVICEID 0x4021
117#define T_PEERCPORTID 0x4022
118#define T_TRAFFICCLASS 0x4023
119#define T_PROTOCOLID 0x4024
120#define T_CPORTFLAGS 0x4025
121#define T_TXTOKENVALUE 0x4026
122#define T_RXTOKENVALUE 0x4027
123#define T_LOCALBUFFERSPACE 0x4028
124#define T_PEERBUFFERSPACE 0x4029
125#define T_CREDITSTOSEND 0x402A
126#define T_CPORTMODE 0x402B
127#define T_TC0TXMAXSDUSIZE 0x4060
128#define T_TC1TXMAXSDUSIZE 0x4061
129
130#endif /* _UNIPRO_H_ */