Changeset f25f1e6 in mainline


Ignore:
Timestamp:
2012-10-15T17:33:59Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e9d636d0
Parents:
b3ab8f7
Message:

rootamdm37x: Refactoring.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/infrastructure/rootamdm37x/rootamdm37x.c

    rb3ab8f7 rf25f1e6  
    5555
    5656typedef 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
     66static 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
     99static 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 */
     161static 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
     239typedef struct {
    57240        hw_resource_list_t hw_resources;
    58241} rootamdm37x_fun_t;
     
    105288        .hw_resources = {
    106289            .resources = ehci_res,
    107             .count = sizeof(ehci_res)/sizeof(ehci_res[0]),
     290            .count = sizeof(ehci_res) / sizeof(ehci_res[0]),
    108291        }
    109292};
     
    121304        .interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops
    122305};
    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_CM
    179         printf("DPLL5 could be on: %x %x.\n",
    180             clock_control_cm->idlest_ckgen, clock_control_cm->idlest2_ckgen);
    181 #endif
    182 
    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_CM
    193         printf("DPLL5 (and everything else) should be on: %x %x.\n",
    194             clock_control_cm->idlest_ckgen, clock_control_cm->idlest2_ckgen);
    195 #endif
    196         } 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 = (sysc
    241             & ~(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 = (sysc
    253             & ~(UHH_SYSCONFIG_SIDLE_MODE_MASK << UHH_SYSCONFIG_SIDLE_MODE_SHIFT)
    254             ) | (0x2 << UHH_SYSCONFIG_SIDLE_MODE_SHIFT);
    255         sysc = (sysc
    256             & ~(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_FLAG
    264             | UHH_HOSTCONFIG_P2_CONNECT_STATUS_FLAG
    265             | 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_FLAG
    270             | UHH_HOSTCONFIG_P2_ULPI_BYPASS_FLAG
    271             | 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_MASK
    284                     << TLL_CHANNEL_CONF_CHANMODE_SHIFT)
    285                     & ~(TLL_CHANNEL_CONF_FSLSMODE_MASK
    286                     << 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_MODE
    290                     << TLL_CHANNEL_CONF_CHANMODE_SHIFT);
    291 
    292                 /* Select FS/LS mode, no idea what the difference is
    293                  * one of bidirectional modes might be good choice
    294                  * 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 }
    304306
    305307static bool rootamdm37x_add_fun(ddf_dev_t *dev, const char *name,
     
    345347static int rootamdm37x_dev_add(ddf_dev_t *dev)
    346348{
    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);
    348360        if (ret != EOK) {
    349361                ddf_msg(LVL_FATAL, "Failed to enable USB HC clocks!.\n");
     
    351363        }
    352364
    353         ret = usb_tll_init();
     365        ret = usb_tll_init(device);
    354366        if (ret != EOK) {
    355367                ddf_msg(LVL_FATAL, "Failed to init USB TLL!.\n");
    356                 usb_clocks(false);
     368                usb_clocks(device, false);
    357369                return ret;
    358370        }
     
    396408{
    397409        printf("%s: HelenOS AM/DM37x(OMAP37x) platform driver\n", NAME);
    398         ddf_log_init(NAME, LVL_ERROR);
     410        ddf_log_init(NAME);
    399411        return ddf_driver_main(&rootamdm37x_driver);
    400412}
Note: See TracChangeset for help on using the changeset viewer.