source: trunk/hal/tsar_mips32/drivers/soclib_pic.c @ 635

Last change on this file since 635 was 635, checked in by alain, 5 years ago

This version is a major evolution: The physical memory allocators,
defined in the kmem.c, ppm.c, and kcm.c files have been modified
to support remote accesses. The RPCs that were previously user
to allocate physical memory in a remote cluster have been removed.
This has been done to cure a dead-lock in case of concurrent page-faults.

This version 2.2 has been tested on a (4 clusters / 2 cores per cluster)
TSAR architecture, for both the "sort" and the "fft" applications.

File size: 20.6 KB
RevLine 
[75]1/*
2 * soclib_pic.c - soclib PIC driver implementation.
3 *
[635]4 * Author  Alain Greiner (2016,2017,2018,2019)
[141]5 *
[75]6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
[141]10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
[75]11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
[141]14 * ALMOS-MKH is distributed in the hope that it will be useful, but
[75]15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
[141]20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
[75]21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[451]24#include <hal_kernel_types.h>
[75]25#include <chdev.h>
26#include <soclib_pic.h>
27#include <errno.h>
28#include <string.h>
[635]29#include <bits.h>
[75]30#include <vfs.h>
[296]31#include <rpc.h>
[188]32#include <cluster.h>
33#include <printk.h>
34#include <core.h>
35#include <thread.h>
[75]36
[188]37//////////////////////////////////////////////////////////////////////////////////////
38//         Extern variables
39//////////////////////////////////////////////////////////////////////////////////////
40
41extern  chdev_directory_t chdev_dir;    // defined in chdev.h / allocated in kerneL-init.c
42
43extern  iopic_input_t  iopic_input;  // defined in dev_pic.h / allocated in kernel_init.c
44extern  lapic_input_t  lapic_input;  // defined in dev_pic.h / allocated in kernel_init.c
45 
[407]46
47
[188]48//////////////////////////////////////////////////////////////////////////////////////
49//        SOCLIB PIC private functions
50//////////////////////////////////////////////////////////////////////////////////////
51
[570]52/////////////////////////////////////
[481]53uint32_t soclib_pic_wti_alloc( void )
[188]54{
55    uint32_t index;
56
57    // get pointer on cluster extension for SOCLIB PIC (XCU descriptor)
58    soclib_pic_cluster_t * ext_ptr = LOCAL_CLUSTER->pic_extend;
59
[492]60    assert( (ext_ptr->first_free_wti < ext_ptr->wti_nr) ,
[188]61            "no free WTI found : too much external IRQs\n");
62
63    // update WTI allocator
64    index = ext_ptr->first_free_wti;
65    ext_ptr->first_free_wti++;
66
67    return index;
68
69}  // end soclib_pic_wti_alloc()
70
[570]71/////////////////////////////////////////////
[481]72inline uint32_t * soclib_pic_xcu_base( void )
[188]73{
[205]74    return ((soclib_pic_cluster_t *)(LOCAL_CLUSTER->pic_extend))->xcu_base;
75}
[188]76
[205]77/////////////////////////////////////////////////////////
78inline uint32_t * soclib_pic_remote_xcu_base( cxy_t cxy )
79{
80    soclib_pic_cluster_t * extend;
[188]81
[205]82    // get extended pointer on PIC extension in remote cluster
83    extend = hal_remote_lpt( XPTR( cxy , &cluster_manager.pic_extend ) );
[188]84
[205]85        return (uint32_t *)hal_remote_lpt( XPTR( cxy , &extend->xcu_base ) );
86                 
87}
88
[188]89///////////////////////////////////////////
90void soclib_pic_xcu_status( lid_t      lid,
91                            uint32_t * hwi_status,
92                            uint32_t * wti_status,
93                            uint32_t * pti_status )
94{
95    // get local XCU segment base
96        uint32_t * base = soclib_pic_xcu_base();
97
98    // read PRIO register
[432]99    // in TSAR : XCU output [4*lid] is connected to core [lid]
100        uint32_t prio = base[ (XCU_PRIO << 5) | (lid<<2) ];
[188]101
102    *wti_status = (prio & 0x4) ? (((prio >> 24) & 0x1F) + 1) : 0;
103    *hwi_status = (prio & 0x2) ? (((prio >> 16) & 0x1F) + 1) : 0;
104    *pti_status = (prio & 0x1) ? (((prio >>  8) & 0x1F) + 1) : 0;
105
106}
107
[279]108////////////////////////////////////////////////////
109inline uint32_t soclib_pic_xcu_ack( uint32_t * reg )
110{
111    return *reg;
112}
113
[570]114///////////////////////////////////
[481]115void soclib_pic_irq_handler( void )
[188]116{
117    uint32_t   hwi_status;   // HWI index + 1  / no pending HWI if 0
118    uint32_t   wti_status;   // WTI index + 1  / no pending WTI if 0
119    uint32_t   pti_status;   // PTI index + 1  / no pending PTI if 0
120    chdev_t  * src_chdev;    // pointer on source chdev descriptor
[279]121    uint32_t   index;        // WTI / HWI / PTI index
[188]122
[406]123    uint32_t * xcu_base = soclib_pic_xcu_base();
[188]124
[406]125    core_t   * core = CURRENT_THREAD->core;
126
[188]127    // get XCU status
128    soclib_pic_xcu_status( core->lid,
129                           &hwi_status,
130                           &wti_status,
131                           &pti_status );
132
[438]133#if DEBUG_HAL_IRQS
[435]134uint32_t cycle = (uint32_t)hal_get_cycles();
[438]135if (DEBUG_HAL_IRQS < cycle )
[435]136printk("\n[DBG] %s : core[%x,%d] enter / WTI = %x / HWI = %x / PTI = %x / cycle %d\n",
137__FUNCTION__ , local_cxy , core->lid , wti_status , hwi_status , pti_status, cycle );
138#endif
[279]139
[457]140    // analyse status and handle up to 3 pending IRQs (one WTI, one HWI, one PTI)
[188]141
142    if( wti_status )          // pending WTI
143        {
144        index = wti_status - 1;
145
[438]146        ////////////////////////////////////////////////////////
[188]147        if( index < LOCAL_CLUSTER->cores_nr )   // it is an IPI
148        {
[492]149            assert( (index == core->lid) , "illegal IPI index" );
[188]150
[438]151#if DEBUG_HAL_IRQS
152if (DEBUG_HAL_IRQS < cycle )
[457]153printk("\n[DBG] %s : core[%x,%d] handling IPI\n", __FUNCTION__ , local_cxy , core->lid );
[435]154#endif
[438]155            // acknowledge IRQ (this require an XCU read)
[406]156            uint32_t   ack  = xcu_base[(XCU_WTI_REG << 5) | core->lid];
[438]157
[296]158            // check RPC FIFO,  and activate or create a RPC thread
[629]159            // condition is always true, but we use the ack value
160            // to avoid a GCC warning
[570]161            if( ack + 1 ) sched_yield("IPI received");
[188]162        }
[438]163        ////////////////////////////////////////////////////////////////
164        else                                    // it is an external IRQ
[188]165        {
166            // get pointer on source chdev
167            src_chdev = ((soclib_pic_core_t *)core->pic_extend)->wti_vector[index];
168
169                    if( src_chdev == NULL )        // strange, but not fatal
170                    {
171                printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n",
172                       __FUNCTION__ , index , core->lid , local_cxy );
173
174                    core->spurious_irqs ++;
175
[279]176                // disable WTI in local XCU controller
[438]177                xcu_base[(XCU_MSK_WTI_DISABLE << 5) | core->lid] = 1 << core->lid;
178
179                hal_fence();
[188]180            }
181            else                                 // call relevant ISR
182            {
183
[438]184#if DEBUG_HAL_IRQS
185if (DEBUG_HAL_IRQS < cycle )
[457]186printk("\n[DBG] %s : core[%x,%d] handling external WTI %d\n",
[435]187__FUNCTION__ , local_cxy , core->lid , index );
188#endif
[188]189                // call ISR
190                    src_chdev->isr( src_chdev );
191            }
192        }
193        }
194
[438]195    /////////////////////////////////////////////////////////////
196        if( hwi_status )                     // It is an Internal IRQ
[188]197        {
198        index = hwi_status - 1;
199
200        // get pointer on source chdev
201        src_chdev = ((soclib_pic_core_t *)core->pic_extend)->hwi_vector[index];
202
203                if( src_chdev == NULL )        // strange, but not fatal
[629]204                {
[188]205            printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n",
206                   __FUNCTION__ , index , core->lid , local_cxy );
207
208                core->spurious_irqs ++;
209
[279]210            // disable HWI in local XCU controller
[406]211            xcu_base[(XCU_MSK_HWI_DISABLE << 5) | core->lid] = 1 << core->lid;
[438]212
213            hal_fence();
[188]214                }
215        else                    // call relevant ISR
216        {
217
[438]218#if DEBUG_HAL_IRQS
219if (DEBUG_HAL_IRQS < cycle )
[457]220printk("\n[DBG] %s : core[%x,%d] handling HWI %d\n",
[435]221__FUNCTION__ , local_cxy , core->lid , index );
222#endif
[188]223            // call ISR
224                    src_chdev->isr( src_chdev );
225        }
226        }
[438]227    ///////////////////////////////////////////////////////
228    if( pti_status )                   // It is a Timer IRQ
[188]229        {
230        index = pti_status - 1;
231
[492]232        assert( (index == core->lid) , "unconsistent PTI index\n");
[188]233
[438]234#if DEBUG_HAL_IRQS
235if (DEBUG_HAL_IRQS < cycle )
[457]236printk("\n[DBG] %s : core[%x,%d] handling PTI %d\n",
[435]237__FUNCTION__ , core->lid , local_cxy , index );
238#endif
[438]239        // acknowledge IRQ (this require a read access to XCU)
[406]240        uint32_t   ack  = xcu_base[(XCU_PTI_ACK << 5) | core->lid];
[188]241
[279]242        // execute all actions related to TICK event
[457]243        // condition is always true, but we use the ack value
244        // to avoid a GCC warning
[406]245        if( ack + 1 ) core_clock( core );
[188]246        }
247}  // end soclib_pic_irq_handler()
248
249
250
251
252//////////////////////////////////////////////////////////////////////////////////////
253//         SOCLIC PIC device  generic API
254//////////////////////////////////////////////////////////////////////////////////////
255
256/////////////////////////////////////
257void soclib_pic_init( chdev_t * pic )
258{
259    uint32_t    i;      // for loop on IOPIC inputs
260
261    // get IOPIC controller cluster and segment base pointer
[451]262    cxy_t      iopic_seg_cxy = GET_CXY( pic->base );
263    uint32_t * iopic_seg_ptr = GET_PTR( pic->base );
[188]264
[407]265    // reset the IOPIC component registers : disable all input IRQs
[188]266    for( i = 0 ; i < CONFIG_MAX_EXTERNAL_IRQS ; i++ )
267    {
268        xptr_t iopic_seg_xp = XPTR( iopic_seg_cxy,
269                                    iopic_seg_ptr + i*IOPIC_SPAN + IOPIC_MASK ); 
[570]270        hal_remote_s32( iopic_seg_xp , 0 ); 
[188]271    }
272
273}  // end soclib_pic_init()
274
275//////////////////////////////////////////////////
276void soclib_pic_extend_init( uint32_t * xcu_base )
277{
278    soclib_pic_cluster_t * cluster_ext_ptr;   
279    soclib_pic_core_t    * core_ext_ptr;
280    kmem_req_t             req;
281    uint32_t               lid;
282    uint32_t               idx;
283
284    cluster_t            * cluster = LOCAL_CLUSTER;
285
286    // create core extension for all cores in cluster
287    for( lid = 0 ; lid < cluster->cores_nr ; lid++ )
288    {
289        // allocate memory for core extension
[635]290        req.type     = KMEM_KCM;
291        req.order    = bits_log2( sizeof(soclib_pic_core_t) );
[188]292        req.flags    = AF_KERNEL;
293        core_ext_ptr = kmem_alloc( &req );
294
[635]295        if( core_ext_ptr == NULL )
296        {
297            printk("\n[PANIC] in %s : cannot allocate memory for core extension\n",
298            __FUNCTION__ );
299        }
[188]300   
301        // reset the HWI / WTI  interrupt vectors
302        for( idx = 0 ; idx < SOCLIB_MAX_HWI ; idx++ ) core_ext_ptr->hwi_vector[idx] = NULL;
303        for( idx = 0 ; idx < SOCLIB_MAX_WTI ; idx++ ) core_ext_ptr->wti_vector[idx] = NULL;
304
305        // register PIC extension in core descriptor
306        cluster->core_tbl[lid].pic_extend = core_ext_ptr;
307    }
308
309    // allocate memory for cluster extension
[635]310    req.type        = KMEM_KCM;
311    req.order       = bits_log2( sizeof(soclib_pic_cluster_t) );
[188]312    req.flags       = AF_KERNEL;
313    cluster_ext_ptr = kmem_alloc( &req );
314
[635]315    if( cluster_ext_ptr == NULL )
316    {
317        printk("\n[PANIC] in %s : cannot allocate memory for cluster extension\n",
318        __FUNCTION__ );
319    }
320   
321assert( (cluster_ext_ptr != NULL) , "cannot allocate memory for cluster extension");
[188]322
323    // get XCU characteristics from the XCU config register
324    uint32_t  config = xcu_base[XCU_CONFIG<<5];
325    uint32_t  wti_nr = (config >> 16) & 0xFF; 
326    uint32_t  hwi_nr = (config >> 8 ) & 0xFF; 
327    uint32_t  pti_nr = (config      ) & 0xFF; 
328
329    // initialize the cluster extension
330    // The first WTI slots are for IPIs (one slot per core)
331    cluster_ext_ptr->xcu_base       = xcu_base;
332    cluster_ext_ptr->hwi_nr         = hwi_nr;
333    cluster_ext_ptr->wti_nr         = wti_nr;
334    cluster_ext_ptr->pti_nr         = pti_nr;
335    cluster_ext_ptr->first_free_wti = cluster->cores_nr;
336
337    // register PIC extension in cluster manager
338    cluster->pic_extend = cluster_ext_ptr;
339
[451]340    // reset the XCU component registers
341    // mask all HWIs, all WTIs, and all PTIs, for all cores in local cluster   
342    for( lid = 0 ; lid < cluster->cores_nr ; lid++ )
343    {
344        xcu_base[XCU_MSK_HWI_DISABLE << 5 | lid] = 0xFFFFFFFF;
345        xcu_base[XCU_MSK_WTI_DISABLE << 5 | lid] = 0xFFFFFFFF;
346        xcu_base[XCU_MSK_PTI_DISABLE << 5 | lid] = 0xFFFFFFFF;
347    }
348
[188]349}  // end soclib_pic_extend_init()
350
[75]351////////////////////////////////////////
[188]352void soclib_pic_bind_irq( lid_t     lid,
353                          chdev_t * src_chdev )
[75]354{
[435]355
[438]356#if DEBUG_HAL_IRQS
[435]357uint32_t cycle = (uint32_t)hal_get_cycles();
[438]358if( DEBUG_HAL_IRQS < cycle )
[435]359printk("\n[DBG] %s : thread %x enter for core[%x,%d] / cycle %d\n",
360__FUNCTION__ , CURRENT_THREAD , local_cxy , lid , cycle );
361#endif
362
[188]363    // get extended & local pointers on PIC chdev descriptor
364    xptr_t     pic_xp  = chdev_dir.pic;
365    cxy_t      pic_cxy = GET_CXY( pic_xp );
366    chdev_t *  pic_ptr = (chdev_t *)GET_PTR( pic_xp );
[75]367
[188]368    // get extended and local pointers on IOPIC  segment base
[570]369    xptr_t     seg_pic_xp  = hal_remote_l64( XPTR( pic_cxy , &pic_ptr->base ) );
[188]370    cxy_t      seg_pic_cxy = GET_CXY( seg_pic_xp );
371    uint32_t * seg_pic_ptr = (uint32_t *)GET_PTR( seg_pic_xp );
372
373    // get local pointer on XCU segment base
374    uint32_t * seg_xcu_ptr = soclib_pic_xcu_base();
375
376    // get the source chdev functionnal type, channel, and direction
377    uint32_t func    = src_chdev->func;
[534]378    uint32_t impl    = src_chdev->impl;
[188]379    uint32_t channel = src_chdev->channel;
380    bool_t   is_rx   = src_chdev->is_rx;
381
[550]382    if( (func == DEV_FUNC_IOC && impl == IMPL_IOC_BDV) || (func == DEV_FUNC_NIC) ||
[534]383        (func == DEV_FUNC_TXT && impl == IMPL_TXT_TTY) || (func == DEV_FUNC_IOB) )          // external IRQ => WTI
[75]384    {
[188]385        // get external IRQ index
[407]386        uint32_t  hwi_id;   
387        if     (  func == DEV_FUNC_IOC            ) hwi_id = iopic_input.ioc[channel];
388        else if(  func == DEV_FUNC_TXT  &&  is_rx ) hwi_id = iopic_input.txt_rx[channel];
389        else if(  func == DEV_FUNC_TXT  && !is_rx ) hwi_id = iopic_input.txt_tx[channel];
390        else if( (func == DEV_FUNC_NIC) &&  is_rx ) hwi_id = iopic_input.nic_rx[channel];
391        else if( (func == DEV_FUNC_NIC) && !is_rx ) hwi_id = iopic_input.nic_tx[channel];
392        else if(  func == DEV_FUNC_IOB            ) hwi_id = iopic_input.iob;
[492]393        else      assert( false , "illegal device functionnal type\n");
[188]394
395        // get a WTI mailbox from local XCU descriptor 
396        uint32_t wti_id = soclib_pic_wti_alloc();
397
398        // register IRQ type and index in chdev
399        src_chdev->irq_type = SOCLIB_TYPE_WTI;
400        src_chdev->irq_id   = wti_id;
401
402        // compute extended pointer on WTI mailbox in local XCU
403        xptr_t wti_xp = XPTR( local_cxy , &seg_xcu_ptr[(XCU_WTI_REG << 5) | wti_id] );
404
405            // set the IOPIC_ADDRESS and IOPIC_EXTEND registers in IOPIC
406        uint32_t lsb_wdata = (uint32_t)wti_xp;
407        uint32_t msb_wdata = (uint32_t)(wti_xp >> 32);
[407]408        xptr_t   lsb_xp = XPTR( seg_pic_cxy , seg_pic_ptr+hwi_id*IOPIC_SPAN+IOPIC_ADDRESS );
409        xptr_t   msb_xp = XPTR( seg_pic_cxy , seg_pic_ptr+hwi_id*IOPIC_SPAN+IOPIC_EXTEND );
[570]410        hal_remote_s32( lsb_xp , lsb_wdata );
411        hal_remote_s32( msb_xp , msb_wdata );
[188]412
[407]413        // enable IRQ in IOPIC
[570]414        hal_remote_s32( XPTR( seg_pic_cxy , seg_pic_ptr+hwi_id*IOPIC_SPAN+IOPIC_MASK ), 1 );
[188]415
416        // update the WTI interrupt vector for core[lid]
417        core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
418        ((soclib_pic_core_t *)core->pic_extend)->wti_vector[wti_id] = src_chdev;
[407]419
[438]420#if DEBUG_HAL_IRQS
421if( DEBUG_HAL_IRQS < cycle )
[435]422printk("\n[DBG] %s : %s / channel = %d / rx = %d / hwi_id = %d / wti_id = %d / cluster = %x\n",
[407]423__FUNCTION__ , chdev_func_str( func ) , channel , is_rx , hwi_id , wti_id , local_cxy );
[435]424#endif
[407]425
[75]426    }
[534]427    else if( (func == DEV_FUNC_DMA) || (func == DEV_FUNC_MMC) ||
[550]428             (func == DEV_FUNC_TXT && impl == IMPL_TXT_MTY) ||
429             (func == DEV_FUNC_IOC && impl == IMPL_IOC_SPI) )   // internal IRQ => HWI
[188]430    {
431        // get internal IRQ index
432        uint32_t hwi_id;
433        if( func == DEV_FUNC_DMA ) hwi_id = lapic_input.dma[channel];
[534]434        else if (func == DEV_FUNC_TXT ) hwi_id = lapic_input.mtty;
[550]435        else if (func == DEV_FUNC_IOC ) hwi_id = lapic_input.sdcard;
[188]436        else                       hwi_id = lapic_input.mmc;
[75]437
[188]438        // register IRQ type and index in chdev
439        src_chdev->irq_type = SOCLIB_TYPE_HWI;
440        src_chdev->irq_id   = hwi_id;
441
442        // update the HWI interrupt vector for core[lid]
443        core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
[468]444        ((soclib_pic_core_t *)core->pic_extend)->hwi_vector[hwi_id] = src_chdev;
[407]445
[438]446#if DEBUG_HAL_IRQS
447if( DEBUG_HAL_IRQS < cycle )
[435]448printk("\n[DBG] %s : %s / channel = %d / hwi_id = %d / cluster = %x\n",
[407]449__FUNCTION__ , chdev_func_str( func ) , channel , hwi_id , local_cxy );
[435]450#endif
[407]451
[188]452    }
453    else
454    {
[492]455        assert( false , "illegal device functionnal type\n" );
[188]456    } 
457}  // end soclib_pic_bind_irq();
458
[205]459///////////////////////////////////////
460void soclib_pic_enable_irq( lid_t  lid,
461                            xptr_t src_chdev_xp )
[75]462{
[205]463    // get cluster and local pointer on remote src_chdev
464    cxy_t     src_chdev_cxy = GET_CXY( src_chdev_xp );
465    chdev_t * src_chdev_ptr = (chdev_t *)GET_PTR( src_chdev_xp );
[141]466
[205]467    // get local pointer on remote XCU segment base
468    uint32_t * seg_xcu_ptr = soclib_pic_remote_xcu_base( src_chdev_cxy );
469
[188]470    // get the source chdev IRQ type and index
[570]471    uint32_t irq_type = hal_remote_l32( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_type ) );
472    uint32_t irq_id   = hal_remote_l32( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_id ) );
[141]473
[188]474    if( irq_type == SOCLIB_TYPE_HWI )
475    {
[205]476        // enable this HWI in remote XCU controller
[432]477        // in TSAR : XCU output [4*lid] is connected to core [lid]
[570]478        hal_remote_s32( XPTR( src_chdev_cxy , 
[440]479                       &seg_xcu_ptr[ (XCU_MSK_HWI_ENABLE << 5) | (lid<<2) ] ) , (1 << irq_id) );
[188]480    }
481    else if( irq_type == SOCLIB_TYPE_WTI )
482    {
[279]483        // enable this WTI in remote XCU controller
[432]484        // in TSAR : XCU output [4*lid] is connected to core [lid]
[570]485        hal_remote_s32( XPTR( src_chdev_cxy , 
[440]486                       &seg_xcu_ptr[ (XCU_MSK_WTI_ENABLE << 5) | (lid<<2) ] ) , (1 << irq_id) );
[188]487    }
488    else
489    {
[492]490        assert( false , "illegal IRQ type\n" );
[188]491    }
492} // end soclib_pic_enable_irq()
[75]493
[205]494////////////////////////////////////////
495void soclib_pic_disable_irq( lid_t  lid,
496                             xptr_t src_chdev_xp )
[188]497{
[205]498    // get cluster and local pointer on remote src_chdev
499    cxy_t     src_chdev_cxy = GET_CXY( src_chdev_xp );
500    chdev_t * src_chdev_ptr = (chdev_t *)GET_PTR( src_chdev_xp );
[75]501
[205]502    // get local pointer on remote XCU segment base
503    uint32_t * seg_xcu_ptr = soclib_pic_remote_xcu_base( src_chdev_cxy );
504
[188]505    // get the source chdev IRQ type and index
[570]506    uint32_t irq_type = hal_remote_l32( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_type ) );
507    uint32_t irq_id   = hal_remote_l32( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_id ) );
[75]508
[188]509    if( irq_type == SOCLIB_TYPE_HWI )
510    {
[432]511        // enable this HWI in remote XCU controller
512        // in TSAR : XCU output [4*lid] is connected to core [lid]
[570]513        hal_remote_s32( XPTR( src_chdev_cxy , 
[432]514                       &seg_xcu_ptr[(XCU_MSK_HWI_DISABLE << 5) | (lid<<2) ] ) , (1 << irq_id) );
[188]515    }
516    else if( irq_type == SOCLIB_TYPE_WTI )
517    {
[279]518        // enable this WTI in remote XCU controller
[432]519        // in TSAR : XCU output [4*lid] is connected to core [lid]
[570]520        hal_remote_s32( XPTR( src_chdev_cxy , 
[440]521                       &seg_xcu_ptr[(XCU_MSK_WTI_DISABLE << 5) | (lid<<2) ] ) , (1 << irq_id) );
[188]522    }
523    else
524    {
[492]525        assert( false , "illegal IRQ type\n" );
[188]526    }
527} // end soclib_pic_enable_irq()
[75]528
[188]529///////////////////////////////////////////////
530void soclib_pic_enable_timer( uint32_t period )
[75]531{
[188]532    // calling core local index
[457]533    lid_t  lid = CURRENT_THREAD->core->lid;
[141]534
[188]535    // get XCU segment base
536    uint32_t * base = soclib_pic_xcu_base();
[141]537
[380]538    // set period value in XCU (in cycles)
[407]539    uint32_t cycles = period * SOCLIB_CYCLES_PER_MS;
[380]540    base[(XCU_PTI_PER << 5) | lid] = cycles;
[75]541
[279]542    // enable PTI in local XCU controller
[432]543    // In TSAR : XCU output [4*lid] is connected to core [lid]
544    base[ (XCU_MSK_PTI_ENABLE << 5) | (lid<<2) ] = 1 << lid;
[75]545}
546
[279]547////////////////////////////
[481]548void soclib_pic_enable_ipi( void )
[279]549{
550    // calling core local index
[457]551    lid_t  lid = CURRENT_THREAD->core->lid;
[279]552
553    // get XCU segment base
554    uint32_t * base = soclib_pic_xcu_base();
555
556    // enable WTI in local XCU controller
[432]557    // In TSAR : XCU output [4*lid] is connected to core [lid]
558    base[ (XCU_MSK_WTI_ENABLE << 5) | (lid<<2) ] = 1 << lid;
[279]559}
560
[188]561///////////////////////////////////////
562void soclib_pic_send_ipi( cxy_t    cxy,
563                          lid_t    lid )
[75]564{
[188]565    // get pointer on local XCU segment base
566    uint32_t * base = soclib_pic_xcu_base();
[141]567
[188]568    // write to WTI mailbox[cxy][lid]
[570]569    hal_remote_s32( XPTR( cxy , &base[(XCU_WTI_REG << 5) | lid ] ) , 0 );
[188]570}
[141]571
[407]572/////////////////////////
[481]573void soclib_pic_ack_ipi( void )
[407]574{
575    // get calling core local index
576    lid_t      lid  = CURRENT_THREAD->core->lid;
[75]577
[407]578    // get pointer on local XCU segment base
579    uint32_t * base = soclib_pic_xcu_base();
[75]580
[407]581    // acknowlege IPI
[432]582    uint32_t   ack  = base[ (XCU_WTI_REG << 5) | lid ];
[407]583
584    // we must make a fake use for ack value to avoid a warning
[424]585    if( (ack + 1) == 0 ) asm volatile( "nop" );
[407]586}
587   
588
Note: See TracBrowser for help on using the repository browser.