11/*
2- * Copyright (c) 2013-2015 , Linux Foundation. All rights reserved.
2+ * Copyright (c) 2013-2016 , Linux Foundation. All rights reserved.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License version 2 and
1616#include <linux/of.h>
1717#include <linux/platform_device.h>
1818#include <linux/phy/phy.h>
19-
2019#include <linux/phy/phy-qcom-ufs.h>
20+
2121#include "ufshcd.h"
2222#include "ufshcd-pltfrm.h"
2323#include "unipro.h"
@@ -58,6 +58,12 @@ static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
5858 len * 4 , false);
5959}
6060
61+ static void ufs_qcom_dump_regs_wrapper (struct ufs_hba * hba , int offset , int len ,
62+ char * prefix , void * priv )
63+ {
64+ ufs_qcom_dump_regs (hba , offset , len , prefix );
65+ }
66+
6167static int ufs_qcom_get_connected_tx_lanes (struct ufs_hba * hba , u32 * tx_lanes )
6268{
6369 int err = 0 ;
@@ -106,9 +112,11 @@ static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
106112 if (!host -> is_lane_clks_enabled )
107113 return ;
108114
109- clk_disable_unprepare (host -> tx_l1_sync_clk );
115+ if (host -> hba -> lanes_per_direction > 1 )
116+ clk_disable_unprepare (host -> tx_l1_sync_clk );
110117 clk_disable_unprepare (host -> tx_l0_sync_clk );
111- clk_disable_unprepare (host -> rx_l1_sync_clk );
118+ if (host -> hba -> lanes_per_direction > 1 )
119+ clk_disable_unprepare (host -> rx_l1_sync_clk );
112120 clk_disable_unprepare (host -> rx_l0_sync_clk );
113121
114122 host -> is_lane_clks_enabled = false;
@@ -132,21 +140,24 @@ static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host *host)
132140 if (err )
133141 goto disable_rx_l0 ;
134142
135- err = ufs_qcom_host_clk_enable (dev , "rx_lane1_sync_clk" ,
136- host -> rx_l1_sync_clk );
137- if (err )
138- goto disable_tx_l0 ;
143+ if (host -> hba -> lanes_per_direction > 1 ) {
144+ err = ufs_qcom_host_clk_enable (dev , "rx_lane1_sync_clk" ,
145+ host -> rx_l1_sync_clk );
146+ if (err )
147+ goto disable_tx_l0 ;
139148
140- err = ufs_qcom_host_clk_enable (dev , "tx_lane1_sync_clk" ,
141- host -> tx_l1_sync_clk );
142- if (err )
143- goto disable_rx_l1 ;
149+ err = ufs_qcom_host_clk_enable (dev , "tx_lane1_sync_clk" ,
150+ host -> tx_l1_sync_clk );
151+ if (err )
152+ goto disable_rx_l1 ;
153+ }
144154
145155 host -> is_lane_clks_enabled = true;
146156 goto out ;
147157
148158disable_rx_l1 :
149- clk_disable_unprepare (host -> rx_l1_sync_clk );
159+ if (host -> hba -> lanes_per_direction > 1 )
160+ clk_disable_unprepare (host -> rx_l1_sync_clk );
150161disable_tx_l0 :
151162 clk_disable_unprepare (host -> tx_l0_sync_clk );
152163disable_rx_l0 :
@@ -170,14 +181,16 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host)
170181 if (err )
171182 goto out ;
172183
173- err = ufs_qcom_host_clk_get (dev , "rx_lane1_sync_clk" ,
174- & host -> rx_l1_sync_clk );
175- if (err )
176- goto out ;
177-
178- err = ufs_qcom_host_clk_get (dev , "tx_lane1_sync_clk" ,
179- & host -> tx_l1_sync_clk );
184+ /* In case of single lane per direction, don't read lane1 clocks */
185+ if (host -> hba -> lanes_per_direction > 1 ) {
186+ err = ufs_qcom_host_clk_get (dev , "rx_lane1_sync_clk" ,
187+ & host -> rx_l1_sync_clk );
188+ if (err )
189+ goto out ;
180190
191+ err = ufs_qcom_host_clk_get (dev , "tx_lane1_sync_clk" ,
192+ & host -> tx_l1_sync_clk );
193+ }
181194out :
182195 return err ;
183196}
@@ -267,9 +280,8 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
267280 ret = ufs_qcom_phy_calibrate_phy (phy , is_rate_B );
268281
269282 if (ret ) {
270- dev_err (hba -> dev ,
271- "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n" ,
272- __func__ , ret );
283+ dev_err (hba -> dev , "%s: ufs_qcom_phy_calibrate_phy() failed, ret = %d\n" ,
284+ __func__ , ret );
273285 goto out ;
274286 }
275287
@@ -519,6 +531,18 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
519531 err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div (hba ,
520532 150 );
521533
534+ /*
535+ * Some UFS devices (and may be host) have issues if LCC is
536+ * enabled. So we are setting PA_Local_TX_LCC_Enable to 0
537+ * before link startup which will make sure that both host
538+ * and device TX LCC are disabled once link startup is
539+ * completed.
540+ */
541+ if (ufshcd_get_local_unipro_ver (hba ) != UFS_UNIPRO_VER_1_41 )
542+ err = ufshcd_dme_set (hba ,
543+ UIC_ARG_MIB (PA_LOCAL_TX_LCC_ENABLE ),
544+ 0 );
545+
522546 break ;
523547 case POST_CHANGE :
524548 ufs_qcom_link_startup_post_change (hba );
@@ -962,6 +986,10 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
962986 goto out ;
963987 }
964988
989+ /* enable the device ref clock before changing to HS mode */
990+ if (!ufshcd_is_hs_mode (& hba -> pwr_info ) &&
991+ ufshcd_is_hs_mode (dev_req_params ))
992+ ufs_qcom_dev_ref_clk_ctrl (host , true);
965993 break ;
966994 case POST_CHANGE :
967995 if (ufs_qcom_cfg_timers (hba , dev_req_params -> gear_rx ,
@@ -989,6 +1017,11 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
9891017 memcpy (& host -> dev_req_params ,
9901018 dev_req_params , sizeof (* dev_req_params ));
9911019 ufs_qcom_update_bus_bw_vote (host );
1020+
1021+ /* disable the device ref clock if entered PWM mode */
1022+ if (ufshcd_is_hs_mode (& hba -> pwr_info ) &&
1023+ !ufshcd_is_hs_mode (dev_req_params ))
1024+ ufs_qcom_dev_ref_clk_ctrl (host , false);
9921025 break ;
9931026 default :
9941027 ret = - EINVAL ;
@@ -1090,6 +1123,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
10901123 ufs_qcom_phy_disable_iface_clk (host -> generic_phy );
10911124 goto out ;
10921125 }
1126+ /* enable the device ref clock for HS mode*/
1127+ if (ufshcd_is_hs_mode (& hba -> pwr_info ))
1128+ ufs_qcom_dev_ref_clk_ctrl (host , true);
10931129 vote = host -> bus_vote .saved_vote ;
10941130 if (vote == host -> bus_vote .min_bw_vote )
10951131 ufs_qcom_update_bus_bw_vote (host );
@@ -1367,6 +1403,74 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
13671403 return err ;
13681404}
13691405
1406+ static void ufs_qcom_print_hw_debug_reg_all (struct ufs_hba * hba ,
1407+ void * priv , void (* print_fn )(struct ufs_hba * hba ,
1408+ int offset , int num_regs , char * str , void * priv ))
1409+ {
1410+ u32 reg ;
1411+ struct ufs_qcom_host * host ;
1412+
1413+ if (unlikely (!hba )) {
1414+ pr_err ("%s: hba is NULL\n" , __func__ );
1415+ return ;
1416+ }
1417+ if (unlikely (!print_fn )) {
1418+ dev_err (hba -> dev , "%s: print_fn is NULL\n" , __func__ );
1419+ return ;
1420+ }
1421+
1422+ host = ufshcd_get_variant (hba );
1423+ if (!(host -> dbg_print_en & UFS_QCOM_DBG_PRINT_REGS_EN ))
1424+ return ;
1425+
1426+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_UFS_DBG_RD_REG_OCSC );
1427+ print_fn (hba , reg , 44 , "UFS_UFS_DBG_RD_REG_OCSC " , priv );
1428+
1429+ reg = ufshcd_readl (hba , REG_UFS_CFG1 );
1430+ reg |= UFS_BIT (17 );
1431+ ufshcd_writel (hba , reg , REG_UFS_CFG1 );
1432+
1433+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_UFS_DBG_RD_EDTL_RAM );
1434+ print_fn (hba , reg , 32 , "UFS_UFS_DBG_RD_EDTL_RAM " , priv );
1435+
1436+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_UFS_DBG_RD_DESC_RAM );
1437+ print_fn (hba , reg , 128 , "UFS_UFS_DBG_RD_DESC_RAM " , priv );
1438+
1439+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_UFS_DBG_RD_PRDT_RAM );
1440+ print_fn (hba , reg , 64 , "UFS_UFS_DBG_RD_PRDT_RAM " , priv );
1441+
1442+ ufshcd_writel (hba , (reg & ~UFS_BIT (17 )), REG_UFS_CFG1 );
1443+
1444+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_DBG_RD_REG_UAWM );
1445+ print_fn (hba , reg , 4 , "UFS_DBG_RD_REG_UAWM " , priv );
1446+
1447+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_DBG_RD_REG_UARM );
1448+ print_fn (hba , reg , 4 , "UFS_DBG_RD_REG_UARM " , priv );
1449+
1450+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_DBG_RD_REG_TXUC );
1451+ print_fn (hba , reg , 48 , "UFS_DBG_RD_REG_TXUC " , priv );
1452+
1453+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_DBG_RD_REG_RXUC );
1454+ print_fn (hba , reg , 27 , "UFS_DBG_RD_REG_RXUC " , priv );
1455+
1456+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_DBG_RD_REG_DFC );
1457+ print_fn (hba , reg , 19 , "UFS_DBG_RD_REG_DFC " , priv );
1458+
1459+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_DBG_RD_REG_TRLUT );
1460+ print_fn (hba , reg , 34 , "UFS_DBG_RD_REG_TRLUT " , priv );
1461+
1462+ reg = ufs_qcom_get_debug_reg_offset (host , UFS_DBG_RD_REG_TMRLUT );
1463+ print_fn (hba , reg , 9 , "UFS_DBG_RD_REG_TMRLUT " , priv );
1464+ }
1465+
1466+ static void ufs_qcom_enable_test_bus (struct ufs_qcom_host * host )
1467+ {
1468+ if (host -> dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN )
1469+ ufshcd_rmwl (host -> hba , TEST_BUS_EN , TEST_BUS_EN , REG_UFS_CFG1 );
1470+ else
1471+ ufshcd_rmwl (host -> hba , TEST_BUS_EN , 0 , REG_UFS_CFG1 );
1472+ }
1473+
13701474static void ufs_qcom_get_default_testbus_cfg (struct ufs_qcom_host * host )
13711475{
13721476 /* provide a legal default configuration */
@@ -1475,6 +1579,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
14751579 ufshcd_rmwl (host -> hba , mask ,
14761580 (u32 )host -> testbus .select_minor << offset ,
14771581 reg );
1582+ ufs_qcom_enable_test_bus (host );
14781583 ufshcd_release (host -> hba );
14791584 pm_runtime_put_sync (host -> hba -> dev );
14801585
@@ -1491,8 +1596,10 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
14911596 ufs_qcom_dump_regs (hba , REG_UFS_SYS1CLK_1US , 16 ,
14921597 "HCI Vendor Specific Registers " );
14931598
1599+ ufs_qcom_print_hw_debug_reg_all (hba , NULL , ufs_qcom_dump_regs_wrapper );
14941600 ufs_qcom_testbus_read (hba );
14951601}
1602+
14961603/**
14971604 * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
14981605 *
@@ -1537,7 +1644,7 @@ static int ufs_qcom_probe(struct platform_device *pdev)
15371644 * ufs_qcom_remove - set driver_data of the device to NULL
15381645 * @pdev: pointer to platform device handle
15391646 *
1540- * Always return 0
1647+ * Always returns 0
15411648 */
15421649static int ufs_qcom_remove (struct platform_device * pdev )
15431650{
0 commit comments