Ignore:
File:
1 edited

Legend:

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

    rbebf97d r57912af3  
    3535/** @file
    3636 */
    37 
    38 #define DEBUG_CM 0
    39 
     37#define _DDF_DATA_IMPLANT
     38
     39#define DEBUG_CM
     40
     41#include <ddf/driver.h>
    4042#include <ddf/log.h>
    4143#include <errno.h>
    4244#include <ops/hw_res.h>
    4345#include <stdio.h>
    44 
    45 #include "amdm37x.h"
     46#include <ddi.h>
     47
     48#include "uhh.h"
     49#include "usbtll.h"
     50#include "cm/core.h"
     51#include "cm/clock_control.h"
     52#include "cm/usbhost.h"
    4653
    4754#define NAME  "rootamdm37x"
     55
     56typedef 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
     67static 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
     74static 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
     114static 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 */
     179static 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}
    48221
    49222typedef struct {
     
    51224} rootamdm37x_fun_t;
    52225
    53 /* See amdm37x TRM page. 3316 for these values */
    54226#define OHCI_BASE_ADDRESS  0x48064400
    55227#define OHCI_SIZE  1024
     
    60232        {
    61233                .type = MEM_RANGE,
     234                /* See amdm37x TRM page. 3316 for these values */
    62235                .res.io_range = {
    63236                        .address = OHCI_BASE_ADDRESS,
     
    70243                .res.interrupt = { .irq = 76 },
    71244        },
     245};
     246
     247static const rootamdm37x_fun_t ohci = {
     248        .hw_resources = {
     249            .resources = ohci_res,
     250            .count = sizeof(ohci_res)/sizeof(ohci_res[0]),
     251        }
    72252};
    73253
     
    88268};
    89269
    90 static const rootamdm37x_fun_t ohci = {
    91         .hw_resources = {
    92             .resources = ohci_res,
    93             .count = sizeof(ohci_res)/sizeof(ohci_res[0]),
    94         }
    95 };
    96 
    97270static const rootamdm37x_fun_t ehci = {
    98271        .hw_resources = {
     
    110283};
    111284
    112 static ddf_dev_ops_t rootamdm37x_fun_ops = {
     285static ddf_dev_ops_t rootamdm37x_fun_ops =
     286{
    113287        .interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops
    114288};
    115289
    116 static int rootamdm37x_add_fun(ddf_dev_t *dev, const char *name,
     290static bool rootamdm37x_add_fun(ddf_dev_t *dev, const char *name,
    117291    const char *str_match_id, const rootamdm37x_fun_t *fun)
    118292{
     
    124298                return ENOMEM;
    125299       
     300       
    126301        /* Add match id */
    127         int ret = ddf_fun_add_match_id(fnode, str_match_id, 100);
    128         if (ret != EOK) {
     302        if (ddf_fun_add_match_id(fnode, str_match_id, 100) != EOK) {
    129303                ddf_fun_destroy(fnode);
    130                 return ret;
    131         }
    132        
    133         /* Alloc needed data */
    134         rootamdm37x_fun_t *rf =
    135             ddf_fun_data_alloc(fnode, sizeof(rootamdm37x_fun_t));
    136         if (!rf) {
     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);
     314                // TODO This will try to free our data!
    137315                ddf_fun_destroy(fnode);
    138                 return ENOMEM;
    139         }
    140         *rf = *fun;
    141 
    142         /* Set provided operations to the device. */
    143         ddf_fun_set_ops(fnode, &rootamdm37x_fun_ops);
    144        
    145         /* Register function. */
    146         ret = ddf_fun_bind(fnode);
    147         if (ret != EOK) {
    148                 ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
    149                 ddf_fun_destroy(fnode);
    150                 return ret;
    151         }
    152        
    153         return EOK;
     316                return false;
     317        }
     318       
     319        return true;
    154320}
    155321
     
    168334        if (!device)
    169335                return ENOMEM;
    170         int ret = amdm37x_init(device, DEBUG_CM);
     336        int ret = amdm37x_hw_access_init(device);
    171337        if (ret != EOK) {
    172338                ddf_msg(LVL_FATAL, "Failed to setup hw access!.\n");
     
    174340        }
    175341
    176         /* Set dplls to ON and automatic */
    177         amdm37x_setup_dpll_on_autoidle(device);
    178 
    179         /* Enable function and interface clocks */
    180         amdm37x_usb_clocks_set(device, true);
    181 
    182         /* Init TLL */
    183         ret = amdm37x_usb_tll_init(device);
     342        ret = usb_clocks(device, true);
     343        if (ret != EOK) {
     344                ddf_msg(LVL_FATAL, "Failed to enable USB HC clocks!.\n");
     345                return ret;
     346        }
     347
     348        ret = usb_tll_init(device);
    184349        if (ret != EOK) {
    185350                ddf_msg(LVL_FATAL, "Failed to init USB TLL!.\n");
    186                 amdm37x_usb_clocks_set(device, false);
     351                usb_clocks(device, false);
    187352                return ret;
    188353        }
    189354
    190355        /* Register functions */
    191         if (rootamdm37x_add_fun(dev, "ohci", "usb/host=ohci", &ohci) != EOK)
     356        if (!rootamdm37x_add_fun(dev, "ohci", "usb/host=ohci", &ohci))
    192357                ddf_msg(LVL_ERROR, "Failed to add OHCI function for "
    193358                    "BeagleBoard-xM platform.");
    194         if (rootamdm37x_add_fun(dev, "ehci", "usb/host=ehci", &ehci) != EOK)
     359        if (!rootamdm37x_add_fun(dev, "ehci", "usb/host=ehci", &ehci))
    195360                ddf_msg(LVL_ERROR, "Failed to add EHCI function for "
    196361                    "BeagleBoard-xM platform.");
     
    210375};
    211376
    212 static hw_resource_list_t * rootamdm37x_get_resources(ddf_fun_t *fnode)
     377static hw_resource_list_t *rootamdm37x_get_resources(ddf_fun_t *fnode)
    213378{
    214379        rootamdm37x_fun_t *fun = ddf_fun_data_get(fnode);
     
    219384static bool rootamdm37x_enable_interrupt(ddf_fun_t *fun)
    220385{
    221         //TODO: Implement
     386        /* TODO */
    222387        return false;
    223388}
Note: See TracChangeset for help on using the changeset viewer.