ambapp.c

来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 360 行

C
360
字号
/* Gaisler AMBA Plug&Play bus scanning. Functions * ending on _nomem is inteded to be used only during * initialization, only registers are used (no ram). * * (C) Copyright 2007 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <command.h>#include <ambapp.h>#if defined(CONFIG_CMD_AMBAPP)extern void ambapp_print_apb(apbctrl_pp_dev * apb,			     ambapp_ahbdev * apbmst, int index);extern void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index);extern int ambapp_apb_print;extern int ambapp_ahb_print;#endifstatic int ambapp_apb_scan(unsigned int vendor,	/* Plug&Play Vendor ID */			   unsigned int driver,	/* Plug&Play Device ID */			   ambapp_apbdev * dev,	/* Result(s) is placed here */			   int index,	/* Index of device to start copying Plug&Play					 * info into dev					 */			   int max_cnt	/* Maximal count that dev can hold, if dev					 * is NULL function will stop scanning after					 * max_cnt devices are found.					 */    ){	int i, cnt = 0;	unsigned int apbmst_base;	ambapp_ahbdev apbmst;	apbctrl_pp_dev *apb;	if (max_cnt == 0)		return 0;	/* Get AMBA APB Master */	if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) {		return 0;	}	/* Get APB CTRL Plug&Play info area */	apbmst_base = apbmst.address[0] & LEON3_IO_AREA;	apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);	for (i = 0; i < LEON3_APB_SLAVES; i++) {#if defined(CONFIG_CMD_AMBAPP)		if (ambapp_apb_print && amba_vendor(apb->conf)		    && amba_device(apb->conf)) {			ambapp_print_apb(apb, &apbmst, i);		}#endif		if ((amba_vendor(apb->conf) == vendor) &&		    (amba_device(apb->conf) == driver) && ((index < 0)							   || (index-- == 0))) {			/* Convert Plug&Play info into a more readable format */			cnt++;			if (dev) {				dev->irq = amba_irq(apb->conf);				dev->ver = amba_ver(apb->conf);				dev->address =				    (apbmst_base |				     (((apb->					bar & 0xfff00000) >> 12))) & (((apb->									bar &									0x0000fff0)								       << 4) |								      0xfff00000);				dev++;			}			/* found max devices? */			if (cnt >= max_cnt)				return cnt;		}		/* Get next Plug&Play entry */		apb++;	}	return cnt;}unsigned int ambapp_apb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */				   register unsigned int driver,	/* Plug&Play Device ID */				   register int index){	register int i;	register ahbctrl_pp_dev *apbmst;	register apbctrl_pp_dev *apb;	register unsigned int apbmst_base;	/* APBMST is a AHB Slave */	apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);	if (!apbmst)		return 0;	apbmst_base = amba_membar_start(apbmst->bars[0]);	if (amba_membar_type(apbmst->bars[0]) == AMBA_TYPE_AHBIO)		apbmst_base = AMBA_TYPE_AHBIO_ADDR(apbmst_base);	apbmst_base &= LEON3_IO_AREA;	/* Find the vendor/driver device on the first APB bus */	apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);	for (i = 0; i < LEON3_APB_SLAVES; i++) {		if ((amba_vendor(apb->conf) == vendor) &&		    (amba_device(apb->conf) == driver) && ((index < 0)							   || (index-- == 0))) {			/* Convert Plug&Play info info a more readable format */			return (apbmst_base | (((apb->bar & 0xfff00000) >> 12)))			    & (((apb->bar & 0x0000fff0) << 4) | 0xfff00000);		}		/* Get next Plug&Play entry */		apb++;	}	return 0;}/****************************** APB SLAVES ******************************/int ambapp_apb_count(unsigned int vendor, unsigned int driver){	return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);}int ambapp_apb_first(unsigned int vendor,		     unsigned int driver, ambapp_apbdev * dev){	return ambapp_apb_scan(vendor, driver, dev, 0, 1);}int ambapp_apb_next(unsigned int vendor,		    unsigned int driver, ambapp_apbdev * dev, int index){	return ambapp_apb_scan(vendor, driver, dev, index, 1);}int ambapp_apbs_first(unsigned int vendor,		      unsigned int driver, ambapp_apbdev * dev, int max_cnt){	return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt);}enum {	AHB_SCAN_MASTER = 0,	AHB_SCAN_SLAVE = 1};/* Scan AMBA Plug&Play bus for AMBA AHB Masters or AHB Slaves * for a certain matching Vendor and Device ID. * * Return number of devices found. * * Compact edition... */static int ambapp_ahb_scan(unsigned int vendor,	/* Plug&Play Vendor ID */			   unsigned int driver,	/* Plug&Play Device ID */			   ambapp_ahbdev * dev,	/* Result(s) is placed here */			   int index,	/* Index of device to start copying Plug&Play					 * info into dev					 */			   int max_cnt,	/* Maximal count that dev can hold, if dev					 * is NULL function will stop scanning after					 * max_cnt devices are found.					 */			   int type	/* Selectes what type of devices to scan.					 * 0=AHB Masters					 * 1=AHB Slaves					 */    ){	int i, j, cnt = 0, max_pp_devs;	unsigned int addr;	ahbctrl_info *info = (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);	ahbctrl_pp_dev *ahb;	if (max_cnt == 0)		return 0;	if (type == 0) {		max_pp_devs = LEON3_AHB_MASTERS;		ahb = info->masters;	} else {		max_pp_devs = LEON3_AHB_SLAVES;		ahb = info->slaves;	}	for (i = 0; i < max_pp_devs; i++) {#if defined(CONFIG_CMD_AMBAPP)		if (ambapp_ahb_print && amba_vendor(ahb->conf) &&		    amba_device(ahb->conf)) {			ambapp_print_ahb(ahb, i);		}#endif		if ((amba_vendor(ahb->conf) == vendor) &&		    (amba_device(ahb->conf) == driver) &&		    ((index < 0) || (index-- == 0))) {			/* Convert Plug&Play info info a more readable format */			cnt++;			if (dev) {				dev->irq = amba_irq(ahb->conf);				dev->ver = amba_ver(ahb->conf);				dev->userdef[0] = ahb->userdef[0];				dev->userdef[1] = ahb->userdef[1];				dev->userdef[2] = ahb->userdef[2];				for (j = 0; j < 4; j++) {					addr = amba_membar_start(ahb->bars[j]);					if (amba_membar_type(ahb->bars[j]) ==					    AMBA_TYPE_AHBIO)						addr =						    AMBA_TYPE_AHBIO_ADDR(addr);					dev->address[j] = addr;				}				dev++;			}			/* found max devices? */			if (cnt >= max_cnt)				return cnt;		}		/* Get next Plug&Play entry */		ahb++;	}	return cnt;}unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info){	register unsigned int ret;	if (!ahb)		return 0;	switch (info) {	default:		info = 0;	case 0:	case 1:	case 2:	case 3:		/* Get Address from PnP Info */		ret = amba_membar_start(ahb->bars[info]);		if (amba_membar_type(ahb->bars[info]) == AMBA_TYPE_AHBIO)			ret = AMBA_TYPE_AHBIO_ADDR(ret);		return ret;	}	return 0;}ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */				      register unsigned int driver,	/* Plug&Play Device ID */				      register unsigned int opts,	/* 1=slave, 0=master */				      register int index){	register ahbctrl_pp_dev *ahb;	register ahbctrl_info *info =	    (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);	register int i;	register int max_pp_devs;	if (opts == 0) {		max_pp_devs = LEON3_AHB_MASTERS;		ahb = info->masters;	} else {		max_pp_devs = LEON3_AHB_SLAVES;		ahb = info->slaves;	}	for (i = 0; i < max_pp_devs; i++) {		if ((amba_vendor(ahb->conf) == vendor) &&		    (amba_device(ahb->conf) == driver) &&		    ((index < 0) || (index-- == 0))) {			/* Convert Plug&Play info info a more readable format */			return ahb;		}		/* Get next Plug&Play entry */		ahb++;	}	return 0;}/****************************** AHB MASTERS ******************************/int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver){	/* Get number of devices of this vendor&device ID */	return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_MASTERS,			       AHB_SCAN_MASTER);}int ambapp_ahbmst_first(unsigned int vendor, unsigned int driver,			ambapp_ahbdev * dev){	/* find first device of this */	return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_MASTER);}int ambapp_ahbmst_next(unsigned int vendor,		       unsigned int driver, ambapp_ahbdev * dev, int index){	/* find first device of this */	return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_MASTER);}int ambapp_ahbmsts_first(unsigned int vendor,			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt){	/* find first device of this */	return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt,			       AHB_SCAN_MASTER);}/****************************** AHB SLAVES ******************************/int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver){	/* Get number of devices of this vendor&device ID */	return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_SLAVES,			       AHB_SCAN_SLAVE);}int ambapp_ahbslv_first(unsigned int vendor, unsigned int driver,			ambapp_ahbdev * dev){	/* find first device of this */	return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_SLAVE);}int ambapp_ahbslv_next(unsigned int vendor,		       unsigned int driver, ambapp_ahbdev * dev, int index){	/* find first device of this */	return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_SLAVE);}int ambapp_ahbslvs_first(unsigned int vendor,			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt){	/* find first device of this */	return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, AHB_SCAN_SLAVE);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?