Changes in uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c [57912af3:2be2506a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c
r57912af3 r2be2506a 37 37 #define _DDF_DATA_IMPLANT 38 38 39 #define DEBUG_CM40 41 39 #include <ddf/driver.h> 42 40 #include <ddf/log.h> … … 48 46 #include "uhh.h" 49 47 #include "usbtll.h" 50 #include "cm/core.h" 51 #include "cm/clock_control.h" 52 #include "cm/usbhost.h" 48 #include "core_cm.h" 49 #include "usbhost_cm.h" 53 50 54 51 #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_CM67 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 #endif73 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_CM105 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 #endif111 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_CM133 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 #endif137 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_CM152 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 #endif156 } 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 is211 * one of bidirectional modes might be good choice212 * 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 }221 52 222 53 typedef struct { … … 271 102 .hw_resources = { 272 103 .resources = ehci_res, 273 .count = sizeof(ehci_res) /sizeof(ehci_res[0]),104 .count = sizeof(ehci_res)/sizeof(ehci_res[0]), 274 105 } 275 106 }; … … 287 118 .interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops 288 119 }; 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 = (sysc 188 & ~(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 = (sysc 200 & ~(UHH_SYSCONFIG_SIDLE_MODE_MASK << UHH_SYSCONFIG_SIDLE_MODE_SHIFT) 201 ) | (0x2 << UHH_SYSCONFIG_SIDLE_MODE_SHIFT); 202 sysc = (sysc 203 & ~(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_FLAG 211 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_FLAG 212 | 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_FLAG 217 | UHH_HOSTCONFIG_P2_ULPI_BYPASS_FLAG 218 | 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_MASK 231 << TLL_CHANNEL_CONF_CHANMODE_SHIFT) 232 & ~(TLL_CHANNEL_CONF_FSLSMODE_MASK 233 << 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_MODE 237 << TLL_CHANNEL_CONF_CHANMODE_SHIFT); 238 239 /* Select FS/LS mode, no idea what the difference is 240 * one of bidirectional modes might be good choice 241 * 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 } 289 251 290 252 static bool rootamdm37x_add_fun(ddf_dev_t *dev, const char *name, … … 301 263 /* Add match id */ 302 264 if (ddf_fun_add_match_id(fnode, str_match_id, 100) != EOK) { 265 // TODO This will try to free our data! 303 266 ddf_fun_destroy(fnode); 304 267 return false; … … 312 275 if (ddf_fun_bind(fnode) != EOK) { 313 276 ddf_msg(LVL_ERROR, "Failed binding function %s.", name); 314 // TODO This will try to free our data!315 277 ddf_fun_destroy(fnode); 316 278 return false; … … 330 292 static int rootamdm37x_dev_add(ddf_dev_t *dev) 331 293 { 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); 294 int ret = usb_clocks(true); 343 295 if (ret != EOK) { 344 296 ddf_msg(LVL_FATAL, "Failed to enable USB HC clocks!.\n"); … … 346 298 } 347 299 348 ret = usb_tll_init( device);300 ret = usb_tll_init(); 349 301 if (ret != EOK) { 350 302 ddf_msg(LVL_FATAL, "Failed to init USB TLL!.\n"); 351 usb_clocks( device,false);303 usb_clocks(false); 352 304 return ret; 353 305 } … … 391 343 { 392 344 printf("%s: HelenOS AM/DM37x(OMAP37x) platform driver\n", NAME); 393 ddf_log_init(NAME );345 ddf_log_init(NAME, LVL_ERROR); 394 346 return ddf_driver_main(&rootamdm37x_driver); 395 347 }
Note:
See TracChangeset
for help on using the changeset viewer.