Changeset f25f1e6 in mainline
- Timestamp:
- 2012-10-15T17:33:59Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e9d636d0
- Parents:
- b3ab8f7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c
rb3ab8f7 rf25f1e6 55 55 56 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 static int amdm37x_hw_access_init(amdm37x_t *device) 67 { 68 assert(device); 69 int ret = EOK; 70 71 ret = pio_enable((void*)USBHOST_CM_BASE_ADDRESS, USBHOST_CM_SIZE, 72 (void**)&device->cm.usbhost); 73 if (ret != EOK) 74 return ret; 75 76 ret = pio_enable((void*)CORE_CM_BASE_ADDRESS, CORE_CM_SIZE, 77 (void**)&device->cm.core); 78 if (ret != EOK) 79 return ret; 80 81 ret = pio_enable((void*)CLOCK_CONTROL_CM_BASE_ADDRESS, 82 CLOCK_CONTROL_CM_SIZE, (void**)&device->cm.clocks); 83 if (ret != EOK) 84 return ret; 85 86 ret = pio_enable((void*)AMDM37x_USBTLL_BASE_ADDRESS, 87 AMDM37x_USBTLL_SIZE, (void**)&device->tll); 88 if (ret != EOK) 89 return ret; 90 91 ret = pio_enable((void*)AMDM37x_UHH_BASE_ADDRESS, 92 AMDM37x_UHH_SIZE, (void**)&device->uhh); 93 if (ret != EOK) 94 return ret; 95 96 return EOK; 97 } 98 99 static int usb_clocks(amdm37x_t *device, bool on) 100 { 101 uint32_t reg; 102 103 /* Set DPLL3 and DPLL4 to automatic */ 104 reg = device->cm.clocks->autoidle_pll; 105 reg &= ~(CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_MASK << 106 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_SHIFT); 107 reg &= ~(CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_MASK << 108 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_SHIFT); 109 reg |= (CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_AUTOMATIC << 110 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_SHIFT); 111 reg |= (CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_AUTOMATIC << 112 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_SHIFT); 113 device->cm.clocks->autoidle_pll = reg; 114 115 /* Set DPLL5 to automatic */ 116 reg = device->cm.clocks->autoidle2_pll; 117 reg &= ~(CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_MASK << 118 CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_SHIFT); 119 reg |= (CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_AUTOMATIC << 120 CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_SHIFT); 121 device->cm.clocks->autoidle2_pll = reg; 122 123 124 #ifdef DEBUG_CM 125 printf("DPLL5 could be on: %x %x.\n", 126 device->cm.clocks->idlest_ckgen, device->cm.clocks->idlest2_ckgen); 127 #endif 128 129 if (on) { 130 /* Enable interface and function clock for USB TLL */ 131 device->cm.core->iclken3 |= CORE_CM_ICLKEN3_EN_USBTLL_FLAG; 132 device->cm.core->fclken3 |= CORE_CM_FCLKEN3_EN_USBTLL_FLAG; 133 134 /* Enable interface and function clock for USB hosts */ 135 device->cm.usbhost->iclken |= USBHOST_CM_ICLKEN_EN_USBHOST; 136 device->cm.usbhost->fclken |= USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG; 137 device->cm.usbhost->fclken |= USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG; 138 #ifdef DEBUG_CM 139 printf("DPLL5 (and everything else) should be on: %x %x.\n", 140 device->cm.clocks->idlest_ckgen, device->cm.clocks->idlest2_ckgen); 141 #endif 142 } else { 143 /* Disable interface and function clock for USB hosts */ 144 device->cm.usbhost->fclken &= ~USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG; 145 device->cm.usbhost->fclken &= ~USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG; 146 device->cm.usbhost->iclken &= ~USBHOST_CM_ICLKEN_EN_USBHOST; 147 148 /* Disable interface and function clock for USB TLL */ 149 device->cm.core->fclken3 &= ~CORE_CM_FCLKEN3_EN_USBTLL_FLAG; 150 device->cm.core->iclken3 &= ~CORE_CM_ICLKEN3_EN_USBTLL_FLAG; 151 } 152 153 return EOK; 154 } 155 156 /** Initialize USB TLL port connections. 157 * 158 * Different modes are on page 3312 of the Manual Figure 22-34. 159 * Select mode than can operate in FS/LS. 160 */ 161 static int usb_tll_init(amdm37x_t *device) 162 { 163 164 /* Reset USB TLL */ 165 device->tll->sysconfig |= TLL_SYSCONFIG_SOFTRESET_FLAG; 166 ddf_msg(LVL_DEBUG2, "Waiting for USB TLL reset"); 167 while (!(device->tll->sysstatus & TLL_SYSSTATUS_RESET_DONE_FLAG)); 168 ddf_msg(LVL_DEBUG, "USB TLL Reset done."); 169 170 { 171 /* Setup idle mode (smart idle) */ 172 uint32_t sysc = device->tll->sysconfig; 173 sysc |= TLL_SYSCONFIG_CLOCKACTIVITY_FLAG | TLL_SYSCONFIG_AUTOIDLE_FLAG; 174 sysc = (sysc 175 & ~(TLL_SYSCONFIG_SIDLE_MODE_MASK << TLL_SYSCONFIG_SIDLE_MODE_SHIFT) 176 ) | (0x2 << TLL_SYSCONFIG_SIDLE_MODE_SHIFT); 177 device->tll->sysconfig = sysc; 178 ddf_msg(LVL_DEBUG2, "Set TLL->sysconfig (%p) to %x:%x.", 179 &device->tll->sysconfig, device->tll->sysconfig, sysc); 180 } 181 182 { 183 /* Smart idle for UHH */ 184 uint32_t sysc = device->uhh->sysconfig; 185 sysc |= UHH_SYSCONFIG_CLOCKACTIVITY_FLAG | UHH_SYSCONFIG_AUTOIDLE_FLAG; 186 sysc = (sysc 187 & ~(UHH_SYSCONFIG_SIDLE_MODE_MASK << UHH_SYSCONFIG_SIDLE_MODE_SHIFT) 188 ) | (0x2 << UHH_SYSCONFIG_SIDLE_MODE_SHIFT); 189 sysc = (sysc 190 & ~(UHH_SYSCONFIG_MIDLE_MODE_MASK << UHH_SYSCONFIG_MIDLE_MODE_SHIFT) 191 ) | (0x2 << UHH_SYSCONFIG_MIDLE_MODE_SHIFT); 192 ddf_msg(LVL_DEBUG2, "Set UHH->sysconfig (%p) to %x.", 193 &device->uhh->sysconfig, device->uhh->sysconfig); 194 device->uhh->sysconfig = sysc; 195 196 /* All ports are connected on BBxM */ 197 device->uhh->hostconfig |= (UHH_HOSTCONFIG_P1_CONNECT_STATUS_FLAG 198 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_FLAG 199 | UHH_HOSTCONFIG_P3_CONNECT_STATUS_FLAG); 200 201 /* Set all ports to go through TLL(UTMI) 202 * Direct connection can only work in HS mode */ 203 device->uhh->hostconfig |= (UHH_HOSTCONFIG_P1_ULPI_BYPASS_FLAG 204 | UHH_HOSTCONFIG_P2_ULPI_BYPASS_FLAG 205 | UHH_HOSTCONFIG_P3_ULPI_BYPASS_FLAG); 206 ddf_msg(LVL_DEBUG2, "Set UHH->hostconfig (%p) to %x.", 207 &device->uhh->hostconfig, device->uhh->hostconfig); 208 } 209 210 device->tll->shared_conf |= TLL_SHARED_CONF_FCLK_IS_ON_FLAG; 211 ddf_msg(LVL_DEBUG2, "Set shared conf port (%p) to %x.", 212 &device->tll->shared_conf, device->tll->shared_conf); 213 214 for (unsigned i = 0; i < 3; ++i) { 215 uint32_t ch = device->tll->channel_conf[i]; 216 /* Clear Channel mode and FSLS mode */ 217 ch &= ~(TLL_CHANNEL_CONF_CHANMODE_MASK 218 << TLL_CHANNEL_CONF_CHANMODE_SHIFT) 219 & ~(TLL_CHANNEL_CONF_FSLSMODE_MASK 220 << TLL_CHANNEL_CONF_FSLSMODE_SHIFT); 221 222 /* Serial mode is the only one capable of FS/LS operation. */ 223 ch |= (TLL_CHANNEL_CONF_CHANMODE_UTMI_SERIAL_MODE 224 << TLL_CHANNEL_CONF_CHANMODE_SHIFT); 225 226 /* Select FS/LS mode, no idea what the difference is 227 * one of bidirectional modes might be good choice 228 * 2 = 3pin bidi phy. */ 229 ch |= (2 << TLL_CHANNEL_CONF_FSLSMODE_SHIFT); 230 231 /* Write to register */ 232 ddf_msg(LVL_DEBUG2, "Setting port %u(%p) to %x.", 233 i, &device->tll->channel_conf[i], ch); 234 device->tll->channel_conf[i] = ch; 235 } 236 return EOK; 237 } 238 239 typedef struct { 57 240 hw_resource_list_t hw_resources; 58 241 } rootamdm37x_fun_t; … … 105 288 .hw_resources = { 106 289 .resources = ehci_res, 107 .count = sizeof(ehci_res) /sizeof(ehci_res[0]),290 .count = sizeof(ehci_res) / sizeof(ehci_res[0]), 108 291 } 109 292 }; … … 121 304 .interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops 122 305 }; 123 124 static int usb_clocks(bool on)125 {126 static usbhost_cm_regs_t *usb_host_cm = NULL;127 static core_cm_regs_t *l4_core_cm = NULL;128 static clock_control_cm_regs_t *clock_control_cm = NULL;129 130 if (!usb_host_cm) {131 const int ret = pio_enable((void*)USBHOST_CM_BASE_ADDRESS,132 USBHOST_CM_SIZE, (void**)&usb_host_cm);133 if (ret != EOK)134 return ret;135 }136 137 if (!l4_core_cm) {138 const int ret = pio_enable((void*)CORE_CM_BASE_ADDRESS,139 CORE_CM_SIZE, (void**)&l4_core_cm);140 if (ret != EOK)141 return ret;142 }143 144 if (!clock_control_cm) {145 const int ret = pio_enable((void*)CLOCK_CONTROL_CM_BASE_ADDRESS,146 CLOCK_CONTROL_CM_SIZE, (void**)&clock_control_cm);147 if (ret != EOK)148 return ret;149 }150 151 assert(l4_core_cm);152 assert(usb_host_cm);153 assert(clock_control_cm);154 155 uint32_t reg;156 157 /* Set DPLL3 and DPLL4 to automatic */158 reg = clock_control_cm->autoidle_pll;159 reg &= ~(CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_MASK <<160 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_SHIFT);161 reg &= ~(CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_MASK <<162 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_SHIFT);163 reg |= (CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_AUTOMATIC <<164 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_CORE_DPLL_SHIFT);165 reg |= (CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_AUTOMATIC <<166 CLOCK_CONTROL_CM_AUTOIDLE_PLL_AUTO_PERIPH_DPLL_SHIFT);167 clock_control_cm->autoidle_pll = reg;168 169 /* Set DPLL5 to automatic */170 reg = clock_control_cm->autoidle2_pll;171 reg &= ~(CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_MASK <<172 CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_SHIFT);173 reg |= (CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_AUTOMATIC <<174 CLOCK_CONTROL_CM_AUTOIDLE2_PLL_AUTO_PERIPH2_DPLL_SHIFT);175 clock_control_cm->autoidle2_pll = reg;176 177 178 #ifdef DEBUG_CM179 printf("DPLL5 could be on: %x %x.\n",180 clock_control_cm->idlest_ckgen, clock_control_cm->idlest2_ckgen);181 #endif182 183 if (on) {184 /* Enable interface and function clock for USB TLL */185 l4_core_cm->iclken3 |= CORE_CM_ICLKEN3_EN_USBTLL_FLAG;186 l4_core_cm->fclken3 |= CORE_CM_FCLKEN3_EN_USBTLL_FLAG;187 188 /* Enable interface and function clock for USB hosts */189 usb_host_cm->iclken |= USBHOST_CM_ICLKEN_EN_USBHOST;190 usb_host_cm->fclken |= USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG;191 usb_host_cm->fclken |= USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG;192 #ifdef DEBUG_CM193 printf("DPLL5 (and everything else) should be on: %x %x.\n",194 clock_control_cm->idlest_ckgen, clock_control_cm->idlest2_ckgen);195 #endif196 } else {197 /* Disable interface and function clock for USB hosts */198 usb_host_cm->fclken &= ~USBHOST_CM_FCLKEN_EN_USBHOST2_FLAG;199 usb_host_cm->fclken &= ~USBHOST_CM_FCLKEN_EN_USBHOST1_FLAG;200 usb_host_cm->iclken &= ~USBHOST_CM_ICLKEN_EN_USBHOST;201 202 /* Disable interface and function clock for USB TLL */203 l4_core_cm->fclken3 &= ~CORE_CM_FCLKEN3_EN_USBTLL_FLAG;204 l4_core_cm->iclken3 &= ~CORE_CM_ICLKEN3_EN_USBTLL_FLAG;205 }206 207 return EOK;208 }209 210 /** Initialize USB TLL port connections.211 *212 * Different modes are on page 3312 of the Manual Figure 22-34.213 * Select mode than can operate in FS/LS.214 */215 static int usb_tll_init()216 {217 tll_regs_t *usb_tll = NULL;218 uhh_regs_t *uhh_conf = NULL;219 220 int ret = pio_enable((void*)AMDM37x_USBTLL_BASE_ADDRESS,221 AMDM37x_USBTLL_SIZE, (void**)&usb_tll);222 if (ret != EOK)223 return ret;224 225 ret = pio_enable((void*)AMDM37x_UHH_BASE_ADDRESS,226 AMDM37x_UHH_SIZE, (void**)&uhh_conf);227 if (ret != EOK)228 return ret;229 230 /* Reset USB TLL */231 usb_tll->sysconfig |= TLL_SYSCONFIG_SOFTRESET_FLAG;232 ddf_msg(LVL_DEBUG2, "Waiting for USB TLL reset");233 while (!(usb_tll->sysstatus & TLL_SYSSTATUS_RESET_DONE_FLAG));234 ddf_msg(LVL_DEBUG, "USB TLL Reset done.");235 236 {237 /* Setup idle mode (smart idle) */238 uint32_t sysc = usb_tll->sysconfig;239 sysc |= TLL_SYSCONFIG_CLOCKACTIVITY_FLAG | TLL_SYSCONFIG_AUTOIDLE_FLAG;240 sysc = (sysc241 & ~(TLL_SYSCONFIG_SIDLE_MODE_MASK << TLL_SYSCONFIG_SIDLE_MODE_SHIFT)242 ) | (0x2 << TLL_SYSCONFIG_SIDLE_MODE_SHIFT);243 usb_tll->sysconfig = sysc;244 ddf_msg(LVL_DEBUG2, "Set TLL->sysconfig (%p) to %x:%x.",245 &usb_tll->sysconfig, usb_tll->sysconfig, sysc);246 }247 248 {249 /* Smart idle for UHH */250 uint32_t sysc = uhh_conf->sysconfig;251 sysc |= UHH_SYSCONFIG_CLOCKACTIVITY_FLAG | UHH_SYSCONFIG_AUTOIDLE_FLAG;252 sysc = (sysc253 & ~(UHH_SYSCONFIG_SIDLE_MODE_MASK << UHH_SYSCONFIG_SIDLE_MODE_SHIFT)254 ) | (0x2 << UHH_SYSCONFIG_SIDLE_MODE_SHIFT);255 sysc = (sysc256 & ~(UHH_SYSCONFIG_MIDLE_MODE_MASK << UHH_SYSCONFIG_MIDLE_MODE_SHIFT)257 ) | (0x2 << UHH_SYSCONFIG_MIDLE_MODE_SHIFT);258 ddf_msg(LVL_DEBUG2, "Set UHH->sysconfig (%p) to %x.",259 &uhh_conf->sysconfig, uhh_conf->sysconfig);260 uhh_conf->sysconfig = sysc;261 262 /* All ports are connected on BBxM */263 uhh_conf->hostconfig |= (UHH_HOSTCONFIG_P1_CONNECT_STATUS_FLAG264 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_FLAG265 | UHH_HOSTCONFIG_P3_CONNECT_STATUS_FLAG);266 267 /* Set all ports to go through TLL(UTMI)268 * Direct connection can only work in HS mode */269 uhh_conf->hostconfig |= (UHH_HOSTCONFIG_P1_ULPI_BYPASS_FLAG270 | UHH_HOSTCONFIG_P2_ULPI_BYPASS_FLAG271 | UHH_HOSTCONFIG_P3_ULPI_BYPASS_FLAG);272 ddf_msg(LVL_DEBUG2, "Set UHH->hostconfig (%p) to %x.",273 &uhh_conf->hostconfig, uhh_conf->hostconfig);274 }275 276 usb_tll->shared_conf |= TLL_SHARED_CONF_FCLK_IS_ON_FLAG;277 ddf_msg(LVL_DEBUG2, "Set shared conf port (%p) to %x.",278 &usb_tll->shared_conf, usb_tll->shared_conf);279 280 for (unsigned i = 0; i < 3; ++i) {281 uint32_t ch = usb_tll->channel_conf[i];282 /* Clear Channel mode and FSLS mode */283 ch &= ~(TLL_CHANNEL_CONF_CHANMODE_MASK284 << TLL_CHANNEL_CONF_CHANMODE_SHIFT)285 & ~(TLL_CHANNEL_CONF_FSLSMODE_MASK286 << TLL_CHANNEL_CONF_FSLSMODE_SHIFT);287 288 /* Serial mode is the only one capable of FS/LS operation. */289 ch |= (TLL_CHANNEL_CONF_CHANMODE_UTMI_SERIAL_MODE290 << TLL_CHANNEL_CONF_CHANMODE_SHIFT);291 292 /* Select FS/LS mode, no idea what the difference is293 * one of bidirectional modes might be good choice294 * 2 = 3pin bidi phy. */295 ch |= (2 << TLL_CHANNEL_CONF_FSLSMODE_SHIFT);296 297 /* Write to register */298 ddf_msg(LVL_DEBUG2, "Setting port %u(%p) to %x.",299 i, &usb_tll->channel_conf[i], ch);300 usb_tll->channel_conf[i] = ch;301 }302 return EOK;303 }304 306 305 307 static bool rootamdm37x_add_fun(ddf_dev_t *dev, const char *name, … … 345 347 static int rootamdm37x_dev_add(ddf_dev_t *dev) 346 348 { 347 int ret = usb_clocks(true); 349 assert(dev); 350 amdm37x_t *device = ddf_dev_data_alloc(dev, sizeof(amdm37x_t)); 351 if (!device) 352 return ENOMEM; 353 int ret = amdm37x_hw_access_init(device); 354 if (ret != EOK) { 355 ddf_msg(LVL_FATAL, "Failed to setup hw access!.\n"); 356 return ret; 357 } 358 359 ret = usb_clocks(device, true); 348 360 if (ret != EOK) { 349 361 ddf_msg(LVL_FATAL, "Failed to enable USB HC clocks!.\n"); … … 351 363 } 352 364 353 ret = usb_tll_init( );365 ret = usb_tll_init(device); 354 366 if (ret != EOK) { 355 367 ddf_msg(LVL_FATAL, "Failed to init USB TLL!.\n"); 356 usb_clocks( false);368 usb_clocks(device, false); 357 369 return ret; 358 370 } … … 396 408 { 397 409 printf("%s: HelenOS AM/DM37x(OMAP37x) platform driver\n", NAME); 398 ddf_log_init(NAME , LVL_ERROR);410 ddf_log_init(NAME); 399 411 return ddf_driver_main(&rootamdm37x_driver); 400 412 }
Note:
See TracChangeset
for help on using the changeset viewer.