/* * Functions to map and unmap memory non-cached into KVA the kernel won't try * to allocate. The goal is to provide uncached memory to busdma, to honor * BUS_DMA_COHERENT. * We can allocate at most ARM_NOCACHE_KVA_SIZE bytes. * The allocator is rather dummy, each page is represented by a bit in * a bitfield, 0 meaning the page is not allocated, 1 meaning it is. * As soon as it finds enough contiguous pages to satisfy the request, * it returns the address. */ void * arm_remap_nocache(void *addr, vm_size_t size) { int i, j; size = round_page(size); for (i = 0; i < ARM_NOCACHE_KVA_SIZE / PAGE_SIZE; i++) { if (!(arm_nocache_allocated[i / BITS_PER_INT] & (1 << (i % BITS_PER_INT)))) { for (j = i; j < i + (size / (PAGE_SIZE)); j++) if (arm_nocache_allocated[j / BITS_PER_INT] & (1 << (j % BITS_PER_INT))) break; if (j == i + (size / (PAGE_SIZE))) break; } } if (i < ARM_NOCACHE_KVA_SIZE / PAGE_SIZE) { vm_offset_t tomap = arm_nocache_startaddr + i * PAGE_SIZE; void *ret = (void *)tomap; vm_paddr_t physaddr = vtophys((vm_offset_t)addr); for (; tomap < (vm_offset_t)ret + size; tomap += PAGE_SIZE, physaddr += PAGE_SIZE, i++) { pmap_kenter_nocache(tomap, physaddr); arm_nocache_allocated[i / BITS_PER_INT] |= 1 << (i % BITS_PER_INT); } return (ret); } return (NULL); }
/* * Functions to map and unmap memory non-cached into KVA the kernel won't try * to allocate. The goal is to provide uncached memory to busdma, to honor * BUS_DMA_COHERENT. * We can allocate at most ARM_NOCACHE_KVA_SIZE bytes. * The allocator is rather dummy, each page is represented by a bit in * a bitfield, 0 meaning the page is not allocated, 1 meaning it is. * As soon as it finds enough contiguous pages to satisfy the request, * it returns the address. */ void * arm_remap_nocache(void *addr, vm_size_t size) { int i, j; size = round_page(size); for (i = 0; i < ARM_NOCACHE_KVA_SIZE / PAGE_SIZE; i++) { if (!(arm_nocache_allocated[i / BITS_PER_INT] & (1 << (i % BITS_PER_INT)))) { for (j = i; j < i + (size / (PAGE_SIZE)); j++) if (arm_nocache_allocated[j / BITS_PER_INT] & (1 << (j % BITS_PER_INT))) break; if (j == i + (size / (PAGE_SIZE))) break; } } if (i < ARM_NOCACHE_KVA_SIZE / PAGE_SIZE) { vm_offset_t tomap = arm_nocache_startaddr + i * PAGE_SIZE; void *ret = (void *)tomap; vm_paddr_t physaddr = vtophys((vm_offset_t)addr); vm_offset_t vaddr = (vm_offset_t) addr; vaddr = vaddr & ~PAGE_MASK; for (; tomap < (vm_offset_t)ret + size; tomap += PAGE_SIZE, vaddr += PAGE_SIZE, physaddr += PAGE_SIZE, i++) { cpu_idcache_wbinv_range(vaddr, PAGE_SIZE); #ifdef ARM_L2_PIPT cpu_l2cache_wbinv_range(physaddr, PAGE_SIZE); #else cpu_l2cache_wbinv_range(vaddr, PAGE_SIZE); #endif pmap_kenter_nocache(tomap, physaddr); cpu_tlb_flushID_SE(vaddr); arm_nocache_allocated[i / BITS_PER_INT] |= 1 << (i % BITS_PER_INT); } return (ret); } return (NULL); }
void platform_mp_start_ap(void) { uint32_t reg, *ptr, cpu_num; /* Copy boot code to SRAM */ *((unsigned int*)(0xf1020240)) = 0xffff0101; *((unsigned int*)(0xf1008500)) = 0xffff0003; pmap_kenter_nocache(0x880f0000, 0xffff0000); reg = 0x880f0000; for (ptr = (uint32_t *)mptramp; ptr < (uint32_t *)mpentry; ptr++, reg += 4) *((uint32_t *)reg) = *ptr; if (mp_ncpus > 1) { reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0); reg &= 0x00ffffff; reg |= 0x01000000; write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL0, reg); } if (mp_ncpus > 2) { reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1); reg &= 0xff00ffff; reg |= 0x00010000; write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg); } if (mp_ncpus > 3) { reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1); reg &= 0x00ffffff; reg |= 0x01000000; write_cpu_clkdiv(CPU_DIVCLK_CTRL2_RATIO_FULL1, reg); } reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0); reg |= ((0x1 << (mp_ncpus - 1)) - 1) << 21; write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg); reg = read_cpu_clkdiv(CPU_DIVCLK_CTRL0); reg |= 0x01000000; write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg); DELAY(100); reg &= ~(0xf << 21); write_cpu_clkdiv(CPU_DIVCLK_CTRL0, reg); DELAY(100); bus_space_write_4(fdtbus_bs_tag, MV_BASE, CPU_RESUME_CONTROL, 0); for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) bus_space_write_4(fdtbus_bs_tag, CPU_PMU(cpu_num), CPU_PMU_BOOT, pmap_kextract((vm_offset_t)mpentry)); cpu_idcache_wbinv_all(); for (cpu_num = 1; cpu_num < mp_ncpus; cpu_num++ ) bus_space_write_4(fdtbus_bs_tag, MP, MP_SW_RESET(cpu_num), 0); /* XXX: Temporary workaround for hangup after releasing AP's */ wmb(); DELAY(10); initialize_coherency_fabric(); }