Changes in uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c [2be2506a:57912af3] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c
r2be2506a r57912af3 37 37 #define _DDF_DATA_IMPLANT 38 38 39 #define DEBUG_CM 40 39 41 #include <ddf/driver.h> 40 42 #include <ddf/log.h> … … 46 48 #include "uhh.h" 47 49 #include "usbtll.h" 48 #include "core_cm.h" 49 #include "usbhost_cm.h" 50 #include "cm/core.h" 51 #include "cm/clock_control.h" 52 #include "cm/usbhost.h" 50 53 51 54 #define NAME "rootamdm37x" 55 56 typedef struct { 57 uhh_regs_t *uhh; 58 tll_regs_t *tll; 59 struct { 60 core_cm_regs_t *core; 61 clock_control_cm_regs_t *clocks; 62 usbhost_cm_regs_t *usbhost; 63 } cm; 64 } amdm37x_t; 65 66 #ifdef DEBUG_CM 67 static void log(volatile void *place, uint32_t val, volatile void* base, size_t size, void *data, bool write) 68 { 69 printf("PIO %s: %p(%p) %#"PRIx32"\n", write ? "WRITE" : "READ", 70 (place - base) + data, place, val); 71 } 72 #endif 73 74 static int amdm37x_hw_access_init(amdm37x_t *device) 75 { 76 assert(device); 77 int ret = EOK; 78 79 ret = pio_enable((void*)USBHOST_CM_BASE_ADDRESS, USBHOST_CM_SIZE, 80 (void**)&device->cm.usbhost); 81 if (ret != EOK) 82 return ret; 83 84 ret = pio_enable((void*)CORE_CM_BASE_ADDRESS, CORE_CM_SIZE, 85 (void**)&device->cm.core); 86 if (ret != EOK) 87 return ret; 88 89 ret = pio_enable((void*)CLOCK_CONTROL_CM_BASE_ADDRESS, 90 CLOCK_CONTROL_CM_SIZE, (void**)&device->cm.clocks); 91 if (ret != EOK) 92 return ret; 93 94 ret = pio_enable((void*)AMDM37x_USBTLL_BASE_ADDRESS, 95 AMDM37x_USBTLL_SIZE, (void**)&device->tll); 96 if (ret != EOK) 97 return ret; 98 99 ret = pio_enable((void*)AMDM37x_UHH_BASE_ADDRESS, 100 AMDM37x_UHH_SIZE, (void**)&device->uhh); 101 if (ret != EOK) 102 return ret; 103 104 #ifdef DEBUG_CM 105 pio_trace_enable(device->tll, AMDM37x_USBTLL_SIZE, log, (void*)AMDM37x_USBTLL_BASE_ADDRESS); 106 pio_trace_enable(device->cm.clocks, CLOCK_CONTROL_CM_SIZE, log, (void*)CLOCK_CONTROL_CM_BASE_ADDRESS); 107 pio_trace_enable(device->cm.core, CORE_CM_SIZE, log, (void*)CORE_CM_BASE_ADDRESS); 108 pio_trace_enable(device->cm.usbhost, USBHOST_CM_SIZE, log, (void*)USBHOST_CM_BASE_ADDRESS); 109 pio_trace_enable(device->uhh, AMDM37x_UHH_SIZE, log, (void*)AMDM37x_UHH_BASE_ADDRESS); 110 #endif 111 return EOK; 112 } 113 114 static int usb_clocks(amdm37x_t *device, bool on) 115 { 116 /* Set DPLL3 to automatic */ 117 pio_change_32(&device->cm.clocks->autoidle_pll, 118 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_AUTOMATIC, 119 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_MASK, 5); 120 121 /* Set DPLL4 to automatic */ 122 pio_change_32(&device->cm.clocks->autoidle_pll, 123 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_AUTOMATIC, 124 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_MASK, 5); 125 126 /* Set DPLL5 to automatic */ 127 pio_change_32(&device->cm.clocks->autoidle2_pll, 128 CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_AUTOMATIC, 129 CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_MASK, 5); 130 131 132 #ifdef DEBUG_CM 133 printf("DPLL5 could be on: %"PRIx32" %"PRIx32".\n", 134 pio_read_32((ioport32_t*)&device->cm.clocks->idlest_ckgen), 135 pio_read_32((ioport32_t*)&device->cm.clocks->idlest2_ckgen)); 136 #endif 137 138 if (on) { 139 /* Enable interface and function clock for USB TLL */ 140 pio_set_32(&device->cm.core->fclken3, 141 CORE_CM_FCLKEN3_EN_USBTLL_FLAG, 5); 142 pio_set_32(&device->cm.core->iclken3, 143 CORE_CM_ICLKEN3_EN_USBTLL_FLAG, 5); 144 145 /* Enable interface and function clock for USB hosts */ 146 pio_set_32(&device->cm.usbhost->fclken, 147 USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG | 148 USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG, 5); 149 pio_set_32(&device->cm.usbhost->iclken, 150 USBHOST_CM_ICLKEN_EN_USBHOST, 5); 151 #ifdef DEBUG_CM 152 printf("DPLL5 (and everything else) should be on: %"PRIx32" %"PRIx32".\n", 153 pio_read_32((ioport32_t*)&device->cm.clocks->idlest_ckgen), 154 pio_read_32((ioport32_t*)&device->cm.clocks->idlest2_ckgen)); 155 #endif 156 } else { 157 /* Disable interface and function clock for USB hosts */ 158 pio_clear_32(&device->cm.usbhost->iclken, 159 USBHOST_CM_ICLKEN_EN_USBHOST, 5); 160 pio_clear_32(&device->cm.usbhost->fclken, 161 USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG | 162 USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG, 5); 163 164 /* Disable interface and function clock for USB TLL */ 165 pio_clear_32(&device->cm.core->iclken3, 166 CORE_CM_ICLKEN3_EN_USBTLL_FLAG, 5); 167 pio_clear_32(&device->cm.core->fclken3, 168 CORE_CM_FCLKEN3_EN_USBTLL_FLAG, 5); 169 } 170 171 return EOK; 172 } 173 174 /** Initialize USB TLL port connections. 175 * 176 * Different modes are on page 3312 of the Manual Figure 22-34. 177 * Select mode than can operate in FS/LS. 178 */ 179 static int usb_tll_init(amdm37x_t *device) 180 { 181 182 /* Reset USB TLL */ 183 pio_set_32(&device->tll->sysconfig, TLL_SYSCONFIG_SOFTRESET_FLAG, 5); 184 ddf_msg(LVL_DEBUG2, "Waiting for USB TLL reset"); 185 while (!(pio_read_32(&device->tll->sysstatus) & TLL_SYSSTATUS_RESET_DONE_FLAG)); 186 ddf_msg(LVL_DEBUG, "USB TLL Reset done."); 187 188 /* Setup idle mode (smart idle) */ 189 pio_change_32(&device->tll->sysconfig, 190 TLL_SYSCONFIG_CLOCKACTIVITY_FLAG | TLL_SYSCONFIG_AUTOIDLE_FLAG | 191 TLL_SYSCONFIG_SIDLE_MODE_SMART, TLL_SYSCONFIG_SIDLE_MODE_MASK, 5); 192 193 /* Smart idle for UHH */ 194 pio_change_32(&device->uhh->sysconfig, 195 UHH_SYSCONFIG_CLOCKACTIVITY_FLAG | UHH_SYSCONFIG_AUTOIDLE_FLAG | 196 UHH_SYSCONFIG_SIDLE_MODE_SMART, UHH_SYSCONFIG_SIDLE_MODE_MASK, 5); 197 198 /* Set all ports to go through TLL(UTMI) 199 * Direct connection can only work in HS mode */ 200 pio_set_32(&device->uhh->hostconfig, 201 UHH_HOSTCONFIG_P1_ULPI_BYPASS_FLAG | 202 UHH_HOSTCONFIG_P2_ULPI_BYPASS_FLAG | 203 UHH_HOSTCONFIG_P3_ULPI_BYPASS_FLAG, 5); 204 205 /* What is this? */ 206 pio_set_32(&device->tll->shared_conf, TLL_SHARED_CONF_FCLK_IS_ON_FLAG, 5); 207 208 for (unsigned i = 0; i < 3; ++i) { 209 /* Serial mode is the only one capable of FS/LS operation. 210 * Select FS/LS mode, no idea what the difference is 211 * one of bidirectional modes might be good choice 212 * 2 = 3pin bidi phy. */ 213 pio_change_32(&device->tll->channel_conf[i], 214 TLL_CHANNEL_CONF_CHANMODE_UTMI_SERIAL_MODE | 215 TLL_CHANNEL_CONF_FSLSMODE_3PIN_BIDI_PHY, 216 TLL_CHANNEL_CONF_CHANMODE_MASK | 217 TLL_CHANNEL_CONF_FSLSMODE_MASK, 5); 218 } 219 return EOK; 220 } 52 221 53 222 typedef struct { … … 102 271 .hw_resources = { 103 272 .resources = ehci_res, 104 .count = sizeof(ehci_res) /sizeof(ehci_res[0]),273 .count = sizeof(ehci_res) / sizeof(ehci_res[0]), 105 274 } 106 275 }; … … 118 287 .interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops 119 288 }; 120 121 static int usb_clocks(bool on)122 {123 usbhost_cm_regs_t *usb_host_cm = NULL;124 core_cm_regs_t *l4_core_cm = NULL;125 126 int ret = pio_enable((void*)USBHOST_CM_BASE_ADDRESS, USBHOST_CM_SIZE,127 (void**)&usb_host_cm);128 if (ret != EOK)129 return ret;130 131 ret = pio_enable((void*)CORE_CM_BASE_ADDRESS, CORE_CM_SIZE,132 (void**)&l4_core_cm);133 if (ret != EOK)134 return ret;135 136 assert(l4_core_cm);137 assert(usb_host_cm);138 if (on) {139 l4_core_cm->iclken3 |= CORE_CM_ICLKEN3_EN_USBTLL_FLAG;140 l4_core_cm->fclken3 |= CORE_CM_FCLKEN3_EN_USBTLL_FLAG;141 usb_host_cm->iclken |= USBHOST_CM_ICLKEN_EN_USBHOST;142 usb_host_cm->fclken |= USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG;143 usb_host_cm->fclken |= USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG;144 } else {145 usb_host_cm->fclken &= ~USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG;146 usb_host_cm->fclken &= ~USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG;147 usb_host_cm->iclken &= ~USBHOST_CM_ICLKEN_EN_USBHOST;148 l4_core_cm->fclken3 &= ~CORE_CM_FCLKEN3_EN_USBTLL_FLAG;149 l4_core_cm->iclken3 &= ~CORE_CM_ICLKEN3_EN_USBTLL_FLAG;150 }151 152 //TODO Unmap those registers.153 154 return ret;155 }156 157 /** Initialize USB TLL port connections.158 *159 * Different modes are on page 3312 of the Manual Figure 22-34.160 * Select mode than can operate in FS/LS.161 */162 static int usb_tll_init()163 {164 tll_regs_t *usb_tll = NULL;165 uhh_regs_t *uhh_conf = NULL;166 167 int ret = pio_enable((void*)AMDM37x_USBTLL_BASE_ADDRESS,168 AMDM37x_USBTLL_SIZE, (void**)&usb_tll);169 if (ret != EOK)170 return ret;171 172 ret = pio_enable((void*)AMDM37x_UHH_BASE_ADDRESS,173 AMDM37x_UHH_SIZE, (void**)&uhh_conf);174 if (ret != EOK)175 return ret;176 177 /* Reset USB TLL */178 usb_tll->sysconfig |= TLL_SYSCONFIG_SOFTRESET_FLAG;179 ddf_msg(LVL_DEBUG2, "Waiting for USB TLL reset");180 while (!(usb_tll->sysstatus & TLL_SYSSTATUS_RESET_DONE_FLAG));181 ddf_msg(LVL_DEBUG, "USB TLL Reset done.");182 183 {184 /* Setup idle mode (smart idle) */185 uint32_t sysc = usb_tll->sysconfig;186 sysc |= TLL_SYSCONFIG_CLOCKACTIVITY_FLAG | TLL_SYSCONFIG_AUTOIDLE_FLAG;187 sysc = (sysc188 & ~(TLL_SYSCONFIG_SIDLE_MODE_MASK << TLL_SYSCONFIG_SIDLE_MODE_SHIFT)189 ) | (0x2 << TLL_SYSCONFIG_SIDLE_MODE_SHIFT);190 usb_tll->sysconfig = sysc;191 ddf_msg(LVL_DEBUG2, "Set TLL->sysconfig (%p) to %x:%x.",192 &usb_tll->sysconfig, usb_tll->sysconfig, sysc);193 }194 195 {196 /* Smart idle for UHH */197 uint32_t sysc = uhh_conf->sysconfig;198 sysc |= UHH_SYSCONFIG_CLOCKACTIVITY_FLAG | UHH_SYSCONFIG_AUTOIDLE_FLAG;199 sysc = (sysc200 & ~(UHH_SYSCONFIG_SIDLE_MODE_MASK << UHH_SYSCONFIG_SIDLE_MODE_SHIFT)201 ) | (0x2 << UHH_SYSCONFIG_SIDLE_MODE_SHIFT);202 sysc = (sysc203 & ~(UHH_SYSCONFIG_MIDLE_MODE_MASK << UHH_SYSCONFIG_MIDLE_MODE_SHIFT)204 ) | (0x2 << UHH_SYSCONFIG_MIDLE_MODE_SHIFT);205 ddf_msg(LVL_DEBUG2, "Set UHH->sysconfig (%p) to %x.",206 &uhh_conf->sysconfig, uhh_conf->sysconfig);207 uhh_conf->sysconfig = sysc;208 209 /* All ports are connected on BBxM */210 uhh_conf->hostconfig |= (UHH_HOSTCONFIG_P1_CONNECT_STATUS_FLAG211 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_FLAG212 | UHH_HOSTCONFIG_P3_CONNECT_STATUS_FLAG);213 214 /* Set all ports to go through TLL(UTMI)215 * Direct connection can only work in HS mode */216 uhh_conf->hostconfig |= (UHH_HOSTCONFIG_P1_ULPI_BYPASS_FLAG217 | UHH_HOSTCONFIG_P2_ULPI_BYPASS_FLAG218 | UHH_HOSTCONFIG_P3_ULPI_BYPASS_FLAG);219 ddf_msg(LVL_DEBUG2, "Set UHH->hostconfig (%p) to %x.",220 &uhh_conf->hostconfig, uhh_conf->hostconfig);221 }222 223 usb_tll->shared_conf |= TLL_SHARED_CONF_FCLK_IS_ON_FLAG;224 ddf_msg(LVL_DEBUG2, "Set shared conf port (%p) to %x.",225 &usb_tll->shared_conf, usb_tll->shared_conf);226 227 for (unsigned i = 0; i < 3; ++i) {228 uint32_t ch = usb_tll->channel_conf[i];229 /* Clear Channel mode and FSLS mode */230 ch &= ~(TLL_CHANNEL_CONF_CHANMODE_MASK231 << TLL_CHANNEL_CONF_CHANMODE_SHIFT)232 & ~(TLL_CHANNEL_CONF_FSLSMODE_MASK233 << TLL_CHANNEL_CONF_FSLSMODE_SHIFT);234 235 /* Serial mode is the only one capable of FS/LS operation. */236 ch |= (TLL_CHANNEL_CONF_CHANMODE_UTMI_SERIAL_MODE237 << TLL_CHANNEL_CONF_CHANMODE_SHIFT);238 239 /* Select FS/LS mode, no idea what the difference is240 * one of bidirectional modes might be good choice241 * 2 = 3pin bidi phy. */242 ch |= (2 << TLL_CHANNEL_CONF_FSLSMODE_SHIFT);243 244 /* Write to register */245 ddf_msg(LVL_DEBUG2, "Setting port %u(%p) to %x.",246 i, &usb_tll->channel_conf[i], ch);247 usb_tll->channel_conf[i] = ch;248 }249 return EOK;250 }251 289 252 290 static bool rootamdm37x_add_fun(ddf_dev_t *dev, const char *name, … … 263 301 /* Add match id */ 264 302 if (ddf_fun_add_match_id(fnode, str_match_id, 100) != EOK) { 303 ddf_fun_destroy(fnode); 304 return false; 305 } 306 307 /* Set provided operations to the device. */ 308 ddf_fun_data_implant(fnode, (void*)fun); 309 ddf_fun_set_ops(fnode, &rootamdm37x_fun_ops); 310 311 /* Register function. */ 312 if (ddf_fun_bind(fnode) != EOK) { 313 ddf_msg(LVL_ERROR, "Failed binding function %s.", name); 265 314 // TODO This will try to free our data! 266 315 ddf_fun_destroy(fnode); … … 268 317 } 269 318 270 /* Set provided operations to the device. */271 ddf_fun_data_implant(fnode, (void*)fun);272 ddf_fun_set_ops(fnode, &rootamdm37x_fun_ops);273 274 /* Register function. */275 if (ddf_fun_bind(fnode) != EOK) {276 ddf_msg(LVL_ERROR, "Failed binding function %s.", name);277 ddf_fun_destroy(fnode);278 return false;279 }280 281 319 return true; 282 320 } … … 292 330 static int rootamdm37x_dev_add(ddf_dev_t *dev) 293 331 { 294 int ret = usb_clocks(true); 332 assert(dev); 333 amdm37x_t *device = ddf_dev_data_alloc(dev, sizeof(amdm37x_t)); 334 if (!device) 335 return ENOMEM; 336 int ret = amdm37x_hw_access_init(device); 337 if (ret != EOK) { 338 ddf_msg(LVL_FATAL, "Failed to setup hw access!.\n"); 339 return ret; 340 } 341 342 ret = usb_clocks(device, true); 295 343 if (ret != EOK) { 296 344 ddf_msg(LVL_FATAL, "Failed to enable USB HC clocks!.\n"); … … 298 346 } 299 347 300 ret = usb_tll_init( );348 ret = usb_tll_init(device); 301 349 if (ret != EOK) { 302 350 ddf_msg(LVL_FATAL, "Failed to init USB TLL!.\n"); 303 usb_clocks( false);351 usb_clocks(device, false); 304 352 return ret; 305 353 } … … 343 391 { 344 392 printf("%s: HelenOS AM/DM37x(OMAP37x) platform driver\n", NAME); 345 ddf_log_init(NAME , LVL_ERROR);393 ddf_log_init(NAME); 346 394 return ddf_driver_main(&rootamdm37x_driver); 347 395 }
Note:
See TracChangeset
for help on using the changeset viewer.