Ignore:
Timestamp:
Jul 12, 2017, 8:12:41 PM (7 years ago)
Author:
alain
Message:

Redefine the PIC device API.

Location:
trunk/hal/tsar_mips32/drivers
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/hal/tsar_mips32/drivers/soclib_pic.c

    r141 r188  
    22 * soclib_pic.c - soclib PIC driver implementation.
    33 *
    4  * Author  Alain Greiner (2016)
     4 * Author  Alain Greiner (2016,2017)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    2525#include <chdev.h>
    2626#include <soclib_pic.h>
    27 #include <soclib_xcu.h>
    2827#include <errno.h>
    2928#include <string.h>
    3029#include <vfs.h>
     30#include <cluster.h>
     31#include <printk.h>
     32#include <core.h>
     33#include <thread.h>
     34
     35//////////////////////////////////////////////////////////////////////////////////////
     36//         Extern variables
     37//////////////////////////////////////////////////////////////////////////////////////
     38
     39extern  chdev_directory_t chdev_dir;    // defined in chdev.h / allocated in kerneL-init.c
     40
     41extern  iopic_input_t  iopic_input;  // defined in dev_pic.h / allocated in kernel_init.c
     42extern  lapic_input_t  lapic_input;  // defined in dev_pic.h / allocated in kernel_init.c
     43 
     44//////////////////////////////////////////////////////////////////////////////////////
     45//        SOCLIB PIC private functions
     46//////////////////////////////////////////////////////////////////////////////////////
     47
     48///////////////////////////////
     49uint32_t soclib_pic_wti_alloc()
     50{
     51    uint32_t index;
     52
     53    // get pointer on cluster extension for SOCLIB PIC (XCU descriptor)
     54    soclib_pic_cluster_t * ext_ptr = LOCAL_CLUSTER->pic_extend;
     55
     56    assert( (ext_ptr->first_free_wti < ext_ptr->wti_nr) , __FUNCTION__ ,
     57            "no free WTI found : too much external IRQs\n");
     58
     59    // update WTI allocator
     60    index = ext_ptr->first_free_wti;
     61    ext_ptr->first_free_wti++;
     62
     63    return index;
     64
     65}  // end soclib_pic_wti_alloc()
     66
     67///////////////////////////////////////
     68inline uint32_t * soclib_pic_xcu_base()
     69{
     70    return ((soclib_pic_cluster_t *)LOCAL_CLUSTER->pic_extend)->xcu_base;
     71
     72}  // end soclib_pic_xcu_base()
     73
     74
     75//////////////////////////////////////////
     76uint32_t soclib_pic_ack_timer( lid_t lid )
     77{
     78    // get local XCU segment base
     79        uint32_t * base = soclib_pic_xcu_base();
     80
     81    // read from register
     82        return base[(XCU_PTI_ACK << 5) | lid];
     83
     84}  // end soclib_pic_ack_timer()
     85
     86///////////////////////////////////////////
     87void soclib_pic_xcu_status( lid_t      lid,
     88                            uint32_t * hwi_status,
     89                            uint32_t * wti_status,
     90                            uint32_t * pti_status )
     91{
     92    // get local XCU segment base
     93        uint32_t * base = soclib_pic_xcu_base();
     94
     95    // read PRIO register
     96        uint32_t prio = base[(XCU_PRIO << 5) | lid];
     97
     98    *wti_status = (prio & 0x4) ? (((prio >> 24) & 0x1F) + 1) : 0;
     99    *hwi_status = (prio & 0x2) ? (((prio >> 16) & 0x1F) + 1) : 0;
     100    *pti_status = (prio & 0x1) ? (((prio >>  8) & 0x1F) + 1) : 0;
     101
     102}
     103
     104/////////////////////////////
     105void soclib_pic_irq_handler()
     106{
     107    uint32_t   hwi_status;   // HWI index + 1  / no pending HWI if 0
     108    uint32_t   wti_status;   // WTI index + 1  / no pending WTI if 0
     109    uint32_t   pti_status;   // PTI index + 1  / no pending PTI if 0
     110    chdev_t  * src_chdev;    // pointer on source chdev descriptor
     111    uint32_t   index;        // IRQ index
     112
     113    core_t * core = CURRENT_THREAD->core;
     114
     115    // get XCU status
     116    soclib_pic_xcu_status( core->lid,
     117                           &hwi_status,
     118                           &wti_status,
     119                           &pti_status );
     120
     121    // analyse status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI)
     122
     123    if( wti_status )          // pending WTI
     124        {
     125        index = wti_status - 1;
     126
     127        if( index < LOCAL_CLUSTER->cores_nr )   // it is an IPI
     128        {
     129            assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" );
     130
     131            // TODO acknowledge WTI [AG]
     132
     133            // TODO force scheduling [AG]
     134        }
     135        else                                    // it is an external device
     136        {
     137            // get pointer on source chdev
     138            src_chdev = ((soclib_pic_core_t *)core->pic_extend)->wti_vector[index];
     139
     140                    if( src_chdev == NULL )        // strange, but not fatal
     141                    {
     142                printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n",
     143                       __FUNCTION__ , index , core->lid , local_cxy );
     144
     145                    core->spurious_irqs ++;
     146
     147                // TODO disable this WTI in local XCU [AG]
     148            }
     149            else                                 // call relevant ISR
     150            {
     151                        irq_dmsg("\n[INFO] %s received WTI : index = %d for core %d in cluster %d\n",
     152                         __FUNCTION__ , index , core->lid , local_cxy );
     153
     154                // call ISR
     155                    src_chdev->isr( src_chdev );
     156            }
     157        }
     158        }
     159
     160        if( hwi_status )      // pending HWI
     161        {
     162        index = hwi_status - 1;
     163
     164        // get pointer on source chdev
     165        src_chdev = ((soclib_pic_core_t *)core->pic_extend)->hwi_vector[index];
     166
     167                if( src_chdev == NULL )        // strange, but not fatal
     168                {
     169            printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n",
     170                   __FUNCTION__ , index , core->lid , local_cxy );
     171
     172                core->spurious_irqs ++;
     173
     174            // TODO disable this HWI in local XCU [AG]
     175                }
     176        else                    // call relevant ISR
     177        {
     178                    irq_dmsg("\n[INFO] %s received HWI : index = %d for core %d in cluster %d\n",
     179                     __FUNCTION__ , index , core->lid , local_cxy );
     180
     181            // call ISR
     182                    src_chdev->isr( src_chdev );
     183        }
     184        }
     185
     186    if( pti_status )      // pending PTI
     187        {
     188        index = pti_status - 1;
     189
     190                irq_dmsg("\n[INFO] %s received PTI : index = %d for cpu %d in cluster %d\n",
     191                 __FUNCTION__ , index , core->lid , local_cxy );
     192
     193        assert( (index == core->lid) , __FUNCTION__ , "unconsistent PTI index\n");
     194
     195        // acknowledge PTI
     196        soclib_pic_ack_timer( index );
     197
     198        // TODO execute all actions related to TICK event
     199        core_clock( core );
     200        }
     201}  // end soclib_pic_irq_handler()
     202
     203
     204
     205
     206//////////////////////////////////////////////////////////////////////////////////////
     207//         SOCLIC PIC device  generic API
     208//////////////////////////////////////////////////////////////////////////////////////
     209
     210/////////////////////////////////////
     211void soclib_pic_init( chdev_t * pic )
     212{
     213    uint32_t    i;      // for loop on IOPIC inputs
     214    uint32_t    x;      // for loop on clusters in a row
     215    uint32_t    y;      // for loop on clusters in a column inputs
     216    uint32_t    lid;    // for loop on cores in a cluster
     217
     218    // get target architecture parameters
     219    cluster_t * cluster = LOCAL_CLUSTER;
     220    uint32_t    x_size  = cluster->x_size;
     221    uint32_t    y_size  = cluster->y_size;
     222    uint32_t    y_width = cluster->y_width;
     223    uint32_t    ncores  = cluster->cores_nr;
     224
     225    // get IOPIC controller cluster and segment base pointer
     226    cxy_t      iopic_seg_cxy = (cxy_t)GET_CXY( pic->base );
     227    uint32_t * iopic_seg_ptr = (uint32_t *)GET_PTR( pic->base );
     228
     229    // reset the IOPIC component registers : mask all input IRQs
     230    for( i = 0 ; i < CONFIG_MAX_EXTERNAL_IRQS ; i++ )
     231    {
     232        xptr_t iopic_seg_xp = XPTR( iopic_seg_cxy,
     233                                    iopic_seg_ptr + i*IOPIC_SPAN + IOPIC_MASK );
     234        hal_remote_sw( iopic_seg_xp , 0 );
     235    }
     236   
     237    // GET XCU controller segment base
     238    uint32_t * base = soclib_pic_xcu_base();
     239
     240    // reset the XCU component registers in all clusters:
     241    // mask all HWIs, all WTIs, and all PTIs, for all cores   
     242    for( x = 0 ; x < x_size ; x++ )
     243    {
     244        for( y = 0 ; y < y_size ; y++ )
     245        {
     246            for( lid = 0 ; lid < ncores ; lid++ )
     247            {
     248                cxy_t cxy = (x<<y_width) + y;
     249                xptr_t hwi_mask_xp = XPTR( cxy , base + (XCU_MSK_HWI_DISABLE << 5 | lid) );
     250                xptr_t wti_mask_xp = XPTR( cxy , base + (XCU_MSK_WTI_DISABLE << 5 | lid) );
     251                xptr_t pti_mask_xp = XPTR( cxy , base + (XCU_MSK_PTI_DISABLE << 5 | lid) );
     252                hal_remote_sw( hwi_mask_xp , 0xFFFFFFFF );
     253                hal_remote_sw( wti_mask_xp , 0xFFFFFFFF );
     254                hal_remote_sw( pti_mask_xp , 0xFFFFFFFF );
     255            }
     256        }
     257    }
     258}  // end soclib_pic_init()
     259
     260//////////////////////////////////////////////////
     261void soclib_pic_extend_init( uint32_t * xcu_base )
     262{
     263    soclib_pic_cluster_t * cluster_ext_ptr;   
     264    soclib_pic_core_t    * core_ext_ptr;
     265    kmem_req_t             req;
     266    uint32_t               lid;
     267    uint32_t               idx;
     268
     269    cluster_t            * cluster = LOCAL_CLUSTER;
     270
     271    // create core extension for all cores in cluster
     272    for( lid = 0 ; lid < cluster->cores_nr ; lid++ )
     273    {
     274        // allocate memory for core extension
     275        req.type     = KMEM_GENERIC;
     276        req.size     = sizeof(soclib_pic_core_t);
     277        req.flags    = AF_KERNEL;
     278        core_ext_ptr = kmem_alloc( &req );
     279
     280        assert( (core_ext_ptr != NULL) , __FUNCTION__ ,
     281                "cannot allocate memory for core extension\n");
     282   
     283        // reset the HWI / WTI  interrupt vectors
     284        for( idx = 0 ; idx < SOCLIB_MAX_HWI ; idx++ ) core_ext_ptr->hwi_vector[idx] = NULL;
     285        for( idx = 0 ; idx < SOCLIB_MAX_WTI ; idx++ ) core_ext_ptr->wti_vector[idx] = NULL;
     286
     287        // register PIC extension in core descriptor
     288        cluster->core_tbl[lid].pic_extend = core_ext_ptr;
     289    }
     290
     291    // allocate memory for cluster extension
     292    req.type        = KMEM_GENERIC;
     293    req.size        = sizeof(soclib_pic_cluster_t);
     294    req.flags       = AF_KERNEL;
     295    cluster_ext_ptr = kmem_alloc( &req );
     296
     297    assert( (cluster_ext_ptr != NULL) , __FUNCTION__ ,
     298            "cannot allocate memory for cluster extension\n");
     299
     300    // get XCU characteristics from the XCU config register
     301    uint32_t  config = xcu_base[XCU_CONFIG<<5];
     302    uint32_t  wti_nr = (config >> 16) & 0xFF;
     303    uint32_t  hwi_nr = (config >> 8 ) & 0xFF;
     304    uint32_t  pti_nr = (config      ) & 0xFF;
     305
     306    // initialize the cluster extension
     307    // The first WTI slots are for IPIs (one slot per core)
     308    cluster_ext_ptr->xcu_base       = xcu_base;
     309    cluster_ext_ptr->hwi_nr         = hwi_nr;
     310    cluster_ext_ptr->wti_nr         = wti_nr;
     311    cluster_ext_ptr->pti_nr         = pti_nr;
     312    cluster_ext_ptr->first_free_wti = cluster->cores_nr;
     313
     314    // register PIC extension in cluster manager
     315    cluster->pic_extend = cluster_ext_ptr;
     316
     317}  // end soclib_pic_extend_init()
    31318
    32319////////////////////////////////////////
    33 void soclib_pic_init( chdev_t  * chdev )
    34 {
    35     // get PIC controller segment cluster and local pointer
    36     cxy_t      seg_cxy = (cxy_t)GET_CXY( chdev->base );
    37     uint32_t * seg_ptr = (uint32_t *)GET_PTR( chdev->base );
    38     uint32_t   i;
    39 
    40     // reset the MASK registers for all input IRQs
    41     for( i = 0 ; i < CONFIG_MAX_IRQS_PER_PIC ; i++ )
    42     {
    43         hal_remote_sw( XPTR( seg_cxy , seg_ptr + i*IOPIC_SPAN + IOPIC_MASK ) , 0 );
    44     }
     320void soclib_pic_bind_irq( lid_t     lid,
     321                          chdev_t * src_chdev )
     322{
     323    // get extended & local pointers on PIC chdev descriptor
     324    xptr_t     pic_xp  = chdev_dir.pic;
     325    cxy_t      pic_cxy = GET_CXY( pic_xp );
     326    chdev_t *  pic_ptr = (chdev_t *)GET_PTR( pic_xp );
     327
     328    // get extended and local pointers on IOPIC  segment base
     329    xptr_t     seg_pic_xp  = hal_remote_lwd( XPTR( pic_cxy , &pic_ptr->base ) );
     330    cxy_t      seg_pic_cxy = GET_CXY( seg_pic_xp );
     331    uint32_t * seg_pic_ptr = (uint32_t *)GET_PTR( seg_pic_xp );
     332
     333    // get local pointer on XCU segment base
     334    uint32_t * seg_xcu_ptr = soclib_pic_xcu_base();
     335
     336    // get the source chdev functionnal type, channel, and direction
     337    uint32_t func    = src_chdev->func;
     338    uint32_t channel = src_chdev->channel;
     339    bool_t   is_rx   = src_chdev->is_rx;
     340
     341    if( (func == DEV_FUNC_IOC) || (func == DEV_FUNC_NIC) ||
     342        (func == DEV_FUNC_TXT) || (func == DEV_FUNC_IOB) )          // external IRQ => WTI
     343    {
     344        // get external IRQ index
     345        uint32_t  irq_id;   
     346        if     (  func == DEV_FUNC_IOC            ) irq_id = iopic_input.ioc[channel];
     347        else if(  func == DEV_FUNC_TXT            ) irq_id = iopic_input.txt[channel];
     348        else if( (func == DEV_FUNC_NIC) &&  is_rx ) irq_id = iopic_input.nic_rx[channel];
     349        else if( (func == DEV_FUNC_NIC) && !is_rx ) irq_id = iopic_input.nic_tx[channel];
     350        else if(  func == DEV_FUNC_IOB            ) irq_id = iopic_input.iob;
     351        else      assert( false , __FUNCTION__ , "illegal device functionnal type\n");
     352
     353        // get a WTI mailbox from local XCU descriptor 
     354        uint32_t wti_id = soclib_pic_wti_alloc();
     355
     356        // register IRQ type and index in chdev
     357        src_chdev->irq_type = SOCLIB_TYPE_WTI;
     358        src_chdev->irq_id   = wti_id;
     359
     360        // compute extended pointer on WTI mailbox in local XCU
     361        xptr_t wti_xp = XPTR( local_cxy , &seg_xcu_ptr[(XCU_WTI_REG << 5) | wti_id] );
     362
     363            // set the IOPIC_ADDRESS and IOPIC_EXTEND registers in IOPIC
     364        uint32_t lsb_wdata = (uint32_t)wti_xp;
     365        uint32_t msb_wdata = (uint32_t)(wti_xp >> 32);
     366        xptr_t   lsb_xp = XPTR( seg_pic_cxy , seg_pic_ptr+irq_id*IOPIC_SPAN+IOPIC_ADDRESS );
     367        xptr_t   msb_xp = XPTR( seg_pic_cxy , seg_pic_ptr+irq_id*IOPIC_SPAN+IOPIC_EXTEND );
     368        hal_remote_sw( lsb_xp , lsb_wdata );
     369        hal_remote_sw( msb_xp , msb_wdata );
     370
     371        // unmask IRQ in IOPIC
     372        hal_remote_sw( XPTR( seg_pic_cxy , seg_pic_ptr+irq_id*IOPIC_SPAN+IOPIC_MASK ), 1 );
     373
     374        // update the WTI interrupt vector for core[lid]
     375        core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
     376        ((soclib_pic_core_t *)core->pic_extend)->wti_vector[wti_id] = src_chdev;
     377    }
     378    else if( (func == DEV_FUNC_DMA) || (func == DEV_FUNC_MMC) )   // internal IRQ => HWI
     379    {
     380        // get internal IRQ index
     381        uint32_t hwi_id;
     382        if( func == DEV_FUNC_DMA ) hwi_id = lapic_input.dma[channel];
     383        else                       hwi_id = lapic_input.mmc;
     384
     385        // register IRQ type and index in chdev
     386        src_chdev->irq_type = SOCLIB_TYPE_HWI;
     387        src_chdev->irq_id   = hwi_id;
     388
     389        // update the HWI interrupt vector for core[lid]
     390        core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
     391        ((soclib_pic_core_t *)core->pic_extend)->wti_vector[hwi_id] = src_chdev;
     392    }
     393    else
     394    {
     395        assert( false , __FUNCTION__ , "illegal device functionnal type\n" );
     396    }
     397}  // end soclib_pic_bind_irq();
     398
     399//////////////////////////////////////////
     400void soclib_pic_enable_irq( lid_t     lid,
     401                            chdev_t * src_chdev )
     402{
     403    // get local pointer on XCU segment base
     404    uint32_t * seg_xcu_ptr = soclib_pic_xcu_base();
     405
     406    // get the source chdev IRQ type and index
     407    uint32_t irq_type = src_chdev->irq_type;
     408    uint32_t irq_id   = src_chdev->irq_id;
     409
     410    if( irq_type == SOCLIB_TYPE_HWI )
     411    {
     412         // enable this HWI in local XCU controller
     413        seg_xcu_ptr[(XCU_MSK_HWI_ENABLE << 5) | lid] = 1 << irq_id;
     414    }
     415    else if( irq_type == SOCLIB_TYPE_WTI )
     416    {
     417         // enable this WTI in local XCU controller
     418        seg_xcu_ptr[(XCU_MSK_WTI_ENABLE << 5) | lid] = 1 << irq_id;
     419    }
     420    else
     421    {
     422        assert( false , __FUNCTION__ , "illegal IRQ type\n" );
     423    }
     424} // end soclib_pic_enable_irq()
     425
     426///////////////////////////////////////////
     427void soclib_pic_disable_irq( lid_t     lid,
     428                             chdev_t * src_chdev )
     429{
     430    // get local pointer on XCU segment base
     431    uint32_t * seg_xcu_ptr = soclib_pic_xcu_base();
     432
     433    // get the source chdev IRQ type and index
     434    uint32_t irq_type = src_chdev->irq_type;
     435    uint32_t irq_id   = src_chdev->irq_id;
     436
     437    if( irq_type == SOCLIB_TYPE_HWI )
     438    {
     439         // disable this HWI in local XCU controller
     440        seg_xcu_ptr[(XCU_MSK_HWI_DISABLE << 5) | lid] = 1 << irq_id;
     441    }
     442    else if( irq_type == SOCLIB_TYPE_WTI )
     443    {
     444         // disable this WTI in local XCU controller
     445        seg_xcu_ptr[(XCU_MSK_WTI_DISABLE << 5) | lid] = 1 << irq_id;
     446    }
     447    else
     448    {
     449        assert( false , __FUNCTION__ , "illegal IRQ type\n" );
     450    }
     451} // end soclib_pic_enable_irq()
     452
     453///////////////////////////////////////////////
     454void soclib_pic_enable_timer( uint32_t period )
     455{
     456    // calling core local index
     457    lid_t  lid = CURRENT_CORE->lid;
     458
     459    // get XCU segment base
     460    uint32_t * base = soclib_pic_xcu_base();
     461
     462    // set period value in XCU
     463    base[(XCU_PTI_PER << 5) | lid] = period;
     464
     465    // enable the PTI in local XCU controller
     466    base[(XCU_MSK_PTI_ENABLE << 5) | lid] = 1 << lid;
    45467}
    46468
    47 ////////////////////////////////////////////
    48 void soclib_pic_bind_irq( xptr_t     dev_xp,
    49                           uint32_t   irq_id,
    50                           xptr_t     xp_wti )
    51 {
    52     // get PIC device descriptor cluster and local pointer
    53     cxy_t     dev_cxy = GET_CXY( dev_xp );
    54     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    55 
    56     // get extended pointer on PIC segment base from PIC device descriptor
    57     xptr_t seg_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );
    58 
    59     // get PIC controller segment cluster and local pointer
    60     cxy_t      seg_cxy = (cxy_t)GET_CXY( seg_xp);
    61     uint32_t * seg_ptr = (uint32_t *)GET_PTR( seg_xp );
    62 
    63     uint32_t lsb = (uint32_t)xp_wti;
    64     uint32_t msb  = (uint32_t)(xp_wti>>32);
    65 
    66     // set the IOPIC_ADDRESS and IOPIC_EXTEND registers
    67     hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_ADDRESS ) , lsb );
    68     hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_EXTEND  ) , msb );
    69 
    70     // set IOPIC_MASK register
    71     hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_MASK    ) , 1   );
     469///////////////////////////////////////
     470void soclib_pic_send_ipi( cxy_t    cxy,
     471                          lid_t    lid )
     472{
     473    // get pointer on local XCU segment base
     474    uint32_t * base = soclib_pic_xcu_base();
     475
     476    // write to WTI mailbox[cxy][lid]
     477    hal_remote_sw( XPTR( cxy , &base[(XCU_WTI_REG << 5) | lid] ) , 0 );
    72478}
    73479
    74 //////////////////////////////////////////////
    75 void soclib_pic_unbind_irq( xptr_t     dev_xp,
    76                             uint32_t   irq_id )
    77 {
    78     // get PIC device descriptor cluster and local pointer
    79     cxy_t     dev_cxy = GET_CXY( dev_xp );
    80     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    81 
    82     // get extended pointer on PIC segment base from PIC device descriptor
    83     xptr_t seg_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );
    84 
    85     // get PIC controller segment cluster and local pointer
    86     cxy_t      seg_cxy = (cxy_t)GET_CXY( seg_xp);
    87     uint32_t * seg_ptr = (uint32_t *)GET_PTR( seg_xp );
    88 
    89     // set IOPIC_MASK register
    90     hal_remote_sw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_MASK    ) , 0   );
    91 }
    92 
    93 //////////////////////////////////////////////
    94 void soclib_pic_get_status( xptr_t     dev_xp,
    95                             uint32_t   irq_id,
    96                             uint32_t * status)
    97 {
    98     // get PIC device descriptor cluster and local pointer
    99     cxy_t     dev_cxy = GET_CXY( dev_xp );
    100     chdev_t * dev_ptr = (chdev_t *)GET_PTR( dev_xp );
    101 
    102     // get extended pointer on PIC segment base from PIC device descriptor
    103     xptr_t seg_xp = (xptr_t)hal_remote_lwd( XPTR( dev_cxy , &dev_ptr->base ) );
    104 
    105     // get PIC controller segment cluster and local pointer
    106     cxy_t      seg_cxy = (cxy_t)GET_CXY( seg_xp);
    107     uint32_t * seg_ptr = (uint32_t *)GET_PTR( seg_xp );
    108 
    109     // return status
    110     *status = hal_remote_lw( XPTR( seg_cxy , seg_ptr+irq_id*IOPIC_SPAN+IOPIC_STATUS ) );
    111 }
    112 
     480
     481
  • trunk/hal/tsar_mips32/drivers/soclib_pic.h

    r75 r188  
    22 * soclib_pic.c - soclib PIC driver definition.
    33 *
    4  * Author  Alain Greiner (2016)
     4 * Author  Alain Greiner (2016,2017)
    55 *
    66 * Copyright (c) UPMC Sorbonne Universites
     
    2222 */
    2323
    24 #ifndef _SOCLIB_IOPIC_H_
    25 #define _SOCLIB_IOPIC_H_
     24#ifndef _SOCLIB_PIC_H_
     25#define _SOCLIB_PIC_H_
    2626
    2727#include <hal_types.h>
    2828
    29 /******************************************************************************************
    30  *  PIC register offsets (per input IRQ)
    31  *****************************************************************************************/
    32 
    33 #define IOPIC_ADDRESS           0
    34 #define IOPIC_EXTEND            1
    35 #define IOPIC_STATUS            2
    36 #define IOPIC_MASK              3
    37 #define IOPIC_SPAN              4
    38 
    39 /******************************************************************************************
    40  * This blocking function desactivates all input IRQs in PIC controler.
    41  * It must be called by a local thread.
    42  ******************************************************************************************
     29/****  Forward declarations  ****/
     30
     31struct chdev_s;
     32
     33/*****************************************************************************************
     34 * This file defines the driver for the SOCLIB PIC device.
     35 *
     36 * The SOCLIB PIC infrastructure contains two types of components:
     37 *
     38 * - The IOPIC external controller handles the external IRQs generated by the external
     39 *   peripherals. The IOPIC controller provides two services:
     40 *   1) It translate each IRQ hardware signal to a write transactions to a specific
     41 *      mailbox, for a given core in a giveb cluster, as explained below.
     42 *   2) It  allows the kernel to selectively enable/disable any external IRQ
     43 *      identified by its index.
     44 *
     45 * - The XCU internal controller implement the generic local interrupt controller
     46 *   (LAPIC), replicated in all clusters containing at  least one core.
     47 *   In each cluster, it concentrates all IRQs destinated to one given core,
     48 *   and helps the interrupt handler to select the ISR (Interrupt Service Routine)
     49 *   that must be executed by the target core. It defines three types of IRQs:
     50 *   1) HWI : The HardWare Interrupts are generated by local internal peripherals.
     51 *      They are connected to the local XCU, to be routed to a given local core.
     52 *   2) WTI : The Write Triggered Interrupts are actually mailboxes implemented in the
     53 *      local XCU. They are used to implement software IPIs (Inter-Processor-Interrupts),
     54 *      or to register the write transactions generated by the IOPIC controller.
     55 *   3) PTI : The Programmable Timer Interrupts are actually timers generating periodic
     56 *      interrupts controled by softare, contained in the local XCU, and routed to
     57 *      a local core.
     58 *   The numbers of interrupts of each type in a given cluster are defined in the
     59 *   XCU_CONFIG register of the XCU component, and cannot be larger than the
     60 *   SOCLIB_MAX_HWI, SOCLIB_MAX_WTI, SOCLIB_MAX_PTI constants defined below.
     61 *   The XCU controller provides three main services:
     62 *   1) It allows the kernel to selectively enable/disable any IRQ (identified by its type
     63 *      and index) for a given core. It is the kernel responsibility to enable a given IRQ
     64 *      for a single core as a given IRQ event should be handled by only one core.
     65 *   2) It makes a global OR between all enabled IRQs for a given core, to interrupt
     66 *      the core when at least one enabled IRQ is active.
     67 *   3) It is capable to return the highest priority active IRQ of each type.
     68 *      For each type, the lowest index have the highest priority.
     69 *
     70 * To select the ISR to be executed for a given HWI or WTI interrupt, the SOCLIB PIC
     71 * infrastructure implements for each core two interrupts vectors, called hwi_vector[]
     72 * and wti_vector[].  Each entry contains a pointer on the local chdev descriptor that
     73 * is the "source" of the interrupt, and contains itself a link to the ISR to be executed.
     74 * These interrupt vectors are stored in the core descriptor extension.
     75 * For the PTI interrupts, there is one PTI per core, and the ISR is simply defined
     76 * by the soclib_pic_timer_isr() function.
     77 *
     78 * There is no specific chdev to describe the current state of a given XCU controller.
     79 * To store the informations attached to a given XCU (namely the WTI allocator), the
     80 * SOCLIB PIC implementation attach a specific PIC extension to the cluster manager,
     81 * called XCU descriptor.
     82 *****************************************************************************************/
     83
     84#define SOCLIB_TYPE_HWI        0
     85#define SOCLIB_TYPE_WTI        1
     86#define SOCLIB_TYPE_PTI        2
     87
     88#define SOCLIB_MAX_HWI         16
     89#define SOCLIB_MAX_WTI         16
     90#define SOCLIB_MAX_PTI         16
     91
     92/******************************************************************************************
     93 * This define the registers offsets for the  external SOCLIB_IOPIC component.
     94 * There is 4 addressable registers for each external input IRQ.
     95 *****************************************************************************************/
     96
     97#define IOPIC_ADDRESS          0
     98#define IOPIC_EXTEND           1
     99#define IOPIC_STATUS           2
     100#define IOPIC_MASK             3
     101
     102#define IOPIC_SPAN             4
     103
     104/******************************************************************************************
     105 * This define the registers offsets for the internal SOCLIB_XCU components.
     106 * There is an XCU component in each cluster.
     107 *****************************************************************************************/
     108
     109#define XCU_WTI_REG            0
     110#define XCU_PTI_PER            1
     111#define XCU_PTI_VAL            2
     112#define XCU_PTI_ACK            3
     113#define XCU_MSK_PTI            4
     114#define XCU_MSK_PTI_ENABLE     5
     115#define XCU_MSK_PTI_DISABLE    6
     116#define XCU_PTI_ACTIVE         6
     117#define XCU_MSK_HWI            8
     118#define XCU_MSK_HWI_ENABLE     9
     119#define XCU_MSK_HWI_DISABLE    10
     120#define XCU_HWI_ACTIVE         10
     121#define XCU_MSK_WTI            12
     122#define XCU_MSK_WTI_ENABLE     13
     123#define XCU_MSK_WTI_DISABLE    14
     124#define XCU_WTI_ACTIVE         14
     125#define XCU_PRIO               15
     126#define XCU_CONFIG             16
     127
     128/******************************************************************************************
     129 * This structure defines the core descriptor extension used by the SOCLIB PIC
     130 * implementation to store the two HWI / WTI interrupts vectors in the core descriptor.
     131 * Each entry contains a local pointer on the chdev that is the source of the IRQ.
     132 * A non allocated entry contains the NULL value.
     133 *****************************************************************************************/
     134
     135typedef struct soclib_pic_core_s
     136{
     137    struct chdev_s * hwi_vector[SOCLIB_MAX_HWI];
     138    struct chdev_s * wti_vector[SOCLIB_MAX_WTI];
     139}
     140soclib_pic_core_t;
     141
     142/******************************************************************************************
     143 * This structure defines the cluster manager extension used by the SOCLIB PIC
     144 * implementation to register the local XCU base address, the number of HWI/WTI/PTI,
     145 * and the WTI allocator. The WTI allocator is very simple, because an allocated WTI
     146 * mailbox is never released.
     147 *****************************************************************************************/
     148
     149typedef struct soclib_pic_cluster_s
     150{
     151    uint32_t * xcu_base;           /*! local pointer on xcu segment base                 */
     152    uint32_t   hwi_nr;             /*! actual number of HWI inputs in XCU                */
     153    uint32_t   wti_nr;             /*! actual number of HWI inputs in XCU                */
     154    uint32_t   pti_nr;             /*! actual number of HWI inputs in XCU                */
     155    uint32_t   first_free_wti;     /*! simple allocator : first free WTI slot index      */
     156}
     157soclib_pic_cluster_t;
     158
     159
     160
     161
     162/******************************************************************************************
     163 *                      Generic PIC API
     164 *****************************************************************************************/
     165
     166/******************************************************************************************
     167 * This blocking function disables all input IRQs in the IOPIC controller, and
     168 * disables all HWIs, WTIs, and PTIs in the XCU (LAPIC) controllers, for all cores,
     169 * in all clusters.
     170 * It must be called by a thread running in the cluster containing the PIC chdev.
     171******************************************************************************************
    43172 * @ chdev    : pointer on PIC chdev descriptor.
    44173 *****************************************************************************************/
    45 void   soclib_pic_init( chdev_t * chdev );
    46 
    47 /******************************************************************************************
    48  * This blocking function returns the status for a given input IRQ in the remote
    49  * PIC controler. It can be called by any thread running on any cluster.
    50  ******************************************************************************************
    51  * @ dev_xp    : extended pointer on the PIC device descriptor.
    52  * @ irq_id    : input IRQ index.
    53  * @ status    : pointer on local buffer for returned status.
    54  *****************************************************************************************/
    55 void   soclib_pic_get_status( xptr_t     dev_xp,
    56                               uint32_t   irq_id,
    57                               uint32_t * status );
    58 
    59 /******************************************************************************************
    60  * This blocking function unmask an input IRQ in a remote PIC controler, and bind it
    61  * with a WTI mailbox, by registering the WTI mailbox extended pointer.
     174void   soclib_pic_init( chdev_t * pic );
     175
     176/*****************************************************************************************
     177 * This function allocates memory from local cluster for the SOCLIB PIC core extensions
     178 * of all cores contained in the cluster, initializes the two HWI, WTI interrupt vectors
     179 * as empty, and registers - for each core - the pointer in core descriptor.
     180 * Then it allocates memory from local cluster for the SOCLIB PIC cluster extension,
     181 * to implement the XCU WTI allocator, and registers the pointer in cluster manager.
     182 * It access the local XCU component to get actual number of HWI / WTI / PTI.
     183 *****************************************************************************************
     184 * @ xcu_base  : local pointer on XCU controller segment base.
     185 ****************************************************************************************/
     186void soclib_pic_extend_init( uint32_t * xcu_base );
     187
     188/******************************************************************************************
     189 * This function configure the PIC device to route the IRQ generated by a local chdev,
     190 * defined by the <src_chdev> argument, to a local core identified by the <lid> argument.
     191 * If the source chdev is external (IOC, TXT, NIC, IOB):
     192 * - it get a WTI mailbox from the XCU.
     193 * - it enables this WTI in XCU.
     194 * - it updates the target core WTI interrupt vector.
     195 * - it link the WTI to the relevant input IRQ in IOPIC.
     196 * If the source chdev is internal (MMC, DMA):
     197 * - it enables the HWI in XCU.
     198 * - it updates the target core HWI interrupt vector.
     199 * It must be called by a thread running in local cluster.
     200 ******************************************************************************************
     201 * @ lid        : target core local index.
     202 * @ src_chdev  : local pointer on source chdev descriptor.
     203 *****************************************************************************************/
     204void soclib_pic_bind_irq( lid_t     lid,
     205                          chdev_t * src_chdev );
     206
     207/******************************************************************************************
     208 * This function enable a HWI/WTI IRQ identified by the <src_chdev> argument,
     209 * that contains information on the IRQ type (HWI/WTI), and IRQ index.
     210 * It access the relevant XCU mask register, but does not access IOPIC.
     211 ******************************************************************************************
     212 * @ lid        : target core local index.
     213 * @ src_chdev  : local pointer on source chdev descriptor.
     214 *****************************************************************************************/
     215void soclib_pic_enable_irq( lid_t     lid,
     216                            chdev_t * src_chdev );
     217
     218/******************************************************************************************
     219 * This function disable a HWI/WTI IRQ identified by the <src_chdev> argument,
     220 * that contains information on the IRQ type (HWI/WTI), and IRQ index.
     221 * It access the relevant XCU mask register, but does not access IOPIC.
     222 ******************************************************************************************
     223 * @ lid        : target core local index.
     224 * @ src_chdev  : local pointer on source chdev descriptor.
     225 *****************************************************************************************/
     226void soclib_pic_disable_irq( lid_t     lid,
     227                             chdev_t * src_chdev );
     228
     229/******************************************************************************************
     230 * This function activates the TICK timer for the calling core.
     231 * The <period> argument define the number of cycles between IRQs.
     232 ******************************************************************************************
     233 * @ period      : number of cycles between IRQs.
     234 *****************************************************************************************/
     235void soclib_pic_enable_timer( uint32_t period );
     236
     237/******************************************************************************************
     238 * This function allows the calling thread to send an IPI to any core in any cluster.
    62239 * It can be called by any thread running on any cluster.
    63240 ******************************************************************************************
    64  * @ dev_xp    : extended pointer on the PIC device descriptor.
    65  * @ irq_id    : input IRQ index.
    66  * @ xp_wti    : extended pointer on the WTI mailbox.
    67  *****************************************************************************************/
    68 void   soclib_pic_bind_irq( xptr_t    dev_xp,
    69                             uint32_t  irq_id,
    70                             xptr_t    wti_xp );
    71 
    72 /******************************************************************************************
    73  * This blocking function mask an input IRQ in a remote PIC controler.
    74  * It can be called by any thread running on any cluster.
    75  ******************************************************************************************
    76  * @ dev_xp    : extended pointer on the PIC device descriptor.
    77  * @ irq_id    : input IRQ index.
    78  *****************************************************************************************/
    79 void   soclib_pic_unbind_irq( xptr_t    dev_xp,
    80                               uint32_t  irq_id );
    81 
    82 
    83 #endif  /* _SOCLIB_IOPIC_H_ */
     241 * @ cxy        : target core cluster.
     242 * @ lid        : target core local index.
     243 *****************************************************************************************/
     244void soclib_pic_send_ipi( cxy_t    cxy,
     245                          lid_t    lid );
     246
     247
     248
     249
     250
     251
     252/******************************************************************************************
     253 *                    Private PIC API for TSAR.
     254 *****************************************************************************************/
     255
     256/******************************************************************************************
     257 * This function returns the first free WTI mailbox from the XCU descriptor.
     258 * cluster extension containing the current XCU state. It does not access the
     259 * hardware XCU component. This WTI allocator is very simple, because an allocated
     260 * WTI is never released. The first WTIs are preallocated for IPI (wpi_id == lid).
     261 * This allocator does not use a lock, because there is no risk of concurrent access.
     262 * If there is no free slot, it means that the total number of external IRQs is too
     263 * large for the number of cores in the architecture, and the core goes to sleep.
     264 *****************************************************************************************/
     265uint32_t soclib_pic_wti_alloc();
     266
     267/******************************************************************************************
     268 * This function returns a local pointer on the local XCU base segment.
     269 *****************************************************************************************/
     270uint32_t * soclib_pic_xcu_base();
     271
     272/******************************************************************************************
     273 * This function acknowledge a PTI IRQ generated by the local XCU for a core
     274 * identified by the <lid> argument.
     275 *****************************************************************************************/
     276uint32_t soclib_pic_ack_timer( lid_t lid );
     277
     278/******************************************************************************************
     279 * This function returns in the <hwi_status>, <wti_status>, <pti_status> buffers
     280 * the local XCU status for a given core identidied by the <lid> argument.
     281 *****************************************************************************************/
     282void soclib_pic_xcu_status( lid_t      lid,
     283                            uint32_t * hwi_status,
     284                            uint32_t * wti_status,
     285                            uint32_t * pti_status );
     286
     287/******************************************************************************************
     288 * This SOCLIB PIC specific is the call-back function is the interrupt handler.
     289 *****************************************************************************************/
     290void soclip_pic_irq_handler();
     291
     292
     293
     294
     295
     296
     297
     298#endif  /* _SOCLIB_PIC_H_ */
Note: See TracChangeset for help on using the changeset viewer.