184c7204bSMichal Simek /* 284c7204bSMichal Simek * (C) Copyright 2014 - 2015 Xilinx, Inc. 384c7204bSMichal Simek * Michal Simek <michal.simek@xilinx.com> 484c7204bSMichal Simek * 584c7204bSMichal Simek * SPDX-License-Identifier: GPL-2.0+ 684c7204bSMichal Simek */ 784c7204bSMichal Simek 884c7204bSMichal Simek #include <common.h> 984c7204bSMichal Simek #include <netdev.h> 106fe6f135SMichal Simek #include <ahci.h> 116fe6f135SMichal Simek #include <scsi.h> 120785dfd8SMichal Simek #include <asm/arch/clk.h> 1384c7204bSMichal Simek #include <asm/arch/hardware.h> 1484c7204bSMichal Simek #include <asm/arch/sys_proto.h> 1584c7204bSMichal Simek #include <asm/io.h> 1616fa00a7SSiva Durga Prasad Paladugu #include <usb.h> 1716fa00a7SSiva Durga Prasad Paladugu #include <dwc3-uboot.h> 1884c7204bSMichal Simek 1984c7204bSMichal Simek DECLARE_GLOBAL_DATA_PTR; 2084c7204bSMichal Simek 2184c7204bSMichal Simek int board_init(void) 2284c7204bSMichal Simek { 23a0736efbSMichal Simek printf("EL Level:\tEL%d\n", current_el()); 24a0736efbSMichal Simek 2584c7204bSMichal Simek return 0; 2684c7204bSMichal Simek } 2784c7204bSMichal Simek 2884c7204bSMichal Simek int board_early_init_r(void) 2984c7204bSMichal Simek { 3084c7204bSMichal Simek u32 val; 3184c7204bSMichal Simek 320785dfd8SMichal Simek if (current_el() == 3) { 3384c7204bSMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 3484c7204bSMichal Simek val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 3584c7204bSMichal Simek writel(val, &crlapb_base->timestamp_ref_ctrl); 3684c7204bSMichal Simek 370785dfd8SMichal Simek /* Program freq register in System counter */ 380785dfd8SMichal Simek writel(zynqmp_get_system_timer_freq(), 390785dfd8SMichal Simek &iou_scntr_secure->base_frequency_id_register); 400785dfd8SMichal Simek /* And enable system counter */ 410785dfd8SMichal Simek writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, 420785dfd8SMichal Simek &iou_scntr_secure->counter_control_register); 430785dfd8SMichal Simek } 4484c7204bSMichal Simek /* Program freq register in System counter and enable system counter */ 4584c7204bSMichal Simek writel(gd->cpu_clk, &iou_scntr->base_frequency_id_register); 4684c7204bSMichal Simek writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_HDBG | 4784c7204bSMichal Simek ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, 4884c7204bSMichal Simek &iou_scntr->counter_control_register); 4984c7204bSMichal Simek 5084c7204bSMichal Simek return 0; 5184c7204bSMichal Simek } 5284c7204bSMichal Simek 53*8d59d7f6SMichal Simek #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) 54*8d59d7f6SMichal Simek /* 55*8d59d7f6SMichal Simek * fdt_get_reg - Fill buffer by information from DT 56*8d59d7f6SMichal Simek */ 57*8d59d7f6SMichal Simek static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf, 58*8d59d7f6SMichal Simek const u32 *cell, int n) 59*8d59d7f6SMichal Simek { 60*8d59d7f6SMichal Simek int i = 0, b, banks; 61*8d59d7f6SMichal Simek int parent_offset = fdt_parent_offset(fdt, nodeoffset); 62*8d59d7f6SMichal Simek int address_cells = fdt_address_cells(fdt, parent_offset); 63*8d59d7f6SMichal Simek int size_cells = fdt_size_cells(fdt, parent_offset); 64*8d59d7f6SMichal Simek char *p = buf; 65*8d59d7f6SMichal Simek phys_addr_t val; 66*8d59d7f6SMichal Simek phys_size_t vals; 67*8d59d7f6SMichal Simek 68*8d59d7f6SMichal Simek debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n", 69*8d59d7f6SMichal Simek __func__, address_cells, size_cells, buf, cell); 70*8d59d7f6SMichal Simek 71*8d59d7f6SMichal Simek /* Check memory bank setup */ 72*8d59d7f6SMichal Simek banks = n % (address_cells + size_cells); 73*8d59d7f6SMichal Simek if (banks) 74*8d59d7f6SMichal Simek panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n", 75*8d59d7f6SMichal Simek n, address_cells, size_cells); 76*8d59d7f6SMichal Simek 77*8d59d7f6SMichal Simek banks = n / (address_cells + size_cells); 78*8d59d7f6SMichal Simek 79*8d59d7f6SMichal Simek for (b = 0; b < banks; b++) { 80*8d59d7f6SMichal Simek debug("%s: Bank #%d:\n", __func__, b); 81*8d59d7f6SMichal Simek if (address_cells == 2) { 82*8d59d7f6SMichal Simek val = cell[i + 1]; 83*8d59d7f6SMichal Simek val <<= 32; 84*8d59d7f6SMichal Simek val |= cell[i]; 85*8d59d7f6SMichal Simek val = fdt64_to_cpu(val); 86*8d59d7f6SMichal Simek debug("%s: addr64=%llx, ptr=%p, cell=%p\n", 87*8d59d7f6SMichal Simek __func__, val, p, &cell[i]); 88*8d59d7f6SMichal Simek *(phys_addr_t *)p = val; 89*8d59d7f6SMichal Simek } else { 90*8d59d7f6SMichal Simek debug("%s: addr32=%x, ptr=%p\n", 91*8d59d7f6SMichal Simek __func__, fdt32_to_cpu(cell[i]), p); 92*8d59d7f6SMichal Simek *(phys_addr_t *)p = fdt32_to_cpu(cell[i]); 93*8d59d7f6SMichal Simek } 94*8d59d7f6SMichal Simek p += sizeof(phys_addr_t); 95*8d59d7f6SMichal Simek i += address_cells; 96*8d59d7f6SMichal Simek 97*8d59d7f6SMichal Simek debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i, 98*8d59d7f6SMichal Simek sizeof(phys_addr_t)); 99*8d59d7f6SMichal Simek 100*8d59d7f6SMichal Simek if (size_cells == 2) { 101*8d59d7f6SMichal Simek vals = cell[i + 1]; 102*8d59d7f6SMichal Simek vals <<= 32; 103*8d59d7f6SMichal Simek vals |= cell[i]; 104*8d59d7f6SMichal Simek vals = fdt64_to_cpu(vals); 105*8d59d7f6SMichal Simek 106*8d59d7f6SMichal Simek debug("%s: size64=%llx, ptr=%p, cell=%p\n", 107*8d59d7f6SMichal Simek __func__, vals, p, &cell[i]); 108*8d59d7f6SMichal Simek *(phys_size_t *)p = vals; 109*8d59d7f6SMichal Simek } else { 110*8d59d7f6SMichal Simek debug("%s: size32=%x, ptr=%p\n", 111*8d59d7f6SMichal Simek __func__, fdt32_to_cpu(cell[i]), p); 112*8d59d7f6SMichal Simek *(phys_size_t *)p = fdt32_to_cpu(cell[i]); 113*8d59d7f6SMichal Simek } 114*8d59d7f6SMichal Simek p += sizeof(phys_size_t); 115*8d59d7f6SMichal Simek i += size_cells; 116*8d59d7f6SMichal Simek 117*8d59d7f6SMichal Simek debug("%s: ps=%p, i=%x, size=%zu\n", 118*8d59d7f6SMichal Simek __func__, p, i, sizeof(phys_size_t)); 119*8d59d7f6SMichal Simek } 120*8d59d7f6SMichal Simek 121*8d59d7f6SMichal Simek /* Return the first address size */ 122*8d59d7f6SMichal Simek return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t)); 123*8d59d7f6SMichal Simek } 124*8d59d7f6SMichal Simek 125*8d59d7f6SMichal Simek #define FDT_REG_SIZE sizeof(u32) 126*8d59d7f6SMichal Simek /* Temp location for sharing data for storing */ 127*8d59d7f6SMichal Simek /* Up to 64-bit address + 64-bit size */ 128*8d59d7f6SMichal Simek static u8 tmp[CONFIG_NR_DRAM_BANKS * 16]; 129*8d59d7f6SMichal Simek 130*8d59d7f6SMichal Simek void dram_init_banksize(void) 131*8d59d7f6SMichal Simek { 132*8d59d7f6SMichal Simek int bank; 133*8d59d7f6SMichal Simek 134*8d59d7f6SMichal Simek memcpy(&gd->bd->bi_dram[0], &tmp, sizeof(tmp)); 135*8d59d7f6SMichal Simek 136*8d59d7f6SMichal Simek for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { 137*8d59d7f6SMichal Simek debug("Bank #%d: start %llx\n", bank, 138*8d59d7f6SMichal Simek (unsigned long long)gd->bd->bi_dram[bank].start); 139*8d59d7f6SMichal Simek debug("Bank #%d: size %llx\n", bank, 140*8d59d7f6SMichal Simek (unsigned long long)gd->bd->bi_dram[bank].size); 141*8d59d7f6SMichal Simek } 142*8d59d7f6SMichal Simek } 143*8d59d7f6SMichal Simek 144*8d59d7f6SMichal Simek int dram_init(void) 145*8d59d7f6SMichal Simek { 146*8d59d7f6SMichal Simek int node, len; 147*8d59d7f6SMichal Simek const void *blob = gd->fdt_blob; 148*8d59d7f6SMichal Simek const u32 *cell; 149*8d59d7f6SMichal Simek 150*8d59d7f6SMichal Simek memset(&tmp, 0, sizeof(tmp)); 151*8d59d7f6SMichal Simek 152*8d59d7f6SMichal Simek /* find or create "/memory" node. */ 153*8d59d7f6SMichal Simek node = fdt_subnode_offset(blob, 0, "memory"); 154*8d59d7f6SMichal Simek if (node < 0) { 155*8d59d7f6SMichal Simek printf("%s: Can't get memory node\n", __func__); 156*8d59d7f6SMichal Simek return node; 157*8d59d7f6SMichal Simek } 158*8d59d7f6SMichal Simek 159*8d59d7f6SMichal Simek /* Get pointer to cells and lenght of it */ 160*8d59d7f6SMichal Simek cell = fdt_getprop(blob, node, "reg", &len); 161*8d59d7f6SMichal Simek if (!cell) { 162*8d59d7f6SMichal Simek printf("%s: Can't get reg property\n", __func__); 163*8d59d7f6SMichal Simek return -1; 164*8d59d7f6SMichal Simek } 165*8d59d7f6SMichal Simek 166*8d59d7f6SMichal Simek gd->ram_size = fdt_get_reg(blob, node, &tmp, cell, len / FDT_REG_SIZE); 167*8d59d7f6SMichal Simek 168*8d59d7f6SMichal Simek debug("%s: Initial DRAM size %llx\n", __func__, gd->ram_size); 169*8d59d7f6SMichal Simek 170*8d59d7f6SMichal Simek return 0; 171*8d59d7f6SMichal Simek } 172*8d59d7f6SMichal Simek #else 17384c7204bSMichal Simek int dram_init(void) 17484c7204bSMichal Simek { 17584c7204bSMichal Simek gd->ram_size = CONFIG_SYS_SDRAM_SIZE; 17684c7204bSMichal Simek 17784c7204bSMichal Simek return 0; 17884c7204bSMichal Simek } 179*8d59d7f6SMichal Simek #endif 18084c7204bSMichal Simek 18184c7204bSMichal Simek void reset_cpu(ulong addr) 18284c7204bSMichal Simek { 18384c7204bSMichal Simek } 18484c7204bSMichal Simek 1856fe6f135SMichal Simek #ifdef CONFIG_SCSI_AHCI_PLAT 1866fe6f135SMichal Simek void scsi_init(void) 1876fe6f135SMichal Simek { 1886fe6f135SMichal Simek ahci_init((void __iomem *)ZYNQMP_SATA_BASEADDR); 1896fe6f135SMichal Simek scsi_scan(1); 1906fe6f135SMichal Simek } 1916fe6f135SMichal Simek #endif 1926fe6f135SMichal Simek 19384c7204bSMichal Simek int board_late_init(void) 19484c7204bSMichal Simek { 19584c7204bSMichal Simek u32 reg = 0; 19684c7204bSMichal Simek u8 bootmode; 19784c7204bSMichal Simek 19884c7204bSMichal Simek reg = readl(&crlapb_base->boot_mode); 19984c7204bSMichal Simek bootmode = reg & BOOT_MODES_MASK; 20084c7204bSMichal Simek 201fb90917cSMichal Simek puts("Bootmode: "); 20284c7204bSMichal Simek switch (bootmode) { 2030a5bcc8cSSiva Durga Prasad Paladugu case JTAG_MODE: 204fb90917cSMichal Simek puts("JTAG_MODE\n"); 205fb90917cSMichal Simek setenv("modeboot", "jtagboot"); 2060a5bcc8cSSiva Durga Prasad Paladugu break; 2070a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_24BIT: 2080a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_32BIT: 2090a5bcc8cSSiva Durga Prasad Paladugu setenv("modeboot", "qspiboot"); 210fb90917cSMichal Simek puts("QSPI_MODE\n"); 2110a5bcc8cSSiva Durga Prasad Paladugu break; 21239c56f55SMichal Simek case EMMC_MODE: 21378678feeSMichal Simek puts("EMMC_MODE\n"); 21478678feeSMichal Simek setenv("modeboot", "sdboot"); 21578678feeSMichal Simek break; 21678678feeSMichal Simek case SD_MODE: 217fb90917cSMichal Simek puts("SD_MODE\n"); 21884c7204bSMichal Simek setenv("modeboot", "sdboot"); 21984c7204bSMichal Simek break; 220af813acdSMichal Simek case SD_MODE1: 221fb90917cSMichal Simek puts("SD_MODE1\n"); 2222d9925bcSMichal Simek #if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1) 2232d9925bcSMichal Simek setenv("sdbootdev", "1"); 2242d9925bcSMichal Simek #endif 2252d9925bcSMichal Simek setenv("modeboot", "sdboot"); 226af813acdSMichal Simek break; 227af813acdSMichal Simek case NAND_MODE: 228fb90917cSMichal Simek puts("NAND_MODE\n"); 229af813acdSMichal Simek setenv("modeboot", "nandboot"); 230af813acdSMichal Simek break; 23184c7204bSMichal Simek default: 23284c7204bSMichal Simek printf("Invalid Boot Mode:0x%x\n", bootmode); 23384c7204bSMichal Simek break; 23484c7204bSMichal Simek } 23584c7204bSMichal Simek 23684c7204bSMichal Simek return 0; 23784c7204bSMichal Simek } 23884696ff5SSiva Durga Prasad Paladugu 23984696ff5SSiva Durga Prasad Paladugu int checkboard(void) 24084696ff5SSiva Durga Prasad Paladugu { 2415af08556SMichal Simek puts("Board: Xilinx ZynqMP\n"); 24284696ff5SSiva Durga Prasad Paladugu return 0; 24384696ff5SSiva Durga Prasad Paladugu } 24416fa00a7SSiva Durga Prasad Paladugu 24516fa00a7SSiva Durga Prasad Paladugu #ifdef CONFIG_USB_DWC3 24616fa00a7SSiva Durga Prasad Paladugu static struct dwc3_device dwc3_device_data = { 24716fa00a7SSiva Durga Prasad Paladugu .maximum_speed = USB_SPEED_HIGH, 24816fa00a7SSiva Durga Prasad Paladugu .base = ZYNQMP_USB0_XHCI_BASEADDR, 24916fa00a7SSiva Durga Prasad Paladugu .dr_mode = USB_DR_MODE_PERIPHERAL, 25016fa00a7SSiva Durga Prasad Paladugu .index = 0, 25116fa00a7SSiva Durga Prasad Paladugu }; 25216fa00a7SSiva Durga Prasad Paladugu 25316fa00a7SSiva Durga Prasad Paladugu int usb_gadget_handle_interrupts(void) 25416fa00a7SSiva Durga Prasad Paladugu { 25516fa00a7SSiva Durga Prasad Paladugu dwc3_uboot_handle_interrupt(0); 25616fa00a7SSiva Durga Prasad Paladugu return 0; 25716fa00a7SSiva Durga Prasad Paladugu } 25816fa00a7SSiva Durga Prasad Paladugu 25916fa00a7SSiva Durga Prasad Paladugu int board_usb_init(int index, enum usb_init_type init) 26016fa00a7SSiva Durga Prasad Paladugu { 26116fa00a7SSiva Durga Prasad Paladugu return dwc3_uboot_init(&dwc3_device_data); 26216fa00a7SSiva Durga Prasad Paladugu } 26316fa00a7SSiva Durga Prasad Paladugu 26416fa00a7SSiva Durga Prasad Paladugu int board_usb_cleanup(int index, enum usb_init_type init) 26516fa00a7SSiva Durga Prasad Paladugu { 26616fa00a7SSiva Durga Prasad Paladugu dwc3_uboot_exit(index); 26716fa00a7SSiva Durga Prasad Paladugu return 0; 26816fa00a7SSiva Durga Prasad Paladugu } 26916fa00a7SSiva Durga Prasad Paladugu #endif 270