1 // SPDX-License-Identifier: GPL-2.0 2 /** 3 * cdns_ti-ti.c - TI specific Glue layer for Cadence USB Controller 4 * 5 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com 6 */ 7 8 #include <common.h> 9 #include <asm-generic/io.h> 10 #include <clk.h> 11 #include <dm.h> 12 #include <linux/io.h> 13 #include <linux/usb/otg.h> 14 #include <malloc.h> 15 16 #include "core.h" 17 18 /* USB Wrapper register offsets */ 19 #define USBSS_PID 0x0 20 #define USBSS_W1 0x4 21 #define USBSS_STATIC_CONFIG 0x8 22 #define USBSS_PHY_TEST 0xc 23 #define USBSS_DEBUG_CTRL 0x10 24 #define USBSS_DEBUG_INFO 0x14 25 #define USBSS_DEBUG_LINK_STATE 0x18 26 #define USBSS_DEVICE_CTRL 0x1c 27 28 /* Wrapper 1 register bits */ 29 #define USBSS_W1_PWRUP_RST BIT(0) 30 #define USBSS_W1_OVERCURRENT_SEL BIT(8) 31 #define USBSS_W1_MODESTRAP_SEL BIT(9) 32 #define USBSS_W1_OVERCURRENT BIT(16) 33 #define USBSS_W1_MODESTRAP_MASK GENMASK(18, 17) 34 #define USBSS_W1_MODESTRAP_SHIFT 17 35 #define USBSS_W1_USB2_ONLY BIT(19) 36 37 /* Static config register bits */ 38 #define USBSS1_STATIC_PLL_REF_SEL_MASK GENMASK(8, 5) 39 #define USBSS1_STATIC_PLL_REF_SEL_SHIFT 5 40 #define USBSS1_STATIC_LOOPBACK_MODE_MASK GENMASK(4, 3) 41 #define USBSS1_STATIC_LOOPBACK_MODE_SHIFT 3 42 #define USBSS1_STATIC_VBUS_SEL_MASK GENMASK(2, 1) 43 #define USBSS1_STATIC_VBUS_SEL_SHIFT 1 44 #define USBSS1_STATIC_LANE_REVERSE BIT(0) 45 46 /* Modestrap modes */ 47 enum modestrap_mode { USBSS_MODESTRAP_MODE_NONE, 48 USBSS_MODESTRAP_MODE_HOST, 49 USBSS_MODESTRAP_MODE_PERIPHERAL}; 50 51 struct cdns_ti { 52 struct udevice *dev; 53 void __iomem *usbss; 54 int usb2_only:1; 55 int vbus_divider:1; 56 struct clk *usb2_refclk; 57 struct clk *lpm_clk; 58 }; 59 60 static const int cdns_ti_rate_table[] = { /* in KHZ */ 61 9600, 62 10000, 63 12000, 64 19200, 65 20000, 66 24000, 67 25000, 68 26000, 69 38400, 70 40000, 71 58000, 72 50000, 73 52000, 74 }; 75 76 static inline u32 cdns_ti_readl(struct cdns_ti *data, u32 offset) 77 { 78 return readl(data->usbss + offset); 79 } 80 81 static inline void cdns_ti_writel(struct cdns_ti *data, u32 offset, u32 value) 82 { 83 writel(value, data->usbss + offset); 84 } 85 86 static int cdns_ti_probe(struct udevice *dev) 87 { 88 struct cdns_ti *data = dev_get_platdata(dev); 89 struct clk usb2_refclk; 90 int modestrap_mode; 91 unsigned long rate; 92 int rate_code, i; 93 u32 reg; 94 int ret; 95 96 data->dev = dev; 97 98 data->usbss = dev_remap_addr_index(dev, 0); 99 if (!data->usbss) 100 return -EINVAL; 101 102 ret = clk_get_by_name(dev, "usb2_refclk", &usb2_refclk); 103 if (ret) { 104 dev_err(dev, "Failed to get usb2_refclk\n"); 105 return ret; 106 } 107 108 rate = clk_get_rate(&usb2_refclk); 109 rate /= 1000; /* To KHz */ 110 for (i = 0; i < ARRAY_SIZE(cdns_ti_rate_table); i++) { 111 if (cdns_ti_rate_table[i] == rate) 112 break; 113 } 114 115 if (i == ARRAY_SIZE(cdns_ti_rate_table)) { 116 dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate); 117 return -EINVAL; 118 } 119 120 rate_code = i; 121 122 /* assert RESET */ 123 reg = cdns_ti_readl(data, USBSS_W1); 124 reg &= ~USBSS_W1_PWRUP_RST; 125 cdns_ti_writel(data, USBSS_W1, reg); 126 127 /* set static config */ 128 reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); 129 reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK; 130 reg |= rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT; 131 132 reg &= ~USBSS1_STATIC_VBUS_SEL_MASK; 133 data->vbus_divider = dev_read_bool(dev, "ti,vbus-divider"); 134 if (data->vbus_divider) 135 reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT; 136 137 cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg); 138 reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG); 139 140 /* set USB2_ONLY mode if requested */ 141 reg = cdns_ti_readl(data, USBSS_W1); 142 data->usb2_only = dev_read_bool(dev, "ti,usb2-only"); 143 if (data->usb2_only) 144 reg |= USBSS_W1_USB2_ONLY; 145 146 /* set modestrap */ 147 if (dev_read_bool(dev, "ti,modestrap-host")) 148 modestrap_mode = USBSS_MODESTRAP_MODE_HOST; 149 else if (dev_read_bool(dev, "ti,modestrap-peripheral")) 150 modestrap_mode = USBSS_MODESTRAP_MODE_PERIPHERAL; 151 else 152 modestrap_mode = USBSS_MODESTRAP_MODE_NONE; 153 154 reg |= USBSS_W1_MODESTRAP_SEL; 155 reg &= ~USBSS_W1_MODESTRAP_MASK; 156 reg |= modestrap_mode << USBSS_W1_MODESTRAP_SHIFT; 157 cdns_ti_writel(data, USBSS_W1, reg); 158 159 /* de-assert RESET */ 160 reg |= USBSS_W1_PWRUP_RST; 161 cdns_ti_writel(data, USBSS_W1, reg); 162 163 return 0; 164 } 165 166 static int cdns_ti_remove(struct udevice *dev) 167 { 168 struct cdns_ti *data = dev_get_platdata(dev); 169 u32 reg; 170 171 /* put device back to RESET*/ 172 reg = cdns_ti_readl(data, USBSS_W1); 173 reg &= ~USBSS_W1_PWRUP_RST; 174 cdns_ti_writel(data, USBSS_W1, reg); 175 176 return 0; 177 } 178 179 static const struct udevice_id cdns_ti_of_match[] = { 180 { .compatible = "ti,j721e-usb", }, 181 {}, 182 }; 183 184 U_BOOT_DRIVER(cdns_ti) = { 185 .name = "cdns-ti", 186 .id = UCLASS_NOP, 187 .of_match = cdns_ti_of_match, 188 .bind = cdns3_bind, 189 .probe = cdns_ti_probe, 190 .remove = cdns_ti_remove, 191 .platdata_auto_alloc_size = sizeof(struct cdns_ti), 192 .flags = DM_FLAG_OS_PREPARE, 193 }; 194