1212#include <linux/module.h>
1313#include <linux/of.h>
1414#include <linux/of_address.h>
15+ #include <linux/mfd/syscon.h>
1516#include <linux/phy/phy.h>
1617#include <linux/platform_device.h>
18+ #include <linux/regmap.h>
1719
1820#include "ufshcd.h"
1921#include "ufshcd-pltfrm.h"
7577 UIC_TRANSPORT_NO_CONNECTION_RX |\
7678 UIC_TRANSPORT_BAD_TC)
7779
80+ /* FSYS UFS Shareability */
81+ #define UFS_WR_SHARABLE BIT(2)
82+ #define UFS_RD_SHARABLE BIT(1)
83+ #define UFS_SHARABLE (UFS_WR_SHARABLE | UFS_RD_SHARABLE)
84+ #define UFS_SHAREABILITY_OFFSET 0x710
85+
7886enum {
7987 UNIPRO_L1_5 = 0 ,/* PHY Adapter */
8088 UNIPRO_L2 , /* Data Link */
@@ -150,6 +158,89 @@ static int exynos7_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs)
150158 return 0 ;
151159}
152160
161+ static int exynosauto_ufs_drv_init (struct device * dev , struct exynos_ufs * ufs )
162+ {
163+ struct exynos_ufs_uic_attr * attr = ufs -> drv_data -> uic_attr ;
164+
165+ /* IO Coherency setting */
166+ if (ufs -> sysreg ) {
167+ return regmap_update_bits (ufs -> sysreg ,
168+ ufs -> shareability_reg_offset ,
169+ UFS_SHARABLE , UFS_SHARABLE );
170+ }
171+
172+ attr -> tx_dif_p_nsec = 3200000 ;
173+
174+ return 0 ;
175+ }
176+
177+ static int exynosauto_ufs_pre_link (struct exynos_ufs * ufs )
178+ {
179+ struct ufs_hba * hba = ufs -> hba ;
180+ int i ;
181+ u32 tx_line_reset_period , rx_line_reset_period ;
182+
183+ rx_line_reset_period = (RX_LINE_RESET_TIME * ufs -> mclk_rate ) / NSEC_PER_MSEC ;
184+ tx_line_reset_period = (TX_LINE_RESET_TIME * ufs -> mclk_rate ) / NSEC_PER_MSEC ;
185+
186+ ufshcd_dme_set (hba , UIC_ARG_MIB (0x200 ), 0x40 );
187+ for_each_ufs_rx_lane (ufs , i ) {
188+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_CLK_PRD , i ),
189+ DIV_ROUND_UP (NSEC_PER_SEC , ufs -> mclk_rate ));
190+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_CLK_PRD_EN , i ), 0x0 );
191+
192+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_LINERESET_VALUE2 , i ),
193+ (rx_line_reset_period >> 16 ) & 0xFF );
194+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_LINERESET_VALUE1 , i ),
195+ (rx_line_reset_period >> 8 ) & 0xFF );
196+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_RX_LINERESET_VALUE0 , i ),
197+ (rx_line_reset_period ) & 0xFF );
198+
199+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x2f , i ), 0x79 );
200+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x84 , i ), 0x1 );
201+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x25 , i ), 0xf6 );
202+ }
203+
204+ for_each_ufs_tx_lane (ufs , i ) {
205+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_CLK_PRD , i ),
206+ DIV_ROUND_UP (NSEC_PER_SEC , ufs -> mclk_rate ));
207+ /* Not to affect VND_TX_LINERESET_PVALUE to VND_TX_CLK_PRD */
208+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_CLK_PRD_EN , i ),
209+ 0x02 );
210+
211+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_LINERESET_PVALUE2 , i ),
212+ (tx_line_reset_period >> 16 ) & 0xFF );
213+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_LINERESET_PVALUE1 , i ),
214+ (tx_line_reset_period >> 8 ) & 0xFF );
215+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (VND_TX_LINERESET_PVALUE0 , i ),
216+ (tx_line_reset_period ) & 0xFF );
217+
218+ /* TX PWM Gear Capability / PWM_G1_ONLY */
219+ ufshcd_dme_set (hba , UIC_ARG_MIB_SEL (0x04 , i ), 0x1 );
220+ }
221+
222+ ufshcd_dme_set (hba , UIC_ARG_MIB (0x200 ), 0x0 );
223+
224+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_LOCAL_TX_LCC_ENABLE ), 0x0 );
225+
226+ ufshcd_dme_set (hba , UIC_ARG_MIB (0xa011 ), 0x8000 );
227+
228+ return 0 ;
229+ }
230+
231+ static int exynosauto_ufs_pre_pwr_change (struct exynos_ufs * ufs ,
232+ struct ufs_pa_layer_attr * pwr )
233+ {
234+ struct ufs_hba * hba = ufs -> hba ;
235+
236+ /* PACP_PWR_req and delivered to the remote DME */
237+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_PWRMODEUSERDATA0 ), 12000 );
238+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_PWRMODEUSERDATA1 ), 32000 );
239+ ufshcd_dme_set (hba , UIC_ARG_MIB (PA_PWRMODEUSERDATA2 ), 16000 );
240+
241+ return 0 ;
242+ }
243+
153244static int exynos7_ufs_pre_link (struct exynos_ufs * ufs )
154245{
155246 struct ufs_hba * hba = ufs -> hba ;
@@ -932,6 +1023,17 @@ static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs)
9321023 goto out ;
9331024 }
9341025
1026+ ufs -> sysreg = syscon_regmap_lookup_by_phandle (np , "samsung,sysreg" );
1027+ if (IS_ERR (ufs -> sysreg ))
1028+ ufs -> sysreg = NULL ;
1029+ else {
1030+ if (of_property_read_u32_index (np , "samsung,sysreg" , 1 ,
1031+ & ufs -> shareability_reg_offset )) {
1032+ dev_warn (dev , "can't get an offset from sysreg. Set to default value\n" );
1033+ ufs -> shareability_reg_offset = UFS_SHAREABILITY_OFFSET ;
1034+ }
1035+ }
1036+
9351037 ufs -> pclk_avail_min = PCLK_AVAIL_MIN ;
9361038 ufs -> pclk_avail_max = PCLK_AVAIL_MAX ;
9371039
@@ -1304,6 +1406,20 @@ static struct exynos_ufs_uic_attr exynos7_uic_attr = {
13041406 .pa_dbg_option_suite = 0x30103 ,
13051407};
13061408
1409+ static struct exynos_ufs_drv_data exynosauto_ufs_drvs = {
1410+ .uic_attr = & exynos7_uic_attr ,
1411+ .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN |
1412+ UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR |
1413+ UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR |
1414+ UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING ,
1415+ .opts = EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL |
1416+ EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR |
1417+ EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX ,
1418+ .drv_init = exynosauto_ufs_drv_init ,
1419+ .pre_link = exynosauto_ufs_pre_link ,
1420+ .pre_pwr_change = exynosauto_ufs_pre_pwr_change ,
1421+ };
1422+
13071423static struct exynos_ufs_drv_data exynos_ufs_drvs = {
13081424 .uic_attr = & exynos7_uic_attr ,
13091425 .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN |
@@ -1329,6 +1445,8 @@ static struct exynos_ufs_drv_data exynos_ufs_drvs = {
13291445static const struct of_device_id exynos_ufs_of_match [] = {
13301446 { .compatible = "samsung,exynos7-ufs" ,
13311447 .data = & exynos_ufs_drvs },
1448+ { .compatible = "samsung,exynosautov9-ufs" ,
1449+ .data = & exynosauto_ufs_drvs },
13321450 {},
13331451};
13341452
0 commit comments