Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/sunxi Add PHY init for OTG ports in host mode.
details: https://anonhg.NetBSD.org/src/rev/1f0511d066ab
branches: trunk
changeset: 356203:1f0511d066ab
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sat Sep 09 11:58:34 2017 +0000
description:
Add PHY init for OTG ports in host mode.
diffstat:
sys/arch/arm/sunxi/sunxi_usbphy.c | 170 +++++++++++++++++++++++++++++++++----
1 files changed, 148 insertions(+), 22 deletions(-)
diffs (226 lines):
diff -r 46bd2ed03371 -r 1f0511d066ab sys/arch/arm/sunxi/sunxi_usbphy.c
--- a/sys/arch/arm/sunxi/sunxi_usbphy.c Fri Sep 08 21:45:08 2017 +0000
+++ b/sys/arch/arm/sunxi/sunxi_usbphy.c Sat Sep 09 11:58:34 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_usbphy.c,v 1.7 2017/09/07 10:30:46 jmcneill Exp $ */
+/* $NetBSD: sunxi_usbphy.c,v 1.8 2017/09/09 11:58:34 jmcneill Exp $ */
/*-
* Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_usbphy.c,v 1.7 2017/09/07 10:30:46 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_usbphy.c,v 1.8 2017/09/09 11:58:34 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -39,14 +39,34 @@
#include <dev/fdt/fdtvar.h>
-#define OTG_PHY_CFG 0x20
-#define OTG_PHY_ROUTE_OTG __BIT(0)
+/* PHY control registers */
+#define PHYCTL_ICR 0x00
+#define PHYCTL_ICR_ID_PULLUP __BIT(17)
+#define PHYCTL_ICR_DPDM_PULLUP __BIT(16)
+#define PHYCTL_ICR_FORCE_ID __BITS(15,14)
+#define PHYCTL_ICR_FORCE_ID_LOW 2
+#define PHYCTL_ICR_FORCE_ID_HIGH 3
+#define PHYCTL_ICR_FORCE_VBUS __BITS(13,12)
+#define PHYCTL_ICR_FORCE_VBUS_LOW 2
+#define PHYCTL_ICR_FORCE_VBUS_HIGH 3
+#define PHYCTL_A10 0x04
+#define PHYCTL_A33 0x10
+#define PHYCTL_ADDR __BITS(15,8)
+#define PHYCTL_DATA __BIT(7)
+#define PHYCTL_OTG_CFG 0x20
+#define PHYCTL_OTG_ROUTE_OTG __BIT(0)
-#define HCI_ICR 0x00
-#define HCI_AHB_INCR8 __BIT(10)
-#define HCI_AHB_INCR4 __BIT(9)
-#define HCI_AHB_INCRX_ALIGN __BIT(8)
-#define HCI_ULPI_BYPASS __BIT(0)
+/* PHY registers */
+#define PHY_RES45_CAL_EN 0x0c
+#define PHY_TX_AMPLITUDE_TUNE 0x20
+#define PHY_DISCON_TH_SEL 0x2a
+
+/* PMU registers */
+#define PMU_CFG 0x00
+#define AHB_INCR8 __BIT(10)
+#define AHB_INCR4 __BIT(9)
+#define AHB_INCRX_ALIGN __BIT(8)
+#define ULPI_BYPASS __BIT(0)
#define PMU_UNK_H3 0x10
#define PMU_UNK_H3_CLR __BIT(1)
@@ -89,16 +109,68 @@
struct fdtbus_gpio_pin *sc_gpio_vbus_det;
};
-#define USBPHY_READ(sc, id, reg) \
+#define PHYCTL_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, \
+ (sc)->sc_bsh_phy_ctrl, (reg))
+#define PHYCTL_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, \
+ (sc)->sc_bsh_phy_ctrl, (reg), (val))
+#define PMU_READ(sc, id, reg) \
bus_space_read_4((sc)->sc_bst, \
(sc)->sc_phys[(id)].phy_bsh, (reg))
-#define USBPHY_WRITE(sc, id, reg, val) \
+#define PMU_WRITE(sc, id, reg, val) \
bus_space_write_4((sc)->sc_bst, \
(sc)->sc_phys[(id)].phy_bsh, (reg), (val))
CFATTACH_DECL_NEW(sunxi_usbphy, sizeof(struct sunxi_usbphy_softc),
sunxi_usbphy_match, sunxi_usbphy_attach, NULL, NULL);
+static void
+sunxi_usbphy_write(struct sunxi_usbphy_softc *sc,
+ struct sunxi_usbphy *phy, u_int bit_addr, u_int bits,
+ u_int len)
+{
+ const uint32_t usbc_mask = __BIT(phy->phy_index * 2);;
+ bus_size_t reg;
+ uint32_t val;
+
+ switch (sc->sc_type) {
+ case USBPHY_A13:
+ case USBPHY_A31:
+ reg = PHYCTL_A10;
+ break;
+ case USBPHY_H3:
+ case USBPHY_A64:
+ reg = PHYCTL_A33;
+ break;
+ default:
+ panic("unsupported phy type");
+ }
+
+ if (reg == PHYCTL_A33)
+ PHYCTL_WRITE(sc, reg, 0);
+
+ for (; len > 0; bit_addr++, bits >>= 1, len--) {
+ val = PHYCTL_READ(sc, reg);
+ val &= ~PHYCTL_ADDR;
+ val |= __SHIFTIN(bit_addr, PHYCTL_ADDR);
+ PHYCTL_WRITE(sc, reg, val);
+
+ val = PHYCTL_READ(sc, reg);
+ val &= ~PHYCTL_DATA;
+ val |= __SHIFTIN(bits & 1, PHYCTL_DATA);
+ PHYCTL_WRITE(sc, reg, val);
+
+ PHYCTL_READ(sc, reg);
+ val |= usbc_mask;
+ PHYCTL_WRITE(sc, reg, val);
+
+ PHYCTL_READ(sc, reg);
+ val &= ~usbc_mask;
+ PHYCTL_WRITE(sc, reg, val);
+ }
+}
+
static bool
sunxi_usbphy_vbus_detect(struct sunxi_usbphy_softc *sc)
{
@@ -132,29 +204,83 @@
{
struct sunxi_usbphy_softc * const sc = device_private(dev);
struct sunxi_usbphy * const phy = priv;
+ u_int disc_thresh;
+ bool phy0_reroute;
uint32_t val;
- if (phy->phy_index > 0) {
- /* Enable passby */
- val = USBPHY_READ(sc, phy->phy_index, HCI_ICR);
- val |= HCI_ULPI_BYPASS;
- val |= HCI_AHB_INCR8;
- val |= HCI_AHB_INCR4;
- val |= HCI_AHB_INCRX_ALIGN;
- USBPHY_WRITE(sc, phy->phy_index, HCI_ICR, val);
+ switch (sc->sc_type) {
+ case USBPHY_A13:
+ disc_thresh = 0x2;
+ phy0_reroute = false;
+ break;
+ case USBPHY_A31:
+ disc_thresh = 0x3;
+ phy0_reroute = false;
+ break;
+ case USBPHY_A64:
+ case USBPHY_H3:
+ disc_thresh = 0x3;
+ phy0_reroute = true;
+ break;
+ }
+
+ if (phy->phy_bsh) {
+ /* Enable/disable passby */
+ const uint32_t mask =
+ ULPI_BYPASS|AHB_INCR8|AHB_INCR4|AHB_INCRX_ALIGN;
+ val = PMU_READ(sc, phy->phy_index, PMU_CFG);
+ if (enable)
+ val |= mask;
+ else
+ val &= ~mask;
+ PMU_WRITE(sc, phy->phy_index, PMU_CFG, val);
}
switch (sc->sc_type) {
case USBPHY_H3:
case USBPHY_A64:
- val = USBPHY_READ(sc, phy->phy_index, PMU_UNK_H3);
- val &= ~PMU_UNK_H3_CLR;
- USBPHY_WRITE(sc, phy->phy_index, PMU_UNK_H3, val);
+ if (enable && phy->phy_bsh) {
+ val = PMU_READ(sc, phy->phy_index, PMU_UNK_H3);
+ val &= ~PMU_UNK_H3_CLR;
+ PMU_WRITE(sc, phy->phy_index, PMU_UNK_H3, val);
+ }
break;
default:
break;
}
+ if (enable) {
+ if (phy->phy_index == 0)
+ sunxi_usbphy_write(sc, phy, PHY_RES45_CAL_EN, 0x1, 1);
+ sunxi_usbphy_write(sc, phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
+ sunxi_usbphy_write(sc, phy, PHY_DISCON_TH_SEL, disc_thresh, 2);
+ }
+
+ if (phy->phy_index == 0) {
+ const uint32_t mask =
+ PHYCTL_ICR_ID_PULLUP|PHYCTL_ICR_DPDM_PULLUP;
+ val = PHYCTL_READ(sc, PHYCTL_ICR);
+
+ if (enable)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ /* XXX only host mode is supported */
+ val &= ~PHYCTL_ICR_FORCE_ID;
+ val |= __SHIFTIN(PHYCTL_ICR_FORCE_ID_LOW, PHYCTL_ICR_FORCE_ID);
+ val &= ~PHYCTL_ICR_FORCE_VBUS;
+ val |= __SHIFTIN(PHYCTL_ICR_FORCE_VBUS_HIGH, PHYCTL_ICR_FORCE_VBUS);
+
+ PHYCTL_WRITE(sc, PHYCTL_ICR, val);
+
+ if (phy0_reroute) {
+ val = PHYCTL_READ(sc, PHYCTL_OTG_CFG);
+ val &= ~PHYCTL_OTG_ROUTE_OTG;
+ PHYCTL_WRITE(sc, PHYCTL_OTG_CFG, val);
+ }
+ }
+
if (phy->phy_reg == NULL)
return 0;
Home |
Main Index |
Thread Index |
Old Index