Commit 53b3d9c3fdda94d14392dd221c67e24700b1fed6
Committed by
James Bottomley
1 parent
12b4fdb4f6
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
[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>
Showing 4 changed files with 225 additions and 4 deletions Side-by-side Diff
drivers/scsi/ufs/ufshcd.c
... | ... | @@ -36,9 +36,11 @@ |
36 | 36 | #include <linux/async.h> |
37 | 37 | |
38 | 38 | #include "ufshcd.h" |
39 | +#include "unipro.h" | |
39 | 40 | |
40 | 41 | #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ |
41 | 42 | UTP_TASK_REQ_COMPL |\ |
43 | + UIC_POWER_MODE |\ | |
42 | 44 | UFSHCD_ERROR_MASK) |
43 | 45 | /* UIC command timeout, unit: ms */ |
44 | 46 | #define UIC_CMD_TIMEOUT 500 |
... | ... | @@ -470,6 +472,18 @@ |
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 | + */ | |
481 | +static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba) | |
482 | +{ | |
483 | + return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) >> 8) & 0x7; | |
484 | +} | |
485 | + | |
486 | +/** | |
473 | 487 | * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers |
474 | 488 | * @hba: per adapter instance |
475 | 489 | * @uic_cmd: UIC command |
... | ... | @@ -1460,6 +1474,64 @@ |
1460 | 1474 | EXPORT_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 | + */ | |
1484 | +int 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 | + } | |
1526 | +out: | |
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 | 1535 | * ufshcd_complete_dev_init() - checks device readiness |
1464 | 1536 | * hba: per-adapter instance |
1465 | 1537 | * |
1466 | 1538 | |
1467 | 1539 | |
1468 | 1540 | |
... | ... | @@ -1988,16 +2060,20 @@ |
1988 | 2060 | /** |
1989 | 2061 | * ufshcd_uic_cmd_compl - handle completion of uic command |
1990 | 2062 | * @hba: per adapter instance |
2063 | + * @intr_status: interrupt status generated by the controller | |
1991 | 2064 | */ |
1992 | -static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) | |
2065 | +static 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 | 2068 | hba->active_uic_cmd->argument2 |= |
1996 | 2069 | ufshcd_get_uic_cmd_result(hba); |
1997 | 2070 | hba->active_uic_cmd->argument3 = |
1998 | 2071 | ufshcd_get_dme_attr_val(hba); |
1999 | 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 @@ |
2343 | 2419 | if (hba->errors) |
2344 | 2420 | ufshcd_err_handler(hba); |
2345 | 2421 | |
2346 | - if (intr_status & UIC_COMMAND_COMPL) | |
2347 | - ufshcd_uic_cmd_compl(hba); | |
2422 | + if (intr_status & UFSHCD_UIC_MASK) | |
2423 | + ufshcd_uic_cmd_compl(hba, intr_status); | |
2348 | 2424 | |
2349 | 2425 | if (intr_status & UTP_TASK_REQ_COMPL) |
2350 | 2426 | ufshcd_tmc_handler(hba); |
drivers/scsi/ufs/ufshcd.h
... | ... | @@ -175,6 +175,7 @@ |
175 | 175 | * @active_uic_cmd: handle of active UIC command |
176 | 176 | * @uic_cmd_mutex: mutex for uic command |
177 | 177 | * @ufshcd_tm_wait_queue: wait queue for task management |
178 | + * @pwr_done: completion for power mode change | |
178 | 179 | * @tm_condition: condition variable for task management |
179 | 180 | * @ufshcd_state: UFSHCD states |
180 | 181 | * @intr_mask: Interrupt Mask Bits |
... | ... | @@ -218,6 +219,8 @@ |
218 | 219 | |
219 | 220 | wait_queue_head_t ufshcd_tm_wait_queue; |
220 | 221 | unsigned long tm_condition; |
222 | + | |
223 | + struct completion *pwr_done; | |
221 | 224 | |
222 | 225 | u32 ufshcd_state; |
223 | 226 | u32 intr_mask; |
drivers/scsi/ufs/ufshci.h
... | ... | @@ -124,6 +124,9 @@ |
124 | 124 | #define CONTROLLER_FATAL_ERROR UFS_BIT(16) |
125 | 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 | 130 | #define UFSHCD_ERROR_MASK (UIC_ERROR |\ |
128 | 131 | DEVICE_FATAL_ERROR |\ |
129 | 132 | CONTROLLER_FATAL_ERROR |\ |
... | ... | @@ -141,6 +144,15 @@ |
141 | 144 | #define HOST_ERROR_INDICATOR UFS_BIT(4) |
142 | 145 | #define DEVICE_ERROR_INDICATOR UFS_BIT(5) |
143 | 146 | #define UIC_POWER_MODE_CHANGE_REQ_STATUS_MASK UFS_MASK(0x7, 8) |
147 | + | |
148 | +enum { | |
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 | +}; | |
144 | 156 | |
145 | 157 | /* HCE - Host Controller Enable 34h */ |
146 | 158 | #define CONTROLLER_ENABLE UFS_BIT(0) |
drivers/scsi/ufs/unipro.h
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_ */ |