source: trunk/kernel/arch/tsar/arch_init.c @ 81

Last change on this file since 81 was 11, checked in by alain, 8 years ago

Merge all FS related files in one single vfs directory.

File size: 18.5 KB
RevLine 
[1]1/*
2 * hal_devices_init.c - Devices intialization operations for the TSAR architecture
3 *
4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012)
5 *         Mohamed Lamine Karaoui (2015)
6 *         Alain Greiner (2016)
7
8 * Copyright (c) UPMC Sorbonne Universites
9 *
10 * This file is part of ALMOS-MKH.
11 *
12 * ALMOS-MKH.is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2.0 of the License.
15 *
16 * ALMOS-MKH.is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include <config.h>
27#include <types.h>
28#include <list.h>
29#include <bits.h>
30#include <cpu.h>
31#include <system.h>
32#include <cluster.h>
[11]33#include <chdev.h>
[1]34#include <driver.h>
35#include <thread.h>
36#include <process.h>
37#include <kmem.h>
38#include <ppm.h>
39#include <pmm.h>
40#include <page.h>
41#include <kdmsg.h>
42#include <devfs.h>
43#include <drvdb.h>
44#include <boot-info.h>
45#include <soclib_xicu.h>
46#include <soclib_iopic.h>
47#define _ARCH_BIB_SIGNATURE_
48#include <arch-bib.h>
49
50#define die(args...) do {boot_dmsg(args); while(1);} while(0)
51
52#define ICU_MASK     0xFFFFFFFF  // interrupt enabled for first 32 devices
53#define KATTR     (PMM_HUGE | PMM_READ | PMM_WRITE | PMM_EXECUTE | PMM_CACHED | PMM_GLOBAL | PMM_DIRTY | PMM_ACCESSED)
54#define KDEV_ATTR (PMM_READ | PMM_WRITE | PMM_GLOBAL | PMM_DIRTY | PMM_ACCESSED)
55
56
57/*********************************************************************************************
58 * This function set the various masks for the XCU device in the local cluster.
59 * It should be executed by core[0] after the local cluster manager initialisation,
60 * and after devices initialisation. The général policy is the following:
61 * - PTI : it routes one PTI per core (with index = lid) for TICK.
62 * - WTI : it routes one WTI per core (with index = lid) for wakup.
63 * - HWI : it routes all local HWI to core[0].
64 ********************************************************************************************/
65void hal_xcu_set_mask()
66{
67    uint32_t       lid;
68        cluster_t    * cluster;    // pointer on local cluster manager
69        uint32_t       cores;      // number of cores in cluster
70    device_t     * xcu;        // pointer on local XCU device descriptor       
71    uint32_t       hwi_mask;   // HWI mask for XCU
72    uint32_t       hwi_index;  // HWI index in XCU
73    list_entry_t * iter;       // iterator to scan the device list
74    device_t     * dev;        // pointer on local device descriptor
75    dev_type_t     type;       // device type       
76
77        cluster   = LOCAL_CLUSTER;
78        cores     = cluster->cores_nr;
79    xcu       = cluster->xcu;   
80
81    // loop on all local devices to compute the hwi_mask
82    hwi_mask  = 0;
83    hwi_index = 0;
84    LIST_FOREACH( cluster->devlist , iter )
85    {
86        dev  = LIST_ELEMENT( iter , device_t , list );
87        type = dev->type;
88
89        // only replicated devices MMC and MWR generate HWI
90        if( (type == DEV_TYPE_MMC) || (type == DEV_TYPE_MWR) )
91        {
92            hwi_mask = hwi_mask |= (1<<hwi_index);
93            hwi_index++;
94        }
95    }
96
97    // set the  three XCU masks
98        for( lid = 0 ; lid < cores ; lid++ )
99        {
100        xcu_set_mask( xcu , (1<<lid) , XCU_PTI_TYPE , lid ); 
101        xcu_set_mask( xcu , (1<<lid) , XCU_WTI_TYPE , lid ); 
102        if( lid == 0 )
103        {
104            xcu_set_mask( xcu , hwi_mask , XCU_HWI_TYPE , lid ); 
105        }
106    }
107}  // end hal_xcu_set_mask()
108
109
110/*********************************************************************************************
111 * This function returns a pointer on a cluster descriptor from the drvid.
112 ********************************************************************************************/
113device_t * hal_dev_locate( list_entry_t * devlist_root,
114                           uint32_t      drvid )
115{
116        struct list_entry *iter;
117        struct device_s *dev;
118 
119        list_foreach(devlist_root, iter)
120        {
121                dev = list_element(iter, struct device_s, list);
122                if(dev->op.drvid == drvid)
123                        return dev;
124        }
125 
126        return NULL;
127}
128
129/*********************************************************************************************
130 * This function register all detected devices in given cluster.
131 ********************************************************************************************/
132void hal_dev_register( cluster_t       * cluster, 
133                                   cluster_entry_s * entry )
134{
135        device_t     * xicu;
136        list_entry_t * iter;
137        device_t     * dev;
138    cpu_t        * cpu_ptr;
139        uint32_t       cpu;
140        error_t        err;
141
142        xicu = hal_dev_locate(&entry->devlist, SOCLIB_XICU_ID);
143        dev  = hal_dev_locate(&entry->devlist, SOCLIB_DMA_ID);
144
145        hal_entrys[entry->cxy].xicu = xicu;
146        hal_entrys[entry->cxy].dma  = dev;
147 
148        if((cluster->id == entry->cxy) && (xicu == NULL))
149                die("[ERROR]\tNo XICU is found for cluster %d\n", entry->cxy);
150               
151        //only local cluster get to set the irq
152        if(cluster->id != entry->cxy)
153                return;
154
155        list_foreach((&entry->devlist), iter)
156        {
157                dev = list_element(iter, struct device_s, list);       
158
159                if((dev != xicu) && (dev->irq != -1))
160                {
161                        err = xicu->op.icu.bind(xicu, dev);
162     
163                        if(err) 
164                                die("[ERROR]\tFailed to bind device %s, irq %d, on xicu %s @%x [ err %d ]\n",
165                                    dev->name, dev->irq, xicu->name, xicu, err);
166                }
167
168        }
169               
170        if(cluster->id != entry->cxy)
171                return;
172
173        hal_xicu_set_mask(cluster, xicu);
174
175        for(cpu = 0; cpu < cluster->cpu_nr; cpu++)
176        {
177                cpu_ptr = &cluster->cpu_tbl[cpu];
178                hal_cpu_set_irq_entry(cpu_ptr, 0, &xicu->action);
179        }
180}  // end hal_dev_register()
181
182//////////////////////////////////////////////////
183void hal_dev_iopic_register( cluster_t * cluster, 
184                        struct cluster_entry_s *entry);
185
186/** HAL-ARCH CPUs & Clusters counters */
187static global_t hal_onln_cpus_nr;
188static global_t hal_cpus_per_cluster;
189static global_t hal_onln_clusters_nr;
190static global_t hal_boot_cxy_;
191
192/**/
193struct hal_entry_s hal_entrys[CLUSTER_NR];
194global_t __current_cxy;
195
196/** Return Platform CPUs Online Number */
197inline uint32_t hal_onln_cpu_nr(void)
198{
199        return hal_onln_cpus_nr.value;
200}
201
202/** Return Platform Clsuters Online Number */
203inline uint32_t hal_onln_cluster_nr(void)
204{
205        return hal_onln_clusters_nr.value;
206}
207
208inline uint32_t hal_cpu_per_cluster(void)
209{
210        return hal_cpus_per_cluster.value;
211}
212
213inline cxy_t hal_boot_cxy(void)
214{
215        return hal_boot_cxy_.value;
216}
217
218extern uint32_t cpu_gid_tbl[CPU_PER_CLUSTER] CACHELINE;
219
220inline void cpu_gid_tbl_init(struct boot_info_s *info)
221{
222        uint32_t i;
223        uint32_t cpu_nr;
224
225        cpu_nr = info->local_onln_cpu_nr;
226
227        if(CPU_PER_CLUSTER < cpu_nr)
228                while(1);//die("ERROR: This Kernel Is Compiled For only %d cpus per cluster\n", CPU_PER_CLUSTER);
229
230        for(i=0; i < cpu_nr; i++)
231                cpu_gid_tbl[i] = hal_cpu_gid(info->local_cluster_id, i); 
232}
233
234cxy_t Arch_cxy_To_Almos_cxy[CLUSTER_NR]; //address of info->hal_cxy_to_cxy array
235
236static void fill_hal_cxy_to_almos_array(struct hal_bib_header_s *header)
237{
238        int i;
239        cluster_info_t *cluster_tbl;
240
241        cluster_tbl = (cluster_info_t*)((uint32_t)header + sizeof(header_info_t));
242        assert(CLUSTER_NR >= header->onln_clstr_nr);
243
244        for(i = 0; i < header->onln_clstr_nr; i++)
245        {
246                if(cluster_tbl[i].hal_cxy >= CLUSTER_NR)
247                        continue;
248                Arch_cxy_To_Almos_cxy[cluster_tbl[i].hal_cxy] = cluster_tbl[i].cxy;
249
250        }
251}
252
253/*********************************************************************************************
254 * This function makes the kernel virtual mapping of all hardware memory banks.
255 * Initialize the boot table entries.
256 ********************************************************************************************/
257void hal_state_init( boot_info_t * info )
258{
259        struct process_s *process;
260        struct thread_s *this;
261        header_info_t *header;
262        cluster_info_t *clusters;
263        cluster_info_t *cluster_ptr;
264        dev_info_t *dev_tbl;
265        uint32_t vaddr_start;
266        uint32_t vaddr_limit;
267        uint32_t size;
268        uint32_t cxy;
269        uint32_t i;
270       
271        header = (header_info_t*) info->hal_info;
272       
273
274        clusters        = (cluster_info_t*) ((uint32_t)header + sizeof(header_info_t));
275        cluster_ptr     = &clusters[info->local_cluster_id];
276        dev_tbl         = (dev_info_t*)(cluster_ptr->offset + (uint32_t)header);
277        cxy             = cluster_ptr->cxy;
278
279        /* Global variables init */
280        hal_onln_clusters_nr.value = header->onln_clstr_nr;
281        hal_onln_cpus_nr.value     = header->onln_cpu_nr;
282        hal_cpus_per_cluster.value = header->cpu_nr;
283        hal_boot_cxy_.value         = info->boot_cluster_id;
284        __current_cxy.value = cxy;
285        fill_hal_cxy_to_almos_array(header);
286
287        //used by remote_sb->hal_cxy_...
288        for(i = 0; i < info->onln_clstr_nr; i++)
289        {
290                cluster_ptr = &clusters[i];
291                cxy = cluster_ptr->cxy;
292                hal_entrys[cxy].hal_cxy = cluster_ptr->hal_cxy;
293        }
294
295        cpu_gid_tbl_init(info);
296        kboot_tty_init(info);
297
298        size = dev_tbl[0].size;
299
300        if(size == 0)
301                die("[ERROR]\t%s: Unexpected memory size for cluster %u\n",             \
302                                __FUNCTION__, cxy);
303
304        this                         = CURRENT_THREAD;
305        process                         = this->process;
306
307        /* TODO: deal with offline clusters as well */
308        for(i = 0; i < info->onln_clstr_nr; i++)
309        {
310                cluster_ptr = &clusters[i];
311                cxy = cluster_ptr->cxy;
312   
313                if(cxy >= CLUSTER_NR)
314                {
315                        die("\n[ERROR]\t%s: This kernel version support up to %d clusters, found %d\n",         \
316                                        __FUNCTION__, CLUSTER_NR, cxy);
317                }
318
319                dev_tbl = (dev_info_t*)(cluster_ptr->offset + (uint32_t)header);
320                if(dev_tbl[0].id == SOCLIB_RAM_ID)
321                {
322                        vaddr_start     = dev_tbl[0].base;
323                        size            = dev_tbl[0].size;
324                }else
325                {
326                        vaddr_start = 0;
327                        size = 0;
328                }
329
330                if((cluster_ptr->cpu_nr != 0) && (size == 0))
331                        die("\n[ERROR]\t%s: This Kernel Version Do Not Support CPU-Only Clusters, cxy %d\n",    \
332                                        __FUNCTION__, cxy);
333
334                vaddr_limit          = vaddr_start + size;
335
336                if(cxy == info->local_cluster_id)
337                {
338                        process->vmm.limit_addr         = vaddr_limit; 
339                }
340
341
342                boot_dmsg("[INFO]\tHardware initialization of cluster %u\t\t\t\t[ %d ]\n",          \
343                                cxy, cpu_time_stamp());
344
345                cluster_entry_init(cxy, vaddr_start, size);
346        }
347}
348
349/*********************************************************************************************
350 * This function makes the architecture specific initialisation.
351 * It makes the local cluster initialisation, dynamically detects the cluster devices,
352 * and associates the appropriate drivers.
353 ********************************************************************************************/
354void hal_init( boot_info_t * info )
355{
356        cluster_t      * cluster;
357        header_info_t  * header;
358        cluster_info_t * clusters;
359        cluster_info_t * cluster_ptr;
360        dev_info_t     * dev_tbl;
361        cxy_t            iopic_cxy;     // should be the IO_cluster
362        bool_t           iopic_found;
363        error_t          error;
364        uint32_t         rcxy;
365        cxy_t            cxy;
366        uint32_t         i;
367 
368/* Local variables init
369        header = (header_info_t *)info->hal_info;
370
371        if( strncmp( header->signature , hal_bib_signature , 16 ) )
372    {
373                while(1);                       // TODO no TTY yet ??? [AG]
374    }
375        if( strncmp( header->arch , "TSAR" , 16))
376    {
377                while(1);           // TODO no TTY yet ??? [AG]
378    }
379*/
380        iopic_found = false;
381        iopic_cxy   = 0;
382        clusters    = (cluster_info_t*)((uint32_t)header + sizeof(header_info_t));
383        cluster_ptr = &clusters[info->local_cluster_id];
384        dev_tbl     = (dev_info_t*)(cluster_ptr->offset + (uint32_t)header);
385        cxy         = cluster_ptr->cxy;
386
387        hal_state_init(info);
388
389        /* init cluster: also init current_{cxy, cluster} macros */
390        error = cluster_init(info, 
391                           dev_tbl[0].base, 
392                           dev_tbl[0].base + dev_tbl[0].size,
393                           clusters_tbl[cxy].vmem_start);
394       
395        if(err)
396                die("ERROR: Failed To Initialize Cluster %d, Err %d\n", cxy, err);
397
398        cluster           = current_cluster;
399        //TODO: move it to cluster.c
400        //!!! THis value include the io_cluster !
401        cluster->clstr_nr = info->onln_clstr_nr; // TODO: headr->x_max * header->y_max;
402 
403        for(i = 0; i < info->onln_clstr_nr; i++)
404        {
405                cluster_ptr = &clusters[i];
406
407                dev_tbl     = (dev_info_t*)(cluster_ptr->offset + (uint32_t)header);
408
409                rcxy = cluster_ptr->cxy;
410
411                boot_dmsg("\n[INFO]\tDevices initialization for cluster %d\t\t\t\t[ %d ]\n",    \
412                                rcxy, cpu_time_stamp());
413
414                if(hal_dev_init(cluster, &clusters_tbl[rcxy], dev_tbl, cluster_ptr))
415                {
416                        iopic = true;
417                        iopic_cxy = rcxy;
418                }
419        }
420
421        if(iopic) //&& (cluster->io_clstr == cluster->id)) // Now it's dynamique
422                hal_dev_iopic_register(cluster, &clusters_tbl[iopic_cxy]);
423
424}  // end hal_init()
425
426
427/*********************************************************************************************
428 * This function initialises all devices descriptors associated to peripherals
429 * contained in the local cluster, as specified by the boot_info structure.
430 *********************************************************************************************
431 * @ info    : pointer on the local boot-info structure.
432 * @ returns 0 if success / returns ENOMEM or EINVAL if error
433 ********************************************************************************************/
434error_t hal_devices_init( boot_info_t * info )
435{
436        drvdb_entry_t * entry;
437        list_entry_t  * devlist;       
438
439    boot_device_t * dev_tbl;         // pointer on array of devices in boot_info
440        uint32_t        dev_nr;          // actual number of devices in this cluster
441    cluster_t     * cluster;         // pointer on local cluster manager
442        cxy_t           local_cxy;       // local cluster identifier
443    cxy-t           target_cxy;      // target cluster identifier
444        device_t      * device;          // pointer on current device descriptor
445        xptr_t          base;            // remote pointer on segment base
446        uint32_t        size;            // segment size (bytes)
447    dev_type_t      type;            // device type
448
449        uint32_t        i;
450        bool_t          pic_found;
451        driver_t      * driver;
452        error_t         error;
453 
454    // get local cluster pointer and identifier
455    cluster = LOCAL_CLUSTER;
456    cxy     = cluster->cxy;
457
458    // get number of peripherals
459        dev_nr      = info->devices_nr;
460    dev_tbl     = info->dev;
461
462    // loop on all peripherals in cluster
463        for( i = 0 ; i < dev_nr ; i++ )
464        {
465        type = dev_tbl[i].type;
466
467        // skip RAM and ROM
468                if( (type == DEV_TYPE_RAM) || (type == DEV_TYPE_ROM) ) continue;
469
470        // test PIC
471                if( dev_tbl[i].type == DEV_TYPE_PIC )  pic_found = true;
472
473        // replicated
474        if( (type == DEV_TYPE_XCU ) || (type == DEV_TYPE_MMC) || (type == DEV_TYPE_MWR) )
475        {
476                    device = device_alloc( local);
477                    if( device == NULL )
478            {
479                            printk(PANIC,"%s failed to allocate device descriptor in cluster %x\n",
480                   __FUNCTION__ , cxy );
481                return ENOMEM;
482            }
483        }
484        else
485        {
486
487                driver          = drvdb_entry_get_driver(entry);
488
489        // initialise device descriptor from boot_info
490                spinlock_init( &device->lock );
491
492        device->type    = dev_tbl[i].type;
493                device->base    = dev_tbl[i].base; 
494        device->size    = dev_tbl[i].size;
495                device->isr         = dev_tbl[i].irq;
496
497                error = driver->init( dev );
498
499                if( error )
500        {
501                        die("[ERROR]\tFailed To Initialize Device %s [Cluster %d, Dev %d, Err %d]\n",       
502                            drvdb_entry_get_name(entry), rcxy, i, err);
503        }
504
505                devfs_register( dev );
506                list_add_last( devlist , &dev->list);
507
508                boot_dmsg("[INFO]\tFound Device: %s\t\t\t\t\t\t[ %d ]\n[INFO]\t\tBase <0x%x> cxy %d Size <0x%x> Irq <%d>\t\t[ %d ]\n", \
509                          drvdb_entry_get_name(entry), cpu_time_stamp(), (uint32_t)dev_base,           \
510                          rcxy, dev_tbl[i].size, dev_tbl[i].irq, cpu_time_stamp());
511        } // end loop on peripherals
512
513        // register device descriptor in global list ???       
514        hal_dev_register( cluster , centry );  // TODO ???
515
516        return iopic_clstr;
517
518}  // end hal_devices_init()
519
520
521
522/*********************************************************************************************
523 ********************************************************************************************/
524void hal_xicu_set_wti(struct device_s *xicu, 
525                        uint32_t cpu_inter, uint32_t wti_index, 
526                        struct irq_action_s *action, 
527                        struct device_s *dev)
528{
529        uint64_t mailbox;
530        uint32_t irq_out;
531        error_t err;
532
533        mailbox = xicu->base_paddr + (wti_index << 2);
534        irq_out = cpu_inter*OUTPUT_IRQ_PER_PROC;
535
536
537        xicu->op.icu.set_mask(xicu,
538                                (1 << wti_index),
539                                XICU_MSK_WTI_ENABLE,
540                                irq_out);
541
542        boot_dmsg("[INFO]\t\t WTI %d <-> CPU %d (mailbox 0x%x%x)\t\t\t[ %d ]\n",        \
543                        wti_index, cpu_inter, MSB(mailbox), LSB(mailbox),               \
544                        cpu_time_stamp());
545
546        err = xicu->op.icu.bind_wti(xicu, action, wti_index);
547
548         
549        if(err != 0) 
550                die("[ERROR]\tFailed to bind %s via wti_mailbox 0x%x:%x , on xicu %s @%x [ err %d ]\n", \
551                        dev ? dev->name : "IPI", MSB(mailbox),LSB(mailbox), xicu->name, xicu, err); 
552         
553        if(dev)
554                dev->mailbox = mailbox;
555        //The binding is (to be) done dynamically in the peripheral
556        //iopic->op.iopic.bind_wti_and_irq(iopic, mailbox, dev->irq);
557                       
558}
559
560//TODO: distibute iopic devices on multiple cluster ?
561//For now all the devices of the IOPIC_Cluster (cluster
562//without cpus) and there IRQs are handled by the IO_Cluster.
563void hal_dev_iopic_register(struct cluster_s *cluster, 
564                        struct cluster_entry_s *entry)
565{
566        struct list_entry *iter;
567        struct device_s *iopic;
568        struct device_s *xicu;
569        struct device_s *dev;
570        uint32_t device_index;
571        uint32_t wti_index;
572        uint32_t cpu_inter;
573        uint32_t cpu_nr;
574        //error_t err;
575
576        cpu_inter = 0;
577        device_index = 0;
578        cpu_nr = cluster->cpu_nr;
579        wti_index = cpu_nr;//Leave one WTI per proc for IPI
580
581        xicu = hal_entrys[cluster->id].xicu;
582        iopic = hal_dev_locate(&entry->devlist, SOCLIB_IOPIC_ID);
583
584        if(xicu == NULL)
585                die("[ERROR]\tNo XICU Is Found for IOPIC cluster %d\n",                         \
586                                entry->cxy);
587
588        boot_dmsg("\n[INFO]\tIOPIC cluster configuration: cxy %d <0x%x,0x%x>\t[ %d ]\n",      \
589                        entry->cxy, iopic->base, (iopic->base+iopic->size), cpu_time_stamp());
590
591        list_foreach(&entry->devlist, iter)
592        {
593                dev = list_element(iter, struct device_s, list);
594
595                if(wti_index > (IOPIC_WTI_PER_CLSTR - cpu_nr))
596                        die("[ERROR]\tNo enough WTI in cluster %d\n", cluster->id);
597               
598                       
599                if((dev != iopic) && (dev->irq != -1))
600                {
601                        boot_dmsg("[INFO]\tLinking device %s to XICU on cluster %d through IOPIC cluster\t[ %d ]\n",  \
602                                        dev->name, xicu->cxy, cpu_time_stamp());
603
604                        hal_xicu_set_wti(xicu, device_index%cpu_nr, wti_index, &dev->action, dev);
605
606                        dev->iopic = iopic;
607
608                        wti_index++;
609                        device_index++;
610                }
611
612                devfs_register(dev);
613        }
614} // end hal_xcu_set_wti()
615
616
Note: See TracBrowser for help on using the repository browser.