Skip to content

Commit cc52e15

Browse files
cometzeromartinkpetersen
authored andcommitted
scsi: ufs: ufs-exynos: Support ExynosAuto v9 UFS
Add support for the ExynosAuto v9 SoC. This requires controlling the UFS IP shareability register via syscon and regmap. The offset of the register can be different according to the UFS instance and SoC specific offset value. As a result, we need to get the offset value from DT property. Unlike exynos7, this implementation has a different M-PHY setting which must be configured via exynosauto_ufs_pre_link. Link: https://lore.kernel.org/r/20211018124216.153072-12-chanho61.park@samsung.com Cc: Alim Akhtar <alim.akhtar@samsung.com> Cc: Kiwoong Kim <kwmad.kim@samsung.com> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com> Signed-off-by: Chanho Park <chanho61.park@samsung.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 52e5035 commit cc52e15

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

drivers/scsi/ufs/ufs-exynos.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
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"
@@ -75,6 +77,12 @@
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+
7886
enum {
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+
153244
static 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+
13071423
static 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 = {
13291445
static 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

drivers/scsi/ufs/ufs-exynos.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@
5656
#define TX_GRAN_NVAL_10_08 0x0296
5757
#define TX_GRAN_NVAL_H(v) (((v) >> 8) & 0x3)
5858

59+
#define VND_TX_CLK_PRD 0xAA
60+
#define VND_TX_CLK_PRD_EN 0xA9
61+
#define VND_TX_LINERESET_PVALUE0 0xAD
62+
#define VND_TX_LINERESET_PVALUE1 0xAC
63+
#define VND_TX_LINERESET_PVALUE2 0xAB
64+
65+
#define TX_LINE_RESET_TIME 3200
66+
67+
#define VND_RX_CLK_PRD 0x12
68+
#define VND_RX_CLK_PRD_EN 0x11
69+
#define VND_RX_LINERESET_VALUE0 0x1D
70+
#define VND_RX_LINERESET_VALUE1 0x1C
71+
#define VND_RX_LINERESET_VALUE2 0x1B
72+
73+
#define RX_LINE_RESET_TIME 1000
74+
5975
#define RX_FILLER_ENABLE 0x0316
6076
#define RX_FILLER_EN (1 << 1)
6177
#define RX_LINERESET_VAL 0x0317
@@ -194,6 +210,8 @@ struct exynos_ufs {
194210
struct ufs_phy_time_cfg t_cfg;
195211
ktime_t entry_hibern8_t;
196212
const struct exynos_ufs_drv_data *drv_data;
213+
struct regmap *sysreg;
214+
u32 shareability_reg_offset;
197215

198216
u32 opts;
199217
#define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL BIT(0)

0 commit comments

Comments
 (0)