Skip to content

Commit 8acc379

Browse files
clamor-sgregkh
authored andcommitted
usb: phy: tegra: add HSIC support
Add support for HSIC USB mode, which can be set for second USB controller and PHY on Tegra SoC along with already supported UTMI or ULPI. Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com> Link: https://patch.msgid.link/20260122151125.7367-3-clamor95@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 53cc2d9 commit 8acc379

2 files changed

Lines changed: 243 additions & 11 deletions

File tree

drivers/usb/phy/phy-tegra-usb.c

Lines changed: 238 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,26 @@
2929
#include <linux/usb/tegra_usb_phy.h>
3030
#include <linux/usb/ulpi.h>
3131

32+
#define USB_TXFILLTUNING 0x154
33+
#define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16)
34+
#define USB_FIFO_TXFILL_MASK 0x1f0000
35+
3236
#define ULPI_VIEWPORT 0x170
3337

3438
/* PORTSC PTS/PHCD bits, Tegra20 only */
3539
#define TEGRA_USB_PORTSC1 0x184
36-
#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
37-
#define TEGRA_USB_PORTSC1_PHCD BIT(23)
40+
#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
41+
#define TEGRA_USB_PORTSC1_PHCD BIT(23)
42+
#define TEGRA_USB_PORTSC1_WKOC BIT(22)
43+
#define TEGRA_USB_PORTSC1_WKDS BIT(21)
44+
#define TEGRA_USB_PORTSC1_WKCN BIT(20)
3845

3946
/* HOSTPC1 PTS/PHCD bits, Tegra30 and above */
47+
#define TEGRA30_USB_PORTSC1 0x174
4048
#define TEGRA_USB_HOSTPC1_DEVLC 0x1b4
41-
#define TEGRA_USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
42-
#define TEGRA_USB_HOSTPC1_DEVLC_PHCD BIT(22)
49+
#define TEGRA_USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
50+
#define TEGRA_USB_HOSTPC1_DEVLC_PHCD BIT(22)
51+
#define TEGRA_USB_HOSTPC1_DEVLC_PTS_HSIC BIT(2)
4352

4453
/* Bits of PORTSC1, which will get cleared by writing 1 into them */
4554
#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
@@ -51,11 +60,12 @@
5160
#define USB_SUSP_CLR BIT(5)
5261
#define USB_PHY_CLK_VALID BIT(7)
5362
#define UTMIP_RESET BIT(11)
54-
#define UHSIC_RESET BIT(11)
5563
#define UTMIP_PHY_ENABLE BIT(12)
5664
#define ULPI_PHY_ENABLE BIT(13)
5765
#define USB_SUSP_SET BIT(14)
66+
#define UHSIC_RESET BIT(14)
5867
#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
68+
#define UHSIC_PHY_ENABLE BIT(19)
5969

6070
#define USB_PHY_VBUS_SENSORS 0x404
6171
#define B_SESS_VLD_WAKEUP_EN BIT(14)
@@ -156,6 +166,58 @@
156166
#define UTMIP_BIAS_CFG1 0x83c
157167
#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
158168

169+
/*
170+
* Tegra20 has no UTMIP registers on PHY2 and UHSIC registers start from 0x800
171+
* just where UTMIP registers should have been. This is the case only with Tegra20
172+
* Tegra30+ have UTMIP registers at 0x800 and UHSIC registers shifter by 0x400
173+
* to 0xc00, but register layout is preserved.
174+
*/
175+
#define UHSIC_PLL_CFG1 0x804
176+
#define UHSIC_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
177+
#define UHSIC_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 14)
178+
179+
#define UHSIC_HSRX_CFG0 0x808
180+
#define UHSIC_ELASTIC_UNDERRUN_LIMIT(x) (((x) & 0x1f) << 2)
181+
#define UHSIC_ELASTIC_OVERRUN_LIMIT(x) (((x) & 0x1f) << 8)
182+
#define UHSIC_IDLE_WAIT(x) (((x) & 0x1f) << 13)
183+
184+
#define UHSIC_HSRX_CFG1 0x80c
185+
#define UHSIC_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
186+
187+
#define UHSIC_TX_CFG0 0x810
188+
#define UHSIC_HS_READY_WAIT_FOR_VALID BIT(9)
189+
190+
#define UHSIC_MISC_CFG0 0x814
191+
#define UHSIC_SUSPEND_EXIT_ON_EDGE BIT(7)
192+
#define UHSIC_DETECT_SHORT_CONNECT BIT(8)
193+
#define UHSIC_FORCE_XCVR_MODE BIT(15)
194+
#define UHSIC_DISABLE_BUSRESET BIT(20)
195+
196+
#define UHSIC_MISC_CFG1 0x818
197+
#define UHSIC_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 2)
198+
199+
#define UHSIC_PADS_CFG0 0x81c
200+
#define UHSIC_TX_RTUNEN 0xf000
201+
#define UHSIC_TX_RTUNE(x) (((x) & 0xf) << 12)
202+
203+
#define UHSIC_PADS_CFG1 0x820
204+
#define UHSIC_PD_BG BIT(2)
205+
#define UHSIC_PD_TX BIT(3)
206+
#define UHSIC_PD_TRK BIT(4)
207+
#define UHSIC_PD_RX BIT(5)
208+
#define UHSIC_PD_ZI BIT(6)
209+
#define UHSIC_RX_SEL BIT(7)
210+
#define UHSIC_RPD_DATA BIT(9)
211+
#define UHSIC_RPD_STROBE BIT(10)
212+
#define UHSIC_RPU_DATA BIT(11)
213+
#define UHSIC_RPU_STROBE BIT(12)
214+
215+
#define UHSIC_CMD_CFG0 0x824
216+
#define UHSIC_PRETEND_CONNECT_DETECT BIT(5)
217+
218+
#define UHSIC_STAT_CFG0 0x828
219+
#define UHSIC_CONNECT_DETECT BIT(0)
220+
159221
/* For Tegra30 and above only, the address is different in Tegra20 */
160222
#define USB_USBMODE 0x1f8
161223
#define USB_USBMODE_MASK (3 << 0)
@@ -174,7 +236,8 @@ struct tegra_xtal_freq {
174236
u8 enable_delay;
175237
u8 stable_count;
176238
u8 active_delay;
177-
u8 xtal_freq_count;
239+
u8 utmi_xtal_freq_count;
240+
u16 hsic_xtal_freq_count;
178241
u16 debounce;
179242
};
180243

@@ -184,31 +247,35 @@ static const struct tegra_xtal_freq tegra_freq_table[] = {
184247
.enable_delay = 0x02,
185248
.stable_count = 0x2F,
186249
.active_delay = 0x04,
187-
.xtal_freq_count = 0x76,
250+
.utmi_xtal_freq_count = 0x76,
251+
.hsic_xtal_freq_count = 0x1CA,
188252
.debounce = 0x7530,
189253
},
190254
{
191255
.freq = 13000000,
192256
.enable_delay = 0x02,
193257
.stable_count = 0x33,
194258
.active_delay = 0x05,
195-
.xtal_freq_count = 0x7F,
259+
.utmi_xtal_freq_count = 0x7F,
260+
.hsic_xtal_freq_count = 0x1F0,
196261
.debounce = 0x7EF4,
197262
},
198263
{
199264
.freq = 19200000,
200265
.enable_delay = 0x03,
201266
.stable_count = 0x4B,
202267
.active_delay = 0x06,
203-
.xtal_freq_count = 0xBB,
268+
.utmi_xtal_freq_count = 0xBB,
269+
.hsic_xtal_freq_count = 0x2DD,
204270
.debounce = 0xBB80,
205271
},
206272
{
207273
.freq = 26000000,
208274
.enable_delay = 0x04,
209275
.stable_count = 0x66,
210276
.active_delay = 0x09,
211-
.xtal_freq_count = 0xFE,
277+
.utmi_xtal_freq_count = 0xFE,
278+
.hsic_xtal_freq_count = 0x3E0,
212279
.debounce = 0xFDE8,
213280
},
214281
};
@@ -532,7 +599,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
532599
val = readl_relaxed(base + UTMIP_PLL_CFG1);
533600
val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) |
534601
UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
535-
val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
602+
val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->utmi_xtal_freq_count) |
536603
UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
537604
writel_relaxed(val, base + UTMIP_PLL_CFG1);
538605
}
@@ -803,6 +870,153 @@ static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
803870
return 0;
804871
}
805872

873+
static u32 tegra_hsic_readl(struct tegra_usb_phy *phy, u32 reg)
874+
{
875+
void __iomem *base = phy->regs;
876+
u32 shift = phy->soc_config->uhsic_registers_shift;
877+
878+
return readl_relaxed(base + shift + reg);
879+
}
880+
881+
static void tegra_hsic_writel(struct tegra_usb_phy *phy, u32 reg, u32 value)
882+
{
883+
void __iomem *base = phy->regs;
884+
u32 shift = phy->soc_config->uhsic_registers_shift;
885+
886+
writel_relaxed(value, base + shift + reg);
887+
}
888+
889+
static int uhsic_phy_power_on(struct tegra_usb_phy *phy)
890+
{
891+
struct tegra_utmip_config *config = phy->config;
892+
void __iomem *base = phy->regs;
893+
u32 val;
894+
895+
val = tegra_hsic_readl(phy, UHSIC_PADS_CFG1);
896+
val &= ~(UHSIC_PD_BG | UHSIC_PD_TX | UHSIC_PD_TRK | UHSIC_PD_RX |
897+
UHSIC_PD_ZI | UHSIC_RPD_DATA | UHSIC_RPD_STROBE);
898+
val |= UHSIC_RX_SEL;
899+
tegra_hsic_writel(phy, UHSIC_PADS_CFG1, val);
900+
901+
udelay(2);
902+
903+
val = readl_relaxed(base + USB_SUSP_CTRL);
904+
val |= UHSIC_RESET;
905+
writel_relaxed(val, base + USB_SUSP_CTRL);
906+
907+
udelay(30);
908+
909+
val = readl_relaxed(base + USB_SUSP_CTRL);
910+
val |= UHSIC_PHY_ENABLE;
911+
writel_relaxed(val, base + USB_SUSP_CTRL);
912+
913+
val = tegra_hsic_readl(phy, UHSIC_HSRX_CFG0);
914+
val &= ~(UHSIC_IDLE_WAIT(~0) |
915+
UHSIC_ELASTIC_UNDERRUN_LIMIT(~0) |
916+
UHSIC_ELASTIC_OVERRUN_LIMIT(~0));
917+
val |= UHSIC_IDLE_WAIT(config->idle_wait_delay) |
918+
UHSIC_ELASTIC_UNDERRUN_LIMIT(config->elastic_limit) |
919+
UHSIC_ELASTIC_OVERRUN_LIMIT(config->elastic_limit);
920+
tegra_hsic_writel(phy, UHSIC_HSRX_CFG0, val);
921+
922+
val = tegra_hsic_readl(phy, UHSIC_HSRX_CFG1);
923+
val &= ~UHSIC_HS_SYNC_START_DLY(~0);
924+
val |= UHSIC_HS_SYNC_START_DLY(config->hssync_start_delay);
925+
tegra_hsic_writel(phy, UHSIC_HSRX_CFG1, val);
926+
927+
val = tegra_hsic_readl(phy, UHSIC_MISC_CFG0);
928+
val |= UHSIC_SUSPEND_EXIT_ON_EDGE;
929+
tegra_hsic_writel(phy, UHSIC_MISC_CFG0, val);
930+
931+
val = tegra_hsic_readl(phy, UHSIC_MISC_CFG1);
932+
val &= ~UHSIC_PLLU_STABLE_COUNT(~0);
933+
val |= UHSIC_PLLU_STABLE_COUNT(phy->freq->stable_count);
934+
tegra_hsic_writel(phy, UHSIC_MISC_CFG1, val);
935+
936+
val = tegra_hsic_readl(phy, UHSIC_PLL_CFG1);
937+
val &= ~(UHSIC_XTAL_FREQ_COUNT(~0) |
938+
UHSIC_PLLU_ENABLE_DLY_COUNT(~0));
939+
val |= UHSIC_XTAL_FREQ_COUNT(phy->freq->hsic_xtal_freq_count) |
940+
UHSIC_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
941+
tegra_hsic_writel(phy, UHSIC_PLL_CFG1, val);
942+
943+
val = readl_relaxed(base + USB_SUSP_CTRL);
944+
val &= ~UHSIC_RESET;
945+
writel_relaxed(val, base + USB_SUSP_CTRL);
946+
947+
udelay(2);
948+
949+
if (phy->soc_config->requires_usbmode_setup) {
950+
val = readl_relaxed(base + USB_USBMODE);
951+
val &= ~USB_USBMODE_MASK;
952+
if (phy->mode == USB_DR_MODE_HOST)
953+
val |= USB_USBMODE_HOST;
954+
else
955+
val |= USB_USBMODE_DEVICE;
956+
writel_relaxed(val, base + USB_USBMODE);
957+
}
958+
959+
if (phy->soc_config->has_hostpc)
960+
set_pts(phy, TEGRA_USB_HOSTPC1_DEVLC_PTS_HSIC);
961+
else
962+
set_pts(phy, 0);
963+
964+
val = readl_relaxed(base + USB_TXFILLTUNING);
965+
if ((val & USB_FIFO_TXFILL_MASK) != USB_FIFO_TXFILL_THRES(0x10)) {
966+
val = USB_FIFO_TXFILL_THRES(0x10);
967+
writel_relaxed(val, base + USB_TXFILLTUNING);
968+
}
969+
970+
if (phy->soc_config->has_hostpc) {
971+
val = readl_relaxed(base + TEGRA30_USB_PORTSC1);
972+
val &= ~(TEGRA_USB_PORTSC1_WKOC | TEGRA_USB_PORTSC1_WKDS |
973+
TEGRA_USB_PORTSC1_WKCN);
974+
writel_relaxed(val, base + TEGRA30_USB_PORTSC1);
975+
} else {
976+
val = readl_relaxed(base + TEGRA_USB_PORTSC1);
977+
val &= ~(TEGRA_USB_PORTSC1_WKOC | TEGRA_USB_PORTSC1_WKDS |
978+
TEGRA_USB_PORTSC1_WKCN);
979+
writel_relaxed(val, base + TEGRA_USB_PORTSC1);
980+
}
981+
982+
val = tegra_hsic_readl(phy, UHSIC_PADS_CFG0);
983+
val &= ~UHSIC_TX_RTUNEN;
984+
val |= UHSIC_TX_RTUNE(phy->soc_config->uhsic_tx_rtune);
985+
tegra_hsic_writel(phy, UHSIC_PADS_CFG0, val);
986+
987+
if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
988+
USB_PHY_CLK_VALID))
989+
dev_err(phy->u_phy.dev,
990+
"Timeout waiting for PHY to stabilize on enable (HSIC)\n");
991+
992+
return 0;
993+
}
994+
995+
static int uhsic_phy_power_off(struct tegra_usb_phy *phy)
996+
{
997+
void __iomem *base = phy->regs;
998+
u32 val;
999+
1000+
set_phcd(phy, true);
1001+
1002+
val = tegra_hsic_readl(phy, UHSIC_PADS_CFG1);
1003+
val |= (UHSIC_PD_BG | UHSIC_PD_TX | UHSIC_PD_TRK | UHSIC_PD_RX |
1004+
UHSIC_PD_ZI | UHSIC_RPD_DATA | UHSIC_RPD_STROBE);
1005+
tegra_hsic_writel(phy, UHSIC_PADS_CFG1, val);
1006+
1007+
val = readl_relaxed(base + USB_SUSP_CTRL);
1008+
val |= UHSIC_RESET;
1009+
writel_relaxed(val, base + USB_SUSP_CTRL);
1010+
1011+
udelay(30);
1012+
1013+
val = readl_relaxed(base + USB_SUSP_CTRL);
1014+
val &= ~UHSIC_PHY_ENABLE;
1015+
writel_relaxed(val, base + USB_SUSP_CTRL);
1016+
1017+
return 0;
1018+
}
1019+
8061020
static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
8071021
{
8081022
int err = 0;
@@ -819,6 +1033,10 @@ static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
8191033
err = ulpi_phy_power_on(phy);
8201034
break;
8211035

1036+
case USBPHY_INTERFACE_MODE_HSIC:
1037+
err = uhsic_phy_power_on(phy);
1038+
break;
1039+
8221040
default:
8231041
break;
8241042
}
@@ -850,6 +1068,10 @@ static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
8501068
err = ulpi_phy_power_off(phy);
8511069
break;
8521070

1071+
case USBPHY_INTERFACE_MODE_HSIC:
1072+
err = uhsic_phy_power_off(phy);
1073+
break;
1074+
8531075
default:
8541076
break;
8551077
}
@@ -1247,6 +1469,8 @@ static const struct tegra_phy_soc_config tegra20_soc_config = {
12471469
.requires_usbmode_setup = false,
12481470
.requires_extra_tuning_parameters = false,
12491471
.requires_pmc_ao_power_up = false,
1472+
.uhsic_registers_shift = 0,
1473+
.uhsic_tx_rtune = 0, /* 40 ohm */
12501474
};
12511475

12521476
static const struct tegra_phy_soc_config tegra30_soc_config = {
@@ -1255,6 +1479,8 @@ static const struct tegra_phy_soc_config tegra30_soc_config = {
12551479
.requires_usbmode_setup = true,
12561480
.requires_extra_tuning_parameters = true,
12571481
.requires_pmc_ao_power_up = true,
1482+
.uhsic_registers_shift = 0x400,
1483+
.uhsic_tx_rtune = 8, /* 50 ohm */
12581484
};
12591485

12601486
static const struct of_device_id tegra_usb_phy_id_table[] = {
@@ -1332,6 +1558,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
13321558
tegra_phy->phy_type = of_usb_get_phy_mode(np);
13331559
switch (tegra_phy->phy_type) {
13341560
case USBPHY_INTERFACE_MODE_UTMI:
1561+
case USBPHY_INTERFACE_MODE_HSIC:
13351562
err = utmi_phy_probe(tegra_phy, pdev);
13361563
if (err)
13371564
return err;

include/linux/usb/tegra_usb_phy.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ struct gpio_desc;
2323
* requires_extra_tuning_parameters: true if xcvr_hsslew, hssquelch_level
2424
* and hsdiscon_level should be set for adequate signal quality
2525
* requires_pmc_ao_power_up: true if USB AO is powered down by default
26+
* uhsic_registers_shift: for Tegra30+ where HSIC registers were shifted
27+
* comparing to Tegra20 by 0x400, since Tegra20 has no UTMIP on PHY2
28+
* uhsic_tx_rtune: fine tuned 50 Ohm termination resistor for NMOS/PMOS driver
2629
*/
2730

2831
struct tegra_phy_soc_config {
@@ -31,6 +34,8 @@ struct tegra_phy_soc_config {
3134
bool requires_usbmode_setup;
3235
bool requires_extra_tuning_parameters;
3336
bool requires_pmc_ao_power_up;
37+
u32 uhsic_registers_shift;
38+
u32 uhsic_tx_rtune;
3439
};
3540

3641
struct tegra_utmip_config {

0 commit comments

Comments
 (0)