Skip to content
Snippets Groups Projects
fpga.c 7.01 KiB
Newer Older
  • Learn to ignore specific revisions
  • Wolfgang Denk's avatar
    Wolfgang Denk committed
    /*
     * (C) Copyright 2002
     * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
     *
    
     * SPDX-License-Identifier:	GPL-2.0+
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     */
    
    
    Michal Simek's avatar
    Michal Simek committed
    /* Generic FPGA support */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #include <common.h>             /* core U-Boot definitions */
    #include <xilinx.h>             /* xilinx specific definitions */
    #include <altera.h>             /* altera specific definitions */
    
    #include <lattice.h>
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    /* Local definitions */
    #ifndef CONFIG_MAX_FPGA_DEVICES
    #define CONFIG_MAX_FPGA_DEVICES		5
    #endif
    
    /* Local static data */
    static int next_desc = FPGA_INVALID_DEVICE;
    static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES];
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fpga_no_sup
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     * 'no support' message function
     */
    
    Michal Simek's avatar
    Michal Simek committed
    static void fpga_no_sup(char *fn, char *msg)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    
    Michal Simek's avatar
    Michal Simek committed
    	if (fn && msg)
    		printf("%s: No support for %s.\n", fn, msg);
    	else if (msg)
    		printf("No support for %s.\n", msg);
    	else
    		printf("No FPGA suport!\n");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    }
    
    
    /* fpga_get_desc
     *	map a device number to a descriptor
     */
    
    Michal Simek's avatar
    Michal Simek committed
    static const fpga_desc *const fpga_get_desc(int devnum)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    
    Michal Simek's avatar
    Michal Simek committed
    	fpga_desc *desc = (fpga_desc *)NULL;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    Michal Simek's avatar
    Michal Simek committed
    	if ((devnum >= 0) && (devnum < next_desc)) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		desc = &desc_table[devnum];
    
    Michal Simek's avatar
    Michal Simek committed
    		debug("%s: found fpga descriptor #%d @ 0x%p\n",
    		      __func__, devnum, desc);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	}
    
    	return desc;
    }
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fpga_validate
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     *	generic parameter checking code
     */
    
    const fpga_desc *const fpga_validate(int devnum, const void *buf,
    				     size_t bsize, char *fn)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    
    Michal Simek's avatar
    Michal Simek committed
    	const fpga_desc *desc = fpga_get_desc(devnum);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    Michal Simek's avatar
    Michal Simek committed
    	if (!desc)
    		printf("%s: Invalid device number %d\n", fn, devnum);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    Michal Simek's avatar
    Michal Simek committed
    	if (!buf) {
    		printf("%s: Null buffer.\n", fn);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		return (fpga_desc * const)NULL;
    	}
    	return desc;
    }
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fpga_dev_info
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     *	generic multiplexing code
     */
    
    Michal Simek's avatar
    Michal Simek committed
    static int fpga_dev_info(int devnum)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    
    Michal Simek's avatar
    Michal Simek committed
    	int ret_val = FPGA_FAIL; /* assume failure */
    	const fpga_desc * const desc = fpga_get_desc(devnum);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    Michal Simek's avatar
    Michal Simek committed
    	if (desc) {
    		debug("%s: Device Descriptor @ 0x%p\n",
    		      __func__, desc->devdesc);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    Michal Simek's avatar
    Michal Simek committed
    		switch (desc->devtype) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		case fpga_xilinx:
    
    #if defined(CONFIG_FPGA_XILINX)
    
    Michal Simek's avatar
    Michal Simek committed
    			printf("Xilinx Device\nDescriptor @ 0x%p\n", desc);
    			ret_val = xilinx_info(desc->devdesc);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #else
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Xilinx devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #endif
    			break;
    		case fpga_altera:
    
    #if defined(CONFIG_FPGA_ALTERA)
    
    Michal Simek's avatar
    Michal Simek committed
    			printf("Altera Device\nDescriptor @ 0x%p\n", desc);
    			ret_val = altera_info(desc->devdesc);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #else
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Altera devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #endif
    			break;
    
    #if defined(CONFIG_FPGA_LATTICE)
    
    			printf("Lattice Device\nDescriptor @ 0x%p\n", desc);
    			ret_val = lattice_info(desc->devdesc);
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Lattice devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		default:
    
    Michal Simek's avatar
    Michal Simek committed
    			printf("%s: Invalid or unsupported device type %d\n",
    			       __func__, desc->devtype);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		}
    	} else {
    
    Michal Simek's avatar
    Michal Simek committed
    		printf("%s: Invalid device number %d\n", __func__, devnum);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	}
    
    	return ret_val;
    }
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fgpa_init is usually called from misc_init_r() and MUST be called
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     * before any of the other fpga functions are used.
     */
    
    void fpga_init(void)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    	next_desc = 0;
    
    Michal Simek's avatar
    Michal Simek committed
    	memset(desc_table, 0, sizeof(desc_table));
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    	debug("%s\n", __func__);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    }
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fpga_count
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     * Basic interface function to get the current number of devices available.
     */
    
    Michal Simek's avatar
    Michal Simek committed
    int fpga_count(void)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    	return next_desc;
    }
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fpga_add
    
     *	Add the device descriptor to the device table.
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     */
    
    Michal Simek's avatar
    Michal Simek committed
    int fpga_add(fpga_type devtype, void *desc)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    	int devnum = FPGA_INVALID_DEVICE;
    
    
    Michal Simek's avatar
    Michal Simek committed
    	if (next_desc < 0) {
    		printf("%s: FPGA support not initialized!\n", __func__);
    	} else if ((devtype > fpga_min_type) && (devtype < fpga_undefined)) {
    		if (desc) {
    			if (next_desc < CONFIG_MAX_FPGA_DEVICES) {
    
    				devnum = next_desc;
    				desc_table[next_desc].devtype = devtype;
    				desc_table[next_desc++].devdesc = desc;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    			} else {
    
    Michal Simek's avatar
    Michal Simek committed
    				printf("%s: Exceeded Max FPGA device count\n",
    				       __func__);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    			}
    		} else {
    
    Michal Simek's avatar
    Michal Simek committed
    			printf("%s: NULL device descriptor\n", __func__);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		}
    	} else {
    
    Michal Simek's avatar
    Michal Simek committed
    		printf("%s: Unsupported FPGA type %d\n", __func__, devtype);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	}
    
    	return devnum;
    }
    
    
    /*
     * Convert bitstream data and load into the fpga
     */
    
    int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size,
    			      bitstream_type bstype)
    
    {
    	printf("Bitstream support not implemented for this FPGA device\n");
    	return FPGA_FAIL;
    }
    
    
    #if defined(CONFIG_CMD_FPGA_LOADFS)
    int fpga_fsload(int devnum, const void *buf, size_t size,
    		 fpga_fs_info *fpga_fsinfo)
    {
    	int ret_val = FPGA_FAIL;           /* assume failure */
    	const fpga_desc *desc = fpga_validate(devnum, buf, size,
    					      (char *)__func__);
    
    	if (desc) {
    		switch (desc->devtype) {
    		case fpga_xilinx:
    #if defined(CONFIG_FPGA_XILINX)
    			ret_val = xilinx_loadfs(desc->devdesc, buf, size,
    						fpga_fsinfo);
    #else
    			fpga_no_sup((char *)__func__, "Xilinx devices");
    #endif
    			break;
    		default:
    			printf("%s: Invalid or unsupported device type %d\n",
    			       __func__, desc->devtype);
    		}
    	}
    
    	return ret_val;
    }
    #endif
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    /*
    
    Michal Simek's avatar
    Michal Simek committed
     * Generic multiplexing code
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     */
    
    int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    	int ret_val = FPGA_FAIL;           /* assume failure */
    
    Michal Simek's avatar
    Michal Simek committed
    	const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
    					      (char *)__func__);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    Michal Simek's avatar
    Michal Simek committed
    	if (desc) {
    		switch (desc->devtype) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		case fpga_xilinx:
    
    #if defined(CONFIG_FPGA_XILINX)
    
    			ret_val = xilinx_load(desc->devdesc, buf, bsize,
    					      bstype);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #else
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Xilinx devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #endif
    			break;
    		case fpga_altera:
    
    #if defined(CONFIG_FPGA_ALTERA)
    
    Michal Simek's avatar
    Michal Simek committed
    			ret_val = altera_load(desc->devdesc, buf, bsize);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #else
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Altera devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #endif
    			break;
    
    #if defined(CONFIG_FPGA_LATTICE)
    
    			ret_val = lattice_load(desc->devdesc, buf, bsize);
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Lattice devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		default:
    
    Michal Simek's avatar
    Michal Simek committed
    			printf("%s: Invalid or unsupported device type %d\n",
    			       __func__, desc->devtype);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		}
    	}
    
    	return ret_val;
    }
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fpga_dump
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     *	generic multiplexing code
     */
    
    int fpga_dump(int devnum, const void *buf, size_t bsize)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    	int ret_val = FPGA_FAIL;           /* assume failure */
    
    Michal Simek's avatar
    Michal Simek committed
    	const fpga_desc *desc = fpga_validate(devnum, buf, bsize,
    					      (char *)__func__);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    Michal Simek's avatar
    Michal Simek committed
    	if (desc) {
    		switch (desc->devtype) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		case fpga_xilinx:
    
    #if defined(CONFIG_FPGA_XILINX)
    
    Michal Simek's avatar
    Michal Simek committed
    			ret_val = xilinx_dump(desc->devdesc, buf, bsize);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #else
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Xilinx devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #endif
    			break;
    		case fpga_altera:
    
    #if defined(CONFIG_FPGA_ALTERA)
    
    Michal Simek's avatar
    Michal Simek committed
    			ret_val = altera_dump(desc->devdesc, buf, bsize);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #else
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Altera devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    #endif
    			break;
    
    #if defined(CONFIG_FPGA_LATTICE)
    
    			ret_val = lattice_dump(desc->devdesc, buf, bsize);
    
    Michal Simek's avatar
    Michal Simek committed
    			fpga_no_sup((char *)__func__, "Lattice devices");
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		default:
    
    Michal Simek's avatar
    Michal Simek committed
    			printf("%s: Invalid or unsupported device type %d\n",
    			       __func__, desc->devtype);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    		}
    	}
    
    	return ret_val;
    }
    
    
    Michal Simek's avatar
    Michal Simek committed
    /*
     * fpga_info
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
     *	front end to fpga_dev_info.  If devnum is invalid, report on all
     *	available devices.
     */
    
    Michal Simek's avatar
    Michal Simek committed
    int fpga_info(int devnum)
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    {
    
    Michal Simek's avatar
    Michal Simek committed
    	if (devnum == FPGA_INVALID_DEVICE) {
    		if (next_desc > 0) {
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    			int dev;
    
    
    Michal Simek's avatar
    Michal Simek committed
    			for (dev = 0; dev < next_desc; dev++)
    				fpga_dev_info(dev);
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    			return FPGA_SUCCESS;
    		} else {
    
    Michal Simek's avatar
    Michal Simek committed
    			printf("%s: No FPGA devices available.\n", __func__);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    			return FPGA_FAIL;
    		}
    	}
    
    
    Michal Simek's avatar
    Michal Simek committed
    	return fpga_dev_info(devnum);
    }