[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 | ********************************************************************************************/ |
---|
| 65 | void 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 | ********************************************************************************************/ |
---|
| 113 | device_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 | ********************************************************************************************/ |
---|
| 132 | void 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 | ////////////////////////////////////////////////// |
---|
| 183 | void hal_dev_iopic_register( cluster_t * cluster, |
---|
| 184 | struct cluster_entry_s *entry); |
---|
| 185 | |
---|
| 186 | /** HAL-ARCH CPUs & Clusters counters */ |
---|
| 187 | static global_t hal_onln_cpus_nr; |
---|
| 188 | static global_t hal_cpus_per_cluster; |
---|
| 189 | static global_t hal_onln_clusters_nr; |
---|
| 190 | static global_t hal_boot_cxy_; |
---|
| 191 | |
---|
| 192 | /**/ |
---|
| 193 | struct hal_entry_s hal_entrys[CLUSTER_NR]; |
---|
| 194 | global_t __current_cxy; |
---|
| 195 | |
---|
| 196 | /** Return Platform CPUs Online Number */ |
---|
| 197 | inline uint32_t hal_onln_cpu_nr(void) |
---|
| 198 | { |
---|
| 199 | return hal_onln_cpus_nr.value; |
---|
| 200 | } |
---|
| 201 | |
---|
| 202 | /** Return Platform Clsuters Online Number */ |
---|
| 203 | inline uint32_t hal_onln_cluster_nr(void) |
---|
| 204 | { |
---|
| 205 | return hal_onln_clusters_nr.value; |
---|
| 206 | } |
---|
| 207 | |
---|
| 208 | inline uint32_t hal_cpu_per_cluster(void) |
---|
| 209 | { |
---|
| 210 | return hal_cpus_per_cluster.value; |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | inline cxy_t hal_boot_cxy(void) |
---|
| 214 | { |
---|
| 215 | return hal_boot_cxy_.value; |
---|
| 216 | } |
---|
| 217 | |
---|
| 218 | extern uint32_t cpu_gid_tbl[CPU_PER_CLUSTER] CACHELINE; |
---|
| 219 | |
---|
| 220 | inline 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 | |
---|
| 234 | cxy_t Arch_cxy_To_Almos_cxy[CLUSTER_NR]; //address of info->hal_cxy_to_cxy array |
---|
| 235 | |
---|
| 236 | static 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 | ********************************************************************************************/ |
---|
| 257 | void 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 | ********************************************************************************************/ |
---|
| 354 | void 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 | ********************************************************************************************/ |
---|
| 434 | error_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 | ********************************************************************************************/ |
---|
| 524 | void 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. |
---|
| 563 | void 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 | |
---|