| 739 | } |
| 740 | |
| 741 | static int |
| 742 | load_fw(struct tegra_xhci_softc *sc) |
| 743 | { |
| 744 | const struct firmware *fw; |
| 745 | const struct tegra_xusb_fw_hdr *fw_hdr; |
| 746 | vm_paddr_t fw_paddr, fw_base; |
| 747 | vm_offset_t fw_vaddr; |
| 748 | vm_size_t fw_size; |
| 749 | uint32_t code_tags, code_size; |
| 750 | struct clocktime fw_clock; |
| 751 | struct timespec fw_timespec; |
| 752 | int i; |
| 753 | |
| 754 | /* Reset ARU */ |
| 755 | FPCI_WR4(sc, XUSB_CFG_ARU_RST, ARU_RST_RESET); |
| 756 | DELAY(3000); |
| 757 | |
| 758 | /* Check if FALCON already runs */ |
| 759 | if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO) != 0) { |
| 760 | device_printf(sc->dev, |
| 761 | "XUSB CPU is already loaded, CPUCTL: 0x%08X\n", |
| 762 | CSB_RD4(sc, XUSB_FALCON_CPUCTL)); |
| 763 | return (0); |
| 764 | } |
| 765 | |
| 766 | fw = firmware_get(sc->soc->fw_name); |
| 767 | if (fw == NULL) { |
| 768 | device_printf(sc->dev, "Cannot read xusb firmware\n"); |
| 769 | return (ENOENT); |
| 770 | } |
| 771 | |
| 772 | /* Allocate uncached memory and copy firmware into. */ |
| 773 | fw_hdr = (const struct tegra_xusb_fw_hdr *)fw->data; |
| 774 | fw_size = fw_hdr->fwimg_len; |
| 775 | |
| 776 | fw_vaddr = kmem_alloc_contig(fw_size, M_WAITOK, 0, -1UL, PAGE_SIZE, 0, |
| 777 | VM_MEMATTR_UNCACHEABLE); |
| 778 | fw_paddr = vtophys(fw_vaddr); |
| 779 | fw_hdr = (const struct tegra_xusb_fw_hdr *)fw_vaddr; |
| 780 | memcpy((void *)fw_vaddr, fw->data, fw_size); |
| 781 | |
| 782 | firmware_put(fw, FIRMWARE_UNLOAD); |
| 783 | sc->fw_vaddr = fw_vaddr; |
| 784 | sc->fw_size = fw_size; |
| 785 | |
| 786 | /* Setup firmware physical address and size. */ |
| 787 | fw_base = fw_paddr + sizeof(*fw_hdr); |
| 788 | CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_ATTR, fw_size); |
| 789 | CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO, fw_base & 0xFFFFFFFF); |
| 790 | CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI, (uint64_t)fw_base >> 32); |
| 791 | CSB_WR4(sc, XUSB_CSB_MEMPOOL_APMAP, APMAP_BOOTPATH); |
| 792 | |
| 793 | /* Invalidate full L2IMEM context. */ |
| 794 | CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG, |
| 795 | L2IMEMOP_INVALIDATE_ALL); |
| 796 | |
| 797 | /* Program load of L2IMEM by boot code. */ |
| 798 | code_tags = howmany(fw_hdr->boot_codetag, XUSB_CSB_IMEM_BLOCK_SIZE); |
no test coverage detected