diff options
author | Seungwon Jeon <tgih.jun@samsung.com> | 2013-08-31 12:10:24 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-09-06 19:08:37 -0400 |
commit | d3e89bac7155341d3cfe58e76842a2a9729e6e41 (patch) | |
tree | d9b33ca91f15e2afd21c7017f856091536599d44 | |
parent | 53b3d9c3fdda94d14392dd221c67e24700b1fed6 (diff) |
[SCSI] ufs: configure the attribute for power mode
UIC attributes can be set with using DME_SET command for
power mode change. For configuration the link capability
attributes are used, which is updated after successful
link startup.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Reviewed-by: Subhash Jadavani <subhashj@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.c | 66 | ||||
-rw-r--r-- | drivers/scsi/ufs/unipro.h | 21 |
2 files changed, 87 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 1788d9cc571b..04884d663e4e 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
@@ -1532,6 +1532,70 @@ out: | |||
1532 | } | 1532 | } |
1533 | 1533 | ||
1534 | /** | 1534 | /** |
1535 | * ufshcd_config_max_pwr_mode - Set & Change power mode with | ||
1536 | * maximum capability attribute information. | ||
1537 | * @hba: per adapter instance | ||
1538 | * | ||
1539 | * Returns 0 on success, non-zero value on failure | ||
1540 | */ | ||
1541 | static int ufshcd_config_max_pwr_mode(struct ufs_hba *hba) | ||
1542 | { | ||
1543 | enum {RX = 0, TX = 1}; | ||
1544 | u32 lanes[] = {1, 1}; | ||
1545 | u32 gear[] = {1, 1}; | ||
1546 | u8 pwr[] = {FASTAUTO_MODE, FASTAUTO_MODE}; | ||
1547 | int ret; | ||
1548 | |||
1549 | /* Get the connected lane count */ | ||
1550 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), &lanes[RX]); | ||
1551 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), &lanes[TX]); | ||
1552 | |||
1553 | /* | ||
1554 | * First, get the maximum gears of HS speed. | ||
1555 | * If a zero value, it means there is no HSGEAR capability. | ||
1556 | * Then, get the maximum gears of PWM speed. | ||
1557 | */ | ||
1558 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &gear[RX]); | ||
1559 | if (!gear[RX]) { | ||
1560 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR), &gear[RX]); | ||
1561 | pwr[RX] = SLOWAUTO_MODE; | ||
1562 | } | ||
1563 | |||
1564 | ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &gear[TX]); | ||
1565 | if (!gear[TX]) { | ||
1566 | ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR), | ||
1567 | &gear[TX]); | ||
1568 | pwr[TX] = SLOWAUTO_MODE; | ||
1569 | } | ||
1570 | |||
1571 | /* | ||
1572 | * Configure attributes for power mode change with below. | ||
1573 | * - PA_RXGEAR, PA_ACTIVERXDATALANES, PA_RXTERMINATION, | ||
1574 | * - PA_TXGEAR, PA_ACTIVETXDATALANES, PA_TXTERMINATION, | ||
1575 | * - PA_HSSERIES | ||
1576 | */ | ||
1577 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXGEAR), gear[RX]); | ||
1578 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVERXDATALANES), lanes[RX]); | ||
1579 | if (pwr[RX] == FASTAUTO_MODE) | ||
1580 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), TRUE); | ||
1581 | |||
1582 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXGEAR), gear[TX]); | ||
1583 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVETXDATALANES), lanes[TX]); | ||
1584 | if (pwr[TX] == FASTAUTO_MODE) | ||
1585 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), TRUE); | ||
1586 | |||
1587 | if (pwr[RX] == FASTAUTO_MODE || pwr[TX] == FASTAUTO_MODE) | ||
1588 | ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HSSERIES), PA_HS_MODE_B); | ||
1589 | |||
1590 | ret = ufshcd_uic_change_pwr_mode(hba, pwr[RX] << 4 | pwr[TX]); | ||
1591 | if (ret) | ||
1592 | dev_err(hba->dev, | ||
1593 | "pwr_mode: power mode change failed %d\n", ret); | ||
1594 | |||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | /** | ||
1535 | * ufshcd_complete_dev_init() - checks device readiness | 1599 | * ufshcd_complete_dev_init() - checks device readiness |
1536 | * hba: per-adapter instance | 1600 | * hba: per-adapter instance |
1537 | * | 1601 | * |
@@ -2662,6 +2726,8 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie) | |||
2662 | if (ret) | 2726 | if (ret) |
2663 | goto out; | 2727 | goto out; |
2664 | 2728 | ||
2729 | ufshcd_config_max_pwr_mode(hba); | ||
2730 | |||
2665 | ret = ufshcd_verify_dev_init(hba); | 2731 | ret = ufshcd_verify_dev_init(hba); |
2666 | if (ret) | 2732 | if (ret) |
2667 | goto out; | 2733 | goto out; |
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h index 3a710eb3ec20..0bb8041c047a 100644 --- a/drivers/scsi/ufs/unipro.h +++ b/drivers/scsi/ufs/unipro.h | |||
@@ -72,6 +72,21 @@ | |||
72 | #define PA_STALLNOCONFIGTIME 0x15A3 | 72 | #define PA_STALLNOCONFIGTIME 0x15A3 |
73 | #define PA_SAVECONFIGTIME 0x15A4 | 73 | #define PA_SAVECONFIGTIME 0x15A4 |
74 | 74 | ||
75 | /* PA power modes */ | ||
76 | enum { | ||
77 | FAST_MODE = 1, | ||
78 | SLOW_MODE = 2, | ||
79 | FASTAUTO_MODE = 4, | ||
80 | SLOWAUTO_MODE = 5, | ||
81 | UNCHANGED = 7, | ||
82 | }; | ||
83 | |||
84 | /* PA TX/RX Frequency Series */ | ||
85 | enum { | ||
86 | PA_HS_MODE_A = 1, | ||
87 | PA_HS_MODE_B = 2, | ||
88 | }; | ||
89 | |||
75 | /* | 90 | /* |
76 | * Data Link Layer Attributes | 91 | * Data Link Layer Attributes |
77 | */ | 92 | */ |
@@ -127,4 +142,10 @@ | |||
127 | #define T_TC0TXMAXSDUSIZE 0x4060 | 142 | #define T_TC0TXMAXSDUSIZE 0x4060 |
128 | #define T_TC1TXMAXSDUSIZE 0x4061 | 143 | #define T_TC1TXMAXSDUSIZE 0x4061 |
129 | 144 | ||
145 | /* Boolean attribute values */ | ||
146 | enum { | ||
147 | FALSE = 0, | ||
148 | TRUE, | ||
149 | }; | ||
150 | |||
130 | #endif /* _UNIPRO_H_ */ | 151 | #endif /* _UNIPRO_H_ */ |