diff options
117 files changed, 12824 insertions, 1637 deletions
diff --git a/CHANGELOG-before-U-Boot-1.1.5 b/CHANGELOG-before-U-Boot-1.1.5 index 727a7b691..24041485a 100644 --- a/CHANGELOG-before-U-Boot-1.1.5 +++ b/CHANGELOG-before-U-Boot-1.1.5 @@ -438,6 +438,20 @@ Changes for U-Boot 1.1.5:  * Call serial_initialize() before first debug() is used. +* Code cleanup + +* Various USB related patches +  - Add support for mpc8xx USB device. +  - Add support for Common Device Class - Abstract Control Model USB console. +  - Add support for flow control in USB slave devices. +  - Add support for switching between gserial and cdc_acm using environment. +  - Minor changes to usbdcore_omap1510.c usbdcore_omap1510.h +  - Update usbcore slightly to ease host enumeration. +  - Fix non-portable endian problems in usbdcore and usbdcore_ep0. +  - Add AdderUSB_config as a defconfig to enable usage of the USB console +    by default with the Adder87x U-Boot port. +  Patch by Bryan O'Donoghue <bodonoghue@codehermit.ie>, 29 May 2006 +  * Cleanup trab board for GCC-4.x  * VoiceBlue update: use new MTD flash partitioning methods, use more @@ -252,6 +252,10 @@ E: Raghu.Krishnaprasad@fci.com  D: Support for Adder-II MPC852T evaluation board  W: http://www.forcecomputers.com +N: Sergey Kubushyn +E: ksi@koi8.net +D: Support for various TI DaVinci based boards. +  N: Bernhard Kuhn  E: bkuhn@metrowerks.com  D Support for Coldfire CPU; Support for Motorola M5272C3 and M5282EVB boards diff --git a/MAINTAINERS b/MAINTAINERS index 693b11572..865f6fe0e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -444,6 +444,12 @@ Nishant Kamat <nskamat@ti.com>  	omap1610h2		ARM926EJS +Sergey Kubushyn <ksi@koi8.net> + +	DV-EVM			ARM926EJS +	SONATA			ARM926EJS +	SCHMOOGIE		ARM926EJS +  Prakash Kumar <prakash@embedx.com>  	cerf250			xscale @@ -26,124 +26,281 @@ LIST=""  ## MPC5xx Systems  ######################################################################### -LIST_5xx="	\ -	cmi_mpc5xx							\ +LIST_5xx="		\ +	cmi_mpc5xx	\  "  #########################################################################  ## MPC5xxx Systems  ######################################################################### -LIST_5xxx="	\ -	BC3450		cm5200		cpci5200	EVAL5200	\ -	fo300		icecube_5100	icecube_5200	lite5200b	\ -	mcc200		mecp5200	motionpro	o2dnt		\ -	pf5200		PM520		TB5200		Total5100	\ -	Total5200	Total5200_Rev2	TQM5200		TQM5200_B	\ -	TQM5200S	v38b						\ +LIST_5xxx="		\ +	BC3450		\ +	cm5200		\ +	cpci5200	\ +	EVAL5200	\ +	fo300		\ +	icecube_5100	\ +	icecube_5200	\ +	lite5200b	\ +	mcc200		\ +	mecp5200	\ +	motionpro	\ +	o2dnt		\ +	pf5200		\ +	PM520		\ +	TB5200		\ +	Total5100	\ +	Total5200	\ +	Total5200_Rev2	\ +	TQM5200		\ +	TQM5200_B	\ +	TQM5200S	\ +	v38b		\  "  #########################################################################  ## MPC512x Systems  ######################################################################### -LIST_512x="	\ -	ads5121							\ +LIST_512x="		\ +	ads5121		\  "  #########################################################################  ## MPC8xx Systems  ######################################################################### -LIST_8xx="	\ -	Adder87x	GENIETV		MBX860T		R360MPI		\ -	AdderII		GTH		MHPC		RBC823		\ -	ADS860		hermes		MPC86xADS	rmu		\ -	AMX860		IAD210		MPC885ADS	RPXClassic	\ -	c2mon		ICU862_100MHz	MVS1		RPXlite		\ -	CCM		IP860		NETPHONE	RPXlite_DW	\ -	cogent_mpc8xx	IVML24		NETTA		RRvision	\ -	ELPT860		IVML24_128	NETTA2		SM850		\ -	EP88x		IVML24_256	NETTA_ISDN	spc1920		\ -	ESTEEM192E	IVMS8		NETVIA		SPD823TS	\ -	ETX094		IVMS8_128	NETVIA_V2	svm_sc8xx	\ -	FADS823		IVMS8_256	NX823		SXNI855T	\ -	FADS850SAR	KUP4K		pcu_e		TOP860		\ -	FADS860T	KUP4X		QS823		TQM823L		\ -	FLAGADM		LANTEC		QS850		TQM823L_LCD	\ -	FPS850L		lwmon		QS860T		TQM850L		\ -	GEN860T		MBX		quantum		TQM855L		\ -	GEN860T_SC					TQM860L		\ -							TQM885D		\ -							uc100		\ -							v37		\ +LIST_8xx="		\ +	Adder87x	\ +	AdderII		\ +	ADS860		\ +	AMX860		\ +	c2mon		\ +	CCM		\ +	cogent_mpc8xx	\ +	ELPT860		\ +	EP88x		\ +	ESTEEM192E	\ +	ETX094		\ +	FADS823		\ +	FADS850SAR	\ +	FADS860T	\ +	FLAGADM		\ +	FPS850L		\ +	GEN860T		\ +	GEN860T_SC	\ +	GENIETV		\ +	GTH		\ +	hermes		\ +	IAD210		\ +	ICU862_100MHz	\ +	IP860		\ +	IVML24		\ +	IVML24_128	\ +	IVML24_256	\ +	IVMS8		\ +	IVMS8_128	\ +	IVMS8_256	\ +	KUP4K		\ +	KUP4X		\ +	LANTEC		\ +	lwmon		\ +	MBX		\ +	MBX860T		\ +	MHPC		\ +	MPC86xADS	\ +	MPC885ADS	\ +	MVS1		\ +	NETPHONE	\ +	NETTA		\ +	NETTA2		\ +	NETTA_ISDN	\ +	NETVIA		\ +	NETVIA_V2	\ +	NX823		\ +	pcu_e		\ +	QS823		\ +	QS850		\ +	QS860T		\ +	quantum		\ +	R360MPI		\ +	RBC823		\ +	rmu		\ +	RPXClassic	\ +	RPXlite		\ +	RPXlite_DW	\ +	RRvision	\ +	SM850		\ +	spc1920		\ +	SPD823TS	\ +	svm_sc8xx	\ +	SXNI855T	\ +	TOP860		\ +	TQM823L		\ +	TQM823L_LCD	\ +	TQM850L		\ +	TQM855L		\ +	TQM860L		\ +	TQM885D		\ +	uc100		\ +	v37		\  "  #########################################################################  ## PPC4xx Systems  ######################################################################### -LIST_4xx="	\ -	acadia		acadia_nand	ADCIOP		alpr		\ -	AP1000		AR405		ASH405		bamboo		\ -	bamboo_nand	bubinga		CANBT		CMS700		\ -	CPCI2DP		CPCI405		CPCI4052	CPCI405AB	\ -	CPCI405DT	CPCI440		CPCIISER4	CRAYL1		\ -	csb272		csb472		DASA_SIM	DP405		\ -	DU405		ebony		ERIC		EXBITGEN	\ -	G2000		HH405		HUB405		JSE		\ -	KAREF		katmai		luan		lwmon5		\ -	METROBOX	MIP405		MIP405T		ML2		\ -	ml300		ocotea		OCRTC		ORSG		\ -	p3p440		PCI405		pcs440ep	PIP405		\ -	PLU405		PMC405		PPChameleonEVB	sbc405		\ -	sc3		sequoia		sequoia_nand	taishan		\ -	VOH405		VOM405		W7OLMC		W7OLMG		\ -	walnut		WUH405		XPEDITE1K	yellowstone	\ -	yosemite	yucca						\ +LIST_4xx="		\ +	acadia		\ +	acadia_nand	\ +	ADCIOP		\ +	alpr		\ +	AP1000		\ +	AR405		\ +	ASH405		\ +	bamboo		\ +	bamboo_nand	\ +	bubinga		\ +	CANBT		\ +	CMS700		\ +	CPCI2DP		\ +	CPCI405		\ +	CPCI4052	\ +	CPCI405AB	\ +	CPCI405DT	\ +	CPCI440		\ +	CPCIISER4	\ +	CRAYL1		\ +	csb272		\ +	csb472		\ +	DASA_SIM	\ +	DP405		\ +	DU405		\ +	ebony		\ +	ERIC		\ +	EXBITGEN	\ +	G2000		\ +	HH405		\ +	HUB405		\ +	JSE		\ +	KAREF		\ +	katmai		\ +	luan		\ +	lwmon5		\ +	METROBOX	\ +	MIP405		\ +	MIP405T		\ +	ML2		\ +	ml300		\ +	ocotea		\ +	OCRTC		\ +	ORSG		\ +	p3p440		\ +	PCI405		\ +	pcs440ep	\ +	PIP405		\ +	PLU405		\ +	PMC405		\ +	PPChameleonEVB	\ +	sbc405		\ +	sc3		\ +	sequoia		\ +	sequoia_nand	\ +	taishan		\ +	VOH405		\ +	VOM405		\ +	W7OLMC		\ +	W7OLMG		\ +	walnut		\ +	WUH405		\ +	XPEDITE1K	\ +	yellowstone	\ +	yosemite	\ +	yucca		\  "  #########################################################################  ## MPC8220 Systems  ######################################################################### -LIST_8220="	\ -	Alaska8220	Yukon8220					\ +LIST_8220="		\ +	Alaska8220	\ +	Yukon8220	\  "  #########################################################################  ## MPC824x Systems  ######################################################################### -LIST_824x="	\ -	A3000		barco		BMW		CPC45		\ -	CU824		debris		eXalion		HIDDEN_DRAGON	\ -			MOUSSE		MUSENKI		MVBLUE		\ -	OXC		PN62		Sandpoint8240	Sandpoint8245	\ -	sbc8240		SL8245		utx8245				\ +LIST_824x="		\ +	A3000		\ +	barco		\ +	BMW		\ +	CPC45		\ +	CU824		\ +	debris		\ +	eXalion		\ +	HIDDEN_DRAGON	\ +	MOUSSE		\ +	MUSENKI		\ +	MVBLUE		\ +	OXC		\ +	PN62		\ +	Sandpoint8240	\ +	Sandpoint8245	\ +	sbc8240		\ +	SL8245		\ +	utx8245		\  "  #########################################################################  ## MPC8260 Systems (includes 8250, 8255 etc.)  ######################################################################### -LIST_8260="	\ -	atc		cogent_mpc8260	CPU86		CPU87		\ -	ep8248		ep8260		ep82xxm		gw8260		\ -	hymod		IPHASE4539	ISPAN		MPC8260ADS	\ -	MPC8266ADS	MPC8272ADS	PM826		PM828		\ -	ppmc8260	Rattler8248	RPXsuper	rsdproto	\ -	sacsng		sbc8260		SCM		TQM8260_AC	\ -	TQM8260_AD	TQM8260_AE	ZPC1900				\ +LIST_8260="		\ +	atc		\ +	cogent_mpc8260	\ +	CPU86		\ +	CPU87		\ +	ep8248		\ +	ep8260		\ +	ep82xxm		\ +	gw8260		\ +	hymod		\ +	IPHASE4539	\ +	ISPAN		\ +	MPC8260ADS	\ +	MPC8266ADS	\ +	MPC8272ADS	\ +	PM826		\ +	PM828		\ +	ppmc8260	\ +	Rattler8248	\ +	RPXsuper	\ +	rsdproto	\ +	sacsng		\ +	sbc8260		\ +	SCM		\ +	TQM8260_AC	\ +	TQM8260_AD	\ +	TQM8260_AE	\ +	ZPC1900		\  "  #########################################################################  ## MPC83xx Systems (includes 8349, etc.)  ######################################################################### -LIST_83xx="	\ -	MPC8313ERDB_33	MPC8313ERDB_66	MPC832XEMDS	MPC8349EMDS	\ -	MPC8349ITX	MPC8349ITXGP	MPC8360EMDS	sbc8349		\ -	TQM834x								\ +LIST_83xx="		\ +	MPC8313ERDB_33	\ +	MPC8313ERDB_66	\ +	MPC832XEMDS	\ +	MPC8349EMDS	\ +	MPC8349ITX	\ +	MPC8349ITXGP	\ +	MPC8360EMDS	\ +	sbc8349		\ +	TQM834x		\  " @@ -151,123 +308,226 @@ LIST_83xx="	\  ## MPC85xx Systems (includes 8540, 8560 etc.)  ######################################################################### -LIST_85xx="	\ -	MPC8540ADS	MPC8540EVAL	MPC8541CDS	MPC8544DS	\ -	MPC8548CDS	MPC8555CDS	MPC8560ADS	MPC8568MDS	\ -	PM854		PM856		sbc8540		sbc8560		\ -	stxgp3		stxssa		TQM8540		TQM8541		\ -	TQM8555		TQM8560						\ +LIST_85xx="		\ +	MPC8540ADS	\ +	MPC8540EVAL	\ +	MPC8541CDS	\ +	MPC8544DS	\ +	MPC8548CDS	\ +	MPC8555CDS	\ +	MPC8560ADS	\ +	MPC8568MDS	\ +	PM854		\ +	PM856		\ +	sbc8540		\ +	sbc8560		\ +	stxgp3		\ +	stxssa		\ +	TQM8540		\ +	TQM8541		\ +	TQM8555		\ +	TQM8560		\  "  #########################################################################  ## MPC86xx Systems  ######################################################################### -LIST_86xx="	\ -    MPC8641HPCN	\ +LIST_86xx="		\ +	MPC8641HPCN	\  "  #########################################################################  ## 74xx/7xx Systems  ######################################################################### -LIST_74xx="	\ -	DB64360		DB64460		EVB64260	P3G4		\ -	p3m7448		PCIPPC2		PCIPPC6		ZUMA		\ -	mpc7448hpc2 +LIST_74xx="		\ +	DB64360		\ +	DB64460		\ +	EVB64260	\ +	mpc7448hpc2	\ +	P3G4		\ +	p3m7448		\ +	PCIPPC2		\ +	PCIPPC6		\ +	ZUMA		\  " -LIST_7xx="	\ -	BAB7xx		CPCI750		ELPPC		p3m750		\ -	ppmc7xx								\ +LIST_7xx="		\ +	BAB7xx		\ +	CPCI750		\ +	ELPPC		\ +	p3m750		\ +	ppmc7xx		\  " -LIST_ppc="${LIST_5xx}  ${LIST_5xxx}		\ -	  ${LIST_8xx}				\ -	  ${LIST_8220} ${LIST_824x} ${LIST_8260} \ -	  ${LIST_83xx}				\ -	  ${LIST_85xx}				\ -	  ${LIST_86xx}				\ -	  ${LIST_4xx}				\ -	  ${LIST_74xx} ${LIST_7xx}" +LIST_ppc="		\ +	${LIST_5xx}	\ +	${LIST_5xxx}	\ +	${LIST_8xx}	\ +	${LIST_8220}	\ +	${LIST_824x}	\ +	${LIST_8260}	\ +	${LIST_83xx}	\ +	${LIST_85xx}	\ +	${LIST_86xx}	\ +	${LIST_4xx}	\ +	${LIST_74xx}	\ +	${LIST_7xx}	\ +"  #########################################################################  ## StrongARM Systems  ######################################################################### -LIST_SA="assabet dnp1110 gcplus lart shannon" +LIST_SA="		\ +	assabet		\ +	dnp1110		\ +	gcplus		\ +	lart		\ +	shannon		\ +"  #########################################################################  ## ARM7 Systems  ######################################################################### -LIST_ARM7="	\ -	armadillo	B2		ep7312		evb4510		\ -	impa7		integratorap	ap7		ap720t		\ -	lpc2292sodimm	modnet50	SMN42				\ +LIST_ARM7="		\ +	ap7		\ +	ap720t		\ +	armadillo	\ +	B2		\ +	ep7312		\ +	evb4510		\ +	impa7		\ +	integratorap	\ +	lpc2292sodimm	\ +	modnet50	\ +	SMN42		\  "  #########################################################################  ## ARM9 Systems  ######################################################################### -LIST_ARM9="	\ -	at91rm9200dk	cmc_pu2						\ -	ap920t		ap922_XA10	ap926ejs	ap946es		\ -	ap966		cp920t		cp922_XA10	cp926ejs	\ -	cp946es		cp966		lpd7a400	mp2usb		\ -	mx1ads		mx1fs2		netstar		omap1510inn	\ -	omap1610h2	omap1610inn	omap730p2	sbc2410x	\ -	scb9328		smdk2400	smdk2410	trab		\ -	VCMA9		versatile	versatileab	versatilepb	\ -	voiceblue							\ +LIST_ARM9="			\ +	at91rm9200dk		\ +	cmc_pu2			\ +	ap920t			\ +	ap922_XA10		\ +	ap926ejs		\ +	ap946es			\ +	ap966			\ +	cp920t			\ +	cp922_XA10		\ +	cp926ejs		\ +	cp946es			\ +	cp966			\ +	lpd7a400		\ +	mp2usb			\ +	mx1ads			\ +	mx1fs2			\ +	netstar			\ +	omap1510inn		\ +	omap1610h2		\ +	omap1610inn		\ +	omap730p2		\ +	sbc2410x		\ +	scb9328			\ +	smdk2400		\ +	smdk2410		\ +	trab			\ +	VCMA9			\ +	versatile		\ +	versatileab		\ +	versatilepb		\ +	voiceblue		\ +	davinci_dvevm		\ +	davinci_schmoogie	\ +	davinci_sonata		\  "  #########################################################################  ## ARM10 Systems  ######################################################################### -LIST_ARM10="	\ -	integratorcp	cp1026						\ +LIST_ARM10="		\ +	integratorcp	\ +	cp1026		\  "  #########################################################################  ## ARM11 Systems  ######################################################################### -LIST_ARM11="	\ -	cp1136		omap2420h4					\ +LIST_ARM11="		\ +	cp1136		\ +	omap2420h4	\  "  #########################################################################  ## Xscale Systems  ######################################################################### -LIST_pxa="	\ -	adsvix		cerf250		cradle		csb226		\ -	delta		innokom		lubbock		pleb2		\ -	pxa255_idp	wepep250	xaeniax		xm250		\ -	xsengine	zylonite					\ +LIST_pxa="		\ +	adsvix		\ +	cerf250		\ +	cradle		\ +	csb226		\ +	delta		\ +	innokom		\ +	lubbock		\ +	pleb2		\ +	pxa255_idp	\ +	wepep250	\ +	xaeniax		\ +	xm250		\ +	xsengine	\ +	zylonite	\  " -LIST_ixp="ixdp425	ixdpg425	pdnb3		scpu" +LIST_ixp="		\ +	ixdp425		\ +	ixdpg425	\ +	pdnb3		\ +	scpu		\ +" -LIST_arm="	\ -	${LIST_SA}							\ -	${LIST_ARM7} ${LIST_ARM9} ${LIST_ARM10} ${LIST_ARM11}		\ -	${LIST_pxa} ${LIST_ixp}						\ +LIST_arm="		\ +	${LIST_SA}	\ +	${LIST_ARM7}	\ +	${LIST_ARM9}	\ +	${LIST_ARM10}	\ +	${LIST_ARM11}	\ +	${LIST_pxa}	\ +	${LIST_ixp}	\  "  #########################################################################  ## MIPS Systems		(default = big endian)  ######################################################################### -LIST_mips4kc="incaip" +LIST_mips4kc="		\ +	incaip		\ +" -LIST_mips5kc="purple" +LIST_mips5kc="		\ +	purple		\ +" -LIST_au1xx0="dbau1000 dbau1100 dbau1500 dbau1550 dbau1550_el gth2" +LIST_au1xx0="		\ +	dbau1000	\ +	dbau1100	\ +	dbau1500	\ +	dbau1550	\ +	dbau1550_el	\ +	gth2		\ +" -LIST_mips="${LIST_mips4kc} ${LIST_mips5kc} ${LIST_au1xx0}" +LIST_mips="		\ +	${LIST_mips4kc}	\ +	${LIST_mips5kc}	\ +	${LIST_au1xx0}	\ +"  #########################################################################  ## MIPS Systems		(little endian) @@ -277,36 +537,55 @@ LIST_mips4kc_el=""  LIST_mips5kc_el="" -LIST_au1xx0_el="dbau1550_el" +LIST_au1xx0_el="	\ +	dbau1550_el	\ +" -LIST_mips_el="${LIST_mips4kc_el} ${LIST_mips5kc_el} ${LIST_au1xx0_el}" +LIST_mips_el="			\ +	${LIST_mips4kc_el}	\ +	${LIST_mips5kc_el}	\ +	${LIST_au1xx0_el}	\ +"  #########################################################################  ## i386 Systems  ######################################################################### -LIST_I486="sc520_cdp sc520_spunk sc520_spunk_rel" +LIST_I486="		\ +	sc520_cdp	\ +	sc520_spunk	\ +	sc520_spunk_rel	\ +" -LIST_x86="${LIST_I486}" +LIST_x86="		\ +	${LIST_I486}	\ +"  #########################################################################  ## NIOS Systems  ######################################################################### -LIST_nios="	\ -	ADNPESC1		ADNPESC1_base_32			\ -	ADNPESC1_DNPEVA2_base_32					\ -	DK1C20			DK1C20_standard_32			\ -	DK1S10			DK1S10_standard_32 DK1S10_mtx_ldk_20	\ +LIST_nios="			\ +	ADNPESC1		\ +	ADNPESC1_base_32	\ +	ADNPESC1_DNPEVA2_base_32\ +	DK1C20			\ +	DK1C20_standard_32	\ +	DK1S10			\ +	DK1S10_standard_32	\ +	DK1S10_mtx_ldk_20	\  "  #########################################################################  ## Nios-II Systems  ######################################################################### -LIST_nios2="	\ -	EP1C20		EP1S10		EP1S40				\ -	PCI5441		PK1C20						\ +LIST_nios2="		\ +	EP1C20		\ +	EP1S10		\ +	EP1S40		\ +	PCI5441		\ +	PK1C20		\  "  ######################################################################### @@ -314,31 +593,44 @@ LIST_nios2="	\  #########################################################################  LIST_microblaze="	\ -	suzaku		ml401		xupv2p +	suzaku		\ +	ml401		\ +	xupv2p		\  "  #########################################################################  ## ColdFire Systems  ######################################################################### -LIST_coldfire="	\ -	cobra5272	EB+MCF-EV123	EB+MCF-EV123_internal		\ -	idmr		M5271EVB	M5272C3		M5282EVB	\ -	TASREG		r5200		M5271EVB			\ +LIST_coldfire="			\ +	cobra5272		\ +	EB+MCF-EV123		\ +	EB+MCF-EV123_internal	\ +	idmr			\ +	M5271EVB		\ +	M5272C3			\ +	M5282EVB		\ +	TASREG			\ +	r5200			\  "  #########################################################################  ## AVR32 Systems  ######################################################################### -LIST_avr32="atstk1002" +LIST_avr32="		\ +	atstk1002	\ +"  #########################################################################  ## Blackfin Systems  ######################################################################### -LIST_blackfin=" \ -	bf533-ezkit	bf533-stamp	bf537-stamp	bf561-ezkit	\ +LIST_blackfin="		\ +	bf533-ezkit	\ +	bf533-stamp	\ +	bf537-stamp	\ +	bf561-ezkit	\  "  #----------------------------------------------------------------------- @@ -34,6 +34,7 @@ HOSTARCH := $(shell uname -m | \  	    -e s/arm.*/arm/ \  	    -e s/sa110/arm/ \  	    -e s/powerpc/ppc/ \ +	    -e s/ppc64/ppc/ \  	    -e s/macppc/ppc/)  HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ @@ -122,7 +123,7 @@ ifeq ($(HOSTARCH),$(ARCH))  CROSS_COMPILE =  else  ifeq ($(ARCH),ppc) -CROSS_COMPILE = powerpc-linux- +CROSS_COMPILE = ppc_8xx-  endif  ifeq ($(ARCH),arm)  CROSS_COMPILE = arm-linux- @@ -657,6 +658,9 @@ AdderII_config  \  	@echo "#define CONFIG_MPC852T" > $(obj)include/config.h)  	@$(MKCONFIG) -a Adder ppc mpc8xx adder +AdderUSB_config:	unconfig +	@./mkconfig -a AdderUSB ppc mpc8xx adder +  ADS860_config     \  FADS823_config    \  FADS850SAR_config \ @@ -1662,15 +1666,18 @@ MPC8313ERDB_66_config: unconfig  	@mkdir -p $(obj)include  	@echo "" >$(obj)include/config.h ; \  	if [ "$(findstring _33_,$@)" ] ; then \ -		echo "...33M ..." ; \ +		echo -n "...33M ..." ; \  		echo "#define CFG_33MHZ" >>$(obj)include/config.h ; \  	fi ; \  	if [ "$(findstring _66_,$@)" ] ; then \ -		echo "...66M..." ; \ +		echo -n "...66M..." ; \  		echo "#define CFG_66MHZ" >>$(obj)include/config.h ; \  	fi ;  	@$(MKCONFIG) -a MPC8313ERDB ppc mpc83xx mpc8313erdb +MPC8323ERDB_config:	unconfig +	@$(MKCONFIG) -a MPC8323ERDB ppc mpc83xx mpc8323erdb freescale +  MPC832XEMDS_config \  MPC832XEMDS_HOST_33_config \  MPC832XEMDS_HOST_66_config \ @@ -1678,7 +1685,7 @@ MPC832XEMDS_SLAVE_config:	unconfig  	@mkdir -p $(obj)include  	@echo "" >$(obj)include/config.h ; \  	if [ "$(findstring _HOST_,$@)" ] ; then \ -		echo "... PCI HOST " ; \ +		echo -n "... PCI HOST " ; \  		echo "#define CONFIG_PCI" >>$(obj)include/config.h ; \  	fi ; \  	if [ "$(findstring _SLAVE_,$@)" ] ; then \ @@ -1687,11 +1694,11 @@ MPC832XEMDS_SLAVE_config:	unconfig  		echo "#define CONFIG_PCISLAVE" >>$(obj)include/config.h ; \  	fi ; \  	if [ "$(findstring _33_,$@)" ] ; then \ -		echo "...33M ..." ; \ +		echo -n "...33M ..." ; \  		echo "#define PCI_33M" >>$(obj)include/config.h ; \  	fi ; \  	if [ "$(findstring _66_,$@)" ] ; then \ -		echo "...66M..." ; \ +		echo -n "...66M..." ; \  		echo "#define PCI_66M" >>$(obj)include/config.h ; \  	fi ;  	@$(MKCONFIG) -a MPC832XEMDS ppc mpc83xx mpc832xemds @@ -1720,7 +1727,7 @@ MPC8360EMDS_SLAVE_config:	unconfig  	@mkdir -p $(obj)include  	@echo "" >$(obj)include/config.h ; \  	if [ "$(findstring _HOST_,$@)" ] ; then \ -		echo "... PCI HOST " ; \ +		echo -n "... PCI HOST " ; \  		echo "#define CONFIG_PCI" >>$(obj)include/config.h ; \  	fi ; \  	if [ "$(findstring _SLAVE_,$@)" ] ; then \ @@ -1729,11 +1736,11 @@ MPC8360EMDS_SLAVE_config:	unconfig  		echo "#define CONFIG_PCISLAVE" >>$(obj)include/config.h ; \  	fi ; \  	if [ "$(findstring _33_,$@)" ] ; then \ -		echo "...33M ..." ; \ +		echo -n "...33M ..." ; \  		echo "#define PCI_33M" >>$(obj)include/config.h ; \  	fi ; \  	if [ "$(findstring _66_,$@)" ] ; then \ -		echo "...66M..." ; \ +		echo -n "...66M..." ; \  		echo "#define PCI_66M" >>$(obj)include/config.h ; \  	fi ;  	@$(MKCONFIG) -a MPC8360EMDS ppc mpc83xx mpc8360emds @@ -2014,6 +2021,15 @@ omap1510inn_config :	unconfig  omap5912osk_config :	unconfig  	@$(MKCONFIG) $(@:_config=) arm arm926ejs omap5912osk NULL omap +davinci_dvevm_config :	unconfig +	@$(MKCONFIG) $(@:_config=) arm arm926ejs dv-evm davinci davinci + +davinci_schmoogie_config :	unconfig +	@$(MKCONFIG) $(@:_config=) arm arm926ejs schmoogie davinci davinci + +davinci_sonata_config :	unconfig +	@$(MKCONFIG) $(@:_config=) arm arm926ejs sonata davinci davinci +  omap1610inn_config \  omap1610inn_cs0boot_config \  omap1610inn_cs3boot_config \ @@ -228,113 +228,9 @@ build a config tool - later.  The following options need to be configured: -- CPU Type:	Define exactly one of +- CPU Type:	Define exactly one, e.g. CONFIG_MPC85XX. -		PowerPC based CPUs: -		------------------- -		CONFIG_MPC823,	CONFIG_MPC850,	CONFIG_MPC855,	CONFIG_MPC860 -	or	CONFIG_MPC5xx -	or	CONFIG_MPC8220 -	or	CONFIG_MPC824X, CONFIG_MPC8260 -	or	CONFIG_MPC85xx -	or	CONFIG_IOP480 -	or	CONFIG_405GP -	or	CONFIG_405EP -	or	CONFIG_440 -	or	CONFIG_MPC74xx -	or	CONFIG_750FX - -		ARM based CPUs: -		--------------- -		CONFIG_SA1110 -		CONFIG_ARM7 -		CONFIG_PXA250 -		CONFIG_CPU_MONAHANS - -		MicroBlaze based CPUs: -		---------------------- -		CONFIG_MICROBLAZE - -		Nios-2 based CPUs: -		---------------------- -		CONFIG_NIOS2 - -		AVR32 based CPUs: -		---------------------- -		CONFIG_AT32AP - -- Board Type:	Define exactly one of - -		PowerPC based boards: -		--------------------- - -		CONFIG_ADCIOP		CONFIG_FPS860L		CONFIG_OXC -		CONFIG_ADS860		CONFIG_GEN860T		CONFIG_PCI405 -		CONFIG_AMX860		CONFIG_GENIETV		CONFIG_PCIPPC2 -		CONFIG_AP1000		CONFIG_GTH		CONFIG_PCIPPC6 -		CONFIG_AR405		CONFIG_gw8260		CONFIG_pcu_e -		CONFIG_BAB7xx		CONFIG_hermes		CONFIG_PIP405 -		CONFIG_BC3450		CONFIG_hymod		CONFIG_PM826 -		CONFIG_c2mon		CONFIG_IAD210		CONFIG_ppmc8260 -		CONFIG_CANBT		CONFIG_ICU862		CONFIG_QS823 -		CONFIG_CCM		CONFIG_IP860		CONFIG_QS850 -		CONFIG_CMI		CONFIG_IPHASE4539	CONFIG_QS860T -		CONFIG_cogent_mpc8260	CONFIG_IVML24		CONFIG_RBC823 -		CONFIG_cogent_mpc8xx	CONFIG_IVML24_128	CONFIG_RPXClassic -		CONFIG_CPCI405		CONFIG_IVML24_256	CONFIG_RPXlite -		CONFIG_CPCI4052		CONFIG_IVMS8		CONFIG_RPXsuper -		CONFIG_CPCIISER4	CONFIG_IVMS8_128	CONFIG_rsdproto -		CONFIG_CPU86		CONFIG_IVMS8_256	CONFIG_sacsng -		CONFIG_CRAYL1		CONFIG_JSE		CONFIG_Sandpoint8240 -		CONFIG_CSB272		CONFIG_LANTEC		CONFIG_Sandpoint8245 -		CONFIG_CU824		CONFIG_LITE5200B	CONFIG_sbc8260 -		CONFIG_DASA_SIM		CONFIG_lwmon		CONFIG_sbc8560 -		CONFIG_DB64360		CONFIG_MBX		CONFIG_SM850 -		CONFIG_DB64460		CONFIG_MBX860T		CONFIG_SPD823TS -		CONFIG_DU405		CONFIG_MHPC		CONFIG_STXGP3 -		CONFIG_DUET_ADS		CONFIG_MIP405		CONFIG_SXNI855T -		CONFIG_EBONY		CONFIG_MOUSSE		CONFIG_TQM823L -		CONFIG_ELPPC		CONFIG_MPC8260ADS	CONFIG_TQM8260 -		CONFIG_ELPT860		CONFIG_MPC8540ADS	CONFIG_TQM850L -		CONFIG_ep8260		CONFIG_MPC8540EVAL	CONFIG_TQM855L -		CONFIG_ERIC		CONFIG_MPC8560ADS	CONFIG_TQM860L -		CONFIG_ESTEEM192E	CONFIG_MUSENKI		CONFIG_TTTech -		CONFIG_ETX094		CONFIG_MVS1		CONFIG_UTX8245 -		CONFIG_EVB64260		CONFIG_NETPHONE		CONFIG_V37 -		CONFIG_FADS823		CONFIG_NETTA		CONFIG_W7OLMC -		CONFIG_FADS850SAR	CONFIG_NETVIA		CONFIG_W7OLMG -		CONFIG_FADS860T		CONFIG_NX823		CONFIG_WALNUT -		CONFIG_FLAGADM		CONFIG_OCRTC		CONFIG_ZPC1900 -		CONFIG_FPS850L		CONFIG_ORSG		CONFIG_ZUMA - -		ARM based boards: -		----------------- - -		CONFIG_ARMADILLO,	CONFIG_AT91RM9200DK,	CONFIG_CERF250, -		CONFIG_CSB637,		CONFIG_DELTA,		CONFIG_DNP1110, -		CONFIG_EP7312,		CONFIG_H2_OMAP1610,	CONFIG_HHP_CRADLE, -		CONFIG_IMPA7,	    CONFIG_INNOVATOROMAP1510,	CONFIG_INNOVATOROMAP1610, -		CONFIG_KB9202,		CONFIG_LART,		CONFIG_LPD7A400, -		CONFIG_LUBBOCK,		CONFIG_OSK_OMAP5912,	CONFIG_OMAP2420H4, -		CONFIG_PLEB2,		CONFIG_SHANNON,		CONFIG_P2_OMAP730, -		CONFIG_SMDK2400,	CONFIG_SMDK2410,	CONFIG_TRAB, -		CONFIG_VCMA9 - -		MicroBlaze based boards: -		------------------------ - -		CONFIG_SUZAKU - -		Nios-2 based boards: -		------------------------ - -		CONFIG_PCI5441 CONFIG_PK1C20 -		CONFIG_EP1C20 CONFIG_EP1S10 CONFIG_EP1S40 - -		AVR32 based boards: -		------------------- - -		CONFIG_ATSTK1000 +- Board Type:	Define exactly one, e.g. CONFIG_MPC8540ADS.  - CPU Daughterboard Type: (if CONFIG_ATSTK1000 is defined)  		Define exactly one of @@ -893,6 +789,71 @@ The following options need to be configured:  			CONFIG_USB_CONFIG  				for differential drivers: 0x00001000  				for single ended drivers: 0x00005000 +			CFG_USB_EVENT_POLL +				May be defined to allow interrupt polling +				instead of using asynchronous interrupts + +- USB Device: +		Define the below if you wish to use the USB console. +		Once firmware is rebuilt from a serial console issue the +		command "setenv stdin usbtty; setenv stdout usbtty" and +		attach your usb cable. The Unix command "dmesg" should print +		it has found a new device. The environment variable usbtty +		can be set to gserial or cdc_acm to enable your device to +		appear to a USB host as a Linux gserial device or a +		Common Device Class Abstract Control Model serial device. +		If you select usbtty = gserial you should be able to enumerate +		a Linux host by +		# modprobe usbserial vendor=0xVendorID product=0xProductID +		else if using cdc_acm, simply setting the environment +		variable usbtty to be cdc_acm should suffice. The following +		might be defined in YourBoardName.h + +			CONFIG_USB_DEVICE +			Define this to build a UDC device + +			CONFIG_USB_TTY +			Define this to have a tty type of device available to +			talk to the UDC device + +			CFG_CONSOLE_IS_IN_ENV +			Define this if you want stdin, stdout &/or stderr to +			be set to usbtty. + +			mpc8xx: +				CFG_USB_EXTC_CLK 0xBLAH +				Derive USB clock from external clock "blah" +				- CFG_USB_EXTC_CLK 0x02 + +				CFG_USB_BRG_CLK 0xBLAH +				Derive USB clock from brgclk +				- CFG_USB_BRG_CLK 0x04 + +		If you have a USB-IF assigned VendorID then you may wish to +		define your own vendor specific values either in BoardName.h +		or directly in usbd_vendor_info.h. If you don't define +		CONFIG_USBD_MANUFACTURER, CONFIG_USBD_PRODUCT_NAME, +		CONFIG_USBD_VENDORID and CONFIG_USBD_PRODUCTID, then U-Boot +		should pretend to be a Linux device to it's target host. + +			CONFIG_USBD_MANUFACTURER +			Define this string as the name of your company for +			- CONFIG_USBD_MANUFACTURER "my company" + +			CONFIG_USBD_PRODUCT_NAME +			Define this string as the name of your product +			- CONFIG_USBD_PRODUCT_NAME "acme usb device" + +			CONFIG_USBD_VENDORID +			Define this as your assigned Vendor ID from the USB +			Implementors Forum. This *must* be a genuine Vendor ID +			to avoid polluting the USB namespace. +			- CONFIG_USBD_VENDORID 0xFFFF + +			CONFIG_USBD_PRODUCTID +			Define this as the unique Product ID +			for your device +			- CONFIG_USBD_PRODUCTID 0xFFFF  - MMC Support: @@ -2426,34 +2387,7 @@ is done by typing:  	make NAME_config  where "NAME_config" is the name of one of the existing -configurations; the following names are supported: - -	ADCIOP_config		FPS860L_config		omap730p2_config -	ADS860_config		GEN860T_config		pcu_e_config -	Alaska8220_config -	AR405_config		GENIETV_config		PIP405_config -	at91rm9200dk_config	GTH_config		QS823_config -	CANBT_config		hermes_config		QS850_config -	cmi_mpc5xx_config	hymod_config		QS860T_config -	cogent_common_config	IP860_config		RPXlite_config -	cogent_mpc8260_config	IVML24_config		RPXlite_DW_config -	cogent_mpc8xx_config	IVMS8_config		RPXsuper_config -	CPCI405_config		JSE_config		rsdproto_config -	CPCIISER4_config	LANTEC_config		Sandpoint8240_config -	csb272_config		lwmon_config		sbc8260_config -	CU824_config		MBX860T_config		sbc8560_33_config -	DUET_ADS_config		MBX_config		sbc8560_66_config -	EBONY_config		mpc7448hpc2_config	SM850_config -	ELPT860_config		MPC8260ADS_config	SPD823TS_config -	ESTEEM192E_config	MPC8540ADS_config	stxgp3_config -	ETX094_config		MPC8540EVAL_config	SXNI855T_config -	FADS823_config		NMPC8560ADS_config	TQM823L_config -	FADS850SAR_config	NETVIA_config		TQM850L_config -	FADS860T_config		omap1510inn_config	TQM855L_config -	FPS850L_config		omap1610h2_config	TQM860L_config -				omap1610inn_config	walnut_config -				omap5912osk_config	Yukon8220_config -				omap2420h4_config	ZPC1900_config +configurations; see the main Makefile for supported names.  Note: for some board special configuration names may exist; check if        additional information is available from the board vendor; for diff --git a/board/davinci/dv-evm/Makefile b/board/davinci/dv-evm/Makefile new file mode 100644 index 000000000..fa0013811 --- /dev/null +++ b/board/davinci/dv-evm/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).a + +COBJS	:= dv_board.o +SOBJS	:= board_init.o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) $(SOBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak *~ .depend + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/davinci/dv-evm/board_init.S b/board/davinci/dv-evm/board_init.S new file mode 100644 index 000000000..22d8adc18 --- /dev/null +++ b/board/davinci/dv-evm/board_init.S @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Board-specific low level initialization code. Called at the very end + * of cpu/arm926ejs/davinci/lowlevel_init.S. Just returns if there is no + * initialization required. + * + * 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 <config.h> + +.globl	dv_board_init +dv_board_init: + +	mov	pc, lr diff --git a/board/davinci/dv-evm/config.mk b/board/davinci/dv-evm/config.mk new file mode 100644 index 000000000..aa89d0ec8 --- /dev/null +++ b/board/davinci/dv-evm/config.mk @@ -0,0 +1,39 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> +# +# (C) Copyright 2003 +# Texas Instruments, <www.ti.com> +# Swaminathan <swami.iyer@ti.com> +# +# Davinci EVM board (ARM925EJS) cpu +# see http://www.ti.com/ for more information on Texas Instruments +# +# Davinci EVM has 1 bank of 256 MB DDR RAM +# Physical Address: +# 8000'0000 to 9000'0000 +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# Visioneering Corp. Sonata board (ARM926EJS) cpu +# +# Sonata board has 1 bank of 128 MB DDR RAM +# Physical Address: +# 8000'0000 to 8800'0000 +# +# Razorstream, LLC. SCHMOOGIE board (ARM926EJS) cpu +# +# Schmoogie board has 1 bank of 128 MB DDR RAM +# Physical Address: +# 8000'0000 to 8800'0000 +# +# Linux-Kernel is expected to be at 8000'8000, entry 8000'8000 +# (mem base + reserved) +# +# we load ourself to 8108 '0000 +# +# + +#Provide at least 16MB spacing between us and the Linux Kernel image +TEXT_BASE = 0x81080000 diff --git a/board/davinci/dv-evm/dv_board.c b/board/davinci/dv-evm/dv_board.c new file mode 100644 index 000000000..94925ecfb --- /dev/null +++ b/board/davinci/dv-evm/dv_board.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts are shamelessly stolen from various TI sources, original copyright + * follows: + * ----------------------------------------------------------------- + * + * Copyright (C) 2004 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + */ + +#include <common.h> +#include <i2c.h> +#include <asm/arch/hardware.h> +#include <asm/arch/emac_defs.h> + +#define MACH_TYPE_DAVINCI_EVM		901 + +extern void	i2c_init(int speed, int slaveaddr); +extern void	timer_init(void); +extern int	eth_hw_init(void); +extern phy_t	phy; + + +/* Works on Always On power domain only (no PD argument) */ +void lpsc_on(unsigned int id) +{ +	dv_reg_p	mdstat, mdctl; + +	if (id >= DAVINCI_LPSC_GEM) +		return;			/* Don't work on DSP Power Domain */ + +	mdstat = REG_P(PSC_MDSTAT_BASE + (id * 4)); +	mdctl = REG_P(PSC_MDCTL_BASE + (id * 4)); + +	while (REG(PSC_PTSTAT) & 0x01) {;} + +	if ((*mdstat & 0x1f) == 0x03) +		return;			/* Already on and enabled */ + +	*mdctl |= 0x03; + +	/* Special treatment for some modules as for sprue14 p.7.4.2 */ +	if (	(id == DAVINCI_LPSC_VPSSSLV) || +		(id == DAVINCI_LPSC_EMAC) || +		(id == DAVINCI_LPSC_EMAC_WRAPPER) || +		(id == DAVINCI_LPSC_MDIO) || +		(id == DAVINCI_LPSC_USB) || +		(id == DAVINCI_LPSC_ATA) || +		(id == DAVINCI_LPSC_VLYNQ) || +		(id == DAVINCI_LPSC_UHPI) || +		(id == DAVINCI_LPSC_DDR_EMIF) || +		(id == DAVINCI_LPSC_AEMIF) || +		(id == DAVINCI_LPSC_MMC_SD) || +		(id == DAVINCI_LPSC_MEMSTICK) || +		(id == DAVINCI_LPSC_McBSP) || +		(id == DAVINCI_LPSC_GPIO) +	   ) +	   	*mdctl |= 0x200; + +	REG(PSC_PTCMD) = 0x01; + +	while (REG(PSC_PTSTAT) & 0x03) {;} +	while ((*mdstat & 0x1f) != 0x03) {;}	/* Probably an overkill... */ +} + +void dsp_on(void) +{ +	int	i; + +	if (REG(PSC_PDSTAT1) & 0x1f) +		return;			/* Already on */ + +	REG(PSC_GBLCTL) |= 0x01; +	REG(PSC_PDCTL1) |= 0x01; +	REG(PSC_PDCTL1) &= ~0x100; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) |= 0x03; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) &= 0xfffffeff; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) |= 0x03; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) &= 0xfffffeff; +	REG(PSC_PTCMD) = 0x02; + +	for (i = 0; i < 100; i++) { +		if (REG(PSC_EPCPR) & 0x02) +			break; +	} + +	REG(PSC_CHP_SHRTSW) = 0x01; +	REG(PSC_PDCTL1) |= 0x100; +	REG(PSC_EPCCR) = 0x02; + +	for (i = 0; i < 100; i++) { +		if (!(REG(PSC_PTSTAT) & 0x02)) +			break; +	} + +	REG(PSC_GBLCTL) &= ~0x1f; +} + + +int board_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	/* arch number of the board */ +	gd->bd->bi_arch_number = MACH_TYPE_DAVINCI_EVM; + +	/* address of boot parameters */ +	gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; + +	/* Workaround for TMS320DM6446 errata 1.3.22 */ +	REG(PSC_SILVER_BULLET) = 0; + +	/* Power on required peripherals */ +	lpsc_on(DAVINCI_LPSC_EMAC); +	lpsc_on(DAVINCI_LPSC_EMAC_WRAPPER); +	lpsc_on(DAVINCI_LPSC_MDIO); +	lpsc_on(DAVINCI_LPSC_I2C); +	lpsc_on(DAVINCI_LPSC_UART0); +	lpsc_on(DAVINCI_LPSC_TIMER1); +	lpsc_on(DAVINCI_LPSC_GPIO); + +	/* Powerup the DSP */ +	dsp_on(); + +	/* Bringup UART0 out of reset */ +	REG(UART0_PWREMU_MGMT) = 0x0000e003; + +	/* Enable GIO3.3V cells used for EMAC */ +	REG(VDD3P3V_PWDN) = 0; + +	/* Enable UART0 MUX lines */ +	REG(PINMUX1) |= 1; + +	/* Enable EMAC and AEMIF pins */ +	REG(PINMUX0) = 0x80000c1f; + +	/* Enable I2C pin Mux */ +	REG(PINMUX1) |= (1 << 7); + +	/* Set the Bus Priority Register to appropriate value */ +	REG(VBPR) = 0x20; + +	timer_init(); + +	return(0); +} + +int misc_init_r (void) +{ +	u_int8_t	tmp[20], buf[10]; +	int		i = 0; +	int		clk = 0; + +	clk = ((REG(PLL2_PLLM) + 1) * 27) / ((REG(PLL2_DIV2) & 0x1f) + 1); + +	printf ("ARM Clock : %dMHz\n", ((REG(PLL1_PLLM) + 1) * 27 ) / 2); +	printf ("DDR Clock : %dMHz\n", (clk / 2)); + +	/* Set Ethernet MAC address from EEPROM */ +	if (i2c_read(CFG_I2C_EEPROM_ADDR, 0x7f00, CFG_I2C_EEPROM_ADDR_LEN, buf, 6)) { +		printf("\nEEPROM @ 0x%02x read FAILED!!!\n", CFG_I2C_EEPROM_ADDR); +	} else { +		tmp[0] = 0xff; +		for (i = 0; i < 6; i++) +			tmp[0] &= buf[i]; + +		if ((tmp[0] != 0xff) && (getenv("ethaddr") == NULL)) { +			sprintf((char *)&tmp[0], "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", +				buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); +			setenv("ethaddr", (char *)&tmp[0]); +		} +	} + +	if (!eth_hw_init()) { +		printf("ethernet init failed!\n"); +	} else { +		printf("ETH PHY   : %s\n", phy.name); +	} + +	i2c_read (0x39, 0x00, 1, (u_int8_t *)&i, 1); + +	setenv ("videostd", ((i  & 0x80) ? "pal" : "ntsc")); + +	return(0); +} + +int dram_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +	return(0); +} diff --git a/board/davinci/dv-evm/u-boot.lds b/board/davinci/dv-evm/u-boot.lds new file mode 100644 index 000000000..710b2a2d6 --- /dev/null +++ b/board/davinci/dv-evm/u-boot.lds @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * 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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ +	. = 0x00000000; +	. = ALIGN(4); +	.text	: +	{ +	  cpu/arm926ejs/start.o	(.text) +	  *(.text) +	} +	. = ALIGN(4); +	.rodata : { *(.rodata) } +	. = ALIGN(4); +	.data : { *(.data) } +	. = ALIGN(4); +	.got : { *(.got) } + +	. = .; +	__u_boot_cmd_start = .; +	.u_boot_cmd : { *(.u_boot_cmd) } +	__u_boot_cmd_end = .; + +	. = ALIGN(4); +	__bss_start = .; +	.bss : { *(.bss) } +	_end = .; +} diff --git a/board/davinci/schmoogie/Makefile b/board/davinci/schmoogie/Makefile new file mode 100644 index 000000000..fa0013811 --- /dev/null +++ b/board/davinci/schmoogie/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).a + +COBJS	:= dv_board.o +SOBJS	:= board_init.o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) $(SOBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak *~ .depend + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/davinci/schmoogie/board_init.S b/board/davinci/schmoogie/board_init.S new file mode 100644 index 000000000..22d8adc18 --- /dev/null +++ b/board/davinci/schmoogie/board_init.S @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Board-specific low level initialization code. Called at the very end + * of cpu/arm926ejs/davinci/lowlevel_init.S. Just returns if there is no + * initialization required. + * + * 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 <config.h> + +.globl	dv_board_init +dv_board_init: + +	mov	pc, lr diff --git a/board/davinci/schmoogie/config.mk b/board/davinci/schmoogie/config.mk new file mode 100644 index 000000000..aa89d0ec8 --- /dev/null +++ b/board/davinci/schmoogie/config.mk @@ -0,0 +1,39 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> +# +# (C) Copyright 2003 +# Texas Instruments, <www.ti.com> +# Swaminathan <swami.iyer@ti.com> +# +# Davinci EVM board (ARM925EJS) cpu +# see http://www.ti.com/ for more information on Texas Instruments +# +# Davinci EVM has 1 bank of 256 MB DDR RAM +# Physical Address: +# 8000'0000 to 9000'0000 +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# Visioneering Corp. Sonata board (ARM926EJS) cpu +# +# Sonata board has 1 bank of 128 MB DDR RAM +# Physical Address: +# 8000'0000 to 8800'0000 +# +# Razorstream, LLC. SCHMOOGIE board (ARM926EJS) cpu +# +# Schmoogie board has 1 bank of 128 MB DDR RAM +# Physical Address: +# 8000'0000 to 8800'0000 +# +# Linux-Kernel is expected to be at 8000'8000, entry 8000'8000 +# (mem base + reserved) +# +# we load ourself to 8108 '0000 +# +# + +#Provide at least 16MB spacing between us and the Linux Kernel image +TEXT_BASE = 0x81080000 diff --git a/board/davinci/schmoogie/dv_board.c b/board/davinci/schmoogie/dv_board.c new file mode 100644 index 000000000..b15c5f718 --- /dev/null +++ b/board/davinci/schmoogie/dv_board.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts are shamelessly stolen from various TI sources, original copyright + * follows: + * ----------------------------------------------------------------- + * + * Copyright (C) 2004 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + */ + +#include <common.h> +#include <i2c.h> +#include <asm/arch/hardware.h> +#include <asm/arch/emac_defs.h> + +#define MACH_TYPE_SCHMOOGIE		1255 + +extern void	i2c_init(int speed, int slaveaddr); +extern void	timer_init(void); +extern int	eth_hw_init(void); +extern phy_t	phy; + + +/* Works on Always On power domain only (no PD argument) */ +void lpsc_on(unsigned int id) +{ +	dv_reg_p	mdstat, mdctl; + +	if (id >= DAVINCI_LPSC_GEM) +		return;			/* Don't work on DSP Power Domain */ + +	mdstat = REG_P(PSC_MDSTAT_BASE + (id * 4)); +	mdctl = REG_P(PSC_MDCTL_BASE + (id * 4)); + +	while (REG(PSC_PTSTAT) & 0x01) {;} + +	if ((*mdstat & 0x1f) == 0x03) +		return;			/* Already on and enabled */ + +	*mdctl |= 0x03; + +	/* Special treatment for some modules as for sprue14 p.7.4.2 */ +	if (	(id == DAVINCI_LPSC_VPSSSLV) || +		(id == DAVINCI_LPSC_EMAC) || +		(id == DAVINCI_LPSC_EMAC_WRAPPER) || +		(id == DAVINCI_LPSC_MDIO) || +		(id == DAVINCI_LPSC_USB) || +		(id == DAVINCI_LPSC_ATA) || +		(id == DAVINCI_LPSC_VLYNQ) || +		(id == DAVINCI_LPSC_UHPI) || +		(id == DAVINCI_LPSC_DDR_EMIF) || +		(id == DAVINCI_LPSC_AEMIF) || +		(id == DAVINCI_LPSC_MMC_SD) || +		(id == DAVINCI_LPSC_MEMSTICK) || +		(id == DAVINCI_LPSC_McBSP) || +		(id == DAVINCI_LPSC_GPIO) +	   ) +	   	*mdctl |= 0x200; + +	REG(PSC_PTCMD) = 0x01; + +	while (REG(PSC_PTSTAT) & 0x03) {;} +	while ((*mdstat & 0x1f) != 0x03) {;}	/* Probably an overkill... */ +} + +void dsp_on(void) +{ +	int	i; + +	if (REG(PSC_PDSTAT1) & 0x1f) +		return;			/* Already on */ + +	REG(PSC_GBLCTL) |= 0x01; +	REG(PSC_PDCTL1) |= 0x01; +	REG(PSC_PDCTL1) &= ~0x100; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) |= 0x03; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) &= 0xfffffeff; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) |= 0x03; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) &= 0xfffffeff; +	REG(PSC_PTCMD) = 0x02; + +	for (i = 0; i < 100; i++) { +		if (REG(PSC_EPCPR) & 0x02) +			break; +	} + +	REG(PSC_CHP_SHRTSW) = 0x01; +	REG(PSC_PDCTL1) |= 0x100; +	REG(PSC_EPCCR) = 0x02; + +	for (i = 0; i < 100; i++) { +		if (!(REG(PSC_PTSTAT) & 0x02)) +			break; +	} + +	REG(PSC_GBLCTL) &= ~0x1f; +} + + +int board_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	/* arch number of the board */ +	gd->bd->bi_arch_number = MACH_TYPE_SCHMOOGIE; + +	/* address of boot parameters */ +	gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; + +	/* Workaround for TMS320DM6446 errata 1.3.22 */ +	REG(PSC_SILVER_BULLET) = 0; + +	/* Power on required peripherals */ +	lpsc_on(DAVINCI_LPSC_EMAC); +	lpsc_on(DAVINCI_LPSC_EMAC_WRAPPER); +	lpsc_on(DAVINCI_LPSC_MDIO); +	lpsc_on(DAVINCI_LPSC_I2C); +	lpsc_on(DAVINCI_LPSC_UART0); +	lpsc_on(DAVINCI_LPSC_TIMER1); +	lpsc_on(DAVINCI_LPSC_GPIO); + +	/* Powerup the DSP */ +	dsp_on(); + +	/* Bringup UART0 out of reset */ +	REG(UART0_PWREMU_MGMT) = 0x0000e003; + +	/* Enable GIO3.3V cells used for EMAC */ +	REG(VDD3P3V_PWDN) = 0; + +	/* Enable UART0 MUX lines */ +	REG(PINMUX1) |= 1; + +	/* Enable EMAC and AEMIF pins */ +	REG(PINMUX0) = 0x80000c1f; + +	/* Enable I2C pin Mux */ +	REG(PINMUX1) |= (1 << 7); + +	/* Set the Bus Priority Register to appropriate value */ +	REG(VBPR) = 0x20; + +	timer_init(); + +	return(0); +} + +int misc_init_r (void) +{ +	u_int8_t	tmp[20], buf[10]; +	int		i = 0; +	int		clk = 0; + +	/* Set serial number from UID chip */ +	u_int8_t	crc_tbl[256] = { +			0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, +			0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41, +			0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, +			0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc, +			0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, +			0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62, +			0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, +			0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff, +			0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, +			0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07, +			0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, +			0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a, +			0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, +			0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24, +			0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, +			0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9, +			0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, +			0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd, +			0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, +			0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50, +			0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, +			0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee, +			0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1, +			0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73, +			0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, +			0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b, +			0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4, +			0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16, +			0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a, +			0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8, +			0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, +			0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35 +		}; + +	clk = ((REG(PLL2_PLLM) + 1) * 27) / ((REG(PLL2_DIV2) & 0x1f) + 1); + +	printf ("ARM Clock : %dMHz\n", ((REG(PLL1_PLLM) + 1) * 27 ) / 2); +	printf ("DDR Clock : %dMHz\n", (clk / 2)); + +	/* Set serial number from UID chip */ +	if (i2c_read(CFG_UID_ADDR, 0, 1, buf, 8)) { +		printf("\nUID @ 0x%02x read FAILED!!!\n", CFG_UID_ADDR); +		forceenv("serial#", "FAILED"); +	} else { +		if (buf[0] != 0x70) {	/* Device Family Code */ +			printf("\nUID @ 0x%02x read FAILED!!!\n", CFG_UID_ADDR); +			forceenv("serial#", "FAILED"); +		} +	} +	/* Now check CRC */ +	tmp[0] = 0; +	for (i = 0; i < 8; i++) +		tmp[0] = crc_tbl[tmp[0] ^ buf[i]]; + +	if (tmp[0] != 0) { +		printf("\nUID @ 0x%02x - BAD CRC!!!\n", CFG_UID_ADDR); +		forceenv("serial#", "FAILED"); +	} else { +		/* CRC OK, set "serial" env variable */ +		sprintf((char *)&tmp[0], "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", +			buf[6], buf[5], buf[4], buf[3], buf[2], buf[1]); +		forceenv("serial#", (char *)&tmp[0]); +	} + +	if (!eth_hw_init()) { +		printf("ethernet init failed!\n"); +	} else { +		printf("ETH PHY   : %s\n", phy.name); +	} + +	return(0); +} + +int dram_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +	return(0); +} diff --git a/board/davinci/schmoogie/u-boot.lds b/board/davinci/schmoogie/u-boot.lds new file mode 100644 index 000000000..710b2a2d6 --- /dev/null +++ b/board/davinci/schmoogie/u-boot.lds @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * 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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ +	. = 0x00000000; +	. = ALIGN(4); +	.text	: +	{ +	  cpu/arm926ejs/start.o	(.text) +	  *(.text) +	} +	. = ALIGN(4); +	.rodata : { *(.rodata) } +	. = ALIGN(4); +	.data : { *(.data) } +	. = ALIGN(4); +	.got : { *(.got) } + +	. = .; +	__u_boot_cmd_start = .; +	.u_boot_cmd : { *(.u_boot_cmd) } +	__u_boot_cmd_end = .; + +	. = ALIGN(4); +	__bss_start = .; +	.bss : { *(.bss) } +	_end = .; +} diff --git a/board/davinci/sonata/Makefile b/board/davinci/sonata/Makefile new file mode 100644 index 000000000..fa0013811 --- /dev/null +++ b/board/davinci/sonata/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).a + +COBJS	:= dv_board.o +SOBJS	:= board_init.o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) $(SOBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak *~ .depend + +######################################################################### +# This is for $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/davinci/sonata/board_init.S b/board/davinci/sonata/board_init.S new file mode 100644 index 000000000..fbb9ea73e --- /dev/null +++ b/board/davinci/sonata/board_init.S @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Board-specific low level initialization code. Called at the very end + * of cpu/arm926ejs/davinci/lowlevel_init.S. Just returns if there is no + * initialization required. + * + * For _OLDER_ Sonata boards sets up GPIO4 to control NAND WP line. Newer + * Sonata boards, AFAIK, don't use this so it's just return by default. Ask + * Visioneering if they reinvented the wheel once again to make sure :) + * + * 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 <config.h> + +.globl	dv_board_init +dv_board_init: +#ifdef SONATA_BOARD_GPIOWP +	/* Set PINMUX0 to enable GPIO4 */ +	ldr	r0, _PINMUX0 +	ldr	r1, GPIO4_EN_MASK +	ldr	r2, [r0] +	and	r2, r2, r1 +	str	r2, [r0] + +	/* Enable GPIO LPSC module */ +	ldr	r0, PTSTAT + +gpio_ptstat_loop1: +	ldr	r2, [r0] +	tst	r2, $0x00000001 +	bne	gpio_ptstat_loop1 + +	ldr	r1, MDCTL_GPIO +	ldr	r2, [r1] +	and	r2, r2, $0xfffffff8 +	orr	r2, r2, $0x00000003 +	str	r2, [r1] + +	orr	r2, r2, $0x00000200 +	str	r2, [r1] + +	ldr	r1, PTCMD +	mov	r2, $0x00000001 +	str	r2, [r1] + +gpio_ptstat_loop2: +	ldr	r2, [r0] +	tst	r2, $0x00000001 +	bne	gpio_ptstat_loop2 + +	ldr	r0, MDSTAT_GPIO +gpio_mdstat_loop: +	ldr	r2, [r0] +	and	r2, r2, $0x0000001f +	teq	r2, $0x00000003 +	bne	gpio_mdstat_loop + +	/* GPIO4 -> output */ +	ldr	r0, GPIO_DIR01 +	mov	r1, $0x10 +	ldr	r2, [r0] +	bic	r2, r2, r0 +	str	r2, [r0] + +	/* Set it to 0 (Write Protect) */ +	ldr	r0, GPIO_CLR_DATA01 +	str	r1, [r0] +#endif + +	mov	pc, lr + +#ifdef SONATA_BOARD_GPIOWP +.ltorg + +GPIO4_EN_MASK: +	.word	0xf77fffff +MDCTL_GPIO: +	.word	0x01c41a68 +MDSTAT_GPIO: +	.word	0x01c41868 +GPIO_DIR01: +	.word	0x01c67010 +GPIO_CLR_DATA01: +	.word	0x01c6701c +#endif diff --git a/board/davinci/sonata/config.mk b/board/davinci/sonata/config.mk new file mode 100644 index 000000000..aa89d0ec8 --- /dev/null +++ b/board/davinci/sonata/config.mk @@ -0,0 +1,39 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@denx.de> +# David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> +# +# (C) Copyright 2003 +# Texas Instruments, <www.ti.com> +# Swaminathan <swami.iyer@ti.com> +# +# Davinci EVM board (ARM925EJS) cpu +# see http://www.ti.com/ for more information on Texas Instruments +# +# Davinci EVM has 1 bank of 256 MB DDR RAM +# Physical Address: +# 8000'0000 to 9000'0000 +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# Visioneering Corp. Sonata board (ARM926EJS) cpu +# +# Sonata board has 1 bank of 128 MB DDR RAM +# Physical Address: +# 8000'0000 to 8800'0000 +# +# Razorstream, LLC. SCHMOOGIE board (ARM926EJS) cpu +# +# Schmoogie board has 1 bank of 128 MB DDR RAM +# Physical Address: +# 8000'0000 to 8800'0000 +# +# Linux-Kernel is expected to be at 8000'8000, entry 8000'8000 +# (mem base + reserved) +# +# we load ourself to 8108 '0000 +# +# + +#Provide at least 16MB spacing between us and the Linux Kernel image +TEXT_BASE = 0x81080000 diff --git a/board/davinci/sonata/dv_board.c b/board/davinci/sonata/dv_board.c new file mode 100644 index 000000000..7b0a459fa --- /dev/null +++ b/board/davinci/sonata/dv_board.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts are shamelessly stolen from various TI sources, original copyright + * follows: + * ----------------------------------------------------------------- + * + * Copyright (C) 2004 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + */ + +#include <common.h> +#include <i2c.h> +#include <asm/arch/hardware.h> +#include <asm/arch/emac_defs.h> + +#define MACH_TYPE_SONATA		1254 + +extern void	i2c_init(int speed, int slaveaddr); +extern void	timer_init(void); +extern int	eth_hw_init(void); +extern phy_t	phy; + + +/* Works on Always On power domain only (no PD argument) */ +void lpsc_on(unsigned int id) +{ +	dv_reg_p	mdstat, mdctl; + +	if (id >= DAVINCI_LPSC_GEM) +		return;			/* Don't work on DSP Power Domain */ + +	mdstat = REG_P(PSC_MDSTAT_BASE + (id * 4)); +	mdctl = REG_P(PSC_MDCTL_BASE + (id * 4)); + +	while (REG(PSC_PTSTAT) & 0x01) {;} + +	if ((*mdstat & 0x1f) == 0x03) +		return;			/* Already on and enabled */ + +	*mdctl |= 0x03; + +	/* Special treatment for some modules as for sprue14 p.7.4.2 */ +	if (	(id == DAVINCI_LPSC_VPSSSLV) || +		(id == DAVINCI_LPSC_EMAC) || +		(id == DAVINCI_LPSC_EMAC_WRAPPER) || +		(id == DAVINCI_LPSC_MDIO) || +		(id == DAVINCI_LPSC_USB) || +		(id == DAVINCI_LPSC_ATA) || +		(id == DAVINCI_LPSC_VLYNQ) || +		(id == DAVINCI_LPSC_UHPI) || +		(id == DAVINCI_LPSC_DDR_EMIF) || +		(id == DAVINCI_LPSC_AEMIF) || +		(id == DAVINCI_LPSC_MMC_SD) || +		(id == DAVINCI_LPSC_MEMSTICK) || +		(id == DAVINCI_LPSC_McBSP) || +		(id == DAVINCI_LPSC_GPIO) +	   ) +	   	*mdctl |= 0x200; + +	REG(PSC_PTCMD) = 0x01; + +	while (REG(PSC_PTSTAT) & 0x03) {;} +	while ((*mdstat & 0x1f) != 0x03) {;}	/* Probably an overkill... */ +} + +void dsp_on(void) +{ +	int	i; + +	if (REG(PSC_PDSTAT1) & 0x1f) +		return;			/* Already on */ + +	REG(PSC_GBLCTL) |= 0x01; +	REG(PSC_PDCTL1) |= 0x01; +	REG(PSC_PDCTL1) &= ~0x100; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) |= 0x03; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_GEM * 4)) &= 0xfffffeff; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) |= 0x03; +	REG(PSC_MDCTL_BASE + (DAVINCI_LPSC_IMCOP * 4)) &= 0xfffffeff; +	REG(PSC_PTCMD) = 0x02; + +	for (i = 0; i < 100; i++) { +		if (REG(PSC_EPCPR) & 0x02) +			break; +	} + +	REG(PSC_CHP_SHRTSW) = 0x01; +	REG(PSC_PDCTL1) |= 0x100; +	REG(PSC_EPCCR) = 0x02; + +	for (i = 0; i < 100; i++) { +		if (!(REG(PSC_PTSTAT) & 0x02)) +			break; +	} + +	REG(PSC_GBLCTL) &= ~0x1f; +} + + +int board_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	/* arch number of the board */ +	gd->bd->bi_arch_number = MACH_TYPE_SONATA; + +	/* address of boot parameters */ +	gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR; + +	/* Workaround for TMS320DM6446 errata 1.3.22 */ +	REG(PSC_SILVER_BULLET) = 0; + +	/* Power on required peripherals */ +	lpsc_on(DAVINCI_LPSC_EMAC); +	lpsc_on(DAVINCI_LPSC_EMAC_WRAPPER); +	lpsc_on(DAVINCI_LPSC_MDIO); +	lpsc_on(DAVINCI_LPSC_I2C); +	lpsc_on(DAVINCI_LPSC_UART0); +	lpsc_on(DAVINCI_LPSC_TIMER1); +	lpsc_on(DAVINCI_LPSC_GPIO); + +	/* Powerup the DSP */ +	dsp_on(); + +	/* Bringup UART0 out of reset */ +	REG(UART0_PWREMU_MGMT) = 0x0000e003; + +	/* Enable GIO3.3V cells used for EMAC */ +	REG(VDD3P3V_PWDN) = 0; + +	/* Enable UART0 MUX lines */ +	REG(PINMUX1) |= 1; + +	/* Enable EMAC and AEMIF pins */ +	REG(PINMUX0) = 0x80000c1f; + +	/* Enable I2C pin Mux */ +	REG(PINMUX1) |= (1 << 7); + +	/* Set the Bus Priority Register to appropriate value */ +	REG(VBPR) = 0x20; + +	timer_init(); + +	return(0); +} + +int misc_init_r (void) +{ +	u_int8_t	tmp[20], buf[10]; +	int		i = 0; +	int		clk = 0; + + +	clk = ((REG(PLL2_PLLM) + 1) * 27) / ((REG(PLL2_DIV2) & 0x1f) + 1); + +	printf ("ARM Clock : %dMHz\n", ((REG(PLL1_PLLM) + 1) * 27 ) / 2); +	printf ("DDR Clock : %dMHz\n", (clk / 2)); + +	/* Set Ethernet MAC address from EEPROM */ +	if (i2c_read(CFG_I2C_EEPROM_ADDR, 0x7f00, CFG_I2C_EEPROM_ADDR_LEN, buf, 6)) { +		printf("\nEEPROM @ 0x%02x read FAILED!!!\n", CFG_I2C_EEPROM_ADDR); +	} else { +		tmp[0] = 0xff; +		for (i = 0; i < 6; i++) +			tmp[0] &= buf[i]; + +		if ((tmp[0] != 0xff) && (getenv("ethaddr") == NULL)) { +			sprintf((char *)&tmp[0], "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", +				buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); +			setenv("ethaddr", (char *)&tmp[0]); +		} +	} + +	if (!eth_hw_init()) { +		printf("ethernet init failed!\n"); +	} else { +		printf("ETH PHY   : %s\n", phy.name); +	} + +	return(0); +} + +int dram_init(void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +	return(0); +} diff --git a/board/davinci/sonata/u-boot.lds b/board/davinci/sonata/u-boot.lds new file mode 100644 index 000000000..710b2a2d6 --- /dev/null +++ b/board/davinci/sonata/u-boot.lds @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * 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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ +	. = 0x00000000; +	. = ALIGN(4); +	.text	: +	{ +	  cpu/arm926ejs/start.o	(.text) +	  *(.text) +	} +	. = ALIGN(4); +	.rodata : { *(.rodata) } +	. = ALIGN(4); +	.data : { *(.data) } +	. = ALIGN(4); +	.got : { *(.got) } + +	. = .; +	__u_boot_cmd_start = .; +	.u_boot_cmd : { *(.u_boot_cmd) } +	__u_boot_cmd_end = .; + +	. = ALIGN(4); +	__bss_start = .; +	.bss : { *(.bss) } +	_end = .; +} diff --git a/board/delta/delta.c b/board/delta/delta.c index b127ac8ca..6e227748b 100644 --- a/board/delta/delta.c +++ b/board/delta/delta.c @@ -1,10 +1,6 @@  /* - * (C) Copyright 2002 - * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.de> + * (C) Copyright 2006 + * DENX Software Engineering   *   * See file CREDITS for list of people who contributed to this   * project. @@ -98,7 +94,6 @@ int board_late_init(void)  	return 0;  } -  /*   * Magic Key Handling, mainly copied from board/lwmon/lwmon.c   */ @@ -324,6 +319,12 @@ static void init_DA9030()  		return;  	} +	val = 0x80; +	if(i2c_write(addr, IRQ_MASK_B, 1, &val, 1)) { +		printf("Error accessing DA9030 via i2c.\n"); +		return; +	} +  	i2c_reg_write(addr, REG_CONTROL_1_97, 0xfd); /* disable LDO1, enable LDO6 */  	i2c_reg_write(addr, LDO2_3, 0xd1);	/* LDO2 =1,9V, LDO3=3,1V */  	i2c_reg_write(addr, LDO4_5, 0xcc);	/* LDO2 =1,9V, LDO3=3,1V */ diff --git a/board/freescale/mpc8323erdb/Makefile b/board/freescale/mpc8323erdb/Makefile new file mode 100644 index 000000000..acc954488 --- /dev/null +++ b/board/freescale/mpc8323erdb/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).a + +COBJS	:= $(BOARD).o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/freescale/mpc8323erdb/config.mk b/board/freescale/mpc8323erdb/config.mk new file mode 100644 index 000000000..fe0d37d42 --- /dev/null +++ b/board/freescale/mpc8323erdb/config.mk @@ -0,0 +1,28 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 +# + +# +# MPC8323ERDB +# + +TEXT_BASE = 0xFE000000 diff --git a/board/freescale/mpc8323erdb/mpc8323erdb.c b/board/freescale/mpc8323erdb/mpc8323erdb.c new file mode 100644 index 000000000..1886f196b --- /dev/null +++ b/board/freescale/mpc8323erdb/mpc8323erdb.c @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2007 Freescale Semiconductor, Inc. + * + * Michael Barkowski <michael.barkowski@freescale.com> + * Based on mpc832xmds file by Dave Liu <daveliu@freescale.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <common.h> +#include <ioports.h> +#include <mpc83xx.h> +#include <i2c.h> +#include <spd.h> +#include <miiphy.h> +#include <command.h> +#include <libfdt.h> +#include <libfdt_env.h> +#if defined(CONFIG_PCI) +#include <pci.h> +#endif +#if defined(CONFIG_SPD_EEPROM) +#include <spd_sdram.h> +#else +#include <asm/mmu.h> +#endif + +const qe_iop_conf_t qe_iop_conf_tab[] = { +	/* UCC3 */ +	{1,  0, 1, 0, 1}, /* TxD0 */ +	{1,  1, 1, 0, 1}, /* TxD1 */ +	{1,  2, 1, 0, 1}, /* TxD2 */ +	{1,  3, 1, 0, 1}, /* TxD3 */ +	{1,  9, 1, 0, 1}, /* TxER */ +	{1, 12, 1, 0, 1}, /* TxEN */ +	{3, 24, 2, 0, 1}, /* TxCLK->CLK10 */ + +	{1,  4, 2, 0, 1}, /* RxD0 */ +	{1,  5, 2, 0, 1}, /* RxD1 */ +	{1,  6, 2, 0, 1}, /* RxD2 */ +	{1,  7, 2, 0, 1}, /* RxD3 */ +	{1,  8, 2, 0, 1}, /* RxER */ +	{1, 10, 2, 0, 1}, /* RxDV */ +	{0, 13, 2, 0, 1}, /* RxCLK->CLK9 */ +	{1, 11, 2, 0, 1}, /* COL */ +	{1, 13, 2, 0, 1}, /* CRS */ + +	/* UCC2 */ +	{0, 18, 1, 0, 1}, /* TxD0 */ +	{0, 19, 1, 0, 1}, /* TxD1 */ +	{0, 20, 1, 0, 1}, /* TxD2 */ +	{0, 21, 1, 0, 1}, /* TxD3 */ +	{0, 27, 1, 0, 1}, /* TxER */ +	{0, 30, 1, 0, 1}, /* TxEN */ +	{3, 23, 2, 0, 1}, /* TxCLK->CLK3 */ + +	{0, 22, 2, 0, 1}, /* RxD0 */ +	{0, 23, 2, 0, 1}, /* RxD1 */ +	{0, 24, 2, 0, 1}, /* RxD2 */ +	{0, 25, 2, 0, 1}, /* RxD3 */ +	{0, 26, 1, 0, 1}, /* RxER */ +	{0, 28, 2, 0, 1}, /* Rx_DV */ +	{3, 21, 2, 0, 1}, /* RxCLK->CLK16 */ +	{0, 29, 2, 0, 1}, /* COL */ +	{0, 31, 2, 0, 1}, /* CRS */ + +	{3,  4, 3, 0, 2}, /* MDIO */ +	{3,  5, 1, 0, 2}, /* MDC */ + +	{0,  0, 0, 0, QE_IOP_TAB_END}, /* END of table */ +}; + +int board_early_init_f(void) +{ +	return 0; +} + +int fixed_sdram(void); + +long int initdram(int board_type) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	u32 msize = 0; + +	if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) +		return -1; + +	/* DDR SDRAM - Main SODIMM */ +	im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; + +	msize = fixed_sdram(); + +	puts("\n   DDR RAM: "); + +	/* return total bus SDRAM size(bytes)  -- DDR */ +	return (msize * 1024 * 1024); +} + +/************************************************************************* + *  fixed sdram init -- doesn't use serial presence detect. + ************************************************************************/ +int fixed_sdram(void) +{ +	volatile immap_t *im = (immap_t *) CFG_IMMR; +	u32 msize = 0; +	u32 ddr_size; +	u32 ddr_size_log2; + +	msize = CFG_DDR_SIZE; +	for (ddr_size = msize << 20, ddr_size_log2 = 0; +	     (ddr_size > 1); ddr_size = ddr_size >> 1, ddr_size_log2++) { +		if (ddr_size & 1) { +			return -1; +		} +	} +	im->sysconf.ddrlaw[0].ar = +	    LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); +	im->ddr.sdram_clk_cntl = CFG_DDR_CLK_CNTL; +	im->ddr.csbnds[0].csbnds = CFG_DDR_CS0_BNDS; +	im->ddr.cs_config[0] = CFG_DDR_CS0_CONFIG; +	im->ddr.timing_cfg_0 = CFG_DDR_TIMING_0; +	im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; +	im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; +	im->ddr.timing_cfg_3 = CFG_DDR_TIMING_3; +	im->ddr.sdram_cfg = CFG_DDR_SDRAM_CFG; +	im->ddr.sdram_cfg2 = CFG_DDR_SDRAM_CFG2; +	im->ddr.sdram_mode = CFG_DDR_MODE; +	im->ddr.sdram_mode2 = CFG_DDR_MODE2; +	im->ddr.sdram_interval = CFG_DDR_INTERVAL; +	__asm__ __volatile__ ("sync"); +	udelay(200); + +	im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; +	__asm__ __volatile__ ("sync"); +	return msize; +} + +int checkboard(void) +{ +	puts("Board: Freescale MPC8323ERDB\n"); +	return 0; +} + +static struct pci_region pci_regions[] = { +	{ +		bus_start: CFG_PCI1_MEM_BASE, +		phys_start: CFG_PCI1_MEM_PHYS, +		size: CFG_PCI1_MEM_SIZE, +		flags: PCI_REGION_MEM | PCI_REGION_PREFETCH +	}, +	{ +		bus_start: CFG_PCI1_MMIO_BASE, +		phys_start: CFG_PCI1_MMIO_PHYS, +		size: CFG_PCI1_MMIO_SIZE, +		flags: PCI_REGION_MEM +	}, +	{ +		bus_start: CFG_PCI1_IO_BASE, +		phys_start: CFG_PCI1_IO_PHYS, +		size: CFG_PCI1_IO_SIZE, +		flags: PCI_REGION_IO +	} +}; + +void pci_init_board(void) +{ +	volatile immap_t *immr = (volatile immap_t *)CFG_IMMR; +	volatile clk83xx_t *clk = (volatile clk83xx_t *)&immr->clk; +	volatile law83xx_t *pci_law = immr->sysconf.pcilaw; +	struct pci_region *reg[] = { pci_regions }; + +	/* Enable all 3 PCI_CLK_OUTPUTs. */ +	clk->occr |= 0xe0000000; + +	/* Configure PCI Local Access Windows */ +	pci_law[0].bar = CFG_PCI1_MEM_PHYS & LAWBAR_BAR; +	pci_law[0].ar = LBLAWAR_EN | LBLAWAR_512MB; + +	pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR; +	pci_law[1].ar = LBLAWAR_EN | LBLAWAR_1MB; + +	mpc83xx_pci_init(1, reg, 0); +} + +#if defined(CONFIG_OF_BOARD_SETUP) + +/* + * Prototypes of functions that we use. + */ +void ft_cpu_setup(void *blob, bd_t *bd); + +#ifdef CONFIG_PCI +void ft_pci_setup(void *blob, bd_t *bd); +#endif + +void +ft_board_setup(void *blob, bd_t *bd) +{ +	int nodeoffset; +	int tmp[2]; + +	nodeoffset = fdt_find_node_by_path(blob, "/memory"); +	if (nodeoffset >= 0) { +		tmp[0] = cpu_to_be32(bd->bi_memstart); +		tmp[1] = cpu_to_be32(bd->bi_memsize); +		fdt_setprop(blob, nodeoffset, "reg", tmp, sizeof(tmp)); +	} + +	ft_cpu_setup(blob, bd); + +#ifdef CONFIG_PCI +	ft_pci_setup(blob, bd); +#endif +} +#endif /* CONFIG_OF_BOARD_SETUP */ diff --git a/board/mpc8349emds/mpc8349emds.c b/board/mpc8349emds/mpc8349emds.c index 071591ed8..521d1bbd4 100644 --- a/board/mpc8349emds/mpc8349emds.c +++ b/board/mpc8349emds/mpc8349emds.c @@ -29,7 +29,6 @@  #include <i2c.h>  #include <spd.h>  #include <miiphy.h> -#include <command.h>  #if defined(CONFIG_SPD_EEPROM)  #include <spd_sdram.h>  #endif @@ -258,332 +257,6 @@ void sdram_init(void)  }  #endif -#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) -/* - * ECC user commands - */ -void ecc_print_status(void) -{ -	volatile immap_t *immap = (immap_t *)CFG_IMMR; -	volatile ddr83xx_t *ddr = &immap->ddr; - -	printf("\nECC mode: %s\n\n", (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); - -	/* Interrupts */ -	printf("Memory Error Interrupt Enable:\n"); -	printf("  Multiple-Bit Error Interrupt Enable: %d\n", -			(ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); -	printf("  Single-Bit Error Interrupt Enable: %d\n", -			(ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); -	printf("  Memory Select Error Interrupt Enable: %d\n\n", -			(ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); - -	/* Error disable */ -	printf("Memory Error Disable:\n"); -	printf("  Multiple-Bit Error Disable: %d\n", -			(ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); -	printf("  Sinle-Bit Error Disable: %d\n", -			(ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); -	printf("  Memory Select Error Disable: %d\n\n", -			(ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); - -	/* Error injection */ -	printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", -			ddr->data_err_inject_hi, ddr->data_err_inject_lo); - -	printf("Memory Data Path Error Injection Mask ECC:\n"); -	printf("  ECC Mirror Byte: %d\n", -			(ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); -	printf("  ECC Injection Enable: %d\n", -			(ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); -	printf("  ECC Error Injection Mask: 0x%02x\n\n", -			ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); - -	/* SBE counter/threshold */ -	printf("Memory Single-Bit Error Management (0..255):\n"); -	printf("  Single-Bit Error Threshold: %d\n", -			(ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); -	printf("  Single-Bit Error Counter: %d\n\n", -			(ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); - -	/* Error detect */ -	printf("Memory Error Detect:\n"); -	printf("  Multiple Memory Errors: %d\n", -			(ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); -	printf("  Multiple-Bit Error: %d\n", -			(ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); -	printf("  Single-Bit Error: %d\n", -			(ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); -	printf("  Memory Select Error: %d\n\n", -			(ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); - -	/* Capture data */ -	printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); -	printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", -			ddr->capture_data_hi, ddr->capture_data_lo); -	printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", -		ddr->capture_ecc & CAPTURE_ECC_ECE); - -	printf("Memory Error Attributes Capture:\n"); -	printf("  Data Beat Number: %d\n", -			(ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> ECC_CAPT_ATTR_BNUM_SHIFT); -	printf("  Transaction Size: %d\n", -			(ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> ECC_CAPT_ATTR_TSIZ_SHIFT); -	printf("  Transaction Source: %d\n", -			(ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> ECC_CAPT_ATTR_TSRC_SHIFT); -	printf("  Transaction Type: %d\n", -			(ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> ECC_CAPT_ATTR_TTYP_SHIFT); -	printf("  Error Information Valid: %d\n\n", -			ddr->capture_attributes & ECC_CAPT_ATTR_VLD); -} - -int do_ecc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ -	volatile immap_t *immap = (immap_t *)CFG_IMMR; -	volatile ddr83xx_t *ddr = &immap->ddr; -	volatile u32 val; -	u64 *addr, count, val64; -	register u64 *i; - -	if (argc > 4) { -		printf ("Usage:\n%s\n", cmdtp->usage); -		return 1; -	} - -	if (argc == 2) { -		if (strcmp(argv[1], "status") == 0) { -			ecc_print_status(); -			return 0; -		} else if (strcmp(argv[1], "captureclear") == 0) { -			ddr->capture_address = 0; -			ddr->capture_data_hi = 0; -			ddr->capture_data_lo = 0; -			ddr->capture_ecc = 0; -			ddr->capture_attributes = 0; -			return 0; -		} -	} - -	if (argc == 3) { -		if (strcmp(argv[1], "sbecnt") == 0) { -			val = simple_strtoul(argv[2], NULL, 10); -			if (val > 255) { -				printf("Incorrect Counter value, should be 0..255\n"); -				return 1; -			} - -			val = (val << ECC_ERROR_MAN_SBEC_SHIFT); -			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); - -			ddr->err_sbe = val; -			return 0; -		} else if (strcmp(argv[1], "sbethr") == 0) { -			val = simple_strtoul(argv[2], NULL, 10); -			if (val > 255) { -				printf("Incorrect Counter value, should be 0..255\n"); -				return 1; -			} - -			val = (val << ECC_ERROR_MAN_SBET_SHIFT); -			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); - -			ddr->err_sbe = val; -			return 0; -		} else if (strcmp(argv[1], "errdisable") == 0) { -			val = ddr->err_disable; - -			if (strcmp(argv[2], "+sbe") == 0) { -				val |= ECC_ERROR_DISABLE_SBED; -			} else if (strcmp(argv[2], "+mbe") == 0) { -				val |= ECC_ERROR_DISABLE_MBED; -			} else if (strcmp(argv[2], "+mse") == 0) { -				val |= ECC_ERROR_DISABLE_MSED; -			} else if (strcmp(argv[2], "+all") == 0) { -				val |= (ECC_ERROR_DISABLE_SBED | -					ECC_ERROR_DISABLE_MBED | -					ECC_ERROR_DISABLE_MSED); -			} else if (strcmp(argv[2], "-sbe") == 0) { -				val &= ~ECC_ERROR_DISABLE_SBED; -			} else if (strcmp(argv[2], "-mbe") == 0) { -				val &= ~ECC_ERROR_DISABLE_MBED; -			} else if (strcmp(argv[2], "-mse") == 0) { -				val &= ~ECC_ERROR_DISABLE_MSED; -			} else if (strcmp(argv[2], "-all") == 0) { -				val &= ~(ECC_ERROR_DISABLE_SBED | -					ECC_ERROR_DISABLE_MBED | -					ECC_ERROR_DISABLE_MSED); -			} else { -				printf("Incorrect err_disable field\n"); -				return 1; -			} - -			ddr->err_disable = val; -			__asm__ __volatile__ ("sync"); -			__asm__ __volatile__ ("isync"); -			return 0; -		} else if (strcmp(argv[1], "errdetectclr") == 0) { -			val = ddr->err_detect; - -			if (strcmp(argv[2], "mme") == 0) { -				val |= ECC_ERROR_DETECT_MME; -			} else if (strcmp(argv[2], "sbe") == 0) { -				val |= ECC_ERROR_DETECT_SBE; -			} else if (strcmp(argv[2], "mbe") == 0) { -				val |= ECC_ERROR_DETECT_MBE; -			} else if (strcmp(argv[2], "mse") == 0) { -				val |= ECC_ERROR_DETECT_MSE; -			} else if (strcmp(argv[2], "all") == 0) { -				val |= (ECC_ERROR_DETECT_MME | -					ECC_ERROR_DETECT_MBE | -					ECC_ERROR_DETECT_SBE | -					ECC_ERROR_DETECT_MSE); -			} else { -				printf("Incorrect err_detect field\n"); -				return 1; -			} - -			ddr->err_detect = val; -			return 0; -		} else if (strcmp(argv[1], "injectdatahi") == 0) { -			val = simple_strtoul(argv[2], NULL, 16); - -			ddr->data_err_inject_hi = val; -			return 0; -		} else if (strcmp(argv[1], "injectdatalo") == 0) { -			val = simple_strtoul(argv[2], NULL, 16); - -			ddr->data_err_inject_lo = val; -			return 0; -		} else if (strcmp(argv[1], "injectecc") == 0) { -			val = simple_strtoul(argv[2], NULL, 16); -			if (val > 0xff) { -				printf("Incorrect ECC inject mask, should be 0x00..0xff\n"); -				return 1; -			} -			val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); - -			ddr->ecc_err_inject = val; -			return 0; -		} else if (strcmp(argv[1], "inject") == 0) { -			val = ddr->ecc_err_inject; - -			if (strcmp(argv[2], "en") == 0) -				val |= ECC_ERR_INJECT_EIEN; -			else if (strcmp(argv[2], "dis") == 0) -				val &= ~ECC_ERR_INJECT_EIEN; -			else -				printf("Incorrect command\n"); - -			ddr->ecc_err_inject = val; -			__asm__ __volatile__ ("sync"); -			__asm__ __volatile__ ("isync"); -			return 0; -		} else if (strcmp(argv[1], "mirror") == 0) { -			val = ddr->ecc_err_inject; - -			if (strcmp(argv[2], "en") == 0) -				val |= ECC_ERR_INJECT_EMB; -			else if (strcmp(argv[2], "dis") == 0) -				val &= ~ECC_ERR_INJECT_EMB; -			else -				printf("Incorrect command\n"); - -			ddr->ecc_err_inject = val; -			return 0; -		} -	} - -	if (argc == 4) { -		if (strcmp(argv[1], "test") == 0) { -			addr = (u64 *)simple_strtoul(argv[2], NULL, 16); -			count = simple_strtoul(argv[3], NULL, 16); - -			if ((u32)addr % 8) { -				printf("Address not alligned on double word boundary\n"); -				return 1; -			} - -			disable_interrupts(); -			icache_disable(); - -			for (i = addr; i < addr + count; i++) { -				/* enable injects */ -				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; -				__asm__ __volatile__ ("sync"); -				__asm__ __volatile__ ("isync"); - -				/* write memory location injecting errors */ -				*i = 0x1122334455667788ULL; -				__asm__ __volatile__ ("sync"); - -				/* disable injects */ -				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; -				__asm__ __volatile__ ("sync"); -				__asm__ __volatile__ ("isync"); - -				/* read data, this generates ECC error */ -				val64 = *i; -				__asm__ __volatile__ ("sync"); - -				/* disable errors for ECC */ -				ddr->err_disable |= ~ECC_ERROR_ENABLE; -				__asm__ __volatile__ ("sync"); -				__asm__ __volatile__ ("isync"); - -				/* re-initialize memory, write the location again -				 * NOT injecting errors this time */ -				*i = 0xcafecafecafecafeULL; -				__asm__ __volatile__ ("sync"); - -				/* enable errors for ECC */ -				ddr->err_disable &= ECC_ERROR_ENABLE; -				__asm__ __volatile__ ("sync"); -				__asm__ __volatile__ ("isync"); -			} - -			icache_enable(); -			enable_interrupts(); - -			return 0; -		} -	} - -	printf ("Usage:\n%s\n", cmdtp->usage); -	return 1; -} - -U_BOOT_CMD( -	ecc,     4,     0,      do_ecc, -	"ecc     - support for DDR ECC features\n", -	"status              - print out status info\n" -	"ecc captureclear        - clear capture regs data\n" -	"ecc sbecnt <val>        - set Single-Bit Error counter\n" -	"ecc sbethr <val>        - set Single-Bit Threshold\n" -	"ecc errdisable <flag>   - clear/set disable Memory Error Disable, flag:\n" -	"  [-|+]sbe - Single-Bit Error\n" -	"  [-|+]mbe - Multiple-Bit Error\n" -	"  [-|+]mse - Memory Select Error\n" -	"  [-|+]all - all errors\n" -	"ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" -	"  mme - Multiple Memory Errors\n" -	"  sbe - Single-Bit Error\n" -	"  mbe - Multiple-Bit Error\n" -	"  mse - Memory Select Error\n" -	"  all - all errors\n" -	"ecc injectdatahi <hi>  - set Memory Data Path Error Injection Mask High\n" -	"ecc injectdatalo <lo>  - set Memory Data Path Error Injection Mask Low\n" -	"ecc injectecc <ecc>    - set ECC Error Injection Mask\n" -	"ecc inject <en|dis>    - enable/disable error injection\n" -	"ecc mirror <en|dis>    - enable/disable mirror byte\n" -	"ecc test <addr> <cnt>  - test mem region:\n" -	"  - enables injects\n" -	"  - writes pattern injecting errors\n" -	"  - disables injects\n" -	"  - reads pattern back, generates error\n" -	"  - re-inits memory" -); -#endif /* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ -  #if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)  void  ft_board_setup(void *blob, bd_t *bd) diff --git a/board/mpc8349itx/config.mk b/board/mpc8349itx/config.mk index 1901fdc2c..79f1765fa 100644 --- a/board/mpc8349itx/config.mk +++ b/board/mpc8349itx/config.mk @@ -29,9 +29,3 @@ sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp  ifndef TEXT_BASE  TEXT_BASE  =   0xFEF00000  endif - -ifneq ($(OBJTREE),$(SRCTREE)) -# We are building u-boot in a separate directory, use generated -# .lds script from OBJTREE directory. -LDSCRIPT := $(OBJTREE)/board/$(BOARDDIR)/u-boot.lds -endif diff --git a/board/mpc8360emds/mpc8360emds.c b/board/mpc8360emds/mpc8360emds.c index 562eb8b53..3fa093d1d 100644 --- a/board/mpc8360emds/mpc8360emds.c +++ b/board/mpc8360emds/mpc8360emds.c @@ -1,8 +1,6 @@  /*   * Copyright (C) 2006 Freescale Semiconductor, Inc. - *   * Dave Liu <daveliu@freescale.com> - * based on board/mpc8349emds/mpc8349emds.c   *   * See file CREDITS for list of people who contributed to this   * project. @@ -19,7 +17,6 @@  #include <i2c.h>  #include <spd.h>  #include <miiphy.h> -#include <command.h>  #if defined(CONFIG_PCI)  #include <pci.h>  #endif @@ -30,8 +27,7 @@  #endif  #if defined(CONFIG_OF_FLAT_TREE)  #include <ft_build.h> -#endif -#if defined(CONFIG_OF_LIBFDT) +#elif defined(CONFIG_OF_LIBFDT)  #include <libfdt.h>  #include <libfdt_env.h>  #endif @@ -103,7 +99,9 @@ int board_early_init_f(void)  	/* Disable G1TXCLK, G2TXCLK h/w buffers (rev.2 h/w bug workaround) */  	if (immr->sysconf.spridr == SPR_8360_REV20 || -	    immr->sysconf.spridr == SPR_8360E_REV20) +	    immr->sysconf.spridr == SPR_8360E_REV20 || +	    immr->sysconf.spridr == SPR_8360_REV21 || +	    immr->sysconf.spridr == SPR_8360E_REV21)  		bcsr[0xe] = 0x30;  	return 0; @@ -287,381 +285,6 @@ void sdram_init(void)  }  #endif -#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) -/* - * ECC user commands - */ -void ecc_print_status(void) -{ -	volatile immap_t *immap = (immap_t *) CFG_IMMR; -	volatile ddr83xx_t *ddr = &immap->ddr; - -	printf("\nECC mode: %s\n\n", -	       (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); - -	/* Interrupts */ -	printf("Memory Error Interrupt Enable:\n"); -	printf("  Multiple-Bit Error Interrupt Enable: %d\n", -	       (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); -	printf("  Single-Bit Error Interrupt Enable: %d\n", -	       (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); -	printf("  Memory Select Error Interrupt Enable: %d\n\n", -	       (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); - -	/* Error disable */ -	printf("Memory Error Disable:\n"); -	printf("  Multiple-Bit Error Disable: %d\n", -	       (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); -	printf("  Sinle-Bit Error Disable: %d\n", -	       (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); -	printf("  Memory Select Error Disable: %d\n\n", -	       (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); - -	/* Error injection */ -	printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", -	       ddr->data_err_inject_hi, ddr->data_err_inject_lo); - -	printf("Memory Data Path Error Injection Mask ECC:\n"); -	printf("  ECC Mirror Byte: %d\n", -	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); -	printf("  ECC Injection Enable: %d\n", -	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); -	printf("  ECC Error Injection Mask: 0x%02x\n\n", -	       ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); - -	/* SBE counter/threshold */ -	printf("Memory Single-Bit Error Management (0..255):\n"); -	printf("  Single-Bit Error Threshold: %d\n", -	       (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); -	printf("  Single-Bit Error Counter: %d\n\n", -	       (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); - -	/* Error detect */ -	printf("Memory Error Detect:\n"); -	printf("  Multiple Memory Errors: %d\n", -	       (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); -	printf("  Multiple-Bit Error: %d\n", -	       (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); -	printf("  Single-Bit Error: %d\n", -	       (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); -	printf("  Memory Select Error: %d\n\n", -	       (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); - -	/* Capture data */ -	printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); -	printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", -	       ddr->capture_data_hi, ddr->capture_data_lo); -	printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", -	       ddr->capture_ecc & CAPTURE_ECC_ECE); - -	printf("Memory Error Attributes Capture:\n"); -	printf(" Data Beat Number: %d\n", -	       (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> -	       ECC_CAPT_ATTR_BNUM_SHIFT); -	printf("  Transaction Size: %d\n", -	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> -	       ECC_CAPT_ATTR_TSIZ_SHIFT); -	printf("  Transaction Source: %d\n", -	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> -	       ECC_CAPT_ATTR_TSRC_SHIFT); -	printf("  Transaction Type: %d\n", -	       (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> -	       ECC_CAPT_ATTR_TTYP_SHIFT); -	printf("  Error Information Valid: %d\n\n", -	       ddr->capture_attributes & ECC_CAPT_ATTR_VLD); -} - -int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) -{ -	volatile immap_t *immap = (immap_t *) CFG_IMMR; -	volatile ddr83xx_t *ddr = &immap->ddr; -	volatile u32 val; -	u64 *addr; -	u32 count; -	register u64 *i; -	u32 ret[2]; -	u32 pattern[2]; -	u32 writeback[2]; - -	/* The pattern is written into memory to generate error */ -	pattern[0] = 0xfedcba98UL; -	pattern[1] = 0x76543210UL; - -	/* After injecting error, re-initialize the memory with the value */ -	writeback[0] = 0x01234567UL; -	writeback[1] = 0x89abcdefUL; - -	if (argc > 4) { -		printf("Usage:\n%s\n", cmdtp->usage); -		return 1; -	} - -	if (argc == 2) { -		if (strcmp(argv[1], "status") == 0) { -			ecc_print_status(); -			return 0; -		} else if (strcmp(argv[1], "captureclear") == 0) { -			ddr->capture_address = 0; -			ddr->capture_data_hi = 0; -			ddr->capture_data_lo = 0; -			ddr->capture_ecc = 0; -			ddr->capture_attributes = 0; -			return 0; -		} -	} -	if (argc == 3) { -		if (strcmp(argv[1], "sbecnt") == 0) { -			val = simple_strtoul(argv[2], NULL, 10); -			if (val > 255) { -				printf("Incorrect Counter value, " -				       "should be 0..255\n"); -				return 1; -			} - -			val = (val << ECC_ERROR_MAN_SBEC_SHIFT); -			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); - -			ddr->err_sbe = val; -			return 0; -		} else if (strcmp(argv[1], "sbethr") == 0) { -			val = simple_strtoul(argv[2], NULL, 10); -			if (val > 255) { -				printf("Incorrect Counter value, " -				       "should be 0..255\n"); -				return 1; -			} - -			val = (val << ECC_ERROR_MAN_SBET_SHIFT); -			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); - -			ddr->err_sbe = val; -			return 0; -		} else if (strcmp(argv[1], "errdisable") == 0) { -			val = ddr->err_disable; - -			if (strcmp(argv[2], "+sbe") == 0) { -				val |= ECC_ERROR_DISABLE_SBED; -			} else if (strcmp(argv[2], "+mbe") == 0) { -				val |= ECC_ERROR_DISABLE_MBED; -			} else if (strcmp(argv[2], "+mse") == 0) { -				val |= ECC_ERROR_DISABLE_MSED; -			} else if (strcmp(argv[2], "+all") == 0) { -				val |= (ECC_ERROR_DISABLE_SBED | -					ECC_ERROR_DISABLE_MBED | -					ECC_ERROR_DISABLE_MSED); -			} else if (strcmp(argv[2], "-sbe") == 0) { -				val &= ~ECC_ERROR_DISABLE_SBED; -			} else if (strcmp(argv[2], "-mbe") == 0) { -				val &= ~ECC_ERROR_DISABLE_MBED; -			} else if (strcmp(argv[2], "-mse") == 0) { -				val &= ~ECC_ERROR_DISABLE_MSED; -			} else if (strcmp(argv[2], "-all") == 0) { -				val &= ~(ECC_ERROR_DISABLE_SBED | -					 ECC_ERROR_DISABLE_MBED | -					 ECC_ERROR_DISABLE_MSED); -			} else { -				printf("Incorrect err_disable field\n"); -				return 1; -			} - -			ddr->err_disable = val; -			__asm__ __volatile__("sync"); -			__asm__ __volatile__("isync"); -			return 0; -		} else if (strcmp(argv[1], "errdetectclr") == 0) { -			val = ddr->err_detect; - -			if (strcmp(argv[2], "mme") == 0) { -				val |= ECC_ERROR_DETECT_MME; -			} else if (strcmp(argv[2], "sbe") == 0) { -				val |= ECC_ERROR_DETECT_SBE; -			} else if (strcmp(argv[2], "mbe") == 0) { -				val |= ECC_ERROR_DETECT_MBE; -			} else if (strcmp(argv[2], "mse") == 0) { -				val |= ECC_ERROR_DETECT_MSE; -			} else if (strcmp(argv[2], "all") == 0) { -				val |= (ECC_ERROR_DETECT_MME | -					ECC_ERROR_DETECT_MBE | -					ECC_ERROR_DETECT_SBE | -					ECC_ERROR_DETECT_MSE); -			} else { -				printf("Incorrect err_detect field\n"); -				return 1; -			} - -			ddr->err_detect = val; -			return 0; -		} else if (strcmp(argv[1], "injectdatahi") == 0) { -			val = simple_strtoul(argv[2], NULL, 16); - -			ddr->data_err_inject_hi = val; -			return 0; -		} else if (strcmp(argv[1], "injectdatalo") == 0) { -			val = simple_strtoul(argv[2], NULL, 16); - -			ddr->data_err_inject_lo = val; -			return 0; -		} else if (strcmp(argv[1], "injectecc") == 0) { -			val = simple_strtoul(argv[2], NULL, 16); -			if (val > 0xff) { -				printf("Incorrect ECC inject mask, " -				       "should be 0x00..0xff\n"); -				return 1; -			} -			val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); - -			ddr->ecc_err_inject = val; -			return 0; -		} else if (strcmp(argv[1], "inject") == 0) { -			val = ddr->ecc_err_inject; - -			if (strcmp(argv[2], "en") == 0) -				val |= ECC_ERR_INJECT_EIEN; -			else if (strcmp(argv[2], "dis") == 0) -				val &= ~ECC_ERR_INJECT_EIEN; -			else -				printf("Incorrect command\n"); - -			ddr->ecc_err_inject = val; -			__asm__ __volatile__("sync"); -			__asm__ __volatile__("isync"); -			return 0; -		} else if (strcmp(argv[1], "mirror") == 0) { -			val = ddr->ecc_err_inject; - -			if (strcmp(argv[2], "en") == 0) -				val |= ECC_ERR_INJECT_EMB; -			else if (strcmp(argv[2], "dis") == 0) -				val &= ~ECC_ERR_INJECT_EMB; -			else -				printf("Incorrect command\n"); - -			ddr->ecc_err_inject = val; -			return 0; -		} -	} -	if (argc == 4) { -		if (strcmp(argv[1], "testdw") == 0) { -			addr = (u64 *) simple_strtoul(argv[2], NULL, 16); -			count = simple_strtoul(argv[3], NULL, 16); - -			if ((u32) addr % 8) { -				printf("Address not alligned on " -				       "double word boundary\n"); -				return 1; -			} -			disable_interrupts(); - -			for (i = addr; i < addr + count; i++) { - -				/* enable injects */ -				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; -				__asm__ __volatile__("sync"); -				__asm__ __volatile__("isync"); - -				/* write memory location injecting errors */ -				ppcDWstore((u32 *) i, pattern); -				__asm__ __volatile__("sync"); - -				/* disable injects */ -				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; -				__asm__ __volatile__("sync"); -				__asm__ __volatile__("isync"); - -				/* read data, this generates ECC error */ -				ppcDWload((u32 *) i, ret); -				__asm__ __volatile__("sync"); - -				/* re-initialize memory, double word write the location again, -				 * generates new ECC code this time */ -				ppcDWstore((u32 *) i, writeback); -				__asm__ __volatile__("sync"); -			} -			enable_interrupts(); -			return 0; -		} -		if (strcmp(argv[1], "testword") == 0) { -			addr = (u64 *) simple_strtoul(argv[2], NULL, 16); -			count = simple_strtoul(argv[3], NULL, 16); - -			if ((u32) addr % 8) { -				printf("Address not alligned on " -				       "double word boundary\n"); -				return 1; -			} -			disable_interrupts(); - -			for (i = addr; i < addr + count; i++) { - -				/* enable injects */ -				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; -				__asm__ __volatile__("sync"); -				__asm__ __volatile__("isync"); - -				/* write memory location injecting errors */ -				*(u32 *) i = 0xfedcba98UL; -				__asm__ __volatile__("sync"); - -				/* sub double word write, -				 * bus will read-modify-write, -				 * generates ECC error */ -				*((u32 *) i + 1) = 0x76543210UL; -				__asm__ __volatile__("sync"); - -				/* disable injects */ -				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; -				__asm__ __volatile__("sync"); -				__asm__ __volatile__("isync"); - -				/* re-initialize memory, -				 * double word write the location again, -				 * generates new ECC code this time */ -				ppcDWstore((u32 *) i, writeback); -				__asm__ __volatile__("sync"); -			} -			enable_interrupts(); -			return 0; -		} -	} -	printf("Usage:\n%s\n", cmdtp->usage); -	return 1; -} - -U_BOOT_CMD(ecc, 4, 0, do_ecc, -	   "ecc     - support for DDR ECC features\n", -	   "status              - print out status info\n" -	   "ecc captureclear        - clear capture regs data\n" -	   "ecc sbecnt <val>        - set Single-Bit Error counter\n" -	   "ecc sbethr <val>        - set Single-Bit Threshold\n" -	   "ecc errdisable <flag>   - clear/set disable Memory Error Disable, flag:\n" -	   "  [-|+]sbe - Single-Bit Error\n" -	   "  [-|+]mbe - Multiple-Bit Error\n" -	   "  [-|+]mse - Memory Select Error\n" -	   "  [-|+]all - all errors\n" -	   "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" -	   "  mme - Multiple Memory Errors\n" -	   "  sbe - Single-Bit Error\n" -	   "  mbe - Multiple-Bit Error\n" -	   "  mse - Memory Select Error\n" -	   "  all - all errors\n" -	   "ecc injectdatahi <hi>  - set Memory Data Path Error Injection Mask High\n" -	   "ecc injectdatalo <lo>  - set Memory Data Path Error Injection Mask Low\n" -	   "ecc injectecc <ecc>    - set ECC Error Injection Mask\n" -	   "ecc inject <en|dis>    - enable/disable error injection\n" -	   "ecc mirror <en|dis>    - enable/disable mirror byte\n" -	   "ecc testdw <addr> <cnt>  - test mem region with double word access:\n" -	   "  - enables injects\n" -	   "  - writes pattern injecting errors with double word access\n" -	   "  - disables injects\n" -	   "  - reads pattern back with double word access, generates error\n" -	   "  - re-inits memory\n" -	   "ecc testword <addr> <cnt>  - test mem region with word access:\n" -	   "  - enables injects\n" -	   "  - writes pattern injecting errors with word access\n" -	   "  - writes pattern with word access, generates error\n" -	   "  - disables injects\n" "  - re-inits memory"); -#endif				/* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ -  #if (defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)) \       && defined(CONFIG_OF_BOARD_SETUP) @@ -681,11 +304,11 @@ ft_board_setup(void *blob, bd_t *bd)  	int nodeoffset;  	int tmp[2]; -	nodeoffset = fdt_path_offset (fdt, "/memory"); +	nodeoffset = fdt_find_node_by_path(blob, "/memory");  	if (nodeoffset >= 0) {  		tmp[0] = cpu_to_be32(bd->bi_memstart);  		tmp[1] = cpu_to_be32(bd->bi_memsize); -		fdt_setprop(fdt, nodeoffset, "reg", tmp, sizeof(tmp)); +		fdt_setprop(blob, nodeoffset, "reg", tmp, sizeof(tmp));  	}  #else  	u32 *p; diff --git a/board/mpc8360emds/pci.c b/board/mpc8360emds/pci.c index 158effe0a..8f904710c 100644 --- a/board/mpc8360emds/pci.c +++ b/board/mpc8360emds/pci.c @@ -20,8 +20,7 @@  #include <i2c.h>  #if defined(CONFIG_OF_FLAT_TREE)  #include <ft_build.h> -#endif -#if defined(CONFIG_OF_LIBFDT) +#elif defined(CONFIG_OF_LIBFDT)  #include <libfdt.h>  #include <libfdt_env.h>  #endif @@ -207,7 +206,7 @@ void pci_init_board(void)  	/* Switch temporarily to I2C bus #2 */  	orig_i2c_bus = i2c_get_bus_num(); - 	i2c_set_bus_num(1); +	i2c_set_bus_num(1);  	val8 = 0;  	i2c_write(0x23, 0x6, 1, &val8, 1); @@ -311,26 +310,25 @@ ft_pci_setup(void *blob, bd_t *bd)  	int err;  	int tmp[2]; -	nodeoffset = fdt_path_offset (fdt, "/" OF_SOC "/pci@8500"); +	nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8500");  	if (nodeoffset >= 0) {  		tmp[0] = cpu_to_be32(hose[0].first_busno);  		tmp[1] = cpu_to_be32(hose[0].last_busno); -		err = fdt_setprop(fdt, nodeoffset, "bus-range", tmp, sizeof(tmp)); +		err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp));  	}  } -#endif				/* CONFIG_OF_LIBFDT */ -#ifdef CONFIG_OF_FLAT_TREE +#elif defined(CONFIG_OF_FLAT_TREE)  void  ft_pci_setup(void *blob, bd_t *bd)  { -       	u32 *p; -       	int len; +	u32 *p; +	int len; -       	p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); -       	if (p != NULL) { +	p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len); +	if (p != NULL) {  		p[0] = hose[0].first_busno;  		p[1] = hose[0].last_busno; -       	} +	}  }  #endif				/* CONFIG_OF_FLAT_TREE */  #endif				/* CONFIG_PCI */ diff --git a/board/trab/auto_update.c b/board/trab/auto_update.c index ef40c5474..92120b0d0 100644 --- a/board/trab/auto_update.c +++ b/board/trab/auto_update.c @@ -34,7 +34,7 @@  #ifdef CONFIG_AUTO_UPDATE -#ifndef CONFIG_USB_OHCI +#ifndef CONFIG_USB_OHCI_NEW  #error "must define CONFIG_USB_OHCI"  #endif diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index de5a5148f..1db0fc3c0 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -193,7 +193,12 @@ int _do_setenv (int flag, int argc, char *argv[])  		 * Ethernet Address and serial# can be set only once,  		 * ver is readonly.  		 */ +#ifdef CONFIG_HAS_UID +		/* Allow serial# forced overwrite with 0xdeaf4add flag */ +		if ( ((strcmp (name, "serial#") == 0) && (flag != 0xdeaf4add)) || +#else  		if ( (strcmp (name, "serial#") == 0) || +#endif  		    ((strcmp (name, "ethaddr") == 0)  #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)  		     && (strcmp ((char *)env_get_addr(oldval),MK_STR(CONFIG_ETHADDR)) != 0) @@ -397,7 +402,15 @@ void setenv (char *varname, char *varvalue)  		_do_setenv (0, 3, argv);  } -int do_setenv ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +#ifdef CONFIG_HAS_UID +void forceenv (char *varname, char *varvalue) +{ +	char *argv[4] = { "forceenv", varname, varvalue, NULL }; +	_do_setenv (0xdeaf4add, 3, argv); +} +#endif + +int do_setenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  {  	if (argc < 2) {  		printf ("Usage:\n%s\n", cmdtp->usage); diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 56c21660f..aec558ad2 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -129,7 +129,11 @@ static int usb_kbd_testc(void)  static int usb_kbd_getc(void)  {  	char c; -	while(usb_in_pointer==usb_out_pointer); +	while(usb_in_pointer==usb_out_pointer) { +#ifdef CFG_USB_EVENT_POLL +		usb_event_poll(); +#endif +	}  	if((usb_out_pointer+1)==USB_KBD_BUFFER_LEN)  		usb_out_pointer=0;  	else diff --git a/cpu/arm920t/at91rm9200/Makefile b/cpu/arm920t/at91rm9200/Makefile index 8d4e478fb..eaabad26a 100644 --- a/cpu/arm920t/at91rm9200/Makefile +++ b/cpu/arm920t/at91rm9200/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(SOC).a  COBJS	= bcm5221.o dm9161.o ether.o i2c.o interrupts.o \ -	  lxt972.o serial.o usb_ohci.o +	  lxt972.o serial.o usb.o  SOBJS	= lowlevel_init.o  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/cpu/arm920t/at91rm9200/usb.c b/cpu/arm920t/at91rm9200/usb.c new file mode 100644 index 000000000..366262e4c --- /dev/null +++ b/cpu/arm920t/at91rm9200/usb.c @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2006 + * DENX Software Engineering <mk@denx.de> + * + * 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> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) +# ifdef CONFIG_AT91RM9200 + +#include <asm/arch/hardware.h> + +int usb_cpu_init() +{ +	/* Enable USB host clock. */ +	*AT91C_PMC_SCER = AT91C_PMC_UHP;	/* 48MHz clock enabled for UHP */ +	*AT91C_PMC_PCER = 1 << AT91C_ID_UHP;	/* Peripheral Clock Enable Register */ +	return 0; +} + +int usb_cpu_stop() +{ +	/* Initialization failed */ +	*AT91C_PMC_PCDR = 1 << AT91C_ID_UHP;	/* Peripheral Clock Disable Register */ +	*AT91C_PMC_SCDR = AT91C_PMC_UHP;	/* 48MHz clock disabled for UHP */ +	return 0; +} + +int usb_cpu_init_fail() +{ +	usb_cpu_stop(); +} + +# endif /* CONFIG_AT91RM9200 */ +#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */ diff --git a/cpu/arm920t/s3c24x0/Makefile b/cpu/arm920t/s3c24x0/Makefile index 3a7c4b35f..0ff36c596 100644 --- a/cpu/arm920t/s3c24x0/Makefile +++ b/cpu/arm920t/s3c24x0/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(SOC).a  COBJS	= i2c.o interrupts.o serial.o speed.o \ -	  usb_ohci.o +	  usb.o  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/arm920t/s3c24x0/usb.c b/cpu/arm920t/s3c24x0/usb.c new file mode 100644 index 000000000..ef5d5bf71 --- /dev/null +++ b/cpu/arm920t/s3c24x0/usb.c @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2006 + * DENX Software Engineering <mk@denx.de> + * + * 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> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) +# if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) + +#if defined(CONFIG_S3C2400) +# include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +# include <s3c2410.h> +#endif + +int usb_cpu_init (void) +{ + +	S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); +	S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); + +	/* +	 * Set the 48 MHz UPLL clocking. Values are taken from +	 * "PLL value selection guide", 6-23, s3c2400_UM.pdf. +	 */ +	clk_power->UPLLCON = ((40 << 12) + (1 << 4) + 2); +	gpio->MISCCR |= 0x8; /* 1 = use pads related USB for USB host */ + +	/* +	 * Enable USB host clock. +	 */ +	clk_power->CLKCON |= (1 << 4); + +	return 0; +} + +int usb_cpu_stop (void) +{ +	S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); +	/* may not want to do this */ +	clk_power->CLKCON &= ~(1 << 4); +	return 0; +} + +int usb_cpu_init_fail (void) +{ +	S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); +	clk_power->CLKCON &= ~(1 << 4); +	return 0; +} + +# endif /* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) */ +#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */ diff --git a/cpu/arm926ejs/davinci/Makefile b/cpu/arm926ejs/davinci/Makefile new file mode 100644 index 000000000..0f77f402e --- /dev/null +++ b/cpu/arm926ejs/davinci/Makefile @@ -0,0 +1,49 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> +# +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(SOC).a + +COBJS	= timer.o ether.o lxt972.o dp83848.o i2c.o nand.o +SOBJS	= lowlevel_init.o reset.o + +SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS)) +START	:= $(addprefix $(obj),$(START)) + +all:	$(obj).depend $(LIB) + +$(LIB):	$(OBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/davinci/dp83848.c b/cpu/arm926ejs/davinci/dp83848.c new file mode 100644 index 000000000..5719845b3 --- /dev/null +++ b/cpu/arm926ejs/davinci/dp83848.c @@ -0,0 +1,156 @@ +/* + * National Semiconductor DP83848 PHY Driver for TI DaVinci + * (TMS320DM644x) based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * 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 <net.h> +#include <dp83848.h> +#include <asm/arch/emac_defs.h> + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +int dp83848_is_phy_connected(int phy_addr) +{ +	u_int16_t	id1, id2; + +	if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID1_REG, &id1)) +		return(0); +	if (!dm644x_eth_phy_read(phy_addr, DP83848_PHYID2_REG, &id2)) +		return(0); + +	if ((id1 == DP83848_PHYID1_OUI) && (id2 == DP83848_PHYID2_OUI)) +		return(1); + +	return(0); +} + +int dp83848_get_link_speed(int phy_addr) +{ +	u_int16_t		tmp; +	volatile emac_regs*	emac = (emac_regs *)EMAC_BASE_ADDR; + +	if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp)) +		return(0); + +	if (!(tmp & DP83848_LINK_STATUS))	/* link up? */ +		return(0); + +	if (!dm644x_eth_phy_read(phy_addr, DP83848_PHY_STAT_REG, &tmp)) +		return(0); + +	/* Speed doesn't matter, there is no setting for it in EMAC... */ +	if (tmp & DP83848_SPEED) { +		if (tmp & DP83848_DUPLEX) { +			/* set DM644x EMAC for Full Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE; +		} else { +			/*set DM644x EMAC for Half Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; +		} + +		return(1); +	} else { +		if (tmp & DP83848_DUPLEX) { +			/* set DM644x EMAC for Full Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE; +		} else { +			/*set DM644x EMAC for Half Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; +		} + +		return(1); +	} + +	return(0); +} + + +int dp83848_init_phy(int phy_addr) +{ +	int	ret = 1; + +	if (!dp83848_get_link_speed(phy_addr)) { +		/* Try another time */ +		udelay(100000); +		ret = dp83848_get_link_speed(phy_addr); +	} + +	/* Disable PHY Interrupts */ +	dm644x_eth_phy_write(phy_addr, DP83848_PHY_INTR_CTRL_REG, 0); + +	return(ret); +} + + +int dp83848_auto_negotiate(int phy_addr) +{ +	u_int16_t	tmp; + + +	if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp)) +		return(0); + +	/* Restart Auto_negotiation  */ +	tmp &= ~DP83848_AUTONEG;	/* remove autonegotiation enable */ +	tmp |= DP83848_ISOLATE;		/* Electrically isolate PHY */ +	dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp); + +	/* Set the Auto_negotiation Advertisement Register +	 * MII advertising for Next page, 100BaseTxFD and HD, +	 * 10BaseTFD and HD, IEEE 802.3 +	 */ +	tmp = DP83848_NP | DP83848_TX_FDX | DP83848_TX_HDX | +	 	DP83848_10_FDX | DP83848_10_HDX | DP83848_AN_IEEE_802_3; +	dm644x_eth_phy_write(phy_addr, DP83848_ANA_REG, tmp); + + +	/* Read Control Register */ +	if (!dm644x_eth_phy_read(phy_addr, DP83848_CTL_REG, &tmp)) +		return(0); + +	tmp |= DP83848_SPEED_SELECT | DP83848_AUTONEG | DP83848_DUPLEX_MODE; +	dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp); + +	/* Restart Auto_negotiation  */ +	tmp |= DP83848_RESTART_AUTONEG; +	dm644x_eth_phy_write(phy_addr, DP83848_CTL_REG, tmp); + +	/*check AutoNegotiate complete */ +	udelay(10000); +	if (!dm644x_eth_phy_read(phy_addr, DP83848_STAT_REG, &tmp)) +		return(0); + +	if (!(tmp & DP83848_AUTONEG_COMP)) +		return(0); + +	return (dp83848_get_link_speed(phy_addr)); +} + +#endif	/* CONFIG_CMD_NET */ + +#endif	/* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm926ejs/davinci/ether.c b/cpu/arm926ejs/davinci/ether.c new file mode 100644 index 000000000..32e81d11d --- /dev/null +++ b/cpu/arm926ejs/davinci/ether.c @@ -0,0 +1,650 @@ +/* + * Ethernet driver for TI TMS320DM644x (DaVinci) chips. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright + * follows: + * + * ---------------------------------------------------------------------------- + * + * dm644x_emac.c + * + * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM + * + * Copyright (C) 2005 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + + * Modifications: + * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot. + * ver  1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors + * + */ +#include <common.h> +#include <command.h> +#include <net.h> +#include <miiphy.h> +#include <asm/arch/emac_defs.h> + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +unsigned int	emac_dbg = 0; +#define debug_emac(fmt,args...)	if (emac_dbg) printf(fmt,##args) + +/* Internal static functions */ +static int dm644x_eth_hw_init (void); +static int dm644x_eth_open (void); +static int dm644x_eth_close (void); +static int dm644x_eth_send_packet (volatile void *packet, int length); +static int dm644x_eth_rcv_packet (void); +static void dm644x_eth_mdio_enable(void); + +static int gen_init_phy(int phy_addr); +static int gen_is_phy_connected(int phy_addr); +static int gen_get_link_speed(int phy_addr); +static int gen_auto_negotiate(int phy_addr); + +/* Wrappers exported to the U-Boot proper */ +int eth_hw_init(void) +{ +	return(dm644x_eth_hw_init()); +} + +int eth_init(bd_t * bd) +{ +	return(dm644x_eth_open()); +} + +void eth_halt(void) +{ +	dm644x_eth_close(); +} + +int eth_send(volatile void *packet, int length) +{ +	return(dm644x_eth_send_packet(packet, length)); +} + +int eth_rx(void) +{ +	return(dm644x_eth_rcv_packet()); +} + +void eth_mdio_enable(void) +{ +	dm644x_eth_mdio_enable(); +} +/* End of wrappers */ + + +static u_int8_t dm644x_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +/* + * This function must be called before emac_open() if you want to override + * the default mac address. + */ +void dm644x_eth_set_mac_addr(const u_int8_t *addr) +{ +	int i; + +	for (i = 0; i < sizeof (dm644x_eth_mac_addr); i++) { +		dm644x_eth_mac_addr[i] = addr[i]; +	} +} + +/* EMAC Addresses */ +static volatile emac_regs	*adap_emac = (emac_regs *)EMAC_BASE_ADDR; +static volatile ewrap_regs	*adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR; +static volatile mdio_regs	*adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR; + +/* EMAC descriptors */ +static volatile emac_desc	*emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE); +static volatile emac_desc	*emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE); +static volatile emac_desc	*emac_rx_active_head = 0; +static volatile emac_desc	*emac_rx_active_tail = 0; +static int			emac_rx_queue_active = 0; + +/* Receive packet buffers */ +static unsigned char		emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; + +/* PHY address for a discovered PHY (0xff - not found) */ +static volatile u_int8_t	active_phy_addr = 0xff; + +phy_t				phy; + +static void dm644x_eth_mdio_enable(void) +{ +	u_int32_t	clkdiv; + +	clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; + +	adap_mdio->CONTROL = (clkdiv & 0xff) | +		MDIO_CONTROL_ENABLE | +		MDIO_CONTROL_FAULT | +		MDIO_CONTROL_FAULT_ENABLE; + +	while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;} +} + +/* + * Tries to find an active connected PHY. Returns 1 if address if found. + * If no active PHY (or more than one PHY) found returns 0. + * Sets active_phy_addr variable. + */ +static int dm644x_eth_phy_detect(void) +{ +	u_int32_t	phy_act_state; +	int		i; + +	active_phy_addr = 0xff; + +	if ((phy_act_state = adap_mdio->ALIVE) == 0) +		return(0);				/* No active PHYs */ + +	debug_emac("dm644x_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state); + +	for (i = 0; i < 32; i++) { +		if (phy_act_state & (1 << i)) { +			if (phy_act_state & ~(1 << i)) +				return(0);		/* More than one PHY */ +			else { +				active_phy_addr = i; +				return(1); +			} +		} +	} + +	return(0);	/* Just to make GCC happy */ +} + + +/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */ +int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data) +{ +	int	tmp; + +	while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} + +	adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | +				MDIO_USERACCESS0_WRITE_READ | +				((reg_num & 0x1f) << 21) | +				((phy_addr & 0x1f) << 16); + +	/* Wait for command to complete */ +	while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;} + +	if (tmp & MDIO_USERACCESS0_ACK) { +		*data = tmp & 0xffff; +		return(1); +	} + +	*data = -1; +	return(0); +} + +/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */ +int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data) +{ + +	while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} + +	adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO | +				MDIO_USERACCESS0_WRITE_WRITE | +				((reg_num & 0x1f) << 21) | +				((phy_addr & 0x1f) << 16) | +				(data & 0xffff); + +	/* Wait for command to complete */ +	while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;} + +	return(1); +} + +/* PHY functions for a generic PHY */ +static int gen_init_phy(int phy_addr) +{ +	int	ret = 1; + +	if (gen_get_link_speed(phy_addr)) { +		/* Try another time */ +		ret = gen_get_link_speed(phy_addr); +	} + +	return(ret); +} + +static int gen_is_phy_connected(int phy_addr) +{ +	u_int16_t	dummy; + +	return(dm644x_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy)); +} + +static int gen_get_link_speed(int phy_addr) +{ +	u_int16_t	tmp; + +	if (dm644x_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04)) +		return(1); + +	return(0); +} + +static int gen_auto_negotiate(int phy_addr) +{ +	u_int16_t	tmp; + +	if (!dm644x_eth_phy_read(phy_addr, PHY_BMCR, &tmp)) +		return(0); + +	/* Restart Auto_negotiation  */ +	tmp |= PHY_BMCR_AUTON; +	dm644x_eth_phy_write(phy_addr, PHY_BMCR, tmp); + +	/*check AutoNegotiate complete */ +	udelay (10000); +	if (!dm644x_eth_phy_read(phy_addr, PHY_BMSR, &tmp)) +		return(0); + +	if (!(tmp & PHY_BMSR_AUTN_COMP)) +		return(0); + +	return(gen_get_link_speed(phy_addr)); +} +/* End of generic PHY functions */ + + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +static int dm644x_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value) +{ +	return(dm644x_eth_phy_read(addr, reg, value) ? 0 : 1); +} + +static int dm644x_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value) +{ +	return(dm644x_eth_phy_write(addr, reg, value) ? 0 : 1); +} + +int dm644x_eth_miiphy_initialize(bd_t *bis) +{ +	miiphy_register(phy.name, dm644x_mii_phy_read, dm644x_mii_phy_write); + +	return(1); +} +#endif + +/* + * This function initializes the emac hardware. It does NOT initialize + * EMAC modules power or pin multiplexors, that is done by board_init() + * much earlier in bootup process. Returns 1 on success, 0 otherwise. + */ +static int dm644x_eth_hw_init(void) +{ +	u_int32_t	phy_id; +	u_int16_t	tmp; +	int		i; + +	dm644x_eth_mdio_enable(); + +	for (i = 0; i < 256; i++) { +		if (adap_mdio->ALIVE) +			break; +		udelay(10); +	} + +	if (i >= 256) { +		printf("No ETH PHY detected!!!\n"); +		return(0); +	} + +	/* Find if a PHY is connected and get it's address */ +	if (!dm644x_eth_phy_detect()) +		return(0); + +	/* Get PHY ID and initialize phy_ops for a detected PHY */ +	if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) { +		active_phy_addr = 0xff; +		return(0); +	} + +	phy_id = (tmp << 16) & 0xffff0000; + +	if (!dm644x_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) { +		active_phy_addr = 0xff; +		return(0); +	} + +	phy_id |= tmp & 0x0000ffff; + +	switch (phy_id) { +		case PHY_LXT972: +			sprintf(phy.name, "LXT972 @ 0x%02x", active_phy_addr); +			phy.init = lxt972_init_phy; +			phy.is_phy_connected = lxt972_is_phy_connected; +			phy.get_link_speed = lxt972_get_link_speed; +			phy.auto_negotiate = lxt972_auto_negotiate; +			break; +		case PHY_DP83848: +			sprintf(phy.name, "DP83848 @ 0x%02x", active_phy_addr); +			phy.init = dp83848_init_phy; +			phy.is_phy_connected = dp83848_is_phy_connected; +			phy.get_link_speed = dp83848_get_link_speed; +			phy.auto_negotiate = dp83848_auto_negotiate; +			break; +		default: +			sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr); +			phy.init = gen_init_phy; +			phy.is_phy_connected = gen_is_phy_connected; +			phy.get_link_speed = gen_get_link_speed; +			phy.auto_negotiate = gen_auto_negotiate; +	} + +	return(1); +} + + +/* Eth device open */ +static int dm644x_eth_open(void) +{ +	dv_reg_p		addr; +	u_int32_t		clkdiv, cnt; +	volatile emac_desc	*rx_desc; + +	debug_emac("+ emac_open\n"); + +	/* Reset EMAC module and disable interrupts in wrapper */ +	adap_emac->SOFTRESET = 1; +	while (adap_emac->SOFTRESET != 0) {;} +	adap_ewrap->EWCTL = 0; +	for (cnt = 0; cnt < 5; cnt++) { +		clkdiv = adap_ewrap->EWCTL; +	} + +	rx_desc = emac_rx_desc; + +	adap_emac->TXCONTROL = 0x01; +	adap_emac->RXCONTROL = 0x01; + +	/* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */ +	/* Using channel 0 only - other channels are disabled */ +	adap_emac->MACINDEX = 0; +	adap_emac->MACADDRHI = +		(dm644x_eth_mac_addr[3] << 24) | +		(dm644x_eth_mac_addr[2] << 16) | +		(dm644x_eth_mac_addr[1] << 8)  | +		(dm644x_eth_mac_addr[0]); +	adap_emac->MACADDRLO = +		(dm644x_eth_mac_addr[5] << 8) | +		(dm644x_eth_mac_addr[4]); + +	adap_emac->MACHASH1 = 0; +	adap_emac->MACHASH2 = 0; + +	/* Set source MAC address - REQUIRED */ +	adap_emac->MACSRCADDRHI = +		(dm644x_eth_mac_addr[3] << 24) | +		(dm644x_eth_mac_addr[2] << 16) | +		(dm644x_eth_mac_addr[1] << 8)  | +		(dm644x_eth_mac_addr[0]); +	adap_emac->MACSRCADDRLO = +		(dm644x_eth_mac_addr[4] << 8) | +		(dm644x_eth_mac_addr[5]); + +	/* Set DMA 8 TX / 8 RX Head pointers to 0 */ +	addr = &adap_emac->TX0HDP; +	for(cnt = 0; cnt < 16; cnt++) +		*addr++ = 0; + +	addr = &adap_emac->RX0HDP; +	for(cnt = 0; cnt < 16; cnt++) +		*addr++ = 0; + +	/* Clear Statistics (do this before setting MacControl register) */ +	addr = &adap_emac->RXGOODFRAMES; +	for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++) +		*addr++ = 0; + +	/* No multicast addressing */ +	adap_emac->MACHASH1 = 0; +	adap_emac->MACHASH2 = 0; + +	/* Create RX queue and set receive process in place */ +	emac_rx_active_head = emac_rx_desc; +	for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) { +		rx_desc->next = (u_int32_t)(rx_desc + 1); +		rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; +		rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; +		rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; +		rx_desc++; +	} + +	/* Set the last descriptor's "next" parameter to 0 to end the RX desc list */ +	rx_desc--; +	rx_desc->next = 0; +	emac_rx_active_tail = rx_desc; +	emac_rx_queue_active = 1; + +	/* Enable TX/RX */ +	adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE; +	adap_emac->RXBUFFEROFFSET = 0; + +	/* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */ +	adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN; + +	/* Enable ch 0 only */ +	adap_emac->RXUNICASTSET = 0x01; + +	/* Enable MII interface and Full duplex mode */ +	adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE); + +	/* Init MDIO & get link state */ +	clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; +	adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT); + +	if (!phy.get_link_speed(active_phy_addr)) +		return(0); + +	/* Start receive process */ +	adap_emac->RX0HDP = (u_int32_t)emac_rx_desc; + +	debug_emac("- emac_open\n"); + +	return(1); +} + +/* EMAC Channel Teardown */ +static void dm644x_eth_ch_teardown(int ch) +{ +	dv_reg		dly = 0xff; +	dv_reg		cnt; + +	debug_emac("+ emac_ch_teardown\n"); + +	if (ch == EMAC_CH_TX) { +		/* Init TX channel teardown */ +		adap_emac->TXTEARDOWN = 1; +		for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) { +			/* Wait here for Tx teardown completion interrupt to occur +			 * Note: A task delay can be called here to pend rather than +			 * occupying CPU cycles - anyway it has been found that teardown +			 * takes very few cpu cycles and does not affect functionality */ +			 dly--; +			 udelay(1); +			 if (dly == 0) +			 	break; +		} +		adap_emac->TX0CP = cnt; +		adap_emac->TX0HDP = 0; +	} else { +		/* Init RX channel teardown */ +		adap_emac->RXTEARDOWN = 1; +		for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) { +			/* Wait here for Rx teardown completion interrupt to occur +			 * Note: A task delay can be called here to pend rather than +			 * occupying CPU cycles - anyway it has been found that teardown +			 * takes very few cpu cycles and does not affect functionality */ +			 dly--; +			 udelay(1); +			 if (dly == 0) +			 	break; +		} +		adap_emac->RX0CP = cnt; +		adap_emac->RX0HDP = 0; +	} + +	debug_emac("- emac_ch_teardown\n"); +} + +/* Eth device close */ +static int dm644x_eth_close(void) +{ +	debug_emac("+ emac_close\n"); + +	dm644x_eth_ch_teardown(EMAC_CH_TX);	/* TX Channel teardown */ +	dm644x_eth_ch_teardown(EMAC_CH_RX);	/* RX Channel teardown */ + +	/* Reset EMAC module and disable interrupts in wrapper */ +	adap_emac->SOFTRESET = 1; +	adap_ewrap->EWCTL = 0; + +	debug_emac("- emac_close\n"); +	return(1); +} + +static int tx_send_loop = 0; + +/* + * This function sends a single packet on the network and returns + * positive number (number of bytes transmitted) or negative for error + */ +static int dm644x_eth_send_packet(volatile void *packet, int length) +{ +	int ret_status = -1; +	tx_send_loop = 0; + +	/* Return error if no link */ +	if (!phy.get_link_speed(active_phy_addr)) +	{ +		printf("WARN: emac_send_packet: No link\n"); +		return (ret_status); +	} + +	/* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */ +	if (length < EMAC_MIN_ETHERNET_PKT_SIZE) +	{ +		length = EMAC_MIN_ETHERNET_PKT_SIZE; +	} + +	/* Populate the TX descriptor */ +	emac_tx_desc->next         = 0; +	emac_tx_desc->buffer       = (u_int8_t *)packet; +	emac_tx_desc->buff_off_len = (length & 0xffff); +	emac_tx_desc->pkt_flag_len = ((length & 0xffff) | +			EMAC_CPPI_SOP_BIT | +			EMAC_CPPI_OWNERSHIP_BIT | +			EMAC_CPPI_EOP_BIT); +	/* Send the packet */ +	adap_emac->TX0HDP = (unsigned int)emac_tx_desc; + +	/* Wait for packet to complete or link down */ +	while (1) { +	        if (!phy.get_link_speed(active_phy_addr)) { +	        	dm644x_eth_ch_teardown(EMAC_CH_TX); +	        	return (ret_status); +	        } +	        if (adap_emac->TXINTSTATRAW & 0x01) { +	        	ret_status = length; +	        	break; +		} +	        tx_send_loop++; +	} + +	return(ret_status); +} + +/* + * This function handles receipt of a packet from the network + */ +static int dm644x_eth_rcv_packet(void) +{ +	volatile emac_desc	*rx_curr_desc; +	volatile emac_desc	*curr_desc; +	volatile emac_desc	*tail_desc; +	int			status, ret = -1; + +	rx_curr_desc = emac_rx_active_head; +	status = rx_curr_desc->pkt_flag_len; +	if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) { +	        if (status & EMAC_CPPI_RX_ERROR_FRAME) { +	        	/* Error in packet - discard it and requeue desc */ +	        	printf("WARN: emac_rcv_pkt: Error in packet\n"); +		} else { +			NetReceive(rx_curr_desc->buffer, (rx_curr_desc->buff_off_len & 0xffff)); +			ret = rx_curr_desc->buff_off_len & 0xffff; +	        } + +	        /* Ack received packet descriptor */ +	        adap_emac->RX0CP = (unsigned int)rx_curr_desc; +	        curr_desc = rx_curr_desc; +	        emac_rx_active_head = (volatile emac_desc *)rx_curr_desc->next; + +	        if (status & EMAC_CPPI_EOQ_BIT) { +	        	if (emac_rx_active_head) { +	        		adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; +			} else { +				emac_rx_queue_active = 0; +				printf("INFO:emac_rcv_packet: RX Queue not active\n"); +			} +		} + +		/* Recycle RX descriptor */ +		rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE; +		rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT; +		rx_curr_desc->next = 0; + +		if (emac_rx_active_head == 0) { +			printf("INFO: emac_rcv_pkt: active queue head = 0\n"); +			emac_rx_active_head = curr_desc; +			emac_rx_active_tail = curr_desc; +			if (emac_rx_queue_active != 0) { +				adap_emac->RX0HDP = (unsigned int)emac_rx_active_head; +				printf("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n"); +				emac_rx_queue_active = 1; +			} +		} else { +			tail_desc = emac_rx_active_tail; +			emac_rx_active_tail = curr_desc; +			tail_desc->next = (unsigned int)curr_desc; +			status = tail_desc->pkt_flag_len; +			if (status & EMAC_CPPI_EOQ_BIT) { +				adap_emac->RX0HDP = (unsigned int)curr_desc; +				status &= ~EMAC_CPPI_EOQ_BIT; +				tail_desc->pkt_flag_len = status; +			} +		} +		return(ret); +	} +	return(0); +} + +#endif /* CONFIG_CMD_NET */ + +#endif /* CONFIG_DRIVER_TI_EMAC */ diff --git a/cpu/arm926ejs/davinci/i2c.c b/cpu/arm926ejs/davinci/i2c.c new file mode 100644 index 000000000..af9dc034c --- /dev/null +++ b/cpu/arm926ejs/davinci/i2c.c @@ -0,0 +1,351 @@ +/* + * TI DaVinci (TMS320DM644x) I2C driver. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * 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> + +#ifdef CONFIG_DRIVER_DAVINCI_I2C + +#include <i2c.h> +#include <asm/arch/hardware.h> +#include <asm/arch/i2c_defs.h> + +#define CHECK_NACK() \ +	do {\ +		if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ +			REG(I2C_CON) = 0;\ +			return(1);\ +		}\ +	} while (0) + + +static int wait_for_bus(void) +{ +	int	stat, timeout; + +	REG(I2C_STAT) = 0xffff; + +	for (timeout = 0; timeout < 10; timeout++) { +		if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { +			REG(I2C_STAT) = 0xffff; +			return(0); +		} + +		REG(I2C_STAT) = stat; +		udelay(50000); +	} + +	REG(I2C_STAT) = 0xffff; +	return(1); +} + + +static int poll_i2c_irq(int mask) +{ +	int	stat, timeout; + +	for (timeout = 0; timeout < 10; timeout++) { +		udelay(1000); +		stat = REG(I2C_STAT); +		if (stat & mask) { +			return(stat); +		} +	} + +	REG(I2C_STAT) = 0xffff; +	return(stat | I2C_TIMEOUT); +} + + +void flush_rx(void) +{ +	int	dummy; + +	while (1) { +		if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) +			break; + +		dummy = REG(I2C_DRR); +		REG(I2C_STAT) = I2C_STAT_RRDY; +		udelay(1000); +	} +} + + +void i2c_init(int speed, int slaveadd) +{ +	u_int32_t	div, psc; + +	if (REG(I2C_CON) & I2C_CON_EN) { +		REG(I2C_CON) = 0; +		udelay (50000); +	} + +	psc = 2; +	div = (CFG_HZ_CLOCK / ((psc + 1) * speed)) - 10;	/* SCLL + SCLH */ +	REG(I2C_PSC) = psc;			/* 27MHz / (2 + 1) = 9MHz */ +	REG(I2C_SCLL) = (div * 50) / 100;	/* 50% Duty */ +	REG(I2C_SCLH) = div - REG(I2C_SCLL); + +	REG(I2C_OA) = slaveadd; +	REG(I2C_CNT) = 0; + +	/* Interrupts must be enabled or I2C module won't work */ +	REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | +		I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; + +	/* Now enable I2C controller (get it out of reset) */ +	REG(I2C_CON) = I2C_CON_EN; + +	udelay(1000); +} + + +int i2c_probe(u_int8_t chip) +{ +	int	rc = 1; + +	if (chip == REG(I2C_OA)) { +		return(rc); +	} + +	REG(I2C_CON) = 0; +	if (wait_for_bus()) {return(1);} + +	/* try to read one byte from current (or only) address */ +	REG(I2C_CNT) = 1; +	REG(I2C_SA) = chip; +	REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP); +	udelay (50000); + +	if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { +		rc = 0; +		flush_rx(); +		REG(I2C_STAT) = 0xffff; +	} else { +		REG(I2C_STAT) = 0xffff; +		REG(I2C_CON) |= I2C_CON_STP; +		udelay(20000); +		if (wait_for_bus()) {return(1);} +	} + +	flush_rx(); +	REG(I2C_STAT) = 0xffff; +	REG(I2C_CNT) = 0; +	return(rc); +} + + +int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) +{ +	u_int32_t	tmp; +	int		i; + +	if ((alen < 0) || (alen > 2)) { +		printf("%s(): bogus address length %x\n", __FUNCTION__, alen); +		return(1); +	} + +	if (wait_for_bus()) {return(1);} + +	if (alen != 0) { +		/* Start address phase */ +		tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX; +		REG(I2C_CNT) = alen; +		REG(I2C_SA) = chip; +		REG(I2C_CON) = tmp; + +		tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + +		CHECK_NACK(); + +		switch (alen) { +			case 2: +				/* Send address MSByte */ +				if (tmp & I2C_STAT_XRDY) { +					REG(I2C_DXR) = (addr >> 8) & 0xff; +				} else { +					REG(I2C_CON) = 0; +					return(1); +				} + +				tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + +				CHECK_NACK(); +				/* No break, fall through */ +			case 1: +				/* Send address LSByte */ +				if (tmp & I2C_STAT_XRDY) { +					REG(I2C_DXR) = addr & 0xff; +				} else { +					REG(I2C_CON) = 0; +					return(1); +				} + +				tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); + +				CHECK_NACK(); + +				if (!(tmp & I2C_STAT_ARDY)) { +					REG(I2C_CON) = 0; +					return(1); +				} +		} +	} + +	/* Address phase is over, now read 'len' bytes and stop */ +	tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP; +	REG(I2C_CNT) = len & 0xffff; +	REG(I2C_SA) = chip; +	REG(I2C_CON) = tmp; + +	for (i = 0; i < len; i++) { +		tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); + +		CHECK_NACK(); + +		if (tmp & I2C_STAT_RRDY) { +			buf[i] = REG(I2C_DRR); +		} else { +			REG(I2C_CON) = 0; +			return(1); +		} +	} + +	tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); + +	CHECK_NACK(); + +	if (!(tmp & I2C_STAT_SCD)) { +		REG(I2C_CON) = 0; +		return(1); +	} + +	flush_rx(); +	REG(I2C_STAT) = 0xffff; +	REG(I2C_CNT) = 0; +	REG(I2C_CON) = 0; + +	return(0); +} + + +int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) +{ +	u_int32_t	tmp; +	int		i; + +	if ((alen < 0) || (alen > 2)) { +		printf("%s(): bogus address length %x\n", __FUNCTION__, alen); +		return(1); +	} +	if (len < 0) { +		printf("%s(): bogus length %x\n", __FUNCTION__, len); +		return(1); +	} + +	if (wait_for_bus()) {return(1);} + +	/* Start address phase */ +	tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; +	REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; +	REG(I2C_SA) = chip; +	REG(I2C_CON) = tmp; + +	switch (alen) { +		case 2: +			/* Send address MSByte */ +			tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + +			CHECK_NACK(); + +			if (tmp & I2C_STAT_XRDY) { +				REG(I2C_DXR) = (addr >> 8) & 0xff; +			} else { +				REG(I2C_CON) = 0; +				return(1); +			} +			/* No break, fall through */ +		case 1: +			/* Send address LSByte */ +			tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + +			CHECK_NACK(); + +			if (tmp & I2C_STAT_XRDY) { +				REG(I2C_DXR) = addr & 0xff; +			} else { +				REG(I2C_CON) = 0; +				return(1); +			} +	} + +	for (i = 0; i < len; i++) { +		tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); + +		CHECK_NACK(); + +		if (tmp & I2C_STAT_XRDY) { +			REG(I2C_DXR) = buf[i]; +		} else { +			return(1); +		} +	} + +	tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); + +	CHECK_NACK(); + +	if (!(tmp & I2C_STAT_SCD)) { +		REG(I2C_CON) = 0; +		return(1); +	} + +	flush_rx(); +	REG(I2C_STAT) = 0xffff; +	REG(I2C_CNT) = 0; +	REG(I2C_CON) = 0; + +	return(0); +} + + +u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg) +{ +	u_int8_t	tmp; + +	i2c_read(chip, reg, 1, &tmp, 1); +	return(tmp); +} + + +void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val) +{ +	u_int8_t	tmp; + +	i2c_write(chip, reg, 1, &tmp, 1); +} + +#endif /* CONFIG_DRIVER_DAVINCI_I2C */ diff --git a/cpu/arm926ejs/davinci/lowlevel_init.S b/cpu/arm926ejs/davinci/lowlevel_init.S new file mode 100644 index 000000000..a87c112ec --- /dev/null +++ b/cpu/arm926ejs/davinci/lowlevel_init.S @@ -0,0 +1,707 @@ +/* + * Low-level board setup code for TI DaVinci SoC based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Partially based on TI sources, original copyrights follow: + */ + +/* + * Board specific setup info + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004 + * + * Modified for OMAP 5912 OSK board by Rishi Bhattacharya, Apr 2004 + * See file CREDITS for list of people who contributed to this + * project. + * + * Modified for DV-EVM board by Rishi Bhattacharya, Apr 2005 + * See file CREDITS for list of people who contributed to this + * project. + * + * Modified for DV-EVM board by Swaminathan S, Nov 2005 + * 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 <config.h> + +.globl	lowlevel_init +lowlevel_init: + +	/*-------------------------------------------------------* +	 * Mask all IRQs by setting all bits in the EINT default * +	 *-------------------------------------------------------*/ +	mov	r1, $0 +	ldr	r0, =EINT_ENABLE0 +	str	r1, [r0] +	ldr	r0, =EINT_ENABLE1 +	str	r1, [r0] + +	/*------------------------------------------------------* +	 * Put the GEM in reset					* +	 *------------------------------------------------------*/ + +	/* Put the GEM in reset */ +	ldr	r8, PSC_GEM_FLAG_CLEAR +	ldr	r6, MDCTL_GEM +	ldr	r7, [r6] +	and	r7, r7, r8 +	str	r7, [r6] + +	/* Enable the Power Domain Transition Command */ +	ldr	r6, PTCMD +	ldr	r7, [r6] +	orr	r7, r7, $0x02 +	str	r7, [r6] + +	/* Check for Transition Complete(PTSTAT) */ +checkStatClkStopGem: +	ldr	r6, PTSTAT +	ldr	r7, [r6] +	ands	r7, r7, $0x02 +	bne	checkStatClkStopGem + +	/* Check for GEM Reset Completion */ +checkGemStatClkStop: +	ldr	r6, MDSTAT_GEM +	ldr	r7, [r6] +	ands	r7, r7, $0x100 +	bne	checkGemStatClkStop + +	/* Do this for enabling a WDT initiated reset this is a workaround +	   for a chip bug.  Not required under normal situations */ +	ldr	r6, P1394 +	mov	r10, $0 +	str	r10, [r6] + +	/*------------------------------------------------------* +	 * Enable L1 & L2 Memories in Fast mode                 * +	 *------------------------------------------------------*/ +	ldr	r6, DFT_ENABLE +	mov	r10, $0x01 +	str	r10, [r6] + +	ldr	r6, MMARG_BRF0 +	ldr	r10, MMARG_BRF0_VAL +	str	r10, [r6] + +	ldr	r6, DFT_ENABLE +	mov	r10, $0 +	str	r10, [r6] + +	/*------------------------------------------------------* +	 * DDR2 PLL Initialization			    	* +	 *------------------------------------------------------*/ + +	/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */ +	mov	r10, $0 +	ldr	r6, PLL2_CTL +	ldr	r7, PLL_CLKSRC_MASK +	ldr	r8, [r6] +	and	r8, r8, r7 +	mov	r9, r10, lsl $8 +	orr	r8, r8, r9 +	str	r8, [r6] + +	/* Select the PLLEN source */ +	ldr	r7, PLL_ENSRC_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Bypass the PLL */ +	ldr	r7, PLL_BYPASS_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */ +	mov	r10, $0x20 +WaitPPL2Loop: +	subs	r10, r10, $1 +	bne	WaitPPL2Loop + +	/* Reset the PLL */ +	ldr	r7, PLL_RESET_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Power up the PLL */ +	ldr	r7, PLL_PWRUP_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Enable the PLL from Disable Mode */ +	ldr	r7, PLL_DISABLE_ENABLE_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Program the PLL Multiplier */ +	ldr	r6, PLL2_PLLM +	mov	r2, $0x17	/* 162 MHz */ +	str	r2, [r6] + +	/* Program the PLL2 Divisor Value */ +	ldr	r6, PLL2_DIV2 +	mov	r3, $0x01 +	str	r3, [r6] + +	/* Program the PLL2 Divisor Value */ +	ldr	r6, PLL2_DIV1 +	mov	r4, $0x0b	/* 54 MHz */ +	str	r4, [r6] + +	/* PLL2 DIV2 MMR */ +	ldr	r8, PLL2_DIV_MASK +	ldr	r6, PLL2_DIV2 +	ldr	r9, [r6] +	and	r8, r8, r9 +	mov	r9, $0x01 +	mov	r9, r9, lsl $15 +	orr	r8, r8, r9 +	str	r8, [r6] + +	/* Program the GOSET bit to take new divider values */ +	ldr	r6, PLL2_PLLCMD +	ldr	r7, [r6] +	orr	r7, r7, $0x01 +	str	r7, [r6] + +	/* Wait for Done */ +	ldr	r6, PLL2_PLLSTAT +doneLoop_0: +	ldr	r7, [r6] +	ands	r7, r7, $0x01 +	bne	doneLoop_0 + +	/* PLL2 DIV1 MMR */ +	ldr	r8, PLL2_DIV_MASK +	ldr	r6, PLL2_DIV1 +	ldr	r9, [r6] +	and	r8, r8, r9 +	mov	r9, $0x01 +	mov	r9, r9, lsl $15 +	orr	r8, r8, r9 +	str	r8, [r6] + +	/* Program the GOSET bit to take new divider values */ +	ldr	r6, PLL2_PLLCMD +	ldr	r7, [r6] +	orr	r7, r7, $0x01 +	str	r7, [r6] + +	/* Wait for Done */ +	ldr	r6, PLL2_PLLSTAT +doneLoop: +	ldr	r7, [r6] +	ands	r7, r7, $0x01 +	bne	doneLoop + +	/* Wait for PLL to Reset Properly */ +	mov	r10, $0x218 +ResetPPL2Loop: +	subs	r10, r10, $1 +	bne	ResetPPL2Loop + +	/* Bring PLL out of Reset */ +	ldr	r6, PLL2_CTL +	ldr	r8, [r6] +	orr	r8, r8, $0x08 +	str	r8, [r6] + +	/* Wait for PLL to Lock */ +	ldr	r10, PLL_LOCK_COUNT +PLL2Lock: +	subs	r10, r10, $1 +	bne	PLL2Lock + +	/* Enable the PLL */ +	ldr	r6, PLL2_CTL +	ldr	r8, [r6] +	orr	r8, r8, $0x01 +	str	r8, [r6] + +	/*------------------------------------------------------* +	 * Issue Soft Reset to DDR Module			* +	 *------------------------------------------------------*/ + +	/* Shut down the DDR2 LPSC Module */ +	ldr	r8, PSC_FLAG_CLEAR +	ldr	r6, MDCTL_DDR2 +	ldr	r7, [r6] +	and	r7, r7, r8 +	orr	r7, r7, $0x03 +	str	r7, [r6] + +	/* Enable the Power Domain Transition Command */ +	ldr	r6, PTCMD +	ldr	r7, [r6] +	orr	r7, r7, $0x01 +	str	r7, [r6] + +	/* Check for Transition Complete(PTSTAT) */ +checkStatClkStop: +	ldr	r6, PTSTAT +	ldr	r7, [r6] +	ands	r7, r7, $0x01 +	bne	checkStatClkStop + +	/* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkStop: +	ldr	r6, MDSTAT_DDR2 +	ldr	r7, [r6] +	and	r7, r7, $0x1f +	cmp	r7, $0x03 +	bne	checkDDRStatClkStop + +	/*------------------------------------------------------* +	 * Program DDR2 MMRs for 162MHz Setting			* +	 *------------------------------------------------------*/ + +	/* Program PHY Control Register */ +	ldr	r6, DDRCTL +	ldr	r7, DDRCTL_VAL +	str	r7, [r6] + +	/* Program SDRAM Bank Config Register */ +	ldr	r6, SDCFG +	ldr	r7, SDCFG_VAL +	str	r7, [r6] + +	/* Program SDRAM TIM-0 Config Register */ +	ldr	r6, SDTIM0 +	ldr	r7, SDTIM0_VAL_162MHz +	str	r7, [r6] + +	/* Program SDRAM TIM-1 Config Register */ +	ldr	r6, SDTIM1 +	ldr	r7, SDTIM1_VAL_162MHz +	str	r7, [r6] + +	/* Program the SDRAM Bank Config Control Register */ +	ldr	r10, MASK_VAL +	ldr	r8, SDCFG +	ldr	r9, SDCFG_VAL +	and	r9, r9, r10 +	str	r9, [r8] + +	/* Program SDRAM SDREF Config Register */ +	ldr	r6, SDREF +	ldr	r7, SDREF_VAL +	str	r7, [r6] + +	/*------------------------------------------------------* +	 * Issue Soft Reset to DDR Module			* +	 *------------------------------------------------------*/ + +	/* Issue a Dummy DDR2 read/write */ +	ldr	r8, DDR2_START_ADDR +	ldr	r7, DUMMY_VAL +	str	r7, [r8] +	ldr	r7, [r8] + +	/* Shut down the DDR2 LPSC Module */ +	ldr	r8, PSC_FLAG_CLEAR +	ldr	r6, MDCTL_DDR2 +	ldr	r7, [r6] +	and	r7, r7, r8 +	orr	r7, r7, $0x01 +	str	r7, [r6] + +	/* Enable the Power Domain Transition Command */ +	ldr	r6, PTCMD +	ldr	r7, [r6] +	orr	r7, r7, $0x01 +	str	r7, [r6] + +	/* Check for Transition Complete(PTSTAT) */ +checkStatClkStop2: +	ldr	r6, PTSTAT +	ldr	r7, [r6] +	ands	r7, r7, $0x01 +	bne	checkStatClkStop2 + +	/* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkStop2: +	ldr	r6, MDSTAT_DDR2 +	ldr	r7, [r6] +	and	r7, r7, $0x1f +	cmp	r7, $0x01 +	bne	checkDDRStatClkStop2 + +	/*------------------------------------------------------* +	 * Turn DDR2 Controller Clocks On			* +	 *------------------------------------------------------*/ + +	/* Enable the DDR2 LPSC Module */ +	ldr	r6, MDCTL_DDR2 +	ldr	r7, [r6] +	orr	r7, r7, $0x03 +	str	r7, [r6] + +	/* Enable the Power Domain Transition Command */ +	ldr	r6, PTCMD +	ldr	r7, [r6] +	orr	r7, r7, $0x01 +	str	r7, [r6] + +	/* Check for Transition Complete(PTSTAT) */ +checkStatClkEn2: +	ldr	r6, PTSTAT +	ldr	r7, [r6] +	ands	r7, r7, $0x01 +	bne	checkStatClkEn2 + +	/* Check for DDR2 Controller Enable Completion */ +checkDDRStatClkEn2: +	ldr	r6, MDSTAT_DDR2 +	ldr	r7, [r6] +	and	r7, r7, $0x1f +	cmp	r7, $0x03 +	bne	checkDDRStatClkEn2 + +	/*  DDR Writes and Reads */ +	ldr	r6, CFGTEST +	mov	r3, $0x01 +	str	r3, [r6] + +	/*------------------------------------------------------* +	 * System PLL Initialization				* +	 *------------------------------------------------------*/ + +	/* Select the Clock Mode Depending on the Value written in the Boot Table by the run script */ +	mov	r2, $0 +	ldr	r6, PLL1_CTL +	ldr	r7, PLL_CLKSRC_MASK +	ldr	r8, [r6] +	and	r8, r8, r7 +	mov	r9, r2, lsl $8 +	orr	r8, r8, r9 +	str	r8, [r6] + +	/* Select the PLLEN source */ +	ldr	r7, PLL_ENSRC_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Bypass the PLL */ +	ldr	r7, PLL_BYPASS_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Wait for few cycles to allow PLLEN Mux switch properly to bypass Clock */ +	mov	r10, $0x20 + +WaitLoop: +	subs	r10, r10, $1 +	bne	WaitLoop + +	/* Reset the PLL */ +	ldr	r7, PLL_RESET_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Disable the PLL */ +	orr	r8, r8, $0x10 +	str	r8, [r6] + +	/* Power up the PLL */ +	ldr	r7, PLL_PWRUP_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Enable the PLL from Disable Mode */ +	ldr	r7, PLL_DISABLE_ENABLE_MASK +	and	r8, r8, r7 +	str	r8, [r6] + +	/* Program the PLL Multiplier */ +	ldr	r6, PLL1_PLLM +	mov	r3, $0x15	/* For 594MHz */ +	str	r3, [r6] + +	/* Wait for PLL to Reset Properly */ +	mov	r10, $0xff + +ResetLoop: +	subs	r10, r10, $1 +	bne	ResetLoop + +	/* Bring PLL out of Reset */ +	ldr	r6, PLL1_CTL +	orr	r8, r8, $0x08 +	str	r8, [r6] + +	/* Wait for PLL to Lock */ +	ldr	r10, PLL_LOCK_COUNT + +PLL1Lock: +	subs	r10, r10, $1 +	bne	PLL1Lock + +	/* Enable the PLL */ +	orr	r8, r8, $0x01 +	str	r8, [r6] + +	nop +	nop +	nop +	nop + +	/*------------------------------------------------------* +	 * AEMIF configuration for NOR Flash (double check)     * +	 *------------------------------------------------------*/ +	ldr	r0, _PINMUX0 +	ldr	r1, _DEV_SETTING +	str	r1, [r0] + +	ldr	r0, WAITCFG +	ldr	r1, WAITCFG_VAL +	ldr	r2, [r0] +	orr	r2, r2, r1 +	str	r2, [r0] + +	ldr	r0, ACFG3 +	ldr	r1, ACFG3_VAL +	ldr	r2, [r0] +	and	r1, r2, r1 +	str	r1, [r0] + +	ldr	r0, ACFG4 +	ldr	r1, ACFG4_VAL +	ldr	r2, [r0] +	and	r1, r2, r1 +	str	r1, [r0] + +	ldr	r0, ACFG5 +	ldr	r1, ACFG5_VAL +	ldr	r2, [r0] +	and	r1, r2, r1 +	str	r1, [r0] + +	/*--------------------------------------* +	 * VTP manual Calibration               * +	 *--------------------------------------*/ +	ldr	r0, VTPIOCR +	ldr	r1, VTP_MMR0 +	str	r1, [r0] + +	ldr	r0, VTPIOCR +	ldr	r1, VTP_MMR1 +	str	r1, [r0] + +	/* Wait for 33 VTP CLK cycles.  VRP operates at 27 MHz */ +	ldr	r10, VTP_LOCK_COUNT +VTPLock: +	subs	r10, r10, $1 +	bne	VTPLock + +	ldr	r6, DFT_ENABLE +	mov	r10, $0x01 +	str	r10, [r6] + +	ldr	r6, DDRVTPR +	ldr	r7, [r6] +	and	r7, r7, $0x1f +	and	r8, r7, $0x3e0 +	orr	r8, r7, r8 +	ldr	r7, VTP_RECAL +	orr	r8, r7, r8 +	ldr	r7, VTP_EN +	orr	r8, r7, r8 +	str	r8, [r0] + + +	/* Wait for 33 VTP CLK cycles.  VRP operates at 27 MHz */ +	ldr	r10, VTP_LOCK_COUNT +VTP1Lock: +	subs	r10, r10, $1 +	bne	VTP1Lock + +	ldr	r1, [r0] +	ldr	r2, VTP_MASK +	and	r2, r1, r2 +	str	r2, [r0] + +	ldr	r6, DFT_ENABLE +	mov	r10, $0 +	str	r10, [r6] + +	/* +	 * Call board-specific lowlevel init. + 	 * That MUST be present and THAT returns +	 * back to arch calling code with "mov pc, lr." +	 */ +	b	dv_board_init + +.ltorg + +_PINMUX0: +	.word	0x01c40000		/* Device Configuration Registers */ +_PINMUX1: +	.word	0x01c40004		/* Device Configuration Registers */ + +_DEV_SETTING: +	.word	0x00000c1f + +WAITCFG: +	.word	0x01e00004 +WAITCFG_VAL: +	.word	0 +ACFG3: +	.word	0x01e00014 +ACFG3_VAL: +	.word	0x3ffffffd +ACFG4: +	.word	0x01e00018 +ACFG4_VAL: +	.word	0x3ffffffd +ACFG5: +	.word	0x01e0001c +ACFG5_VAL: +	.word	0x3ffffffd + +MDCTL_DDR2: +	.word	0x01c41a34 +MDSTAT_DDR2: +	.word	0x01c41834 + +PTCMD: +	.word	0x01c41120 +PTSTAT: +	.word	0x01c41128 + +EINT_ENABLE0: +	.word	0x01c48018 +EINT_ENABLE1: +	.word	0x01c4801c + +PSC_FLAG_CLEAR: +	.word	0xffffffe0 +PSC_GEM_FLAG_CLEAR: +	.word	0xfffffeff + +/* DDR2 MMR & CONFIGURATION VALUES, 162 MHZ clock */ +DDRCTL: +	.word	0x200000e4 +DDRCTL_VAL: +	.word	0x50006405 +SDREF: +	.word	0x2000000c +SDREF_VAL: +	.word	0x000005c3 +SDCFG: +	.word	0x20000008 +SDCFG_VAL: +#ifdef	DDR_4BANKS +	.word	0x00178622 +#elif defined DDR_8BANKS +	.word	0x00178632 +#else +#error "Unknown DDR configuration!!!" +#endif +SDTIM0: +	.word	0x20000010 +SDTIM0_VAL_162MHz: +	.word	0x28923211 +SDTIM1: +	.word	0x20000014 +SDTIM1_VAL_162MHz: +	.word	0x0016c722 +VTPIOCR: +	.word	0x200000f0	/* VTP IO Control register */ +DDRVTPR: +	.word	0x01c42030	/* DDR VPTR MMR */ +VTP_MMR0: +	.word	0x201f +VTP_MMR1: +	.word	0xa01f +DFT_ENABLE: +	.word	0x01c4004c +VTP_LOCK_COUNT: +	.word	0x5b0 +VTP_MASK: +	.word	0xffffdfff +VTP_RECAL: +	.word	0x40000 +VTP_EN: +	.word	0x02000 +CFGTEST: +	.word	0x80010000 +MASK_VAL: +	.word	0x00000fff + +/* GEM Power Up & LPSC Control Register */ +MDCTL_GEM: +	.word	0x01c41a9c +MDSTAT_GEM: +	.word	0x01c4189c + +/* For WDT reset chip bug */ +P1394: +	.word	0x01c41a20 + +PLL_CLKSRC_MASK: +	.word	0xfffffeff	/* Mask the Clock Mode bit */ +PLL_ENSRC_MASK: +	.word	0xffffffdf	/* Select the PLLEN source */ +PLL_BYPASS_MASK: +	.word	0xfffffffe	/* Put the PLL in BYPASS */ +PLL_RESET_MASK: +	.word	0xfffffff7	/* Put the PLL in Reset Mode */ +PLL_PWRUP_MASK: +	.word	0xfffffffd	/* PLL Power up Mask Bit  */ +PLL_DISABLE_ENABLE_MASK: +	.word	0xffffffef	/* Enable the PLL from Disable */ +PLL_LOCK_COUNT: +	.word	0x2000 + +/* PLL1-SYSTEM PLL MMRs */ +PLL1_CTL: +	.word	0x01c40900 +PLL1_PLLM: +	.word	0x01c40910 + +/* PLL2-SYSTEM PLL MMRs */ +PLL2_CTL: +	.word	0x01c40d00 +PLL2_PLLM: +	.word	0x01c40d10 +PLL2_DIV1: +	.word	0x01c40d18 +PLL2_DIV2: +	.word	0x01c40d1c +PLL2_PLLCMD: +	.word	0x01c40d38 +PLL2_PLLSTAT: +	.word	0x01c40d3c +PLL2_DIV_MASK: +	.word	0xffff7fff + +MMARG_BRF0: +	.word	0x01c42010	/* BRF margin mode 0 (R/W)*/ +MMARG_BRF0_VAL: +	.word	0x00444400 + +DDR2_START_ADDR: +	.word	0x80000000 +DUMMY_VAL: +	.word	0xa55aa55a diff --git a/cpu/arm926ejs/davinci/lxt972.c b/cpu/arm926ejs/davinci/lxt972.c new file mode 100644 index 000000000..6eeb6e5ee --- /dev/null +++ b/cpu/arm926ejs/davinci/lxt972.c @@ -0,0 +1,142 @@ +/* + * Intel LXT971/LXT972 PHY Driver for TI DaVinci + * (TMS320DM644x) based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * -------------------------------------------------------- + * + * 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 <net.h> +#include <lxt971a.h> +#include <asm/arch/emac_defs.h> + +#ifdef CONFIG_DRIVER_TI_EMAC + +#ifdef CONFIG_CMD_NET + +int lxt972_is_phy_connected(int phy_addr) +{ +	u_int16_t	id1, id2; + +	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID1, &id1)) +		return(0); +	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_ID2, &id2)) +		return(0); + +	if ((id1 == (0x0013)) && ((id2  & 0xfff0) == 0x78e0)) +		return(1); + +	return(0); +} + +int lxt972_get_link_speed(int phy_addr) +{ +	u_int16_t		stat1, tmp; +	volatile emac_regs*	emac = (emac_regs *)EMAC_BASE_ADDR; + +	if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_STAT2, &stat1)) +		return(0); + +	if (!(stat1 & PHY_LXT971_STAT2_LINK))	/* link up? */ +		return(0); + +	if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp)) +		return(0); + +	tmp |= PHY_LXT971_DIG_CFG_MII_DRIVE; + +	dm644x_eth_phy_write(phy_addr, PHY_LXT971_DIG_CFG, tmp); +	/* Read back */ +	if (!dm644x_eth_phy_read(phy_addr, PHY_LXT971_DIG_CFG, &tmp)) +		return(0); + + +	/* Speed doesn't matter, there is no setting for it in EMAC... */ +	if (stat1 & PHY_LXT971_STAT2_100BTX) { +		if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) { +			/* set DM644x EMAC for Full Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE; +		} else { +			/*set DM644x EMAC for Half Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; +		} + +		return(1); +	} else { +		if (stat1 & PHY_LXT971_STAT2_DUPLEX_MODE) { +			/* set DM644x EMAC for Full Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE; +		} else { +			/*set DM644x EMAC for Half Duplex  */ +			emac->MACCONTROL = EMAC_MACCONTROL_MIIEN_ENABLE; +		} + +		return(1); +	} + +	return(0); +} + + +int lxt972_init_phy(int phy_addr) +{ +	int	ret = 1; + +	if (!lxt972_get_link_speed(phy_addr)) { +		/* Try another time */ +		ret = lxt972_get_link_speed(phy_addr); +	} + +	/* Disable PHY Interrupts */ +	dm644x_eth_phy_write(phy_addr, PHY_LXT971_INT_ENABLE, 0); + +	return(ret); +} + + +int lxt972_auto_negotiate(int phy_addr) +{ +	u_int16_t	tmp; + + +	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_CTRL, &tmp)) +		return(0); + +	/* Restart Auto_negotiation  */ +	tmp |= PHY_COMMON_CTRL_RES_AUTO; +	dm644x_eth_phy_write(phy_addr, PHY_COMMON_CTRL, tmp); + +	/*check AutoNegotiate complete */ +	udelay (10000); +	if (!dm644x_eth_phy_read(phy_addr, PHY_COMMON_STAT, &tmp)) +		return(0); + +	if (!(tmp & PHY_COMMON_STAT_AN_COMP)) +		return(0); + +	return (lxt972_get_link_speed(phy_addr)); +} + +#endif	/* CONFIG_CMD_NET */ + +#endif	/* CONFIG_DRIVER_ETHER */ diff --git a/cpu/arm926ejs/davinci/nand.c b/cpu/arm926ejs/davinci/nand.c new file mode 100644 index 000000000..127be9fcd --- /dev/null +++ b/cpu/arm926ejs/davinci/nand.c @@ -0,0 +1,389 @@ +/* + * NAND driver for TI DaVinci based boards. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Based on Linux DaVinci NAND driver by TI. Original copyright follows: + */ + +/* + * + * linux/drivers/mtd/nand/nand_davinci.c + * + * NAND Flash Driver + * + * Copyright (C) 2006 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + * + *  Overview: + *   This is a device driver for the NAND flash device found on the + *   DaVinci board which utilizes the Samsung k9k2g08 part. + * + Modifications: + ver. 1.0: Feb 2005, Vinod/Sudhakar + - + * + */ + +#include <common.h> + +#ifdef CFG_USE_NAND +#if !defined(CFG_NAND_LEGACY) + +#include <nand.h> +#include <asm/arch/nand_defs.h> +#include <asm/arch/emif_defs.h> + +extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE]; + +static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd) +{ +	struct		nand_chip *this = mtd->priv; +	u_int32_t	IO_ADDR_W = (u_int32_t)this->IO_ADDR_W; + +	IO_ADDR_W &= ~(MASK_ALE|MASK_CLE); + +	switch (cmd) { +		case NAND_CTL_SETCLE: +			IO_ADDR_W |= MASK_CLE; +			break; +		case NAND_CTL_SETALE: +			IO_ADDR_W |= MASK_ALE; +			break; +	} + +	this->IO_ADDR_W = (void *)IO_ADDR_W; +} + +/* Set WP on deselect, write enable on select */ +static void nand_davinci_select_chip(struct mtd_info *mtd, int chip) +{ +#define GPIO_SET_DATA01	0x01c67018 +#define GPIO_CLR_DATA01	0x01c6701c +#define GPIO_NAND_WP	(1 << 4) +#ifdef SONATA_BOARD_GPIOWP +	if (chip < 0) { +		REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP; +	} else { +		REG(GPIO_SET_DATA01) |= GPIO_NAND_WP; +	} +#endif +} + +#ifdef CFG_NAND_HW_ECC +#ifdef CFG_NAND_LARGEPAGE +static struct nand_oobinfo davinci_nand_oobinfo = { +	.useecc = MTD_NANDECC_AUTOPLACE, +	.eccbytes = 12, +	.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58}, +	.oobfree = { {2, 6}, {12, 12}, {28, 12}, {44, 12}, {60, 4} } +}; +#elif defined(CFG_NAND_SMALLPAGE) +static struct nand_oobinfo davinci_nand_oobinfo = { +	.useecc = MTD_NANDECC_AUTOPLACE, +	.eccbytes = 3, +	.eccpos = {0, 1, 2}, +	.oobfree = { {6, 2}, {8, 8} } +}; +#else +#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!" +#endif + +static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode) +{ +	emifregs	emif_addr; +	int		dummy; + +	emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + +	dummy = emif_addr->NANDF1ECC; +	dummy = emif_addr->NANDF2ECC; +	dummy = emif_addr->NANDF3ECC; +	dummy = emif_addr->NANDF4ECC; + +	emif_addr->NANDFCR |= (1 << 8); +} + +static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region) +{ +	u_int32_t	ecc = 0; +	emifregs	emif_base_addr; + +	emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + +	if (region == 1) +		ecc = emif_base_addr->NANDF1ECC; +	else if (region == 2) +		ecc = emif_base_addr->NANDF2ECC; +	else if (region == 3) +		ecc = emif_base_addr->NANDF3ECC; +	else if (region == 4) +		ecc = emif_base_addr->NANDF4ECC; + +	return(ecc); +} + +static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +{ +	u_int32_t		tmp; +	int			region, n; +	struct nand_chip	*this = mtd->priv; + +	n = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1; + +	region = 1; +	while (n--) { +		tmp = nand_davinci_readecc(mtd, region); +		*ecc_code++ = tmp; +		*ecc_code++ = tmp >> 16; +		*ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0); +		region++; +	} +	return(0); +} + +static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf) +{ +	u_int32_t	tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8); + +	ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp)); +	ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp)); +	ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp)); +} + +static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data) +{ +	u_int32_t	i; +	u_int8_t	tmp0_bit[8], tmp1_bit[8], tmp2_bit[8]; +	u_int8_t	comp0_bit[8], comp1_bit[8], comp2_bit[8]; +	u_int8_t	ecc_bit[24]; +	u_int8_t	ecc_sum = 0; +	u_int8_t	find_bit = 0; +	u_int32_t	find_byte = 0; +	int		is_ecc_ff; + +	is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff)); + +	nand_davinci_gen_true_ecc(ecc_nand); +	nand_davinci_gen_true_ecc(ecc_calc); + +	for (i = 0; i <= 2; i++) { +		*(ecc_nand + i) = ~(*(ecc_nand + i)); +		*(ecc_calc + i) = ~(*(ecc_calc + i)); +	} + +	for (i = 0; i < 8; i++) { +		tmp0_bit[i] = *ecc_nand % 2; +		*ecc_nand = *ecc_nand / 2; +	} + +	for (i = 0; i < 8; i++) { +		tmp1_bit[i] = *(ecc_nand + 1) % 2; +		*(ecc_nand + 1) = *(ecc_nand + 1) / 2; +	} + +	for (i = 0; i < 8; i++) { +		tmp2_bit[i] = *(ecc_nand + 2) % 2; +		*(ecc_nand + 2) = *(ecc_nand + 2) / 2; +	} + +	for (i = 0; i < 8; i++) { +		comp0_bit[i] = *ecc_calc % 2; +		*ecc_calc = *ecc_calc / 2; +	} + +	for (i = 0; i < 8; i++) { +		comp1_bit[i] = *(ecc_calc + 1) % 2; +		*(ecc_calc + 1) = *(ecc_calc + 1) / 2; +	} + +	for (i = 0; i < 8; i++) { +		comp2_bit[i] = *(ecc_calc + 2) % 2; +		*(ecc_calc + 2) = *(ecc_calc + 2) / 2; +	} + +	for (i = 0; i< 6; i++) +		ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2]; + +	for (i = 0; i < 8; i++) +		ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i]; + +	for (i = 0; i < 8; i++) +		ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i]; + +	ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0]; +	ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1]; + +	for (i = 0; i < 24; i++) +		ecc_sum += ecc_bit[i]; + +	switch (ecc_sum) { +		case 0: +			/* Not reached because this function is not called if +			   ECC values are equal */ +			return 0; +		case 1: +			/* Uncorrectable error */ +			DEBUG (MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n"); +			return(-1); +		case 12: +			/* Correctable error */ +			find_byte = (ecc_bit[23] << 8) + +				(ecc_bit[21] << 7) + +				(ecc_bit[19] << 6) + +				(ecc_bit[17] << 5) + +				(ecc_bit[15] << 4) + +				(ecc_bit[13] << 3) + +				(ecc_bit[11] << 2) + +				(ecc_bit[9]  << 1) + +				ecc_bit[7]; + +			find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1]; + +			DEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at offset: %d, bit: %d\n", find_byte, find_bit); + +			page_data[find_byte] ^= (1 << find_bit); + +			return(0); +		default: +			if (is_ecc_ff) { +				if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0) +					return(0); +			} +			DEBUG (MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n"); +			return(-1); +	} +} + +static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) +{ +	struct nand_chip	*this; +	int			block_count = 0, i, rc; + +	this = mtd->priv; +	block_count = (this->eccmode == NAND_ECC_HW12_2048) ? 4 : 1; +	for (i = 0; i < block_count; i++) { +		if (memcmp(read_ecc, calc_ecc, 3) != 0) { +			rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat); +			if (rc < 0) { +				return(rc); +			} +		} +		read_ecc += 3; +		calc_ecc += 3; +		dat += 512; +	} +	return(0); +} +#endif + +static int nand_davinci_dev_ready(struct mtd_info *mtd) +{ +	emifregs	emif_addr; + +	emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + +	return(emif_addr->NANDFSR & 0x1); +} + +static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this, int state) +{ +	while(!nand_davinci_dev_ready(mtd)) {;} +	*NAND_CE0CLE = NAND_STATUS; +	return(*NAND_CE0DATA); +} + +static void nand_flash_init(void) +{ +	u_int32_t	acfg1 = 0x3ffffffc; +	u_int32_t	acfg2 = 0x3ffffffc; +	u_int32_t	acfg3 = 0x3ffffffc; +	u_int32_t	acfg4 = 0x3ffffffc; +	emifregs	emif_regs; + +	/*------------------------------------------------------------------* +	 *  NAND FLASH CHIP TIMEOUT @ 459 MHz                               * +	 *                                                                  * +	 *  AEMIF.CLK freq   = PLL1/6 = 459/6 = 76.5 MHz                    * +	 *  AEMIF.CLK period = 1/76.5 MHz = 13.1 ns                         * +	 *                                                                  * +	 *------------------------------------------------------------------*/ +	 acfg1 = 0 +	 	| (0 << 31 )	/* selectStrobe */ +	 	| (0 << 30 )	/* extWait */ +	 	| (1 << 26 )	/* writeSetup	10 ns */ +	 	| (3 << 20 )	/* writeStrobe	40 ns */ +	 	| (1 << 17 )	/* writeHold	10 ns */ +	 	| (1 << 13 )	/* readSetup	10 ns */ +	 	| (5 << 7 )	/* readStrobe	60 ns */ +	 	| (1 << 4 )	/* readHold	10 ns */ +	 	| (3 << 2 )	/* turnAround	?? ns */ +	 	| (0 << 0 )	/* asyncSize	8-bit bus */ +	 	; + +	emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE; + +	emif_regs->AWCCR |= 0x10000000; +	emif_regs->AB1CR = acfg1;	/* 0x08244128 */; +	emif_regs->AB2CR = acfg2; +	emif_regs->AB3CR = acfg3; +	emif_regs->AB4CR = acfg4; +	emif_regs->NANDFCR = 0x00000101; +} + +int board_nand_init(struct nand_chip *nand) +{ +	nand->IO_ADDR_R   = (void  __iomem *)NAND_CE0DATA; +	nand->IO_ADDR_W   = (void  __iomem *)NAND_CE0DATA; +	nand->chip_delay  = 0; +	nand->select_chip = nand_davinci_select_chip; +#ifdef CFG_NAND_USE_FLASH_BBT +	nand->options	  = NAND_USE_FLASH_BBT; +#endif +#ifdef CFG_NAND_HW_ECC +#ifdef CFG_NAND_LARGEPAGE +	nand->eccmode     = NAND_ECC_HW12_2048; +#elif defined(CFG_NAND_SMALLPAGE) +	nand->eccmode     = NAND_ECC_HW3_512; +#else +#error "Either CFG_NAND_LARGEPAGE or CFG_NAND_SMALLPAGE must be defined!" +#endif +	nand->autooob	  = &davinci_nand_oobinfo; +	nand->calculate_ecc = nand_davinci_calculate_ecc; +	nand->correct_data  = nand_davinci_correct_data; +	nand->enable_hwecc  = nand_davinci_enable_hwecc; +#else +	nand->eccmode     = NAND_ECC_SOFT; +#endif + +	/* Set address of hardware control function */ +	nand->hwcontrol = nand_davinci_hwcontrol; + +	nand->dev_ready = nand_davinci_dev_ready; +	nand->waitfunc = nand_davinci_waitfunc; + +	nand_flash_init(); + +	return(0); +} + +#else +#error "U-Boot legacy NAND support not available for DaVinci chips" +#endif +#endif	/* CFG_USE_NAND */ diff --git a/cpu/arm926ejs/davinci/reset.S b/cpu/arm926ejs/davinci/reset.S new file mode 100644 index 000000000..a687d4403 --- /dev/null +++ b/cpu/arm926ejs/davinci/reset.S @@ -0,0 +1,77 @@ +/* + * Processor reset using WDT for TI TMS320DM644x SoC. + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * ----------------------------------------------------- + * + * 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 + */ + +.globl reset_cpu +reset_cpu: +	ldr	r0, WDT_TGCR +	mov	r1, $0x08 +	str	r1, [r0] +	ldr	r1, [r0] +	orr	r1, r1, $0x03 +	str	r1, [r0] +	mov	r1, $0 +	ldr	r0, WDT_TIM12 +	str	r1, [r0] +	ldr	r0, WDT_TIM34 +	str	r1, [r0] +	ldr	r0, WDT_PRD12 +	str	r1, [r0] +	ldr	r0, WDT_PRD34 +	str	r1, [r0] +	ldr	r0, WDT_TCR +	ldr	r1, [r0] +	orr	r1, r1, $0x40 +	str	r1, [r0] +	ldr	r0, WDT_WDTCR +	ldr	r1, [r0] +	orr	r1, r1, $0x4000 +	str	r1, [r0] +	ldr	r1, WDTCR_VAL1 +	str	r1, [r0] +	ldr	r1, WDTCR_VAL2 +	str	r1, [r0] +	nop +	nop +	nop +	nop +reset_cpu_loop: +	b	reset_cpu_loop + +WDT_TGCR: +	.word	0x01c21c24 +WDT_TIM12: +	.word	0x01c21c10 +WDT_TIM34: +	.word	0x01c21c14 +WDT_PRD12: +	.word	0x01c21c18 +WDT_PRD34: +	.word	0x01c21c1c +WDT_TCR: +	.word	0x01c21c20 +WDT_WDTCR: +	.word	0x01c21c28 +WDTCR_VAL1: +	.word	0xa5c64000 +WDTCR_VAL2: +	.word	0xda7e4000 diff --git a/cpu/arm926ejs/davinci/timer.c b/cpu/arm926ejs/davinci/timer.c new file mode 100644 index 000000000..c6b1dda51 --- /dev/null +++ b/cpu/arm926ejs/davinci/timer.c @@ -0,0 +1,165 @@ +/* + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 <arm926ejs.h> + +typedef volatile struct { +	u_int32_t	pid12; +	u_int32_t	emumgt_clksped; +	u_int32_t	gpint_en; +	u_int32_t	gpdir_dat; +	u_int32_t	tim12; +	u_int32_t	tim34; +	u_int32_t	prd12; +	u_int32_t	prd34; +	u_int32_t	tcr; +	u_int32_t	tgcr; +	u_int32_t	wdtcr; +	u_int32_t	tlgc; +	u_int32_t	tlmr; +} davinci_timer; + +davinci_timer		*timer = (davinci_timer *)CFG_TIMERBASE; + +#define TIMER_LOAD_VAL	(CFG_HZ_CLOCK / CFG_HZ) +#define READ_TIMER	timer->tim34 + +static ulong timestamp; +static ulong lastinc; + +int timer_init(void) +{ +	/* We are using timer34 in unchained 32-bit mode, full speed */ +	timer->tcr = 0x0; +	timer->tgcr = 0x0; +	timer->tgcr = 0x06; +	timer->tim34 = 0x0; +	timer->prd34 = TIMER_LOAD_VAL; +	lastinc = 0; +	timer->tcr = 0x80 << 16; +	timestamp = 0; + +	return(0); +} + +void reset_timer(void) +{ +	reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ +	return(get_timer_masked() - base); +} + +void set_timer(ulong t) +{ +	timestamp = t; +} + +void udelay(unsigned long usec) +{ +	udelay_masked(usec); +} + +void reset_timer_masked(void) +{ +	lastinc = READ_TIMER; +	timestamp = 0; +} + +ulong get_timer_raw(void) +{ +	ulong now = READ_TIMER; + +	if (now >= lastinc) { +		/* normal mode */ +		timestamp += now - lastinc; +	} else { +		/* overflow ... */ +		timestamp += now + TIMER_LOAD_VAL - lastinc; +	} +	lastinc = now; +	return timestamp; +} + +ulong get_timer_masked(void) +{ +	return(get_timer_raw() / TIMER_LOAD_VAL); +} + +void udelay_masked(unsigned long usec) +{ +	ulong tmo; +	ulong endtime; +	signed long diff; + +	tmo = CFG_HZ_CLOCK / 1000; +	tmo *= usec; +	tmo /= 1000; + +	endtime = get_timer_raw() + tmo; + +	do { +		ulong now = get_timer_raw(); +		diff = endtime - now; +	} while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ +	return(get_timer(0)); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ +	ulong tbclk; + +	tbclk = CFG_HZ; +	return(tbclk); +} diff --git a/cpu/mpc5xxx/Makefile b/cpu/mpc5xxx/Makefile index 235adb7c0..312b0bfc6 100644 --- a/cpu/mpc5xxx/Makefile +++ b/cpu/mpc5xxx/Makefile @@ -28,7 +28,7 @@ LIB	= $(obj)lib$(CPU).a  START	= start.o  SOBJS	= io.o firmware_sc_task_bestcomm.impl.o firmware_sc_task.impl.o  COBJS	= i2c.o traps.o cpu.o cpu_init.o fec.o ide.o interrupts.o \ -	  loadtask.o pci_mpc5200.o serial.o speed.o usb_ohci.o +	  loadtask.o pci_mpc5200.o serial.o speed.o usb_ohci.o usb.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/mpc5xxx/usb.c b/cpu/mpc5xxx/usb.c new file mode 100644 index 000000000..ce709fc65 --- /dev/null +++ b/cpu/mpc5xxx/usb.c @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2007 + * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de> + * + * 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> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) + +#include <mpc5xxx.h> + +int usb_cpu_init() +{ +	/* Set the USB Clock						     */ +	*(vu_long *)MPC5XXX_CDM_48_FDC = CONFIG_USB_CLOCK; + +	/* remove all USB bits first before ORing in ours */ +	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00807000; + +	/* Activate USB port						     */ +	*(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= CONFIG_USB_CONFIG; + +	return 0; +} + +int usb_cpu_stop() +{ +	return 0; +} + +int usb_cpu_init_fail() +{ +	return 0; +} + +#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */ diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile index bb96f774f..232997005 100644 --- a/cpu/mpc83xx/Makefile +++ b/cpu/mpc83xx/Makefile @@ -29,7 +29,7 @@ LIB	= $(obj)lib$(CPU).a  START	= start.o  COBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o \ -	  spd_sdram.o qe_io.o pci.o +	  spd_sdram.o ecc.o qe_io.o pci.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 841fe8242..adf808301 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -33,8 +33,7 @@  #include <asm/processor.h>  #if defined(CONFIG_OF_FLAT_TREE)  #include <ft_build.h> -#endif -#if defined(CONFIG_OF_LIBFDT) +#elif defined(CONFIG_OF_LIBFDT)  #include <libfdt.h>  #include <libfdt_env.h>  #endif @@ -113,12 +112,14 @@ int checkcpu(void)  	case SPR_8360E_REV11:  	case SPR_8360E_REV12:  	case SPR_8360E_REV20: +	case SPR_8360E_REV21:  		puts("MPC8360E, ");  		break;  	case SPR_8360_REV10:  	case SPR_8360_REV11:  	case SPR_8360_REV12:  	case SPR_8360_REV20: +	case SPR_8360_REV21:  		puts("MPC8360, ");  		break;  	case SPR_8323E_REV10: @@ -150,7 +151,8 @@ int checkcpu(void)  		puts("MPC8313E, ");  		break;  	default: -		puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n"); +		printf("Rev: Unknown revision number:%08x\n" +			"Warning: Unsupported cpu revision!\n",spridr);  		return 0;  	} @@ -329,154 +331,167 @@ void watchdog_reset (void)  /*   * "Setter" functions used to add/modify FDT entries.   */ -static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth0(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enetaddr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #ifdef CONFIG_HAS_ETH1  /* second onboard ethernet port */ -static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth1(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enet1addr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #endif  #ifdef CONFIG_HAS_ETH2  /* third onboard ethernet port */ -static int fdt_set_eth2(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth2(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet2addr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enet2addr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #endif  #ifdef CONFIG_HAS_ETH3  /* fourth onboard ethernet port */ -static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth3(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enet3addr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #endif -static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	u32  tmp;  	/*  	 * Create or update the property.  	 */  	tmp = cpu_to_be32(bd->bi_busfreq); -	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +	return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); +} + +static int fdt_set_tbfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) +{ +	u32  tmp; +	/* +	 * Create or update the property. +	 */ +	tmp = cpu_to_be32(OF_TBCLK); +	return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));  } +  /* - * Fixups to the fdt.  If "create" is TRUE, the node is created - * unconditionally.  If "create" is FALSE, the node is updated - * only if it already exists. + * Fixups to the fdt.   */  static const struct {  	char *node;  	char *prop; -	int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd); +	int (*set_fn)(void *blob, int nodeoffset, const char *name, bd_t *bd);  } fixup_props[] = {  	{	"/cpus/" OF_CPU, -		 "bus-frequency", -		fdt_set_busfreq +		"timebase-frequency", +		fdt_set_tbfreq  	}, -	{	"/cpus/" OF_SOC, +	{	"/cpus/" OF_CPU,  		"bus-frequency",  		fdt_set_busfreq  	}, -	{	"/" OF_SOC "/serial@4500/", +	{	"/cpus/" OF_CPU, +		"clock-frequency", +		fdt_set_busfreq +	}, +	{	"/" OF_SOC "/serial@4500",  		"clock-frequency",  		fdt_set_busfreq  	}, -	{	"/" OF_SOC "/serial@4600/", +	{	"/" OF_SOC "/serial@4600",  		"clock-frequency",  		fdt_set_busfreq  	},  #ifdef CONFIG_TSEC1 -	{	"/" OF_SOC "/ethernet@24000, +	{	"/" OF_SOC "/ethernet@24000",  		"mac-address",  		fdt_set_eth0  	}, -	{	"/" OF_SOC "/ethernet@24000, +	{	"/" OF_SOC "/ethernet@24000",  		"local-mac-address",  		fdt_set_eth0  	},  #endif  #ifdef CONFIG_TSEC2 -	{	"/" OF_SOC "/ethernet@25000, +	{	"/" OF_SOC "/ethernet@25000",  		"mac-address",  		fdt_set_eth1  	}, -	{	"/" OF_SOC "/ethernet@25000, +	{	"/" OF_SOC "/ethernet@25000",  		"local-mac-address",  		fdt_set_eth1  	},  #endif  #ifdef CONFIG_UEC_ETH1  #if CFG_UEC1_UCC_NUM == 0  /* UCC1 */ -	{	"/" OF_QE "/ucc@2000/mac-address", +	{	"/" OF_QE "/ucc@2000",  		"mac-address",  		fdt_set_eth0  	}, -	{	"/" OF_QE "/ucc@2000/mac-address", +	{	"/" OF_QE "/ucc@2000",  		"local-mac-address",  		fdt_set_eth0  	},  #elif CFG_UEC1_UCC_NUM == 2  /* UCC3 */ -	{	"/" OF_QE "/ucc@2200/mac-address", +	{	"/" OF_QE "/ucc@2200",  		"mac-address",  		fdt_set_eth0  	}, -	{	"/" OF_QE "/ucc@2200/mac-address", +	{	"/" OF_QE "/ucc@2200",  		"local-mac-address",  		fdt_set_eth0  	},  #endif -#endif +#endif /* CONFIG_UEC_ETH1 */  #ifdef CONFIG_UEC_ETH2  #if CFG_UEC2_UCC_NUM == 1  /* UCC2 */ -	{	"/" OF_QE "/ucc@3000/mac-address", +	{	"/" OF_QE "/ucc@3000",  		"mac-address",  		fdt_set_eth1  	}, -	{	"/" OF_QE "/ucc@3000/mac-address", +	{	"/" OF_QE "/ucc@3000",  		"local-mac-address",  		fdt_set_eth1  	},  #elif CFG_UEC1_UCC_NUM == 3  /* UCC4 */ -	{	"/" OF_QE "/ucc@3200/mac-address", +	{	"/" OF_QE "/ucc@3200",  		"mac-address",  		fdt_set_eth1  	}, -	{	"/" OF_QE "/ucc@3200/mac-address", +	{	"/" OF_QE "/ucc@3200",  		"local-mac-address",  		fdt_set_eth1  	},  #endif -#endif +#endif /* CONFIG_UEC_ETH2 */  };  void @@ -487,20 +502,23 @@ ft_cpu_setup(void *blob, bd_t *bd)  	int  j;  	for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) { -		nodeoffset = fdt_path_offset(fdt, fixup_props[j].node); +		nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);  		if (nodeoffset >= 0) { -			err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd); +			err = fixup_props[j].set_fn(blob, nodeoffset, +						    fixup_props[j].prop, bd);  			if (err < 0) -				printf("set_fn/libfdt: %s %s returned %s\n", +				debug("Problem setting %s = %s: %s\n",  					fixup_props[j].node,  					fixup_props[j].prop,  					fdt_strerror(err)); +		} else { +			debug("Couldn't find %s: %s\n", +				fixup_props[j].node, +				fdt_strerror(nodeoffset));  		}  	}  } -#endif - -#if defined(CONFIG_OF_FLAT_TREE) +#elif defined(CONFIG_OF_FLAT_TREE)  void  ft_cpu_setup(void *blob, bd_t *bd)  { diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index 3ac91619c..722497966 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -83,20 +83,30 @@ void cpu_init_f (volatile immap_t * im)  	im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC2EP) | (CFG_SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT);  #endif -#ifdef CONFIG_MPC834X  #ifdef CFG_SCCR_TSEC1CM  	/* TSEC1 clock mode */  	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1CM) | (CFG_SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT);  #endif +  #ifdef CFG_SCCR_TSEC2CM  	/* TSEC2 & I2C1 clock mode */  	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2CM) | (CFG_SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT);  #endif + +#ifdef CFG_SCCR_TSEC1ON +	/* TSEC1 clock switch */ +	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1ON) | (CFG_SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT); +#endif + +#ifdef CFG_SCCR_TSEC2ON +	/* TSEC2 clock switch */ +	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2ON) | (CFG_SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT); +#endif +  #ifdef CFG_SCCR_USBMPHCM  	/* USB MPH clock mode */  	im->clk.sccr = (im->clk.sccr & ~SCCR_USBMPHCM) | (CFG_SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT);  #endif -#endif /* CONFIG_MPC834X */  #ifdef CFG_SCCR_PCICM  	/* PCI & DMA clock mode */ @@ -247,3 +257,39 @@ int cpu_init_r (void)  #endif  	return 0;  } + +/* + * Figure out the cause of the reset + */ +int prt_83xx_rsr(void) +{ +	static struct { +		ulong mask; +		char *desc; +	} bits[] = { +		{ +		RSR_SWSR, "Software Soft"}, { +		RSR_SWHR, "Software Hard"}, { +		RSR_JSRS, "JTAG Soft"}, { +		RSR_CSHR, "Check Stop"}, { +		RSR_SWRS, "Software Watchdog"}, { +		RSR_BMRS, "Bus Monitor"}, { +		RSR_SRS,  "External/Internal Soft"}, { +		RSR_HRS,  "External/Internal Hard"} +	}; +	static int n = sizeof bits / sizeof bits[0]; +	ulong rsr = gd->reset_status; +	int i; +	char *sep; + +	puts("Reset Status:"); + +	sep = " "; +	for (i = 0; i < n; i++) +		if (rsr & bits[i].mask) { +			printf("%s%s", sep, bits[i].desc); +			sep = ", "; +		} +	puts("\n\n"); +	return 0; +} diff --git a/cpu/mpc83xx/ecc.c b/cpu/mpc83xx/ecc.c new file mode 100644 index 000000000..6f1309424 --- /dev/null +++ b/cpu/mpc83xx/ecc.c @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2007 Freescale Semiconductor, Inc. + * + * Dave Liu <daveliu@freescale.com> + * based on the contribution of Marian Balakowicz <m8@semihalf.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. + */ + +#include <common.h> +#include <mpc83xx.h> +#include <command.h> + +#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) +void ecc_print_status(void) +{ +	volatile immap_t *immap = (immap_t *) CFG_IMMR; +	volatile ddr83xx_t *ddr = &immap->ddr; + +	printf("\nECC mode: %s\n\n", +	       (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); + +	/* Interrupts */ +	printf("Memory Error Interrupt Enable:\n"); +	printf("  Multiple-Bit Error Interrupt Enable: %d\n", +	       (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); +	printf("  Single-Bit Error Interrupt Enable: %d\n", +	       (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); +	printf("  Memory Select Error Interrupt Enable: %d\n\n", +	       (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); + +	/* Error disable */ +	printf("Memory Error Disable:\n"); +	printf("  Multiple-Bit Error Disable: %d\n", +	       (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); +	printf("  Sinle-Bit Error Disable: %d\n", +	       (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); +	printf("  Memory Select Error Disable: %d\n\n", +	       (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); + +	/* Error injection */ +	printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", +	       ddr->data_err_inject_hi, ddr->data_err_inject_lo); + +	printf("Memory Data Path Error Injection Mask ECC:\n"); +	printf("  ECC Mirror Byte: %d\n", +	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); +	printf("  ECC Injection Enable: %d\n", +	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); +	printf("  ECC Error Injection Mask: 0x%02x\n\n", +	       ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); + +	/* SBE counter/threshold */ +	printf("Memory Single-Bit Error Management (0..255):\n"); +	printf("  Single-Bit Error Threshold: %d\n", +	       (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); +	printf("  Single-Bit Error Counter: %d\n\n", +	       (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); + +	/* Error detect */ +	printf("Memory Error Detect:\n"); +	printf("  Multiple Memory Errors: %d\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); +	printf("  Multiple-Bit Error: %d\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); +	printf("  Single-Bit Error: %d\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); +	printf("  Memory Select Error: %d\n\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); + +	/* Capture data */ +	printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); +	printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", +	       ddr->capture_data_hi, ddr->capture_data_lo); +	printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", +	       ddr->capture_ecc & CAPTURE_ECC_ECE); + +	printf("Memory Error Attributes Capture:\n"); +	printf(" Data Beat Number: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> +	       ECC_CAPT_ATTR_BNUM_SHIFT); +	printf("  Transaction Size: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> +	       ECC_CAPT_ATTR_TSIZ_SHIFT); +	printf("  Transaction Source: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> +	       ECC_CAPT_ATTR_TSRC_SHIFT); +	printf("  Transaction Type: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> +	       ECC_CAPT_ATTR_TTYP_SHIFT); +	printf("  Error Information Valid: %d\n\n", +	       ddr->capture_attributes & ECC_CAPT_ATTR_VLD); +} + +int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +	volatile immap_t *immap = (immap_t *) CFG_IMMR; +	volatile ddr83xx_t *ddr = &immap->ddr; +	volatile u32 val; +	u64 *addr; +	u32 count; +	register u64 *i; +	u32 ret[2]; +	u32 pattern[2]; +	u32 writeback[2]; + +	/* The pattern is written into memory to generate error */ +	pattern[0] = 0xfedcba98UL; +	pattern[1] = 0x76543210UL; + +	/* After injecting error, re-initialize the memory with the value */ +	writeback[0] = 0x01234567UL; +	writeback[1] = 0x89abcdefUL; + +	if (argc > 4) { +		printf("Usage:\n%s\n", cmdtp->usage); +		return 1; +	} + +	if (argc == 2) { +		if (strcmp(argv[1], "status") == 0) { +			ecc_print_status(); +			return 0; +		} else if (strcmp(argv[1], "captureclear") == 0) { +			ddr->capture_address = 0; +			ddr->capture_data_hi = 0; +			ddr->capture_data_lo = 0; +			ddr->capture_ecc = 0; +			ddr->capture_attributes = 0; +			return 0; +		} +	} +	if (argc == 3) { +		if (strcmp(argv[1], "sbecnt") == 0) { +			val = simple_strtoul(argv[2], NULL, 10); +			if (val > 255) { +				printf("Incorrect Counter value, " +				       "should be 0..255\n"); +				return 1; +			} + +			val = (val << ECC_ERROR_MAN_SBEC_SHIFT); +			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); + +			ddr->err_sbe = val; +			return 0; +		} else if (strcmp(argv[1], "sbethr") == 0) { +			val = simple_strtoul(argv[2], NULL, 10); +			if (val > 255) { +				printf("Incorrect Counter value, " +				       "should be 0..255\n"); +				return 1; +			} + +			val = (val << ECC_ERROR_MAN_SBET_SHIFT); +			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); + +			ddr->err_sbe = val; +			return 0; +		} else if (strcmp(argv[1], "errdisable") == 0) { +			val = ddr->err_disable; + +			if (strcmp(argv[2], "+sbe") == 0) { +				val |= ECC_ERROR_DISABLE_SBED; +			} else if (strcmp(argv[2], "+mbe") == 0) { +				val |= ECC_ERROR_DISABLE_MBED; +			} else if (strcmp(argv[2], "+mse") == 0) { +				val |= ECC_ERROR_DISABLE_MSED; +			} else if (strcmp(argv[2], "+all") == 0) { +				val |= (ECC_ERROR_DISABLE_SBED | +					ECC_ERROR_DISABLE_MBED | +					ECC_ERROR_DISABLE_MSED); +			} else if (strcmp(argv[2], "-sbe") == 0) { +				val &= ~ECC_ERROR_DISABLE_SBED; +			} else if (strcmp(argv[2], "-mbe") == 0) { +				val &= ~ECC_ERROR_DISABLE_MBED; +			} else if (strcmp(argv[2], "-mse") == 0) { +				val &= ~ECC_ERROR_DISABLE_MSED; +			} else if (strcmp(argv[2], "-all") == 0) { +				val &= ~(ECC_ERROR_DISABLE_SBED | +					 ECC_ERROR_DISABLE_MBED | +					 ECC_ERROR_DISABLE_MSED); +			} else { +				printf("Incorrect err_disable field\n"); +				return 1; +			} + +			ddr->err_disable = val; +			__asm__ __volatile__("sync"); +			__asm__ __volatile__("isync"); +			return 0; +		} else if (strcmp(argv[1], "errdetectclr") == 0) { +			val = ddr->err_detect; + +			if (strcmp(argv[2], "mme") == 0) { +				val |= ECC_ERROR_DETECT_MME; +			} else if (strcmp(argv[2], "sbe") == 0) { +				val |= ECC_ERROR_DETECT_SBE; +			} else if (strcmp(argv[2], "mbe") == 0) { +				val |= ECC_ERROR_DETECT_MBE; +			} else if (strcmp(argv[2], "mse") == 0) { +				val |= ECC_ERROR_DETECT_MSE; +			} else if (strcmp(argv[2], "all") == 0) { +				val |= (ECC_ERROR_DETECT_MME | +					ECC_ERROR_DETECT_MBE | +					ECC_ERROR_DETECT_SBE | +					ECC_ERROR_DETECT_MSE); +			} else { +				printf("Incorrect err_detect field\n"); +				return 1; +			} + +			ddr->err_detect = val; +			return 0; +		} else if (strcmp(argv[1], "injectdatahi") == 0) { +			val = simple_strtoul(argv[2], NULL, 16); + +			ddr->data_err_inject_hi = val; +			return 0; +		} else if (strcmp(argv[1], "injectdatalo") == 0) { +			val = simple_strtoul(argv[2], NULL, 16); + +			ddr->data_err_inject_lo = val; +			return 0; +		} else if (strcmp(argv[1], "injectecc") == 0) { +			val = simple_strtoul(argv[2], NULL, 16); +			if (val > 0xff) { +				printf("Incorrect ECC inject mask, " +				       "should be 0x00..0xff\n"); +				return 1; +			} +			val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); + +			ddr->ecc_err_inject = val; +			return 0; +		} else if (strcmp(argv[1], "inject") == 0) { +			val = ddr->ecc_err_inject; + +			if (strcmp(argv[2], "en") == 0) +				val |= ECC_ERR_INJECT_EIEN; +			else if (strcmp(argv[2], "dis") == 0) +				val &= ~ECC_ERR_INJECT_EIEN; +			else +				printf("Incorrect command\n"); + +			ddr->ecc_err_inject = val; +			__asm__ __volatile__("sync"); +			__asm__ __volatile__("isync"); +			return 0; +		} else if (strcmp(argv[1], "mirror") == 0) { +			val = ddr->ecc_err_inject; + +			if (strcmp(argv[2], "en") == 0) +				val |= ECC_ERR_INJECT_EMB; +			else if (strcmp(argv[2], "dis") == 0) +				val &= ~ECC_ERR_INJECT_EMB; +			else +				printf("Incorrect command\n"); + +			ddr->ecc_err_inject = val; +			return 0; +		} +	} +	if (argc == 4) { +		if (strcmp(argv[1], "testdw") == 0) { +			addr = (u64 *) simple_strtoul(argv[2], NULL, 16); +			count = simple_strtoul(argv[3], NULL, 16); + +			if ((u32) addr % 8) { +				printf("Address not alligned on " +				       "double word boundary\n"); +				return 1; +			} +			disable_interrupts(); + +			for (i = addr; i < addr + count; i++) { + +				/* enable injects */ +				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* write memory location injecting errors */ +				ppcDWstore((u32 *) i, pattern); +				__asm__ __volatile__("sync"); + +				/* disable injects */ +				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* read data, this generates ECC error */ +				ppcDWload((u32 *) i, ret); +				__asm__ __volatile__("sync"); + +				/* re-initialize memory, double word write the location again, +				 * generates new ECC code this time */ +				ppcDWstore((u32 *) i, writeback); +				__asm__ __volatile__("sync"); +			} +			enable_interrupts(); +			return 0; +		} +		if (strcmp(argv[1], "testword") == 0) { +			addr = (u64 *) simple_strtoul(argv[2], NULL, 16); +			count = simple_strtoul(argv[3], NULL, 16); + +			if ((u32) addr % 8) { +				printf("Address not alligned on " +				       "double word boundary\n"); +				return 1; +			} +			disable_interrupts(); + +			for (i = addr; i < addr + count; i++) { + +				/* enable injects */ +				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* write memory location injecting errors */ +				*(u32 *) i = 0xfedcba98UL; +				__asm__ __volatile__("sync"); + +				/* sub double word write, +				 * bus will read-modify-write, +				 * generates ECC error */ +				*((u32 *) i + 1) = 0x76543210UL; +				__asm__ __volatile__("sync"); + +				/* disable injects */ +				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* re-initialize memory, +				 * double word write the location again, +				 * generates new ECC code this time */ +				ppcDWstore((u32 *) i, writeback); +				__asm__ __volatile__("sync"); +			} +			enable_interrupts(); +			return 0; +		} +	} +	printf("Usage:\n%s\n", cmdtp->usage); +	return 1; +} + +U_BOOT_CMD(ecc, 4, 0, do_ecc, +	   "ecc     - support for DDR ECC features\n", +	   "status              - print out status info\n" +	   "ecc captureclear        - clear capture regs data\n" +	   "ecc sbecnt <val>        - set Single-Bit Error counter\n" +	   "ecc sbethr <val>        - set Single-Bit Threshold\n" +	   "ecc errdisable <flag>   - clear/set disable Memory Error Disable, flag:\n" +	   "  [-|+]sbe - Single-Bit Error\n" +	   "  [-|+]mbe - Multiple-Bit Error\n" +	   "  [-|+]mse - Memory Select Error\n" +	   "  [-|+]all - all errors\n" +	   "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" +	   "  mme - Multiple Memory Errors\n" +	   "  sbe - Single-Bit Error\n" +	   "  mbe - Multiple-Bit Error\n" +	   "  mse - Memory Select Error\n" +	   "  all - all errors\n" +	   "ecc injectdatahi <hi>  - set Memory Data Path Error Injection Mask High\n" +	   "ecc injectdatalo <lo>  - set Memory Data Path Error Injection Mask Low\n" +	   "ecc injectecc <ecc>    - set ECC Error Injection Mask\n" +	   "ecc inject <en|dis>    - enable/disable error injection\n" +	   "ecc mirror <en|dis>    - enable/disable mirror byte\n" +	   "ecc testdw <addr> <cnt>  - test mem region with double word access:\n" +	   "  - enables injects\n" +	   "  - writes pattern injecting errors with double word access\n" +	   "  - disables injects\n" +	   "  - reads pattern back with double word access, generates error\n" +	   "  - re-inits memory\n" +	   "ecc testword <addr> <cnt>  - test mem region with word access:\n" +	   "  - enables injects\n" +	   "  - writes pattern injecting errors with word access\n" +	   "  - writes pattern with word access, generates error\n" +	   "  - disables injects\n" "  - re-inits memory"); +#endif diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c index 785d6129d..229821887 100644 --- a/cpu/mpc83xx/pci.c +++ b/cpu/mpc83xx/pci.c @@ -25,7 +25,14 @@  #include <common.h>  #include <pci.h> + +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#elif defined(CONFIG_OF_FLAT_TREE)  #include <ft_build.h> +#endif +  #include <asm/mpc8349_pci.h>  #ifdef CONFIG_83XX_GENERIC_PCI @@ -163,7 +170,34 @@ void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot)  		pci_init_bus(i, reg[i]);  } -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_LIBFDT) +void ft_pci_setup(void *blob, bd_t *bd) +{ +	int nodeoffset; +	int err; +	int tmp[2]; + +	if (pci_num_buses < 1) +		return; + +	nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8500"); +	if (nodeoffset >= 0) { +		tmp[0] = cpu_to_be32(pci_hose[0].first_busno); +		tmp[1] = cpu_to_be32(pci_hose[0].last_busno); +		err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp)); +	} + +	if (pci_num_buses < 2) +		return; + +	nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8600"); +	if (nodeoffset >= 0) { +		tmp[0] = cpu_to_be32(pci_hose[0].first_busno); +		tmp[1] = cpu_to_be32(pci_hose[0].last_busno); +		err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp)); +	} +} +#elif CONFIG_OF_FLAT_TREE  void ft_pci_setup(void *blob, bd_t *bd)  {  	u32 *p; diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 647813f68..54f0c83d4 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -574,7 +574,10 @@ long int spd_sdram()  	/* Check DIMM data bus width */  	if (spd.dataw_lsb == 0x20) { -		burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ +		if (spd.mem_type == SPD_MEMTYPE_DDR) +			burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ +		else +			burstlen = 0x02; /* 32 bit data bus, burst len is 4 */  		printf("\n   DDR DIMM: data bus width is 32 bit");  	} else {  		burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */ @@ -730,8 +733,12 @@ long int spd_sdram()  		sdram_cfg |= 0x10000000;  	/* The DIMM is 32bit width */ -	if (spd.dataw_lsb == 0x20) -		sdram_cfg |= 0x000C0000; +	if (spd.dataw_lsb == 0x20) { +		if (spd.mem_type == SPD_MEMTYPE_DDR) +			sdram_cfg |= 0x000C0000; +		if (spd.mem_type == SPD_MEMTYPE_DDR2) +			sdram_cfg |= 0x00080000; +	}  	ddrc_ecc_enable = 0; diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile index 4068b5320..af9da5b95 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -27,12 +27,12 @@ LIB	= $(obj)lib$(CPU).a  START	= start.o resetvec.o kgdb.o  SOBJS	= dcr.o -COBJS	= 405gp_pci.o 4xx_enet.o \ +COBJS	= 405gp_pci.o 440spe_pcie.o 4xx_enet.o \  	  bedbug_405.o commproc.o \  	  cpu.o cpu_init.o gpio.o i2c.o interrupts.o \  	  miiphy.o ndfc.o sdram.o serial.o \  	  40x_spd_sdram.o 44x_spd_ddr.o 44x_spd_ddr2.o speed.o \ -	  tlb.o traps.o usb_ohci.o usbdev.o \ +	  tlb.o traps.o usb_ohci.o usb.o usbdev.o \  	  440spe_pcie.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/cpu/ppc4xx/usb.c b/cpu/ppc4xx/usb.c new file mode 100644 index 000000000..2837b37c5 --- /dev/null +++ b/cpu/ppc4xx/usb.c @@ -0,0 +1,50 @@ +/* + * (C) Copyright 2007 + * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de> + * + * 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> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) + +#include "usbdev.h" + +int usb_cpu_init() +{ + +#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) +	usb_dev_init(); +#endif + +	return 0; +} + +int usb_cpu_stop() +{ +	return 0; +} + +int usb_cpu_init_fail() +{ +	return 0; +} + +#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */ diff --git a/cpu/pxa/Makefile b/cpu/pxa/Makefile index cded7ffd3..8b4367e20 100644 --- a/cpu/pxa/Makefile +++ b/cpu/pxa/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(CPU).a  START	= start.o -COBJS	= serial.o interrupts.o cpu.o i2c.o pxafb.o mmc.o +COBJS	= serial.o interrupts.o cpu.o i2c.o pxafb.o mmc.o usb.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/pxa/usb.c b/cpu/pxa/usb.c new file mode 100644 index 000000000..65f457fe5 --- /dev/null +++ b/cpu/pxa/usb.c @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2006 + * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de> + * + * 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> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CFG_USB_OHCI_CPU_INIT) +# if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X) + +#include <asm/arch/pxa-regs.h> + +int usb_cpu_init() +{ +#if defined(CONFIG_CPU_MONAHANS) +	/* Enable USB host clock. */ +	CKENA |= (CKENA_2_USBHOST |  CKENA_20_UDC); +	udelay(100); +#endif +#if defined(CONFIG_PXA27X) +	/* Enable USB host clock. */ +	CKEN |= CKEN10_USBHOST; +#endif + +#if defined(CONFIG_CPU_MONAHANS) +	/* Configure Port 2 for Host (USB Client Registers) */ +	UP2OCR = 0x3000c; +#endif + +	UHCHR |= UHCHR_FHR; +	wait_ms(11); +	UHCHR &= ~UHCHR_FHR; + +	UHCHR |= UHCHR_FSBIR; +	while (UHCHR & UHCHR_FSBIR) +		udelay(1); + +#if defined(CONFIG_CPU_MONAHANS) +	UHCHR &= ~UHCHR_SSEP0; +#endif +#if defined(CONFIG_PXA27X) +	UHCHR &= ~UHCHR_SSEP2; +#endif +	UHCHR &= ~UHCHR_SSEP1; +	UHCHR &= ~UHCHR_SSE; + +	return 0; +} + +int usb_cpu_stop() +{ +	return 0; +} + +int usb_cpu_init_fail() +{ +	return 0; +} + +# endif /* defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X) */ +#endif /* defined(CONFIG_USB_OHCI) && defined(CFG_USB_OHCI_CPU_INIT) */ diff --git a/doc/README.generic_usb_ohci b/doc/README.generic_usb_ohci new file mode 100644 index 000000000..c343dfdf9 --- /dev/null +++ b/doc/README.generic_usb_ohci @@ -0,0 +1,60 @@ +Notes on the the generic USB-OHCI driver +======================================== + +This driver (drivers/usb_ohci.[ch]) is the result of the merge of +various existing OHCI drivers that were basically identical beside +cpu/board dependant initalization. This initalization has been moved +into cpu/board directories and are called via the hooks below. + +Configuration options +---------------------- + +	CONFIG_USB_OHCI_NEW: enable the new OHCI driver + +	CFG_USB_OHCI_BOARD_INIT: call the board dependant hooks: + +		  - extern int usb_board_init(void); +		  - extern int usb_board_stop(void); +		  - extern int usb_cpu_init_fail(void); + +	CFG_USB_OHCI_CPU_INIT: call the cpu dependant hooks: + +		  - extern int usb_cpu_init(void); +		  - extern int usb_cpu_stop(void); +		  - extern int usb_cpu_init_fail(void); + +	CFG_USB_OHCI_REGS_BASE: defines the base address of the OHCI +				registers + +	CFG_USB_OHCI_SLOT_NAME: slot name + +	CFG_USB_OHCI_MAX_ROOT_PORTS: maximal number of ports of the +				     root hub. + + +Endianness issues +------------------ + +The USB bus operates in little endian, but unfortunately there are +OHCI controllers that operate in big endian such as ppc4xx and +mpc5xxx. For these the config option + +	CFG_OHCI_BE_CONTROLLER + +needs to be defined.  + + +PCI Controllers +---------------- + +You'll need to define + +	CONFIG_PCI_OHCI + +PCI Controllers need to do byte swapping on register accesses, so they +should to define: + +	CFG_OHCI_SWAP_REG_ACCESS + + + diff --git a/doc/README.mpc8323erdb b/doc/README.mpc8323erdb new file mode 100644 index 000000000..6f8982937 --- /dev/null +++ b/doc/README.mpc8323erdb @@ -0,0 +1,71 @@ +Freescale MPC8323ERDB Board +----------------------------------------- + +1.	Memory Map +	The memory map looks like this: + +	0x0000_0000	0x03ff_ffff	DDR		 64M +	0x8000_0000	0x8fff_ffff	PCI MEM		 256M +	0x9000_0000	0x9fff_ffff	PCI_MMIO	 256M +	0xe000_0000	0xe00f_ffff	IMMR		 1M +	0xd000_0000	0xd3ff_ffff	PCI IO		 64M +	0xfe00_0000	0xfeff_ffff	NOR FLASH (CS0)	 16M + +2.	Compilation + +	Assuming you're using BASH (or similar) as your shell: + +	export CROSS_COMPILE=your-cross-compiler-prefix- +	make distclean +	make MPC8323ERDB_config +	make + +3.	Downloading and Flashing Images + +3.1	Reflash U-boot Image using U-boot + +	N.b, have an alternate means of programming +	the flash available if the new u-boot doesn't boot. + +	First try a: + +	tftpboot $loadaddr $uboot + +	to make sure that the TFTP load will succeed before +	an erase goes ahead and wipes out your current firmware. +	Then do a: + +	run tftpflash + +	which is a shorter version of the manual sequence: + +	tftp $loadaddr u-boot.bin +	protect off fe000000 +$filesize +	erase fe000000 +$filesize +	cp.b $loadaddr fe000000 $filesize + +	To keep your old u-boot's environment variables, do a: + +	saveenv + +	prior to resetting the board. + +3.2	Downloading and Booting Linux Kernel + +	Ensure that all networking-related environment variables are set +	properly (including ipaddr, serverip, gatewayip (if needed), +	netmask, ethaddr, eth1addr, rootpath (if using NFS root), +	fdtfile, and bootfile). + +	Then, do one of the following, depending on whether you +	want an NFS root or a ramdisk root: + +	run nfsboot + +	or + +	run ramboot + +4	Notes + +	The console baudrate for MPC8323ERDB is 115200bps. diff --git a/doc/README.mpc8360emds b/doc/README.mpc8360emds index c87469f43..5f202475b 100644 --- a/doc/README.mpc8360emds +++ b/doc/README.mpc8360emds @@ -21,7 +21,13 @@ Freescale MPC8360EMDS Board  	SW3[1:8]= 0000_0001 refers to bits labeled 1 through 6 is set as "On"  		and bits labeled 8 is set as "Off". -1.1	For the MPC8360E PB PROTO Board +1.1	There are three type boards for MPC8360E silicon up to now, They are + +	* MPC8360E-MDS-PB PROTO (a.k.a 8360SYS PROTOTYPE) +	* MPC8360E-MDS-PB PILOT (a.k.a 8360SYS PILOT) +	* MPC8360EA-MDS-PB PROTO (a.k.a 8360SYS2 PROTOTYPE) + +1.2	For all the MPC8360EMDS Board  	First, make sure the board default setting is consistent with the  	document shipped with your board. Then apply the following setting: @@ -33,6 +39,21 @@ Freescale MPC8360EMDS Board  	JP6 1-2  	on board Oscillator: 66M +1.3	Since different board/chip rev. combinations have AC timing issues, +	u-boot forces RGMII-ID (RGMII with Internal Delay) mode on by default +	by the patch (mpc83xx: Disable G1TXCLK, G2TXCLK h/w buffers). + +	When the rev2.x silicon mount on these boards, and if you are using +	u-boot version after this patch, to make the ethernet interfaces usable, +	and to enable RGMII-ID on your board, you have to setup the jumpers +	correctly. + +	* MPC8360E-MDS-PB PROTO +	  nothing to do +	* MPC8360E-MDS-PB PILOT +	  JP9 and JP8 should be ON +	* MPC8360EA-MDS-PB PROTO +	  JP2 and JP3 should be ON  2.	Memory Map diff --git a/doc/README.mpc8349emds.ddrecc b/doc/README.mpc83xx.ddrecc index eb249c395..0029f0875 100644 --- a/doc/README.mpc8349emds.ddrecc +++ b/doc/README.mpc83xx.ddrecc @@ -15,10 +15,10 @@ IMPORTANT NOTICE: enabling injecting multiple-bit errors is potentially  dangerous as such errors are NOT corrected by the controller. Therefore caution  should be taken when enabling the injection of multiple-bit errors: it is only  safe when used on a carefully selected memory area and used under control of -the 'ecc test' command (see example 'Injecting Multiple-Bit Errors' below). In -particular, when you simply set the multiple-bit errors in inject mask and -enable injection, U-Boot is very likely to hang quickly as the errors will be -injected when it accesses its code, data etc. +the 'ecc testdw' 'ecc testword' command (see example 'Injecting Multiple-Bit +Errors' below). In particular, when you simply set the multiple-bit errors in +inject mask and enable injection, U-Boot is very likely to hang quickly as the +errors will be injected when it accesses its code, data etc.  Use cases for DDR 'ecc' command: @@ -40,7 +40,7 @@ Injecting Single-Bit Errors  2. Run test over some memory region -=> ecc test 200000 10 +=> ecc testdw 200000 10  3. Check ECC status @@ -61,57 +61,57 @@ Memory Error Detect:  16 errors were generated, Single-Bit Error flag was not set as Single Bit Error  Counter did not reach  Single-Bit Error Threshold. -4. Make sure used memory region got re-initialized with 0xcafecafe pattern +4. Make sure used memory region got re-initialized with 0x0123456789abcdef  => md 200000 -00200000: cafecafe cafecafe cafecafe cafecafe    ................ -00200010: cafecafe cafecafe cafecafe cafecafe    ................ -00200020: cafecafe cafecafe cafecafe cafecafe    ................ -00200030: cafecafe cafecafe cafecafe cafecafe    ................ -00200040: cafecafe cafecafe cafecafe cafecafe    ................ -00200050: cafecafe cafecafe cafecafe cafecafe    ................ -00200060: cafecafe cafecafe cafecafe cafecafe    ................ -00200070: cafecafe cafecafe cafecafe cafecafe    ................ +00200000: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200010: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200020: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200030: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200040: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200050: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200060: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200070: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg....  00200080: deadbeef deadbeef deadbeef deadbeef    ................  00200090: deadbeef deadbeef deadbeef deadbeef    ................ -  Injecting Multiple-Bit Errors  -----------------------------  1. Set more than 1 bit in Data Path Error Inject Mask -=> ecc injectdatahi 5 +=> ecc injectdatahi 1 +=> ecc injectdatalo 1  2. Run test over some memory region -=> ecc test 200000 10 +=> ecc testword 200000 1  3. Check ECC status  => ecc status  ... -Memory Data Path Error Injection Mask High/Low: 00000005 00000000 +Memory Data Path Error Injection Mask High/Low: 00000001 00000001  ...  Memory Error Detect: -  Multiple Memory Errors: 1 +  Multiple Memory Errors: 0    Multiple-Bit Error: 1    Single-Bit Error: 0  ... -Observe that both Multiple Memory Errors and Multiple-Bit Error flags are set. +The Multiple Memory Errors flags not set and Multiple-Bit Error flags are set. -4. Make sure used memory region got re-initialized with 0xcafecafe pattern +4. Make sure used memory region got re-initialized with 0x0123456789abcdef  => md 200000 -00200000: cafecafe cafecafe cafecafe cafecafe    ................ -00200010: cafecafe cafecafe cafecafe cafecafe    ................ -00200020: cafecafe cafecafe cafecafe cafecafe    ................ -00200030: cafecafe cafecafe cafecafe cafecafe    ................ -00200040: cafecafe cafecafe cafecafe cafecafe    ................ -00200050: cafecafe cafecafe cafecafe cafecafe    ................ -00200060: cafecafe cafecafe cafecafe cafecafe    ................ -00200070: cafecafe cafecafe cafecafe cafecafe    ................ +00200000: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200010: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200020: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200030: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200040: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200050: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200060: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg.... +00200070: 01234567 89abcdef 01234567 89abcdef    .#Eg.....#Eg....  00200080: deadbeef deadbeef deadbeef deadbeef    ................  00200090: deadbeef deadbeef deadbeef deadbeef    ................ @@ -140,7 +140,7 @@ Test Single-Bit Error Counter and Threshold  ...  Memory Single-Bit Error Management (0..255):    Single-Bit Error Threshold: 255 -  Single Bit Error Counter: 60 +  Single Bit Error Counter: 199  Memory Error Detect:    Multiple Memory Errors: 1 diff --git a/drivers/Makefile b/drivers/Makefile index 881153ac9..fc9804076 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -31,7 +31,7 @@ COBJS	= 3c589.o 5701rls.o ali512x.o ata_piix.o atmel_usart.o \  	  bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \  	  cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \  	  e1000.o eepro100.o enc28j60.o \ -	  i8042.o inca-ip_sw.o keyboard.o \ +	  i8042.o inca-ip_sw.o isp116x-hcd.o keyboard.o \  	  lan91c96.o macb.o \  	  natsemi.o ne2000.o netarm_eth.o netconsole.o \  	  ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \ @@ -47,7 +47,9 @@ COBJS	= 3c589.o 5701rls.o ali512x.o ata_piix.o atmel_usart.o \  	  status_led.o sym53c8xx.o systemace.o ahci.o \  	  ti_pci1410a.o tigon3.o tsec.o \  	  tsi108_eth.o tsi108_i2c.o tsi108_pci.o \ -	  usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \ +	  usb_ohci.o \ +	  usbdcore.o usbdcore_ep0.o usbdcore_mpc8xx.o usbdcore_omap1510.o \ +	  usbtty.o \  	  videomodes.o w83c553f.o \  	  ks8695eth.o \  	  pxa_pcmcia.o mpc8xx_pcmcia.o tqm8xx_pcmcia.o	\ diff --git a/drivers/bios_emulator/Makefile b/drivers/bios_emulator/Makefile index ba7d43673..586e83be8 100644 --- a/drivers/bios_emulator/Makefile +++ b/drivers/bios_emulator/Makefile @@ -1,6 +1,6 @@  include $(TOPDIR)/config.mk -LIB := libatibiosemu.a +LIB := $(obj)libatibiosemu.a  X86DIR  = ./x86emu diff --git a/drivers/fsl_i2c.c b/drivers/fsl_i2c.c index ebae5af15..22485ea91 100644 --- a/drivers/fsl_i2c.c +++ b/drivers/fsl_i2c.c @@ -69,9 +69,10 @@ i2c_init(int speed, int slaveadd)  	dev = (struct fsl_i2c *) (CFG_IMMR + CFG_I2C2_OFFSET);  	writeb(0, &dev->cr);			/* stop I2C controller */ +	udelay(5);				/* let it shutdown in peace */  	writeb(0x3F, &dev->fdr);		/* set bus speed */  	writeb(0x3F, &dev->dfsrr);		/* set default filter */ -	writeb(slaveadd, &dev->adr);		/* write slave address */ +	writeb(slaveadd << 1, &dev->adr);	/* write slave address */  	writeb(0x0, &dev->sr);			/* clear status register */  	writeb(I2C_CR_MEN, &dev->cr);		/* start I2C controller */  #endif	/* CFG_I2C2_OFFSET */ diff --git a/drivers/isp116x-hcd.c b/drivers/isp116x-hcd.c new file mode 100644 index 000000000..8e2bc7adc --- /dev/null +++ b/drivers/isp116x-hcd.c @@ -0,0 +1,1413 @@ +/* + * ISP116x HCD (Host Controller Driver) for u-boot. + * + * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it> + * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it> + * + * 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 + * + * + * Derived in part from the SL811 HCD driver "u-boot/drivers/sl811_usb.c" + * (original copyright message follows): + * + *    (C) Copyright 2004 + *    Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + *    This code is based on linux driver for sl811hs chip, source at + *    drivers/usb/host/sl811.c: + * + *    SL811 Host Controller Interface driver for USB. + * + *    Copyright (c) 2003/06, Courage Co., Ltd. + * + *    Based on: + *         1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, + *           Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, + *           Adam Richter, Gregory P. Smith; + *         2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com> + *         3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn> + * + *    [[GNU/GPL disclaimer]] + * + * and in part from AU1x00 OHCI HCD driver "u-boot/cpu/mips/au1x00_usb_ohci.c" + * (original copyright message follows): + * + *    URB OHCI HCD (Host Controller Driver) for USB on the AU1x00. + * + *    (C) Copyright 2003 + *    Gary Jennejohn, DENX Software Engineering <gj@denx.de> + * + *    [[GNU/GPL disclaimer]] + * + *    Note: Part of this code has been derived from linux + */ + +#include <common.h> + +#ifdef CONFIG_USB_ISP116X_HCD +#include <asm/io.h> +#include <usb.h> +#include <malloc.h> +#include <linux/list.h> + +/* + * ISP116x chips require certain delays between accesses to its + * registers. The following timing options exist. + * + * 1. Configure your memory controller (the best) + * 2. Use ndelay (easiest, poorest). For that, enable the following macro. + * + * Value is in microseconds. + */ +#ifdef ISP116X_HCD_USE_UDELAY +#define UDELAY		1 +#endif + +/* + * On some (slowly?) machines an extra delay after data packing into + * controller's FIFOs is required, * otherwise you may get the following + * error: + * + *   uboot> usb start + *   (Re)start USB... + *   USB:   scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT + *   isp116x: isp116x_submit_job: ****** FIFO not ready! ****** + * + *         USB device not responding, giving up (status=4) + *         isp116x: isp116x_submit_job: ****** FIFO not empty! ****** + *         isp116x: isp116x_submit_job: ****** FIFO not empty! ****** + *         isp116x: isp116x_submit_job: ****** FIFO not empty! ****** + *         3 USB Device(s) found + *                scanning bus for storage devices... 0 Storage Device(s) found + * + * Value is in milliseconds. + */ +#ifdef ISP116X_HCD_USE_EXTRA_DELAY +#define EXTRA_DELAY	2 +#endif + +/* + * Enable the following defines if you wish enable debugging messages. + */ +#undef DEBUG			/* enable debugging messages */ +#undef TRACE			/* enable tracing code */ +#undef VERBOSE			/* verbose debugging messages */ + +#include "isp116x.h" + +#define DRIVER_VERSION	"08 Jan 2007" +static const char hcd_name[] = "isp116x-hcd"; + +struct isp116x isp116x_dev; +struct isp116x_platform_data isp116x_board; +int got_rhsc = 0;		/* root hub status change */ +struct usb_device *devgone;	/* device which was disconnected */ +int rh_devnum = 0;		/* address of Root Hub endpoint */ + +/* ------------------------------------------------------------------------- */ + +#define ALIGN(x,a)	(((x)+(a)-1UL)&~((a)-1UL)) +#define min_t(type,x,y)	\ +	({ type __x = (x); type __y = (y); __x < __y ? __x : __y; }) + +/* ------------------------------------------------------------------------- */ + +static int isp116x_reset(struct isp116x *isp116x); + +/* --- Debugging functions ------------------------------------------------- */ + +#define isp116x_show_reg(d, r) {				\ +	if ((r) < 0x20) {					\ +		DBG("%-12s[%02x]: %08x", #r,			\ +			r, isp116x_read_reg32(d, r));		\ +	} else {						\ +		DBG("%-12s[%02x]:     %04x", #r,		\ +			r, isp116x_read_reg16(d, r));  		\ +	}							\ +} + +#define isp116x_show_regs(d) {					\ +	isp116x_show_reg(d, HCREVISION);			\ +	isp116x_show_reg(d, HCCONTROL);				\ +	isp116x_show_reg(d, HCCMDSTAT);				\ +	isp116x_show_reg(d, HCINTSTAT);				\ +	isp116x_show_reg(d, HCINTENB);				\ +	isp116x_show_reg(d, HCFMINTVL);				\ +	isp116x_show_reg(d, HCFMREM);				\ +	isp116x_show_reg(d, HCFMNUM);				\ +	isp116x_show_reg(d, HCLSTHRESH);			\ +	isp116x_show_reg(d, HCRHDESCA);				\ +	isp116x_show_reg(d, HCRHDESCB);				\ +	isp116x_show_reg(d, HCRHSTATUS);			\ +	isp116x_show_reg(d, HCRHPORT1);				\ +	isp116x_show_reg(d, HCRHPORT2);				\ +	isp116x_show_reg(d, HCHWCFG);				\ +	isp116x_show_reg(d, HCDMACFG);				\ +	isp116x_show_reg(d, HCXFERCTR);				\ +	isp116x_show_reg(d, HCuPINT);				\ +	isp116x_show_reg(d, HCuPINTENB);			\ +	isp116x_show_reg(d, HCCHIPID);				\ +	isp116x_show_reg(d, HCSCRATCH);				\ +	isp116x_show_reg(d, HCITLBUFLEN);			\ +	isp116x_show_reg(d, HCATLBUFLEN);			\ +	isp116x_show_reg(d, HCBUFSTAT);				\ +	isp116x_show_reg(d, HCRDITL0LEN);			\ +	isp116x_show_reg(d, HCRDITL1LEN);			\ +} + +#if defined(TRACE) + +static int isp116x_get_current_frame_number(struct usb_device *usb_dev) +{ +	struct isp116x *isp116x = &isp116x_dev; + +	return isp116x_read_reg32(isp116x, HCFMNUM); +} + +static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +		     int len, char *str) +{ +#if defined(VERBOSE) +	int i; +#endif + +	DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx", +	    str, +	    isp116x_get_current_frame_number(dev), +	    usb_pipedevice(pipe), +	    usb_pipeendpoint(pipe), +	    usb_pipeout(pipe) ? 'O' : 'I', +	    usb_pipetype(pipe) < 2 ? +	    (usb_pipeint(pipe) ? +	     "INTR" : "ISOC") : +	    (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status); +#if defined(VERBOSE) +	if (len > 0 && buffer) { +		printf(__FILE__ ": data(%d):", len); +		for (i = 0; i < 16 && i < len; i++) +			printf(" %02x", ((__u8 *) buffer)[i]); +		printf("%s\n", i < len ? "..." : ""); +	} +#endif +} + +#define PTD_DIR_STR(ptd)  ({char __c;		\ +	switch(PTD_GET_DIR(ptd)){		\ +	case 0:  __c = 's'; break;		\ +	case 1:  __c = 'o'; break;		\ +	default: __c = 'i'; break;		\ +	}; __c;}) + +/* +  Dump PTD info. The code documents the format +  perfectly, right :) +*/ +static inline void dump_ptd(struct ptd *ptd) +{ +#if defined(VERBOSE) +	int k; +#endif + +	DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x", +	    PTD_GET_CC(ptd), +	    PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd), +	    PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), +	    PTD_GET_TOGGLE(ptd), +	    PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd)); +#if defined(VERBOSE) +	printf("isp116x: %s: PTD(byte): ", __FUNCTION__); +	for (k = 0; k < sizeof(struct ptd); ++k) +		printf("%02x ", ((u8 *) ptd)[k]); +	printf("\n"); +#endif +} + +static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type) +{ +#if defined(VERBOSE) +	int k; + +	if (type == 0 /* 0ut data */ ) { +		printf("isp116x: %s: out data: ", __FUNCTION__); +		for (k = 0; k < PTD_GET_LEN(ptd); ++k) +			printf("%02x ", ((u8 *) buf)[k]); +		printf("\n"); +	} +	if (type == 1 /* 1n data */ ) { +		printf("isp116x: %s: in data: ", __FUNCTION__); +		for (k = 0; k < PTD_GET_COUNT(ptd); ++k) +			printf("%02x ", ((u8 *) buf)[k]); +		printf("\n"); +	} + +	if (PTD_GET_LAST(ptd)) +		DBG("--- last PTD ---"); +#endif +} + +#else + +#define dump_msg(dev, pipe, buffer, len, str)			do { } while (0) +#define dump_pkt(dev, pipe, buffer, len, setup, str, small)	do {} while (0) + +#define dump_ptd(ptd)			do {} while (0) +#define dump_ptd_data(ptd, buf, type)	do {} while (0) + +#endif + +/* --- Virtual Root Hub ---------------------------------------------------- */ + +/* Device descriptor */ +static __u8 root_hub_dev_des[] = { +	0x12,			/*  __u8  bLength; */ +	0x01,			/*  __u8  bDescriptorType; Device */ +	0x10,			/*  __u16 bcdUSB; v1.1 */ +	0x01, +	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */ +	0x00,			/*  __u8  bDeviceSubClass; */ +	0x00,			/*  __u8  bDeviceProtocol; */ +	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */ +	0x00,			/*  __u16 idVendor; */ +	0x00, +	0x00,			/*  __u16 idProduct; */ +	0x00, +	0x00,			/*  __u16 bcdDevice; */ +	0x00, +	0x00,			/*  __u8  iManufacturer; */ +	0x01,			/*  __u8  iProduct; */ +	0x00,			/*  __u8  iSerialNumber; */ +	0x01			/*  __u8  bNumConfigurations; */ +}; + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = { +	0x09,			/*  __u8  bLength; */ +	0x02,			/*  __u8  bDescriptorType; Configuration */ +	0x19,			/*  __u16 wTotalLength; */ +	0x00, +	0x01,			/*  __u8  bNumInterfaces; */ +	0x01,			/*  __u8  bConfigurationValue; */ +	0x00,			/*  __u8  iConfiguration; */ +	0x40,			/*  __u8  bmAttributes; +				   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ +	0x00,			/*  __u8  MaxPower; */ + +	/* interface */ +	0x09,			/*  __u8  if_bLength; */ +	0x04,			/*  __u8  if_bDescriptorType; Interface */ +	0x00,			/*  __u8  if_bInterfaceNumber; */ +	0x00,			/*  __u8  if_bAlternateSetting; */ +	0x01,			/*  __u8  if_bNumEndpoints; */ +	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */ +	0x00,			/*  __u8  if_bInterfaceSubClass; */ +	0x00,			/*  __u8  if_bInterfaceProtocol; */ +	0x00,			/*  __u8  if_iInterface; */ + +	/* endpoint */ +	0x07,			/*  __u8  ep_bLength; */ +	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */ +	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */ +	0x03,			/*  __u8  ep_bmAttributes; Interrupt */ +	0x00,			/*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ +	0x02, +	0xff			/*  __u8  ep_bInterval; 255 ms */ +}; + +static unsigned char root_hub_str_index0[] = { +	0x04,			/*  __u8  bLength; */ +	0x03,			/*  __u8  bDescriptorType; String-descriptor */ +	0x09,			/*  __u8  lang ID */ +	0x04,			/*  __u8  lang ID */ +}; + +static unsigned char root_hub_str_index1[] = { +	0x22,			/*  __u8  bLength; */ +	0x03,			/*  __u8  bDescriptorType; String-descriptor */ +	'I',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'S',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'P',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'1',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'1',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'6',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'x',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	' ',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'R',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'o',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'o',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	't',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	' ',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'H',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'u',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +	'b',			/*  __u8  Unicode */ +	0,			/*  __u8  Unicode */ +}; + +/* + * Hub class-specific descriptor is constructed dynamically + */ + +/* --- Virtual root hub management functions ------------------------------- */ + +static int rh_check_port_status(struct isp116x *isp116x) +{ +	u32 temp, ndp, i; +	int res; + +	res = -1; +	temp = isp116x_read_reg32(isp116x, HCRHSTATUS); +	ndp = (temp & RH_A_NDP); +	for (i = 0; i < ndp; i++) { +		temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i); +		/* check for a device disconnect */ +		if (((temp & (RH_PS_PESC | RH_PS_CSC)) == +		     (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { +			res = i; +			break; +		} +	} +	return res; +} + +/* --- HC management functions --------------------------------------------- */ + +/* Write len bytes to fifo, pad till 32-bit boundary + */ +static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) +{ +	u8 *dp = (u8 *) buf; +	u16 *dp2 = (u16 *) buf; +	u16 w; +	int quot = len % 4; + +	if ((unsigned long)dp2 & 1) { +		/* not aligned */ +		for (; len > 1; len -= 2) { +			w = *dp++; +			w |= *dp++ << 8; +			isp116x_raw_write_data16(isp116x, w); +		} +		if (len) +			isp116x_write_data16(isp116x, (u16) * dp); +	} else { +		/* aligned */ +		for (; len > 1; len -= 2) +			isp116x_raw_write_data16(isp116x, *dp2++); +		if (len) +			isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2)); +	} +	if (quot == 1 || quot == 2) +		isp116x_raw_write_data16(isp116x, 0); +} + +/* Read len bytes from fifo and then read till 32-bit boundary + */ +static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) +{ +	u8 *dp = (u8 *) buf; +	u16 *dp2 = (u16 *) buf; +	u16 w; +	int quot = len % 4; + +	if ((unsigned long)dp2 & 1) { +		/* not aligned */ +		for (; len > 1; len -= 2) { +			w = isp116x_raw_read_data16(isp116x); +			*dp++ = w & 0xff; +			*dp++ = (w >> 8) & 0xff; +		} +		if (len) +			*dp = 0xff & isp116x_read_data16(isp116x); +	} else { +		/* aligned */ +		for (; len > 1; len -= 2) +			*dp2++ = isp116x_raw_read_data16(isp116x); +		if (len) +			*(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x); +	} +	if (quot == 1 || quot == 2) +		isp116x_raw_read_data16(isp116x); +} + +/* Write PTD's and data for scheduled transfers into the fifo ram. + * Fifo must be empty and ready */ +static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev, +		      unsigned long pipe, struct ptd *ptd, int n, void *data, +		      int len) +{ +	int buflen = n * sizeof(struct ptd) + len; +	int i, done; + +	DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); + +	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); +	isp116x_write_reg16(isp116x, HCXFERCTR, buflen); +	isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); + +	done = 0; +	for (i = 0; i < n; i++) { +		DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); + +		dump_ptd(&ptd[i]); +		isp116x_write_data16(isp116x, ptd[i].count); +		isp116x_write_data16(isp116x, ptd[i].mps); +		isp116x_write_data16(isp116x, ptd[i].len); +		isp116x_write_data16(isp116x, ptd[i].faddr); + +		dump_ptd_data(&ptd[i], (__u8 *) data + done, 0); +		write_ptddata_to_fifo(isp116x, +				      (__u8 *) data + done, +				      PTD_GET_LEN(&ptd[i])); + +		done += PTD_GET_LEN(&ptd[i]); +	} +} + +/* Read the processed PTD's and data from fifo ram back to URBs' buffers. + * Fifo must be full and done */ +static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev, +		       unsigned long pipe, struct ptd *ptd, int n, void *data, +		       int len) +{ +	int buflen = n * sizeof(struct ptd) + len; +	int i, done, cc, ret; + +	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); +	isp116x_write_reg16(isp116x, HCXFERCTR, buflen); +	isp116x_write_addr(isp116x, HCATLPORT); + +	ret = TD_CC_NOERROR; +	done = 0; +	for (i = 0; i < n; i++) { +		DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); + +		ptd[i].count = isp116x_read_data16(isp116x); +		ptd[i].mps = isp116x_read_data16(isp116x); +		ptd[i].len = isp116x_read_data16(isp116x); +		ptd[i].faddr = isp116x_read_data16(isp116x); +		dump_ptd(&ptd[i]); + +		read_ptddata_from_fifo(isp116x, +				       (__u8 *) data + done, +				       PTD_GET_LEN(&ptd[i])); +		dump_ptd_data(&ptd[i], (__u8 *) data + done, 1); + +		done += PTD_GET_LEN(&ptd[i]); + +		cc = PTD_GET_CC(&ptd[i]); +		if (cc == TD_DATAUNDERRUN) {	/* underrun is no error... */ +			DBG("allowed data underrun"); +			cc = TD_CC_NOERROR; +		} +		if (cc != TD_CC_NOERROR && ret == TD_CC_NOERROR) +			ret = cc; +	} + +	DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); + +	return ret; +} + +/* Interrupt handling + */ +static int isp116x_interrupt(struct isp116x *isp116x) +{ +	u16 irqstat; +	u32 intstat; +	int ret = 0; + +	isp116x_write_reg16(isp116x, HCuPINTENB, 0); +	irqstat = isp116x_read_reg16(isp116x, HCuPINT); +	isp116x_write_reg16(isp116x, HCuPINT, irqstat); +	DBG(">>>>>> irqstat %x <<<<<<", irqstat); + +	if (irqstat & HCuPINT_ATL) { +		DBG(">>>>>> HCuPINT_ATL <<<<<<"); +		udelay(500); +		ret = 1; +	} + +	if (irqstat & HCuPINT_OPR) { +		intstat = isp116x_read_reg32(isp116x, HCINTSTAT); +		isp116x_write_reg32(isp116x, HCINTSTAT, intstat); +		DBG(">>>>>> HCuPINT_OPR %x <<<<<<", intstat); + +		if (intstat & HCINT_UE) { +			ERR("unrecoverable error, controller disabled"); + +			/* FIXME: be optimistic, hope that bug won't repeat +			 * often. Make some non-interrupt context restart the +			 * controller. Count and limit the retries though; +			 * either hardware or software errors can go forever... +			 */ +			isp116x_reset(isp116x); +			ret = -1; +			return -1; +		} + +		if (intstat & HCINT_RHSC) { +			got_rhsc = 1; +			ret = 1; +			/* When root hub or any of its ports is going +			   to come out of suspend, it may take more +			   than 10ms for status bits to stabilize. */ +			wait_ms(20); +		} + +		if (intstat & HCINT_SO) { +			ERR("schedule overrun"); +			ret = -1; +		} + +		irqstat &= ~HCuPINT_OPR; +	} + +	return ret; +} + +#define PTD_NUM			64	/* it should be enougth... */ +struct ptd ptd[PTD_NUM]; +static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe) +{ +	return min(PTD_NUM * usb_maxpacket(dev, pipe), PTD_NUM * 16); +} + +/* Do an USB transfer + */ +static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe, +			      int dir, void *buffer, int len) +{ +	struct isp116x *isp116x = &isp116x_dev; +	int type = usb_pipetype(pipe); +	int epnum = usb_pipeendpoint(pipe); +	int max = usb_maxpacket(dev, pipe); +	int dir_out = usb_pipeout(pipe); +	int speed_low = usb_pipeslow(pipe); +	int i, done, stat, timeout, cc; +	int retries = 10; + +	DBG("------------------------------------------------"); +	dump_msg(dev, pipe, buffer, len, "SUBMIT"); +	DBG("------------------------------------------------"); + +	if (isp116x->disabled) { +		ERR("EPIPE"); +		dev->status = USB_ST_CRC_ERR; +		return -1; +	} + +	/* device pulled? Shortcut the action. */ +	if (devgone == dev) { +		ERR("ENODEV"); +		dev->status = USB_ST_CRC_ERR; +		return USB_ST_CRC_ERR; +	} + +	if (!max) { +		ERR("pipesize for pipe %lx is zero", pipe); +		dev->status = USB_ST_CRC_ERR; +		return -1; +	} + +	if (type == PIPE_ISOCHRONOUS) { +		ERR("isochronous transfers not supported"); +		dev->status = USB_ST_CRC_ERR; +		return -1; +	} + +	/* FIFO not empty? */ +	if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) { +		ERR("****** FIFO not empty! ******"); +		dev->status = USB_ST_BUF_ERR; +		return -1; +	} + +      retry: +	isp116x_write_reg32(isp116x, HCINTSTAT, 0xff); + +	/* Prepare the PTD data */ +	done = 0; +	i = 0; +	do { +		ptd[i].count = PTD_CC_MSK | PTD_ACTIVE_MSK | +		    PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out)); +		ptd[i].mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum); +		ptd[i].len = PTD_LEN(max > len - done ? len - done : max) | +		    PTD_DIR(dir); +		ptd[i].faddr = PTD_FA(usb_pipedevice(pipe)); + +		usb_dotoggle(dev, epnum, dir_out); +		done += PTD_GET_LEN(&ptd[i]); +		i++; +		if (i >= PTD_NUM) { +			ERR("****** Cannot pack buffer! ******"); +			dev->status = USB_ST_BUF_ERR; +			return -1; +		} +	} while (done < len); +	ptd[i - 1].mps |= PTD_LAST_MSK; + +	/* Pack data into FIFO ram */ +	pack_fifo(isp116x, dev, pipe, ptd, i, buffer, len); +#ifdef EXTRA_DELAY +	wait_ms(EXTRA_DELAY); +#endif + +	/* Start the data transfer */ + +	/* Allow more time for a BULK device to react - some are slow */ +	if (usb_pipetype(pipe) == PIPE_BULK) +		timeout = 5000; +	else +		timeout = 100; + +	/* Wait for it to complete */ +	for (;;) { +		/* Check whether the controller is done */ +		stat = isp116x_interrupt(isp116x); + +		if (stat < 0) { +			dev->status = USB_ST_CRC_ERR; +			break; +		} +		if (stat > 0) +			break; + +		/* Check the timeout */ +		if (--timeout) +			udelay(1); +		else { +			ERR("CTL:TIMEOUT "); +			stat = USB_ST_CRC_ERR; +			break; +		} +	} + +	/* We got an Root Hub Status Change interrupt */ +	if (got_rhsc) { +		isp116x_show_regs(isp116x); + +		got_rhsc = 0; + +		/* Abuse timeout */ +		timeout = rh_check_port_status(isp116x); +		if (timeout >= 0) { +			/* +			 * FIXME! NOTE! AAAARGH! +			 * This is potentially dangerous because it assumes +			 * that only one device is ever plugged in! +			 */ +			devgone = dev; +		} +	} + +	/* Ok, now we can read transfer status */ + +	/* FIFO not ready? */ +	if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) { +		ERR("****** FIFO not ready! ******"); +		dev->status = USB_ST_BUF_ERR; +		return -1; +	} + +	/* Unpack data from FIFO ram */ +	cc = unpack_fifo(isp116x, dev, pipe, ptd, i, buffer, len); + +	/* Mmm... sometime we get 0x0f as cc which is a non sense! +	 * Just retry the transfer... +	 */ +	if (cc == 0x0f && retries-- > 0) { +		usb_dotoggle(dev, epnum, dir_out); +		goto retry; +	} + +	if (cc != TD_CC_NOERROR) { +		DBG("****** completition code error %x ******", cc); +		switch (cc) { +		case TD_CC_BITSTUFFING: +			dev->status = USB_ST_BIT_ERR; +			break; +		case TD_CC_STALL: +			dev->status = USB_ST_STALLED; +			break; +		case TD_BUFFEROVERRUN: +		case TD_BUFFERUNDERRUN: +			dev->status = USB_ST_BUF_ERR; +			break; +		default: +			dev->status = USB_ST_CRC_ERR; +		} +		return -cc; +	} + +	dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)"); + +	dev->status = 0; +	return done; +} + +/* Adapted from au1x00_usb_ohci.c + */ +static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe, +				 void *buffer, int transfer_len, +				 struct devrequest *cmd) +{ +	struct isp116x *isp116x = &isp116x_dev; +	u32 tmp = 0; + +	int leni = transfer_len; +	int len = 0; +	int stat = 0; +	u32 datab[4]; +	u8 *data_buf = (u8 *) datab; +	u16 bmRType_bReq; +	u16 wValue; +	u16 wIndex; +	u16 wLength; + +	if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { +		INFO("Root-Hub submit IRQ: NOT implemented"); +		return 0; +	} + +	bmRType_bReq = cmd->requesttype | (cmd->request << 8); +	wValue = swap_16(cmd->value); +	wIndex = swap_16(cmd->index); +	wLength = swap_16(cmd->length); + +	DBG("--- HUB ----------------------------------------"); +	DBG("submit rh urb, req=%x val=%#x index=%#x len=%d", +	    bmRType_bReq, wValue, wIndex, wLength); +	dump_msg(dev, pipe, buffer, transfer_len, "RH"); +	DBG("------------------------------------------------"); + +	switch (bmRType_bReq) { +	case RH_GET_STATUS: +		DBG("RH_GET_STATUS"); + +		*(__u16 *) data_buf = swap_16(1); +		len = 2; +		break; + +	case RH_GET_STATUS | RH_INTERFACE: +		DBG("RH_GET_STATUS | RH_INTERFACE"); + +		*(__u16 *) data_buf = swap_16(0); +		len = 2; +		break; + +	case RH_GET_STATUS | RH_ENDPOINT: +		DBG("RH_GET_STATUS | RH_ENDPOINT"); + +		*(__u16 *) data_buf = swap_16(0); +		len = 2; +		break; + +	case RH_GET_STATUS | RH_CLASS: +		DBG("RH_GET_STATUS | RH_CLASS"); + +		tmp = isp116x_read_reg32(isp116x, HCRHSTATUS); + +		*(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE)); +		len = 4; +		break; + +	case RH_GET_STATUS | RH_OTHER | RH_CLASS: +		DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS"); + +		tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1); +		*(__u32 *) data_buf = swap_32(tmp); +		isp116x_show_regs(isp116x); +		len = 4; +		break; + +	case RH_CLEAR_FEATURE | RH_ENDPOINT: +		DBG("RH_CLEAR_FEATURE | RH_ENDPOINT"); + +		switch (wValue) { +		case RH_ENDPOINT_STALL: +			DBG("C_HUB_ENDPOINT_STALL"); +			len = 0; +			break; +		} +		break; + +	case RH_CLEAR_FEATURE | RH_CLASS: +		DBG("RH_CLEAR_FEATURE | RH_CLASS"); + +		switch (wValue) { +		case RH_C_HUB_LOCAL_POWER: +			DBG("C_HUB_LOCAL_POWER"); +			len = 0; +			break; + +		case RH_C_HUB_OVER_CURRENT: +			DBG("C_HUB_OVER_CURRENT"); +			isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); +			len = 0; +			break; +		} +		break; + +	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: +		DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS"); + +		switch (wValue) { +		case RH_PORT_ENABLE: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_CCS); +			len = 0; +			break; + +		case RH_PORT_SUSPEND: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_POCI); +			len = 0; +			break; + +		case RH_PORT_POWER: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_LSDA); +			len = 0; +			break; + +		case RH_C_PORT_CONNECTION: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_CSC); +			len = 0; +			break; + +		case RH_C_PORT_ENABLE: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_PESC); +			len = 0; +			break; + +		case RH_C_PORT_SUSPEND: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_PSSC); +			len = 0; +			break; + +		case RH_C_PORT_OVER_CURRENT: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_POCI); +			len = 0; +			break; + +		case RH_C_PORT_RESET: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_PRSC); +			len = 0; +			break; + +		default: +			ERR("invalid wValue"); +			stat = USB_ST_STALLED; +		} + +		isp116x_show_regs(isp116x); + +		break; + +	case RH_SET_FEATURE | RH_OTHER | RH_CLASS: +		DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS"); + +		switch (wValue) { +		case RH_PORT_SUSPEND: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_PSS); +			len = 0; +			break; + +		case RH_PORT_RESET: +			/* Spin until any current reset finishes */ +			while (1) { +				tmp = +				    isp116x_read_reg32(isp116x, +						       HCRHPORT1 + wIndex - 1); +				if (!(tmp & RH_PS_PRS)) +					break; +				wait_ms(1); +			} +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_PRS); +			wait_ms(10); + +			len = 0; +			break; + +		case RH_PORT_POWER: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_PPS); +			len = 0; +			break; + +		case RH_PORT_ENABLE: +			isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, +					    RH_PS_PES); +			len = 0; +			break; + +		default: +			ERR("invalid wValue"); +			stat = USB_ST_STALLED; +		} + +		isp116x_show_regs(isp116x); + +		break; + +	case RH_SET_ADDRESS: +		DBG("RH_SET_ADDRESS"); + +		rh_devnum = wValue; +		len = 0; +		break; + +	case RH_GET_DESCRIPTOR: +		DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength); + +		switch (wValue) { +		case (USB_DT_DEVICE << 8):	/* device descriptor */ +			len = min_t(unsigned int, +				    leni, min_t(unsigned int, +						sizeof(root_hub_dev_des), +						wLength)); +			data_buf = root_hub_dev_des; +			break; + +		case (USB_DT_CONFIG << 8):	/* configuration descriptor */ +			len = min_t(unsigned int, +				    leni, min_t(unsigned int, +						sizeof(root_hub_config_des), +						wLength)); +			data_buf = root_hub_config_des; +			break; + +		case ((USB_DT_STRING << 8) | 0x00):	/* string 0 descriptors */ +			len = min_t(unsigned int, +				    leni, min_t(unsigned int, +						sizeof(root_hub_str_index0), +						wLength)); +			data_buf = root_hub_str_index0; +			break; + +		case ((USB_DT_STRING << 8) | 0x01):	/* string 1 descriptors */ +			len = min_t(unsigned int, +				    leni, min_t(unsigned int, +						sizeof(root_hub_str_index1), +						wLength)); +			data_buf = root_hub_str_index1; +			break; + +		default: +			ERR("invalid wValue"); +			stat = USB_ST_STALLED; +		} + +		break; + +	case RH_GET_DESCRIPTOR | RH_CLASS: +		DBG("RH_GET_DESCRIPTOR | RH_CLASS"); + +		tmp = isp116x_read_reg32(isp116x, HCRHDESCA); + +		data_buf[0] = 0x09;	/* min length; */ +		data_buf[1] = 0x29; +		data_buf[2] = tmp & RH_A_NDP; +		data_buf[3] = 0; +		if (tmp & RH_A_PSM)	/* per-port power switching? */ +			data_buf[3] |= 0x01; +		if (tmp & RH_A_NOCP)	/* no overcurrent reporting? */ +			data_buf[3] |= 0x10; +		else if (tmp & RH_A_OCPM)	/* per-port overcurrent rep? */ +			data_buf[3] |= 0x08; + +		/* Corresponds to data_buf[4-7] */ +		datab[1] = 0; +		data_buf[5] = (tmp & RH_A_POTPGT) >> 24; + +		tmp = isp116x_read_reg32(isp116x, HCRHDESCB); + +		data_buf[7] = tmp & RH_B_DR; +		if (data_buf[2] < 7) +			data_buf[8] = 0xff; +		else { +			data_buf[0] += 2; +			data_buf[8] = (tmp & RH_B_DR) >> 8; +			data_buf[10] = data_buf[9] = 0xff; +		} + +		len = min_t(unsigned int, leni, +			    min_t(unsigned int, data_buf[0], wLength)); +		break; + +	case RH_GET_CONFIGURATION: +		DBG("RH_GET_CONFIGURATION"); + +		*(__u8 *) data_buf = 0x01; +		len = 1; +		break; + +	case RH_SET_CONFIGURATION: +		DBG("RH_SET_CONFIGURATION"); + +		isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC); +		len = 0; +		break; + +	default: +		ERR("*** *** *** unsupported root hub command *** *** ***"); +		stat = USB_ST_STALLED; +	} + +	len = min_t(int, len, leni); +	if (buffer != data_buf) +		memcpy(buffer, data_buf, len); + +	dev->act_len = len; +	dev->status = stat; +	DBG("dev act_len %d, status %d", dev->act_len, dev->status); + +	dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)"); + +	return stat; +} + +/* --- Transfer functions -------------------------------------------------- */ + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +		   int len, int interval) +{ +	DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d", +	    dev, pipe, buffer, len, interval); + +	return -1; +} + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +		       int len, struct devrequest *setup) +{ +	int devnum = usb_pipedevice(pipe); +	int epnum = usb_pipeendpoint(pipe); +	int max = max_transfer_len(dev, pipe); +	int dir_in = usb_pipein(pipe); +	int done, ret; + +	/* Control message is for the HUB? */ +	if (devnum == rh_devnum) +		return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup); + +	/* Ok, no HUB message so send the message to the device */ + +	/* Setup phase */ +	DBG("--- SETUP PHASE --------------------------------"); +	usb_settoggle(dev, epnum, 1, 0); +	ret = isp116x_submit_job(dev, pipe, +				 PTD_DIR_SETUP, +				 setup, sizeof(struct devrequest)); +	if (ret < 0) { +		DBG("control setup phase error (ret = %d", ret); +		return -1; +	} + +	/* Data phase */ +	DBG("--- DATA PHASE ---------------------------------"); +	done = 0; +	usb_settoggle(dev, epnum, !dir_in, 1); +	while (done < len) { +		ret = isp116x_submit_job(dev, pipe, +					 dir_in ? PTD_DIR_IN : PTD_DIR_OUT, +					 (__u8 *) buffer + done, +					 max > len - done ? len - done : max); +		if (ret < 0) { +			DBG("control data phase error (ret = %d)", ret); +			return -1; +		} +		done += ret; + +		if (dir_in && ret < max)	/* short packet */ +			break; +	} + +	/* Status phase */ +	DBG("--- STATUS PHASE -------------------------------"); +	usb_settoggle(dev, epnum, !dir_in, 1); +	ret = isp116x_submit_job(dev, pipe, +				 !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0); +	if (ret < 0) { +		DBG("control status phase error (ret = %d", ret); +		return -1; +	} + +	dev->act_len = done; + +	dump_msg(dev, pipe, buffer, len, "DEV(ret)"); + +	return done; +} + +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +		    int len) +{ +	int dir_out = usb_pipeout(pipe); +	int max = max_transfer_len(dev, pipe); +	int done, ret; + +	DBG("--- BULK ---------------------------------------"); +	DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d", +	    usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out); + +	done = 0; +	while (done < len) { +		ret = isp116x_submit_job(dev, pipe, +					 !dir_out ? PTD_DIR_IN : PTD_DIR_OUT, +					 (__u8 *) buffer + done, +					 max > len - done ? len - done : max); +		if (ret < 0) { +			DBG("error on bulk message (ret = %d)", ret); +			return -1; +		} + +		done += ret; + +		if (!dir_out && ret < max)	/* short packet */ +			break; +	} + +	dev->act_len = done; + +	return 0; +} + +/* --- Basic functions ----------------------------------------------------- */ + +static int isp116x_sw_reset(struct isp116x *isp116x) +{ +	int retries = 15; +	int ret = 0; + +	DBG(""); + +	isp116x->disabled = 1; + +	isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC); +	isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR); +	while (--retries) { +		/* It usually resets within 1 ms */ +		wait_ms(1); +		if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR)) +			break; +	} +	if (!retries) { +		ERR("software reset timeout"); +		ret = -1; +	} +	return ret; +} + +static int isp116x_reset(struct isp116x *isp116x) +{ +	unsigned long t; +	u16 clkrdy = 0; +	int ret, timeout = 15 /* ms */ ; + +	DBG(""); + +	ret = isp116x_sw_reset(isp116x); +	if (ret) +		return ret; + +	for (t = 0; t < timeout; t++) { +		clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY; +		if (clkrdy) +			break; +		wait_ms(1); +	} +	if (!clkrdy) { +		ERR("clock not ready after %dms", timeout); +		/* After sw_reset the clock won't report to be ready, if +		   H_WAKEUP pin is high. */ +		ERR("please make sure that the H_WAKEUP pin is pulled low!"); +		ret = -1; +	} +	return ret; +} + +static void isp116x_stop(struct isp116x *isp116x) +{ +	u32 val; + +	DBG(""); + +	isp116x_write_reg16(isp116x, HCuPINTENB, 0); + +	/* Switch off ports' power, some devices don't come up +	   after next 'start' without this */ +	val = isp116x_read_reg32(isp116x, HCRHDESCA); +	val &= ~(RH_A_NPS | RH_A_PSM); +	isp116x_write_reg32(isp116x, HCRHDESCA, val); +	isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); + +	isp116x_sw_reset(isp116x); +} + +/* + *  Configure the chip. The chip must be successfully reset by now. + */ +static int isp116x_start(struct isp116x *isp116x) +{ +	struct isp116x_platform_data *board = isp116x->board; +	u32 val; + +	DBG(""); + +	/* Clear interrupt status and disable all interrupt sources */ +	isp116x_write_reg16(isp116x, HCuPINT, 0xff); +	isp116x_write_reg16(isp116x, HCuPINTENB, 0); + +	isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); +	isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); + +	/* Hardware configuration */ +	val = HCHWCFG_DBWIDTH(1); +	if (board->sel15Kres) +		val |= HCHWCFG_15KRSEL; +	/* Remote wakeup won't work without working clock */ +	if (board->remote_wakeup_enable) +		val |= HCHWCFG_CLKNOTSTOP; +	if (board->oc_enable) +		val |= HCHWCFG_ANALOG_OC; +	isp116x_write_reg16(isp116x, HCHWCFG, val); + +	/* --- Root hub configuration */ +	val = (25 << 24) & RH_A_POTPGT; +	/* AN10003_1.pdf recommends RH_A_NPS (no power switching) to +	   be always set. Yet, instead, we request individual port +	   power switching. */ +	val |= RH_A_PSM; +	/* Report overcurrent per port */ +	val |= RH_A_OCPM; +	isp116x_write_reg32(isp116x, HCRHDESCA, val); +	isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); + +	val = RH_B_PPCM; +	isp116x_write_reg32(isp116x, HCRHDESCB, val); +	isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB); + +	val = 0; +	if (board->remote_wakeup_enable) +		val |= RH_HS_DRWE; +	isp116x_write_reg32(isp116x, HCRHSTATUS, val); +	isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); + +	isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf); + +	/* Go operational */ +	val = HCCONTROL_USB_OPER; +	if (board->remote_wakeup_enable) +		val |= HCCONTROL_RWE; +	isp116x_write_reg32(isp116x, HCCONTROL, val); + +	/* Disable ports to avoid race in device enumeration */ +	isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); +	isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); + +	isp116x_show_regs(isp116x); + +	isp116x->disabled = 0; + +	return 0; +} + +/* --- Init functions ------------------------------------------------------ */ + +int isp116x_check_id(struct isp116x *isp116x) +{ +	int val; + +	val = isp116x_read_reg16(isp116x, HCCHIPID); +	if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) { +		ERR("invalid chip ID %04x", val); +		return -1; +	} + +	return 0; +} + +int usb_lowlevel_init(void) +{ +	struct isp116x *isp116x = &isp116x_dev; + +	DBG(""); + +	/* Init device registers addr */ +	isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR; +	isp116x->data_reg = (u16 *) ISP116X_HCD_DATA; + +	/* Setup specific board settings */ +#ifdef ISP116X_HCD_SEL15kRES +	isp116x_board.sel15Kres = 1; +#endif +#ifdef ISP116X_HCD_OC_ENABLE +	isp116x_board.oc_enable = 1; +#endif +#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE +	isp116x_board.remote_wakeup_enable = 1; +#endif +	isp116x->board = &isp116x_board; + +	/* Try to get ISP116x silicon chip ID */ +	if (isp116x_check_id(isp116x) < 0) +		return -1; + +	isp116x->disabled = 1; +	isp116x->sleeping = 0; + +	isp116x_reset(isp116x); +	isp116x_start(isp116x); + +	return 0; +} + +int usb_lowlevel_stop(void) +{ +	struct isp116x *isp116x = &isp116x_dev; + +	DBG(""); + +	if (!isp116x->disabled) +		isp116x_stop(isp116x); + +	return 0; +} + +#endif				/* CONFIG_USB_ISP116X_HCD */ diff --git a/drivers/isp116x.h b/drivers/isp116x.h new file mode 100644 index 000000000..a3ce3b582 --- /dev/null +++ b/drivers/isp116x.h @@ -0,0 +1,489 @@ +/* + * ISP116x register declarations and HCD data structures + * + * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it> + * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it> + * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> + * Portions: + * Copyright (C) 2004 Lothar Wassmann + * Copyright (C) 2004 Psion Teklogix + * Copyright (C) 2004 David Brownell + * + * 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 + */ + +#ifdef DEBUG +#define DBG(fmt, args...)	\ +		printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) +#else +#define DBG(fmt, args...)	do {} while (0) +#endif + +#ifdef VERBOSE +#    define VDBG		DBG +#else +#    define VDBG(fmt, args...)	do {} while (0) +#endif + +#define ERR(fmt, args...)	\ +		printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) +#define WARN(fmt, args...)	\ +		printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) +#define INFO(fmt, args...)	\ +		printf("isp116x: " fmt "\n" , ## args) + +/* ------------------------------------------------------------------------- */ + +/* us of 1ms frame */ +#define  MAX_LOAD_LIMIT		850 + +/* Full speed: max # of bytes to transfer for a single urb +   at a time must be < 1024 && must be multiple of 64. +   832 allows transfering 4kiB within 5 frames. */ +#define MAX_TRANSFER_SIZE_FULLSPEED	832 + +/* Low speed: there is no reason to schedule in very big +   chunks; often the requested long transfers are for +   string descriptors containing short strings. */ +#define MAX_TRANSFER_SIZE_LOWSPEED	64 + +/* Bytetime (us), a rough indication of how much time it +   would take to transfer a byte of useful data over USB */ +#define BYTE_TIME_FULLSPEED	1 +#define BYTE_TIME_LOWSPEED	20 + +/* Buffer sizes */ +#define ISP116x_BUF_SIZE	4096 +#define ISP116x_ITL_BUFSIZE	0 +#define ISP116x_ATL_BUFSIZE	((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE)) + +#define ISP116x_WRITE_OFFSET	0x80 + +/* --- ISP116x registers/bits ---------------------------------------------- */ + +#define	HCREVISION	0x00 +#define	HCCONTROL	0x01 +#define		HCCONTROL_HCFS	(3 << 6)	/* host controller +						   functional state */ +#define		HCCONTROL_USB_RESET	(0 << 6) +#define		HCCONTROL_USB_RESUME	(1 << 6) +#define		HCCONTROL_USB_OPER	(2 << 6) +#define		HCCONTROL_USB_SUSPEND	(3 << 6) +#define		HCCONTROL_RWC	(1 << 9)	/* remote wakeup connected */ +#define		HCCONTROL_RWE	(1 << 10)	/* remote wakeup enable */ +#define	HCCMDSTAT	0x02 +#define		HCCMDSTAT_HCR	(1 << 0)	/* host controller reset */ +#define		HCCMDSTAT_SOC	(3 << 16)	/* scheduling overrun count */ +#define	HCINTSTAT	0x03 +#define		HCINT_SO	(1 << 0)	/* scheduling overrun */ +#define		HCINT_WDH	(1 << 1)	/* writeback of done_head */ +#define		HCINT_SF	(1 << 2)	/* start frame */ +#define		HCINT_RD	(1 << 3)	/* resume detect */ +#define		HCINT_UE	(1 << 4)	/* unrecoverable error */ +#define		HCINT_FNO	(1 << 5)	/* frame number overflow */ +#define		HCINT_RHSC	(1 << 6)	/* root hub status change */ +#define		HCINT_OC	(1 << 30)	/* ownership change */ +#define		HCINT_MIE	(1 << 31)	/* master interrupt enable */ +#define	HCINTENB	0x04 +#define	HCINTDIS	0x05 +#define	HCFMINTVL	0x0d +#define	HCFMREM		0x0e +#define	HCFMNUM		0x0f +#define	HCLSTHRESH	0x11 +#define	HCRHDESCA	0x12 +#define		RH_A_NDP	(0x3 << 0)	/* # downstream ports */ +#define		RH_A_PSM	(1 << 8)	/* power switching mode */ +#define		RH_A_NPS	(1 << 9)	/* no power switching */ +#define		RH_A_DT		(1 << 10)	/* device type (mbz) */ +#define		RH_A_OCPM	(1 << 11)	/* overcurrent protection +						   mode */ +#define		RH_A_NOCP	(1 << 12)	/* no overcurrent protection */ +#define		RH_A_POTPGT	(0xff << 24)	/* power on -> power good +						   time */ +#define	HCRHDESCB	0x13 +#define		RH_B_DR		(0xffff << 0)	/* device removable flags */ +#define		RH_B_PPCM	(0xffff << 16)	/* port power control mask */ +#define	HCRHSTATUS	0x14 +#define		RH_HS_LPS	(1 << 0)	/* local power status */ +#define		RH_HS_OCI	(1 << 1)	/* over current indicator */ +#define		RH_HS_DRWE	(1 << 15)	/* device remote wakeup +						   enable */ +#define		RH_HS_LPSC	(1 << 16)	/* local power status change */ +#define		RH_HS_OCIC	(1 << 17)	/* over current indicator +						   change */ +#define		RH_HS_CRWE	(1 << 31)	/* clear remote wakeup +						   enable */ +#define	HCRHPORT1	0x15 +#define		RH_PS_CCS	(1 << 0)	/* current connect status */ +#define		RH_PS_PES	(1 << 1)	/* port enable status */ +#define		RH_PS_PSS	(1 << 2)	/* port suspend status */ +#define		RH_PS_POCI	(1 << 3)	/* port over current +						   indicator */ +#define		RH_PS_PRS	(1 << 4)	/* port reset status */ +#define		RH_PS_PPS	(1 << 8)	/* port power status */ +#define		RH_PS_LSDA	(1 << 9)	/* low speed device attached */ +#define		RH_PS_CSC	(1 << 16)	/* connect status change */ +#define		RH_PS_PESC	(1 << 17)	/* port enable status change */ +#define		RH_PS_PSSC	(1 << 18)	/* port suspend status +						   change */ +#define		RH_PS_OCIC	(1 << 19)	/* over current indicator +						   change */ +#define		RH_PS_PRSC	(1 << 20)	/* port reset status change */ +#define		HCRHPORT_CLRMASK	(0x1f << 16) +#define	HCRHPORT2	0x16 +#define	HCHWCFG		0x20 +#define		HCHWCFG_15KRSEL		(1 << 12) +#define		HCHWCFG_CLKNOTSTOP	(1 << 11) +#define		HCHWCFG_ANALOG_OC	(1 << 10) +#define		HCHWCFG_DACK_MODE	(1 << 8) +#define		HCHWCFG_EOT_POL		(1 << 7) +#define		HCHWCFG_DACK_POL	(1 << 6) +#define		HCHWCFG_DREQ_POL	(1 << 5) +#define		HCHWCFG_DBWIDTH_MASK	(0x03 << 3) +#define		HCHWCFG_DBWIDTH(n)	(((n) << 3) & HCHWCFG_DBWIDTH_MASK) +#define		HCHWCFG_INT_POL		(1 << 2) +#define		HCHWCFG_INT_TRIGGER	(1 << 1) +#define		HCHWCFG_INT_ENABLE	(1 << 0) +#define	HCDMACFG	0x21 +#define		HCDMACFG_BURST_LEN_MASK	(0x03 << 5) +#define		HCDMACFG_BURST_LEN(n)	(((n) << 5) & HCDMACFG_BURST_LEN_MASK) +#define		HCDMACFG_BURST_LEN_1	HCDMACFG_BURST_LEN(0) +#define		HCDMACFG_BURST_LEN_4	HCDMACFG_BURST_LEN(1) +#define		HCDMACFG_BURST_LEN_8	HCDMACFG_BURST_LEN(2) +#define		HCDMACFG_DMA_ENABLE	(1 << 4) +#define		HCDMACFG_BUF_TYPE_MASK	(0x07 << 1) +#define		HCDMACFG_CTR_SEL	(1 << 2) +#define		HCDMACFG_ITLATL_SEL	(1 << 1) +#define		HCDMACFG_DMA_RW_SELECT	(1 << 0) +#define	HCXFERCTR	0x22 +#define	HCuPINT		0x24 +#define		HCuPINT_SOF		(1 << 0) +#define		HCuPINT_ATL		(1 << 1) +#define		HCuPINT_AIIEOT		(1 << 2) +#define		HCuPINT_OPR		(1 << 4) +#define		HCuPINT_SUSP		(1 << 5) +#define		HCuPINT_CLKRDY		(1 << 6) +#define	HCuPINTENB	0x25 +#define	HCCHIPID	0x27 +#define		HCCHIPID_MASK		0xff00 +#define		HCCHIPID_MAGIC		0x6100 +#define	HCSCRATCH	0x28 +#define	HCSWRES		0x29 +#define		HCSWRES_MAGIC		0x00f6 +#define	HCITLBUFLEN	0x2a +#define	HCATLBUFLEN	0x2b +#define	HCBUFSTAT	0x2c +#define		HCBUFSTAT_ITL0_FULL	(1 << 0) +#define		HCBUFSTAT_ITL1_FULL	(1 << 1) +#define		HCBUFSTAT_ATL_FULL	(1 << 2) +#define		HCBUFSTAT_ITL0_DONE	(1 << 3) +#define		HCBUFSTAT_ITL1_DONE	(1 << 4) +#define		HCBUFSTAT_ATL_DONE	(1 << 5) +#define	HCRDITL0LEN	0x2d +#define	HCRDITL1LEN	0x2e +#define	HCITLPORT	0x40 +#define	HCATLPORT	0x41 + +/* PTD accessor macros. */ +#define PTD_GET_COUNT(p)	(((p)->count & PTD_COUNT_MSK) >> 0) +#define PTD_COUNT(v)		(((v) << 0) & PTD_COUNT_MSK) +#define PTD_GET_TOGGLE(p)	(((p)->count & PTD_TOGGLE_MSK) >> 10) +#define PTD_TOGGLE(v)		(((v) << 10) & PTD_TOGGLE_MSK) +#define PTD_GET_ACTIVE(p)	(((p)->count & PTD_ACTIVE_MSK) >> 11) +#define PTD_ACTIVE(v)		(((v) << 11) & PTD_ACTIVE_MSK) +#define PTD_GET_CC(p)		(((p)->count & PTD_CC_MSK) >> 12) +#define PTD_CC(v)		(((v) << 12) & PTD_CC_MSK) +#define PTD_GET_MPS(p)		(((p)->mps & PTD_MPS_MSK) >> 0) +#define PTD_MPS(v)		(((v) << 0) & PTD_MPS_MSK) +#define PTD_GET_SPD(p)		(((p)->mps & PTD_SPD_MSK) >> 10) +#define PTD_SPD(v)		(((v) << 10) & PTD_SPD_MSK) +#define PTD_GET_LAST(p)		(((p)->mps & PTD_LAST_MSK) >> 11) +#define PTD_LAST(v)		(((v) << 11) & PTD_LAST_MSK) +#define PTD_GET_EP(p)		(((p)->mps & PTD_EP_MSK) >> 12) +#define PTD_EP(v)		(((v) << 12) & PTD_EP_MSK) +#define PTD_GET_LEN(p)		(((p)->len & PTD_LEN_MSK) >> 0) +#define PTD_LEN(v)		(((v) << 0) & PTD_LEN_MSK) +#define PTD_GET_DIR(p)		(((p)->len & PTD_DIR_MSK) >> 10) +#define PTD_DIR(v)		(((v) << 10) & PTD_DIR_MSK) +#define PTD_GET_B5_5(p)		(((p)->len & PTD_B5_5_MSK) >> 13) +#define PTD_B5_5(v)		(((v) << 13) & PTD_B5_5_MSK) +#define PTD_GET_FA(p)		(((p)->faddr & PTD_FA_MSK) >> 0) +#define PTD_FA(v)		(((v) << 0) & PTD_FA_MSK) +#define PTD_GET_FMT(p)		(((p)->faddr & PTD_FMT_MSK) >> 7) +#define PTD_FMT(v)		(((v) << 7) & PTD_FMT_MSK) + +/*  Hardware transfer status codes -- CC from ptd->count */ +#define TD_CC_NOERROR      0x00 +#define TD_CC_CRC          0x01 +#define TD_CC_BITSTUFFING  0x02 +#define TD_CC_DATATOGGLEM  0x03 +#define TD_CC_STALL        0x04 +#define TD_DEVNOTRESP      0x05 +#define TD_PIDCHECKFAIL    0x06 +#define TD_UNEXPECTEDPID   0x07 +#define TD_DATAOVERRUN     0x08 +#define TD_DATAUNDERRUN    0x09 +    /* 0x0A, 0x0B reserved for hardware */ +#define TD_BUFFEROVERRUN   0x0C +#define TD_BUFFERUNDERRUN  0x0D +    /* 0x0E, 0x0F reserved for HCD */ +#define TD_NOTACCESSED     0x0F + +/* ------------------------------------------------------------------------- */ + +#define	LOG2_PERIODIC_SIZE	5	/* arbitrary; this matches OHCI */ +#define	PERIODIC_SIZE		(1 << LOG2_PERIODIC_SIZE) + +/* Philips transfer descriptor */ +struct ptd { +	u16 count; +#define	PTD_COUNT_MSK	(0x3ff << 0) +#define	PTD_TOGGLE_MSK	(1 << 10) +#define	PTD_ACTIVE_MSK	(1 << 11) +#define	PTD_CC_MSK	(0xf << 12) +	u16 mps; +#define	PTD_MPS_MSK	(0x3ff << 0) +#define	PTD_SPD_MSK	(1 << 10) +#define	PTD_LAST_MSK	(1 << 11) +#define	PTD_EP_MSK	(0xf << 12) +	u16 len; +#define	PTD_LEN_MSK	(0x3ff << 0) +#define	PTD_DIR_MSK	(3 << 10) +#define	PTD_DIR_SETUP	(0) +#define	PTD_DIR_OUT	(1) +#define	PTD_DIR_IN	(2) +#define	PTD_B5_5_MSK	(1 << 13) +	u16 faddr; +#define	PTD_FA_MSK	(0x7f << 0) +#define	PTD_FMT_MSK	(1 << 7) +} __attribute__ ((packed, aligned(2))); + +struct isp116x_ep { +	struct usb_device *udev; +	struct ptd ptd; + +	u8 maxpacket; +	u8 epnum; +	u8 nextpid; + +	u16 length;		/* of current packet */ +	unsigned char *data;	/* to databuf */ + +	u16 error_count; +}; + +/* URB struct */ +#define N_URB_TD		48 +#define URB_DEL			1 +typedef struct { +	struct isp116x_ep *ed; +	void *transfer_buffer;	/* (in) associated data buffer */ +	int actual_length;	/* (return) actual transfer length */ +	unsigned long pipe;	/* (in) pipe information */ +#if 0 +	int state; +#endif +} urb_priv_t; + +struct isp116x_platform_data { +	/* Enable internal resistors on downstream ports */ +	unsigned sel15Kres:1; +	/* On-chip overcurrent detection */ +	unsigned oc_enable:1; +	/* Enable wakeup by devices on usb bus (e.g. wakeup +	   by attachment/detachment or by device activity +	   such as moving a mouse). When chosen, this option +	   prevents stopping internal clock, increasing +	   thereby power consumption in suspended state. */ +	unsigned remote_wakeup_enable:1; +}; + +struct isp116x { +	u16 *addr_reg; +	u16 *data_reg; + +	struct isp116x_platform_data *board; + +	struct dentry *dentry; +	unsigned long stat1, stat2, stat4, stat8, stat16; + +	/* Status flags */ +	unsigned disabled:1; +	unsigned sleeping:1; + +	/* Root hub registers */ +	u32 rhdesca; +	u32 rhdescb; +	u32 rhstatus; +	u32 rhport[2]; + +	/* Schedule for the current frame */ +	struct isp116x_ep *atl_active; +	int atl_buflen; +	int atl_bufshrt; +	int atl_last_dir; +	int atl_finishing; +}; + +/* ------------------------------------------------- */ + +/* Inter-io delay (ns). The chip is picky about access timings; it + * expects at least: + * 150ns delay between consecutive accesses to DATA_REG, + * 300ns delay between access to ADDR_REG and DATA_REG + * OE, WE MUST NOT be changed during these intervals + */ +#if defined(UDELAY) +#define	isp116x_delay(h,d)	udelay(d) +#else +#define	isp116x_delay(h,d)	do {} while (0) +#endif + +static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg) +{ +	writew(reg & 0xff, isp116x->addr_reg); +	isp116x_delay(isp116x, UDELAY); +} + +static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val) +{ +	writew(val, isp116x->data_reg); +	isp116x_delay(isp116x, UDELAY); +} + +static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val) +{ +	__raw_writew(val, isp116x->data_reg); +	isp116x_delay(isp116x, UDELAY); +} + +static inline u16 isp116x_read_data16(struct isp116x *isp116x) +{ +	u16 val; + +	val = readw(isp116x->data_reg); +	isp116x_delay(isp116x, UDELAY); +	return val; +} + +static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x) +{ +	u16 val; + +	val = __raw_readw(isp116x->data_reg); +	isp116x_delay(isp116x, UDELAY); +	return val; +} + +static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val) +{ +	writew(val & 0xffff, isp116x->data_reg); +	isp116x_delay(isp116x, UDELAY); +	writew(val >> 16, isp116x->data_reg); +	isp116x_delay(isp116x, UDELAY); +} + +static inline u32 isp116x_read_data32(struct isp116x *isp116x) +{ +	u32 val; + +	val = (u32) readw(isp116x->data_reg); +	isp116x_delay(isp116x, UDELAY); +	val |= ((u32) readw(isp116x->data_reg)) << 16; +	isp116x_delay(isp116x, UDELAY); +	return val; +} + +/* Let's keep register access functions out of line. Hint: +   we wait at least 150 ns at every access. +*/ +static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg) +{ +	isp116x_write_addr(isp116x, reg); +	return isp116x_read_data16(isp116x); +} + +static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg) +{ +	isp116x_write_addr(isp116x, reg); +	return isp116x_read_data32(isp116x); +} + +static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg, +				unsigned val) +{ +	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); +	isp116x_write_data16(isp116x, (u16) (val & 0xffff)); +} + +static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, +				unsigned val) +{ +	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); +	isp116x_write_data32(isp116x, (u32) val); +} + +/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */ + +/* destination of request */ +#define RH_INTERFACE               0x01 +#define RH_ENDPOINT                0x02 +#define RH_OTHER                   0x03 + +#define RH_CLASS                   0x20 +#define RH_VENDOR                  0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS           0x0080 +#define RH_CLEAR_FEATURE        0x0100 +#define RH_SET_FEATURE          0x0300 +#define RH_SET_ADDRESS          0x0500 +#define RH_GET_DESCRIPTOR       0x0680 +#define RH_SET_DESCRIPTOR       0x0700 +#define RH_GET_CONFIGURATION    0x0880 +#define RH_SET_CONFIGURATION    0x0900 +#define RH_GET_STATE            0x0280 +#define RH_GET_INTERFACE        0x0A80 +#define RH_SET_INTERFACE        0x0B00 +#define RH_SYNC_FRAME           0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP               0x2000 + +/* Hub port features */ +#define RH_PORT_CONNECTION         0x00 +#define RH_PORT_ENABLE             0x01 +#define RH_PORT_SUSPEND            0x02 +#define RH_PORT_OVER_CURRENT       0x03 +#define RH_PORT_RESET              0x04 +#define RH_PORT_POWER              0x08 +#define RH_PORT_LOW_SPEED          0x09 + +#define RH_C_PORT_CONNECTION       0x10 +#define RH_C_PORT_ENABLE           0x11 +#define RH_C_PORT_SUSPEND          0x12 +#define RH_C_PORT_OVER_CURRENT     0x13 +#define RH_C_PORT_RESET            0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER       0x00 +#define RH_C_HUB_OVER_CURRENT      0x01 + +#define RH_DEVICE_REMOTE_WAKEUP    0x00 +#define RH_ENDPOINT_STALL          0x01 + +#define RH_ACK                     0x01 +#define RH_REQ_ERR                 -1 +#define RH_NACK                    0x00 diff --git a/drivers/nand/nand_util.c b/drivers/nand/nand_util.c index 88c1df6c2..aee872703 100644 --- a/drivers/nand/nand_util.c +++ b/drivers/nand/nand_util.c @@ -37,6 +37,7 @@  #include <command.h>  #include <watchdog.h>  #include <malloc.h> +#include <div64.h>  #include <nand.h>  #include <jffs2/jffs2.h> @@ -208,10 +209,10 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)  		}  		if (!opts->quiet) { -			int percent = (int) -				((unsigned long long) +                        unsigned long long n =(unsigned long long)  				 (erase.addr+meminfo->erasesize-opts->offset) -				 * 100 / erase_length); +				 * 100; +			int percent = (int)do_div(n, erase_length);  			/* output progress message only at whole percent  			 * steps to reduce the number of messages printed @@ -475,10 +476,9 @@ int nand_write_opts(nand_info_t *meminfo, const nand_write_options_t *opts)  		imglen -= readlen;  		if (!opts->quiet) { -			int percent = (int) -				((unsigned long long) -				 (opts->length-imglen) * 100 -				 / opts->length); +                        unsigned long long n = (unsigned long long) +			         (opts->length-imglen) * 100; +			int percent = (int)do_div(n, opts->length);  			/* output progress message only at whole percent  			 * steps to reduce the number of messages printed  			 * on (slow) serial consoles @@ -651,10 +651,9 @@ int nand_read_opts(nand_info_t *meminfo, const nand_read_options_t *opts)  		}  		if (!opts->quiet) { -			int percent = (int) -				((unsigned long long) -				 (opts->length-imglen) * 100 -				 / opts->length); +                        unsigned long long n = (unsigned long long) +			         (opts->length-imglen) * 100; +			int percent = (int)do_div(n ,opts->length);  			/* output progress message only at whole percent  			 * steps to reduce the number of messages printed  			 * on (slow) serial consoles diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 5f209629f..0f5232a72 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -98,7 +98,7 @@ static void qe_sdma_init(void)  	out_be32(&p->sdaqmr, 0);  	/* Allocate 2KB temporary buffer for sdma */ -	sdma_buffer_base = qe_muram_alloc(2048, 64); +	sdma_buffer_base = qe_muram_alloc(2048, 4096);  	out_be32(&p->sdwbcr, sdma_buffer_base & QE_SDEBCR_BA_MASK);  	/* Clear sdma status */ diff --git a/drivers/qe/qe.h b/drivers/qe/qe.h index 0bcd0a957..400b1a6f6 100644 --- a/drivers/qe/qe.h +++ b/drivers/qe/qe.h @@ -29,7 +29,7 @@  #define QE_NUM_OF_BRGS	16  #define UCC_MAX_NUM	8 -#define QE_DATAONLY_BASE	(uint)(128) +#define QE_DATAONLY_BASE	0  #define QE_DATAONLY_SIZE	(QE_MURAM_SIZE - QE_DATAONLY_BASE)  /* QE threads SNUM diff --git a/drivers/tsec.c b/drivers/tsec.c index 60bef9af3..c01112349 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -71,6 +71,7 @@ static struct tsec_info_struct tsec_info[] = {  #else  	{TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},  #endif +#else  	{0, 0, 0},  #endif  #if defined(CONFIG_TSEC2) @@ -79,6 +80,7 @@ static struct tsec_info_struct tsec_info[] = {  #else  	{TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},  #endif +#else  	{0, 0, 0},  #endif  #ifdef CONFIG_MPC85XX_FEC @@ -296,9 +298,9 @@ static int init_phy(struct eth_device *dev)  	volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);  	/* Assign a Physical address to the TBI */ -	regs->tbipa = TBIPA_VALUE; +	regs->tbipa = CFG_TBIPA_VALUE;  	regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE); -	regs->tbipa = TBIPA_VALUE; +	regs->tbipa = CFG_TBIPA_VALUE;  	asm("sync");  	/* Reset MII (due to new addresses) */ diff --git a/drivers/tsec.h b/drivers/tsec.h index 7bf3dee2b..2f0092ad5 100644 --- a/drivers/tsec.h +++ b/drivers/tsec.h @@ -70,7 +70,9 @@  #define miim_end -2  #define miim_read -1 -#define TBIPA_VALUE		0x1f +#ifndef CFG_TBIPA_VALUE +    #define CFG_TBIPA_VALUE	0x1f +#endif  #define MIIMCFG_INIT_VALUE	0x00000003  #define MIIMCFG_RESET		0x80000000 diff --git a/cpu/arm920t/at91rm9200/usb_ohci.c b/drivers/usb_ohci.c index 5b2c56cff..d6b745fad 100644 --- a/cpu/arm920t/at91rm9200/usb_ohci.c +++ b/drivers/usb_ohci.c @@ -1,5 +1,11 @@  /* - * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200. + * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus. + * + * Interrupt support is added. Now, it has been tested + * on ULI1575 chip and works well with USB keyboard. + * + * (C) Copyright 2007 + * Zhang Wei, Freescale Semiconductor, Inc. <wei.zhang@freescale.com>   *   * (C) Copyright 2003   * Gary Jennejohn, DENX Software Engineering <gj@denx.de> @@ -21,7 +27,7 @@   *   * 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 + * 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 @@ -32,38 +38,66 @@   */  /*   * IMPORTANT NOTES - * 1 - you MUST define LITTLEENDIAN in the configuration file for the - *     board or this driver will NOT work! + * 1 - Read doc/README.generic_usb_ohci   * 2 - this driver is intended for use with USB Mass Storage Devices - *     (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! - * 3 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG + *     (BBB) and USB keyboard. There is NO support for Isochronous pipes! + * 2 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG   *     to activate workaround for bug #41 or this driver will NOT work!   */  #include <common.h> -/* #include <pci.h> no PCI on the S3C24X0 */ -#ifdef CONFIG_USB_OHCI +#ifdef CONFIG_USB_OHCI_NEW -#include <asm/arch/hardware.h> +#include <asm/byteorder.h> + +#if defined(CONFIG_PCI_OHCI) +# include <pci.h> +#endif  #include <malloc.h>  #include <usb.h>  #include "usb_ohci.h" -#define OHCI_USE_NPS		/* force NoPowerSwitching mode */ +#if defined(CONFIG_ARM920T) || \ +    defined(CONFIG_S3C2400) || \ +    defined(CONFIG_S3C2410) || \ +    defined(CONFIG_440EP) || \ +    defined(CONFIG_PCI_OHCI) || \ +    defined(CONFIG_MPC5200) +# define OHCI_USE_NPS		/* force NoPowerSwitching mode */ +#endif +  #undef OHCI_VERBOSE_DEBUG	/* not always helpful */ +#undef DEBUG +#undef SHOW_INFO +#undef OHCI_FILL_TRACE  /* For initializing controller (mask in an HCFS mode too) */  #define OHCI_CONTROL_INIT \  	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE -#define readl(a) (*((vu_long *)(a))) -#define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a)) +/* + * e.g. PCI controllers need this + */ +#ifdef CFG_OHCI_SWAP_REG_ACCESS +# define readl(a) __swap_32(*((vu_long *)(a))) +# define writel(a, b) (*((vu_long *)(b)) = __swap_32((vu_long)a)) +#else +# define readl(a) (*((vu_long *)(a))) +# define writel(a, b) (*((vu_long *)(b)) = ((vu_long)a)) +#endif /* CFG_OHCI_SWAP_REG_ACCESS */  #define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) -#undef DEBUG +#ifdef CONFIG_PCI_OHCI +static struct pci_device_id ohci_pci_ids[] = { +	{0x10b9, 0x5237},	/* ULI1575 PCI OHCI module ids */ +	/* Please add supported PCI OHCI controller ids here */ +	{0, 0} +}; +#endif +  #ifdef DEBUG  #define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)  #else @@ -77,8 +111,13 @@  #define info(format, arg...) do {} while(0)  #endif -#define m16_swap(x) swap_16(x) -#define m32_swap(x) swap_32(x) +#ifdef CFG_OHCI_BE_CONTROLLER +# define m16_swap(x) cpu_to_be16(x) +# define m32_swap(x) cpu_to_be32(x) +#else +# define m16_swap(x) cpu_to_le16(x) +# define m32_swap(x) cpu_to_le32(x) +#endif /* CFG_OHCI_BE_CONTROLLER */  /* global ohci_t */  static ohci_t gohci; @@ -88,13 +127,13 @@ struct ohci_hcca ghcca[1];  struct ohci_hcca *phcca;  /* this allocates EDs for all possible endpoints */  struct ohci_device ohci_dev; -/* urb_priv */ -urb_priv_t urb_priv;  /* RHSC flag */  int got_rhsc;  /* device which was disconnected */  struct usb_device *devgone; + +  /*-------------------------------------------------------------------------*/  /* AMD-756 (D2 rev) reports corrupt register contents in some cases. @@ -147,6 +186,7 @@ static void urb_free_priv (urb_priv_t * urb)  			}  		}  	} +	free(urb);  }  /*-------------------------------------------------------------------------*/ @@ -157,11 +197,10 @@ static int sohci_get_current_frame_number (struct usb_device * dev);  /* debug| print the main components of an URB   * small: 0) header + data packets 1) just header */ -static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, +static void pkt_print (urb_priv_t *purb, struct usb_device * dev, +	unsigned long pipe, void * buffer,  	int transfer_len, struct devrequest * setup, char * str, int small)  { -	urb_priv_t * purb = &urb_priv; -  	dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",  			str,  			sohci_get_current_frame_number (dev), @@ -170,7 +209,7 @@ static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffe  			usb_pipeout (pipe)? 'O': 'I',  			usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):  				(usb_pipecontrol (pipe)? "CTRL": "BULK"), -			purb->actual_length, +			(purb ? purb->actual_length : 0),  			transfer_len, dev->status);  #ifdef	OHCI_VERBOSE_DEBUG  	if (!small) { @@ -184,10 +223,11 @@ static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffe  		}  		if (transfer_len > 0 && buffer) {  			printf (__FILE__ ": data(%d/%d):", -				purb->actual_length, +				(purb ? purb->actual_length : 0),  				transfer_len);  			len = usb_pipeout (pipe)? -					transfer_len: purb->actual_length; +					transfer_len: +					(purb ? purb->actual_length : 0);  			for (i = 0; i < 16 && i < len; i++)  				printf (" %02x", ((__u8 *) buffer) [i]);  			printf ("%s\n", i < len? "...": ""); @@ -383,13 +423,17 @@ static void ohci_dump (ohci_t *controller, int verbose)  /* get a transfer request */ -int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, -		int transfer_len, struct devrequest *setup, int interval) +int sohci_submit_job(urb_priv_t *urb, struct devrequest *setup)  {  	ohci_t *ohci;  	ed_t * ed; -	urb_priv_t *purb_priv; +	urb_priv_t *purb_priv = urb;  	int i, size = 0; +	struct usb_device *dev = urb->dev; +	unsigned long pipe = urb->pipe; +	void *buffer = urb->transfer_buffer; +	int transfer_len = urb->transfer_buffer_length; +	int interval = urb->interval;  	ohci = &gohci; @@ -400,8 +444,11 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,  		return -1;  	} +	/* we're about to begin a new transaction here so mark the URB unfinished */ +	urb->finished = 0; +  	/* every endpoint has a ed, locate and fill it */ -	if (!(ed = ep_add_ed (dev, pipe))) { +	if (!(ed = ep_add_ed (dev, pipe, interval, 1))) {  		err("sohci_submit_job: ENOMEM");  		return -1;  	} @@ -415,13 +462,17 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,  			size = (transfer_len == 0)? 2:  						(transfer_len - 1) / 4096 + 3;  			break; +		case PIPE_INTERRUPT: /* 1 TD */ +			size = 1; +			break;  	} +	ed->purb = urb; +  	if (size >= (N_URB_TD - 1)) {  		err("need %d TDs, only have %d", size, N_URB_TD);  		return -1;  	} -	purb_priv = &urb_priv;  	purb_priv->pipe = pipe;  	/* fill the private part of the URB */ @@ -457,6 +508,40 @@ int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,  	return 0;  } +static inline int sohci_return_job(struct ohci *hc, urb_priv_t *urb) +{ +	struct ohci_regs *regs = hc->regs; + +	switch (usb_pipetype (urb->pipe)) { +	case PIPE_INTERRUPT: +		/* implicitly requeued */ +		if (urb->dev->irq_handle && +				(urb->dev->irq_act_len = urb->actual_length)) { +			writel (OHCI_INTR_WDH, ®s->intrenable); +			readl (®s->intrenable); /* PCI posting flush */ +			urb->dev->irq_handle(urb->dev); +			writel (OHCI_INTR_WDH, ®s->intrdisable); +			readl (®s->intrdisable); /* PCI posting flush */ +		} +		urb->actual_length = 0; +		td_submit_job ( +				urb->dev, +				urb->pipe, +				urb->transfer_buffer, +				urb->transfer_buffer_length, +				NULL, +				urb, +				urb->interval); +		break; +	case PIPE_CONTROL: +	case PIPE_BULK: +		break; +	default: +		return 0; +	} +	return 1; +} +  /*-------------------------------------------------------------------------*/  #ifdef DEBUG @@ -474,13 +559,73 @@ static int sohci_get_current_frame_number (struct usb_device *usb_dev)   * ED handling functions   *-------------------------------------------------------------------------*/ +/* search for the right branch to insert an interrupt ed into the int tree + * do some load ballancing; + * returns the branch and + * sets the interval to interval = 2^integer (ld (interval)) */ + +static int ep_int_ballance (ohci_t * ohci, int interval, int load) +{ +	int i, branch = 0; + +	/* search for the least loaded interrupt endpoint +	 * branch of all 32 branches +	 */ +	for (i = 0; i < 32; i++) +		if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) +			branch = i; + +	branch = branch % interval; +	for (i = branch; i < 32; i += interval) +		ohci->ohci_int_load [i] += load; + +	return branch; +} + +/*-------------------------------------------------------------------------*/ + +/*  2^int( ld (inter)) */ + +static int ep_2_n_interval (int inter) +{ +	int i; +	for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); +	return 1 << i; +} + +/*-------------------------------------------------------------------------*/ + +/* the int tree is a binary tree + * in order to process it sequentially the indexes of the branches have to be mapped + * the mapping reverses the bits of a word of num_bits length */ + +static int ep_rev (int num_bits, int word) +{ +	int i, wout = 0; + +	for (i = 0; i < num_bits; i++) +		wout |= (((word >> i) & 1) << (num_bits - i - 1)); +	return wout; +} + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ +  /* link an ed into one of the HC chains */  static int ep_link (ohci_t *ohci, ed_t *edi)  {  	volatile ed_t *ed = edi; +	int int_branch; +	int i; +	int inter; +	int interval; +	int load; +	__u32 * ed_p;  	ed->state = ED_OPER; +	ed->int_interval = 0;  	switch (ed->type) {  	case PIPE_CONTROL: @@ -488,7 +633,7 @@ static int ep_link (ohci_t *ohci, ed_t *edi)  		if (ohci->ed_controltail == NULL) {  			writel (ed, &ohci->regs->ed_controlhead);  		} else { -			ohci->ed_controltail->hwNextED = m32_swap (ed); +			ohci->ed_controltail->hwNextED = m32_swap ((unsigned long)ed);  		}  		ed->ed_prev = ohci->ed_controltail;  		if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && @@ -504,7 +649,7 @@ static int ep_link (ohci_t *ohci, ed_t *edi)  		if (ohci->ed_bulktail == NULL) {  			writel (ed, &ohci->regs->ed_bulkhead);  		} else { -			ohci->ed_bulktail->hwNextED = m32_swap (ed); +			ohci->ed_bulktail->hwNextED = m32_swap ((unsigned long)ed);  		}  		ed->ed_prev = ohci->ed_bulktail;  		if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && @@ -514,19 +659,59 @@ static int ep_link (ohci_t *ohci, ed_t *edi)  		}  		ohci->ed_bulktail = edi;  		break; + +	case PIPE_INTERRUPT: +		load = ed->int_load; +		interval = ep_2_n_interval (ed->int_period); +		ed->int_interval = interval; +		int_branch = ep_int_ballance (ohci, interval, load); +		ed->int_branch = int_branch; + +		for (i = 0; i < ep_rev (6, interval); i += inter) { +			inter = 1; +			for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); +				(*ed_p != 0) && (((ed_t *)ed_p)->int_interval >= interval); +				ed_p = &(((ed_t *)ed_p)->hwNextED)) +					inter = ep_rev (6, ((ed_t *)ed_p)->int_interval); +			ed->hwNextED = *ed_p; +			*ed_p = m32_swap(ed); +		} +		break;  	}  	return 0;  }  /*-------------------------------------------------------------------------*/ +/* scan the periodic table to find and unlink this ED */ +static void periodic_unlink ( struct ohci *ohci, volatile struct ed *ed, +		unsigned index, unsigned period) +{ +	for (; index < NUM_INTS; index += period) { +		__u32	*ed_p = &ohci->hcca->int_table [index]; + +		/* ED might have been unlinked through another path */ +		while (*ed_p != 0) { +			if (((struct ed *)m32_swap (ed_p)) == ed) { +				*ed_p = ed->hwNextED; +				break; +			} +			ed_p = & (((struct ed *)m32_swap (ed_p))->hwNextED); +		} +	} +} + +  /* unlink an ed from one of the HC chains.   * just the link to the ed is unlinked.   * the link from the ed still points to another operational ed or 0   * so the HC can eventually finish the processing of the unlinked ed */ -static int ep_unlink (ohci_t *ohci, ed_t *ed) +static int ep_unlink (ohci_t *ohci, ed_t *edi)  { +	volatile ed_t *ed = edi; +	int i; +  	ed->hwINFO |= m32_swap (OHCI_ED_SKIP);  	switch (ed->type) { @@ -563,6 +748,12 @@ static int ep_unlink (ohci_t *ohci, ed_t *ed)  			((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;  		}  		break; + +	case PIPE_INTERRUPT: +		periodic_unlink (ohci, ed, 0, 1); +		for (i = ed->int_branch; i < 32; i += ed->int_interval) +		    ohci->ohci_int_load[i] -= ed->int_load; +		break;  	}  	ed->state = ED_UNLINK;  	return 0; @@ -571,13 +762,16 @@ static int ep_unlink (ohci_t *ohci, ed_t *ed)  /*-------------------------------------------------------------------------*/ -/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, - * but the USB stack is a little bit stateless	so we do it at every transaction - * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK - * in all other cases the state is left unchanged - * the ed info fields are setted anyway even though most of them should not change */ - -static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) +/* add/reinit an endpoint; this should be done once at the + * usb_set_configuration command, but the USB stack is a little bit + * stateless so we do it at every transaction if the state of the ed + * is ED_NEW then a dummy td is added and the state is changed to + * ED_UNLINK in all other cases the state is left unchanged the ed + * info fields are setted anyway even though most of them should not + * change + */ +static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe, +		int interval, int load)  {  	td_t *td;  	ed_t *ed_ret; @@ -596,7 +790,7 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)  		ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */  		/* dummy td; end of td list for ed */  		td = td_alloc (usb_dev); -		ed->hwTailP = m32_swap (td); +		ed->hwTailP = m32_swap ((unsigned long)td);  		ed->hwHeadP = ed->hwTailP;  		ed->state = ED_UNLINK;  		ed->type = usb_pipetype (pipe); @@ -610,6 +804,11 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)  			| usb_pipeslow (pipe) << 13  			| usb_maxpacket (usb_dev, pipe) << 16); +	if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { +		ed->int_period = interval; +		ed->int_load = load; +	} +  	return ed_ret;  } @@ -654,13 +853,12 @@ static void td_fill (ohci_t *ohci, unsigned int info,  		data = 0;  	td->hwINFO = m32_swap (info); -	td->hwCBP = m32_swap (data); +	td->hwCBP = m32_swap ((unsigned long)data);  	if (data) -		td->hwBE = m32_swap (data + len - 1); +		td->hwBE = m32_swap ((unsigned long)(data + len - 1));  	else  		td->hwBE = 0; -	td->hwNextTD = m32_swap (td_pt); -	td->hwPSW [0] = m16_swap (((__u32)data & 0x0FFF) | 0xE000); +	td->hwNextTD = m32_swap ((unsigned long)td_pt);  	/* append to queue */  	td->ed->hwTailP = td->hwNextTD; @@ -725,6 +923,13 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf  		if (!ohci->sleeping)  			writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */  		break; + +	case PIPE_INTERRUPT: +		info = usb_pipeout (urb->pipe)? +			TD_CC | TD_DP_OUT | toggle: +			TD_CC | TD_R | TD_DP_IN | toggle; +		td_fill (ohci, info, data, data_len, dev, cnt++, urb); +		break;  	}  	if (urb->length != cnt)  		dbg("TD LENGTH %d != CNT %d", urb->length, cnt); @@ -740,7 +945,7 @@ static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buf  static void dl_transfer_length(td_t * td)  {  	__u32 tdINFO, tdBE, tdCBP; -	urb_priv_t *lurb_priv = &urb_priv; +	urb_priv_t *lurb_priv = td->ed->purb;  	tdINFO = m32_swap (td->hwINFO);  	tdBE   = m32_swap (td->hwBE); @@ -777,7 +982,7 @@ static td_t * dl_reverse_done_list (ohci_t *ohci)  		td_list = (td_t *)td_list_hc;  		if (TD_CC_GET (m32_swap (td_list->hwINFO))) { -			lurb_priv = &urb_priv; +			lurb_priv = td_list->ed->purb;  			dbg(" USB-error/status: %x : %p",  					TD_CC_GET (m32_swap (td_list->hwINFO)), td_list);  			if (td_list->ed->hwHeadP & m32_swap (0x1)) { @@ -789,6 +994,9 @@ static td_t * dl_reverse_done_list (ohci_t *ohci)  				} else  					td_list->ed->hwHeadP &= m32_swap (0xfffffff2);  			} +#ifdef CONFIG_MPC5200 +			td_list->hwNextTD = 0; +#endif  		}  		td_list->next_dl_td = td_rev; @@ -814,10 +1022,10 @@ static int dl_done_list (ohci_t *ohci, td_t *td_list)  	while (td_list) {  		td_list_next = td_list->next_dl_td; -		lurb_priv = &urb_priv;  		tdINFO = m32_swap (td_list->hwINFO);  		ed = td_list->ed; +		lurb_priv = ed->purb;  		dl_transfer_length(td_list); @@ -828,7 +1036,24 @@ static int dl_done_list (ohci_t *ohci, td_t *td_list)  			stat = cc_to_error[cc];  		} -		if (ed->state != ED_NEW) { +		/* see if this done list makes for all TD's of current URB, +		 * and mark the URB finished if so */ +		if (++(lurb_priv->td_cnt) == lurb_priv->length) { +#if 1 +			if ((ed->state & (ED_OPER | ED_UNLINK)) && +			    (lurb_priv->state != URB_DEL)) +#else +			if ((ed->state & (ED_OPER | ED_UNLINK))) +#endif +				lurb_priv->finished = sohci_return_job(ohci, +						lurb_priv); +			else +				dbg("dl_done_list: strange.., ED state %x, ed->state\n"); +		} else +			dbg("dl_done_list: processing TD %x, len %x\n", lurb_priv->td_cnt, +				lurb_priv->length); +		if (ed->state != ED_NEW && +			  (usb_pipetype (lurb_priv->pipe) != PIPE_INTERRUPT)) {  			edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0;  			edTailP = m32_swap (ed->hwTailP); @@ -974,7 +1199,6 @@ int rh_check_port_status(ohci_t *controller)  #ifdef CONFIG_AT91C_PQFP_UHPBUG  	ndp = (ndp == 2) ? 1:0;  #endif -  	for (i = 0; i < ndp; i++) {  		temp = roothub_portstatus (controller, i);  		/* check for a device disconnect */ @@ -1003,8 +1227,7 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,  	__u16 wLength;  #ifdef DEBUG -urb_priv.actual_length = 0; -pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); +pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));  #else  	wait_ms(1);  #endif @@ -1014,9 +1237,9 @@ pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));  	}  	bmRType_bReq  = cmd->requesttype | (cmd->request << 8); -	wValue	      = m16_swap (cmd->value); -	wIndex	      = m16_swap (cmd->index); -	wLength	      = m16_swap (cmd->length); +	wValue	      = cpu_to_le16 (cmd->value); +	wIndex	      = cpu_to_le16 (cmd->index); +	wLength	      = cpu_to_le16 (cmd->length);  	info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",  		dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); @@ -1031,17 +1254,17 @@ pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));  	*/  	case RH_GET_STATUS: -			*(__u16 *) data_buf = m16_swap (1); OK (2); +			*(__u16 *) data_buf = cpu_to_le16 (1); OK (2);  	case RH_GET_STATUS | RH_INTERFACE: -			*(__u16 *) data_buf = m16_swap (0); OK (2); +			*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);  	case RH_GET_STATUS | RH_ENDPOINT: -			*(__u16 *) data_buf = m16_swap (0); OK (2); +			*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);  	case RH_GET_STATUS | RH_CLASS: -			*(__u32 *) data_buf = m32_swap ( +			*(__u32 *) data_buf = cpu_to_le32 (  				RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));  			OK (4);  	case RH_GET_STATUS | RH_OTHER | RH_CLASS: -			*(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4); +			*(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4);  	case RH_CLEAR_FEATURE | RH_ENDPOINT:  		switch (wValue) { @@ -1088,7 +1311,9 @@ pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));  					    WR_RH_PORTSTAT (RH_PS_PRS);  					OK (0);  			case (RH_PORT_POWER): -					WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); +					WR_RH_PORTSTAT (RH_PS_PPS ); +					wait_ms(100); +					OK (0);  			case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/  					if (RD_RH_PORTSTAT & RH_PS_CCS)  					    WR_RH_PORTSTAT (RH_PS_PES ); @@ -1170,7 +1395,7 @@ pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));  		}  		len = min_t(unsigned int, leni, -		min_t(unsigned int, data_buf [0], wLength)); +			    min_t(unsigned int, data_buf [0], wLength));  		OK (len);  	} @@ -1196,9 +1421,7 @@ pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));  	dev->status = stat;  #ifdef DEBUG -	if (transfer_len) -		urb_priv.actual_length = transfer_len; -	pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); +	pkt_print(NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);  #else  	wait_ms(1);  #endif @@ -1216,6 +1439,16 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  	int stat = 0;  	int maxsize = usb_maxpacket(dev, pipe);  	int timeout; +	urb_priv_t *urb; + +	urb = malloc(sizeof(urb_priv_t)); +	memset(urb, 0, sizeof(urb_priv_t)); + +	urb->dev = dev; +	urb->pipe = pipe; +	urb->transfer_buffer = buffer; +	urb->transfer_buffer_length = transfer_len; +	urb->interval = interval;  	/* device pulled? Shortcut the action. */  	if (devgone == dev) { @@ -1224,8 +1457,8 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  	}  #ifdef DEBUG -	urb_priv.actual_length = 0; -	pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +	urb->actual_length = 0; +	pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));  #else  	wait_ms(1);  #endif @@ -1235,13 +1468,15 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  		return -1;  	} -	if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { +	if (sohci_submit_job(urb, setup) < 0) {  		err("sohci_submit_job failed");  		return -1;  	} +#if 0  	wait_ms(10);  	/* ohci_dump_status(&gohci); */ +#endif  	/* allow more time for a BULK device to react - some are slow */  #define BULK_TO	 5000	/* timeout in milliseconds */ @@ -1258,51 +1493,47 @@ int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  			stat = USB_ST_CRC_ERR;  			break;  		} -		if (stat >= 0 && stat != 0xff) { + +		/* NOTE: since we are not interrupt driven in U-Boot and always +		 * handle only one URB at a time, we cannot assume the +		 * transaction finished on the first successful return from +		 * hc_interrupt().. unless the flag for current URB is set, +		 * meaning that all TD's to/from device got actually +		 * transferred and processed. If the current URB is not +		 * finished we need to re-iterate this loop so as +		 * hc_interrupt() gets called again as there needs to be some +		 * more TD's to process still */ +		if ((stat >= 0) && (stat != 0xff) && (urb->finished)) {  			/* 0xff is returned for an SF-interrupt */  			break;  		} +  		if (--timeout) {  			wait_ms(1); +			if (!urb->finished) +				dbg("\%"); +  		} else {  			err("CTL:TIMEOUT "); +			dbg("submit_common_msg: TO status %x\n", stat); +			urb->finished = 1;  			stat = USB_ST_CRC_ERR;  			break;  		}  	} -	/* we got an Root Hub Status Change interrupt */ -	if (got_rhsc) { -#ifdef DEBUG -		ohci_dump_roothub (&gohci, 1); -#endif -		got_rhsc = 0; -		/* abuse timeout */ -		timeout = rh_check_port_status(&gohci); -		if (timeout >= 0) { -#if 0 /* this does nothing useful, but leave it here in case that changes */ -			/* the called routine adds 1 to the passed value */ -			usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); -#endif -			/* -			 * XXX -			 * This is potentially dangerous because it assumes -			 * that only one device is ever plugged in! -			 */ -			devgone = dev; -		} -	}  	dev->status = stat;  	dev->act_len = transfer_len;  #ifdef DEBUG -	pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); +	pkt_print(urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));  #else  	wait_ms(1);  #endif  	/* free TDs in urb_priv */ -	urb_free_priv (&urb_priv); +	if (usb_pipetype (pipe) != PIPE_INTERRUPT) +		urb_free_priv (urb);  	return 0;  } @@ -1321,8 +1552,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  	info("submit_control_msg");  #ifdef DEBUG -	urb_priv.actual_length = 0; -	pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +	pkt_print(NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));  #else  	wait_ms(1);  #endif @@ -1345,7 +1575,8 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  		int transfer_len, int interval)  {  	info("submit_int_msg"); -	return -1; +	return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, +			interval);  }  /*-------------------------------------------------------------------------* @@ -1381,7 +1612,8 @@ static int hc_reset (ohci_t *ohci)  		readl(&ohci->regs->control));  	/* Reset USB (needed by some controllers) */ -	writel (0, &ohci->regs->control); +	ohci->hc_control = 0; +	writel (ohci->hc_control, &ohci->regs->control);  	/* HC Reset requires max 10 us delay */  	writel (OHCI_HCR,  &ohci->regs->cmdstatus); @@ -1458,26 +1690,38 @@ static int hc_start (ohci_t * ohci)  /*-------------------------------------------------------------------------*/ +/* Poll USB interrupt. */ +void usb_event_poll(void) +{ +	hc_interrupt(); +} +  /* an interrupt happens */ -static int -hc_interrupt (void) +static int hc_interrupt (void)  {  	ohci_t *ohci = &gohci;  	struct ohci_regs *regs = ohci->regs;  	int ints;  	int stat = -1; -	if ((ohci->hcca->done_head != 0) && !(m32_swap (ohci->hcca->done_head) & 0x01)) { -		ints =	OHCI_INTR_WDH; -	} else { -		ints = readl (®s->intrstatus); +	if ((ohci->hcca->done_head != 0) && +	    !(m32_swap (ohci->hcca->done_head) & 0x01)) { +		ints =  OHCI_INTR_WDH; +	} else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { +		ohci->disabled++; +		err ("%s device removed!", ohci->slot_name); +		return -1; +	} else if ((ints &= readl (®s->intrenable)) == 0) { +		dbg("hc_interrupt: returning..\n"); +		return 0xff;  	}  	/* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */  	if (ints & OHCI_INTR_RHSC) {  		got_rhsc = 1; +		stat = 0xff;  	}  	if (ints & OHCI_INTR_UE) { @@ -1502,8 +1746,10 @@ hc_interrupt (void)  	if (ints & OHCI_INTR_WDH) {  		wait_ms(1);  		writel (OHCI_INTR_WDH, ®s->intrdisable); +		(void)readl (®s->intrdisable); /* flush */  		stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));  		writel (OHCI_INTR_WDH, ®s->intrenable); +		(void)readl (®s->intrdisable); /* flush */  	}  	if (ints & OHCI_INTR_SO) { @@ -1549,14 +1795,22 @@ static char ohci_inited = 0;  int usb_lowlevel_init(void)  { -	/* -	 * Enable USB host clock. -	 */ -	*AT91C_PMC_SCER = AT91C_PMC_UHP;	/* 48MHz clock enabled for UHP */ -	*AT91C_PMC_PCER = 1 << AT91C_ID_UHP;	/* Peripheral Clock Enable Register */ +#ifdef CONFIG_PCI_OHCI +	pci_dev_t pdev; +#endif +#ifdef CFG_USB_OHCI_CPU_INIT +	/* cpu dependant init */ +	if(usb_cpu_init()) +		return -1; +#endif + +#ifdef CFG_USB_OHCI_BOARD_INIT +	/*  board dependant init */ +	if(usb_board_init()) +		return -1; +#endif  	memset (&gohci, 0, sizeof (ohci_t)); -	memset (&urb_priv, 0, sizeof (urb_priv_t));  	/* align the storage */  	if ((__u32)&ghcca[0] & 0xff) { @@ -1582,29 +1836,60 @@ int usb_lowlevel_init(void)  	gohci.disabled = 1;  	gohci.sleeping = 0;  	gohci.irq = -1; -	gohci.regs = (struct ohci_regs *)AT91_USB_HOST_BASE; +#ifdef CONFIG_PCI_OHCI +	pdev = pci_find_devices(ohci_pci_ids, 0); + +	if (pdev != -1) { +		u16 vid, did; +		u32 base; +		pci_read_config_word(pdev, PCI_VENDOR_ID, &vid); +		pci_read_config_word(pdev, PCI_DEVICE_ID, &did); +		printf("OHCI pci controller (%04x, %04x) found @(%d:%d:%d)\n", +				vid, did, (pdev >> 16) & 0xff, +				(pdev >> 11) & 0x1f, (pdev >> 8) & 0x7); +		pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base); +		printf("OHCI regs address 0x%08x\n", base); +		gohci.regs = (struct ohci_regs *)base; +	} else +		return -1; +#else +	gohci.regs = (struct ohci_regs *)CFG_USB_OHCI_REGS_BASE; +#endif  	gohci.flags = 0; -	gohci.slot_name = "at91rm9200"; +	gohci.slot_name = CFG_USB_OHCI_SLOT_NAME;  	if (hc_reset (&gohci) < 0) {  		hc_release_ohci (&gohci); -		/* Initialization failed */ -		*AT91C_PMC_PCER = AT91C_ID_UHP; -		*AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP;	/* 48MHz clock disabled for UHP */ +		err ("can't reset usb-%s", gohci.slot_name); +#ifdef CFG_USB_OHCI_BOARD_INIT +		/* board dependant cleanup */ +		usb_board_init_fail(); +#endif + +#ifdef CFG_USB_OHCI_CPU_INIT +		/* cpu dependant cleanup */ +		usb_cpu_init_fail(); +#endif  		return -1;  	}  	/* FIXME this is a second HC reset; why?? */ -/*	writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); -	wait_ms (10);*/ - +	/* writel(gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); +	   wait_ms(10); */  	if (hc_start (&gohci) < 0) {  		err ("can't start usb-%s", gohci.slot_name);  		hc_release_ohci (&gohci);  		/* Initialization failed */ -		*AT91C_PMC_PCER = AT91C_ID_UHP; -		*AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP;	/* 48MHz clock disabled for UHP */ +#ifdef CFG_USB_OHCI_BOARD_INIT +		/* board dependant cleanup */ +		usb_board_stop(); +#endif + +#ifdef CFG_USB_OHCI_CPU_INIT +		/* cpu dependant cleanup */ +		usb_cpu_stop(); +#endif  		return -1;  	} @@ -1626,10 +1911,19 @@ int usb_lowlevel_stop(void)  	/* TODO release any interrupts, etc. */  	/* call hc_release_ohci() here ? */  	hc_reset (&gohci); -	/* may not want to do this */ -	*AT91C_PMC_PCER = 1 << AT91C_ID_UHP; -	*AT91C_PMC_SCDR = 1 << AT91C_PMC_UHP;	/* 48MHz clock disabled for UHP */ + +#ifdef CFG_USB_OHCI_BOARD_INIT +	/* board dependant cleanup */ +	if(usb_board_stop()) +		return -1; +#endif + +#ifdef CFG_USB_OHCI_CPU_INIT +	/* cpu dependant cleanup */ +	if(usb_cpu_stop()) +		return -1; +#endif +  	return 0;  } - -#endif /* CONFIG_USB_OHCI */ +#endif /* CONFIG_USB_OHCI_NEW */ diff --git a/cpu/arm920t/at91rm9200/usb_ohci.h b/drivers/usb_ohci.h index ecb4e937b..380cb4c92 100644 --- a/cpu/arm920t/at91rm9200/usb_ohci.h +++ b/drivers/usb_ohci.h @@ -7,6 +7,15 @@   * usb-ohci.h   */ +/* functions for doing board or CPU specific setup/cleanup */ +extern int usb_board_init(void); +extern int usb_board_stop(void); +extern int usb_board_init_fail(void); + +extern int usb_cpu_init(void); +extern int usb_cpu_stop(void); +extern int usb_cpu_init_fail(void); +  static int cc_to_error[16] = { @@ -55,7 +64,8 @@ struct ed {  	struct ed *ed_rm_list;  	struct usb_device *usb_dev; -	__u32 unused[3]; +	void *purb; +	__u32 unused[2];  } __attribute((aligned(16)));  typedef struct ed ed_t; @@ -104,7 +114,9 @@ struct td {  	__u32 hwNextTD;		/* Next TD Pointer */  	__u32 hwBE;		/* Memory Buffer End Pointer */ +/* #ifndef CONFIG_MPC5200 /\* this seems wrong *\/ */  	__u16 hwPSW[MAXPSW]; +/* #endif */  	__u8 unused;  	__u8 index;  	struct ed *ed; @@ -128,8 +140,13 @@ typedef struct td td_t;  #define NUM_INTS 32	/* part of the OHCI standard */  struct ohci_hcca {  	__u32	int_table[NUM_INTS];	/* Interrupt ED table */ +#if defined(CONFIG_MPC5200) +	__u16	pad1;			/* set to 0 on each frame_no change */ +	__u16	frame_no;		/* current frame number */ +#else  	__u16	frame_no;		/* current frame number */  	__u16	pad1;			/* set to 0 on each frame_no change */ +#endif  	__u32	done_head;		/* info returned for an interrupt */  	u8		reserved_for_hc[116];  } __attribute((aligned(256))); @@ -138,7 +155,9 @@ struct ohci_hcca {  /*   * Maximum number of root hub ports.   */ -#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports */ +#ifndef CFG_USB_OHCI_MAX_ROOT_PORTS +# error "CFG_USB_OHCI_MAX_ROOT_PORTS undefined!" +#endif  /*   * This is the structure of the OHCI controller's memory mapped I/O @@ -172,7 +191,7 @@ struct ohci_regs {  		__u32	a;  		__u32	b;  		__u32	status; -		__u32	portstatus[MAX_ROOT_PORTS]; +		__u32	portstatus[CFG_USB_OHCI_MAX_ROOT_PORTS];  	} roothub;  } __attribute((aligned(32))); @@ -331,9 +350,14 @@ typedef struct  	ed_t *ed;  	__u16 length;	/* number of tds associated with this request */  	__u16 td_cnt;	/* number of tds already serviced */ +	struct usb_device *dev;  	int   state;  	unsigned long pipe; +	void *transfer_buffer; +	int transfer_buffer_length; +	int interval;  	int actual_length; +	int finished;  	td_t *td[N_URB_TD];	/* list pointer to all corresponding TDs associated with this request */  } urb_priv_t;  #define URB_DEL 1 @@ -357,6 +381,7 @@ typedef struct ohci {  	struct ohci_regs *regs; /* OHCI controller's memory */ +	int ohci_int_load[32];	 /* load of the 32 Interrupt Chains (for load balancing)*/  	ed_t *ed_rm_list[2];	 /* lists of all endpoints to be removed */  	ed_t *ed_bulktail;	 /* last endpoint of bulk list */  	ed_t *ed_controltail;	 /* last endpoint of control list */ @@ -379,7 +404,8 @@ struct ohci_device {  /* endpoint */  static int ep_link(ohci_t * ohci, ed_t * ed);  static int ep_unlink(ohci_t * ohci, ed_t * ed); -static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe, +		int interval, int load);  /*-------------------------------------------------------------------------*/ diff --git a/drivers/usbdcore_ep0.c b/drivers/usbdcore_ep0.c index 260befe97..1e44f322a 100644 --- a/drivers/usbdcore_ep0.c +++ b/drivers/usbdcore_ep0.c @@ -2,6 +2,9 @@   * (C) Copyright 2003   * Gerry Hamel, geh@ti.com, Texas Instruments   * + * (C) Copyright 2006 + * Bryan O'Donoghue, deckard@CodeHermit.ie + *   * Based on   * linux/drivers/usbd/ep0.c   * @@ -39,11 +42,17 @@   * function driver. This may need to change.   *   * XXX + * + * As alluded to above, a simple callback cdc_recv_setup has been implemented + * in the usb_device data structure to facilicate passing + * Common Device Class packets to a function driver. + * + * XXX   */  #include <common.h> -#if defined(CONFIG_OMAP1510) && defined(CONFIG_USB_DEVICE) +#if defined(CONFIG_USB_DEVICE)  #include "usbdcore.h"  #if 0 @@ -69,7 +78,7 @@ static int ep0_get_status (struct usb_device_instance *device,  	char *cp;  	urb->actual_length = 2; -	cp = urb->buffer; +	cp = (char*)urb->buffer;  	cp[0] = cp[1] = 0;  	switch (requesttype) { @@ -115,7 +124,7 @@ static int ep0_get_one (struct usb_device_instance *device, struct urb *urb,   *   * Copy configuration data to urb transfer buffer if there is room for it.   */ -static void copy_config (struct urb *urb, void *data, int max_length, +void copy_config (struct urb *urb, void *data, int max_length,  			 int max_buf)  {  	int available; @@ -128,10 +137,7 @@ static void copy_config (struct urb *urb, void *data, int max_length,  		dbg_ep0 (1, "data is NULL");  		return;  	} -	if (!(length = *(unsigned char *) data)) { -		dbg_ep0 (1, "length is zero"); -		return; -	} +	length = max_length;  	if (length > max_length) {  		dbg_ep0 (1, "length: %d >= max_length: %d", length, @@ -192,7 +198,7 @@ static int ep0_get_descriptor (struct usb_device_instance *device,  	/* setup tx urb */  	urb->actual_length = 0; -	cp = urb->buffer; +	cp = (char*)urb->buffer;  	dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type)); @@ -200,7 +206,6 @@ static int ep0_get_descriptor (struct usb_device_instance *device,  	case USB_DESCRIPTOR_TYPE_DEVICE:  		{  			struct usb_device_descriptor *device_descriptor; -  			if (!  			    (device_descriptor =  			     usbd_device_device_descriptor (device, port))) { @@ -214,20 +219,16 @@ static int ep0_get_descriptor (struct usb_device_instance *device,  			/* correct the correct control endpoint 0 max packet size into the descriptor */  			device_descriptor =  				(struct usb_device_descriptor *) urb->buffer; -			device_descriptor->bMaxPacketSize0 = -				urb->device->bus->maxpacketsize;  		} -		/*dbg_ep0(3, "copied device configuration, actual_length: %x", urb->actual_length); */ +		dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length);  		break;  	case USB_DESCRIPTOR_TYPE_CONFIGURATION:  		{ -			int bNumInterface;  			struct usb_configuration_descriptor  				*configuration_descriptor;  			struct usb_device_descriptor *device_descriptor; -  			if (!  			    (device_descriptor =  			     usbd_device_device_descriptor (device, port))) { @@ -251,130 +252,35 @@ static int ep0_get_descriptor (struct usb_device_instance *device,  					 index);  				return -1;  			} +			dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength));  			copy_config (urb, configuration_descriptor, -				     sizeof (struct -					     usb_configuration_descriptor), -				     max); - - -			/* iterate across interfaces for specified configuration */ -			dbg_ep0 (0, "bNumInterfaces: %d", -				 configuration_descriptor->bNumInterfaces); -			for (bNumInterface = 0; -			     bNumInterface < -			     configuration_descriptor->bNumInterfaces; -			     bNumInterface++) { - -				int bAlternateSetting; -				struct usb_interface_instance -					*interface_instance; - -				dbg_ep0 (3, "[%d] bNumInterfaces: %d", -					 bNumInterface, -					 configuration_descriptor->bNumInterfaces); - -				if (! (interface_instance = usbd_device_interface_instance (device, -								     port, index, bNumInterface))) -				{ -					dbg_ep0 (3, "[%d] interface_instance NULL", -						 bNumInterface); -					return -1; -				} -				/* iterate across interface alternates */ -				for (bAlternateSetting = 0; -				     bAlternateSetting < interface_instance->alternates; -				     bAlternateSetting++) { -					/*int class; */ -					int bNumEndpoint; -					struct usb_interface_descriptor *interface_descriptor; -					struct usb_alternate_instance *alternate_instance; - -					dbg_ep0 (3, "[%d:%d] alternates: %d", -						 bNumInterface, -						 bAlternateSetting, -						 interface_instance->alternates); - -					if (! (alternate_instance = usbd_device_alternate_instance (device, port, index, bNumInterface, bAlternateSetting))) { -						dbg_ep0 (3, "[%d] alternate_instance NULL", -							 bNumInterface); -						return -1; -					} -					/* copy descriptor for this interface */ -					copy_config (urb, alternate_instance->interface_descriptor, -						     sizeof (struct usb_interface_descriptor), -						     max); - -					/*dbg_ep0(3, "[%d:%d] classes: %d endpoints: %d", bNumInterface, bAlternateSetting, */ -					/*        alternate_instance->classes, alternate_instance->endpoints); */ - -					/* iterate across classes for this alternate interface */ -#if 0 -					for (class = 0; -					     class < alternate_instance->classes; -					     class++) { -						struct usb_class_descriptor *class_descriptor; -						/*dbg_ep0(3, "[%d:%d:%d] classes: %d", bNumInterface, bAlternateSetting, */ -						/*        class, alternate_instance->classes); */ -						if (!(class_descriptor = usbd_device_class_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, class))) { -							dbg_ep0 (3, "[%d] class NULL", -								 class); -							return -1; -						} -						/* copy descriptor for this class */ -						copy_config (urb, class_descriptor, -							sizeof (struct usb_class_descriptor), -							max); -					} -#endif - -					/* iterate across endpoints for this alternate interface */ -					interface_descriptor = alternate_instance->interface_descriptor; -					for (bNumEndpoint = 0; -					     bNumEndpoint < alternate_instance->endpoints; -					     bNumEndpoint++) { -						struct usb_endpoint_descriptor *endpoint_descriptor; -						dbg_ep0 (3, "[%d:%d:%d] endpoint: %d", -							 bNumInterface, -							 bAlternateSetting, -							 bNumEndpoint, -							 interface_descriptor-> -							 bNumEndpoints); -						if (!(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, bNumEndpoint))) { -							dbg_ep0 (3, "[%d] endpoint NULL", -								 bNumEndpoint); -							return -1; -						} -						/* copy descriptor for this endpoint */ -						copy_config (urb, endpoint_descriptor, -							     sizeof (struct usb_endpoint_descriptor), -							     max); -					} -				} -			} -			dbg_ep0 (3, "lengths: %d %d", -				 le16_to_cpu (configuration_descriptor->wTotalLength), -				 urb->actual_length); +					cpu_to_le16(configuration_descriptor->wTotalLength), +				     max);  		} +  		break;  	case USB_DESCRIPTOR_TYPE_STRING:  		{  			struct usb_string_descriptor *string_descriptor; -  			if (!(string_descriptor = usbd_get_string (index))) { +				serial_printf("Invalid string index %d\n", index);  				return -1;  			} -			/*dbg_ep0(3, "string_descriptor: %p", string_descriptor); */ +			dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength);  			copy_config (urb, string_descriptor, string_descriptor->bLength, max);  		}  		break;  	case USB_DESCRIPTOR_TYPE_INTERFACE: +	serial_printf("USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n");  		return -1;  	case USB_DESCRIPTOR_TYPE_ENDPOINT: +		serial_printf("USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n");  		return -1;  	case USB_DESCRIPTOR_TYPE_HID:  		{ +			serial_printf("USB_DESCRIPTOR_TYPE_HID - error not implemented\n");  			return -1;	/* unsupported at this time */  #if 0  			int bNumInterface = @@ -403,6 +309,7 @@ static int ep0_get_descriptor (struct usb_device_instance *device,  		break;  	case USB_DESCRIPTOR_TYPE_REPORT:  		{ +			serial_printf("USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n");  			return -1;	/* unsupported at this time */  #if 0  			int bNumInterface = @@ -434,12 +341,19 @@ static int ep0_get_descriptor (struct usb_device_instance *device,  #endif  		}  		break; +	case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: +		{ +			/* If a USB device supports both a full speed and low speed operation +			 * we must send a Device_Qualifier descriptor here +			 */ +			return -1; +		}  	default:  		return -1;  	} -	dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d packet size: %2d", +	dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d",  		 urb->buffer, urb->buffer_length, urb->actual_length,  		 device->bus->endpoint_array[0].tx_packetSize);  /* @@ -495,6 +409,12 @@ int ep0_recv_setup (struct urb *urb)  	/* handle USB Standard Request (c.f. USB Spec table 9-2) */  	if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) { +		if(device->device_state <= STATE_CONFIGURED){ +			/*	Attempt to handle a CDC specific request if we are +			 *	in the configured state. +			 */ +			return device->cdc_recv_setup(request,urb); +		}  		dbg_ep0 (1, "non standard request: %x",  			 request->bmRequestType & USB_REQ_TYPE_MASK);  		return -1;	/* Stall here */ @@ -567,6 +487,7 @@ int ep0_recv_setup (struct urb *urb)  						   le16_to_cpu (request->wValue) & 0xff);  		case USB_REQ_GET_CONFIGURATION: +			serial_printf("get config %d\n", device->configuration);  			return ep0_get_one (device, urb,  					    device->configuration); @@ -642,7 +563,6 @@ int ep0_recv_setup (struct urb *urb)  			/*dbg_ep0(2, "address: %d %d %d", */  			/*        request->wValue, le16_to_cpu(request->wValue), device->address); */ -			serial_printf ("DEVICE_ADDRESS_ASSIGNED.. event?\n");  			return 0;  		case USB_REQ_SET_DESCRIPTOR:	/* XXX should we support this? */ @@ -653,9 +573,10 @@ int ep0_recv_setup (struct urb *urb)  			/* c.f. 9.4.7 - the top half of wValue is reserved */  			/* */  			if ((device->configuration = -			     le16_to_cpu (request->wValue) & 0x7f) != 0) { +				le16_to_cpu (request->wValue) & 0xFF80) != 0) {  				/* c.f. 9.4.7 - zero is the default or addressed state, in our case this */  				/* is the same is configuration zero */ +				serial_printf("error setting dev->config to zero!\n");  				device->configuration = 0;	/* TBR - ?????? */  			}  			/* reset interface and alternate settings */ diff --git a/drivers/usbdcore_mpc8xx.c b/drivers/usbdcore_mpc8xx.c new file mode 100644 index 000000000..e87284b17 --- /dev/null +++ b/drivers/usbdcore_mpc8xx.c @@ -0,0 +1,1400 @@ +/* + * Copyright (C) 2006 by Bryan O'Donoghue, CodeHermit + * bodonoghue@CodeHermit.ie + * + * References + * DasUBoot/drivers/usbdcore_omap1510.c, for design and implementation ideas. + * + * 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. + * + */ + +/* + * Notes : + * 1.	#define __SIMULATE_ERROR__ to inject a CRC error into every 2nd TX + *		packet to force the USB re-transmit protocol. + * + * 2.	#define __DEBUG_UDC__ to switch on debug tracing to serial console + *	be careful that tracing doesn't create Hiesen-bugs with respect to + *	response timeouts to control requests. + * + * 3.	This driver should be able to support any higher level driver that + *	that wants to do either of the two standard UDC implementations + *	Control-Bulk-Interrupt or  Bulk-IN/Bulk-Out standards. Hence + *	gserial and cdc_acm should work with this code. + * + * 4.	NAK events never actually get raised at all, the documentation + *	is just wrong ! + * + * 5.	For some reason, cbd_datlen is *always* +2 the value it should be. + *	this means that having an RX cbd of 16 bytes is not possible, since + *	the same size is reported for 14 bytes received as 16 bytes received + *	until we can find out why this happens, RX cbds must be limited to 8 + *	bytes. TODO: check errata for this behaviour. + * + * 6.	Right now this code doesn't support properly powering up with the USB + *	cable attached to the USB host my development board the Adder87x doesn't + *	have a pull-up fitted to allow this, so it is necessary to power the + *	board and *then* attached the USB cable to the host. However somebody + *	with a different design in their board may be able to keep the cable + *	constantly connected and simply enable/disable a pull-up  re + *	figure 31.1 in MPC885RM.pdf instead of having to power up the board and + *	then attach the cable ! + * + */ +#include <common.h> +#include <config.h> + +#if defined(CONFIG_MPC885_FAMILY) && defined(CONFIG_USB_DEVICE) +#include <commproc.h> +#include "usbdcore.h" +#include "usbdcore_mpc8xx.h" +#include "usbdcore_ep0.h" + +#define ERR(fmt, args...)\ +	serial_printf("ERROR : [%s] %s:%d: "fmt,\ +				__FILE__,__FUNCTION__,__LINE__, ##args) +#ifdef __DEBUG_UDC__ +#define DBG(fmt,args...)\ +		serial_printf("[%s] %s:%d: "fmt,\ +				__FILE__,__FUNCTION__,__LINE__, ##args) +#else +#define DBG(fmt,args...) +#endif + +/* Static Data */ +#ifdef __SIMULATE_ERROR__ +static char err_poison_test = 0; +#endif +static struct mpc8xx_ep ep_ref[MAX_ENDPOINTS]; +static u32 address_base = STATE_NOT_READY; +static mpc8xx_udc_state_t udc_state = 0; +static struct usb_device_instance *udc_device = 0; +static volatile usb_epb_t *endpoints[MAX_ENDPOINTS]; +static volatile cbd_t *tx_cbd[TX_RING_SIZE]; +static volatile cbd_t *rx_cbd[RX_RING_SIZE]; +static volatile immap_t *immr = 0; +static volatile cpm8xx_t *cp = 0; +static volatile usb_pram_t *usb_paramp = 0; +static volatile usb_t *usbp = 0; +static int rx_ct = 0; +static int tx_ct = 0; + +/* Static Function Declarations */ +static void mpc8xx_udc_state_transition_up (usb_device_state_t initial, +					    usb_device_state_t final); +static void mpc8xx_udc_state_transition_down (usb_device_state_t initial, +					      usb_device_state_t final); +static void mpc8xx_udc_stall (unsigned int ep); +static void mpc8xx_udc_flush_tx_fifo (int epid); +static void mpc8xx_udc_flush_rx_fifo (void); +static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp); +static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi, +				struct urb *tx_urb); +static void mpc8xx_udc_dump_request (struct usb_device_request *request); +static void mpc8xx_udc_clock_init (volatile immap_t * immr, +				   volatile cpm8xx_t * cp); +static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi); +static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp); +static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp); +static void mpc8xx_udc_cbd_init (void); +static void mpc8xx_udc_endpoint_init (void); +static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size); +static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment); +static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp); +static void mpc8xx_udc_set_nak (unsigned int ep); +static short mpc8xx_udc_handle_txerr (void); +static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid); + +/****************************************************************************** +			       Global Linkage + *****************************************************************************/ + +/* udc_init + * + * Do initial bus gluing + */ +int udc_init (void) +{ +	/* Init various pointers */ +	immr = (immap_t *) CFG_IMMR; +	cp = (cpm8xx_t *) & (immr->im_cpm); +	usb_paramp = (usb_pram_t *) & (cp->cp_dparam[PROFF_USB]); +	usbp = (usb_t *) & (cp->cp_scc[0]); + +	memset (ep_ref, 0x00, (sizeof (struct mpc8xx_ep) * MAX_ENDPOINTS)); + +	udc_device = 0; +	udc_state = STATE_NOT_READY; + +	usbp->usmod = 0x00; +	usbp->uscom = 0; + +	/* Set USB Frame #0, Respond at Address & Get a clock source  */ +	usbp->usaddr = 0x00; +	mpc8xx_udc_clock_init (immr, cp); + +	/* PA15, PA14 as perhiperal USBRXD and USBOE */ +	immr->im_ioport.iop_padir &= ~0x0003; +	immr->im_ioport.iop_papar |= 0x0003; + +	/* PC11/PC10 as peripheral USBRXP USBRXN */ +	immr->im_ioport.iop_pcso |= 0x0030; + +	/* PC7/PC6 as perhiperal USBTXP and USBTXN */ +	immr->im_ioport.iop_pcdir |= 0x0300; +	immr->im_ioport.iop_pcpar |= 0x0300; + +	/* Set the base address */ +	address_base = (u32) (cp->cp_dpmem + CPM_USB_BASE); + +	/* Initialise endpoints and circular buffers */ +	mpc8xx_udc_endpoint_init (); +	mpc8xx_udc_cbd_init (); + +	/* Assign allocated Dual Port Endpoint descriptors */ +	usb_paramp->ep0ptr = (u32) endpoints[0]; +	usb_paramp->ep1ptr = (u32) endpoints[1]; +	usb_paramp->ep2ptr = (u32) endpoints[2]; +	usb_paramp->ep3ptr = (u32) endpoints[3]; +	usb_paramp->frame_n = 0; + +	DBG ("ep0ptr=0x%08x ep1ptr=0x%08x ep2ptr=0x%08x ep3ptr=0x%08x\n", +	     usb_paramp->ep0ptr, usb_paramp->ep1ptr, usb_paramp->ep2ptr, +	     usb_paramp->ep3ptr); + +	return 0; +} + +/* udc_irq + * + * Poll for whatever events may have occured + */ +void udc_irq (void) +{ +	int epid = 0; +	volatile cbd_t *rx_cbdp = 0; +	volatile cbd_t *rx_cbdp_base = 0; + +	if (udc_state != STATE_READY) { +		return; +	} + +	if (usbp->usber & USB_E_BSY) { +		/* This shouldn't happen. If it does then it's a bug ! */ +		usbp->usber |= USB_E_BSY; +		mpc8xx_udc_flush_rx_fifo (); +	} + +	/* Scan all RX/Bidirectional Endpoints for RX data. */ +	for (epid = 0; epid < MAX_ENDPOINTS; epid++) { +		if (!ep_ref[epid].prx) { +			continue; +		} +		rx_cbdp = rx_cbdp_base = ep_ref[epid].prx; + +		do { +			if (!(rx_cbdp->cbd_sc & RX_BD_E)) { + +				if (rx_cbdp->cbd_sc & 0x1F) { +					/* Corrupt data discard it. +					 * Controller has NAK'd this packet. +					 */ +					mpc8xx_udc_clear_rxbd (rx_cbdp); + +				} else { +					if (!epid) { +						mpc8xx_udc_ep0_rx (rx_cbdp); + +					} else { +						/* Process data */ +						mpc8xx_udc_set_nak (epid); +						mpc8xx_udc_epn_rx (epid, rx_cbdp); +						mpc8xx_udc_clear_rxbd (rx_cbdp); +					} +				} + +				/* Advance RX CBD pointer */ +				mpc8xx_udc_advance_rx (&rx_cbdp, epid); +				ep_ref[epid].prx = rx_cbdp; +			} else { +				/* Advance RX CBD pointer */ +				mpc8xx_udc_advance_rx (&rx_cbdp, epid); +			} + +		} while (rx_cbdp != rx_cbdp_base); +	} + +	/* Handle TX events as appropiate, the correct place to do this is +	 * in a tx routine. Perhaps TX on epn was pre-empted by ep0 +	 */ + +	if (usbp->usber & USB_E_TXB) { +		usbp->usber |= USB_E_TXB; +	} + +	if (usbp->usber & (USB_TX_ERRMASK)) { +		mpc8xx_udc_handle_txerr (); +	} + +	/* Switch to the default state, respond at the default address */ +	if (usbp->usber & USB_E_RESET) { +		usbp->usber |= USB_E_RESET; +		usbp->usaddr = 0x00; +		udc_device->device_state = STATE_DEFAULT; +	} + +	/* if(usbp->usber&USB_E_IDLE){ +	   We could suspend here ! +	   usbp->usber|=USB_E_IDLE; +	   DBG("idle state change\n"); +	   } +	   if(usbp->usbs){ +	   We could resume here when IDLE is deasserted ! +	   Not worth doing, so long as we are self powered though. +	   } +	*/ + +	return; +} + +/* udc_endpoint_write + * + * Write some data to an endpoint + */ +int udc_endpoint_write (struct usb_endpoint_instance *epi) +{ +	int ep = 0; +	short epid = 1, unnak = 0, ret = 0; + +	if (udc_state != STATE_READY) { +		ERR ("invalid udc_state != STATE_READY!\n"); +		return -1; +	} + +	if (!udc_device || !epi) { +		return -1; +	} + +	if (udc_device->device_state != STATE_CONFIGURED) { +		return -1; +	} + +	ep = epi->endpoint_address & 0x03; +	if (ep >= MAX_ENDPOINTS) { +		return -1; +	} + +	/* Set NAK for all RX endpoints during TX */ +	for (epid = 1; epid < MAX_ENDPOINTS; epid++) { + +		/* Don't set NAK on DATA IN/CONTROL endpoints */ +		if (ep_ref[epid].sc & USB_DIR_IN) { +			continue; +		} + +		if (!(usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK))) { +			unnak |= 1 << epid; +		} + +		mpc8xx_udc_set_nak (epid); +	} + +	mpc8xx_udc_init_tx (&udc_device->bus->endpoint_array[ep], +			    epi->tx_urb); +	ret = mpc8xx_udc_ep_tx (&udc_device->bus->endpoint_array[ep]); + +	/* Remove temporary NAK */ +	for (epid = 1; epid < MAX_ENDPOINTS; epid++) { +		if (unnak & (1 << epid)) { +			udc_unset_nak (epid); +		} +	} + +	return ret; +} + +/* mpc8xx_udc_assign_urb + * + * Associate a given urb to an endpoint TX or RX transmit/receive buffers + */ +static int mpc8xx_udc_assign_urb (int ep, char direction) +{ +	struct usb_endpoint_instance *epi = 0; + +	if (ep >= MAX_ENDPOINTS) { +		goto err; +	} +	epi = &udc_device->bus->endpoint_array[ep]; +	if (!epi) { +		goto err; +	} + +	if (!ep_ref[ep].urb) { +		ep_ref[ep].urb = usbd_alloc_urb (udc_device, udc_device->bus->endpoint_array); +		if (!ep_ref[ep].urb) { +			goto err; +		} +	} else { +		ep_ref[ep].urb->actual_length = 0; +	} + +	switch (direction) { +	case USB_DIR_IN: +		epi->tx_urb = ep_ref[ep].urb; +		break; +	case USB_DIR_OUT: +		epi->rcv_urb = ep_ref[ep].urb; +		break; +	default: +		goto err; +	} +	return 0; + +      err: +	udc_state = STATE_ERROR; +	return -1; +} + +/* udc_setup_ep + * + * Associate U-Boot software endpoints to mpc8xx endpoint parameter ram + * Isochronous endpoints aren't yet supported! + */ +void udc_setup_ep (struct usb_device_instance *device, unsigned int ep, +		   struct usb_endpoint_instance *epi) +{ +	uchar direction = 0; +	int ep_attrib = 0; + +	if (epi && (ep < MAX_ENDPOINTS)) { + +		if (ep == 0) { +			if (epi->rcv_attributes != USB_ENDPOINT_XFER_CONTROL +			    || epi->tx_attributes != +			    USB_ENDPOINT_XFER_CONTROL) { + +				/* ep0 must be a control endpoint */ +				udc_state = STATE_ERROR; +				return; + +			} +			if (!(ep_ref[ep].sc & EP_ATTACHED)) { +				mpc8xx_udc_cbd_attach (ep, epi->tx_packetSize, +						       epi->rcv_packetSize); +			} +			usbp->usep[ep] = 0x0000; +			return; +		} + +		if ((epi->endpoint_address & USB_ENDPOINT_DIR_MASK) +		    == USB_DIR_IN) { + +			direction = 1; +			ep_attrib = epi->tx_attributes; +			epi->rcv_packetSize = 0; +			ep_ref[ep].sc |= USB_DIR_IN; +		} else { + +			direction = 0; +			ep_attrib = epi->rcv_attributes; +			epi->tx_packetSize = 0; +			ep_ref[ep].sc &= ~USB_DIR_IN; +		} + +		if (mpc8xx_udc_assign_urb (ep, epi->endpoint_address +					   & USB_ENDPOINT_DIR_MASK)) { +			return; +		} + +		switch (ep_attrib) { +		case USB_ENDPOINT_XFER_CONTROL: +			if (!(ep_ref[ep].sc & EP_ATTACHED)) { +				mpc8xx_udc_cbd_attach (ep, +						       epi->tx_packetSize, +						       epi->rcv_packetSize); +			} +			usbp->usep[ep] = ep << 12; +			epi->rcv_urb = epi->tx_urb = ep_ref[ep].urb; + +			break; +		case USB_ENDPOINT_XFER_BULK: +		case USB_ENDPOINT_XFER_INT: +			if (!(ep_ref[ep].sc & EP_ATTACHED)) { +				if (direction) { +					mpc8xx_udc_cbd_attach (ep, +							       epi->tx_packetSize, +							       0); +				} else { +					mpc8xx_udc_cbd_attach (ep, +							       0, +							       epi->rcv_packetSize); +				} +			} +			usbp->usep[ep] = (ep << 12) | ((ep_attrib) << 8); + +			break; +		case USB_ENDPOINT_XFER_ISOC: +		default: +			serial_printf ("Error endpoint attrib %d>3\n", ep_attrib); +			udc_state = STATE_ERROR; +			break; +		} +	} + +} + +/* udc_connect + * + * Move state, switch on the USB + */ +void udc_connect (void) +{ +	/* Enable pull-up resistor on D+ +	 * TODO: fit a pull-up resistor to drive SE0 for > 2.5us +	 */ + +	if (udc_state != STATE_ERROR) { +		udc_state = STATE_READY; +		usbp->usmod |= USMOD_EN; +	} +} + +/* udc_disconnect + * + * Disconnect is not used but, is included for completeness + */ +void udc_disconnect (void) +{ +	/* Disable pull-up resistor on D- +	 * TODO: fix a pullup resistor to control this +	 */ + +	if (udc_state != STATE_ERROR) { +		udc_state = STATE_NOT_READY; +	} +	usbp->usmod &= ~USMOD_EN; +} + +/* udc_enable + * + * Grab an EP0 URB, register interest in a subset of USB events + */ +void udc_enable (struct usb_device_instance *device) +{ +	if (udc_state == STATE_ERROR) { +		return; +	} + +	udc_device = device; + +	if (!ep_ref[0].urb) { +		ep_ref[0].urb = usbd_alloc_urb (device, device->bus->endpoint_array); +	} + +	/* Register interest in all events except SOF, enable transceiver */ +	usbp->usber = 0x03FF; +	usbp->usbmr = 0x02F7; + +	return; +} + +/* udc_disable + * + * disable the currently hooked device + */ +void udc_disable (void) +{ +	int i = 0; + +	if (udc_state == STATE_ERROR) { +		DBG ("Won't disable UDC. udc_state==STATE_ERROR !\n"); +		return; +	} + +	udc_device = 0; + +	for (; i < MAX_ENDPOINTS; i++) { +		if (ep_ref[i].urb) { +			usbd_dealloc_urb (ep_ref[i].urb); +			ep_ref[i].urb = 0; +		} +	} + +	usbp->usbmr = 0x00; +	usbp->usmod = ~USMOD_EN; +	udc_state = STATE_NOT_READY; +} + +/* udc_startup_events + * + * Enable the specified device + */ +void udc_startup_events (struct usb_device_instance *device) +{ +	udc_enable (device); +	if (udc_state == STATE_READY) { +		usbd_device_event_irq (device, DEVICE_CREATE, 0); +	} +} + +/* udc_set_nak + * + * Allow upper layers to signal lower layers should not accept more RX data + * + */ +void udc_set_nak (int epid) +{ +	if (epid) { +		mpc8xx_udc_set_nak (epid); +	} +} + +/* udc_unset_nak + * + * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint. + * Switch off NAKing on this endpoint to accept more data output from host. + * + */ +void udc_unset_nak (int epid) +{ +	if (epid > MAX_ENDPOINTS) { +		return; +	} + +	if (usbp->usep[epid] & (USEP_THS_NAK | USEP_RHS_NAK)) { +		usbp->usep[epid] &= ~(USEP_THS_NAK | USEP_RHS_NAK); +		__asm__ ("eieio"); +	} +} + +/****************************************************************************** +			      Static Linkage +******************************************************************************/ + +/* udc_state_transition_up + * udc_state_transition_down + * + * Helper functions to implement device state changes.	The device states and + * the events that transition between them are: + * + *				STATE_ATTACHED + *				||	/\ + *				\/	|| + *	DEVICE_HUB_CONFIGURED			DEVICE_HUB_RESET + *				||	/\ + *				\/	|| + *				STATE_POWERED + *				||	/\ + *				\/	|| + *	DEVICE_RESET				DEVICE_POWER_INTERRUPTION + *				||	/\ + *				\/	|| + *				STATE_DEFAULT + *				||	/\ + *				\/	|| + *	DEVICE_ADDRESS_ASSIGNED			DEVICE_RESET + *				||	/\ + *				\/	|| + *				STATE_ADDRESSED + *				||	/\ + *				\/	|| + *	DEVICE_CONFIGURED			DEVICE_DE_CONFIGURED + *				||	/\ + *				\/	|| + *				STATE_CONFIGURED + * + * udc_state_transition_up transitions up (in the direction from STATE_ATTACHED + * to STATE_CONFIGURED) from the specified initial state to the specified final + * state, passing through each intermediate state on the way.  If the initial + * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then + * no state transitions will take place. + * + * udc_state_transition_down transitions down (in the direction from + * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the + * specified final state, passing through each intermediate state on the way. + * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final + * state, then no state transitions will take place. + * + */ + +static void mpc8xx_udc_state_transition_up (usb_device_state_t initial, +					    usb_device_state_t final) +{ +	if (initial < final) { +		switch (initial) { +		case STATE_ATTACHED: +			usbd_device_event_irq (udc_device, +					       DEVICE_HUB_CONFIGURED, 0); +			if (final == STATE_POWERED) +				break; +		case STATE_POWERED: +			usbd_device_event_irq (udc_device, DEVICE_RESET, 0); +			if (final == STATE_DEFAULT) +				break; +		case STATE_DEFAULT: +			usbd_device_event_irq (udc_device, +					       DEVICE_ADDRESS_ASSIGNED, 0); +			if (final == STATE_ADDRESSED) +				break; +		case STATE_ADDRESSED: +			usbd_device_event_irq (udc_device, DEVICE_CONFIGURED, +					       0); +		case STATE_CONFIGURED: +			break; +		default: +			break; +		} +	} +} + +static void mpc8xx_udc_state_transition_down (usb_device_state_t initial, +					      usb_device_state_t final) +{ +	if (initial > final) { +		switch (initial) { +		case STATE_CONFIGURED: +			usbd_device_event_irq (udc_device, +					       DEVICE_DE_CONFIGURED, 0); +			if (final == STATE_ADDRESSED) +				break; +		case STATE_ADDRESSED: +			usbd_device_event_irq (udc_device, DEVICE_RESET, 0); +			if (final == STATE_DEFAULT) +				break; +		case STATE_DEFAULT: +			usbd_device_event_irq (udc_device, +					       DEVICE_POWER_INTERRUPTION, 0); +			if (final == STATE_POWERED) +				break; +		case STATE_POWERED: +			usbd_device_event_irq (udc_device, DEVICE_HUB_RESET, +					       0); +		case STATE_ATTACHED: +			break; +		default: +			break; +		} +	} +} + +/* mpc8xx_udc_stall + * + * Force returning of STALL tokens on the given endpoint. Protocol or function + * STALL conditions are permissable here + */ +static void mpc8xx_udc_stall (unsigned int ep) +{ +	usbp->usep[ep] |= STALL_BITMASK; +} + +/* mpc8xx_udc_set_nak + * + * Force returning of NAK responses for the given endpoint as a kind of very + * simple flow control + */ +static void mpc8xx_udc_set_nak (unsigned int ep) +{ +	usbp->usep[ep] |= NAK_BITMASK; +	__asm__ ("eieio"); +} + +/* mpc8xx_udc_handle_txerr + * + * Handle errors relevant to TX. Return a status code to allow calling + * indicative of what if anything happened + */ +static short mpc8xx_udc_handle_txerr () +{ +	short ep = 0, ret = 0; + +	for (; ep < TX_RING_SIZE; ep++) { +		if (usbp->usber & (0x10 << ep)) { + +			/* Timeout or underrun */ +			if (tx_cbd[ep]->cbd_sc & 0x06) { +				ret = 1; +				mpc8xx_udc_flush_tx_fifo (ep); + +			} else { +				if (usbp->usep[ep] & STALL_BITMASK) { +					if (!ep) { +						usbp->usep[ep] &= ~STALL_BITMASK; +					} +				}	/* else NAK */ +			} +			usbp->usber |= (0x10 << ep); +		} +	} +	return ret; +} + +/* mpc8xx_udc_advance_rx + * + * Advance cbd rx + */ +static void mpc8xx_udc_advance_rx (volatile cbd_t ** rx_cbdp, int epid) +{ +	if ((*rx_cbdp)->cbd_sc & RX_BD_W) { +		*rx_cbdp = (volatile cbd_t *) (endpoints[epid]->rbase + CFG_IMMR); + +	} else { +		(*rx_cbdp)++; +	} +} + + +/* mpc8xx_udc_flush_tx_fifo + * + * Flush a given TX fifo. Assumes one tx cbd per endpoint + */ +static void mpc8xx_udc_flush_tx_fifo (int epid) +{ +	volatile cbd_t *tx_cbdp = 0; + +	if (epid > MAX_ENDPOINTS) { +		return; +	} + +	/* TX stop */ +	immr->im_cpm.cp_cpcr = ((epid << 2) | 0x1D01); +	__asm__ ("eieio"); +	while (immr->im_cpm.cp_cpcr & 0x01); + +	usbp->uscom = 0x40 | 0; + +	/* reset ring */ +	tx_cbdp = (cbd_t *) (endpoints[epid]->tbptr + CFG_IMMR); +	tx_cbdp->cbd_sc = (TX_BD_I | TX_BD_W); + + +	endpoints[epid]->tptr = endpoints[epid]->tbase; +	endpoints[epid]->tstate = 0x00; +	endpoints[epid]->tbcnt = 0x00; + +	/* TX start */ +	immr->im_cpm.cp_cpcr = ((epid << 2) | 0x2D01); +	__asm__ ("eieio"); +	while (immr->im_cpm.cp_cpcr & 0x01); + +	return; +} + +/* mpc8xx_udc_flush_rx_fifo + * + * For the sake of completeness of the namespace, it seems like + * a good-design-decision (tm) to include mpc8xx_udc_flush_rx_fifo(); + * If RX_BD_E is true => a driver bug either here or in an upper layer + * not polling frequently enough. If RX_BD_E is true we have told the host + * we have accepted data but, the CPM found it had no-where to put that data + * which needless to say would be a bad thing. + */ +static void mpc8xx_udc_flush_rx_fifo () +{ +	int i = 0; + +	for (i = 0; i < RX_RING_SIZE; i++) { +		if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) { +			ERR ("buf %p used rx data len = 0x%x sc=0x%x!\n", +			     rx_cbd[i], rx_cbd[i]->cbd_datlen, +			     rx_cbd[i]->cbd_sc); + +		} +	} +	ERR ("BUG : Input over-run\n"); +} + +/* mpc8xx_udc_clear_rxbd + * + * Release control of RX CBD to CP. + */ +static void mpc8xx_udc_clear_rxbd (volatile cbd_t * rx_cbdp) +{ +	rx_cbdp->cbd_datlen = 0x0000; +	rx_cbdp->cbd_sc = ((rx_cbdp->cbd_sc & RX_BD_W) | (RX_BD_E | RX_BD_I)); +	__asm__ ("eieio"); +} + +/* mpc8xx_udc_tx_irq + * + * Parse for tx timeout, control RX or USB reset/busy conditions + * Return -1 on timeout, -2 on fatal error, else return zero + */ +static int mpc8xx_udc_tx_irq (int ep) +{ +	int i = 0; + +	if (usbp->usber & (USB_TX_ERRMASK)) { +		if (mpc8xx_udc_handle_txerr ()) { +			/* Timeout, controlling function must retry send */ +			return -1; +		} +	} + +	if (usbp->usber & (USB_E_RESET | USB_E_BSY)) { +		/* Fatal, abandon TX transaction */ +		return -2; +	} + +	if (usbp->usber & USB_E_RXB) { +		for (i = 0; i < RX_RING_SIZE; i++) { +			if (!(rx_cbd[i]->cbd_sc & RX_BD_E)) { +				if ((rx_cbd[i] == ep_ref[0].prx) || ep) { +					return -2; +				} +			} +		} +	} + +	return 0; +} + +/* mpc8xx_udc_ep_tx + * + * Transmit in a re-entrant fashion outbound USB packets. + * Implement retry/timeout mechanism described in USB specification + * Toggle DATA0/DATA1 pids as necessary + * Introduces non-standard tx_retry. The USB standard has no scope for slave + * devices to give up TX, however tx_retry stops us getting stuck in an endless + * TX loop. + */ +static int mpc8xx_udc_ep_tx (struct usb_endpoint_instance *epi) +{ +	struct urb *urb = epi->tx_urb; +	volatile cbd_t *tx_cbdp = 0; +	unsigned int ep = 0, pkt_len = 0, x = 0, tx_retry = 0; +	int ret = 0; + +	if (!epi || (epi->endpoint_address & 0x03) >= MAX_ENDPOINTS || !urb) { +		return -1; +	} + +	ep = epi->endpoint_address & 0x03; +	tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CFG_IMMR); + +	if (tx_cbdp->cbd_sc & TX_BD_R || usbp->usber & USB_E_TXB) { +		mpc8xx_udc_flush_tx_fifo (ep); +		usbp->usber |= USB_E_TXB; +	}; + +	while (tx_retry++ < 100) { +		ret = mpc8xx_udc_tx_irq (ep); +		if (ret == -1) { +			/* ignore timeout here */ +		} else if (ret == -2) { +			/* Abandon TX */ +			mpc8xx_udc_flush_tx_fifo (ep); +			return -1; +		} + +		tx_cbdp = (cbd_t *) (endpoints[ep]->tbptr + CFG_IMMR); +		while (tx_cbdp->cbd_sc & TX_BD_R) { +		}; +		tx_cbdp->cbd_sc = (tx_cbdp->cbd_sc & TX_BD_W); + +		pkt_len = urb->actual_length - epi->sent; + +		if (pkt_len > epi->tx_packetSize || pkt_len > EP_MAX_PKT) { +			pkt_len = MIN (epi->tx_packetSize, EP_MAX_PKT); +		} + +		for (x = 0; x < pkt_len; x++) { +			*((unsigned char *) (tx_cbdp->cbd_bufaddr + x)) = +				urb->buffer[epi->sent + x]; +		} +		tx_cbdp->cbd_datlen = pkt_len; +		tx_cbdp->cbd_sc |= (CBD_TX_BITMASK | ep_ref[ep].pid); +		__asm__ ("eieio"); + +#ifdef __SIMULATE_ERROR__ +		if (++err_poison_test == 2) { +			err_poison_test = 0; +			tx_cbdp->cbd_sc &= ~TX_BD_TC; +		} +#endif + +		usbp->uscom = (USCOM_STR | ep); + +		while (!(usbp->usber & USB_E_TXB)) { +			ret = mpc8xx_udc_tx_irq (ep); +			if (ret == -1) { +				/* TX timeout */ +				break; +			} else if (ret == -2) { +				if (usbp->usber & USB_E_TXB) { +					usbp->usber |= USB_E_TXB; +				} +				mpc8xx_udc_flush_tx_fifo (ep); +				return -1; +			} +		}; + +		if (usbp->usber & USB_E_TXB) { +			usbp->usber |= USB_E_TXB; +		} + +		/* ACK must be present <= 18bit times from TX */ +		if (ret == -1) { +			continue; +		} + +		/* TX ACK : USB 2.0 8.7.2, Toggle PID, Advance TX */ +		epi->sent += pkt_len; +		epi->last = MIN (urb->actual_length - epi->sent, epi->tx_packetSize); +		TOGGLE_TX_PID (ep_ref[ep].pid); + +		if (epi->sent >= epi->tx_urb->actual_length) { + +			epi->tx_urb->actual_length = 0; +			epi->sent = 0; + +			if (ep_ref[ep].sc & EP_SEND_ZLP) { +				ep_ref[ep].sc &= ~EP_SEND_ZLP; +			} else { +				return 0; +			} +		} +	} + +	ERR ("TX fail, endpoint 0x%x tx bytes 0x%x/0x%x\n", ep, epi->sent, +	     epi->tx_urb->actual_length); + +	return -1; +} + +/* mpc8xx_udc_dump_request + * + * Dump a control request to console + */ +static void mpc8xx_udc_dump_request (struct usb_device_request *request) +{ +	DBG ("bmRequestType:%02x bRequest:%02x wValue:%04x " +	     "wIndex:%04x wLength:%04x ?\n", +	     request->bmRequestType, +	     request->bRequest, +	     request->wValue, request->wIndex, request->wLength); + +	return; +} + +/* mpc8xx_udc_ep0_rx_setup + * + * Decode received ep0 SETUP packet. return non-zero on error + */ +static int mpc8xx_udc_ep0_rx_setup (volatile cbd_t * rx_cbdp) +{ +	unsigned int x = 0; +	struct urb *purb = ep_ref[0].urb; +	struct usb_endpoint_instance *epi = +		&udc_device->bus->endpoint_array[0]; + +	for (; x < rx_cbdp->cbd_datlen; x++) { +		*(((unsigned char *) &ep_ref[0].urb->device_request) + x) = +			*((unsigned char *) (rx_cbdp->cbd_bufaddr + x)); +	} + +	mpc8xx_udc_clear_rxbd (rx_cbdp); + +	if (ep0_recv_setup (purb)) { +		mpc8xx_udc_dump_request (&purb->device_request); +		return -1; +	} + +	if ((purb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) +	    == USB_REQ_HOST2DEVICE) { + +		switch (purb->device_request.bRequest) { +		case USB_REQ_SET_ADDRESS: +			/* Send the Status OUT ZLP */ +			ep_ref[0].pid = TX_BD_PID_DATA1; +			purb->actual_length = 0; +			mpc8xx_udc_init_tx (epi, purb); +			mpc8xx_udc_ep_tx (epi); + +			/* Move to the addressed state */ +			usbp->usaddr = udc_device->address; +			mpc8xx_udc_state_transition_up (udc_device->device_state, +							STATE_ADDRESSED); +			return 0; + +		case USB_REQ_SET_CONFIGURATION: +			if (!purb->device_request.wValue) { +				/* Respond at default address */ +				usbp->usaddr = 0x00; +				mpc8xx_udc_state_transition_down (udc_device->device_state, +								  STATE_ADDRESSED); +			} else { +				/* TODO: Support multiple configurations */ +				mpc8xx_udc_state_transition_up (udc_device->device_state, +								STATE_CONFIGURED); +				for (x = 1; x < MAX_ENDPOINTS; x++) { +					if ((udc_device->bus->endpoint_array[x].endpoint_address & USB_ENDPOINT_DIR_MASK) +					    == USB_DIR_IN) { +						ep_ref[x].pid = TX_BD_PID_DATA0; +					} else { +						ep_ref[x].pid = RX_BD_PID_DATA0; +					} +					/* Set configuration must unstall endpoints */ +					usbp->usep[x] &= ~STALL_BITMASK; +				} +			} +			break; +		default: +			/* CDC/Vendor specific */ +			break; +		} + +		/* Send ZLP as ACK in Status OUT phase */ +		ep_ref[0].pid = TX_BD_PID_DATA1; +		purb->actual_length = 0; +		mpc8xx_udc_init_tx (epi, purb); +		mpc8xx_udc_ep_tx (epi); + +	} else { + +		if (purb->actual_length) { +			ep_ref[0].pid = TX_BD_PID_DATA1; +			mpc8xx_udc_init_tx (epi, purb); + +			if (!(purb->actual_length % EP0_MAX_PACKET_SIZE)) { +				ep_ref[0].sc |= EP_SEND_ZLP; +			} + +			if (purb->device_request.wValue == +			    USB_DESCRIPTOR_TYPE_DEVICE) { +				if (le16_to_cpu (purb->device_request.wLength) +				    > purb->actual_length) { +					/* Send EP0_MAX_PACKET_SIZE bytes +					 * unless correct size requested. +					 */ +					if (purb->actual_length > epi->tx_packetSize) { +						purb->actual_length = epi->tx_packetSize; +					} +				} +			} +			mpc8xx_udc_ep_tx (epi); + +		} else { +			/* Corrupt SETUP packet? */ +			ERR ("Zero length data or SETUP with DATA-IN phase ?\n"); +			return 1; +		} +	} +	return 0; +} + +/* mpc8xx_udc_init_tx + * + * Setup some basic parameters for a TX transaction + */ +static void mpc8xx_udc_init_tx (struct usb_endpoint_instance *epi, +				struct urb *tx_urb) +{ +	epi->sent = 0; +	epi->last = 0; +	epi->tx_urb = tx_urb; +} + +/* mpc8xx_udc_ep0_rx + * + * Receive ep0/control USB data. Parse and possibly send a response. + */ +static void mpc8xx_udc_ep0_rx (volatile cbd_t * rx_cbdp) +{ +	if (rx_cbdp->cbd_sc & RX_BD_PID_SETUP) { + +		/* Unconditionally accept SETUP packets */ +		if (mpc8xx_udc_ep0_rx_setup (rx_cbdp)) { +			mpc8xx_udc_stall (0); +		} + +	} else { + +		mpc8xx_udc_clear_rxbd (rx_cbdp); + +		if ((rx_cbdp->cbd_datlen - 2)) { +			/* SETUP with a DATA phase +			 * outside of SETUP packet. +			 * Reply with STALL. +			 */ +			mpc8xx_udc_stall (0); +		} +	} +} + +/* mpc8xx_udc_epn_rx + * + * Receive some data from cbd into USB system urb data abstraction + * Upper layers should NAK if there is insufficient RX data space + */ +static int mpc8xx_udc_epn_rx (unsigned int epid, volatile cbd_t * rx_cbdp) +{ +	struct usb_endpoint_instance *epi = 0; +	struct urb *urb = 0; +	unsigned int x = 0; + +	if (epid >= MAX_ENDPOINTS || !rx_cbdp->cbd_datlen) { +		return 0; +	} + +	/* USB 2.0 PDF section 8.6.4 +	 * Discard data with invalid PID it is a resend. +	 */ +	if (ep_ref[epid].pid != (rx_cbdp->cbd_sc & 0xC0)) { +		return 1; +	} +	TOGGLE_RX_PID (ep_ref[epid].pid); + +	epi = &udc_device->bus->endpoint_array[epid]; +	urb = epi->rcv_urb; + +	for (; x < (rx_cbdp->cbd_datlen - 2); x++) { +		*((unsigned char *) (urb->buffer + urb->actual_length + x)) = +			*((unsigned char *) (rx_cbdp->cbd_bufaddr + x)); +	} + +	if (x) { +		usbd_rcv_complete (epi, x, 0); +		if (ep_ref[epid].urb->status == RECV_ERROR) { +			DBG ("RX error unset NAK\n"); +			udc_unset_nak (epid); +		} +	} +	return x; +} + +/* mpc8xx_udc_clock_init + * + * Obtain a clock reference for Full Speed Signaling + */ +static void mpc8xx_udc_clock_init (volatile immap_t * immr, +				   volatile cpm8xx_t * cp) +{ + +#if defined(CFG_USB_EXTC_CLK) + +	/* This has been tested with a 48MHz crystal on CLK6 */ +	switch (CFG_USB_EXTC_CLK) { +	case 1: +		immr->im_ioport.iop_papar |= 0x0100; +		immr->im_ioport.iop_padir &= ~0x0100; +		cp->cp_sicr |= 0x24; +		break; +	case 2: +		immr->im_ioport.iop_papar |= 0x0200; +		immr->im_ioport.iop_padir &= ~0x0200; +		cp->cp_sicr |= 0x2D; +		break; +	case 3: +		immr->im_ioport.iop_papar |= 0x0400; +		immr->im_ioport.iop_padir &= ~0x0400; +		cp->cp_sicr |= 0x36; +		break; +	case 4: +		immr->im_ioport.iop_papar |= 0x0800; +		immr->im_ioport.iop_padir &= ~0x0800; +		cp->cp_sicr |= 0x3F; +		break; +	default: +		udc_state = STATE_ERROR; +		break; +	} + +#elif defined(CFG_USB_BRGCLK) + +	/* This has been tested with brgclk == 50MHz */ +	DECLARE_GLOBAL_DATA_PTR; +	int divisor = 0; + +	if (gd->cpu_clk < 48000000L) { +		ERR ("brgclk is too slow for full-speed USB!\n"); +		udc_state = STATE_ERROR; +		return; +	} + +	/* Assume the brgclk is 'good enough', we want !(gd->cpu_clk%48Mhz) +	 * but, can /probably/ live with close-ish alternative rates. +	 */ +	divisor = (gd->cpu_clk / 48000000L) - 1; +	cp->cp_sicr &= ~0x0000003F; + +	switch (CFG_USB_BRGCLK) { +	case 1: +		cp->cp_brgc1 |= (divisor | CPM_BRG_EN); +		cp->cp_sicr &= ~0x2F; +		break; +	case 2: +		cp->cp_brgc2 |= (divisor | CPM_BRG_EN); +		cp->cp_sicr |= 0x00000009; +		break; +	case 3: +		cp->cp_brgc3 |= (divisor | CPM_BRG_EN); +		cp->cp_sicr |= 0x00000012; +		break; +	case 4: +		cp->cp_brgc4 = (divisor | CPM_BRG_EN); +		cp->cp_sicr |= 0x0000001B; +		break; +	default: +		udc_state = STATE_ERROR; +		break; +	} + +#else +#error "CFG_USB_EXTC_CLK or CFG_USB_BRGCLK must be defined" +#endif + +} + +/* mpc8xx_udc_cbd_attach + * + * attach a cbd to and endpoint + */ +static void mpc8xx_udc_cbd_attach (int ep, uchar tx_size, uchar rx_size) +{ + +	if (!tx_cbd[ep] || !rx_cbd[ep] || ep >= MAX_ENDPOINTS) { +		udc_state = STATE_ERROR; +		return; +	} + +	if (tx_size > USB_MAX_PKT || rx_size > USB_MAX_PKT || +	    (!tx_size && !rx_size)) { +		udc_state = STATE_ERROR; +		return; +	} + +	/* Attach CBD to appropiate Parameter RAM Endpoint data structure */ +	if (rx_size) { +		endpoints[ep]->rbase = (u32) rx_cbd[rx_ct]; +		endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct]; +		rx_ct++; + +		if (!ep) { + +			endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct]; +			rx_cbd[rx_ct]->cbd_sc |= RX_BD_W; +			rx_ct++; + +		} else { +			rx_ct += 2; +			endpoints[ep]->rbptr = (u32) rx_cbd[rx_ct]; +			rx_cbd[rx_ct]->cbd_sc |= RX_BD_W; +			rx_ct++; +		} + +		/* Where we expect to RX data on this endpoint */ +		ep_ref[ep].prx = rx_cbd[rx_ct - 1]; +	} else { + +		ep_ref[ep].prx = 0; +		endpoints[ep]->rbase = 0; +		endpoints[ep]->rbptr = 0; +	} + +	if (tx_size) { +		endpoints[ep]->tbase = (u32) tx_cbd[tx_ct]; +		endpoints[ep]->tbptr = (u32) tx_cbd[tx_ct]; +		tx_ct++; +	} else { +		endpoints[ep]->tbase = 0; +		endpoints[ep]->tbptr = 0; +	} + +	endpoints[ep]->tstate = 0; +	endpoints[ep]->tbcnt = 0; +	endpoints[ep]->mrblr = EP_MAX_PKT; +	endpoints[ep]->rfcr = 0x18; +	endpoints[ep]->tfcr = 0x18; +	ep_ref[ep].sc |= EP_ATTACHED; + +	DBG ("ep %d rbase 0x%08x rbptr 0x%08x tbase 0x%08x tbptr 0x%08x prx = %p\n", +		ep, endpoints[ep]->rbase, endpoints[ep]->rbptr, +		endpoints[ep]->tbase, endpoints[ep]->tbptr, +		ep_ref[ep].prx); + +	return; +} + +/* mpc8xx_udc_cbd_init + * + * Allocate space for a cbd and allocate TX/RX data space + */ +static void mpc8xx_udc_cbd_init (void) +{ +	int i = 0; + +	for (; i < TX_RING_SIZE; i++) { +		tx_cbd[i] = (cbd_t *) +			mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int)); +	} + +	for (i = 0; i < RX_RING_SIZE; i++) { +		rx_cbd[i] = (cbd_t *) +			mpc8xx_udc_alloc (sizeof (cbd_t), sizeof (int)); +	} + +	for (i = 0; i < TX_RING_SIZE; i++) { +		tx_cbd[i]->cbd_bufaddr = +			mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int)); + +		tx_cbd[i]->cbd_sc = (TX_BD_I | TX_BD_W); +		tx_cbd[i]->cbd_datlen = 0x0000; +	} + + +	for (i = 0; i < RX_RING_SIZE; i++) { +		rx_cbd[i]->cbd_bufaddr = +			mpc8xx_udc_alloc (EP_MAX_PKT, sizeof (int)); +		rx_cbd[i]->cbd_sc = (RX_BD_I | RX_BD_E); +		rx_cbd[i]->cbd_datlen = 0x0000; + +	} + +	return; +} + +/* mpc8xx_udc_endpoint_init + * + * Attach an endpoint to some dpram + */ +static void mpc8xx_udc_endpoint_init (void) +{ +	int i = 0; + +	for (; i < MAX_ENDPOINTS; i++) { +		endpoints[i] = (usb_epb_t *) +			mpc8xx_udc_alloc (sizeof (usb_epb_t), 32); +	} +} + +/* mpc8xx_udc_alloc + * + * Grab the address of some dpram + */ +static u32 mpc8xx_udc_alloc (u32 data_size, u32 alignment) +{ +	u32 retaddr = address_base; + +	while (retaddr % alignment) { +		retaddr++; +	} +	address_base += data_size; + +	return retaddr; +} + +#endif /* CONFIG_MPC885_FAMILY && CONFIG_USB_DEVICE) */ diff --git a/drivers/usbdcore_omap1510.c b/drivers/usbdcore_omap1510.c index 1d54a6357..84bb936d8 100644 --- a/drivers/usbdcore_omap1510.c +++ b/drivers/usbdcore_omap1510.c @@ -1517,4 +1517,31 @@ void udc_startup_events (struct usb_device_instance *device)  	udc_enable (device);  } +/** + * udc_irq - do pseudo interrupts + */ +void udc_irq(void) +{ +	/* Loop while we have interrupts. +	 * If we don't do this, the input chain +	 * polling delay is likely to miss +	 * host requests. +	 */ +	while (inw (UDC_IRQ_SRC) & ~UDC_SOF_Flg) { +		/* Handle any new IRQs */ +		omap1510_udc_irq (); +		omap1510_udc_noniso_irq (); +	} +} + +/* Flow control */ +void udc_set_nak(int epid) +{ +	/* TODO: implement this functionality in omap1510 */ +} + +void udc_unset_nak (int epid) +{ +	/* TODO: implement this functionality in omap1510 */ +}  #endif diff --git a/drivers/usbtty.c b/drivers/usbtty.c index ce4a12e16..a3b50131d 100644 --- a/drivers/usbtty.c +++ b/drivers/usbtty.c @@ -2,6 +2,9 @@   * (C) Copyright 2003   * Gerry Hamel, geh@ti.com, Texas Instruments   * + * (C) Copyright 2006 + * Bryan O'Donoghue, bodonoghue@codehermit.ie + *   * 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 @@ -25,20 +28,42 @@  #include <circbuf.h>  #include <devices.h>  #include "usbtty.h" +#include "usb_cdc_acm.h" +#include "usbdescriptors.h" +#include <config.h>		/* If defined, override Linux identifiers with +			   	 * vendor specific ones */  #if 0 -#define TTYDBG(fmt,args...) serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args) +#define TTYDBG(fmt,args...)\ +	serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)  #else  #define TTYDBG(fmt,args...) do{}while(0)  #endif -#if 0 -#define TTYERR(fmt,args...) serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args) +#if 1 +#define TTYERR(fmt,args...)\ +	serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\ +	__LINE__,##args)  #else  #define TTYERR(fmt,args...) do{}while(0)  #endif  /* + * Defines + */ +#define NUM_CONFIGS    1 +#define MAX_INTERFACES 2 +#define NUM_ENDPOINTS  3 +#define ACM_TX_ENDPOINT 3 +#define ACM_RX_ENDPOINT 2 +#define GSERIAL_TX_ENDPOINT 2 +#define GSERIAL_RX_ENDPOINT 1 +#define NUM_ACM_INTERFACES 2 +#define NUM_GSERIAL_INTERFACES 1 +#define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface" +#define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface" + +/*   * Buffers to hold input and output data   */  #define USBTTY_BUFFER_SIZE 256 @@ -50,157 +75,336 @@ static circbuf_t usbtty_output;   * Instance variables   */  static device_t usbttydev; -static struct usb_device_instance	 device_instance[1]; -static struct usb_bus_instance		 bus_instance[1]; +static struct usb_device_instance device_instance[1]; +static struct usb_bus_instance bus_instance[1];  static struct usb_configuration_instance config_instance[NUM_CONFIGS]; -static struct usb_interface_instance	 interface_instance[NUM_INTERFACES]; -static struct usb_alternate_instance	 alternate_instance[NUM_INTERFACES]; -static struct usb_endpoint_instance	 endpoint_instance[NUM_ENDPOINTS+1]; /* one extra for control endpoint */ - -/* - * Static allocation of urbs - */ -#define RECV_ENDPOINT 1 -#define TX_ENDPOINT 2 +static struct usb_interface_instance interface_instance[MAX_INTERFACES]; +static struct usb_alternate_instance alternate_instance[MAX_INTERFACES]; +/* one extra for control endpoint */ +static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1];  /*   * Global flag   */  int usbtty_configured_flag = 0; -  /*   * Serial number   */  static char serial_number[16]; +  /* - * Descriptors + * Descriptors, Strings, Local variables.   */ + +/* defined and used by usbdcore_ep0.c */ +extern struct usb_string_descriptor **usb_strings; + +/* Indicies, References */ +static unsigned short rx_endpoint = 0; +static unsigned short tx_endpoint = 0; +static unsigned short interface_count = 0; +static struct usb_string_descriptor *usbtty_string_table[STR_COUNT]; + +/* USB Descriptor Strings */  static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4};  static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];  static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)];  static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)];  static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)]; -static u8 wstrInterface[2 + 2*(sizeof(CONFIG_USBD_INTERFACE_STR)-1)]; - -static struct usb_string_descriptor *usbtty_string_table[] = { -  (struct usb_string_descriptor*)wstrLang, -  (struct usb_string_descriptor*)wstrManufacturer, -  (struct usb_string_descriptor*)wstrProduct, -  (struct usb_string_descriptor*)wstrSerial, -  (struct usb_string_descriptor*)wstrConfiguration, -  (struct usb_string_descriptor*)wstrInterface -}; -extern struct usb_string_descriptor **usb_strings; /* defined and used by omap1510_ep0.c */ +static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)]; +static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)]; +/* Standard USB Data Structures */ +static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES]; +static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS]; +static struct usb_configuration_descriptor	*configuration_descriptor = 0;  static struct usb_device_descriptor device_descriptor = { -  bLength:	      sizeof(struct usb_device_descriptor), -  bDescriptorType:    USB_DT_DEVICE, -  bcdUSB:	      USB_BCD_VERSION, -  bDeviceClass:	      USBTTY_DEVICE_CLASS, -  bDeviceSubClass:    USBTTY_DEVICE_SUBCLASS, -  bDeviceProtocol:    USBTTY_DEVICE_PROTOCOL, -  bMaxPacketSize0:    EP0_MAX_PACKET_SIZE, -  idVendor:	      CONFIG_USBD_VENDORID, -  idProduct:	      CONFIG_USBD_PRODUCTID, -  bcdDevice:	      USBTTY_BCD_DEVICE, -  iManufacturer:      STR_MANUFACTURER, -  iProduct:	      STR_PRODUCT, -  iSerialNumber:      STR_SERIAL, -  bNumConfigurations: NUM_CONFIGS -  }; -static struct usb_configuration_descriptor config_descriptors[NUM_CONFIGS] = { -  { -    bLength:		 sizeof(struct usb_configuration_descriptor), -    bDescriptorType:	 USB_DT_CONFIG, -    wTotalLength:	 (sizeof(struct usb_configuration_descriptor)*NUM_CONFIGS) + -			 (sizeof(struct usb_interface_descriptor)*NUM_INTERFACES) + -			 (sizeof(struct usb_endpoint_descriptor)*NUM_ENDPOINTS), -    bNumInterfaces:	 NUM_INTERFACES, -    bConfigurationValue: 1, -    iConfiguration:	 STR_CONFIG, -    bmAttributes:	 BMATTRIBUTE_SELF_POWERED | BMATTRIBUTE_RESERVED, -    bMaxPower:		 USBTTY_MAXPOWER -  }, +	.bLength = sizeof(struct usb_device_descriptor), +	.bDescriptorType =	USB_DT_DEVICE, +	.bcdUSB = 		cpu_to_le16(USB_BCD_VERSION), +	.bDeviceSubClass =	0x00, +	.bDeviceProtocol =	0x00, +	.bMaxPacketSize0 =	EP0_MAX_PACKET_SIZE, +	.idVendor =		cpu_to_le16(CONFIG_USBD_VENDORID), +	.bcdDevice =		cpu_to_le16(USBTTY_BCD_DEVICE), +	.iManufacturer =	STR_MANUFACTURER, +	.iProduct =		STR_PRODUCT, +	.iSerialNumber =	STR_SERIAL, +	.bNumConfigurations =	NUM_CONFIGS  }; -static struct usb_interface_descriptor interface_descriptors[NUM_INTERFACES] = { -  { -    bLength:		 sizeof(struct usb_interface_descriptor), -    bDescriptorType:	 USB_DT_INTERFACE, -    bInterfaceNumber:	 0, -    bAlternateSetting:	 0, -    bNumEndpoints:	 NUM_ENDPOINTS, -    bInterfaceClass:	 USBTTY_INTERFACE_CLASS, -    bInterfaceSubClass:	 USBTTY_INTERFACE_SUBCLASS, -    bInterfaceProtocol:	 USBTTY_INTERFACE_PROTOCOL, -    iInterface:		 STR_INTERFACE -  }, -}; -static struct usb_endpoint_descriptor ep_descriptors[NUM_ENDPOINTS] = { -  { -    bLength:		 sizeof(struct usb_endpoint_descriptor), -    bDescriptorType:	 USB_DT_ENDPOINT, -    bEndpointAddress:	 CONFIG_USBD_SERIAL_OUT_ENDPOINT | USB_DIR_OUT, -    bmAttributes:	 USB_ENDPOINT_XFER_BULK, -    wMaxPacketSize:	 CONFIG_USBD_SERIAL_OUT_PKTSIZE, -    bInterval:		 0 -  }, -  { -    bLength:		 sizeof(struct usb_endpoint_descriptor), -    bDescriptorType:	 USB_DT_ENDPOINT, -    bEndpointAddress:	 CONFIG_USBD_SERIAL_IN_ENDPOINT | USB_DIR_IN, -    bmAttributes:	 USB_ENDPOINT_XFER_BULK, -    wMaxPacketSize:	 CONFIG_USBD_SERIAL_IN_PKTSIZE, -    bInterval:		 0 -  }, -  { -    bLength:		 sizeof(struct usb_endpoint_descriptor), -    bDescriptorType:	 USB_DT_ENDPOINT, -    bEndpointAddress:	 CONFIG_USBD_SERIAL_INT_ENDPOINT | USB_DIR_IN, -    bmAttributes:	 USB_ENDPOINT_XFER_INT, -    wMaxPacketSize:	 CONFIG_USBD_SERIAL_INT_PKTSIZE, -    bInterval:		 0 -  }, + + +/* + * Static CDC ACM specific descriptors + */ + +struct acm_config_desc { +	struct usb_configuration_descriptor configuration_desc; + +	/* Master Interface */ +	struct usb_interface_descriptor interface_desc; + +	struct usb_class_header_function_descriptor usb_class_header; +	struct usb_class_call_management_descriptor usb_class_call_mgt; +	struct usb_class_abstract_control_descriptor usb_class_acm; +	struct usb_class_union_function_descriptor usb_class_union; +	struct usb_endpoint_descriptor notification_endpoint; + +	/* Slave Interface */ +	struct usb_interface_descriptor data_class_interface; +	struct usb_endpoint_descriptor +		data_endpoints[NUM_ENDPOINTS-1] __attribute__((packed)); +} __attribute__((packed)); + +static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = { +	{ +		.configuration_desc ={ +			.bLength = +				sizeof(struct usb_configuration_descriptor), +    			.bDescriptorType = USB_DT_CONFIG, +			.wTotalLength = +				cpu_to_le16(sizeof(struct acm_config_desc)), +	    		.bNumInterfaces = NUM_ACM_INTERFACES, +    			.bConfigurationValue = 1, +			.iConfiguration = STR_CONFIG, +			.bmAttributes = +				BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, +			.bMaxPower = USBTTY_MAXPOWER +		}, +		/* Interface 1 */ +		.interface_desc = { +			.bLength  = sizeof(struct usb_interface_descriptor), +			.bDescriptorType = USB_DT_INTERFACE, +			.bInterfaceNumber = 0, +			.bAlternateSetting = 0, +			.bNumEndpoints = 0x01, +			.bInterfaceClass = +				COMMUNICATIONS_INTERFACE_CLASS_CONTROL, +			.bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS, +			.bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL, +			.iInterface = STR_CTRL_INTERFACE, +		}, +		.usb_class_header = { +			.bFunctionLength	= +				sizeof(struct usb_class_header_function_descriptor), +			.bDescriptorType	= CS_INTERFACE, +			.bDescriptorSubtype	= USB_ST_HEADER, +			.bcdCDC	= cpu_to_le16(110), +		}, +		.usb_class_call_mgt = { +			.bFunctionLength	= +				sizeof(struct usb_class_call_management_descriptor), +			.bDescriptorType	= CS_INTERFACE, +			.bDescriptorSubtype	= USB_ST_CMF, +			.bmCapabilities		= 0x00, +			.bDataInterface		= 0x01, +		}, +		.usb_class_acm = { +			.bFunctionLength	= +				sizeof(struct usb_class_abstract_control_descriptor), +			.bDescriptorType	= CS_INTERFACE, +			.bDescriptorSubtype	= USB_ST_ACMF, +			.bmCapabilities		= 0x00, +		}, +		.usb_class_union = { +			.bFunctionLength	= +				sizeof(struct usb_class_union_function_descriptor), +			.bDescriptorType	= CS_INTERFACE, +			.bDescriptorSubtype	= USB_ST_UF, +			.bMasterInterface	= 0x00, +			.bSlaveInterface0	= 0x01, +		}, +		.notification_endpoint = { +			.bLength = +				sizeof(struct usb_endpoint_descriptor), +			.bDescriptorType	= USB_DT_ENDPOINT, +			.bEndpointAddress	= 0x01 | USB_DIR_IN, +			.bmAttributes		= USB_ENDPOINT_XFER_INT, +			.wMaxPacketSize +				= cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE), +			.bInterval		= 0xFF, +		}, + +		/* Interface 2 */ +		.data_class_interface = { +			.bLength		= +				sizeof(struct usb_interface_descriptor), +			.bDescriptorType	= USB_DT_INTERFACE, +			.bInterfaceNumber	= 0x01, +			.bAlternateSetting	= 0x00, +			.bNumEndpoints		= 0x02, +			.bInterfaceClass	= +				COMMUNICATIONS_INTERFACE_CLASS_DATA, +			.bInterfaceSubClass	= DATA_INTERFACE_SUBCLASS_NONE, +			.bInterfaceProtocol	= DATA_INTERFACE_PROTOCOL_NONE, +			.iInterface		= STR_DATA_INTERFACE, +		}, +		.data_endpoints = { +			{ +				.bLength		= +					sizeof(struct usb_endpoint_descriptor), +				.bDescriptorType	= USB_DT_ENDPOINT, +				.bEndpointAddress	= 0x02 | USB_DIR_OUT, +				.bmAttributes		= +					USB_ENDPOINT_XFER_BULK, +				.wMaxPacketSize		= +					cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE), +				.bInterval		= 0xFF, +			}, +			{ +				.bLength		= +					sizeof(struct usb_endpoint_descriptor), +				.bDescriptorType	= USB_DT_ENDPOINT, +				.bEndpointAddress	= 0x03 | USB_DIR_IN, +				.bmAttributes		= +					USB_ENDPOINT_XFER_BULK, +				.wMaxPacketSize		= +					cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE), +				.bInterval		= 0xFF, +			}, +		}, +	},  }; -static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS] = { -  &(ep_descriptors[0]), -  &(ep_descriptors[1]), -  &(ep_descriptors[2]), + +static struct rs232_emu rs232_desc={ +		.dter 		=  	115200, +	   	.stop_bits	=	0x00, +	   	.parity		=	0x00, +		.data_bits	=	0x08  }; -/* utility function for converting char* to wide string used by USB */ -static void str2wide (char *str, u16 * wide) -{ -	int i; -	for (i = 0; i < strlen (str) && str[i]; i++) -		wide[i] = (u16) str[i]; -} +/* + * Static Generic Serial specific data + */ + + +struct gserial_config_desc { + +	struct usb_configuration_descriptor configuration_desc; +	struct usb_interface_descriptor +		interface_desc[NUM_GSERIAL_INTERFACES] __attribute__((packed)); +	struct usb_endpoint_descriptor +		data_endpoints[NUM_ENDPOINTS] __attribute__((packed)); + +} __attribute__((packed)); + +static struct gserial_config_desc +gserial_configuration_descriptors[NUM_CONFIGS] ={ +	{ +		.configuration_desc ={ +			.bLength = sizeof(struct usb_configuration_descriptor), +			.bDescriptorType = USB_DT_CONFIG, +			.wTotalLength = +				cpu_to_le16(sizeof(struct gserial_config_desc)), +			.bNumInterfaces = NUM_GSERIAL_INTERFACES, +			.bConfigurationValue = 1, +			.iConfiguration = STR_CONFIG, +			.bmAttributes = +				BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, +			.bMaxPower = USBTTY_MAXPOWER +		}, +		.interface_desc = { +			{ +				.bLength  = +					sizeof(struct usb_interface_descriptor), +				.bDescriptorType = USB_DT_INTERFACE, +				.bInterfaceNumber = 0, +				.bAlternateSetting = 0, +				.bNumEndpoints = NUM_ENDPOINTS, +				.bInterfaceClass = +					COMMUNICATIONS_INTERFACE_CLASS_VENDOR, +				.bInterfaceSubClass = +					COMMUNICATIONS_NO_SUBCLASS, +				.bInterfaceProtocol = +					COMMUNICATIONS_NO_PROTOCOL, +				.iInterface = STR_DATA_INTERFACE +			}, +  		}, +		.data_endpoints  = { +			{ +				.bLength = +					sizeof(struct usb_endpoint_descriptor), +				.bDescriptorType =	USB_DT_ENDPOINT, +				.bEndpointAddress =	0x01 | USB_DIR_OUT, +				.bmAttributes =		USB_ENDPOINT_XFER_BULK, +				.wMaxPacketSize = +					cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE), +				.bInterval=		0xFF, +			}, +			{ +				.bLength = +					sizeof(struct usb_endpoint_descriptor), +				.bDescriptorType =	USB_DT_ENDPOINT, +				.bEndpointAddress =	0x02 | USB_DIR_IN, +				.bmAttributes =		USB_ENDPOINT_XFER_BULK, +				.wMaxPacketSize = +					cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE), +				.bInterval = 		0xFF, +			}, +			{ +				.bLength = +					sizeof(struct usb_endpoint_descriptor), +				.bDescriptorType =	USB_DT_ENDPOINT, +				.bEndpointAddress =	0x03 | USB_DIR_IN, +				.bmAttributes =		USB_ENDPOINT_XFER_INT, +    				.wMaxPacketSize = +					cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE), +				.bInterval =		0xFF, +			}, +		}, +	}, +};  /* - * Prototypes + * Static Function Prototypes   */ +  static void usbtty_init_strings (void);  static void usbtty_init_instances (void);  static void usbtty_init_endpoints (void); - +static void usbtty_init_terminal_type(short type);  static void usbtty_event_handler (struct usb_device_instance *device, -				  usb_device_event_t event, int data); +				usb_device_event_t event, int data); +static int usbtty_cdc_setup(struct usb_device_request *request, +				struct urb *urb);  static int usbtty_configured (void); -  static int write_buffer (circbuf_t * buf);  static int fill_buffer (circbuf_t * buf);  void usbtty_poll (void); -static void pretend_interrupts (void); +/* utility function for converting char* to wide string used by USB */ +static void str2wide (char *str, u16 * wide) +{ +	int i; +	for (i = 0; i < strlen (str) && str[i]; i++){ +		#if defined(__LITTLE_ENDIAN) +			wide[i] = (u16) str[i]; +		#elif defined(__BIG_ENDIAN) +			wide[i] = ((u16)(str[i])<<8); +		#else +			#error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined" +		#endif +	} +}  /*   * Test whether a character is in the RX buffer   */ +  int usbtty_tstc (void)  { +	struct usb_endpoint_instance *endpoint = +		&endpoint_instance[rx_endpoint]; + +	/* If no input data exists, allow more RX to be accepted */ +	if(usbtty_input.size <= 0){ +		udc_unset_nak(endpoint->endpoint_address&0x03); +	} +  	usbtty_poll ();  	return (usbtty_input.size > 0);  } @@ -210,15 +414,21 @@ int usbtty_tstc (void)   * otherwise. When the function is succesfull, the character read is   * written into its argument c.   */ +  int usbtty_getc (void)  {  	char c; +	struct usb_endpoint_instance *endpoint = +		&endpoint_instance[rx_endpoint];  	while (usbtty_input.size <= 0) { +		udc_unset_nak(endpoint->endpoint_address&0x03);  		usbtty_poll ();  	}  	buf_pop (&usbtty_input, &c, 1); +	udc_set_nak(endpoint->endpoint_address&0x03); +  	return c;  } @@ -238,7 +448,6 @@ void usbtty_putc (const char c)  	}  } -  /* usbtty_puts() helper function for finding the next '\n' in a string */  static int next_nl_pos (const char *s)  { @@ -252,8 +461,9 @@ static int next_nl_pos (const char *s)  }  /* - * Output a string to the usb client port. + * Output a string to the usb client port - implementing flow control   */ +  static void __usbtty_puts (const char *str, int len)  {  	int maxlen = usbtty_output.totalsize; @@ -261,22 +471,19 @@ static void __usbtty_puts (const char *str, int len)  	/* break str into chunks < buffer size, if needed */  	while (len > 0) { -		space = maxlen - usbtty_output.size; +		usbtty_poll (); +		space = maxlen - usbtty_output.size;  		/* Empty buffer here, if needed, to ensure space... */ -		if (space <= 0) { +		if (space) {  			write_buffer (&usbtty_output); -			space = maxlen - usbtty_output.size; -			if (space <= 0) { -				space = len;	/* allow old data to be overwritten. */ -			} -		} -		n = MIN (space, MIN (len, maxlen)); -		buf_push (&usbtty_output, str, n); +			n = MIN (space, MIN (len, maxlen)); +			buf_push (&usbtty_output, str, n); -		str += n; -		len -= n; +			str += n; +			len -= n; +		}  	}  } @@ -313,8 +520,10 @@ int drv_usbtty_init (void)  {  	int rc;  	char * sn; +	char * tt;  	int snlen; +	/* Ger seiral number */  	if (!(sn = getenv("serial#"))) {  		sn = "000000000000";  	} @@ -327,6 +536,14 @@ int drv_usbtty_init (void)  	memcpy (serial_number, sn, snlen);  	serial_number[snlen] = '\0'; +	/* Decide on which type of UDC device to be. +	 */ + +	if(!(tt = getenv("usbtty"))) { +		tt = "generic"; +	} +	usbtty_init_terminal_type(strcmp(tt,"cdc_acm")); +  	/* prepare buffers... */  	buf_init (&usbtty_input, USBTTY_BUFFER_SIZE);  	buf_init (&usbtty_output, USBTTY_BUFFER_SIZE); @@ -337,7 +554,7 @@ int drv_usbtty_init (void)  	usbtty_init_strings ();  	usbtty_init_instances (); -	udc_startup_events (device_instance);	/* Enable our device, initialize udc pointers */ +	udc_startup_events (device_instance);/* Enable dev, init udc pointers */  	udc_connect ();		/* Enable pullup for host detection */  	usbtty_init_endpoints (); @@ -362,30 +579,48 @@ static void usbtty_init_strings (void)  {  	struct usb_string_descriptor *string; +	usbtty_string_table[STR_LANG] = +		(struct usb_string_descriptor*)wstrLang; +  	string = (struct usb_string_descriptor *) wstrManufacturer; -	string->bLength = sizeof (wstrManufacturer); +	string->bLength = sizeof(wstrManufacturer);  	string->bDescriptorType = USB_DT_STRING;  	str2wide (CONFIG_USBD_MANUFACTURER, string->wData); +	usbtty_string_table[STR_MANUFACTURER]=string; +  	string = (struct usb_string_descriptor *) wstrProduct; -	string->bLength = sizeof (wstrProduct); +	string->bLength = sizeof(wstrProduct);  	string->bDescriptorType = USB_DT_STRING;  	str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData); +	usbtty_string_table[STR_PRODUCT]=string; +  	string = (struct usb_string_descriptor *) wstrSerial; -	string->bLength = 2 + 2*strlen(serial_number); +	string->bLength = sizeof(serial_number);  	string->bDescriptorType = USB_DT_STRING;  	str2wide (serial_number, string->wData); +	usbtty_string_table[STR_SERIAL]=string; +  	string = (struct usb_string_descriptor *) wstrConfiguration; -	string->bLength = sizeof (wstrConfiguration); +	string->bLength = sizeof(wstrConfiguration);  	string->bDescriptorType = USB_DT_STRING;  	str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData); +	usbtty_string_table[STR_CONFIG]=string; -	string = (struct usb_string_descriptor *) wstrInterface; -	string->bLength = sizeof (wstrInterface); + +	string = (struct usb_string_descriptor *) wstrDataInterface; +	string->bLength = sizeof(wstrDataInterface);  	string->bDescriptorType = USB_DT_STRING; -	str2wide (CONFIG_USBD_INTERFACE_STR, string->wData); +	str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData); +	usbtty_string_table[STR_DATA_INTERFACE]=string; + +	string = (struct usb_string_descriptor *) wstrCtrlInterface; +	string->bLength = sizeof(wstrCtrlInterface); +	string->bDescriptorType = USB_DT_STRING; +	str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData); +	usbtty_string_table[STR_CTRL_INTERFACE]=string;  	/* Now, initialize the string table for ep0 handling */  	usb_strings = usbtty_string_table; @@ -400,6 +635,7 @@ static void usbtty_init_instances (void)  	device_instance->device_state = STATE_INIT;  	device_instance->device_descriptor = &device_descriptor;  	device_instance->event = usbtty_event_handler; +	device_instance->cdc_recv_setup = usbtty_cdc_setup;  	device_instance->bus = bus_instance;  	device_instance->configurations = NUM_CONFIGS;  	device_instance->configuration_instance_array = config_instance; @@ -415,8 +651,8 @@ static void usbtty_init_instances (void)  	/* configuration instance */  	memset (config_instance, 0,  		sizeof (struct usb_configuration_instance)); -	config_instance->interfaces = NUM_INTERFACES; -	config_instance->configuration_descriptor = config_descriptors; +	config_instance->interfaces = interface_count; +	config_instance->configuration_descriptor = configuration_descriptor;  	config_instance->interface_instance_array = interface_instance;  	/* interface instance */ @@ -447,17 +683,22 @@ static void usbtty_init_instances (void)  			sizeof (struct usb_endpoint_instance));  		endpoint_instance[i].endpoint_address = -			ep_descriptors[i - 1].bEndpointAddress; +			ep_descriptor_ptrs[i - 1]->bEndpointAddress; -		endpoint_instance[i].rcv_packetSize = -			ep_descriptors[i - 1].wMaxPacketSize;  		endpoint_instance[i].rcv_attributes = -			ep_descriptors[i - 1].bmAttributes; +			ep_descriptor_ptrs[i - 1]->bmAttributes; + +		endpoint_instance[i].rcv_packetSize = +			le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize); + +		endpoint_instance[i].tx_attributes = +			ep_descriptor_ptrs[i - 1]->bmAttributes;  		endpoint_instance[i].tx_packetSize = -			ep_descriptors[i - 1].wMaxPacketSize; +			le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize); +  		endpoint_instance[i].tx_attributes = -			ep_descriptors[i - 1].bmAttributes; +			ep_descriptor_ptrs[i - 1]->bmAttributes;  		urb_link_init (&endpoint_instance[i].rcv);  		urb_link_init (&endpoint_instance[i].rdy); @@ -480,13 +721,79 @@ static void usbtty_init_endpoints (void)  	int i;  	bus_instance->max_endpoints = NUM_ENDPOINTS + 1; -	for (i = 0; i <= NUM_ENDPOINTS; i++) { +	for (i = 1; i <= NUM_ENDPOINTS; i++) {  		udc_setup_ep (device_instance, i, &endpoint_instance[i]);  	}  } +/* usbtty_init_terminal_type + * + * Do some late binding for our device type. + */ +static void usbtty_init_terminal_type(short type) +{ +	switch(type){ +		/* CDC ACM */ +		case 0: +			/* Assign endpoint descriptors */ +			ep_descriptor_ptrs[0] = +				&acm_configuration_descriptors[0].notification_endpoint; +			ep_descriptor_ptrs[1] = +				&acm_configuration_descriptors[0].data_endpoints[0]; +			ep_descriptor_ptrs[2] = +				&acm_configuration_descriptors[0].data_endpoints[1]; + +			/* Enumerate Device Descriptor */ +			device_descriptor.bDeviceClass = +				COMMUNICATIONS_DEVICE_CLASS; +			device_descriptor.idProduct = +				cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM); + +			/* Assign endpoint indices */ +			tx_endpoint = ACM_TX_ENDPOINT; +			rx_endpoint = ACM_RX_ENDPOINT; + +			/* Configuration Descriptor */ +			configuration_descriptor = +				(struct usb_configuration_descriptor*) +				&acm_configuration_descriptors; + +			/* Interface count */ +			interface_count = NUM_ACM_INTERFACES; +		break; + +		/* BULK IN/OUT & Default */ +		case 1: +		default: +			/* Assign endpoint descriptors */ +			ep_descriptor_ptrs[0] = +				&gserial_configuration_descriptors[0].data_endpoints[0]; +			ep_descriptor_ptrs[1] = +				&gserial_configuration_descriptors[0].data_endpoints[1]; +			ep_descriptor_ptrs[2] = +				&gserial_configuration_descriptors[0].data_endpoints[2]; + +			/* Enumerate Device Descriptor */ +			device_descriptor.bDeviceClass = 0xFF; +			device_descriptor.idProduct = +				cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL); + +			/* Assign endpoint indices */ +			tx_endpoint = GSERIAL_TX_ENDPOINT; +			rx_endpoint = GSERIAL_RX_ENDPOINT; + +			/* Configuration Descriptor */ +			configuration_descriptor = +				(struct usb_configuration_descriptor*) +				&gserial_configuration_descriptors; + +			/* Interface count */ +			interface_count = NUM_GSERIAL_INTERFACES; +		break; +	} +} -/*********************************************************************************/ +/******************************************************************************/  static struct urb *next_urb (struct usb_device_instance *device,  			     struct usb_endpoint_instance *endpoint) @@ -526,27 +833,39 @@ static int write_buffer (circbuf_t * buf)  		return 0;  	} -	if (buf->size) { +	struct usb_endpoint_instance *endpoint = +			&endpoint_instance[tx_endpoint]; +	struct urb *current_urb = NULL; -		struct usb_endpoint_instance *endpoint = -			&endpoint_instance[TX_ENDPOINT]; -		struct urb *current_urb = NULL; +	current_urb = next_urb (device_instance, endpoint); +	/* TX data still exists - send it now +	 */ +	if(endpoint->sent < current_urb->actual_length){ +		if(udc_endpoint_write (endpoint)){ +			/* Write pre-empted by RX */ +			return -1; +		} +	} + +	if (buf->size) {  		char *dest;  		int space_avail;  		int popnum, popped;  		int total = 0; -		/* Break buffer into urb sized pieces, and link each to the endpoint */ +		/* Break buffer into urb sized pieces, +		 * and link each to the endpoint +		 */  		while (buf->size > 0) { -			current_urb = next_urb (device_instance, endpoint); +  			if (!current_urb) {  				TTYERR ("current_urb is NULL, buf->size %d\n",  					buf->size);  				return total;  			} -			dest = current_urb->buffer + +			dest = (char*)current_urb->buffer +  				current_urb->actual_length;  			space_avail = @@ -562,14 +881,19 @@ static int write_buffer (circbuf_t * buf)  			current_urb->actual_length += popped;  			total += popped; -			/* If endpoint->last == 0, then transfers have not started on this endpoint */ +			/* If endpoint->last == 0, then transfers have +			 * not started on this endpoint +			 */  			if (endpoint->last == 0) { -				udc_endpoint_write (endpoint); +				if(udc_endpoint_write (endpoint)){ +					/* Write pre-empted by RX */ +					return -1; +				}  			} -		}		/* end while */ +		}/* end while */  		return total; -	}			/* end if tx_urb */ +	}  	return 0;  } @@ -577,18 +901,22 @@ static int write_buffer (circbuf_t * buf)  static int fill_buffer (circbuf_t * buf)  {  	struct usb_endpoint_instance *endpoint = -		&endpoint_instance[RECV_ENDPOINT]; +		&endpoint_instance[rx_endpoint];  	if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) { -		unsigned int nb = endpoint->rcv_urb->actual_length; +		unsigned int nb = 0;  		char *src = (char *) endpoint->rcv_urb->buffer; +		unsigned int rx_avail = buf->totalsize - buf->size; + +		if(rx_avail >= endpoint->rcv_urb->actual_length){ -		buf_push (buf, src, nb); -		endpoint->rcv_urb->actual_length = 0; +			nb = endpoint->rcv_urb->actual_length; +			buf_push (buf, src, nb); +			endpoint->rcv_urb->actual_length = 0; +		}  		return nb;  	} -  	return 0;  } @@ -597,7 +925,7 @@ static int usbtty_configured (void)  	return usbtty_configured_flag;  } -/*********************************************************************************/ +/******************************************************************************/  static void usbtty_event_handler (struct usb_device_instance *device,  				  usb_device_event_t event, int data) @@ -619,8 +947,34 @@ static void usbtty_event_handler (struct usb_device_instance *device,  	}  } -/*********************************************************************************/ +/******************************************************************************/ +int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb) +{ +	switch (request->bRequest){ + +	   	case ACM_SET_CONTROL_LINE_STATE:	/* Implies DTE ready */ +			break; +	   	case ACM_SEND_ENCAPSULATED_COMMAND :	/* Required */ +			break; +		case ACM_SET_LINE_ENCODING :		/* DTE stop/parity bits +							 * per character */ +			break; +	   	case ACM_GET_ENCAPSULATED_RESPONSE :	/* request response */ +			break; +		case ACM_GET_LINE_ENCODING :		/* request DTE rate, +							 * stop/parity bits */ +			memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc)); +			urb->actual_length = sizeof(rs232_desc); + +			break; +	 	default: +			return 1; +	} +	return 0; +} + +/******************************************************************************/  /*   * Since interrupt handling has not yet been implemented, we use this function @@ -630,36 +984,29 @@ static void usbtty_event_handler (struct usb_device_instance *device,  void usbtty_poll (void)  {  	/* New interrupts? */ -	pretend_interrupts (); +	udc_irq(); -	/* Write any output data to host buffer (do this before checking interrupts to avoid missing one) */ +	/* Write any output data to host buffer +	 * (do this before checking interrupts to avoid missing one) +	 */  	if (usbtty_configured ()) {  		write_buffer (&usbtty_output);  	}  	/* New interrupts? */ -	pretend_interrupts (); +	udc_irq(); -	/* Check for new data from host.. (do this after checking interrupts to get latest data) */ +	/* Check for new data from host.. +	 * (do this after checking interrupts to get latest data) +	 */  	if (usbtty_configured ()) {  		fill_buffer (&usbtty_input);  	}  	/* New interrupts? */ -	pretend_interrupts (); -} +	udc_irq(); -static void pretend_interrupts (void) -{ -	/* Loop while we have interrupts. -	 * If we don't do this, the input chain -	 * polling delay is likely to miss -	 * host requests. -	 */ -	while (inw (UDC_IRQ_SRC) & ~UDC_SOF_Flg) { -		/* Handle any new IRQs */ -		omap1510_udc_irq (); -		omap1510_udc_noniso_irq (); -	}  } + +  #endif diff --git a/drivers/usbtty.h b/drivers/usbtty.h index 79c2fe57d..8154e3072 100644 --- a/drivers/usbtty.h +++ b/drivers/usbtty.h @@ -2,6 +2,9 @@   * (C) Copyright 2003   * Gerry Hamel, geh@ti.com, Texas Instruments   * + * (C) Copyright 2006 + * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit + *   * 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 @@ -21,44 +24,47 @@  #ifndef __USB_TTY_H__  #define __USB_TTY_H__ -  #include "usbdcore.h" +#if defined(CONFIG_PPC) +#include "usbdcore_mpc8xx.h" +#elif defined(CONFIG_ARM)  #include "usbdcore_omap1510.h" +#endif +#include <version_autogenerated.h> -#define NUM_CONFIGS    1 -#define NUM_INTERFACES 1 -#define NUM_ENDPOINTS  3 +/* If no VendorID/ProductID is defined in config.h, pretend to be Linux + * DO NOT Reuse this Vendor/Product setup with protocol incompatible devices */ -#define EP0_MAX_PACKET_SIZE 64 +#define CONFIG_USBD_VENDORID 0x0525 	/* Linux/NetChip */ +#define CONFIG_USBD_PRODUCTID_GSERIAL 0xa4a6	/* gserial */ +#define CONFIG_USBD_PRODUCTID_CDCACM  0xa4a7	/* CDC ACM */ +#define CONFIG_USBD_MANUFACTURER "Das U-Boot" +#define CONFIG_USBD_PRODUCT_NAME U_BOOT_VERSION -#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB" -#define CONFIG_USBD_INTERFACE_STR     "Simple Serial Data Interface - Bulk Mode" +#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB" -#define CONFIG_USBD_SERIAL_OUT_ENDPOINT 2 -#define CONFIG_USBD_SERIAL_OUT_PKTSIZE	64 -#define CONFIG_USBD_SERIAL_IN_ENDPOINT	1 -#define CONFIG_USBD_SERIAL_IN_PKTSIZE	64 -#define CONFIG_USBD_SERIAL_INT_ENDPOINT 5 -#define CONFIG_USBD_SERIAL_INT_PKTSIZE	16 - +#define CONFIG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT +#define CONFIG_USBD_SERIAL_OUT_PKTSIZE	UDC_OUT_PACKET_SIZE +#define CONFIG_USBD_SERIAL_IN_ENDPOINT	UDC_IN_ENDPOINT +#define CONFIG_USBD_SERIAL_IN_PKTSIZE	UDC_IN_PACKET_SIZE +#define CONFIG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT +#define CONFIG_USBD_SERIAL_INT_PKTSIZE	UDC_INT_PACKET_SIZE +#define CONFIG_USBD_SERIAL_BULK_PKTSIZE	UDC_BULK_PACKET_SIZE  #define USBTTY_DEVICE_CLASS	COMMUNICATIONS_DEVICE_CLASS -#define USBTTY_DEVICE_SUBCLASS	COMMUNICATIONS_NO_SUBCLASS -#define USBTTY_DEVICE_PROTOCOL	COMMUNICATIONS_NO_PROTOCOL - -#define USBTTY_INTERFACE_CLASS	   0xFF /* Vendor Specific */ -#define USBTTY_INTERFACE_SUBCLASS  0x02 -#define USBTTY_INTERFACE_PROTOCOL  0x01 -#define USBTTY_BCD_DEVICE 0x0 -#define USBTTY_MAXPOWER	  0x0 +#define USBTTY_BCD_DEVICE 	0x00 +#define USBTTY_MAXPOWER	  	0x00 -#define STR_MANUFACTURER 1 -#define STR_PRODUCT	 2 -#define STR_SERIAL	 3 -#define STR_CONFIG	 4 -#define STR_INTERFACE	 5 +#define STR_LANG		0x00 +#define STR_MANUFACTURER	0x01 +#define STR_PRODUCT		0x02 +#define STR_SERIAL		0x03 +#define STR_CONFIG		0x04 +#define STR_DATA_INTERFACE	0x05 +#define STR_CTRL_INTERFACE	0x06 +#define STR_COUNT		0x07  #endif diff --git a/include/_exports.h b/include/_exports.h index da6e08816..af43885c5 100644 --- a/include/_exports.h +++ b/include/_exports.h @@ -14,6 +14,9 @@ EXPORT_FUNC(vprintf)  EXPORT_FUNC(do_reset)  EXPORT_FUNC(getenv)  EXPORT_FUNC(setenv) +#ifdef CONFIG_HAS_UID +EXPORT_FUNC(forceenv) +#endif  EXPORT_FUNC(simple_strtoul)  EXPORT_FUNC(simple_strtol)  EXPORT_FUNC(strcmp) diff --git a/include/asm-arm/arch-davinci/emac_defs.h b/include/asm-arm/arch-davinci/emac_defs.h new file mode 100644 index 000000000..0e10116d8 --- /dev/null +++ b/include/asm-arm/arch-davinci/emac_defs.h @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Based on: + * + * ---------------------------------------------------------------------------- + * + * dm644x_emac.h + * + * TI DaVinci (DM644X) EMAC peripheral driver header for DV-EVM + * + * Copyright (C) 2005 Texas Instruments. + * + * ---------------------------------------------------------------------------- + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * ---------------------------------------------------------------------------- + + * Modifications: + * ver. 1.0: Sep 2005, TI PSP Team - Created EMAC version for uBoot. + * + */ + +#ifndef _DM644X_EMAC_H_ +#define _DM644X_EMAC_H_ + +#include <asm/arch/hardware.h> + +#define EMAC_BASE_ADDR			(0x01c80000) +#define EMAC_WRAPPER_BASE_ADDR		(0x01c81000) +#define EMAC_WRAPPER_RAM_ADDR		(0x01c82000) +#define EMAC_MDIO_BASE_ADDR		(0x01c84000) + +/* MDIO module input frequency */ +#define EMAC_MDIO_BUS_FREQ		99000000	/* PLL/6 - 99 MHz */ +/* MDIO clock output frequency */ +#define EMAC_MDIO_CLOCK_FREQ		2000000		/* 2.0 MHz */ + +/* Ethernet Min/Max packet size */ +#define EMAC_MIN_ETHERNET_PKT_SIZE	60 +#define EMAC_MAX_ETHERNET_PKT_SIZE	1518 +#define EMAC_PKT_ALIGN			18	/* 1518 + 18 = 1536 (packet aligned on 32 byte boundry) */ + +/* Number of RX packet buffers + * NOTE: Only 1 buffer supported as of now + */ +#define EMAC_MAX_RX_BUFFERS		10 + + +/*********************************************** + ******** Internally used macros *************** + ***********************************************/ + +#define EMAC_CH_TX			1 +#define EMAC_CH_RX			0 + +/* Each descriptor occupies 4 words, lets start RX desc's at 0 and + * reserve space for 64 descriptors max + */ +#define EMAC_RX_DESC_BASE		0x0 +#define EMAC_TX_DESC_BASE		0x1000 + +/* EMAC Teardown value */ +#define EMAC_TEARDOWN_VALUE		0xfffffffc + +/* MII Status Register */ +#define MII_STATUS_REG			1 + +/* Number of statistics registers */ +#define EMAC_NUM_STATS			36 + + +/* EMAC Descriptor */ +typedef volatile struct _emac_desc +{ +	u_int32_t	next;		/* Pointer to next descriptor in chain */ +	u_int8_t	*buffer;	/* Pointer to data buffer */ +	u_int32_t	buff_off_len;	/* Buffer Offset(MSW) and Length(LSW) */ +	u_int32_t	pkt_flag_len;	/* Packet Flags(MSW) and Length(LSW) */ +} emac_desc; + +/* CPPI bit positions */ +#define EMAC_CPPI_SOP_BIT		(0x80000000) +#define EMAC_CPPI_EOP_BIT		(0x40000000) +#define EMAC_CPPI_OWNERSHIP_BIT		(0x20000000) +#define EMAC_CPPI_EOQ_BIT		(0x10000000) +#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT	(0x08000000) +#define EMAC_CPPI_PASS_CRC_BIT		(0x04000000) + +#define EMAC_CPPI_RX_ERROR_FRAME	(0x03fc0000) + +#define EMAC_MACCONTROL_MIIEN_ENABLE		(0x20) +#define EMAC_MACCONTROL_FULLDUPLEX_ENABLE	(0x1) + +#define EMAC_RXMBPENABLE_RXCAFEN_ENABLE	(0x200000) +#define EMAC_RXMBPENABLE_RXBROADEN	(0x2000) + + +#define MDIO_CONTROL_IDLE		(0x80000000) +#define MDIO_CONTROL_ENABLE		(0x40000000) +#define MDIO_CONTROL_FAULT_ENABLE	(0x40000) +#define MDIO_CONTROL_FAULT		(0x80000) +#define MDIO_USERACCESS0_GO		(0x80000000) +#define MDIO_USERACCESS0_WRITE_READ	(0x0) +#define MDIO_USERACCESS0_WRITE_WRITE	(0x40000000) +#define MDIO_USERACCESS0_ACK		(0x20000000) + +/* Ethernet MAC Registers Structure */ +typedef struct  { +	dv_reg		TXIDVER; +	dv_reg		TXCONTROL; +	dv_reg		TXTEARDOWN; +	u_int8_t	RSVD0[4]; +	dv_reg		RXIDVER; +	dv_reg		RXCONTROL; +	dv_reg		RXTEARDOWN; +	u_int8_t	RSVD1[100]; +	dv_reg		TXINTSTATRAW; +	dv_reg		TXINTSTATMASKED; +	dv_reg		TXINTMASKSET; +	dv_reg		TXINTMASKCLEAR; +	dv_reg		MACINVECTOR; +	u_int8_t	RSVD2[12]; +	dv_reg		RXINTSTATRAW; +	dv_reg		RXINTSTATMASKED; +	dv_reg		RXINTMASKSET; +	dv_reg		RXINTMASKCLEAR; +	dv_reg		MACINTSTATRAW; +	dv_reg		MACINTSTATMASKED; +	dv_reg		MACINTMASKSET; +	dv_reg		MACINTMASKCLEAR; +	u_int8_t	RSVD3[64]; +	dv_reg		RXMBPENABLE; +	dv_reg		RXUNICASTSET; +	dv_reg		RXUNICASTCLEAR; +	dv_reg		RXMAXLEN; +	dv_reg		RXBUFFEROFFSET; +	dv_reg		RXFILTERLOWTHRESH; +	u_int8_t	RSVD4[8]; +	dv_reg		RX0FLOWTHRESH; +	dv_reg		RX1FLOWTHRESH; +	dv_reg		RX2FLOWTHRESH; +	dv_reg		RX3FLOWTHRESH; +	dv_reg		RX4FLOWTHRESH; +	dv_reg		RX5FLOWTHRESH; +	dv_reg		RX6FLOWTHRESH; +	dv_reg		RX7FLOWTHRESH; +	dv_reg		RX0FREEBUFFER; +	dv_reg		RX1FREEBUFFER; +	dv_reg		RX2FREEBUFFER; +	dv_reg		RX3FREEBUFFER; +	dv_reg		RX4FREEBUFFER; +	dv_reg		RX5FREEBUFFER; +	dv_reg		RX6FREEBUFFER; +	dv_reg		RX7FREEBUFFER; +	dv_reg		MACCONTROL; +	dv_reg		MACSTATUS; +	dv_reg		EMCONTROL; +	dv_reg		FIFOCONTROL; +	dv_reg		MACCONFIG; +	dv_reg		SOFTRESET; +	u_int8_t	RSVD5[88]; +	dv_reg		MACSRCADDRLO; +	dv_reg		MACSRCADDRHI; +	dv_reg		MACHASH1; +	dv_reg		MACHASH2; +	dv_reg		BOFFTEST; +	dv_reg		TPACETEST; +	dv_reg		RXPAUSE; +	dv_reg		TXPAUSE; +	u_int8_t	RSVD6[16]; +	dv_reg		RXGOODFRAMES; +	dv_reg		RXBCASTFRAMES; +	dv_reg		RXMCASTFRAMES; +	dv_reg		RXPAUSEFRAMES; +	dv_reg		RXCRCERRORS; +	dv_reg		RXALIGNCODEERRORS; +	dv_reg		RXOVERSIZED; +	dv_reg		RXJABBER; +	dv_reg		RXUNDERSIZED; +	dv_reg		RXFRAGMENTS; +	dv_reg		RXFILTERED; +	dv_reg		RXQOSFILTERED; +	dv_reg		RXOCTETS; +	dv_reg		TXGOODFRAMES; +	dv_reg		TXBCASTFRAMES; +	dv_reg		TXMCASTFRAMES; +	dv_reg		TXPAUSEFRAMES; +	dv_reg		TXDEFERRED; +	dv_reg		TXCOLLISION; +	dv_reg		TXSINGLECOLL; +	dv_reg		TXMULTICOLL; +	dv_reg		TXEXCESSIVECOLL; +	dv_reg		TXLATECOLL; +	dv_reg		TXUNDERRUN; +	dv_reg		TXCARRIERSENSE; +	dv_reg		TXOCTETS; +	dv_reg		FRAME64; +	dv_reg		FRAME65T127; +	dv_reg		FRAME128T255; +	dv_reg		FRAME256T511; +	dv_reg		FRAME512T1023; +	dv_reg		FRAME1024TUP; +	dv_reg		NETOCTETS; +	dv_reg		RXSOFOVERRUNS; +	dv_reg		RXMOFOVERRUNS; +	dv_reg		RXDMAOVERRUNS; +	u_int8_t	RSVD7[624]; +	dv_reg		MACADDRLO; +	dv_reg		MACADDRHI; +	dv_reg		MACINDEX; +	u_int8_t	RSVD8[244]; +	dv_reg		TX0HDP; +	dv_reg		TX1HDP; +	dv_reg		TX2HDP; +	dv_reg		TX3HDP; +	dv_reg		TX4HDP; +	dv_reg		TX5HDP; +	dv_reg		TX6HDP; +	dv_reg		TX7HDP; +	dv_reg		RX0HDP; +	dv_reg		RX1HDP; +	dv_reg		RX2HDP; +	dv_reg		RX3HDP; +	dv_reg		RX4HDP; +	dv_reg		RX5HDP; +	dv_reg		RX6HDP; +	dv_reg		RX7HDP; +	dv_reg		TX0CP; +	dv_reg		TX1CP; +	dv_reg		TX2CP; +	dv_reg		TX3CP; +	dv_reg		TX4CP; +	dv_reg		TX5CP; +	dv_reg		TX6CP; +	dv_reg		TX7CP; +	dv_reg		RX0CP; +	dv_reg		RX1CP; +	dv_reg		RX2CP; +	dv_reg		RX3CP; +	dv_reg		RX4CP; +	dv_reg		RX5CP; +	dv_reg		RX6CP; +	dv_reg		RX7CP; +} emac_regs; + +/* EMAC Wrapper Registers Structure */ +typedef struct  { +	u_int8_t	RSVD0[4100]; +	dv_reg		EWCTL; +	dv_reg		EWINTTCNT; +} ewrap_regs; + + +/* EMAC MDIO Registers Structure */ +typedef struct  { +	dv_reg		VERSION; +	dv_reg		CONTROL; +	dv_reg		ALIVE; +	dv_reg		LINK; +	dv_reg		LINKINTRAW; +	dv_reg		LINKINTMASKED; +	u_int8_t	RSVD0[8]; +	dv_reg		USERINTRAW; +	dv_reg		USERINTMASKED; +	dv_reg		USERINTMASKSET; +	dv_reg		USERINTMASKCLEAR; +	u_int8_t	RSVD1[80]; +	dv_reg		USERACCESS0; +	dv_reg		USERPHYSEL0; +	dv_reg		USERACCESS1; +	dv_reg		USERPHYSEL1; +} mdio_regs; + +int dm644x_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data); +int dm644x_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data); + +typedef struct +{ +	char	name[64]; +	int	(*init)(int phy_addr); +	int	(*is_phy_connected)(int phy_addr); +	int	(*get_link_speed)(int phy_addr); +	int	(*auto_negotiate)(int phy_addr); +} phy_t; + +#define PHY_LXT972	(0x001378e2) +int lxt972_is_phy_connected(int phy_addr); +int lxt972_get_link_speed(int phy_addr); +int lxt972_init_phy(int phy_addr); +int lxt972_auto_negotiate(int phy_addr); + +#define PHY_DP83848	(0x20005c90) +int dp83848_is_phy_connected(int phy_addr); +int dp83848_get_link_speed(int phy_addr); +int dp83848_init_phy(int phy_addr); +int dp83848_auto_negotiate(int phy_addr); + +#endif  /* _DM644X_EMAC_H_ */ diff --git a/include/asm-arm/arch-davinci/emif_defs.h b/include/asm-arm/arch-davinci/emif_defs.h new file mode 100644 index 000000000..646fc7746 --- /dev/null +++ b/include/asm-arm/arch-davinci/emif_defs.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ +#ifndef _EMIF_DEFS_H_ +#define _EMIF_DEFS_H_ + +#include <asm/arch/hardware.h> + +typedef struct { +	dv_reg		ERCSR; +	dv_reg		AWCCR; +	dv_reg		SDBCR; +	dv_reg		SDRCR; +	dv_reg		AB1CR; +	dv_reg		AB2CR; +	dv_reg		AB3CR; +	dv_reg		AB4CR; +	dv_reg		SDTIMR; +	dv_reg		DDRSR; +	dv_reg		DDRPHYCR; +	dv_reg		DDRPHYSR; +	dv_reg		TOTAR; +	dv_reg		TOTACTR; +	dv_reg		DDRPHYID_REV; +	dv_reg		SDSRETR; +	dv_reg		EIRR; +	dv_reg		EIMR; +	dv_reg		EIMSR; +	dv_reg		EIMCR; +	dv_reg		IOCTRLR; +	dv_reg		IOSTATR; +	u_int8_t	RSVD0[8]; +	dv_reg		NANDFCR; +	dv_reg		NANDFSR; +	u_int8_t	RSVD1[8]; +	dv_reg		NANDF1ECC; +	dv_reg		NANDF2ECC; +	dv_reg		NANDF3ECC; +	dv_reg		NANDF4ECC; +} emif_registers; + +typedef emif_registers	*emifregs; +#endif diff --git a/include/asm-arm/arch-davinci/hardware.h b/include/asm-arm/arch-davinci/hardware.h new file mode 100644 index 000000000..ebcdcfea1 --- /dev/null +++ b/include/asm-arm/arch-davinci/hardware.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Based on: + * + * ------------------------------------------------------------------------- + * + *  linux/include/asm-arm/arch-davinci/hardware.h + * + *  Copyright (C) 2006 Texas Instruments. + * + *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED + *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN + *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF + *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  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., + *  675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include <config.h> +#include <asm/sizes.h> + +#define	REG(addr)	(*(volatile unsigned int *)(addr)) +#define REG_P(addr)	((volatile unsigned int *)(addr)) + +typedef volatile unsigned int	dv_reg; +typedef volatile unsigned int *	dv_reg_p; + +/* + * Base register addresses + */ +#define DAVINCI_DMA_3PCC_BASE			(0x01c00000) +#define DAVINCI_DMA_3PTC0_BASE			(0x01c10000) +#define DAVINCI_DMA_3PTC1_BASE			(0x01c10400) +#define DAVINCI_UART0_BASE			(0x01c20000) +#define DAVINCI_UART1_BASE			(0x01c20400) +#define DAVINCI_UART2_BASE			(0x01c20800) +#define DAVINCI_I2C_BASE			(0x01c21000) +#define DAVINCI_TIMER0_BASE			(0x01c21400) +#define DAVINCI_TIMER1_BASE			(0x01c21800) +#define DAVINCI_WDOG_BASE			(0x01c21c00) +#define DAVINCI_PWM0_BASE			(0x01c22000) +#define DAVINCI_PWM1_BASE			(0x01c22400) +#define DAVINCI_PWM2_BASE			(0x01c22800) +#define DAVINCI_SYSTEM_MODULE_BASE		(0x01c40000) +#define DAVINCI_PLL_CNTRL0_BASE			(0x01c40800) +#define DAVINCI_PLL_CNTRL1_BASE			(0x01c40c00) +#define DAVINCI_PWR_SLEEP_CNTRL_BASE		(0x01c41000) +#define DAVINCI_SYSTEM_DFT_BASE			(0x01c42000) +#define DAVINCI_ARM_INTC_BASE			(0x01c48000) +#define DAVINCI_IEEE1394_BASE			(0x01c60000) +#define DAVINCI_USB_OTG_BASE			(0x01c64000) +#define DAVINCI_CFC_ATA_BASE			(0x01c66000) +#define DAVINCI_SPI_BASE			(0x01c66800) +#define DAVINCI_GPIO_BASE			(0x01c67000) +#define DAVINCI_UHPI_BASE			(0x01c67800) +#define DAVINCI_VPSS_REGS_BASE			(0x01c70000) +#define DAVINCI_EMAC_CNTRL_REGS_BASE		(0x01c80000) +#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE	(0x01c81000) +#define DAVINCI_EMAC_WRAPPER_RAM_BASE		(0x01c82000) +#define DAVINCI_MDIO_CNTRL_REGS_BASE		(0x01c84000) +#define DAVINCI_IMCOP_BASE			(0x01cc0000) +#define DAVINCI_ASYNC_EMIF_CNTRL_BASE		(0x01e00000) +#define DAVINCI_VLYNQ_BASE			(0x01e01000) +#define DAVINCI_MCBSP_BASE			(0x01e02000) +#define DAVINCI_MMC_SD_BASE			(0x01e10000) +#define DAVINCI_MS_BASE				(0x01e20000) +#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE	(0x02000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE	(0x04000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE	(0x06000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE	(0x08000000) +#define DAVINCI_VLYNQ_REMOTE_BASE		(0x0c000000) + +/* Power and Sleep Controller (PSC) Domains */ +#define DAVINCI_GPSC_ARMDOMAIN		0 +#define DAVINCI_GPSC_DSPDOMAIN		1 + +#define DAVINCI_LPSC_VPSSMSTR		0 +#define DAVINCI_LPSC_VPSSSLV		1 +#define DAVINCI_LPSC_TPCC		2 +#define DAVINCI_LPSC_TPTC0		3 +#define DAVINCI_LPSC_TPTC1		4 +#define DAVINCI_LPSC_EMAC		5 +#define DAVINCI_LPSC_EMAC_WRAPPER	6 +#define DAVINCI_LPSC_MDIO		7 +#define DAVINCI_LPSC_IEEE1394		8 +#define DAVINCI_LPSC_USB		9 +#define DAVINCI_LPSC_ATA		10 +#define DAVINCI_LPSC_VLYNQ		11 +#define DAVINCI_LPSC_UHPI		12 +#define DAVINCI_LPSC_DDR_EMIF		13 +#define DAVINCI_LPSC_AEMIF		14 +#define DAVINCI_LPSC_MMC_SD		15 +#define DAVINCI_LPSC_MEMSTICK		16 +#define DAVINCI_LPSC_McBSP		17 +#define DAVINCI_LPSC_I2C		18 +#define DAVINCI_LPSC_UART0		19 +#define DAVINCI_LPSC_UART1		20 +#define DAVINCI_LPSC_UART2		21 +#define DAVINCI_LPSC_SPI		22 +#define DAVINCI_LPSC_PWM0		23 +#define DAVINCI_LPSC_PWM1		24 +#define DAVINCI_LPSC_PWM2		25 +#define DAVINCI_LPSC_GPIO		26 +#define DAVINCI_LPSC_TIMER0		27 +#define DAVINCI_LPSC_TIMER1		28 +#define DAVINCI_LPSC_TIMER2		29 +#define DAVINCI_LPSC_SYSTEM_SUBSYS	30 +#define DAVINCI_LPSC_ARM		31 +#define DAVINCI_LPSC_SCR2		32 +#define DAVINCI_LPSC_SCR3		33 +#define DAVINCI_LPSC_SCR4		34 +#define DAVINCI_LPSC_CROSSBAR		35 +#define DAVINCI_LPSC_CFG27		36 +#define DAVINCI_LPSC_CFG3		37 +#define DAVINCI_LPSC_CFG5		38 +#define DAVINCI_LPSC_GEM		39 +#define DAVINCI_LPSC_IMCOP		40 + +/* Some PSC defines */ +#define PSC_CHP_SHRTSW			(0x01c40038) +#define PSC_GBLCTL			(0x01c41010) +#define PSC_EPCPR			(0x01c41070) +#define PSC_EPCCR			(0x01c41078) +#define PSC_PTCMD			(0x01c41120) +#define PSC_PTSTAT			(0x01c41128) +#define PSC_PDSTAT			(0x01c41200) +#define PSC_PDSTAT1			(0x01c41204) +#define PSC_PDCTL			(0x01c41300) +#define PSC_PDCTL1			(0x01c41304) + +#define PSC_MDCTL_BASE			(0x01c41a00) +#define PSC_MDSTAT_BASE			(0x01c41800) + +#define VDD3P3V_PWDN			(0x01c40048) +#define UART0_PWREMU_MGMT		(0x01c20030) + +#define PSC_SILVER_BULLET		(0x01c41a20) + +/* Some PLL defines */ +#define PLL1_PLLM			(0x01c40910) +#define PLL2_PLLM			(0x01c40d10) +#define PLL2_DIV2			(0x01c40d1c) + +/* Miscellania... */ +#define VBPR				(0x20000020) +#define PINMUX0				(0x01c40000) +#define PINMUX1				(0x01c40004) + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/include/asm-arm/arch-davinci/i2c_defs.h b/include/asm-arm/arch-davinci/i2c_defs.h new file mode 100644 index 000000000..2e902e17f --- /dev/null +++ b/include/asm-arm/arch-davinci/i2c_defs.h @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2004 + * Texas Instruments, <www.ti.com> + * + * Some changes copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ +#ifndef _DAVINCI_I2C_H_ +#define _DAVINCI_I2C_H_ + +#define I2C_WRITE		0 +#define I2C_READ		1 + +#define I2C_BASE		0x01c21000 + +#define	I2C_OA			(I2C_BASE + 0x00) +#define I2C_IE			(I2C_BASE + 0x04) +#define I2C_STAT		(I2C_BASE + 0x08) +#define I2C_SCLL		(I2C_BASE + 0x0c) +#define I2C_SCLH		(I2C_BASE + 0x10) +#define I2C_CNT			(I2C_BASE + 0x14) +#define I2C_DRR			(I2C_BASE + 0x18) +#define I2C_SA			(I2C_BASE + 0x1c) +#define I2C_DXR			(I2C_BASE + 0x20) +#define I2C_CON			(I2C_BASE + 0x24) +#define I2C_IV			(I2C_BASE + 0x28) +#define I2C_PSC			(I2C_BASE + 0x30) + +/* I2C masks */ + +/* I2C Interrupt Enable Register (I2C_IE): */ +#define I2C_IE_SCD_IE	(1 << 5)	/* Stop condition detect interrupt enable */ +#define I2C_IE_XRDY_IE	(1 << 4)	/* Transmit data ready interrupt enable */ +#define I2C_IE_RRDY_IE	(1 << 3)	/* Receive data ready interrupt enable */ +#define I2C_IE_ARDY_IE	(1 << 2)	/* Register access ready interrupt enable */ +#define I2C_IE_NACK_IE	(1 << 1)	/* No acknowledgment interrupt enable */ +#define I2C_IE_AL_IE	(1 << 0)	/* Arbitration lost interrupt enable */ + +/* I2C Status Register (I2C_STAT): */ + +#define I2C_STAT_BB	(1 << 12)	/* Bus busy */ +#define I2C_STAT_ROVR	(1 << 11)	/* Receive overrun */ +#define I2C_STAT_XUDF	(1 << 10)	/* Transmit underflow */ +#define I2C_STAT_AAS	(1 << 9)	/* Address as slave */ +#define I2C_STAT_SCD	(1 << 5)	/* Stop condition detect */ +#define I2C_STAT_XRDY	(1 << 4)	/* Transmit data ready */ +#define I2C_STAT_RRDY	(1 << 3)	/* Receive data ready */ +#define I2C_STAT_ARDY	(1 << 2)	/* Register access ready */ +#define I2C_STAT_NACK	(1 << 1)	/* No acknowledgment interrupt enable */ +#define I2C_STAT_AL	(1 << 0)	/* Arbitration lost interrupt enable */ + + +/* I2C Interrupt Code Register (I2C_INTCODE): */ + +#define I2C_INTCODE_MASK	7 +#define I2C_INTCODE_NONE	0 +#define I2C_INTCODE_AL		1	/* Arbitration lost */ +#define I2C_INTCODE_NAK		2	/* No acknowledgement/general call */ +#define I2C_INTCODE_ARDY	3	/* Register access ready */ +#define I2C_INTCODE_RRDY	4	/* Rcv data ready */ +#define I2C_INTCODE_XRDY	5	/* Xmit data ready */ +#define I2C_INTCODE_SCD		6	/* Stop condition detect */ + + +/* I2C Configuration Register (I2C_CON): */ + +#define I2C_CON_EN	(1 << 5)	/* I2C module enable */ +#define I2C_CON_STB	(1 << 4)	/* Start byte mode (master mode only) */ +#define I2C_CON_MST	(1 << 10)	/* Master/slave mode */ +#define I2C_CON_TRX	(1 << 9)	/* Transmitter/receiver mode (master mode only) */ +#define I2C_CON_XA	(1 << 8)	/* Expand address */ +#define I2C_CON_STP	(1 << 11)	/* Stop condition (master mode only) */ +#define I2C_CON_STT	(1 << 13)	/* Start condition (master mode only) */ + +#define I2C_TIMEOUT	0xffff0000	/* Timeout mask for poll_i2c_irq() */ + +#endif diff --git a/include/asm-arm/arch-davinci/nand_defs.h b/include/asm-arm/arch-davinci/nand_defs.h new file mode 100644 index 000000000..619bd4797 --- /dev/null +++ b/include/asm-arm/arch-davinci/nand_defs.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * Parts shamelesly stolen from Linux Kernel source tree. + * + * ------------------------------------------------------------ + * + * 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 + */ +#ifndef _NAND_DEFS_H_ +#define _NAND_DEFS_H_ + +#include <asm/arch/hardware.h> + +#define	MASK_CLE	0x10 +#define	MASK_ALE	0x0a + +#define NAND_CE0CLE	((volatile u_int8_t *)(CFG_NAND_BASE + 0x10)) +#define NAND_CE0ALE	((volatile u_int8_t *)(CFG_NAND_BASE + 0x0a)) +#define NAND_CE0DATA	((volatile u_int8_t *)CFG_NAND_BASE) + +typedef struct  { +	u_int32_t	NRCSR; +	u_int32_t	AWCCR; +	u_int8_t	RSVD0[8]; +	u_int32_t	AB1CR; +	u_int32_t	AB2CR; +	u_int32_t	AB3CR; +	u_int32_t	AB4CR; +	u_int8_t	RSVD1[32]; +	u_int32_t	NIRR; +	u_int32_t	NIMR; +	u_int32_t	NIMSR; +	u_int32_t	NIMCR; +	u_int8_t	RSVD2[16]; +	u_int32_t	NANDFCR; +	u_int32_t	NANDFSR; +	u_int8_t	RSVD3[8]; +	u_int32_t	NANDF1ECC; +	u_int32_t	NANDF2ECC; +	u_int32_t	NANDF3ECC; +	u_int32_t	NANDF4ECC; +	u_int8_t	RSVD4[4]; +	u_int32_t	IODFTECR; +	u_int32_t	IODFTGCR; +	u_int8_t	RSVD5[4]; +	u_int32_t	IODFTMRLR; +	u_int32_t	IODFTMRMR; +	u_int32_t	IODFTMRMSBR; +	u_int8_t	RSVD6[20]; +	u_int32_t	MODRNR; +	u_int8_t	RSVD7[76]; +	u_int32_t	CE0DATA; +	u_int32_t	CE0ALE; +	u_int32_t	CE0CLE; +	u_int8_t	RSVD8[4]; +	u_int32_t	CE1DATA; +	u_int32_t	CE1ALE; +	u_int32_t	CE1CLE; +	u_int8_t	RSVD9[4]; +	u_int32_t	CE2DATA; +	u_int32_t	CE2ALE; +	u_int32_t	CE2CLE; +	u_int8_t	RSVD10[4]; +	u_int32_t	CE3DATA; +	u_int32_t	CE3ALE; +	u_int32_t	CE3CLE; +} nand_registers; + +typedef volatile nand_registers	*nandregs; + +#define NAND_READ_START		0x00 +#define NAND_READ_END		0x30 +#define NAND_STATUS		0x70 + +#ifdef CFG_NAND_HW_ECC +#define NAND_Ecc_P1e		(1 << 0) +#define NAND_Ecc_P2e		(1 << 1) +#define NAND_Ecc_P4e		(1 << 2) +#define NAND_Ecc_P8e		(1 << 3) +#define NAND_Ecc_P16e		(1 << 4) +#define NAND_Ecc_P32e		(1 << 5) +#define NAND_Ecc_P64e		(1 << 6) +#define NAND_Ecc_P128e		(1 << 7) +#define NAND_Ecc_P256e		(1 << 8) +#define NAND_Ecc_P512e		(1 << 9) +#define NAND_Ecc_P1024e		(1 << 10) +#define NAND_Ecc_P2048e		(1 << 11) + +#define NAND_Ecc_P1o		(1 << 16) +#define NAND_Ecc_P2o		(1 << 17) +#define NAND_Ecc_P4o		(1 << 18) +#define NAND_Ecc_P8o		(1 << 19) +#define NAND_Ecc_P16o		(1 << 20) +#define NAND_Ecc_P32o		(1 << 21) +#define NAND_Ecc_P64o		(1 << 22) +#define NAND_Ecc_P128o		(1 << 23) +#define NAND_Ecc_P256o		(1 << 24) +#define NAND_Ecc_P512o		(1 << 25) +#define NAND_Ecc_P1024o		(1 << 26) +#define NAND_Ecc_P2048o		(1 << 27) + +#define TF(v)			(v ? 1 : 0) + +#define P2048e(a)		(TF(a & NAND_Ecc_P2048e) << 0) +#define P2048o(a)		(TF(a & NAND_Ecc_P2048o) << 1) +#define P1e(a)			(TF(a & NAND_Ecc_P1e) << 2) +#define P1o(a)			(TF(a & NAND_Ecc_P1o) << 3) +#define P2e(a)			(TF(a & NAND_Ecc_P2e) << 4) +#define P2o(a)			(TF(a & NAND_Ecc_P2o) << 5) +#define P4e(a)			(TF(a & NAND_Ecc_P4e) << 6) +#define P4o(a)			(TF(a & NAND_Ecc_P4o) << 7) + +#define P8e(a)			(TF(a & NAND_Ecc_P8e) << 0) +#define P8o(a)			(TF(a & NAND_Ecc_P8o) << 1) +#define P16e(a)			(TF(a & NAND_Ecc_P16e) << 2) +#define P16o(a)			(TF(a & NAND_Ecc_P16o) << 3) +#define P32e(a)			(TF(a & NAND_Ecc_P32e) << 4) +#define P32o(a)			(TF(a & NAND_Ecc_P32o) << 5) +#define P64e(a)			(TF(a & NAND_Ecc_P64e) << 6) +#define P64o(a)			(TF(a & NAND_Ecc_P64o) << 7) + +#define P128e(a)		(TF(a & NAND_Ecc_P128e) << 0) +#define P128o(a)		(TF(a & NAND_Ecc_P128o) << 1) +#define P256e(a)		(TF(a & NAND_Ecc_P256e) << 2) +#define P256o(a)		(TF(a & NAND_Ecc_P256o) << 3) +#define P512e(a)		(TF(a & NAND_Ecc_P512e) << 4) +#define P512o(a)		(TF(a & NAND_Ecc_P512o) << 5) +#define P1024e(a)		(TF(a & NAND_Ecc_P1024e) << 6) +#define P1024o(a)		(TF(a & NAND_Ecc_P1024o) << 7) + +#define P8e_s(a)		(TF(a & NAND_Ecc_P8e) << 0) +#define P8o_s(a)		(TF(a & NAND_Ecc_P8o) << 1) +#define P16e_s(a)		(TF(a & NAND_Ecc_P16e) << 2) +#define P16o_s(a)		(TF(a & NAND_Ecc_P16o) << 3) +#define P1e_s(a)		(TF(a & NAND_Ecc_P1e) << 4) +#define P1o_s(a)		(TF(a & NAND_Ecc_P1o) << 5) +#define P2e_s(a)		(TF(a & NAND_Ecc_P2e) << 6) +#define P2o_s(a)		(TF(a & NAND_Ecc_P2o) << 7) + +#define P4e_s(a)		(TF(a & NAND_Ecc_P4e) << 0) +#define P4o_s(a)		(TF(a & NAND_Ecc_P4o) << 1) +#endif + +#endif diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index ebda7192e..e8cb29903 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -592,9 +592,11 @@ typedef void		(*ExcpHndlr) (void) ;  #define PMC_REG_BASE	__REG(0x40500400)  /* Primary Modem Codec */  #define SMC_REG_BASE	__REG(0x40500500)  /* Secondary Modem Codec */ +  /*   * USB Device Controller   */ +#ifndef CONFIG_CPU_MONAHANS  #define UDC_RES1	__REG(0x40600004)  /* UDC Undocumented - Reserved1 */  #define UDC_RES2	__REG(0x40600008)  /* UDC Undocumented - Reserved2 */  #define UDC_RES3	__REG(0x4060000C)  /* UDC Undocumented - Reserved3 */ @@ -749,11 +751,28 @@ typedef void		(*ExcpHndlr) (void) ;  #define USIR1_IR13	(1 << 5)	/* Interrup request ep 13 */  #define USIR1_IR14	(1 << 6)	/* Interrup request ep 14 */  #define USIR1_IR15	(1 << 7)	/* Interrup request ep 15 */ +#endif /* ! CONFIG_CPU_MONAHANS */ + +#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS) + +/* + * USB Client Controller (incomplete) + */ +#define UDCCR		__REG(0x40600000) +#define UDCICR0		__REG(0x40600004) +#define UDCCIR0		__REG(0x40600008) +#define UDCISR0		__REG(0x4060000c) +#define UDCSIR1		__REG(0x40600010) +#define UDCFNR		__REG(0x40600014) +#define UDCOTGICR	__REG(0x40600018) +#define UDCOTGISR	__REG(0x4060001c) +#define UP2OCR		__REG(0x40600020) +#define UP3OCR		__REG(0x40600024) -#if defined(CONFIG_PXA27X)  /*   * USB Host Controller   */ +#define OHCI_REGS_BASE	0x4C000000	/* required for ohci driver */  #define UHCREV		__REG(0x4C000000)  #define UHCHCON		__REG(0x4C000004)  #define UHCCOMS		__REG(0x4C000008) diff --git a/include/common.h b/include/common.h index ac29d3aac..27a660a4d 100644 --- a/include/common.h +++ b/include/common.h @@ -241,6 +241,9 @@ int	saveenv	     (void);  void inline setenv   (char *, char *);  #else  void	setenv	     (char *, char *); +#ifdef CONFIG_HAS_UID +void	forceenv     (char *, char *); +#endif  #endif /* CONFIG_PPC */  #ifdef CONFIG_ARM  # include <asm/mach-types.h> @@ -526,6 +529,8 @@ void	cpu_init_f    (void);  int	cpu_init_r    (void);  #if defined(CONFIG_8260)  int	prt_8260_rsr  (void); +#elif defined(CONFIG_MPC83XX) +int	prt_83xx_rsr  (void);  #endif  /* $(CPU)/interrupts.c */ diff --git a/include/configs/AdderUSB.h b/include/configs/AdderUSB.h new file mode 100644 index 000000000..a4f7f9a28 --- /dev/null +++ b/include/configs/AdderUSB.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2006 CodeHermit. + * Bryan O'Donoghue <bodonoghue@codehermit.ie> + * + * Provides support for USB console on the Analogue & Micro Adder87x + * + * 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 + */ + +#ifndef __ADDERUSB__ +#define __ADDERUSB__ + +/* Include the board port */ +#include "Adder.h" + +#define CONFIG_USB_DEVICE		/* Include UDC driver */ +#define CONFIG_USB_TTY			/* Bind the TTY driver to UDC */ +#define CFG_USB_EXTC_CLK 0x02		/* Oscillator on EXTC_CLK 2 */ +#define CFG_USB_BRG_CLK	0x04		/* or use Baud rate generator 0x04 */ +#define CFG_CONSOLE_IS_IN_ENV		/* Console is in env */ + +/* If you have a USB-IF assigned VendorID then you may wish to define + * your own vendor specific values either in BoardName.h or directly in + * usbd_vendor_info.h + */ + +/* +#define CONFIG_USBD_MANUFACTURER	"CodeHermit.ie" +#define CONFIG_USBD_PRODUCT_NAME	"Das U-Boot" +#define CONFIG_USBD_VENDORID		0xFFFF +#define CONFIG_USBD_PRODUCTID_GSERIAL	0xFFFF +#define CONFIG_USBD_PRODUCTID_CDCACM	0xFFFE +*/ + +#endif /* __ADDERUSB_H__ */ diff --git a/include/configs/IceCube.h b/include/configs/IceCube.h index cc902c842..1a7167b48 100644 --- a/include/configs/IceCube.h +++ b/include/configs/IceCube.h @@ -84,10 +84,15 @@  #define CONFIG_ISO_PARTITION  /* USB */ -#if 1 -#define CONFIG_USB_OHCI +#define CONFIG_USB_OHCI_NEW +#define ADD_USB_CMD             CFG_CMD_USB | CFG_CMD_FAT  #define CONFIG_USB_STORAGE -#endif +#define CFG_OHCI_BE_CONTROLLER +#undef CFG_USB_OHCI_BOARD_INIT +#define CFG_USB_OHCI_CPU_INIT	1 +#define CFG_USB_OHCI_REGS_BASE	MPC5XXX_USB +#define CFG_USB_OHCI_SLOT_NAME	"mpc5200" +#define CFG_USB_OHCI_MAX_ROOT_PORTS	15  #define	CONFIG_TIMESTAMP		/* Print image info with timestamp */ diff --git a/include/configs/MPC8323ERDB.h b/include/configs/MPC8323ERDB.h new file mode 100644 index 000000000..376973b94 --- /dev/null +++ b/include/configs/MPC8323ERDB.h @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2007 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#undef DEBUG + +/* + * High Level Configuration Options + */ +#define CONFIG_E300		1	/* E300 family */ +#define CONFIG_QE		1	/* Has QE */ +#define CONFIG_MPC83XX		1	/* MPC83xx family */ +#define CONFIG_MPC832X		1	/* MPC832x CPU specific */ + +#define CONFIG_PCI		1 +#define CONFIG_83XX_GENERIC_PCI	1 + +/* + * System Clock Setup + */ +#define CONFIG_83XX_CLKIN	66666667	/* in Hz */ + +#ifndef CONFIG_SYS_CLK_FREQ +#define CONFIG_SYS_CLK_FREQ	CONFIG_83XX_CLKIN +#endif + +/* + * Hardware Reset Configuration Word + */ +#define CFG_HRCW_LOW (\ +	HRCWL_LCL_BUS_TO_SCB_CLK_1X1 |\ +	HRCWL_DDR_TO_SCB_CLK_2X1 |\ +	HRCWL_VCO_1X2 |\ +	HRCWL_CSB_TO_CLKIN_2X1 |\ +	HRCWL_CORE_TO_CSB_2_5X1 |\ +	HRCWL_CE_PLL_VCO_DIV_2 |\ +	HRCWL_CE_PLL_DIV_1X1 |\ +	HRCWL_CE_TO_PLL_1X3) + +#define CFG_HRCW_HIGH (\ +	HRCWH_PCI_HOST |\ +	HRCWH_PCI1_ARBITER_ENABLE |\ +	HRCWH_CORE_ENABLE |\ +	HRCWH_FROM_0X00000100 |\ +	HRCWH_BOOTSEQ_DISABLE |\ +	HRCWH_SW_WATCHDOG_DISABLE |\ +	HRCWH_ROM_LOC_LOCAL_16BIT |\ +	HRCWH_BIG_ENDIAN |\ +	HRCWH_LALE_NORMAL) + +/* + * System IO Config + */ +#define CFG_SICRL		0x00000000 + +#define CONFIG_BOARD_EARLY_INIT_F	/* call board_pre_init */ + +/* + * IMMR new address + */ +#define CFG_IMMR		0xE0000000 + +/* + * DDR Setup + */ +#define CFG_DDR_BASE		0x00000000	/* DDR is system memory */ +#define CFG_SDRAM_BASE		CFG_DDR_BASE +#define CFG_DDR_SDRAM_BASE	CFG_DDR_BASE +#define CFG_DDRCDR		0x73000002	/* DDR II voltage is 1.8V */ + +#undef CONFIG_SPD_EEPROM +#if defined(CONFIG_SPD_EEPROM) +/* Determine DDR configuration from I2C interface + */ +#define SPD_EEPROM_ADDRESS	0x51	/* DDR SODIMM */ +#else +/* Manually set up DDR parameters + */ +#define CFG_DDR_SIZE		64	/* MB */ +#define CFG_DDR_CS0_CONFIG	0x80840101 +#define CFG_DDR_TIMING_0	0x00220802 +#define CFG_DDR_TIMING_1	0x3935d322 +#define CFG_DDR_TIMING_2	0x0f9048ca +#define CFG_DDR_TIMING_3	0x00000000 +#define CFG_DDR_CLK_CNTL	0x02000000 +#define CFG_DDR_MODE		0x44400232 +#define CFG_DDR_MODE2		0x8000c000 +#define CFG_DDR_INTERVAL	0x03200064 +#define CFG_DDR_CS0_BNDS	0x00000003 +#define CFG_DDR_SDRAM_CFG	0x43080000 +#define CFG_DDR_SDRAM_CFG2	0x00401000 +#endif + +/* + * Memory test + */ +#undef CFG_DRAM_TEST		/* memory test, takes time */ +#define CFG_MEMTEST_START	0x00030000	/* memtest region */ +#define CFG_MEMTEST_END		0x03f00000 + +/* + * The reserved memory + */ +#define CFG_MONITOR_BASE	TEXT_BASE	/* start of monitor */ + +#if (CFG_MONITOR_BASE < CFG_FLASH_BASE) +#define CFG_RAMBOOT +#else +#undef  CFG_RAMBOOT +#endif + +#define CFG_MONITOR_LEN		(256 * 1024)	/* Reserve 256 kB for Mon */ +#define CFG_MALLOC_LEN		(128 * 1024)	/* Reserved for malloc */ + +/* + * Initial RAM Base Address Setup + */ +#define CFG_INIT_RAM_LOCK	1 +#define CFG_INIT_RAM_ADDR	0xE6000000	/* Initial RAM address */ +#define CFG_INIT_RAM_END	0x1000		/* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE	0x100		/* num bytes initial data */ +#define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + +/* + * Local Bus Configuration & Clock Setup + */ +#define CFG_LCRR		(LCRR_DBYP | LCRR_CLKDIV_2) +#define CFG_LBC_LBCR		0x00000000 + +/* + * FLASH on the Local Bus + */ +#define CFG_FLASH_CFI		/* use the Common Flash Interface */ +#define CFG_FLASH_CFI_DRIVER	/* use the CFI driver */ +#define CFG_FLASH_BASE		0xFE000000	/* FLASH base address */ +#define CFG_FLASH_SIZE		16	/* FLASH size is 16M */ + +#define CFG_LBLAWBAR0_PRELIM	CFG_FLASH_BASE	/* Window base at flash base */ +#define CFG_LBLAWAR0_PRELIM	0x80000018	/* 32MB window size */ + +#define CFG_BR0_PRELIM	(CFG_FLASH_BASE |	/* Flash Base address */ \ +			(2 << BR_PS_SHIFT) |	/* 16 bit port size */ \ +			BR_V)			/* valid */ +#define CFG_OR0_PRELIM		0xfe006ff7	/* 16MB Flash size */ + +#define CFG_MAX_FLASH_BANKS	1		/* number of banks */ +#define CFG_MAX_FLASH_SECT	128		/* sectors per device */ + +#undef CFG_FLASH_CHECKSUM + +/* + * SDRAM on the Local Bus + */ +#undef CFG_LB_SDRAM		/* The board has not SRDAM on local bus */ + +#ifdef CFG_LB_SDRAM +#define CFG_LBC_SDRAM_BASE	0xF0000000	/* SDRAM base address */ +#define CFG_LBC_SDRAM_SIZE	64		/* LBC SDRAM is 64MB */ + +#define CFG_LBLAWBAR2_PRELIM	CFG_LBC_SDRAM_BASE +#define CFG_LBLAWAR2_PRELIM	0x80000019	/* 64MB */ + +/*local bus BR2, OR2 definition for SDRAM if soldered on the EPB board */ +/* + * Base Register 2 and Option Register 2 configure SDRAM. + * The SDRAM base address, CFG_LBC_SDRAM_BASE, is 0xf0000000. + * + * For BR2, need: + *    Base address of 0xf0000000 = BR[0:16] = 1111 0000 0000 0000 0 + *    port size = 32-bits = BR2[19:20] = 11 + *    no parity checking = BR2[21:22] = 00 + *    SDRAM for MSEL = BR2[24:26] = 011 + *    Valid = BR[31] = 1 + * + * 0    4    8    12   16   20   24   28 + * 1111 0000 0000 0000 0001 1000 0110 0001 = f0001861 + * + * CFG_LBC_SDRAM_BASE should be masked and OR'ed into + * the top 17 bits of BR2. + */ + +#define CFG_BR2_PRELIM	0xf0001861	/*Port size=32bit, MSEL=SDRAM */ + +/* + * The SDRAM size in MB, CFG_LBC_SDRAM_SIZE, is 64. + * + * For OR2, need: + *    64MB mask for AM, OR2[0:7] = 1111 1100 + *                 XAM, OR2[17:18] = 11 + *    9 columns OR2[19-21] = 010 + *    13 rows   OR2[23-25] = 100 + *    EAD set for extra time OR[31] = 1 + * + * 0    4    8    12   16   20   24   28 + * 1111 1100 0000 0000 0110 1001 0000 0001 = fc006901 + */ + +#define CFG_OR2_PRELIM	0xfc006901 + +#define CFG_LBC_LSRT	0x32000000	/* LB sdram refresh timer, about 6us */ +#define CFG_LBC_MRTPR	0x20000000	/* LB refresh timer prescal, 266MHz/32 */ + +/* + * LSDMR masks + */ +#define CFG_LBC_LSDMR_OP_NORMAL	(0 << (31 - 4)) +#define CFG_LBC_LSDMR_OP_ARFRSH	(1 << (31 - 4)) +#define CFG_LBC_LSDMR_OP_SRFRSH	(2 << (31 - 4)) +#define CFG_LBC_LSDMR_OP_MRW	(3 << (31 - 4)) +#define CFG_LBC_LSDMR_OP_PRECH	(4 << (31 - 4)) +#define CFG_LBC_LSDMR_OP_PCHALL	(5 << (31 - 4)) +#define CFG_LBC_LSDMR_OP_ACTBNK	(6 << (31 - 4)) +#define CFG_LBC_LSDMR_OP_RWINV	(7 << (31 - 4)) + +#define CFG_LBC_LSDMR_COMMON	0x0063b723 + +/* + * SDRAM Controller configuration sequence. + */ +#define CFG_LBC_LSDMR_1		( CFG_LBC_LSDMR_COMMON \ +				| CFG_LBC_LSDMR_OP_PCHALL) +#define CFG_LBC_LSDMR_2		( CFG_LBC_LSDMR_COMMON \ +				| CFG_LBC_LSDMR_OP_ARFRSH) +#define CFG_LBC_LSDMR_3		( CFG_LBC_LSDMR_COMMON \ +				| CFG_LBC_LSDMR_OP_ARFRSH) +#define CFG_LBC_LSDMR_4		( CFG_LBC_LSDMR_COMMON \ +				| CFG_LBC_LSDMR_OP_MRW) +#define CFG_LBC_LSDMR_5		( CFG_LBC_LSDMR_COMMON \ +				| CFG_LBC_LSDMR_OP_NORMAL) + +#endif + +/* + * Windows to access PIB via local bus + */ +#define CFG_LBLAWBAR3_PRELIM	0xf8008000	/* windows base 0xf8008000 */ +#define CFG_LBLAWAR3_PRELIM	0x8000000f	/* windows size 64KB */ + +/* + * Serial Port + */ +#define CONFIG_CONS_INDEX	1 +#undef CONFIG_SERIAL_SOFTWARE_FIFO +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE	1 +#define CFG_NS16550_CLK		get_bus_freq(0) + +#define CFG_BAUDRATE_TABLE  \ +	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400,115200} + +#define CFG_NS16550_COM1	(CFG_IMMR+0x4500) +#define CFG_NS16550_COM2	(CFG_IMMR+0x4600) + +#define CONFIG_CMDLINE_EDITING	1	/* add command line history */ +/* Use the HUSH parser */ +#define CFG_HUSH_PARSER +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +/* pass open firmware flat tree */ +#define CONFIG_OF_LIBFDT	1 +#define CONFIG_OF_BOARD_SETUP	1 + +#define OF_CPU			"PowerPC,8323@0" +#define OF_SOC			"soc8323@e0000000" +#define OF_QE			"qe@e0100000" +#define OF_TBCLK		(bd->bi_busfreq / 4) +#define OF_STDOUT_PATH		"/soc8323@e0000000/serial@4500" + +/* I2C */ +#define CONFIG_HARD_I2C		/* I2C with hardware support */ +#undef CONFIG_SOFT_I2C		/* I2C bit-banged */ +#define CONFIG_FSL_I2C +#define CFG_I2C_SPEED	400000	/* I2C speed and slave address */ +#define CFG_I2C_SLAVE	0x7F +#define CFG_I2C_NOPROBES	{0x51}	/* Don't probe these addrs */ +#define CFG_I2C_OFFSET	0x3000 + +/* + * Config on-board RTC + */ +#define CONFIG_RTC_DS1374		/* use ds1374 rtc via i2c */ +#define CFG_I2C_RTC_ADDR	0x68	/* at address 0x68 */ + +/* + * General PCI + * Addresses are mapped 1-1. + */ +#define CFG_PCI1_MEM_BASE	0x80000000 +#define CFG_PCI1_MEM_PHYS	CFG_PCI1_MEM_BASE +#define CFG_PCI1_MEM_SIZE	0x10000000	/* 256M */ +#define CFG_PCI1_MMIO_BASE	0x90000000 +#define CFG_PCI1_MMIO_PHYS	CFG_PCI1_MMIO_BASE +#define CFG_PCI1_MMIO_SIZE	0x10000000	/* 256M */ +#define CFG_PCI1_IO_BASE		0xd0000000 +#define CFG_PCI1_IO_PHYS		CFG_PCI1_IO_BASE +#define CFG_PCI1_IO_SIZE		0x04000000	/* 64M */ + +#ifdef CONFIG_PCI + +#define CONFIG_NET_MULTI +#define CONFIG_PCI_PNP		/* do pci plug-and-play */ + +#undef CONFIG_EEPRO100 +#undef CONFIG_PCI_SCAN_SHOW	/* show pci devices on startup */ +#define CFG_PCI_SUBSYS_VENDORID	0x1957	/* Freescale */ + +#endif	/* CONFIG_PCI */ + + +#ifndef CONFIG_NET_MULTI +#define CONFIG_NET_MULTI	1 +#endif + +/* + * QE UEC ethernet configuration + */ +#define CONFIG_UEC_ETH +#define CONFIG_ETHPRIME		"Freescale GETH" + +#define CONFIG_UEC_ETH1		/* ETH3 */ + +#ifdef CONFIG_UEC_ETH1 +#define CFG_UEC1_UCC_NUM	2	/* UCC3 */ +#define CFG_UEC1_RX_CLK		QE_CLK9 +#define CFG_UEC1_TX_CLK		QE_CLK10 +#define CFG_UEC1_ETH_TYPE	FAST_ETH +#define CFG_UEC1_PHY_ADDR	4 +#define CFG_UEC1_INTERFACE_MODE	ENET_100_MII +#endif + +#define CONFIG_UEC_ETH2		/* ETH4 */ + +#ifdef CONFIG_UEC_ETH2 +#define CFG_UEC2_UCC_NUM	1	/* UCC2 */ +#define CFG_UEC2_RX_CLK		QE_CLK16 +#define CFG_UEC2_TX_CLK		QE_CLK3 +#define CFG_UEC2_ETH_TYPE	FAST_ETH +#define CFG_UEC2_PHY_ADDR	0 +#define CFG_UEC2_INTERFACE_MODE	ENET_100_MII +#endif + +/* + * Environment + */ +#ifndef CFG_RAMBOOT +	#define CFG_ENV_IS_IN_FLASH	1 +	#define CFG_ENV_ADDR		(CFG_MONITOR_BASE + 0x40000) +	#define CFG_ENV_SECT_SIZE	0x40000	/* 256K(one sector) for env */ +	#define CFG_ENV_SIZE		0x2000 +#else +	#define CFG_NO_FLASH		1	/* Flash is not usable now */ +	#define CFG_ENV_IS_NOWHERE	1	/* Store ENV in memory only */ +	#define CFG_ENV_ADDR		(CFG_MONITOR_BASE - 0x1000) +	#define CFG_ENV_SIZE		0x2000 +#endif + +#define CONFIG_LOADS_ECHO	1	/* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE	1	/* allow baudrate change */ + +/* + * BOOTP options + */ +#define CONFIG_BOOTP_BOOTFILESIZE +#define CONFIG_BOOTP_BOOTPATH +#define CONFIG_BOOTP_GATEWAY +#define CONFIG_BOOTP_HOSTNAME + +/* + * Command line configuration. + */ +#include <config_cmd_default.h> + +#define CONFIG_CMD_PING +#define CONFIG_CMD_I2C +#define CONFIG_CMD_ASKENV + +#if defined(CONFIG_PCI) +	#define CONFIG_CMD_PCI +#endif +#if defined(CFG_RAMBOOT) +	#undef CONFIG_CMD_ENV +	#undef CONFIG_CMD_LOADS +#endif + +#undef CONFIG_WATCHDOG		/* watchdog disabled */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP		/* undef to save memory */ +#define CFG_LOAD_ADDR		0x2000000	/* default load address */ +#define CFG_PROMPT		"=> "	/* Monitor Command Prompt */ + +#if (CONFIG_CMD_KGDB) +	#define CFG_CBSIZE	1024	/* Console I/O Buffer Size */ +#else +	#define CFG_CBSIZE	256	/* Console I/O Buffer Size */ +#endif + +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)	/* Print Buffer Size */ +#define CFG_MAXARGS	16		/* max number of command args */ +#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size */ +#define CFG_HZ		1000		/* decrementer freq: 1ms ticks */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ		(8 << 20)	/* Initial Memory map for Linux */ + +/* + * Core HID Setup + */ +#define CFG_HID0_INIT		0x000000000 +#define CFG_HID0_FINAL		HID0_ENABLE_MACHINE_CHECK +#define CFG_HID2		HID2_HBE + +/* + * Cache Config + */ +#define CFG_DCACHE_SIZE		16384 +#define CFG_CACHELINE_SIZE	32 +#if defined(CONFIG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT	5	/*log base 2 of the above value */ +#endif + +/* + * MMU Setup + */ + +/* DDR: cache cacheable */ +#define CFG_IBAT0L	(CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U	(CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT0L	CFG_IBAT0L +#define CFG_DBAT0U	CFG_IBAT0U + +/* IMMRBAR & PCI IO: cache-inhibit and guarded */ +#define CFG_IBAT1L	(CFG_IMMR | BATL_PP_10 | \ +			BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_IBAT1U	(CFG_IMMR | BATU_BL_4M | BATU_VS | BATU_VP) +#define CFG_DBAT1L	CFG_IBAT1L +#define CFG_DBAT1U	CFG_IBAT1U + +/* FLASH: icache cacheable, but dcache-inhibit and guarded */ +#define CFG_IBAT2L	(CFG_FLASH_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT2U	(CFG_FLASH_BASE | BATU_BL_32M | BATU_VS | BATU_VP) +#define CFG_DBAT2L	(CFG_FLASH_BASE | BATL_PP_10 | \ +			BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_DBAT2U	CFG_IBAT2U + +#define CFG_IBAT3L	(0) +#define CFG_IBAT3U	(0) +#define CFG_DBAT3L	CFG_IBAT3L +#define CFG_DBAT3U	CFG_IBAT3U + +/* Stack in dcache: cacheable, no memory coherence */ +#define CFG_IBAT4L	(CFG_INIT_RAM_ADDR | BATL_PP_10) +#define CFG_IBAT4U	(CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) +#define CFG_DBAT4L	CFG_IBAT4L +#define CFG_DBAT4U	CFG_IBAT4U + +#ifdef CONFIG_PCI +/* PCI MEM space: cacheable */ +#define CFG_IBAT5L	(CFG_PCI1_MEM_PHYS | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT5U	(CFG_PCI1_MEM_PHYS | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT5L	CFG_IBAT5L +#define CFG_DBAT5U	CFG_IBAT5U +/* PCI MMIO space: cache-inhibit and guarded */ +#define CFG_IBAT6L	(CFG_PCI1_MMIO_PHYS | BATL_PP_10 | \ +			BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_IBAT6U	(CFG_PCI1_MMIO_PHYS | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT6L	CFG_IBAT6L +#define CFG_DBAT6U	CFG_IBAT6U +#else +#define CFG_IBAT5L	(0) +#define CFG_IBAT5U	(0) +#define CFG_IBAT6L	(0) +#define CFG_IBAT6U	(0) +#define CFG_DBAT5L	CFG_IBAT5L +#define CFG_DBAT5U	CFG_IBAT5U +#define CFG_DBAT6L	CFG_IBAT6L +#define CFG_DBAT6U	CFG_IBAT6U +#endif + +/* Nothing in BAT7 */ +#define CFG_IBAT7L	(0) +#define CFG_IBAT7U	(0) +#define CFG_DBAT7L	CFG_IBAT7L +#define CFG_DBAT7U	CFG_IBAT7U + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD	0x01	/* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM	0x02	/* Software reboot */ + +#if (CONFIG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE	230400	/* speed of kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX	2	/* which serial port to use */ +#endif + +/* + * Environment Configuration + */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_ETHADDR	00:04:9f:ef:03:01 +#define CONFIG_HAS_ETH1				/* add support for "eth1addr" */ +#define CONFIG_ETH1ADDR	00:04:9f:ef:03:02 + +#define CONFIG_IPADDR		10.0.0.2 +#define CONFIG_SERVERIP		10.0.0.1 +#define CONFIG_GATEWAYIP	10.0.0.1 +#define CONFIG_NETMASK		255.0.0.0 +#define CONFIG_NETDEV		eth1 + +#define CONFIG_HOSTNAME		mpc8323erdb +#define CONFIG_ROOTPATH		/nfsroot +#define CONFIG_RAMDISKFILE	rootfs.ext2.gz.uboot +#define CONFIG_BOOTFILE		uImage +#define CONFIG_UBOOTPATH	u-boot.bin	/* U-Boot image on TFTP server */ +#define CONFIG_FDTFILE		mpc832x_rdb.dtb + +#define CONFIG_LOADADDR		200000	/* default location for tftp and bootm */ +#define CONFIG_BOOTDELAY	-1	/* -1 disables auto-boot */ +#define CONFIG_BAUDRATE		115200 + +#define XMK_STR(x)	#x +#define MK_STR(x)	XMK_STR(x) + +#define CONFIG_EXTRA_ENV_SETTINGS \ +	"netdev=" MK_STR(CONFIG_NETDEV) "\0"				\ +	"uboot=" MK_STR(CONFIG_UBOOTPATH) "\0"				\ +	"tftpflash=tftp $loadaddr $uboot;"				\ +		"protect off " MK_STR(TEXT_BASE) " +$filesize; "	\ +		"erase " MK_STR(TEXT_BASE) " +$filesize; "		\ +		"cp.b $loadaddr " MK_STR(TEXT_BASE) " $filesize; "	\ +		"protect on " MK_STR(TEXT_BASE) " +$filesize; "		\ +		"cmp.b $loadaddr " MK_STR(TEXT_BASE) " $filesize\0"	\ +	"fdtaddr=400000\0"						\ +	"fdtfile=" MK_STR(CONFIG_FDTFILE) "\0"				\ +	"ramdiskaddr=1000000\0"						\ +	"ramdiskfile=" MK_STR(CONFIG_RAMDISKFILE) "\0"			\ +	"console=ttyS0\0"						\ +	"setbootargs=setenv bootargs "					\ +		"root=$rootdev rw console=$console,$baudrate $othbootargs\0" \ +	"setipargs=setenv bootargs nfsroot=$serverip:$rootpath "	\ +		"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \ +		"root=$rootdev rw console=$console,$baudrate $othbootargs\0" + +#define CONFIG_NFSBOOTCOMMAND						\ +	"setenv rootdev /dev/nfs;"					\ +	"run setbootargs;"						\ +	"run setipargs;"						\ +	"tftp $loadaddr $bootfile;"					\ +	"tftp $fdtaddr $fdtfile;"					\ +	"bootm $loadaddr - $fdtaddr" + +#define CONFIG_RAMBOOTCOMMAND						\ +	"setenv rootdev /dev/ram;"					\ +	"run setbootargs;"						\ +	"tftp $ramdiskaddr $ramdiskfile;"				\ +	"tftp $loadaddr $bootfile;"					\ +	"tftp $fdtaddr $fdtfile;"					\ +	"bootm $loadaddr $ramdiskaddr $fdtaddr" + +#undef MK_STR +#undef XMK_STR + +#endif	/* __CONFIG_H */ diff --git a/include/configs/MPC8349ITX.h b/include/configs/MPC8349ITX.h index 121ff06dc..44649d050 100644 --- a/include/configs/MPC8349ITX.h +++ b/include/configs/MPC8349ITX.h @@ -289,6 +289,7 @@ boards, we say we have two, but don't display a message if we find only one. */  #define CFG_BAUDRATE_TABLE  \  	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 115200} +#define CONFIG_CONSOLE		ttyS0  #define CONFIG_BAUDRATE		115200  #define CFG_NS16550_COM1	(CFG_IMMR + 0x4500) @@ -408,6 +409,7 @@ boards, we say we have two, but don't display a message if we find only one. */    #define CFG_ENV_SIZE		0x2000  #else    #define CFG_NO_FLASH		/* Flash is not usable now */ +  #undef  CFG_FLASH_CFI_DRIVER    #define CFG_ENV_IS_NOWHERE	/* Store ENV in memory only */    #define CFG_ENV_ADDR		(CFG_MONITOR_BASE - 0x1000)    #define CFG_ENV_SIZE		0x2000 @@ -450,9 +452,7 @@ boards, we say we have two, but don't display a message if we find only one. */      #define CONFIG_CMD_I2C  #endif -  /* Watchdog */ -  #undef CONFIG_WATCHDOG		/* watchdog disabled */  /* @@ -673,9 +673,10 @@ boards, we say we have two, but don't display a message if we find only one. */  	" ip=" MK_STR(CONFIG_IPADDR) ":" MK_STR(CONFIG_SERVERIP) ":" 	\  		MK_STR(CONFIG_GATEWAYIP) ":" MK_STR(CONFIG_NETMASK) ":" \  		MK_STR(CONFIG_HOSTNAME) ":" MK_STR(CONFIG_NETDEV) ":off" \ -	" console=ttyS0," MK_STR(CONFIG_BAUDRATE) +	" console=" MK_STR(CONFIG_CONSOLE) "," MK_STR(CONFIG_BAUDRATE)  #define CONFIG_EXTRA_ENV_SETTINGS \ +	"console=" MK_STR(CONFIG_CONSOLE) "\0" 				\  	"netdev=" MK_STR(CONFIG_NETDEV) "\0" 				\  	"uboot=" MK_STR(CONFIG_UBOOTPATH) "\0" 				\  	"tftpflash=tftpboot $loadaddr $uboot; " 			\ diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 888af530c..64dcbd010 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -338,6 +338,17 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);  #undef CONFIG_EEPRO100  #undef CONFIG_TULIP +/************************************************************ + * USB support + ************************************************************/ +#define CONFIG_PCI_OHCI		1 +#define CONFIG_USB_OHCI_NEW		1 +#define CONFIG_USB_KEYBOARD	1 +#define CFG_DEVICE_DEREGISTER +#define CFG_USB_EVENT_POLL	1 +#define CFG_USB_OHCI_SLOT_NAME 	"ohci_pci" +#define CFG_USB_OHCI_MAX_ROOT_PORTS 15 +  #if !defined(CONFIG_PCI_PNP)      #define PCI_ENET0_IOADDR	0xe0000000      #define PCI_ENET0_MEMADDR	0xe0000000 diff --git a/include/configs/TQM5200.h b/include/configs/TQM5200.h index 63d77e294..8360d8c0d 100644 --- a/include/configs/TQM5200.h +++ b/include/configs/TQM5200.h @@ -130,8 +130,18 @@  /* USB */  #if defined(CONFIG_STK52XX) || defined(CONFIG_FO300) -#define CONFIG_USB_OHCI +#define CONFIG_USB_OHCI_NEW +#define ADD_USB_CMD		CFG_CMD_USB | CFG_CMD_FAT  #define CONFIG_USB_STORAGE + +#undef CFG_USB_OHCI_BOARD_INIT +#define CFG_USB_OHCI_CPU_INIT +#define CFG_USB_OHCI_REGS_BASE	MPC5XXX_USB +#define CFG_USB_OHCI_SLOT_NAME	"mpc5200" +#define CFG_USB_OHCI_MAX_ROOT_PORTS	15 + +#else +#define ADD_USB_CMD		0  #endif  #ifndef CONFIG_CAM5200 diff --git a/include/configs/TQM834x.h b/include/configs/TQM834x.h index c3efb7bb9..661712b22 100644 --- a/include/configs/TQM834x.h +++ b/include/configs/TQM834x.h @@ -28,9 +28,6 @@  #ifndef __CONFIG_H  #define __CONFIG_H -#define DEBUG -#undef DEBUG -  /*   * High Level Configuration Options   */ diff --git a/include/configs/davinci_dvevm.h b/include/configs/davinci_dvevm.h new file mode 100644 index 000000000..8ecd0595a --- /dev/null +++ b/include/configs/davinci_dvevm.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H +#include <asm/sizes.h> + +/* + * Define this to make U-Boot skip low level initialization when loaded + * by initial bootloader. Not required by NAND U-Boot version but IS + * required for a NOR version used to burn the real NOR U-Boot into + * NOR Flash. NAND and NOR support for DaVinci chips is mutually exclusive + * so it is NOT possible to build a U-Boot with both NAND and NOR routines. + * NOR U-Boot is loaded directly from Flash so it must perform all the + * low level initialization itself. NAND version is loaded by an initial + * bootloader (UBL in TI-ese) that performs such an initialization so it's + * skipped in NAND version. The third DaVinci boot mode loads a bootloader + * via UART0 and that bootloader in turn loads and runs U-Boot (or whatever) + * performing low level init prior to loading. All that means we can NOT use + * NAND version to put U-Boot into NOR because it doesn't have NOR support and + * we can NOT use NOR version because it performs low level initialization + * effectively destroying itself in DDR memory. That's why a separate NOR + * version with this define is needed. It is loaded via UART, then one uses + * it to somehow download a proper NOR version built WITHOUT this define to + * RAM (tftp?) and burn it to NOR Flash. I would be probably able to squeeze + * NOR support into the initial bootloader so it won't be needed but DaVinci + * static RAM might be too small for this (I have something like 2Kbytes left + * as of now, without NOR support) so this might've not happened... + * +#define CONFIG_NOR_UART_BOOT + */ + +/*=======*/ +/* Board */ +/*=======*/ +#define DV_EVM +#define CFG_NAND_SMALLPAGE +#define CFG_USE_NOR +/*===================*/ +/* SoC Configuration */ +/*===================*/ +#define CONFIG_ARM926EJS			/* arm926ejs CPU core */ +#define CONFIG_SYS_CLK_FREQ	297000000	/* Arm Clock frequency */ +#define CFG_TIMERBASE		0x01c21400	/* use timer 0 */ +#define CFG_HZ_CLOCK		27000000	/* Timer Input clock freq */ +#define CFG_HZ			1000 +/*====================================================*/ +/* EEPROM definitions for Atmel 24C256BN SEEPROM chip */ +/* on Sonata/DV_EVM board. No EEPROM on schmoogie.    */ +/*====================================================*/ +#define CFG_I2C_EEPROM_ADDR_LEN		2 +#define CFG_I2C_EEPROM_ADDR		0x50 +#define CFG_EEPROM_PAGE_WRITE_BITS	6 +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS	20 +/*=============*/ +/* Memory Info */ +/*=============*/ +#define CFG_MALLOC_LEN		(0x10000 + 128*1024)	/* malloc() len */ +#define CFG_GBL_DATA_SIZE	128		/* reserved for initial data */ +#define CFG_MEMTEST_START	0x80000000	/* memtest start address */ +#define CFG_MEMTEST_END		0x81000000	/* 16MB RAM test */ +#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */ +#define CONFIG_STACKSIZE	(256*1024)	/* regular stack */ +#define PHYS_SDRAM_1		0x80000000	/* DDR Start */ +#define PHYS_SDRAM_1_SIZE	0x10000000	/* DDR size 256MB */ +#define DDR_8BANKS				/* 8-bank DDR2 (256MB) */ +/*====================*/ +/* Serial Driver info */ +/*====================*/ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE	4		/* NS16550 register size */ +#define CFG_NS16550_COM1	0x01c20000	/* Base address of UART0 */ +#define CFG_NS16550_CLK		27000000	/* Input clock to NS16550 */ +#define CONFIG_CONS_INDEX	1		/* use UART0 for console */ +#define CONFIG_BAUDRATE		115200		/* Default baud rate */ +#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 } +/*===================*/ +/* I2C Configuration */ +/*===================*/ +#define CONFIG_HARD_I2C +#define CONFIG_DRIVER_DAVINCI_I2C +#define CFG_I2C_SPEED		80000	/* 100Kbps won't work, silicon bug */ +#define CFG_I2C_SLAVE		10	/* Bogus, master-only in U-Boot */ +/*==================================*/ +/* Network & Ethernet Configuration */ +/*==================================*/ +#define CONFIG_DRIVER_TI_EMAC +#define CONFIG_MII +#define CONFIG_BOOTP_DEFAULT +#define CONFIG_BOOTP_DNS +#define CONFIG_BOOTP_DNS2 +#define CONFIG_BOOTP_SEND_HOSTNAME +#define CONFIG_NET_RETRY_COUNT	10 +/*=====================*/ +/* Flash & Environment */ +/*=====================*/ +#ifdef CFG_USE_NAND +#undef CFG_ENV_IS_IN_FLASH +#define CFG_NO_FLASH +#define CFG_ENV_IS_IN_NAND		/* U-Boot env in NAND Flash  */ +#ifdef CFG_NAND_SMALLPAGE +#define CFG_ENV_SECT_SIZE	512	/* Env sector Size */ +#define CFG_ENV_SIZE		SZ_16K +#else +#define CFG_ENV_SECT_SIZE	2048	/* Env sector Size */ +#define CFG_ENV_SIZE		SZ_128K +#endif +#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is loaded by a bootloader */ +#define CONFIG_SKIP_RELOCATE_UBOOT	/* to a proper address, init done */ +#define CFG_NAND_BASE		0x02000000 +#define CFG_NAND_HW_ECC +#define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices */ +#define NAND_MAX_CHIPS		1 +#define CFG_ENV_OFFSET		0x0	/* Block 0--not used by bootcode */ +#define DEF_BOOTM		"" +#elif defined(CFG_USE_NOR) +#ifdef CONFIG_NOR_UART_BOOT +#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is loaded by a bootloader */ +#define CONFIG_SKIP_RELOCATE_UBOOT	/* to a proper address, init done */ +#else +#undef CONFIG_SKIP_LOWLEVEL_INIT +#undef CONFIG_SKIP_RELOCATE_UBOOT +#endif +#define CFG_ENV_IS_IN_FLASH +#undef CFG_NO_FLASH +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +#define CFG_MAX_FLASH_BANKS	1		/* max number of flash banks */ +#define CFG_FLASH_SECT_SZ	0x10000		/* 64KB sect size AMD Flash */ +#define CFG_ENV_OFFSET		(CFG_FLASH_SECT_SZ*3) +#define PHYS_FLASH_1		0x02000000	/* CS2 Base address 	 */ +#define CFG_FLASH_BASE		PHYS_FLASH_1	/* Flash Base for U-Boot */ +#define PHYS_FLASH_SIZE		0x2000000	/* Flash size 32MB 	 */ +#define CFG_MAX_FLASH_SECT	(PHYS_FLASH_SIZE/CFG_FLASH_SECT_SZ) +#define CFG_ENV_SECT_SIZE	CFG_FLASH_SECT_SZ	/* Env sector Size */ +#endif +/*==============================*/ +/* U-Boot general configuration */ +/*==============================*/ +#undef 	CONFIG_USE_IRQ			/* No IRQ/FIQ in U-Boot */ +#define CONFIG_MISC_INIT_R +#undef CONFIG_BOOTDELAY +#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */ +#define CFG_PROMPT		"U-Boot > "	/* Monitor Command Prompt */ +#define CFG_CBSIZE		1024		/* Console I/O Buffer Size  */ +#define CFG_PBSIZE		(CFG_CBSIZE+sizeof(CFG_PROMPT)+16)	/* Print buffer sz */ +#define CFG_MAXARGS		16		/* max number of command args */ +#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR		0x80700000	/* default Linux kernel load address */ +#define CONFIG_VERSION_VARIABLE +#define CONFIG_AUTO_COMPLETE		/* Won't work with hush so far, may be later */ +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2	"> " +#define CONFIG_CMDLINE_EDITING +#define CFG_LONGHELP +#define CONFIG_CRC32_VERIFY +#define CONFIG_MX_CYCLIC +/*===================*/ +/* Linux Information */ +/*===================*/ +#define LINUX_BOOT_PARAM_ADDR	0x80000100 +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_BOOTARGS		"mem=120M console=ttyS0,115200n8 root=/dev/hda1 rw noinitrd ip=dhcp" +#define CONFIG_BOOTCOMMAND	"setenv setboot setenv bootargs \\$(bootargs) video=dm64xxfb:output=\\$(videostd);run setboot; bootm 0x2050000" +/*=================*/ +/* U-Boot commands */ +/*=================*/ +#include <config_cmd_default.h> +#define CONFIG_CMD_ASKENV +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_I2C +#define CONFIG_CMD_MII +#define CONFIG_CMD_PING +#define CONFIG_CMD_SAVES +#define CONFIG_CMD_EEPROM +#undef CONFIG_CMD_BDI +#undef CONFIG_CMD_FPGA +#undef CONFIG_CMD_SETGETDCR +#ifdef CFG_USE_NAND +#undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_IMLS +#define CONFIG_CMD_NAND +#elif defined(CFG_USE_NOR) +#define CONFIG_CMD_JFFS2 +#else +#error "Either CFG_USE_NAND or CFG_USE_NOR _MUST_ be defined !!!" +#endif +/*=======================*/ +/* KGDB support (if any) */ +/*=======================*/ +#ifdef CONFIG_CMD_KGDB +#define CONFIG_KGDB_BAUDRATE	115200	/* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX	1	/* which serial port to use */ +#endif +#endif /* __CONFIG_H */ diff --git a/include/configs/davinci_schmoogie.h b/include/configs/davinci_schmoogie.h new file mode 100644 index 000000000..96c9a3014 --- /dev/null +++ b/include/configs/davinci_schmoogie.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H +#include <asm/sizes.h> + +/*=======*/ +/* Board */ +/*=======*/ +#define SCHMOOGIE +#define CFG_NAND_LARGEPAGE +#define CFG_USE_NAND +/*===================*/ +/* SoC Configuration */ +/*===================*/ +#define CONFIG_ARM926EJS			/* arm926ejs CPU core */ +#define CONFIG_SYS_CLK_FREQ	297000000	/* Arm Clock frequency */ +#define CFG_TIMERBASE		0x01c21400	/* use timer 0 */ +#define CFG_HZ_CLOCK		27000000	/* Timer Input clock freq */ +#define CFG_HZ			1000 +/*=============*/ +/* Memory Info */ +/*=============*/ +#define CFG_MALLOC_LEN		(0x10000 + 256*1024)	/* malloc() len */ +#define CFG_GBL_DATA_SIZE	128		/* reserved for initial data */ +#define CFG_MEMTEST_START	0x80000000	/* memtest start address */ +#define CFG_MEMTEST_END		0x81000000	/* 16MB RAM test */ +#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */ +#define CONFIG_STACKSIZE	(256*1024)	/* regular stack */ +#define PHYS_SDRAM_1		0x80000000	/* DDR Start */ +#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */ +#define DDR_4BANKS				/* 4-bank DDR2 (128MB) */ +/*====================*/ +/* Serial Driver info */ +/*====================*/ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE	4		/* NS16550 register size */ +#define CFG_NS16550_COM1	0x01c20000	/* Base address of UART0 */ +#define CFG_NS16550_CLK		27000000	/* Input clock to NS16550 */ +#define CONFIG_CONS_INDEX	1		/* use UART0 for console */ +#define CONFIG_BAUDRATE		115200		/* Default baud rate */ +#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 } +/*===================*/ +/* I2C Configuration */ +/*===================*/ +#define CONFIG_HARD_I2C +#define CONFIG_DRIVER_DAVINCI_I2C +#define CFG_I2C_SPEED		80000	/* 100Kbps won't work, silicon bug */ +#define CFG_I2C_SLAVE		10	/* Bogus, master-only in U-Boot */ +/*==================================*/ +/* Network & Ethernet Configuration */ +/*==================================*/ +#define CONFIG_DRIVER_TI_EMAC +#define CONFIG_MII +#define CONFIG_BOOTP_DEFAULT +#define CONFIG_BOOTP_DNS +#define CONFIG_BOOTP_DNS2 +#define CONFIG_BOOTP_SEND_HOSTNAME +#define CONFIG_NET_RETRY_COUNT	10 +#define CONFIG_OVERWRITE_ETHADDR_ONCE +/*=====================*/ +/* Flash & Environment */ +/*=====================*/ +#undef CFG_ENV_IS_IN_FLASH +#define CFG_NO_FLASH +#define CFG_ENV_IS_IN_NAND		/* U-Boot env in NAND Flash  */ +#define CFG_ENV_SECT_SIZE	2048	/* Env sector Size */ +#define CFG_ENV_SIZE		SZ_128K +#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is loaded by a bootloader */ +#define CONFIG_SKIP_RELOCATE_UBOOT	/* to a proper address, init done */ +#define CFG_NAND_BASE		0x02000000 +#define CFG_NAND_HW_ECC +#define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices */ +#define NAND_MAX_CHIPS		1 +#define CFG_ENV_OFFSET		0x0	/* Block 0--not used by bootcode */ +/*=====================*/ +/* Board related stuff */ +/*=====================*/ +#define CONFIG_RTC_DS1307		/* RTC chip on SCHMOOGIE */ +#define CFG_I2C_RTC_ADDR	0x6f	/* RTC chip I2C address */ +#define CONFIG_HAS_UID +#define CONFIG_UID_DS28CM00		/* Unique ID on SCHMOOGIE */ +#define CFG_UID_ADDR		0x50	/* UID chip I2C address */ +/*==============================*/ +/* U-Boot general configuration */ +/*==============================*/ +#undef 	CONFIG_USE_IRQ			/* No IRQ/FIQ in U-Boot */ +#define CONFIG_MISC_INIT_R +#undef CONFIG_BOOTDELAY +#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */ +#define CFG_PROMPT		"U-Boot > "	/* Monitor Command Prompt */ +#define CFG_CBSIZE		1024		/* Console I/O Buffer Size  */ +#define CFG_PBSIZE		(CFG_CBSIZE+sizeof(CFG_PROMPT)+16)	/* Print buffer sz */ +#define CFG_MAXARGS		16		/* max number of command args */ +#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR		0x80700000	/* default Linux kernel load address */ +#define CONFIG_VERSION_VARIABLE +#define CONFIG_AUTO_COMPLETE		/* Won't work with hush so far, may be later */ +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2	"> " +#define CONFIG_CMDLINE_EDITING +#define CFG_LONGHELP +#define CONFIG_CRC32_VERIFY +#define CONFIG_MX_CYCLIC +/*===================*/ +/* Linux Information */ +/*===================*/ +#define LINUX_BOOT_PARAM_ADDR	0x80000100 +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_BOOTARGS		"mem=56M console=ttyS0,115200n8 root=/dev/hda1 rw noinitrd ip=dhcp" +#define CONFIG_BOOTCOMMAND	"setenv setboot setenv bootargs \\$(bootargs) video=dm64xxfb:output=\\$(videostd);run setboot" +/*=================*/ +/* U-Boot commands */ +/*=================*/ +#include <config_cmd_default.h> +#define CONFIG_CMD_ASKENV +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_I2C +#define CONFIG_CMD_MII +#define CONFIG_CMD_PING +#define CONFIG_CMD_SAVES +#define CONFIG_CMD_DATE +#define CONFIG_CMD_NAND +#undef CONFIG_CMD_EEPROM +#undef CONFIG_CMD_BDI +#undef CONFIG_CMD_FPGA +#undef CONFIG_CMD_SETGETDCR +#undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_IMLS +/*=======================*/ +/* KGDB support (if any) */ +/*=======================*/ +#ifdef CONFIG_CMD_KGDB +#define CONFIG_KGDB_BAUDRATE	115200	/* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX	1	/* which serial port to use */ +#endif +#endif /* __CONFIG_H */ diff --git a/include/configs/davinci_sonata.h b/include/configs/davinci_sonata.h new file mode 100644 index 000000000..de8c4fac2 --- /dev/null +++ b/include/configs/davinci_sonata.h @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H +#include <asm/sizes.h> + +/* + * Define this to make U-Boot skip low level initialization when loaded + * by initial bootloader. Not required by NAND U-Boot version but IS + * required for a NOR version used to burn the real NOR U-Boot into + * NOR Flash. NAND and NOR support for DaVinci chips is mutually exclusive + * so it is NOT possible to build a U-Boot with both NAND and NOR routines. + * NOR U-Boot is loaded directly from Flash so it must perform all the + * low level initialization itself. NAND version is loaded by an initial + * bootloader (UBL in TI-ese) that performs such an initialization so it's + * skipped in NAND version. The third DaVinci boot mode loads a bootloader + * via UART0 and that bootloader in turn loads and runs U-Boot (or whatever) + * performing low level init prior to loading. All that means we can NOT use + * NAND version to put U-Boot into NOR because it doesn't have NOR support and + * we can NOT use NOR version because it performs low level initialization + * effectively destroying itself in DDR memory. That's why a separate NOR + * version with this define is needed. It is loaded via UART, then one uses + * it to somehow download a proper NOR version built WITHOUT this define to + * RAM (tftp?) and burn it to NOR Flash. I would be probably able to squeeze + * NOR support into the initial bootloader so it won't be needed but DaVinci + * static RAM might be too small for this (I have something like 2Kbytes left + * as of now, without NOR support) so this might've not happened... + * +#define CONFIG_NOR_UART_BOOT + */ + +/*=======*/ +/* Board */ +/*=======*/ +#define SONATA_BOARD +#define CFG_NAND_SMALLPAGE +#define CFG_USE_NOR +/*===================*/ +/* SoC Configuration */ +/*===================*/ +#define CONFIG_ARM926EJS			/* arm926ejs CPU core */ +#define CONFIG_SYS_CLK_FREQ	297000000	/* Arm Clock frequency */ +#define CFG_TIMERBASE		0x01c21400	/* use timer 0 */ +#define CFG_HZ_CLOCK		27000000	/* Timer Input clock freq */ +#define CFG_HZ			1000 +/*====================================================*/ +/* EEPROM definitions for Atmel 24C256BN SEEPROM chip */ +/* on Sonata/DV_EVM board. No EEPROM on schmoogie.    */ +/*====================================================*/ +#define CFG_I2C_EEPROM_ADDR_LEN		2 +#define CFG_I2C_EEPROM_ADDR		0x50 +#define CFG_EEPROM_PAGE_WRITE_BITS	6 +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS	20 +/*=============*/ +/* Memory Info */ +/*=============*/ +#define CFG_MALLOC_LEN		(0x10000 + 128*1024)	/* malloc() len */ +#define CFG_GBL_DATA_SIZE	128		/* reserved for initial data */ +#define CFG_MEMTEST_START	0x80000000	/* memtest start address */ +#define CFG_MEMTEST_END		0x81000000	/* 16MB RAM test */ +#define CONFIG_NR_DRAM_BANKS	1		/* we have 1 bank of DRAM */ +#define CONFIG_STACKSIZE	(256*1024)	/* regular stack */ +#define PHYS_SDRAM_1		0x80000000	/* DDR Start */ +#define PHYS_SDRAM_1_SIZE	0x08000000	/* DDR size 128MB */ +#define DDR_4BANKS				/* 4-bank DDR2 (128MB) */ +/*====================*/ +/* Serial Driver info */ +/*====================*/ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE	4		/* NS16550 register size */ +#define CFG_NS16550_COM1	0x01c20000	/* Base address of UART0 */ +#define CFG_NS16550_CLK		27000000	/* Input clock to NS16550 */ +#define CONFIG_CONS_INDEX	1		/* use UART0 for console */ +#define CONFIG_BAUDRATE		115200		/* Default baud rate */ +#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 } +/*===================*/ +/* I2C Configuration */ +/*===================*/ +#define CONFIG_HARD_I2C +#define CONFIG_DRIVER_DAVINCI_I2C +#define CFG_I2C_SPEED		80000	/* 100Kbps won't work, silicon bug */ +#define CFG_I2C_SLAVE		10	/* Bogus, master-only in U-Boot */ +/*==================================*/ +/* Network & Ethernet Configuration */ +/*==================================*/ +#define CONFIG_DRIVER_TI_EMAC +#define CONFIG_MII +#define CONFIG_BOOTP_DEFAULT +#define CONFIG_BOOTP_DNS +#define CONFIG_BOOTP_DNS2 +#define CONFIG_BOOTP_SEND_HOSTNAME +#define CONFIG_NET_RETRY_COUNT	10 +/*=====================*/ +/* Flash & Environment */ +/*=====================*/ +#ifdef CFG_USE_NAND +#undef CFG_ENV_IS_IN_FLASH +#define CFG_NO_FLASH +#define CFG_ENV_IS_IN_NAND		/* U-Boot env in NAND Flash  */ +#define CFG_ENV_SECT_SIZE	512	/* Env sector Size */ +#define CFG_ENV_SIZE		SZ_16K +#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is loaded by a bootloader */ +#define CONFIG_SKIP_RELOCATE_UBOOT	/* to a proper address, init done */ +#define CFG_NAND_BASE		0x02000000 +#define CFG_NAND_HW_ECC +#define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices */ +#define NAND_MAX_CHIPS		1 +#define CFG_ENV_OFFSET		0x0	/* Block 0--not used by bootcode */ +#define DEF_BOOTM		"" +#elif defined(CFG_USE_NOR) +#ifdef CONFIG_NOR_UART_BOOT +#define CONFIG_SKIP_LOWLEVEL_INIT	/* U-Boot is loaded by a bootloader */ +#define CONFIG_SKIP_RELOCATE_UBOOT	/* to a proper address, init done */ +#else +#undef CONFIG_SKIP_LOWLEVEL_INIT +#undef CONFIG_SKIP_RELOCATE_UBOOT +#endif +#define CFG_ENV_IS_IN_FLASH +#undef CFG_NO_FLASH +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +#define CFG_MAX_FLASH_BANKS	1		/* max number of flash banks */ +#define CFG_FLASH_SECT_SZ	0x20000		/* 128KB sect size AMD Flash */ +#define CFG_ENV_OFFSET		(CFG_FLASH_SECT_SZ*2) +#define PHYS_FLASH_1		0x02000000	/* CS2 Base address 	 */ +#define CFG_FLASH_BASE		PHYS_FLASH_1	/* Flash Base for U-Boot */ +#define PHYS_FLASH_SIZE		0x2000000	/* Flash size 32MB 	 */ +#define CFG_MAX_FLASH_SECT	(PHYS_FLASH_SIZE/CFG_FLASH_SECT_SZ) +#define CFG_ENV_SECT_SIZE	CFG_FLASH_SECT_SZ	/* Env sector Size */ +#endif +/*==============================*/ +/* U-Boot general configuration */ +/*==============================*/ +#undef 	CONFIG_USE_IRQ			/* No IRQ/FIQ in U-Boot */ +#define CONFIG_MISC_INIT_R +#undef CONFIG_BOOTDELAY +#define CONFIG_BOOTFILE		"uImage"	/* Boot file name */ +#define CFG_PROMPT		"U-Boot > "	/* Monitor Command Prompt */ +#define CFG_CBSIZE		1024		/* Console I/O Buffer Size  */ +#define CFG_PBSIZE		(CFG_CBSIZE+sizeof(CFG_PROMPT)+16)	/* Print buffer sz */ +#define CFG_MAXARGS		16		/* max number of command args */ +#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR		0x80700000	/* default Linux kernel load address */ +#define CONFIG_VERSION_VARIABLE +#define CONFIG_AUTO_COMPLETE		/* Won't work with hush so far, may be later */ +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2	"> " +#define CONFIG_CMDLINE_EDITING +#define CFG_LONGHELP +#define CONFIG_CRC32_VERIFY +#define CONFIG_MX_CYCLIC +/*===================*/ +/* Linux Information */ +/*===================*/ +#define LINUX_BOOT_PARAM_ADDR	0x80000100 +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_BOOTARGS		"mem=56M console=ttyS0,115200n8 root=/dev/hda1 rw noinitrd ip=dhcp" +#define CONFIG_BOOTCOMMAND	"setenv setboot setenv bootargs \\$(bootargs) video=dm64xxfb:output=\\$(videostd);run setboot; bootm 0x2060000" +/*=================*/ +/* U-Boot commands */ +/*=================*/ +#include <config_cmd_default.h> +#define CONFIG_CMD_ASKENV +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_I2C +#define CONFIG_CMD_MII +#define CONFIG_CMD_PING +#define CONFIG_CMD_SAVES +#define CONFIG_CMD_EEPROM +#undef CONFIG_CMD_BDI +#undef CONFIG_CMD_FPGA +#undef CONFIG_CMD_SETGETDCR +#ifdef CFG_USE_NAND +#undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_IMLS +#define CONFIG_CMD_NAND +#elif defined(CFG_USE_NOR) +#define CONFIG_CMD_JFFS2 +#else +#error "Either CFG_USE_NAND or CFG_USE_NOR _MUST_ be defined !!!" +#endif +/*=======================*/ +/* KGDB support (if any) */ +/*=======================*/ +#ifdef CONFIG_CMD_KGDB +#define CONFIG_KGDB_BAUDRATE	115200	/* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX	1	/* which serial port to use */ +#endif +#endif /* __CONFIG_H */ diff --git a/include/configs/delta.h b/include/configs/delta.h index dbfe7a702..09667edaa 100644 --- a/include/configs/delta.h +++ b/include/configs/delta.h @@ -118,6 +118,18 @@  #endif +/* USB */ +#define CONFIG_USB_OHCI_NEW	1 +#define CONFIG_USB_STORAGE      1 +#define CONFIG_DOS_PARTITION    1 + +#undef CFG_USB_OHCI_BOARD_INIT +#define CFG_USB_OHCI_CPU_INIT	1 +#define CFG_USB_OHCI_REGS_BASE	OHCI_REGS_BASE +#define CFG_USB_OHCI_SLOT_NAME	"delta" +#define CFG_USB_OHCI_MAX_ROOT_PORTS	3 + +#define LITTLEENDIAN            1       /* used by usb_ohci.c  */  #define CONFIG_BOOTDELAY	-1  #define CONFIG_ETHADDR		08:00:3e:26:0a:5b diff --git a/include/configs/mp2usb.h b/include/configs/mp2usb.h index 8d6f2613c..ea5a44b1d 100644 --- a/include/configs/mp2usb.h +++ b/include/configs/mp2usb.h @@ -101,12 +101,18 @@  #undef	CONFIG_MODEM_SUPPORT		/* disable modem initialization stuff */ -#define CONFIG_USB_OHCI		1 +#define CONFIG_USB_OHCI_NEW	1  #define CONFIG_USB_KEYBOARD	1  #define CONFIG_USB_STORAGE	1  #define CONFIG_DOS_PARTITION	1  #define CONFIG_AT91C_PQFP_UHPBUG 1 +#undef CFG_USB_OHCI_BOARD_INIT +#define CFG_USB_OHCI_CPU_INIT		1 +#define CFG_USB_OHCI_REGS_BASE		AT91_USB_HOST_BASE +#define CFG_USB_OHCI_SLOT_NAME		"at91rm9200" +#define CFG_USB_OHCI_MAX_ROOT_PORTS	15 +  #undef CONFIG_HARD_I2C  #ifdef CONFIG_HARD_I2C @@ -123,7 +129,6 @@  #define CONFIG_BOOTDELAY      3 -  #if !defined(CONFIG_HARD_I2C)  #define CONFIG_TIMESTAMP  #endif @@ -173,7 +178,7 @@  #define CONFIG_NR_DRAM_BANKS	1  #define PHYS_SDRAM		0x20000000 -#define PHYS_SDRAM_SIZE		0x08000000 	/* 128 megs */ +#define PHYS_SDRAM_SIZE		0x08000000	/* 128 megs */  #define CFG_MEMTEST_START	PHYS_SDRAM  #define CFG_MEMTEST_END		CFG_MEMTEST_START + PHYS_SDRAM_SIZE - 262144 diff --git a/include/configs/trab.h b/include/configs/trab.h index 52bcbfc15..dbccea28a 100644 --- a/include/configs/trab.h +++ b/include/configs/trab.h @@ -80,10 +80,17 @@  #define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10  /* USB stuff */ -#define CONFIG_USB_OHCI		1 +#define CONFIG_USB_OHCI_NEW	1  #define CONFIG_USB_STORAGE	1  #define CONFIG_DOS_PARTITION	1 +#undef CFG_USB_OHCI_BOARD_INIT +#define CFG_USB_OHCI_CPU_INIT	1 + +#define CFG_USB_OHCI_REGS_BASE	0x14200000 +#define CFG_USB_OHCI_SLOT_NAME	"s3c2400" +#define CFG_USB_OHCI_MAX_ROOT_PORTS	15 +  /*   * Size of malloc() pool   */ diff --git a/include/configs/yosemite.h b/include/configs/yosemite.h index dd6d9acdd..6a5b7f1ea 100644 --- a/include/configs/yosemite.h +++ b/include/configs/yosemite.h @@ -233,8 +233,15 @@  #ifdef CONFIG_440EP  /* USB */ -#define CONFIG_USB_OHCI +#define CONFIG_USB_OHCI_NEW  #define CONFIG_USB_STORAGE +#define CFG_OHCI_BE_CONTROLLER + +#undef CFG_USB_OHCI_BOARD_INIT +#define CFG_USB_OHCI_CPU_INIT	1 +#define CFG_USB_OHCI_REGS_BASE	(CFG_PERIPHERAL_BASE | 0x1000) +#define CFG_USB_OHCI_SLOT_NAME	"ppc440" +#define CFG_USB_OHCI_MAX_ROOT_PORTS	15  /* Comment this out to enable USB 1.1 device */  #define USB_2_0_DEVICE diff --git a/include/da9030.h b/include/da9030.h index 41108b9b3..3e3b20241 100644 --- a/include/da9030.h +++ b/include/da9030.h @@ -104,3 +104,15 @@  #define SYS_CONTROL_A_HWRES_ENABLE		(1<<2)  #define SYS_CONTROL_A_WDOG_ACTION		(1<<3)  #define SYS_CONTROL_A_WATCHDOG			(1<<7) + +#define MISC_CONTROLB_USB_INT_RISING		(1<<2) +#define MISC_CONTROLB_SESSION_VALID_EN		(1<<3) + +#define USB_PUMP_USBVE				(1<<0) +#define USB_PUMP_USBVEP				(1<<1) +#define USB_PUMP_SRP_DETECT			(1<<2) +#define USB_PUMP_SESSION_VALID			(1<<3) +#define USB_PUMP_VBUS_VALID_4_0			(1<<4) +#define USB_PUMP_VBUS_VALID_4_4			(1<<5) +#define USB_PUMP_EN_USBVE			(1<<6) +#define USB_PUMP_EN_USBVEP			(1<<7) diff --git a/include/asm-avr32/div64.h b/include/div64.h index 2e0ba8389..2e0ba8389 100644 --- a/include/asm-avr32/div64.h +++ b/include/div64.h diff --git a/include/dp83848.h b/include/dp83848.h new file mode 100644 index 000000000..274bc4c96 --- /dev/null +++ b/include/dp83848.h @@ -0,0 +1,88 @@ +/* + * DP83848 ethernet Physical layer + * + * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> + * + * + * 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. + */ + + +/* National Semiconductor PHYSICAL LAYER TRANSCEIVER DP83848 */ + +#define DP83848_CTL_REG		0x0	/* Basic Mode Control Reg */ +#define DP83848_STAT_REG		0x1	/* Basic Mode Status Reg */ +#define DP83848_PHYID1_REG		0x2	/* PHY Idendifier Reg 1 */ +#define DP83848_PHYID2_REG		0x3	/* PHY Idendifier Reg 2 */ +#define DP83848_ANA_REG			0x4	/* Auto_Neg Advt Reg  */ +#define DP83848_ANLPA_REG		0x5	/* Auto_neg Link Partner Ability Reg */ +#define DP83848_ANE_REG			0x6	/* Auto-neg Expansion Reg  */ +#define DP83848_PHY_STAT_REG		0x10	/* PHY Status Register  */ +#define DP83848_PHY_INTR_CTRL_REG	0x11	/* PHY Interrupt Control Register */ +#define DP83848_PHY_CTRL_REG		0x19	/* PHY Status Register  */ + +/*--Bit definitions: DP83848_CTL_REG */ +#define DP83848_RESET		(1 << 15)  /* 1= S/W Reset */ +#define DP83848_LOOPBACK	(1 << 14)  /* 1=loopback Enabled */ +#define DP83848_SPEED_SELECT	(1 << 13) +#define DP83848_AUTONEG		(1 << 12) +#define DP83848_POWER_DOWN	(1 << 11) +#define DP83848_ISOLATE		(1 << 10) +#define DP83848_RESTART_AUTONEG	(1 << 9) +#define DP83848_DUPLEX_MODE	(1 << 8) +#define DP83848_COLLISION_TEST	(1 << 7) + +/*--Bit definitions: DP83848_STAT_REG */ +#define DP83848_100BASE_T4	(1 << 15) +#define DP83848_100BASE_TX_FD	(1 << 14) +#define DP83848_100BASE_TX_HD	(1 << 13) +#define DP83848_10BASE_T_FD	(1 << 12) +#define DP83848_10BASE_T_HD	(1 << 11) +#define DP83848_MF_PREAMB_SUPPR	(1 << 6) +#define DP83848_AUTONEG_COMP	(1 << 5) +#define DP83848_RMT_FAULT	(1 << 4) +#define DP83848_AUTONEG_ABILITY	(1 << 3) +#define DP83848_LINK_STATUS	(1 << 2) +#define DP83848_JABBER_DETECT	(1 << 1) +#define DP83848_EXTEND_CAPAB	(1 << 0) + +/*--definitions: DP83848_PHYID1 */ +#define DP83848_PHYID1_OUI	0x2000 +#define DP83848_PHYID2_OUI	0x5c90 + +/*--Bit definitions: DP83848_ANAR, DP83848_ANLPAR */ +#define DP83848_NP		(1 << 15) +#define DP83848_ACK		(1 << 14) +#define DP83848_RF		(1 << 13) +#define DP83848_PAUSE		(1 << 10) +#define DP83848_T4		(1 << 9) +#define DP83848_TX_FDX		(1 << 8) +#define DP83848_TX_HDX		(1 << 7) +#define DP83848_10_FDX		(1 << 6) +#define DP83848_10_HDX		(1 << 5) +#define DP83848_AN_IEEE_802_3	0x0001 + +/*--Bit definitions: DP83848_ANER */ +#define DP83848_PDF		(1 << 4) +#define DP83848_LP_NP_ABLE	(1 << 3) +#define DP83848_NP_ABLE		(1 << 2) +#define DP83848_PAGE_RX		(1 << 1) +#define DP83848_LP_AN_ABLE	(1 << 0) + +/*--Bit definitions: DP83848_PHY_STAT */ +#define DP83848_RX_ERR_LATCH		(1 << 13) +#define DP83848_POLARITY_STAT		(1 << 12) +#define DP83848_FALSE_CAR_SENSE		(1 << 11) +#define DP83848_SIG_DETECT		(1 << 10) +#define DP83848_DESCRAM_LOCK		(1 << 9) +#define DP83848_PAGE_RCV		(1 << 8) +#define DP83848_PHY_RMT_FAULT		(1 << 6) +#define DP83848_JABBER			(1 << 5) +#define DP83848_AUTONEG_COMPLETE	(1 << 4) +#define DP83848_LOOPBACK_STAT		(1 << 3) +#define DP83848_DUPLEX			(1 << 2) +#define DP83848_SPEED			(1 << 1) +#define DP83848_LINK			(1 << 0) diff --git a/include/exports.h b/include/exports.h index 0516da937..d6512cb3a 100644 --- a/include/exports.h +++ b/include/exports.h @@ -25,6 +25,9 @@ char *getenv (char *name);  void setenv (char *varname, char *varvalue);  long simple_strtol(const char *cp,char **endp,unsigned int base);  int strcmp(const char * cs,const char * ct); +#ifdef CONFIG_HAS_UID +void forceenv (char *varname, char *varvalue); +#endif  #if defined(CONFIG_CMD_I2C)  int i2c_write (uchar, uint, int , uchar* , int);  int i2c_read (uchar, uint, int , uchar* , int); diff --git a/include/mpc83xx.h b/include/mpc83xx.h index 336c0ac4f..829dbf938 100644 --- a/include/mpc83xx.h +++ b/include/mpc83xx.h @@ -86,6 +86,8 @@  #define SPR_8360_REV12			0x80490012  #define SPR_8360E_REV20			0x80480020  #define SPR_8360_REV20			0x80490020 +#define SPR_8360E_REV21			0x80480021 +#define SPR_8360_REV21			0x80490021  #define SPR_8323E_REV10			0x80620010  #define SPR_8323_REV10			0x80630010 @@ -600,7 +602,9 @@  #define SCCR_TSEC1CM_3			0xC0000000  #define SCCR_TSEC1ON			0x20000000 +#define SCCR_TSEC1ON_SHIFT		29  #define SCCR_TSEC2ON			0x10000000 +#define SCCR_TSEC2ON_SHIFT		28  #endif diff --git a/include/usb.h b/include/usb.h index bf7155404..4e1539fa8 100644 --- a/include/usb.h +++ b/include/usb.h @@ -169,7 +169,10 @@ struct usb_device {   * this is how the lowlevel part communicate with the outer world   */ -#if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || defined (CONFIG_USB_SL811HS) +#if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \ +	defined(CONFIG_USB_OHCI_NEW) || defined (CONFIG_USB_SL811HS) || \ +	defined(CONFIG_USB_ISP116X_HCD) +  int usb_lowlevel_init(void);  int usb_lowlevel_stop(void);  int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len); @@ -177,6 +180,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  			int transfer_len,struct devrequest *setup);  int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,  			int transfer_len, int interval); +void usb_event_poll(void);  /* Defines */  #define USB_UHCI_VEND_ID 0x8086 @@ -230,16 +234,12 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);  /* big endian -> little endian conversion */  /* some CPUs are already little endian e.g. the ARM920T */ -#ifdef LITTLEENDIAN -#define swap_16(x) ((unsigned short)(x)) -#define swap_32(x) ((unsigned long)(x)) -#else -#define swap_16(x) \ +#define __swap_16(x) \  	({ unsigned short x_ = (unsigned short)x; \  	 (unsigned short)( \  		((x_ & 0x00FFU) << 8) | ((x_ & 0xFF00U) >> 8) ); \  	}) -#define swap_32(x) \ +#define __swap_32(x) \  	({ unsigned long x_ = (unsigned long)x; \  	 (unsigned long)( \  		((x_ & 0x000000FFUL) << 24) | \ @@ -247,6 +247,13 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);  		((x_ & 0x00FF0000UL) >>	 8) | \  		((x_ & 0xFF000000UL) >> 24) ); \  	}) + +#ifdef LITTLEENDIAN +# define swap_16(x) (x) +# define swap_32(x) (x) +#else +# define swap_16(x) __swap_16(x) +# define swap_32(x) __swap_32(x)  #endif /* LITTLEENDIAN */  /* diff --git a/include/usb_cdc_acm.h b/include/usb_cdc_acm.h new file mode 100644 index 000000000..87bf50c52 --- /dev/null +++ b/include/usb_cdc_acm.h @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2006 + * Bryan O'Donoghue, deckard@codehermit.ie, CodeHermit + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* ACM Control Requests */ +#define ACM_SEND_ENCAPSULATED_COMMAND	0x00 +#define ACM_GET_ENCAPSULATED_RESPONSE	0x01 +#define ACM_SET_COMM_FEATURE		0x02 +#define ACM_GET_COMM_FEATRUE		0x03 +#define ACM_CLEAR_COMM_FEATURE		0x04 +#define ACM_SET_LINE_ENCODING		0x20 +#define ACM_GET_LINE_ENCODING		0x21 +#define ACM_SET_CONTROL_LINE_STATE	0x22 +#define ACM_SEND_BREAK			0x23 + +/* ACM Notification Codes */ +#define ACM_NETWORK_CONNECTION		0x00 +#define ACM_RESPONSE_AVAILABLE		0x01 +#define ACM_SERIAL_STATE		0x20 + +/* Format of response expected by a ACM_GET_LINE_ENCODING request */ +struct rs232_emu{ +		unsigned long dter; +		unsigned char stop_bits; +		unsigned char parity; +		unsigned char data_bits; +}__attribute__((packed)); diff --git a/include/usbdcore.h b/include/usbdcore.h index 6e92df13b..cb2be7280 100644 --- a/include/usbdcore.h +++ b/include/usbdcore.h @@ -576,6 +576,9 @@ struct usb_device_instance {  	void (*event) (struct usb_device_instance *device, usb_device_event_t event, int data); +	/* Do cdc device specific control requests */ +	int (*cdc_recv_setup)(struct usb_device_request *request, struct urb *urb); +  	/* bus interface */  	struct usb_bus_instance *bus;	/* which bus interface driver */ diff --git a/include/usbdcore_mpc8xx.h b/include/usbdcore_mpc8xx.h new file mode 100644 index 000000000..9df62f4ca --- /dev/null +++ b/include/usbdcore_mpc8xx.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2006 Bryan O'Donoghue, CodeHermit + * bodonoghue@codehermit.ie + * + * + * 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 <commproc.h> + +/* Mode Register */ +#define USMOD_EN	0x01 +#define USMOD_HOST	0x02 +#define USMOD_TEST	0x04 +#define USMOD_SFTE	0x08 +#define USMOD_RESUME	0x40 +#define USMOD_LSS	0x80 + +/* Endpoint Registers */ +#define USEP_RHS_NORM	0x00 +#define USEP_RHS_IGNORE	0x01 +#define USEP_RHS_NAK	0x02 +#define USEP_RHS_STALL	0x03 + +#define USEP_THS_NORM	0x00 +#define USEP_THS_IGNORE	0x04 +#define USEP_THS_NAK	0x08 +#define USEP_THS_STALL	0x0C + +#define USEP_RTE	0x10 +#define USEP_MF		0x20 + +#define USEP_TM_CONTROL	0x00 +#define USEP_TM_INT	0x100 +#define USEP_TM_BULK	0x200 +#define USEP_TM_ISO	0x300 + +/* Command Register */ +#define USCOM_EP0	0x00 +#define USCOM_EP1	0x01 +#define USCOM_EP2	0x02 +#define USCOM_EP3	0x03 + +#define USCOM_FLUSH	0x40 +#define USCOM_STR	0x80 + +/* Event Register */ +#define USB_E_RXB	0x0001 +#define USB_E_TXB	0x0002 +#define USB_E_BSY	0x0004 +#define USB_E_SOF	0x0008 +#define USB_E_TXE1	0x0010 +#define USB_E_TXE2	0x0020 +#define USB_E_TXE3	0x0040 +#define USB_E_TXE4	0x0080 +#define USB_TX_ERRMASK (USB_E_TXE1|USB_E_TXE2|USB_E_TXE3|USB_E_TXE4) +#define USB_E_IDLE	0x0100 +#define USB_E_RESET	0x0200 + +/* Mask Register */ +#define USBS_IDLE	0x01 + +/* RX Buffer Descriptor */ +#define RX_BD_OV	0x02 +#define RX_BD_CR	0x04 +#define RX_BD_AB	0x08 +#define RX_BD_NO	0x10 +#define RX_BD_PID_DATA0	0x00 +#define RX_BD_PID_DATA1	0x40 +#define RX_BD_PID_SETUP	0x80 +#define RX_BD_F		0x400 +#define RX_BD_L		0x800 +#define RX_BD_I		0x1000 +#define RX_BD_W		0x2000 +#define RX_BD_E		0x8000 + +/* Useful masks */ +#define RX_BD_PID_BITMASK (RX_BD_PID_DATA1 | RX_BD_PID_SETUP) +#define STALL_BITMASK (USEP_THS_STALL | USEP_RHS_STALL) +#define NAK_BITMASK (USEP_THS_NAK | USEP_RHS_NAK) +#define CBD_TX_BITMASK (TX_BD_R | TX_BD_L | TX_BD_TC | TX_BD_I | TX_BD_CNF) + +/* TX Buffer Descriptor */ +#define TX_BD_UN	0x02 +#define TX_BD_TO	0x04 +#define TX_BD_NO_PID	0x00 +#define TX_BD_PID_DATA0	0x80 +#define TX_BD_PID_DATA1	0xC0 +#define TX_BD_CNF	0x200 +#define TX_BD_TC	0x400 +#define TX_BD_L		0x800 +#define TX_BD_I		0x1000 +#define TX_BD_W		0x2000 +#define TX_BD_R		0x8000 + +/* Implementation specific defines */ + +#define EP_MIN_PACKET_SIZE 0x08 +#define MAX_ENDPOINTS	0x04 +#define FIFO_SIZE	0x10 +#define EP_MAX_PKT	FIFO_SIZE +#define TX_RING_SIZE	0x04 +#define RX_RING_SIZE	0x06 +#define USB_MAX_PKT	0x40 +#define TOGGLE_TX_PID(x) x= ((~x)&0x40)|0x80 +#define TOGGLE_RX_PID(x) x^= 0x40 +#define EP_ATTACHED	0x01	/* Endpoint has a urb attached or not */ +#define EP_SEND_ZLP	0x02	/* Send ZLP y/n ? */ + +#define PROFF_USB	0x00000000 +#define CPM_USB_BASE	0x00000A00 + +/* UDC device defines */ +#define EP0_MAX_PACKET_SIZE	EP_MAX_PKT +#define UDC_OUT_ENDPOINT	0x02 +#define UDC_OUT_PACKET_SIZE	EP_MIN_PACKET_SIZE +#define UDC_IN_ENDPOINT		0x03 +#define UDC_IN_PACKET_SIZE	EP_MIN_PACKET_SIZE +#define UDC_INT_ENDPOINT	0x01 +#define UDC_INT_PACKET_SIZE	UDC_IN_PACKET_SIZE +#define UDC_BULK_PACKET_SIZE	EP_MIN_PACKET_SIZE + +struct mpc8xx_ep { +	struct urb * urb; +	unsigned char pid; +	unsigned char sc; +	volatile cbd_t * prx; +}; + +typedef struct mpc8xx_usb{ +	char usmod;	/* Mode Register */ +	char usaddr;	/* Slave Address Register */ +	char uscom;	/* Command Register */ +	char res1;	/* Reserved */ +	ushort usep[4]; +	ulong res2;	/* Reserved */ +	ushort usber;	/* Event Register */ +	ushort res3;	/* Reserved */ +	ushort usbmr;	/* Mask Register */ +	char res4;	/* Reserved */ +	char usbs;	/* Status Register */ +	char res5[8];	/* Reserved */ +}usb_t; + +typedef struct mpc8xx_parameter_ram{ +	ushort ep0ptr;	/* Endpoint Pointer Register 0 */ +	ushort ep1ptr;	/* Endpoint Pointer Register 1 */ +	ushort ep2ptr;	/* Endpoint Pointer Register 2 */ +	ushort ep3ptr;	/* Endpoint Pointer Register 3 */ +	uint rstate;	/* Receive state */ +	uint rptr;	/* Receive internal data pointer */ +	ushort frame_n;	/* Frame number */ +	ushort rbcnt;	/* Receive byte count */ +	uint rtemp;	/* Receive temp cp use only */ +	uint rxusb;	/* Rx Data Temp */ +	ushort rxuptr;	/* Rx microcode return address temp */ +}usb_pram_t; + +typedef struct endpoint_parameter_block_pointer{ +	ushort rbase;	/* RxBD base address */ +	ushort tbase;	/* TxBD base address */ +	char rfcr;	/* Rx Function code */ +	char tfcr;	/* Tx Function code */ +	ushort mrblr;	/* Maximum Receive Buffer Length */ +	ushort rbptr; 	/* RxBD pointer Next Buffer Descriptor */ +	ushort tbptr;	/* TxBD pointer Next Buffer Descriptor  */ +	ulong tstate;	/* Transmit internal state */ +	ulong tptr;	/* Transmit internal data pointer */ +	ushort tcrc;	/* Transmit temp CRC */ +	ushort tbcnt;	/* Transmit internal bye count */ +	ulong ttemp;	/* Tx temp */ +	ushort txuptr;	/* Tx microcode return address */ +	ushort res1;	/* Reserved */ +}usb_epb_t; + +typedef enum mpc8xx_udc_state{ +	STATE_NOT_READY, +	STATE_ERROR, +	STATE_READY, +}mpc8xx_udc_state_t; + +/* Declarations */ +int udc_init(void); +void udc_irq(void); +int udc_endpoint_write(struct usb_endpoint_instance *endpoint); +void udc_setup_ep(struct usb_device_instance *device, unsigned int ep, +		  struct usb_endpoint_instance *endpoint); +void udc_connect(void); +void udc_disconnect(void); +void udc_enable(struct usb_device_instance *device); +void udc_disable(void); +void udc_startup_events(struct usb_device_instance *device); + +/* Flow control */ +void udc_set_nak(int epid); +void udc_unset_nak (int epid); diff --git a/include/usbdcore_omap1510.h b/include/usbdcore_omap1510.h index 6ea333122..526fcd920 100644 --- a/include/usbdcore_omap1510.h +++ b/include/usbdcore_omap1510.h @@ -161,10 +161,20 @@  #define UDC_VBUS_CTRL	    (1 << 19)  #define UDC_VBUS_MODE	    (1 << 18) +/* OMAP Endpoint parameters */ +#define EP0_MAX_PACKET_SIZE 64 +#define UDC_OUT_ENDPOINT 2 +#define UDC_OUT_PACKET_SIZE 64 +#define UDC_IN_ENDPOINT	1 +#define UDC_IN_PACKET_SIZE 64 +#define UDC_INT_ENDPOINT 5 +#define UDC_INT_PKTSIZE	16 +#define UDC_BULK_PKTSIZE 16 -void omap1510_udc_irq(void); -void omap1510_udc_noniso_irq(void); - +void udc_irq (void); +/* Flow control */ +void udc_set_nak(int epid); +void udc_unset_nak (int epid);  /* Higher level functions for abstracting away from specific device */  void udc_endpoint_write(struct usb_endpoint_instance *endpoint); diff --git a/include/usbdescriptors.h b/include/usbdescriptors.h index 2d9f73934..a752097e5 100644 --- a/include/usbdescriptors.h +++ b/include/usbdescriptors.h @@ -92,33 +92,42 @@  #define COMMUNICATIONS_DEVICE_CLASS	0x02  /* c.f. CDC 4.2 Table 15 */ -#define COMMUNICATIONS_INTERFACE_CLASS	0x02 +#define COMMUNICATIONS_INTERFACE_CLASS_CONTROL	0x02 +#define COMMUNICATIONS_INTERFACE_CLASS_DATA		0x0A +#define COMMUNICATIONS_INTERFACE_CLASS_VENDOR	0x0FF  /* c.f. CDC 4.3 Table 16 */ -#define COMMUNICATIONS_NO_SUBCLASS	0x00 +#define COMMUNICATIONS_NO_SUBCLASS		0x00  #define COMMUNICATIONS_DLCM_SUBCLASS	0x01 -#define COMMUNICATIONS_ACM_SUBCLASS	0x02 -#define COMMUNICATIONS_TCM_SUBCLASS	0x03 +#define COMMUNICATIONS_ACM_SUBCLASS		0x02 +#define COMMUNICATIONS_TCM_SUBCLASS		0x03  #define COMMUNICATIONS_MCCM_SUBCLASS	0x04 -#define COMMUNICATIONS_CCM_SUBCLASS	0x05 +#define COMMUNICATIONS_CCM_SUBCLASS		0x05  #define COMMUNICATIONS_ENCM_SUBCLASS	0x06  #define COMMUNICATIONS_ANCM_SUBCLASS	0x07  /* c.f. WMCD 5.1 */  #define COMMUNICATIONS_WHCM_SUBCLASS	0x08 -#define COMMUNICATIONS_DMM_SUBCLASS	0x09 +#define COMMUNICATIONS_DMM_SUBCLASS		0x09  #define COMMUNICATIONS_MDLM_SUBCLASS	0x0a  #define COMMUNICATIONS_OBEX_SUBCLASS	0x0b -/* c.f. CDC 4.6 Table 18 */ +/* c.f. CDC 4.4 Table 17 */ +#define COMMUNICATIONS_NO_PROTOCOL		0x00 +#define COMMUNICATIONS_V25TER_PROTOCOL	0x01	/*Common AT Hayes compatible*/ + +/* c.f. CDC 4.5 Table 18 */  #define DATA_INTERFACE_CLASS		0x0a +/* c.f. CDC 4.6 No Table */ +#define DATA_INTERFACE_SUBCLASS_NONE	0x00	/* No subclass pertinent */ +  /* c.f. CDC 4.7 Table 19 */ -#define COMMUNICATIONS_NO_PROTOCOL	0x00 +#define DATA_INTERFACE_PROTOCOL_NONE	0x00	/* No class protcol required */  /* c.f. CDC 5.2.3 Table 24 */ -#define CS_INTERFACE			0x24 +#define CS_INTERFACE		0x24  #define CS_ENDPOINT			0x25  /* @@ -128,7 +137,7 @@   * c.f. WMCD 5.3 Table 5.3   */ -#define USB_ST_HEADER			0x00 +#define USB_ST_HEADER		0x00  #define USB_ST_CMF			0x01  #define USB_ST_ACMF			0x02  #define USB_ST_DLMF			0x03 @@ -137,18 +146,18 @@  #define USB_ST_UF			0x06  #define USB_ST_CSF			0x07  #define USB_ST_TOMF			0x08 -#define USB_ST_USBTF			0x09 +#define USB_ST_USBTF		0x09  #define USB_ST_NCT			0x0a  #define USB_ST_PUF			0x0b  #define USB_ST_EUF			0x0c  #define USB_ST_MCMF			0x0d  #define USB_ST_CCMF			0x0e  #define USB_ST_ENF			0x0f -#define USB_ST_ATMNF			0x10 +#define USB_ST_ATMNF		0x10  #define USB_ST_WHCM			0x11  #define USB_ST_MDLM			0x12 -#define USB_ST_MDLMD			0x13 +#define USB_ST_MDLMD		0x13  #define USB_ST_DMM			0x14  #define USB_ST_OBEX			0x15  #define USB_ST_CS			0x16 @@ -312,7 +321,8 @@ struct usb_class_union_function_descriptor {  	u8 bDescriptorType;  	u8 bDescriptorSubtype;	/* 0x06 */  	u8 bMasterInterface; -	u8 bSlaveInterface0[0]; +	/* u8 bSlaveInterface0[0]; */ +	u8 bSlaveInterface0;  } __attribute__ ((packed));  struct usb_class_country_selection_descriptor { diff --git a/lib_arm/board.c b/lib_arm/board.c index 8f4e19bfc..d37e5dab3 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -364,6 +364,13 @@ void start_armboot (void)  	enable_interrupts ();  	/* Perform network card initialisation if necessary */ +#ifdef CONFIG_DRIVER_TI_EMAC +extern void dm644x_eth_set_mac_addr (const u_int8_t *addr); +	if (getenv ("ethaddr")) { +		dm644x_eth_set_mac_addr(gd->bd->bi_enetaddr); +	} +#endif +  #ifdef CONFIG_DRIVER_CS8900  	cs8900_get_enetaddr (gd->bd->bi_enetaddr);  #endif diff --git a/lib_avr32/Makefile b/lib_avr32/Makefile index cf2083602..bb2938fe5 100644 --- a/lib_avr32/Makefile +++ b/lib_avr32/Makefile @@ -29,7 +29,7 @@ LIB	= $(obj)lib$(ARCH).a  SOBJS	= memset.o -COBJS	= board.o interrupts.o avr32_linux.o div64.o +COBJS	= board.o interrupts.o avr32_linux.o  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_generic/Makefile b/lib_generic/Makefile index b2091c5e7..bf377529c 100644 --- a/lib_generic/Makefile +++ b/lib_generic/Makefile @@ -27,7 +27,7 @@ LIB	= $(obj)libgeneric.a  COBJS	= bzlib.o bzlib_crctable.o bzlib_decompress.o \  	  bzlib_randtable.o bzlib_huffman.o \ -	  crc32.o ctype.o display_options.o ldiv.o sha1.o \ +	  crc32.o ctype.o display_options.o div64.o ldiv.o sha1.o \  	  string.o vsprintf.o zlib.o  SRCS 	:= $(COBJS:.o=.c) diff --git a/lib_avr32/div64.c b/lib_generic/div64.c index 99726e325..d9951b597 100644 --- a/lib_avr32/div64.c +++ b/lib_generic/div64.c @@ -18,8 +18,6 @@  #include <linux/types.h> -#include <asm/div64.h> -  uint32_t __div64_32(uint64_t *n, uint32_t base)  {  	uint64_t rem = *n; diff --git a/lib_ppc/board.c b/lib_ppc/board.c index 325f5c219..c87d46c3d 100644 --- a/lib_ppc/board.c +++ b/lib_ppc/board.c @@ -309,7 +309,9 @@ init_fnc_t *init_sequence[] = {  	prt_8260_rsr,  	prt_8260_clks,  #endif /* CONFIG_8260 */ - +#if defined(CONFIG_MPC83XX) +	prt_83xx_rsr, +#endif  	checkcpu,  #if defined(CONFIG_MPC5xxx)  	prt_mpc5xxx_clks, @@ -376,7 +378,7 @@ void board_init_f (ulong bootflag)  	/* compiler optimization barrier needed for GCC >= 3.4 */  	__asm__ __volatile__("": : :"memory"); -#if !defined(CONFIG_CPM2) +#if !defined(CONFIG_CPM2) && !defined(CONFIG_MPC83XX)  	/* Clear initial global data */  	memset ((void *) gd, 0, sizeof (gd_t));  #endif @@ -464,6 +464,8 @@ extern int at91rm9200_miiphy_initialize(bd_t *bis);  extern int emac4xx_miiphy_initialize(bd_t *bis);  extern int mcf52x2_miiphy_initialize(bd_t *bis);  extern int ns7520_miiphy_initialize(bd_t *bis); +extern int dm644x_eth_miiphy_initialize(bd_t *bis); +  int eth_initialize(bd_t *bis)  { @@ -484,6 +486,9 @@ int eth_initialize(bd_t *bis)  #if defined(CONFIG_NETARM)  	ns7520_miiphy_initialize(bis);  #endif +#if defined(CONFIG_DRIVER_TI_EMAC) +	dm644x_eth_miiphy_initialize(bis); +#endif  	return 0;  }  #endif  |