13
13
#include <linux/regulator/consumer.h>
14
14
#include <linux/reset.h>
15
15
16
+ #define EXYNOS_USB_PHY_HS_PHY_CTRL_RST (0x0)
17
+ #define USB_PHY_RST_MASK GENMASK(1, 0)
18
+ #define UTMI_PORT_RST_MASK GENMASK(5, 4)
19
+
20
+ #define EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON (0x4)
21
+ #define RPTR_MODE BIT(10)
22
+ #define FSEL_20_MHZ_VAL (0x1)
23
+ #define FSEL_24_MHZ_VAL (0x2)
24
+ #define FSEL_26_MHZ_VAL (0x3)
25
+ #define FSEL_48_MHZ_VAL (0x2)
26
+
27
+ #define EXYNOS_USB_PHY_CFG_PLLCFG0 (0x8)
28
+ #define PHY_CFG_PLL_FB_DIV_19_8_MASK GENMASK(19, 8)
29
+ #define DIV_19_8_19_2_MHZ_VAL (0x170)
30
+ #define DIV_19_8_20_MHZ_VAL (0x160)
31
+ #define DIV_19_8_24_MHZ_VAL (0x120)
32
+ #define DIV_19_8_26_MHZ_VAL (0x107)
33
+ #define DIV_19_8_48_MHZ_VAL (0x120)
34
+
35
+ #define EXYNOS_USB_PHY_CFG_PLLCFG1 (0xc)
36
+ #define EXYNOS_PHY_CFG_PLL_FB_DIV_11_8_MASK GENMASK(11, 8)
37
+ #define EXYNOS_DIV_11_8_19_2_MHZ_VAL (0x0)
38
+ #define EXYNOS_DIV_11_8_20_MHZ_VAL (0x0)
39
+ #define EXYNOS_DIV_11_8_24_MHZ_VAL (0x0)
40
+ #define EXYNOS_DIV_11_8_26_MHZ_VAL (0x0)
41
+ #define EXYNOS_DIV_11_8_48_MHZ_VAL (0x1)
42
+
43
+ #define EXYNOS_PHY_CFG_TX (0x14)
44
+ #define EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK GENMASK(2, 1)
45
+
46
+ #define EXYNOS_USB_PHY_UTMI_TESTSE (0x20)
47
+ #define TEST_IDDQ BIT(6)
48
+
16
49
#define QCOM_USB_PHY_UTMI_CTRL0 (0x3c)
17
50
#define SLEEPM BIT(0)
18
51
#define OPMODE_MASK GENMASK(4, 3)
@@ -123,13 +156,16 @@ static const char * const eusb2_hsphy_vreg_names[] = {
123
156
124
157
struct snps_eusb2_phy_drvdata {
125
158
int (* phy_init )(struct phy * p );
159
+ const char * const * clk_names ;
160
+ int num_clks ;
126
161
};
127
162
128
163
struct snps_eusb2_hsphy {
129
164
struct phy * phy ;
130
165
void __iomem * base ;
131
166
132
167
struct clk * ref_clk ;
168
+ struct clk_bulk_data * clks ;
133
169
struct reset_control * phy_reset ;
134
170
135
171
struct regulator_bulk_data vregs [EUSB2_NUM_VREGS ];
@@ -199,6 +235,46 @@ struct snps_eusb2_ref_clk {
199
235
u32 div_11_8_val ;
200
236
};
201
237
238
+ static const struct snps_eusb2_ref_clk exynos_eusb2_ref_clk [] = {
239
+ { 19200000 , FSEL_19_2_MHZ_VAL , DIV_19_8_19_2_MHZ_VAL , EXYNOS_DIV_11_8_19_2_MHZ_VAL },
240
+ { 20000000 , FSEL_20_MHZ_VAL , DIV_19_8_20_MHZ_VAL , EXYNOS_DIV_11_8_20_MHZ_VAL },
241
+ { 24000000 , FSEL_24_MHZ_VAL , DIV_19_8_24_MHZ_VAL , EXYNOS_DIV_11_8_24_MHZ_VAL },
242
+ { 26000000 , FSEL_26_MHZ_VAL , DIV_19_8_26_MHZ_VAL , EXYNOS_DIV_11_8_26_MHZ_VAL },
243
+ { 48000000 , FSEL_48_MHZ_VAL , DIV_19_8_48_MHZ_VAL , EXYNOS_DIV_11_8_48_MHZ_VAL },
244
+ };
245
+
246
+ static int exynos_eusb2_ref_clk_init (struct snps_eusb2_hsphy * phy )
247
+ {
248
+ const struct snps_eusb2_ref_clk * config = NULL ;
249
+ unsigned long ref_clk_freq = clk_get_rate (phy -> ref_clk );
250
+
251
+ for (int i = 0 ; i < ARRAY_SIZE (exynos_eusb2_ref_clk ); i ++ ) {
252
+ if (exynos_eusb2_ref_clk [i ].freq == ref_clk_freq ) {
253
+ config = & exynos_eusb2_ref_clk [i ];
254
+ break ;
255
+ }
256
+ }
257
+
258
+ if (!config ) {
259
+ dev_err (& phy -> phy -> dev , "unsupported ref_clk_freq:%lu\n" , ref_clk_freq );
260
+ return - EINVAL ;
261
+ }
262
+
263
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON ,
264
+ FSEL_MASK ,
265
+ FIELD_PREP (FSEL_MASK , config -> fsel_val ));
266
+
267
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_CFG_PLLCFG0 ,
268
+ PHY_CFG_PLL_FB_DIV_19_8_MASK ,
269
+ FIELD_PREP (PHY_CFG_PLL_FB_DIV_19_8_MASK ,
270
+ config -> div_7_0_val ));
271
+
272
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_CFG_PLLCFG1 ,
273
+ EXYNOS_PHY_CFG_PLL_FB_DIV_11_8_MASK ,
274
+ config -> div_11_8_val );
275
+ return 0 ;
276
+ }
277
+
202
278
static const struct snps_eusb2_ref_clk qcom_eusb2_ref_clk [] = {
203
279
{ 19200000 , FSEL_19_2_MHZ_VAL , DIV_7_0_19_2_MHZ_VAL , DIV_11_8_19_2_MHZ_VAL },
204
280
{ 38400000 , FSEL_38_4_MHZ_VAL , DIV_7_0_38_4_MHZ_VAL , DIV_11_8_38_4_MHZ_VAL },
@@ -239,6 +315,55 @@ static int qcom_eusb2_ref_clk_init(struct snps_eusb2_hsphy *phy)
239
315
return 0 ;
240
316
}
241
317
318
+ static int exynos_snps_eusb2_hsphy_init (struct phy * p )
319
+ {
320
+ struct snps_eusb2_hsphy * phy = phy_get_drvdata (p );
321
+ int ret ;
322
+
323
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_HS_PHY_CTRL_RST ,
324
+ USB_PHY_RST_MASK | UTMI_PORT_RST_MASK ,
325
+ USB_PHY_RST_MASK | UTMI_PORT_RST_MASK );
326
+ fsleep (50 ); /* required after holding phy in reset */
327
+
328
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON ,
329
+ RPTR_MODE , RPTR_MODE );
330
+
331
+ /* update ref_clk related registers */
332
+ ret = exynos_eusb2_ref_clk_init (phy );
333
+ if (ret )
334
+ return ret ;
335
+
336
+ /* default parameter: tx fsls-vref */
337
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_PHY_CFG_TX ,
338
+ EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK ,
339
+ FIELD_PREP (EXYNOS_PHY_CFG_TX_FSLS_VREF_TUNE_MASK , 0x0 ));
340
+
341
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_UTMI_TESTSE ,
342
+ TEST_IDDQ , 0 );
343
+ fsleep (10 ); /* required after releasing test_iddq */
344
+
345
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_HS_PHY_CTRL_RST ,
346
+ USB_PHY_RST_MASK , 0 );
347
+
348
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_HS_PHY_CTRL_COMMON ,
349
+ PHY_ENABLE , PHY_ENABLE );
350
+
351
+ snps_eusb2_hsphy_write_mask (phy -> base , EXYNOS_USB_PHY_HS_PHY_CTRL_RST ,
352
+ UTMI_PORT_RST_MASK , 0 );
353
+
354
+ return 0 ;
355
+ }
356
+
357
+ static const char * const exynos_eusb2_hsphy_clock_names [] = {
358
+ "ref" , "bus" , "ctrl" ,
359
+ };
360
+
361
+ static const struct snps_eusb2_phy_drvdata exynos2200_snps_eusb2_phy = {
362
+ .phy_init = exynos_snps_eusb2_hsphy_init ,
363
+ .clk_names = exynos_eusb2_hsphy_clock_names ,
364
+ .num_clks = ARRAY_SIZE (exynos_eusb2_hsphy_clock_names ),
365
+ };
366
+
242
367
static int qcom_snps_eusb2_hsphy_init (struct phy * p )
243
368
{
244
369
struct snps_eusb2_hsphy * phy = phy_get_drvdata (p );
@@ -315,8 +440,14 @@ static int qcom_snps_eusb2_hsphy_init(struct phy *p)
315
440
return 0 ;
316
441
}
317
442
443
+ static const char * const qcom_eusb2_hsphy_clock_names [] = {
444
+ "ref" ,
445
+ };
446
+
318
447
static const struct snps_eusb2_phy_drvdata sm8550_snps_eusb2_phy = {
319
448
.phy_init = qcom_snps_eusb2_hsphy_init ,
449
+ .clk_names = qcom_eusb2_hsphy_clock_names ,
450
+ .num_clks = ARRAY_SIZE (qcom_eusb2_hsphy_clock_names ),
320
451
};
321
452
322
453
static int snps_eusb2_hsphy_init (struct phy * p )
@@ -334,7 +465,7 @@ static int snps_eusb2_hsphy_init(struct phy *p)
334
465
goto disable_vreg ;
335
466
}
336
467
337
- ret = clk_prepare_enable (phy -> ref_clk );
468
+ ret = clk_bulk_prepare_enable (phy -> data -> num_clks , phy -> clks );
338
469
if (ret ) {
339
470
dev_err (& p -> dev , "failed to enable ref clock, %d\n" , ret );
340
471
goto disable_vreg ;
@@ -361,7 +492,7 @@ static int snps_eusb2_hsphy_init(struct phy *p)
361
492
return 0 ;
362
493
363
494
disable_ref_clk :
364
- clk_disable_unprepare (phy -> ref_clk );
495
+ clk_bulk_disable_unprepare (phy -> data -> num_clks , phy -> clks );
365
496
366
497
disable_vreg :
367
498
regulator_bulk_disable (ARRAY_SIZE (phy -> vregs ), phy -> vregs );
@@ -415,8 +546,28 @@ static int snps_eusb2_hsphy_probe(struct platform_device *pdev)
415
546
if (IS_ERR (phy -> phy_reset ))
416
547
return PTR_ERR (phy -> phy_reset );
417
548
418
- phy -> ref_clk = devm_clk_get (dev , "ref" );
419
- if (IS_ERR (phy -> ref_clk ))
549
+ phy -> clks = devm_kcalloc (dev , phy -> data -> num_clks , sizeof (* phy -> clks ),
550
+ GFP_KERNEL );
551
+ if (!phy -> clks )
552
+ return - ENOMEM ;
553
+
554
+ for (int i = 0 ; i < phy -> data -> num_clks ; ++ i )
555
+ phy -> clks [i ].id = phy -> data -> clk_names [i ];
556
+
557
+ ret = devm_clk_bulk_get (dev , phy -> data -> num_clks , phy -> clks );
558
+ if (ret )
559
+ return dev_err_probe (dev , ret ,
560
+ "failed to get phy clock(s)\n" );
561
+
562
+ phy -> ref_clk = NULL ;
563
+ for (int i = 0 ; i < phy -> data -> num_clks ; ++ i ) {
564
+ if (!strcmp (phy -> clks [i ].id , "ref" )) {
565
+ phy -> ref_clk = phy -> clks [i ].clk ;
566
+ break ;
567
+ }
568
+ }
569
+
570
+ if (IS_ERR_OR_NULL (phy -> ref_clk ))
420
571
return dev_err_probe (dev , PTR_ERR (phy -> ref_clk ),
421
572
"failed to get ref clk\n" );
422
573
@@ -456,6 +607,9 @@ static const struct of_device_id snps_eusb2_hsphy_of_match_table[] = {
456
607
{
457
608
.compatible = "qcom,sm8550-snps-eusb2-phy" ,
458
609
.data = & sm8550_snps_eusb2_phy ,
610
+ }, {
611
+ .compatible = "samsung,exynos2200-eusb2-phy" ,
612
+ .data = & exynos2200_snps_eusb2_phy ,
459
613
}, { },
460
614
};
461
615
MODULE_DEVICE_TABLE (of , snps_eusb2_hsphy_of_match_table );
0 commit comments