Initial code import
This commit is contained in:
parent
124a04a9d6
commit
2875718480
|
@ -0,0 +1,43 @@
|
|||
export BUILD_TOPDIR=$(PWD)
|
||||
export STAGING_DIR=$(BUILD_TOPDIR)/tmp
|
||||
export TOPDIR=$(PWD)
|
||||
export UBOOTDIR=$(TOPDIR)/u-boot
|
||||
|
||||
### Toolchain config ###
|
||||
#buildroot
|
||||
CONFIG_TOOLCHAIN_PREFIX=/opt/build/toolchain-mipsbe-4.7.3/bin/mips-linux-
|
||||
|
||||
#openwrt NOT YET
|
||||
#CONFIG_TOOLCHAIN_PREFIX=mips-openwrt-linux-uclibc-
|
||||
#export PATH:=$(BUILD_TOPDIR)/toolchain/bin/:$(PATH)
|
||||
|
||||
########################
|
||||
|
||||
export CROSS_COMPILE=$(CONFIG_TOOLCHAIN_PREFIX)
|
||||
export MAKECMD=make ARCH=mips
|
||||
|
||||
export UBOOT_GCC_4_3_3_EXTRA_CFLAGS=-fPIC
|
||||
export BUILD_TYPE=squashfs
|
||||
|
||||
BOARD_TYPE=carambola2
|
||||
export COMPRESSED_UBOOT=0
|
||||
export FLASH_SIZE=16
|
||||
export NEW_DDR_TAP_CAL=1
|
||||
export CONFIG_HORNET_XTAL=40
|
||||
|
||||
IMAGEPATH=$(BUILD_TOPDIR)/bin
|
||||
UBOOT_BINARY=u-boot.bin
|
||||
UBOOTFILE=$(BOARD_TYPE)_u-boot.bin
|
||||
|
||||
all:
|
||||
cd $(UBOOTDIR) && $(MAKECMD) distclean
|
||||
cd $(UBOOTDIR) && $(MAKECMD) $(BOARD_TYPE)_config
|
||||
cd $(UBOOTDIR) && $(MAKECMD) all
|
||||
@echo Copy binaries to $(IMAGEPATH)/$(UBOOTFILE)
|
||||
mkdir -p $(IMAGEPATH)
|
||||
cp -f $(UBOOTDIR)/$(UBOOT_BINARY) $(IMAGEPATH)/$(UBOOTFILE)
|
||||
|
||||
@echo Done
|
||||
|
||||
clean:
|
||||
cd $(UBOOTDIR) && $(MAKECMD) distclean
|
|
@ -0,0 +1,14 @@
|
|||
*.a
|
||||
*.o
|
||||
.depend
|
||||
|
||||
include/version_autogenerated.h
|
||||
tools/envcrc
|
||||
tools/mkimage
|
||||
u-boot
|
||||
u-boot.bin
|
||||
u-boot.map
|
||||
u-boot.srec
|
||||
System.map
|
||||
include/config.h
|
||||
include/config.mk
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,298 @@
|
|||
NOTE! This copyright does *not* cover the so-called "standalone"
|
||||
applications that use U-Boot services by means of the jump table
|
||||
provided by U-Boot exactly for this purpose - this is merely
|
||||
considered normal use of U-Boot, and does *not* fall under the
|
||||
heading of "derived work".
|
||||
|
||||
The header files "include/image.h" and "include/asm-*/u-boot.h"
|
||||
define interfaces to U-Boot. Including these (unmodified) header
|
||||
files in another file is considered normal use of U-Boot, and does
|
||||
*not* fall under the heading of "derived work".
|
||||
|
||||
Also note that the GPL below is copyrighted by the Free Software
|
||||
Foundation, but the instance of code that it refers to (the U-Boot
|
||||
source code) is copyrighted by me and others who actually wrote it.
|
||||
-- Wolfgang Denk
|
||||
|
||||
=======================================================================
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
|
@ -0,0 +1,458 @@
|
|||
#
|
||||
# Parts of the development effort for this project have been
|
||||
# sponsored by SIEMENS AG, Austria. Thanks to SIEMENS for
|
||||
# supporting an Open Source project!
|
||||
#
|
||||
#
|
||||
# This is at least a partial credits-file of individual people that
|
||||
# have contributed to the U-Boot project. It is sorted by name and
|
||||
# formatted to allow easy grepping and beautification by scripts.
|
||||
# The fields are: name (N), email (E), web-address (W), PGP key ID
|
||||
# and fingerprint (P), description (D), and snail-mail address (S).
|
||||
# Thanks,
|
||||
#
|
||||
# Wolfgang Denk
|
||||
#----------
|
||||
|
||||
N: Dr. Bruno Achauer
|
||||
E: bruno@exet-ag.de
|
||||
D: Support for NetBSD (both as host and target system)
|
||||
|
||||
N: Guillaume Alexandre
|
||||
E: guillaume.alexandre@gespac.ch
|
||||
D: Add PCIPPC6 configuration
|
||||
|
||||
N: Swen Anderson
|
||||
E: sand@peppercon.de
|
||||
D: ERIC Support
|
||||
|
||||
N: Pantelis Antoniou
|
||||
E: panto@intracom.gr
|
||||
D: NETVIA & NETPHONE board support, ARTOS support.
|
||||
D: Support for Silicon Turnkey eXpress XTc
|
||||
|
||||
N: Pierre Aubert
|
||||
E: <p.aubert@staubli.com>
|
||||
D: Support for RPXClassic board
|
||||
|
||||
N: Yuli Barcohen
|
||||
E: yuli@arabellasw.com
|
||||
D: Unified support for Motorola MPC826xADS/MPC8272ADS/PQ2FADS boards.
|
||||
D: Support for Zephyr Engineering ZPC.1900 board.
|
||||
D: Support for Interphase iSPAN boards.
|
||||
D: Support for Analogue&Micro Adder boards.
|
||||
D: Support for Analogue&Micro Rattler boards.
|
||||
W: http://www.arabellasw.com
|
||||
|
||||
N: Jerry van Baren
|
||||
E: <vanbaren@cideas.com>
|
||||
D: BedBug port to 603e core (MPC82xx). Code for enhanced memory test.
|
||||
|
||||
N: Pavel Bartusek
|
||||
E: <pba@sysgo.com>
|
||||
D: Reiserfs support
|
||||
W: http://www.elinos.com
|
||||
|
||||
N: Andre Beaudin
|
||||
E: <andre.beaudin@colubris.com>
|
||||
D: PCMCIA, Ethernet, TFTP
|
||||
|
||||
N: Jon Benediktsson
|
||||
E: jonb@marel.is
|
||||
D: Support for Marel V37 board
|
||||
|
||||
N: Raphael Bossek
|
||||
E: raphael.bossek@solutions4linux.de
|
||||
D: 8xxrom-0.3.0
|
||||
|
||||
N: Cliff Brake
|
||||
E: cliff.brake@gmail.com
|
||||
D: Port to Vibren PXA255 IDP platform
|
||||
W: http://www.vibren.com
|
||||
W: http://bec-systems.com
|
||||
|
||||
N: Rick Bronson
|
||||
E: rick@efn.org
|
||||
D: Atmel AT91RM9200DK and NAND support
|
||||
|
||||
N: David Brown
|
||||
E: DBrown03@harris.com
|
||||
D: Extensions to 8xxrom-0.3.0
|
||||
|
||||
N: Oliver Brown
|
||||
E: obrown@adventnetworks.com
|
||||
D: Port to the gw8260 board
|
||||
|
||||
N: Curt Brune
|
||||
E: curt@cucy.com
|
||||
D: Added support for Samsung S3C4510B CPU (ARM7tdmi based SoC)
|
||||
D: Added support for ESPD-Inc. EVB4510 Board
|
||||
W: http://www.cucy.com
|
||||
|
||||
N: Jonathan De Bruyne
|
||||
E: jonathan.debruyne@siemens.atea.be
|
||||
D: Port to Siemens IAD210 board
|
||||
|
||||
N: Ken Chou
|
||||
E: kchou@ieee.org
|
||||
D: Support for A3000 SBC board
|
||||
|
||||
N: Conn Clark
|
||||
E: clark@esteem.com
|
||||
D: ESTEEM192E support
|
||||
|
||||
N: Magnus Damm
|
||||
E: damm@opensource.se
|
||||
D: 8xxrom
|
||||
|
||||
N: George G. Davis
|
||||
E: gdavis@mvista.com
|
||||
D: Board ports for ADS GraphicsClient+ and Intel Assabet
|
||||
|
||||
N: Arun Dharankar
|
||||
E: ADharankar@ATTBI.Com
|
||||
D: threads / scheduler example code
|
||||
|
||||
N: Kári Davíðsson
|
||||
E: kd@flaga.is
|
||||
D: FLAGA DM Support
|
||||
|
||||
N: Wolfgang Denk
|
||||
E: wd@denx.de
|
||||
D: U-Boot initial version, continuing maintenance, ARMBoot merge
|
||||
W: http://www.denx.de
|
||||
|
||||
N: Dan A. Dickey
|
||||
E: ddickey@charter.net
|
||||
D: FADS Support
|
||||
|
||||
N: James F. Dougherty
|
||||
E: jfd@GigabitNetworks.COM
|
||||
D: Port to the MOUSSE board
|
||||
|
||||
N: Dave Ellis
|
||||
E: DGE@sixnetio.com
|
||||
D: EEPROM Speedup, SXNI855T port
|
||||
|
||||
N: Thomas Elste
|
||||
E: info@elste.org
|
||||
D: Port for the ModNET50 Board, NET+50 CPU Port
|
||||
W: http://www.imms.de
|
||||
|
||||
N: Daniel Engström
|
||||
E: daniel@omicron.se
|
||||
D: x86 port, Support for sc520_cdp board
|
||||
|
||||
N: Dr. Wolfgang Grandegger
|
||||
E: wg@denx.de
|
||||
D: Support for Interphase 4539 T1/E1/J1 PMC, PN62, CCM, SCM boards
|
||||
W: www.denx.de
|
||||
|
||||
N: Peter Figuli
|
||||
E: peposh@etc.sk
|
||||
D: Support for WEP EP250 (PXA) board
|
||||
|
||||
N: Thomas Frieden
|
||||
E: ThomasF@hyperion-entertainment.com
|
||||
D: Support for AmigaOne
|
||||
|
||||
N: Frank Gottschling
|
||||
E: fgottschling@eltec.de
|
||||
D: Support for ELTEC MHPC/BAB7xx/ELPPC boards, cfb-console, i8042, SMI LynxEM
|
||||
W: www.eltec.de
|
||||
|
||||
N: Marius Groeger
|
||||
E: mgroeger@sysgo.de
|
||||
D: MBX Support, board specific function interface, EST SBC8260 support; initial support for StrongARM (LART), ARM720TDMI (implementa A7)
|
||||
W: www.elinos.com
|
||||
|
||||
N: Kirk Haderlie
|
||||
E: khaderlie@vividimage.com
|
||||
D: Added TFTP to 8xxrom (-> 0.3.1)
|
||||
|
||||
N: Chris Hallinan
|
||||
E: clh@net1plus.com
|
||||
D: DHCP Support
|
||||
|
||||
N: Anne-Sophie Harnois
|
||||
E: Anne-Sophie.Harnois@nextream.fr
|
||||
D: Port to Walnut405 board
|
||||
|
||||
N: Andreas Heppel
|
||||
E: aheppel@sysgo.de
|
||||
D: CPU Support for MPC 75x; board support for Eltec BAB750 [obsolete!]
|
||||
|
||||
N: August Hoeraendl
|
||||
E: august.hoerandl@gmx.at
|
||||
D: Support for the logodl board (PXA2xx)
|
||||
|
||||
N: Josh Huber
|
||||
E: huber@alum.wpi.edu
|
||||
D: Port to the Galileo Evaluation Board, and the MPC74xx cpu series.
|
||||
W: http://www.mclx.com/
|
||||
|
||||
H: Stuart Hughes
|
||||
E: stuarth@lineo.com
|
||||
D: Port to MPC8260ADS board
|
||||
|
||||
H: Rich Ireland
|
||||
E: r.ireland@computer.org
|
||||
D: FPGA device configuration driver
|
||||
|
||||
N: Gary Jennejohn
|
||||
E: garyj@jennejohn.org, gj@denx.de
|
||||
D: Support for Samsung ARM920T S3C2400X, ARM920T "TRAB"
|
||||
W: www.denx.de
|
||||
|
||||
N: Murray Jensen
|
||||
E: Murray.Jensen@csiro.au
|
||||
D: Initial 8260 support; GDB support
|
||||
D: Port to Cogent+Hymod boards; Hymod Board Database
|
||||
|
||||
N: Yoo. Jonghoon
|
||||
E: yooth@ipone.co.kr
|
||||
D: Added port to the RPXlite board
|
||||
|
||||
N: Mark Jonas
|
||||
E: mark.jonas@freescale.com
|
||||
D: Support for Freescale Total5200 platform
|
||||
W: http://www.mobilegt.com/
|
||||
|
||||
N: Sam Song
|
||||
E: samsongshu@yahoo.com.cn
|
||||
D: Port to the RPXlite_DW board
|
||||
|
||||
N: Brad Kemp
|
||||
E: Brad.Kemp@seranoa.com
|
||||
D: Port to Windriver ppmc8260 board
|
||||
|
||||
N: Sangmoon Kim
|
||||
E: dogoil@etinsys.com
|
||||
D: Support for debris board
|
||||
|
||||
N: Frederick W. Klatt
|
||||
E: fred.klatt@windriver.com
|
||||
D: Support for Wind River SBC8540/SBC8560 boards
|
||||
|
||||
N: Thomas Koeller
|
||||
E: tkoeller@gmx.net
|
||||
D: Port to Motorola Sandpoint 3 (MPC8240)
|
||||
|
||||
N: Raghu Krishnaprasad
|
||||
E: Raghu.Krishnaprasad@fci.com
|
||||
D: Support for Adder-II MPC852T evaluation board
|
||||
W: http://www.forcecomputers.com
|
||||
|
||||
N: Bernhard Kuhn
|
||||
E: bkuhn@metrowerks.com
|
||||
D Support for Coldfire CPU; Support for Motorola M5272C3 and M5282EVB boards
|
||||
|
||||
N: Prakash Kumar
|
||||
E: prakash@embedx.com
|
||||
D Support for Intrinsyc CERF PXA250 board.
|
||||
|
||||
N: Thomas Lange
|
||||
E: thomas@corelatus.se
|
||||
D: Support for GTH and dbau1x00 boards; lots of PCMCIA fixes
|
||||
|
||||
N: Marc Leeman
|
||||
E: marc.leeman@barco.com
|
||||
D: Support for Barco Streaming Video Card (SVC) and Sample Compress Network (SCN)
|
||||
W: www.barco.com
|
||||
|
||||
N: The LEOX team
|
||||
E: team@leox.org
|
||||
D: Support for LEOX boards, DS164x RTC
|
||||
W: http://www.leox.org
|
||||
|
||||
N: Leif Lindholm
|
||||
E: leif.lindholm@i3micro.com
|
||||
D: Support for AMD dbau1550 board.
|
||||
|
||||
N: Stephan Linz
|
||||
E: linz@li-pro.net
|
||||
D: Support for Nios Stratix Development Kit (DK-1S10)
|
||||
D: Support for SSV ADNP/ESC1 (Nios Cyclone)
|
||||
W: http://www.li-pro.net
|
||||
|
||||
N: Raymond Lo
|
||||
E: lo@routefree.com
|
||||
D: Support for DOS partitions
|
||||
|
||||
N: Dan Malek
|
||||
E: dan@embeddedalley.com
|
||||
D: FADSROM, the grandfather of all of this
|
||||
D: Support for Silicon Turnkey eXpress XTc
|
||||
|
||||
N: Andrea "llandre" Marson
|
||||
E: andrea.marson@dave-tech.it
|
||||
D: Port to PPChameleonEVB board
|
||||
W: www.dave-tech.it
|
||||
|
||||
N: Reinhard Meyer
|
||||
E: r.meyer@emk-elektronik.de
|
||||
D: Port to EMK TOP860 Module
|
||||
|
||||
N: Jay Monkman
|
||||
E: jtm@smoothsmoothie.com
|
||||
D: EST SBC8260 support
|
||||
|
||||
N: Frank Morauf
|
||||
E: frank.morauf@salzbrenner.com
|
||||
D: Support for Embedded Planet RPX Super Board
|
||||
|
||||
N: David Müller
|
||||
E: d.mueller@elsoft.ch
|
||||
D: Support for Samsung ARM920T SMDK2410 eval board
|
||||
|
||||
N: Scott McNutt
|
||||
E: smcnutt@psyent.com
|
||||
D: Support for Altera Nios-32 CPU
|
||||
D: Support for Altera Nios-II CPU
|
||||
D: Support for Nios Cyclone Development Kit (DK-1C20)
|
||||
W: http://www.psyent.com
|
||||
|
||||
N: Rolf Offermanns
|
||||
E: rof@sysgo.de
|
||||
D: Initial support for SSV-DNP1110, SMC91111 driver
|
||||
W: www.elinos.com
|
||||
|
||||
N: John Otken
|
||||
E: jotken@softadvances.com
|
||||
D: Support for AMCC Luan 440SP board
|
||||
|
||||
N: Tolunay Orkun
|
||||
E: torkun@nextio.com
|
||||
D: Support for Cogent CSB272 & CSB472 boards
|
||||
|
||||
N: Keith Outwater
|
||||
E: keith_outwater@mvis.com
|
||||
D: Support for generic/custom MPC860T boards (GEN860T, GEN860T_SC)
|
||||
|
||||
N: Frank Panno
|
||||
E: fpanno@delphintech.com
|
||||
D: Support for Embedded Planet EP8260 Board
|
||||
|
||||
N: Denis Peter
|
||||
E: d.peter@mpl.ch
|
||||
D: Support for 4xx SCSI, floppy, CDROM, CT69000 video, ...
|
||||
D: Support for PIP405 board
|
||||
D: Support for MIP405 board
|
||||
|
||||
N: Dave Peverley
|
||||
E: dpeverley@mpc-data.co.uk
|
||||
W: http://www.mpc-data.co.uk
|
||||
D: OMAP730 P2 board support
|
||||
|
||||
N: Bill Pitts
|
||||
E: wlp@mindspring.com
|
||||
D: BedBug embedded debugger code
|
||||
|
||||
N: Daniel Poirot
|
||||
E: dan.poirot@windriver.com
|
||||
D: Support for the Wind River sbc405, sbc8240 board
|
||||
W: http://www.windriver.com
|
||||
|
||||
N: Stefan Roese
|
||||
E: stefan.roese@esd-electronics.com
|
||||
D: AMCC PPC401/403/405GP Support; Windows environment support
|
||||
|
||||
N: Erwin Rol
|
||||
E: erwin@muffin.org
|
||||
D: boot support for RTEMS
|
||||
|
||||
N: Paul Ruhland
|
||||
E: pruhland@rochester.rr.com
|
||||
D: Port to Logic Zoom LH7A40x SDK board(s)
|
||||
|
||||
N: Neil Russell
|
||||
E: caret@c-side.com
|
||||
D: Author of LiMon-1.4.2, which contributed some ideas
|
||||
|
||||
N: Travis B. Sawyer
|
||||
E: travis.sawyer@sandburst.com
|
||||
D: Support for AMCC PPC440GX, XES XPedite1000 440GX PrPMC board. AMCC 440gx Ref Platform (Ocotea)
|
||||
|
||||
N: Paolo Scaffardi
|
||||
E: arsenio@tin.it
|
||||
D: FADS823 configuration, MPC823 video support, I2C, wireless keyboard, lots more
|
||||
|
||||
N: Robert Schwebel
|
||||
E: r.schwebel@pengutronix.de
|
||||
D: Support for csb226, logodl and innokom boards (PXA2xx)
|
||||
|
||||
N: Art Shipkowski
|
||||
E: art@videon-central.com
|
||||
D: Support for NetSilicon NS7520
|
||||
|
||||
N: Yasushi Shoji
|
||||
E: yashi@atmark-techno.com
|
||||
D: Support for Xilinx MicroBlaze, for Atmark Techno SUZAKU FPGA board
|
||||
|
||||
N: Kurt Stremerch
|
||||
E: kurt@exys.be
|
||||
D: Support for Exys XSEngine board
|
||||
|
||||
N: Andrea Scian
|
||||
E: andrea.scian@dave-tech.it
|
||||
D: Port to B2 board
|
||||
W: www.dave-tech.it
|
||||
|
||||
N: Rob Taylor
|
||||
E: robt@flyingpig.com
|
||||
D: Port to MBX860T and Sandpoint8240
|
||||
|
||||
N: Erik Theisen
|
||||
E: etheisen@mindspring.com
|
||||
D: MBX8xx and many other patches
|
||||
|
||||
N: Jim Thompson
|
||||
E: jim@musenki.com
|
||||
D: Support for MUSENKI board
|
||||
|
||||
N: Rune Torgersen
|
||||
E: <runet@innovsys.com>
|
||||
D: Support for Motorola MPC8266ADS board
|
||||
|
||||
N: Greg Ungerer
|
||||
E: greg.ungerer@opengear.com
|
||||
D: Support for ks8695 CPU, and OpenGear cmXXXX boards
|
||||
|
||||
N: David Updegraff
|
||||
E: dave@cray.com
|
||||
D: Port to Cray L1 board; DHCP vendor extensions
|
||||
|
||||
N: Christian Vejlbo
|
||||
E: christian.vejlbo@tellabs.com
|
||||
D: FADS860T ethernet support
|
||||
|
||||
N: Robert Whaley
|
||||
E: rwhaley@applieddata.net
|
||||
D: Port to ARM PXA27x adsvix SBC
|
||||
|
||||
N: Martin Winistoerfer
|
||||
E: martinwinistoerfer@gmx.ch
|
||||
D: Port to MPC555/556 microcontrollers and support for cmi board
|
||||
|
||||
N: Ming-Len Wu
|
||||
E: minglen_wu@techware.com.tw
|
||||
D: Motorola MX1ADS board support
|
||||
W: http://www.techware.com.tw/
|
||||
|
||||
N: Xianghua Xiao
|
||||
E: x.xiao@motorola.com
|
||||
D: Support for Motorola 85xx(PowerQUICC III) chip, MPC8540ADS and MPC8560ADS boards.
|
||||
|
||||
N: John Zhan
|
||||
E: zhanz@sinovee.com
|
||||
D: Support for SinoVee Microsystems SC8xx SBC
|
||||
|
||||
N: Alex Zuepke
|
||||
E: azu@sysgo.de
|
||||
D: Overall improvements on StrongARM, ARM720TDMI; Support for Tuxscreen; initial PCMCIA support for ARM
|
||||
W: www.elinos.com
|
||||
|
||||
N: James MacAulay
|
||||
E: james.macaulay@amirix.com
|
||||
D: Suppport for Amirix AP1000
|
||||
W: www.amirix.com
|
|
@ -0,0 +1,539 @@
|
|||
#########################################################################
|
||||
# #
|
||||
# Regular Maintainers for U-Boot board support: #
|
||||
# #
|
||||
# For any board without permanent maintainer, please contact #
|
||||
# Wolfgang Denk <wd@denx.de> #
|
||||
# and Cc: the <U-Boot-Users@lists.sourceforge.net> mailing lists. #
|
||||
# #
|
||||
# Note: lists sorted by Maintainer Name #
|
||||
#########################################################################
|
||||
|
||||
|
||||
#########################################################################
|
||||
# PowerPC Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Greg Allen <gallen@arlut.utexas.edu>
|
||||
|
||||
UTX8245 MPC8245
|
||||
|
||||
Pantelis Antoniou <panto@intracom.gr>
|
||||
|
||||
NETVIA MPC8xx
|
||||
|
||||
Reinhard Arlt <reinhard.arlt@esd-electronics.com>
|
||||
|
||||
cpci5200 MPC5200
|
||||
pf5200 MPC5200
|
||||
|
||||
CPCI750 PPC750FX/GX
|
||||
|
||||
Yuli Barcohen <yuli@arabellasw.com>
|
||||
|
||||
Adder MPC87x/MPC852T
|
||||
ep8248 MPC8248
|
||||
ISPAN MPC8260
|
||||
MPC8260ADS MPC826x/MPC827x/MPC8280
|
||||
Rattler MPC8248
|
||||
ZPC1900 MPC8265
|
||||
|
||||
Jerry Van Baren <gerald.vanbaren@smiths-aerospace.com>
|
||||
|
||||
sacsng MPC8260
|
||||
|
||||
Oliver Brown <obrown@adventnetworks.com>
|
||||
|
||||
gw8260 MPC8260
|
||||
|
||||
Conn Clark <clark@esteem.com>
|
||||
|
||||
ESTEEM192E MPC8xx
|
||||
|
||||
Kári Davíðsson <kd@flaga.is>
|
||||
|
||||
FLAGADM MPC823
|
||||
|
||||
Torsten Demke <torsten.demke@fci.com>
|
||||
|
||||
eXalion MPC824x
|
||||
|
||||
Wolfgang Denk <wd@denx.de>
|
||||
|
||||
IceCube_5100 MGT5100
|
||||
IceCube_5200 MPC5200
|
||||
|
||||
AMX860 MPC860
|
||||
ETX094 MPC850
|
||||
FPS850L MPC850
|
||||
FPS860L MPC860
|
||||
ICU862 MPC862
|
||||
IP860 MPC860
|
||||
IVML24 MPC860
|
||||
IVML24_128 MPC860
|
||||
IVML24_256 MPC860
|
||||
IVMS8 MPC860
|
||||
IVMS8_128 MPC860
|
||||
IVMS8_256 MPC860
|
||||
LANTEC MPC850
|
||||
LWMON MPC823
|
||||
NC650 MPC852
|
||||
R360MPI MPC823
|
||||
RMU MPC850
|
||||
RRvision MPC823
|
||||
SM850 MPC850
|
||||
SPD823TS MPC823
|
||||
TQM823L MPC823
|
||||
TQM823L_LCD MPC823
|
||||
TQM850L MPC850
|
||||
TQM855L MPC855
|
||||
TQM860L MPC860
|
||||
TQM860L_FEC MPC860
|
||||
c2mon MPC855
|
||||
hermes MPC860
|
||||
lwmon MPC823
|
||||
pcu_e MPC855
|
||||
|
||||
CU824 MPC8240
|
||||
Sandpoint8240 MPC8240
|
||||
SL8245 MPC8245
|
||||
|
||||
ATC MPC8250
|
||||
PM825 MPC8250
|
||||
|
||||
TQM8255 MPC8255
|
||||
|
||||
CPU86 MPC8260
|
||||
PM826 MPC8260
|
||||
TQM8260 MPC8260
|
||||
|
||||
P3G4 MPC7410
|
||||
|
||||
PCIPPC2 MPC750
|
||||
PCIPPC6 MPC750
|
||||
|
||||
EXBITGEN PPC405GP
|
||||
|
||||
Jon Diekema <jon.diekema@smiths-aerospace.com>
|
||||
|
||||
sbc8260 MPC8260
|
||||
|
||||
Dave Ellis <DGE@sixnetio.com>
|
||||
|
||||
SXNI855T MPC8xx
|
||||
|
||||
Thomas Frieden <ThomasF@hyperion-entertainment.com>
|
||||
|
||||
AmigaOneG3SE MPC7xx
|
||||
|
||||
Matthias Fuchs <matthias.fuchs@esd-electronics.com>
|
||||
|
||||
ADCIOP IOP480 (PPC401)
|
||||
APC405 PPC405GP
|
||||
AR405 PPC405GP
|
||||
ASH405 PPC405EP
|
||||
CANBT PPC405CR
|
||||
CPCI2DP PPC405GP
|
||||
CPCI405 PPC405GP
|
||||
CPCI4052 PPC405GP
|
||||
CPCI405AB PPC405GP
|
||||
CPCI405DT PPC405GP
|
||||
CPCI440 PPC440GP
|
||||
CPCIISER4 PPC405GP
|
||||
DASA_SIM IOP480 (PPC401)
|
||||
DP405 PPC405EP
|
||||
DU405 PPC405GP
|
||||
G2000 PPC405EP
|
||||
HH405 PPC405EP
|
||||
HUB405 PPC405EP
|
||||
OCRTC PPC405GP
|
||||
ORSG PPC405GP
|
||||
PCI405 PPC405GP
|
||||
PLU405 PPC405EP
|
||||
PMC405 PPC405GP
|
||||
VOH405 PPC405EP
|
||||
VOM405 PPC405EP
|
||||
WUH405 PPC405EP
|
||||
CMS700 PPC405EP
|
||||
|
||||
Frank Gottschling <fgottschling@eltec.de>
|
||||
|
||||
MHPC MPC8xx
|
||||
|
||||
BAB7xx MPC740/MPC750
|
||||
|
||||
Wolfgang Grandegger <wg@denx.de>
|
||||
|
||||
CCM MPC855
|
||||
|
||||
PN62 MPC8240
|
||||
|
||||
IPHASE4539 MPC8260
|
||||
SCM MPC8260
|
||||
|
||||
Howard Gray <mvsensor@matrix-vision.de>
|
||||
|
||||
MVS1 MPC823
|
||||
|
||||
Klaus Heydeck <heydeck@kieback-peter.de>
|
||||
|
||||
KUP4K MPC855
|
||||
KUP4X MPC859
|
||||
|
||||
Murray Jensen <Murray.Jensen@csiro.au>
|
||||
|
||||
cogent_mpc8xx MPC8xx
|
||||
|
||||
cogent_mpc8260 MPC8260
|
||||
hymod MPC8260
|
||||
|
||||
Brad Kemp <Brad.Kemp@seranoa.com>
|
||||
|
||||
ppmc8260 MPC8260
|
||||
|
||||
Sangmoon Kim <dogoil@etinsys.com>
|
||||
|
||||
debris MPC8245
|
||||
|
||||
Thomas Lange <thomas@corelatus.se>
|
||||
|
||||
GTH MPC860
|
||||
|
||||
The LEOX team <team@leox.org>
|
||||
|
||||
ELPT860 MPC860T
|
||||
|
||||
Nye Liu <nyet@zumanetworks.com>
|
||||
|
||||
ZUMA MPC7xx_74xx
|
||||
|
||||
Jon Loeliger <jdl@freescale.com>
|
||||
|
||||
MPC8540ADS MPC8540
|
||||
MPC8560ADS MPC8560
|
||||
MPC8541CDS MPC8541
|
||||
MPC8555CDS MPC8555
|
||||
|
||||
Dan Malek <dan@embeddededge.com>
|
||||
|
||||
STxGP3 MPC85xx
|
||||
STxXTc MPC8xx
|
||||
|
||||
Eran Man <eran@nbase.co.il>
|
||||
|
||||
EVB64260_750CX MPC750CX
|
||||
|
||||
Andrea "llandre" Marson <andrea.marson@dave-tech.it>
|
||||
|
||||
PPChameleonEVB PPC405EP
|
||||
|
||||
Reinhard Meyer <r.meyer@emk-elektronik.de>
|
||||
|
||||
TOP860 MPC860T
|
||||
TOP5200 MPC5200
|
||||
|
||||
Tolunay Orkun <torkun@nextio.com>
|
||||
|
||||
csb272 PPC405GP
|
||||
csb472 PPC405GP
|
||||
|
||||
John Otken <jotken@softadvances.com>
|
||||
|
||||
luan PPC440SP
|
||||
|
||||
Keith Outwater <Keith_Outwater@mvis.com>
|
||||
|
||||
GEN860T MPC860T
|
||||
GEN860T_SC MPC860T
|
||||
|
||||
Frank Panno <fpanno@delphintech.com>
|
||||
|
||||
ep8260 MPC8260
|
||||
|
||||
Peter Pearse <peter.pearse@arm.com>
|
||||
integratorcp All current ARM supplied &
|
||||
supported core modules
|
||||
- see http://www.arm.com
|
||||
/products/DevTools
|
||||
/Hardware_Platforms.html
|
||||
versatile ARM926EJ-S
|
||||
versatile ARM926EJ-S
|
||||
|
||||
Denis Peter <d.peter@mpl.ch>
|
||||
|
||||
MIP405 PPC4xx
|
||||
PIP405 PPC4xx
|
||||
|
||||
Daniel Poirot <dan.poirot@windriver.com>
|
||||
|
||||
sbc8240 MPC8240
|
||||
sbc405 PPC405GP
|
||||
|
||||
Stefan Roese <sr@denx.de>
|
||||
|
||||
uc100 MPC857
|
||||
|
||||
TQM85xx MPC8540/8541/8555/8560
|
||||
|
||||
bamboo PPC440EP
|
||||
bunbinga PPC405EP
|
||||
ebony PPC440GP
|
||||
ocotea PPC440GX
|
||||
p3p440 PPC440GP
|
||||
sycamore PPC405GPr
|
||||
walnut PPC405GP
|
||||
yellowstone PPC440GR
|
||||
yosemite PPC440EP
|
||||
|
||||
Yusdi Santoso <yusdi_santoso@adaptec.com>
|
||||
|
||||
HIDDEN_DRAGON MPC8241/MPC8245
|
||||
|
||||
Travis Sawyer (travis.sawyer@sandburst.com>
|
||||
|
||||
KAREF PPC440GX
|
||||
METROBOX PPC440GX
|
||||
XPEDITE1K PPC440GX
|
||||
|
||||
Peter De Schrijver <p2@mind.be>
|
||||
|
||||
ML2 PPC4xx
|
||||
|
||||
Erik Theisen <etheisen@mindspring.com>
|
||||
|
||||
W7OLMC PPC4xx
|
||||
W7OLMG PPC4xx
|
||||
|
||||
Jim Thompson <jim@musenki.com>
|
||||
|
||||
MUSENKI MPC8245/8241
|
||||
Sandpoint8245 MPC8245
|
||||
|
||||
Rune Torgersen <runet@innovsys.com>
|
||||
|
||||
MPC8266ADS MPC8266
|
||||
|
||||
Josef Wagner <Wagner@Microsys.de>
|
||||
|
||||
CPC45 MPC8245
|
||||
PM520 MPC5200
|
||||
|
||||
Stephen Williams <steve@icarus.com>
|
||||
|
||||
JSE PPC405GPr
|
||||
|
||||
John Zhan <zhanz@sinovee.com>
|
||||
|
||||
svm_sc8xx MPC8xx
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Unknown / orphaned boards:
|
||||
|
||||
ADS860 MPC8xx
|
||||
FADS823 MPC8xx
|
||||
FADS850SAR MPC8xx
|
||||
FADS860T MPC8xx
|
||||
GENIETV MPC8xx
|
||||
IAD210 MPC8xx
|
||||
MBX MPC8xx
|
||||
MBX860T MPC8xx
|
||||
NX823 MPC8xx
|
||||
RPXClassic MPC8xx
|
||||
RPXlite MPC8xx
|
||||
|
||||
CRAYL1 PPC4xx
|
||||
ERIC PPC4xx
|
||||
|
||||
MOUSSE MPC824x
|
||||
|
||||
RPXsuper MPC8260
|
||||
rsdproto MPC8260
|
||||
|
||||
EVB64260 MPC7xx_74xx
|
||||
|
||||
|
||||
#########################################################################
|
||||
# ARM Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Rowel Atienza <rowel@diwalabs.com>
|
||||
|
||||
armadillo ARM720T
|
||||
|
||||
Rishi Bhattacharya <rishi@ti.com>
|
||||
|
||||
omap5912osk ARM926EJS
|
||||
|
||||
Cliff Brake <cliff.brake@gmail.com>
|
||||
|
||||
pxa255_idp xscale
|
||||
|
||||
Rick Bronson <rick@efn.org>
|
||||
|
||||
AT91RM9200DK at91rm9200
|
||||
|
||||
George G. Davis <gdavis@mvista.com>
|
||||
|
||||
assabet SA1100
|
||||
gcplus SA1100
|
||||
|
||||
Thomas Elste <info@elste.org>
|
||||
|
||||
modnet50 ARM720T (NET+50)
|
||||
|
||||
Peter Figuli <peposh@etc.sk>
|
||||
|
||||
wepep250 xscale
|
||||
|
||||
Marius Gröger <mag@sysgo.de>
|
||||
|
||||
impa7 ARM720T (EP7211)
|
||||
ep7312 ARM720T (EP7312)
|
||||
|
||||
Kshitij Gupta <kshitij@ti.com>
|
||||
|
||||
omap1510inn ARM925T
|
||||
omap1610inn ARM926EJS
|
||||
|
||||
Kyle Harris <kharris@nexus-tech.net>
|
||||
|
||||
lubbock xscale
|
||||
cradle xscale
|
||||
ixdp425 xscale
|
||||
|
||||
Gary Jennejohn <gj@denx.de>
|
||||
|
||||
smdk2400 ARM920T
|
||||
trab ARM920T
|
||||
|
||||
Nishant Kamat <nskamat@ti.com>
|
||||
|
||||
omap1610h2 ARM926EJS
|
||||
|
||||
Prakash Kumar <prakash@embedx.com>
|
||||
|
||||
cerf250 xscale
|
||||
|
||||
David Müller <d.mueller@elsoft.ch>
|
||||
|
||||
smdk2410 ARM920T
|
||||
VCMA9 ARM920T
|
||||
|
||||
Rolf Offermanns <rof@sysgo.de>
|
||||
|
||||
shannon SA1100
|
||||
|
||||
Dave Peverley <dpeverley@mpc-data.co.uk>
|
||||
|
||||
omap730p2 ARM926EJS
|
||||
|
||||
Robert Schwebel <r.schwebel@pengutronix.de>
|
||||
|
||||
csb226 xscale
|
||||
innokom xscale
|
||||
|
||||
Andrea Scian <andrea.scian@dave-tech.it>
|
||||
|
||||
B2 ARM7TDMI (S3C44B0X)
|
||||
|
||||
Greg Ungerer <greg.ungerer@opengear.com>
|
||||
|
||||
cm4008 ks8695p
|
||||
cm4116 ks8695p
|
||||
cm4148 ks8695p
|
||||
|
||||
Richard Woodruff <r-woodruff2@ti.com>
|
||||
|
||||
omap2420h4 ARM1136EJS
|
||||
|
||||
Alex Züpke <azu@sysgo.de>
|
||||
|
||||
lart SA1100
|
||||
dnp1110 SA1110
|
||||
|
||||
#########################################################################
|
||||
# x86 Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Daniel Engström <daniel@omicron.se>
|
||||
|
||||
sc520_cdp x86
|
||||
|
||||
#########################################################################
|
||||
# MIPS Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Wolfgang Denk <wd@denx.de>
|
||||
|
||||
incaip MIPS32 4Kc
|
||||
purple MIPS64 5Kc
|
||||
|
||||
Thomas Lange <thomas@corelatus.se>
|
||||
dbau1x00 MIPS32 Au1000
|
||||
|
||||
#########################################################################
|
||||
# Nios-32 Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Stephan Linz <linz@li-pro.net>
|
||||
|
||||
DK1S10 Nios-32
|
||||
ADNPESC1 Nios-32
|
||||
|
||||
Scott McNutt <smcnutt@psyent.com>
|
||||
|
||||
DK1C20 Nios-32
|
||||
|
||||
#########################################################################
|
||||
# Nios-II Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Scott McNutt <smcnutt@psyent.com>
|
||||
|
||||
PCI5441 Nios-II
|
||||
PK1C20 Nios-II
|
||||
|
||||
#########################################################################
|
||||
# MicroBlaze Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Yasushi Shoji <yashi@atmark-techno.com>
|
||||
|
||||
SUZAKU MicroBlaze
|
||||
|
||||
#########################################################################
|
||||
# Coldfire Systems: #
|
||||
# #
|
||||
# Maintainer Name, Email Address #
|
||||
# Board CPU #
|
||||
#########################################################################
|
||||
|
||||
Matthias Fuchs <matthias.fuchs@esd-electronics.com>
|
||||
|
||||
TASREG MCF5249
|
||||
|
||||
#########################################################################
|
||||
# End of MAINTAINERS list #
|
||||
#########################################################################
|
|
@ -0,0 +1,346 @@
|
|||
#
|
||||
# (C) Copyright 2000-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
|
||||
#
|
||||
|
||||
VERSION = 1
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 4
|
||||
EXTRAVERSION =
|
||||
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||
VERSION_FILE = include/version_autogenerated.h
|
||||
|
||||
HOSTARCH := $(shell uname -m | \
|
||||
sed -e s/i.86/i386/ \
|
||||
-e s/sun4u/sparc64/ \
|
||||
-e s/arm.*/arm/ \
|
||||
-e s/sa110/arm/ \
|
||||
-e s/powerpc/ppc/ \
|
||||
-e s/macppc/ppc/)
|
||||
|
||||
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
|
||||
sed -e 's/\(cygwin\).*/cygwin/')
|
||||
|
||||
export HOSTARCH HOSTOS
|
||||
|
||||
# Deal with colliding definitions from tcsh etc.
|
||||
VENDOR=
|
||||
|
||||
#########################################################################
|
||||
|
||||
TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
|
||||
export TOPDIR
|
||||
|
||||
BUILDVERSION=$(shell if test -e $(KERNELPATH)/ath_version.mk ; then cat $(KERNELPATH)/ath_version.mk | sed s/EXTRAVERSION=-LSDK-//g; fi)
|
||||
|
||||
ifndef COMPRESSED_UBOOT
|
||||
COMPRESSED_UBOOT = 0
|
||||
endif
|
||||
|
||||
ifeq (include/config.mk,$(wildcard include/config.mk))
|
||||
# load ARCH, BOARD, and CPU configuration
|
||||
include include/config.mk
|
||||
export ARCH CPU BOARD VENDOR SOC
|
||||
ifndef CROSS_COMPILE
|
||||
ifeq ($(HOSTARCH),ppc)
|
||||
CROSS_COMPILE =
|
||||
else
|
||||
ifeq ($(ARCH),ppc)
|
||||
CROSS_COMPILE = powerpc-linux-
|
||||
endif
|
||||
ifeq ($(ARCH),arm)
|
||||
CROSS_COMPILE = arm-linux-
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
ifeq ($(HOSTARCH),i386)
|
||||
CROSS_COMPILE =
|
||||
else
|
||||
CROSS_COMPILE = i386-linux-
|
||||
endif
|
||||
endif
|
||||
ifeq ($(ARCH),mips)
|
||||
CROSS_COMPILE = mips-linux-
|
||||
endif
|
||||
ifeq ($(ARCH),nios)
|
||||
CROSS_COMPILE = nios-elf-
|
||||
endif
|
||||
ifeq ($(ARCH),nios2)
|
||||
CROSS_COMPILE = nios2-elf-
|
||||
endif
|
||||
ifeq ($(ARCH),m68k)
|
||||
CROSS_COMPILE = m68k-elf-
|
||||
endif
|
||||
ifeq ($(ARCH),microblaze)
|
||||
CROSS_COMPILE = mb-
|
||||
endif
|
||||
ifeq ($(ARCH),blackfin)
|
||||
CROSS_COMPILE = bfin-elf-
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
export CROSS_COMPILE
|
||||
|
||||
# load other configuration
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
|
||||
#########################################################################
|
||||
# U-Boot objects....order is important (i.e. start must be first)
|
||||
OBJS = cpu/$(CPU)/start.o
|
||||
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
OBJS_BOOTSTRAP = cpu/$(CPU)/start_bootstrap.o
|
||||
endif
|
||||
|
||||
|
||||
|
||||
LIBS = lib_generic/libgeneric.a
|
||||
LIBS += common/libcommon.a
|
||||
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
|
||||
LIBS += cpu/$(CPU)/lib$(CPU).a
|
||||
ifdef SOC
|
||||
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
|
||||
endif
|
||||
LIBS += lib_$(ARCH)/lib$(ARCH).a
|
||||
|
||||
LIBS += drivers/libdrivers.a
|
||||
LIBS += disk/libdisk.a fs/fat/libfat.a fs/libfs.a
|
||||
LIBS += net/libnet.a
|
||||
LIBS += rtc/librtc.a
|
||||
LIBS += $(BOARDLIBS)
|
||||
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
LIBS_BOOTSTRAP = lib_bootstrap/libbootstrap.a
|
||||
#LIBS_BOOTSTRAP += lib_$(CPU)/lib$(CPU).a
|
||||
LIBS_BOOTSTRAP += board/$(BOARDDIR)/lib$(BOARD).a
|
||||
LIBS_BOOTSTRAP += cpu/$(CPU)/lib$(CPU).a
|
||||
ifneq ($(SOC),)
|
||||
LIBS_BOOTSTRAP += cpu/$(CPU)/$(SOC)/lib$(SOC).a
|
||||
endif
|
||||
endif
|
||||
.PHONY : $(LIBS)
|
||||
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
.PHONY : $(LIBS_BOOTSTRAP)
|
||||
endif
|
||||
|
||||
# Add GCC lib
|
||||
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
|
||||
|
||||
|
||||
# The "tools" are needed early, so put this first
|
||||
# Don't include stuff already done in $(LIBS)
|
||||
SUBDIRS = tools
|
||||
.PHONY : $(SUBDIRS)
|
||||
|
||||
#########################################################################
|
||||
#########################################################################
|
||||
|
||||
ALL = u-boot.srec u-boot.bin System.map
|
||||
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
all: $(ALL) tuboot.bin
|
||||
else
|
||||
all: $(ALL)
|
||||
endif
|
||||
|
||||
u-boot.hex: u-boot
|
||||
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
|
||||
|
||||
u-boot.srec: u-boot
|
||||
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@
|
||||
|
||||
u-boot.bin: u-boot
|
||||
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
|
||||
|
||||
u-boot.img: u-boot.bin
|
||||
./tools/mkimage -A $(ARCH) -T firmware -C none \
|
||||
-a $(TEXT_BASE) -e 0 \
|
||||
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
|
||||
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
|
||||
-d $< $@
|
||||
|
||||
u-boot.dis: u-boot
|
||||
$(OBJDUMP) -d $< > $@
|
||||
|
||||
u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
|
||||
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
|
||||
$(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) $(BOARD_EXTRA_OBJS) \
|
||||
--start-group $(LIBS) --end-group $(PLATFORM_LIBS) \
|
||||
-Map u-boot.map -o u-boot
|
||||
|
||||
$(LIBS):
|
||||
$(MAKE) -C `dirname $@`
|
||||
|
||||
$(SUBDIRS):
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
|
||||
LZMA = $(BUILD_DIR)/util/lzma
|
||||
|
||||
tuboot.bin: System.map bootstrap.bin u-boot.lzimg
|
||||
@cat bootstrap.bin > $@
|
||||
@cat u-boot.lzimg >> $@
|
||||
|
||||
u-boot.lzimg: $(obj)u-boot.bin System.map
|
||||
@$(LZMA) e $(obj)u-boot.bin u-boot.bin.lzma
|
||||
@./tools/mkimage -A mips -T firmware -C lzma \
|
||||
-a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \
|
||||
-e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \
|
||||
-n 'u-boot image' -d $(obj)u-boot.bin.lzma $@
|
||||
|
||||
bootstrap.bin: bootstrap
|
||||
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
|
||||
|
||||
bootstrap: depend version $(SUBDIRS) $(OBJS_BOOTSTRAP) $(LIBS_BOOTSTRAP) $(LDSCRIPT_BOOTSTRAP)
|
||||
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS_BOOTSTRAP) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
|
||||
$(LD) $(LDFLAGS_BOOTSTRAP) $$UNDEF_SYM $(OBJS_BOOTSTRAP) \
|
||||
--start-group $(LIBS_BOOTSTRAP) --end-group $(PLATFORM_LIBS) \
|
||||
-Map bootstrap.map -o bootstrap
|
||||
|
||||
$(LIBS_BOOTSTRAP):
|
||||
$(MAKE) -C `dirname $@`
|
||||
endif
|
||||
|
||||
version:
|
||||
@echo -n "#define U_BOOT_VERSION \"U-Boot " > $(VERSION_FILE); \
|
||||
echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); \
|
||||
echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion \
|
||||
$(TOPDIR)) >> $(VERSION_FILE); \
|
||||
echo "\"" >> $(VERSION_FILE)
|
||||
|
||||
gdbtools:
|
||||
$(MAKE) -C tools/gdb || exit 1
|
||||
|
||||
depend dep:
|
||||
@for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir .depend ; done
|
||||
|
||||
tags:
|
||||
ctags -w `find $(SUBDIRS) include \
|
||||
lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \
|
||||
fs/cramfs fs/fat fs/fdos fs/jffs2 \
|
||||
net disk rtc dtt drivers drivers/sk98lin common \
|
||||
\( -name CVS -prune \) -o \( -name '*.[ch]' -print \)`
|
||||
|
||||
etags:
|
||||
etags -a `find $(SUBDIRS) include \
|
||||
lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \
|
||||
fs/cramfs fs/fat fs/fdos fs/jffs2 \
|
||||
net disk rtc dtt drivers drivers/sk98lin common \
|
||||
\( -name CVS -prune \) -o \( -name '*.[ch]' -print \)`
|
||||
|
||||
System.map: u-boot
|
||||
@$(NM) $< | \
|
||||
grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
|
||||
sort > System.map
|
||||
|
||||
#########################################################################
|
||||
else
|
||||
all install u-boot u-boot.srec depend dep:
|
||||
@echo "System not configured - see README" >&2
|
||||
@ exit 1
|
||||
endif
|
||||
|
||||
#########################################################################
|
||||
|
||||
unconfig:
|
||||
@rm -f include/config.h include/config.mk board/*/config.tmp
|
||||
|
||||
|
||||
#========================================================================
|
||||
# MIPS
|
||||
#========================================================================
|
||||
|
||||
carambola2_config: unconfig hornet_common_config
|
||||
@echo "#define FLASH_SIZE $(FLASH_SIZE)" >>include/config.h
|
||||
@./mkconfig -a carambola2 mips mips carambola2 ar7240 ar7240
|
||||
|
||||
|
||||
hornet_common_config :
|
||||
@ >include/config.h
|
||||
@echo "#define CONFIG_AR7240 1" >>include/config.h
|
||||
@echo "#define CONFIG_MACH_HORNET 1" >>include/config.h
|
||||
ifeq ($(CONFIG_HORNET_XTAL), 40)
|
||||
@echo "#define CONFIG_40MHZ_XTAL_SUPPORT 1" >>include/config.h
|
||||
endif
|
||||
ifeq ($(CONFIG_HORNET_1_1_WAR), 1)
|
||||
@echo "#define CONFIG_HORNET_1_1_WAR 1" >>include/config.h
|
||||
endif
|
||||
ifeq ($(AG7240_BROADCAST_ENABLE), 1)
|
||||
@echo "#define AG7240_BROADCAST_ENABLE 1" >>include/config.h
|
||||
endif
|
||||
ifeq ($(NEW_DDR_TAP_CAL), 1)
|
||||
@echo "#define NEW_DDR_TAP_CAL 1" >>include/config.h
|
||||
endif
|
||||
|
||||
|
||||
###############
|
||||
|
||||
clean:
|
||||
@echo Making $@
|
||||
@find . -type f \
|
||||
\( -name 'core' -o -name '*.bak' -o -name '*~' \
|
||||
-o -name '*.o' -o -name '*.a' -o -name .depend \) -print \
|
||||
| xargs rm -f
|
||||
@rm -f examples/hello_world examples/timer \
|
||||
examples/eepro100_eeprom examples/sched \
|
||||
examples/mem_to_mem_idma2intr examples/82559_eeprom \
|
||||
examples/smc91111_eeprom \
|
||||
examples/test_burst
|
||||
@rm -f tools/img2srec tools/mkimage tools/envcrc tools/gen_eth_addr
|
||||
@rm -f tools/mpc86x_clk tools/ncb
|
||||
@rm -f tools/easylogo/easylogo tools/bmp_logo
|
||||
@rm -f tools/gdb/astest tools/gdb/gdbcont tools/gdb/gdbsend
|
||||
@rm -f tools/env/fw_printenv tools/env/fw_setenv
|
||||
@rm -f board/cray/L1/bootscript.c board/cray/L1/bootscript.image
|
||||
@rm -f board/netstar/eeprom board/netstar/crcek
|
||||
@rm -f board/netstar/*.srec board/netstar/*.bin
|
||||
@rm -f board/trab/trab_fkt board/voiceblue/eeprom
|
||||
@rm -f board/integratorap/u-boot.lds board/integratorcp/u-boot.lds
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
@rm -f lib_bootstrap/*.o
|
||||
@rm -f lib_bootstrap/*.a
|
||||
@rm -f bootstrap bootstrap.bin tuboot.bin u-boot.lzimg
|
||||
endif
|
||||
|
||||
clobber: clean
|
||||
@echo Making $@
|
||||
@find . -type f \( -name .depend \
|
||||
-o -name '*.srec' -o -name '*.bin' -o -name u-boot.img \) \
|
||||
-print0 \
|
||||
| xargs -0 rm -f
|
||||
@rm -f $(OBJS) *.bak tags TAGS include/version_autogenerated.h
|
||||
@rm -fr *.*~
|
||||
@rm -f u-boot u-boot.map u-boot.hex $(ALL)
|
||||
@rm -f tools/crc32.c tools/environment.c tools/env/crc32.c
|
||||
@rm -f tools/inca-swap-bytes cpu/mpc824x/bedbug_603e.c
|
||||
@rm -f include/asm/proc include/asm/arch include/asm
|
||||
|
||||
mrproper \
|
||||
distclean: clobber unconfig
|
||||
|
||||
backup:
|
||||
F=`basename $(TOPDIR)` ; cd .. ; \
|
||||
gtar --force-local -zcvf `date "+$$F-%Y-%m-%d-%T.tar.gz"` $$F
|
||||
|
||||
#########################################################################
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
|||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = lib$(BOARD).a
|
||||
|
||||
OBJS = $(BOARD).o flash.o ../common/ar7240_flash.o ../common/ar7240_s26_phy.o
|
||||
OBJS += carambola_factory.o
|
||||
OBJS += ../common/usb_boot.o
|
||||
SOBJS = ../common/lowlevel_init.o
|
||||
SOBJS += hornet_pll_init.o
|
||||
|
||||
$(LIB): .depend $(OBJS) $(SOBJS)
|
||||
$(AR) crv $@ $(OBJS) $(SOBJS)
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,469 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <config.h>
|
||||
#include <version.h>
|
||||
#include "ar7240_soc.h"
|
||||
|
||||
extern void ar7240_ddr_initial_config(uint32_t refresh);
|
||||
extern int ar7240_ddr_find_size(void);
|
||||
|
||||
void
|
||||
ar7240_usb_initial_config(void)
|
||||
{
|
||||
#ifndef CONFIG_HORNET_EMU
|
||||
ar7240_reg_wr_nf(AR7240_USB_PLL_CONFIG, 0x0a04081e);
|
||||
ar7240_reg_wr_nf(AR7240_USB_PLL_CONFIG, 0x0804081e);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
int ar7240_boot_status = 0; // Global variable to indicate if boot is succesful
|
||||
// negative values show failure
|
||||
#endif
|
||||
|
||||
typedef struct reg_conf{
|
||||
unsigned int addr;
|
||||
unsigned int set_mask;
|
||||
unsigned int clear_mask;
|
||||
};
|
||||
|
||||
// Carambola2 GPIO LED definition
|
||||
|
||||
typedef struct gpio_led_desc {
|
||||
int id;
|
||||
int bit; //GPIO bit
|
||||
int polarity; //1 - high active; 0 - low active
|
||||
int disable; //1 - disable led, 0 - enable
|
||||
};
|
||||
|
||||
int led_count=5;
|
||||
struct gpio_led_desc leds[]={
|
||||
{// WLAN LED
|
||||
.id=0,
|
||||
.bit=0,
|
||||
.polarity=0,
|
||||
.disable=0
|
||||
},
|
||||
{// ETH0_LED
|
||||
.id=1,
|
||||
.bit=13,
|
||||
.polarity=1,
|
||||
.disable=0
|
||||
},
|
||||
{// ETH1_LED
|
||||
.id=2,
|
||||
.bit=14,
|
||||
.polarity=1,
|
||||
.disable=0
|
||||
},
|
||||
{// USB recovery indication
|
||||
.id=3,
|
||||
.bit=0,
|
||||
.polarity=0,
|
||||
.disable=0
|
||||
},
|
||||
{// Nothing
|
||||
.id=4,
|
||||
.bit=0,
|
||||
.polarity=0,
|
||||
.disable=1
|
||||
}
|
||||
};
|
||||
|
||||
struct gpio_led_desc buttons[]={
|
||||
{// USB Boot
|
||||
.id=0,
|
||||
.bit=11,
|
||||
.polarity=0,
|
||||
.disable=0
|
||||
},
|
||||
{// Nothing
|
||||
.id=1,
|
||||
.bit=0,
|
||||
.polarity=0,
|
||||
.disable=1
|
||||
},
|
||||
{// Nothing
|
||||
.id=2,
|
||||
.bit=0,
|
||||
.polarity=0,
|
||||
.disable=1
|
||||
},
|
||||
{// Nothing
|
||||
.id=3,
|
||||
.bit=0,
|
||||
.polarity=0,
|
||||
.disable=1
|
||||
},
|
||||
{// Nothing
|
||||
.id=4,
|
||||
.bit=0,
|
||||
.polarity=0,
|
||||
.disable=1
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
ar7240_usb_otp_config(void)
|
||||
{
|
||||
unsigned int addr, reg_val, reg_usb;
|
||||
int time_out, status, usb_valid;
|
||||
|
||||
for (addr = 0xb8114014; ;addr -= 0x10) {
|
||||
status = 0;
|
||||
time_out = 20;
|
||||
|
||||
reg_val = ar7240_reg_rd(addr);
|
||||
|
||||
while ((time_out > 0) && (~status)) {
|
||||
if ((( ar7240_reg_rd(0xb8115f18)) & 0x7) == 0x4) {
|
||||
status = 1;
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
time_out--;
|
||||
}
|
||||
|
||||
reg_val = ar7240_reg_rd(0xb8115f1c);
|
||||
if ((reg_val & 0x80) == 0x80){
|
||||
usb_valid = 1;
|
||||
reg_usb = reg_val & 0x000000ff;
|
||||
}
|
||||
|
||||
if (addr == 0xb8114004) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (usb_valid) {
|
||||
reg_val = ar7240_reg_rd(0xb8116c88);
|
||||
reg_val &= ~0x03f00000;
|
||||
reg_val |= (reg_usb & 0xf) << 22;
|
||||
ar7240_reg_wr(0xb8116c88, reg_val);
|
||||
}
|
||||
}
|
||||
|
||||
void assign_gpio(void *data, int item_count1, int* tmp_item)
|
||||
{
|
||||
struct reg_conf *regs;
|
||||
regs = (struct reg_conf*)data;
|
||||
regs[item_count1].addr = tmp_item[0];
|
||||
regs[item_count1].set_mask = tmp_item[1];
|
||||
regs[item_count1].clear_mask = tmp_item[2];
|
||||
return;
|
||||
}
|
||||
|
||||
void assign_leds(void *data, int item_count1, int* tmp_item)
|
||||
{
|
||||
if (tmp_item[0]<5 && tmp_item[0]>=0){
|
||||
int id=tmp_item[0];
|
||||
leds[id].id = id;
|
||||
leds[id].bit = tmp_item[1];
|
||||
leds[id].polarity = tmp_item[2];
|
||||
leds[id].disable = tmp_item[3];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void assign_buttons(void *data, int item_count1, int* tmp_item)
|
||||
{
|
||||
if (tmp_item[0]<5 && tmp_item[0]>=0){
|
||||
int id=tmp_item[0];
|
||||
buttons[id].id = id;
|
||||
buttons[id].bit = tmp_item[1];
|
||||
buttons[id].polarity = tmp_item[2];
|
||||
buttons[id].disable = tmp_item[3];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int convert_hex(char* str, int item_nr)
|
||||
{
|
||||
return (simple_strtol(str, NULL, 16));
|
||||
}
|
||||
|
||||
int convert_dec(char* str, int item_nr)
|
||||
{
|
||||
return (simple_strtol(str, NULL, 10));
|
||||
}
|
||||
|
||||
int count_args(char* env)
|
||||
{
|
||||
char* pos;
|
||||
pos = strchr(env,'/');
|
||||
unsigned int reg_count=1;
|
||||
while (pos != NULL){
|
||||
reg_count++;
|
||||
pos = strchr(pos+1,'/');
|
||||
}
|
||||
return reg_count;
|
||||
}
|
||||
|
||||
int parse_config(char* env, int max_args, void *regs, int *reg_count,
|
||||
void (*assign)(void*, int, int*),
|
||||
int (*convert)(char*, int) )
|
||||
{
|
||||
char *tmp_str1, *tmp_str2, *tok1, *tok2;
|
||||
int item_count1=0;
|
||||
int item_count2;
|
||||
int* tmp_item = malloc((sizeof(int))*max_args);
|
||||
if (tmp_item == NULL){
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tmp_str1 = strdup(env);
|
||||
tok1=strsep(&tmp_str1, "/");
|
||||
while (tok1 != NULL){
|
||||
item_count2=0;
|
||||
tmp_str2 = strdup(tok1);
|
||||
tok2=strsep(&tmp_str2, ":");
|
||||
while (tok2 != NULL){
|
||||
item_count2++;
|
||||
if (item_count2 > max_args)
|
||||
break;
|
||||
tmp_item[item_count2-1] = convert(tok2,item_count2);
|
||||
tok2=strsep(&tmp_str2, ":");
|
||||
}
|
||||
if (item_count2 == max_args){
|
||||
assign(regs, item_count1, tmp_item);
|
||||
item_count1++;
|
||||
}
|
||||
tok1 = strsep(&tmp_str1, "/");
|
||||
}
|
||||
*reg_count = item_count1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void apply_config(struct reg_conf *regs, int reg_count)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<reg_count; i++){
|
||||
//Check if given registers belong to GPIO range
|
||||
if ((regs[i].addr>=0x18040000) && (regs[i].addr<=0x18040044)){
|
||||
ar7240_reg_wr(regs[i].addr, ((ar7240_reg_rd(regs[i].addr)|regs[i].set_mask)&(~regs[i].clear_mask)));
|
||||
}
|
||||
else{
|
||||
printf("Reg: %x is not in valid GPIO range\n");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void gpio_env_init(int mode)
|
||||
{
|
||||
int max_args;
|
||||
void (*assign)(struct reg_conf*, int, int*);
|
||||
int (*convert)(char* ,int);
|
||||
char* gpio_env;
|
||||
int ret;
|
||||
struct reg_conf *regs;
|
||||
int reg_count;
|
||||
int i;
|
||||
|
||||
if (mode==0){
|
||||
assign = &assign_gpio;
|
||||
convert = &convert_hex;
|
||||
max_args = 3;
|
||||
gpio_env = getenv("gpio_config");
|
||||
}
|
||||
else{
|
||||
convert = &convert_dec;
|
||||
max_args = 4;
|
||||
if (mode==1){
|
||||
assign = &assign_leds;
|
||||
gpio_env = getenv("led_config");
|
||||
}
|
||||
else if(mode == 2){
|
||||
assign = &assign_buttons;
|
||||
gpio_env = getenv("button_config");
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_env == NULL){
|
||||
if (mode==0){
|
||||
//Default init
|
||||
//set output enable
|
||||
ar7240_reg_wr (AR7240_GPIO_OE, (ar7240_reg_rd(AR7240_GPIO_OE) | (1<<13)|(1<<14)|(1<<0) ));
|
||||
//set ETH0 ETH1 LED output to high
|
||||
ar7240_reg_wr (AR7240_GPIO_SET, (1<<13)|(1<<14));
|
||||
//set WLAN LED output to low (reverse polarity LED)
|
||||
ar7240_reg_wr (AR7240_GPIO_CLEAR, (1<<0));
|
||||
//Enable USB boot sense GPIO as input
|
||||
ar7240_reg_wr (AR7240_GPIO_OE, (ar7240_reg_rd(AR7240_GPIO_OE) & ~(1<<11)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
reg_count = count_args(gpio_env);
|
||||
|
||||
if (mode==0){
|
||||
regs = malloc(sizeof(struct reg_conf)*reg_count);
|
||||
if (regs == NULL)
|
||||
return;
|
||||
}
|
||||
else
|
||||
regs = NULL;
|
||||
|
||||
ret = parse_config(gpio_env, max_args, (void*)regs, ®_count, assign, convert);
|
||||
if (ret<0)
|
||||
return;
|
||||
|
||||
if (mode==0)
|
||||
apply_config(regs, reg_count);
|
||||
|
||||
free(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void ar7240_gpio_config(void)
|
||||
{
|
||||
/* Disable clock obs
|
||||
* clk_obs1(gpio13/bit8), clk_obs2(gpio14/bit9), clk_obs3(gpio15/bit10),
|
||||
* clk_obs4(gpio16/bit11), clk_obs5(gpio17/bit12)
|
||||
* clk_obs0(gpio1/bit19), 6(gpio11/bit20)
|
||||
*/
|
||||
ar7240_reg_wr (AR7240_GPIO_FUNC,
|
||||
(ar7240_reg_rd(AR7240_GPIO_FUNC) & ~((0x1f<<8)|(0x3<<19))));
|
||||
|
||||
/* Enable eth Switch LEDs */
|
||||
//ar7240_reg_wr (AR7240_GPIO_FUNC, (ar7240_reg_rd(AR7240_GPIO_FUNC) | (0x1f<<3)));
|
||||
|
||||
/* Clear AR7240_GPIO_FUNC BIT2 to ensure that software can control LED5(GPIO16) and LED6(GPIO17) */
|
||||
ar7240_reg_wr (AR7240_GPIO_FUNC, (ar7240_reg_rd(AR7240_GPIO_FUNC) & ~(0x1<<2)));
|
||||
|
||||
/* Set HORNET_BOOTSTRAP_STATUS BIT18 to ensure that software can control GPIO26 and GPIO27 */
|
||||
//ar7240_reg_wr (HORNET_BOOTSTRAP_STATUS, (ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS) | (0x1<<18)));
|
||||
}
|
||||
|
||||
int button_read(int button_id){
|
||||
if (buttons[button_id].disable != 1){
|
||||
if (((ar7240_reg_rd(AR7240_GPIO_IN)>>buttons[button_id].bit)&0x01) == buttons[button_id].polarity)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
void ar7240_gpio_led_switch(int led_id, int state)
|
||||
//switch LED (led_id is defined in struct[] leds) to state (0 - off, 1 -on)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<led_count;i++){
|
||||
if (leds[i].disable != 1){
|
||||
if (leds[i].id==led_id) {
|
||||
if ((!leds[i].polarity) ^ state){
|
||||
ar7240_reg_wr (AR7240_GPIO_SET, (1<<leds[i].bit));
|
||||
}
|
||||
else{
|
||||
ar7240_reg_wr (AR7240_GPIO_CLEAR, (1<<leds[i].bit));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ar7240_gpio_leds_off(void)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<led_count;i++){
|
||||
if (leds[i].disable != 1){
|
||||
ar7240_gpio_led_switch(i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void show_activity(int arg)
|
||||
{
|
||||
uint32_t time = 0;
|
||||
static uint32_t led = 0;
|
||||
time =get_timer(0);
|
||||
|
||||
if ( (ar7240_boot_status<0) )
|
||||
{
|
||||
//Blink 3 first LEDs in descriptor together
|
||||
led += 1;
|
||||
if (led > 2) led = 0;
|
||||
ar7240_gpio_led_switch(led ,(time>>24)&0x01);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
void show_boot_progress(int arg)
|
||||
{
|
||||
ar7240_boot_status = arg;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
ar7240_mem_config(void)
|
||||
{
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
unsigned int tap_val1, tap_val2;
|
||||
#endif
|
||||
|
||||
ar7240_gpio_config(); // init GPIO
|
||||
|
||||
ar7240_ddr_initial_config(CFG_DDR_REFRESH_VAL);
|
||||
|
||||
/* Default tap values for starting the tap_init*/
|
||||
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL0, CFG_DDR_TAP0_VAL);
|
||||
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL1, CFG_DDR_TAP1_VAL);
|
||||
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
ar7240_ddr_tap_init();
|
||||
|
||||
tap_val1 = ar7240_reg_rd(0xb800001c);
|
||||
tap_val2 = ar7240_reg_rd(0xb8000020);
|
||||
debug("#### TAP VALUE 1 = %x, 2 = %x\n",tap_val1, tap_val2);
|
||||
#endif
|
||||
|
||||
ar7240_usb_initial_config();
|
||||
ar7240_usb_otp_config();
|
||||
|
||||
//hornet_ddr_tap_init();
|
||||
|
||||
gpio_env_init(0); // custom GPIO init, turns on all LEDs
|
||||
gpio_env_init(1); //LEDs
|
||||
gpio_env_init(2); //BUTTONs
|
||||
|
||||
udelay(100 * 1000); // 100ms delay
|
||||
ar7240_gpio_leds_off();
|
||||
|
||||
return (ar7240_ddr_find_size());
|
||||
}
|
||||
|
||||
long int initdram(int board_type)
|
||||
{
|
||||
return (ar7240_mem_config());
|
||||
}
|
||||
|
||||
#ifdef COMPRESSED_UBOOT
|
||||
int checkboard (char *board_string)
|
||||
{
|
||||
strcpy(board_string, "Caraboot v2.0 (AR9331) U-boot");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int checkboard (void)
|
||||
{
|
||||
printf("=====================================\n");
|
||||
printf("Caraboot v2.0 (AR9331) U-boot\n");
|
||||
printf("http://www.8devices.com/\n");
|
||||
printf("-------------------------------------\n");
|
||||
return 0;
|
||||
}
|
||||
#endif /* #ifdef COMPRESSED_UBOOT */
|
|
@ -0,0 +1,57 @@
|
|||
#include <common.h>
|
||||
#include <config.h>
|
||||
|
||||
#define XMK_STR(x) #x
|
||||
#define MK_STR(x) XMK_STR(x)
|
||||
|
||||
static void carambola_factory_load_image(void)
|
||||
{
|
||||
char *filename = CFG_C2_IMG_FILENAME;
|
||||
int tftp_ret;
|
||||
|
||||
int argc_tftp = 3;
|
||||
char* argv_tftp[] = {"tftpboot", CFG_C2_IMG_LOAD_ADDR, filename};
|
||||
|
||||
int argc_bootm = 2;
|
||||
char* argv_bootm[] = {"bootm", CFG_C2_IMG_LOAD_ADDR};
|
||||
|
||||
if (!getenv ("ipaddr"))
|
||||
setenv("ipaddr", MK_STR(CONFIG_IPADDR));
|
||||
|
||||
if (!getenv ("serverip"))
|
||||
setenv("serverip", MK_STR(CONFIG_SERVERIP));
|
||||
|
||||
//Workaround for slow TFTP:
|
||||
//wake-up network stack with ping to server
|
||||
char *serverip = getenv ("serverip");
|
||||
char ping_command[32]="ping ";
|
||||
strncpy(ping_command+5, serverip, 16);
|
||||
run_command(ping_command, NULL);
|
||||
//end of workaround
|
||||
|
||||
setenv("netretry", "once"); // Try once, reboot after
|
||||
tftp_ret=do_tftpb (NULL, 0, argc_tftp, argv_tftp);
|
||||
if (0 == tftp_ret) {
|
||||
printf("Booting TFTP image...\n");
|
||||
do_bootm(NULL, 0, argc_bootm, argv_bootm);
|
||||
do_reset(NULL, 0, 0, NULL);
|
||||
}
|
||||
else{
|
||||
printf("Error getting TFTP image. Rebooting...\n");
|
||||
do_reset(NULL, 0, 0, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void carambola_factory_mode(void)
|
||||
{
|
||||
char* production_env = getenv("production");
|
||||
|
||||
if (production_env){
|
||||
if (strncmp(production_env, "yes", 3) == 0){
|
||||
carambola_factory_load_image();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
# ROM version
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
TEXT_BASE = 0x80010000
|
||||
BOOTSTRAP_TEXT_BASE = 0x9f000000
|
||||
else
|
||||
TEXT_BASE = 0x9f000000
|
||||
endif
|
||||
|
||||
# SDRAM version
|
||||
#TEXT_BASE = 0x80000000
|
|
@ -0,0 +1,28 @@
|
|||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <asm/types.h>
|
||||
#include <flash.h>
|
||||
|
||||
/*
|
||||
* sets up flash_info and returns size of FLASH (bytes)
|
||||
*/
|
||||
unsigned long
|
||||
flash_get_geom (flash_info_t *flash_info)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* XXX this is hardcoded until we figure out how to read flash id */
|
||||
|
||||
flash_info->flash_id = FLASH_M25P64;
|
||||
flash_info->size = CFG_FLASH_SIZE; /* bytes */
|
||||
flash_info->sector_count = flash_info->size/CFG_FLASH_SECTOR_SIZE;
|
||||
|
||||
for (i = 0; i < flash_info->sector_count; i++) {
|
||||
flash_info->start[i] = CFG_FLASH_BASE + (i * CFG_FLASH_SECTOR_SIZE);
|
||||
flash_info->protect[i] = 0;
|
||||
}
|
||||
|
||||
debug ("flash size %d, sector count = %d\n", flash_info->size, flash_info->sector_count);
|
||||
return (flash_info->size);
|
||||
|
||||
}
|
|
@ -0,0 +1,375 @@
|
|||
#include <config.h>
|
||||
#include <version.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <ar7240_soc.h>
|
||||
|
||||
.globl hornet_pll_init
|
||||
.text
|
||||
.align 4
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
* These Clobber t7, t8 and t9
|
||||
*/
|
||||
/* or t8, t8, t9; \ */
|
||||
#define set_reg(_reg, _val) \
|
||||
li t7, KSEG1ADDR(_reg); \
|
||||
lw t8, 0(t7); \
|
||||
li t9, _val; \
|
||||
sw t9, 0(t7);
|
||||
|
||||
hornet_pll_init:
|
||||
|
||||
#if 1
|
||||
/* These three wlan reset will avoid original issue,
|
||||
so full chip reset isn't needed here. */
|
||||
set_reg(0xb806001c, 0x00c06b30)
|
||||
nop
|
||||
set_reg(0xb806001c, 0x00c06330)
|
||||
nop
|
||||
set_reg(0xb806001c, 0x00c06b30)
|
||||
nop
|
||||
set_reg(0xb806001c, 0x00c06330)
|
||||
nop
|
||||
reset_wlan:
|
||||
set_reg(0xb806001c, 0x00c06b30)
|
||||
nop
|
||||
set_reg(0xb806001c, 0x00c06330)
|
||||
nop
|
||||
|
||||
li t5, 0x20
|
||||
check_val:
|
||||
beq zero, t5, reset_wlan
|
||||
addi t5, t5, -1
|
||||
li t6, 0xb80600ac
|
||||
lw t7, 0(t6)
|
||||
li t8, 0x10
|
||||
and t7, t7, t8
|
||||
bne zero, t7, check_val
|
||||
|
||||
set_reg(HORNET_BOOTSTRAP_STATUS, 0x0002110e)
|
||||
nop
|
||||
#else
|
||||
/* clear wlan reset bit in RESET_Register 0x1c */
|
||||
set_reg(AR7240_RESET, 0x00c06b30)
|
||||
nop
|
||||
set_reg(AR7240_RESET, 0x00c06330)
|
||||
nop
|
||||
|
||||
/* cleck bootstrap status, wait for bit4 on, then clear bit16 */
|
||||
wait_loop0:
|
||||
li t6, KSEG1ADDR(HORNET_BOOTSTRAP_STATUS)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0x10
|
||||
and t7, t7, t8
|
||||
bne zero, t7, wait_loop0
|
||||
nop
|
||||
set_reg(HORNET_BOOTSTRAP_STATUS, 0x0002110e)
|
||||
nop
|
||||
#endif
|
||||
|
||||
/* RTC reset */
|
||||
set_reg(0x1810704c, 0x00000003)
|
||||
nop
|
||||
nop
|
||||
set_reg(0x18107040, 0x00000000)
|
||||
nop
|
||||
nop
|
||||
set_reg(0x18107040, 0x00000001)
|
||||
nop
|
||||
wait_loop1:
|
||||
li t6, KSEG1ADDR(0x18107044)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0x2
|
||||
and t7, t7, t8
|
||||
bne t8, t7, wait_loop1
|
||||
nop
|
||||
|
||||
/* AHB/APH reset */
|
||||
set_reg(0x18104000, 0x00000003)
|
||||
nop
|
||||
set_reg(0x18104000, 0x00000000)
|
||||
nop
|
||||
|
||||
/* MAC reset */
|
||||
set_reg(0x18107000, 0x0000000F)
|
||||
nop
|
||||
set_reg(0x18107000, 0x00000000)
|
||||
nop
|
||||
|
||||
#if 1 /* fetch pmu1.refv and ctrl2.tx from OTP */
|
||||
li t1, KSEG1ADDR(0x18114014)
|
||||
lw t2, 0(t1)
|
||||
otp_loop0:
|
||||
li t3, KSEG1ADDR(0x18115f18)
|
||||
lw t4, 0(t3)
|
||||
nop
|
||||
li t5, 0x7
|
||||
and t4, t4, t5
|
||||
li t5, 0x4
|
||||
bne t4, t5, otp_loop0
|
||||
nop
|
||||
|
||||
li t6, KSEG1ADDR(0x18115f1c)
|
||||
lw t7, 0(t6)
|
||||
nop
|
||||
li t8, 0x80000080
|
||||
and t9, t7, t8
|
||||
beq t8, t9, fetch_otp
|
||||
otp_loop0_end:
|
||||
|
||||
li t1, KSEG1ADDR(0x18114004)
|
||||
lw t2, 0(t1)
|
||||
otp_loop1:
|
||||
li t3, KSEG1ADDR(0x18115f18)
|
||||
lw t4, 0(t3)
|
||||
nop
|
||||
li t5, 0x7
|
||||
and t4, t4, t5
|
||||
li t5, 0x4
|
||||
bne t4, t5, otp_loop1
|
||||
nop
|
||||
|
||||
li t6, KSEG1ADDR(0x18115f1c)
|
||||
lw t7, 0(t6)
|
||||
nop
|
||||
li t8, 0x80000080
|
||||
and t9, t7, t8
|
||||
default_pmu:
|
||||
li t5, 0x80 /* default 0x031c4386 */
|
||||
bne t8, t9, otp_end
|
||||
otp_loop1_end:
|
||||
|
||||
fetch_otp:
|
||||
srl t8, t7, 0x18
|
||||
li t1, 0xf
|
||||
and t2, t1 , t7 /* USB */
|
||||
and t5, t1 , t8 /* PMU */
|
||||
|
||||
check_pmu:
|
||||
li t0, 0x4 /* PMU range should be 0x4~0xa */
|
||||
bgt t0, t5, default_pmu
|
||||
nop
|
||||
li t0, 0xa /* PMU range should be 0x4~0xa */
|
||||
blt t0, t5, default_pmu
|
||||
nop
|
||||
li t0, 0x4
|
||||
sll t5, t5, t0
|
||||
|
||||
otp_end:
|
||||
#endif
|
||||
|
||||
#if 1 /* Program PMU */
|
||||
#define PMU_TEST_NO 1000
|
||||
li t6, KSEG1ADDR(0x18116c40)
|
||||
li t9, 0xbd000010
|
||||
li t0, 0
|
||||
li t1, 0
|
||||
li t2, 0
|
||||
|
||||
li t3, PMU_TEST_NO
|
||||
sw t3, 12(t9)
|
||||
pmu_loop0:
|
||||
beq zero, t3, pmu_loop0_end
|
||||
nop
|
||||
addi t3, t3, -1
|
||||
|
||||
#li t7, 0x10000000 /* ldo_tune 0x0 */
|
||||
#li t7, 0x10080000 /* ldo_tune 0x1 */
|
||||
#li t7, 0x10100000 /* ldo_tune 0x2 */
|
||||
li t7, 0x10180000 /* ldo_tune 0x3 */
|
||||
nop
|
||||
sw t7, 4(t6)
|
||||
nop
|
||||
lw t8, 4(t6)
|
||||
nop
|
||||
beq t8, t7, pmu_loop0_end
|
||||
nop
|
||||
|
||||
addiu t0, t0, 1
|
||||
b pmu_loop0
|
||||
nop
|
||||
pmu_loop0_end:
|
||||
|
||||
li t3, PMU_TEST_NO
|
||||
pmu_loop1:
|
||||
beq zero, t3, pmu_loop1_end
|
||||
nop
|
||||
addi t3, t3, -1
|
||||
|
||||
//li t7, 0x031c4326 /* 1.100V */
|
||||
//li t7, 0x031c4336 /* 1.125V */
|
||||
//li t7, 0x031c4346 /* 1.150V */
|
||||
//li t7, 0x031c4356 /* 1.175V */
|
||||
//li t7, 0x031c4366 /* 1.200V */
|
||||
//li t7, 0x031c4376 /* 1.225V */
|
||||
li t7, 0x031c4386 /* 1.250V */
|
||||
//li t7, 0x031c4396 /* 1.275V */
|
||||
//li t7, 0x031c43a6 /* 1.300V */
|
||||
nop
|
||||
#if 1 /* from OTP */
|
||||
li t8, 0xffffff0f
|
||||
and t7, t7, t8
|
||||
or t7, t7, t5
|
||||
#endif
|
||||
sw t7, 0(t6)
|
||||
nop
|
||||
lw t8, 0(t6)
|
||||
nop
|
||||
beq t8, t7, pmu_loop1_end
|
||||
nop
|
||||
|
||||
addiu t1, t1, 1
|
||||
b pmu_loop1
|
||||
nop
|
||||
pmu_loop1_end:
|
||||
|
||||
li t3, PMU_TEST_NO
|
||||
pmu_loop2:
|
||||
beq zero, t3, pmu_loop2_end
|
||||
nop
|
||||
addi t3, t3, -1
|
||||
|
||||
#li t7, 0x10200000 /* ldo_tune 0x0 */
|
||||
#li t7, 0x10280000 /* ldo_tune 0x1 */
|
||||
#li t7, 0x10300000 /* ldo_tune 0x2 */
|
||||
li t7, 0x10380000 /* ldo_tune 0x3 */
|
||||
nop
|
||||
sw t7, 4(t6)
|
||||
nop
|
||||
lw t8, 4(t6)
|
||||
nop
|
||||
beq t8, t7, pmu_loop2_end
|
||||
nop
|
||||
|
||||
addiu t2, t2, 1
|
||||
b pmu_loop2
|
||||
nop
|
||||
pmu_loop2_end:
|
||||
|
||||
sw t0, 0(t9)
|
||||
nop
|
||||
sw t1, 4(t9)
|
||||
nop
|
||||
sw t2, 8(t9)
|
||||
nop
|
||||
#endif
|
||||
|
||||
#if 1 /* Program ki, kd */
|
||||
/* Program ki/kd */
|
||||
#if CONFIG_40MHZ_XTAL_SUPPORT
|
||||
set_reg(0x18116244, 0x19e82f01)
|
||||
#else
|
||||
set_reg(0x18116244, 0x18e82f01)
|
||||
#endif
|
||||
nop
|
||||
|
||||
/* Program phase shift */
|
||||
li t6, KSEG1ADDR(0x18116248)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0xc07fffff
|
||||
and t7, t7, t8
|
||||
li t8, 0x800000
|
||||
or t7, t7, t8
|
||||
sw t7, 0(t6)
|
||||
nop
|
||||
#endif
|
||||
|
||||
/* set PLL bypass(Bit 2), CPU_POST_DIV, DDR_POST_DIV, AHB_POST_DIV in CPU clock control */
|
||||
set_reg(AR7240_CPU_CLOCK_CONTROL, 0x00018004)
|
||||
nop
|
||||
|
||||
/* set SETTLE_TIME in CPU PLL */
|
||||
set_reg(AR7240_USB_PLL_CONFIG, CPU_PLL_SETTLE_TIME_VAL)
|
||||
nop
|
||||
|
||||
pll_unlock_handler:
|
||||
|
||||
/* set nint, frac, refdiv, outdiv, range in CPU PLL configuration resiter */
|
||||
set_reg(AR7240_CPU_PLL_CONFIG, CPU_PLL_CONFIG_VAL1)
|
||||
nop
|
||||
|
||||
wait_loop2:
|
||||
li t6, KSEG1ADDR(AR7240_CPU_PLL_CONFIG)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0x80000000
|
||||
and t7, t7, t8
|
||||
bne zero, t7, wait_loop2
|
||||
nop
|
||||
|
||||
/* put frac bit19:10 configuration */
|
||||
set_reg(AR7240_PCIE_PLL_CONFIG, CPU_PLL_DITHER_FRAC_VAL)
|
||||
nop
|
||||
|
||||
/* clear PLL power down bit in CPU PLLl configuration */
|
||||
set_reg(AR7240_CPU_PLL_CONFIG, CPU_PLL_CONFIG_VAL2)
|
||||
nop
|
||||
wait_loop3:
|
||||
li t6, KSEG1ADDR(AR7240_CPU_PLL_CONFIG)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0x80000000
|
||||
and t7, t7, t8
|
||||
bne zero, t7, wait_loop3
|
||||
nop
|
||||
|
||||
/* confirm DDR PLL lock */
|
||||
li t3, 100
|
||||
li t4, 0
|
||||
start_meas0:
|
||||
addi t4, t4, 1
|
||||
bgt t4, t3, pll_unlock_handler
|
||||
nop
|
||||
li t5, 5
|
||||
start_meas:
|
||||
li t6, KSEG1ADDR(0x18116248)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0xbfffffff
|
||||
and t7, t7, t8
|
||||
sw t7, 0(t6)
|
||||
nop
|
||||
|
||||
/* delay */
|
||||
li t9, 10
|
||||
delayloop0:
|
||||
subu t9, t9, 1
|
||||
bne t9, zero, delayloop0
|
||||
nop
|
||||
|
||||
li t8, 0x40000000
|
||||
or t7, t7, t8
|
||||
sw t7, 0(t6)
|
||||
nop
|
||||
|
||||
meas_done_statue:
|
||||
li t6, KSEG1ADDR(0x1811624c)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0x8
|
||||
and t7, t7, t8
|
||||
beq zero, t7, meas_done_statue
|
||||
nop
|
||||
|
||||
meas_result:
|
||||
li t6, KSEG1ADDR(0x18116248)
|
||||
lw t7, 0(t6)
|
||||
li t8, 0x007ffff8
|
||||
and t7, t7, t8
|
||||
srl t7, t7, 3
|
||||
li t8, 0x4000
|
||||
bgt t7, t8, start_meas0
|
||||
nop
|
||||
addi t5, t5, -1
|
||||
bne zero, t5, start_meas
|
||||
nop
|
||||
|
||||
/* clear PLL bypass(Bit 2), CPU_POST_DIV, DDR_POST_DIV, AHB_POST_DIV in CPU clock control */
|
||||
set_reg(AR7240_CPU_CLOCK_CONTROL, CPU_CLK_CONTROL_VAL2)
|
||||
nop
|
||||
|
||||
/* Sync mode , Set Bit 8 of DDR Tap Conrtol 3 register */
|
||||
set_reg(AR7240_DDR_TAP_CONTROL3, 0x10105);
|
||||
nop
|
||||
|
||||
jr ra
|
||||
nop
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Wolfgang Denk 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
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
|
||||
OUTPUT_ARCH(mips)
|
||||
ENTRY(_start_bootstrap)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.sdata : { *(.sdata) }
|
||||
|
||||
_gp = ALIGN(16);
|
||||
|
||||
. = ALIGN(16);
|
||||
__got_start_bootstrap = .;
|
||||
.got : { *(.got) }
|
||||
__got_end_bootstrap = .;
|
||||
|
||||
.sdata : { *(.sdata) }
|
||||
|
||||
uboot_end_data_bootstrap = .;
|
||||
num_got_entries = (__got_end_bootstrap - __got_start_bootstrap) >> 2;
|
||||
|
||||
. = ALIGN(4);
|
||||
.sbss : { *(.sbss) }
|
||||
.bss : { *(.bss) }
|
||||
uboot_end_bootstrap = .;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
|
||||
OUTPUT_ARCH(mips)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.sdata : { *(.sdata) }
|
||||
|
||||
_gp = ALIGN(16);
|
||||
|
||||
__got_start = .;
|
||||
.got : { *(.got) }
|
||||
__got_end = .;
|
||||
|
||||
.sdata : { *(.sdata) }
|
||||
|
||||
__u_boot_cmd_start = .;
|
||||
.u_boot_cmd : { *(.u_boot_cmd) }
|
||||
__u_boot_cmd_end = .;
|
||||
|
||||
uboot_end_data = .;
|
||||
num_got_entries = (__got_end - __got_start) >> 2;
|
||||
|
||||
. = ALIGN(4);
|
||||
.sbss : { *(.sbss) }
|
||||
.bss : { *(.bss) }
|
||||
uboot_end = .;
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
#include <common.h>
|
||||
#include <jffs2/jffs2.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/types.h>
|
||||
#include "ar7240_soc.h"
|
||||
#include "ar7240_flash.h"
|
||||
|
||||
/*
|
||||
* globals
|
||||
*/
|
||||
flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
|
||||
|
||||
#undef display
|
||||
#define display(x) ;
|
||||
|
||||
/*
|
||||
* statics
|
||||
*/
|
||||
static void ar7240_spi_write_enable(void);
|
||||
static void ar7240_spi_poll(void);
|
||||
#if !defined(ATH_SST_FLASH)
|
||||
static void ar7240_spi_write_page(uint32_t addr, uint8_t * data, int len);
|
||||
#endif
|
||||
static void ar7240_spi_sector_erase(uint32_t addr);
|
||||
|
||||
static void
|
||||
ath_spi_read_id(void)
|
||||
{
|
||||
u32 rd = 0x777777;
|
||||
|
||||
ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_RDID);
|
||||
ar7240_spi_delay_8();
|
||||
ar7240_spi_delay_8();
|
||||
ar7240_spi_delay_8();
|
||||
ar7240_spi_go();
|
||||
|
||||
rd = ar7240_reg_rd(AR7240_SPI_RD_STATUS);
|
||||
|
||||
debug("Flash Manuf Id 0x%x, DeviceId0 0x%x, DeviceId1 0x%x\n",
|
||||
(rd >> 16) & 0xff, (rd >> 8) & 0xff, (rd >> 0) & 0xff);
|
||||
}
|
||||
|
||||
|
||||
#ifdef ATH_SST_FLASH
|
||||
void ar7240_spi_flash_unblock(void)
|
||||
{
|
||||
ar7240_spi_write_enable();
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_WRITE_SR);
|
||||
ar7240_spi_bit_banger(0x0);
|
||||
ar7240_spi_go();
|
||||
ar7240_spi_poll();
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long flash_init(void)
|
||||
{
|
||||
#ifndef CONFIG_WASP
|
||||
#ifdef ATH_SST_FLASH
|
||||
ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x3);
|
||||
ar7240_spi_flash_unblock();
|
||||
ar7240_reg_wr(AR7240_SPI_FS, 0);
|
||||
#else
|
||||
ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x43);
|
||||
#endif
|
||||
#endif
|
||||
ar7240_reg_rmw_set(AR7240_SPI_FS, 1);
|
||||
ath_spi_read_id();
|
||||
ar7240_reg_rmw_clear(AR7240_SPI_FS, 1);
|
||||
|
||||
/*
|
||||
* hook into board specific code to fill flash_info
|
||||
*/
|
||||
return (flash_get_geom(&flash_info[0]));
|
||||
}
|
||||
|
||||
void
|
||||
flash_print_info(flash_info_t *info)
|
||||
{
|
||||
printf("The hell do you want flinfo for??\n");
|
||||
}
|
||||
|
||||
int
|
||||
flash_erase(flash_info_t *info, int s_first, int s_last)
|
||||
{
|
||||
int i, sector_size = info->size / info->sector_count;
|
||||
|
||||
#ifdef FLASH_DEBUG
|
||||
printf("\nFirst %#x last %#x sector size %#x\n",
|
||||
s_first, s_last, sector_size);
|
||||
#endif
|
||||
|
||||
for (i = s_first; i <= s_last; i++) {
|
||||
#ifdef FLASH_DEBUG
|
||||
printf("\b\b\b\b%4d", i);
|
||||
#else
|
||||
puts(".");
|
||||
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
extern void show_activity(int arg);
|
||||
show_activity(3);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
ar7240_spi_sector_erase(i * sector_size);
|
||||
}
|
||||
ar7240_spi_done();
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a buffer from memory to flash:
|
||||
* 0. Assumption: Caller has already erased the appropriate sectors.
|
||||
* 1. call page programming for every 256 bytes
|
||||
*/
|
||||
#ifdef ATH_SST_FLASH
|
||||
void
|
||||
ar7240_spi_flash_chip_erase(void)
|
||||
{
|
||||
ar7240_spi_write_enable();
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_CHIP_ERASE);
|
||||
ar7240_spi_go();
|
||||
ar7240_spi_poll();
|
||||
}
|
||||
|
||||
int
|
||||
write_buff(flash_info_t *info, uchar *src, ulong dst, ulong len)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
dst = dst - CFG_FLASH_BASE;
|
||||
printf("write len: %lu dst: 0x%x src: %p\n", len, dst, src);
|
||||
|
||||
for (; len; len--, dst++, src++) {
|
||||
ar7240_spi_write_enable(); // dont move this above 'for'
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_PAGE_PROG);
|
||||
ar7240_spi_send_addr(dst);
|
||||
|
||||
val = *src & 0xff;
|
||||
ar7240_spi_bit_banger(val);
|
||||
|
||||
ar7240_spi_go();
|
||||
ar7240_spi_poll();
|
||||
}
|
||||
/*
|
||||
* Disable the Function Select
|
||||
* Without this we can't read from the chip again
|
||||
*/
|
||||
ar7240_reg_wr(AR7240_SPI_FS, 0);
|
||||
|
||||
if (len) {
|
||||
// how to differentiate errors ??
|
||||
return ERR_PROG_ERROR;
|
||||
} else {
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int
|
||||
write_buff(flash_info_t *info, uchar *source, ulong addr, ulong len)
|
||||
{
|
||||
int total = 0, len_this_lp, bytes_this_page, counter = 0;
|
||||
ulong dst;
|
||||
uchar *src;
|
||||
|
||||
#ifdef FLASH_DEBUG
|
||||
printf("write addr: %x\n", addr);
|
||||
#endif
|
||||
addr = addr - CFG_FLASH_BASE;
|
||||
|
||||
while (total < len) {
|
||||
src = source + total;
|
||||
dst = addr + total;
|
||||
bytes_this_page =
|
||||
AR7240_SPI_PAGE_SIZE - (addr & AR7240_SPI_PAGE_SIZE-1);
|
||||
len_this_lp =
|
||||
((len - total) >
|
||||
bytes_this_page) ? bytes_this_page : (len - total);
|
||||
ar7240_spi_write_page(dst, src, len_this_lp);
|
||||
total += len_this_lp;
|
||||
if(counter>=255)
|
||||
{
|
||||
puts(".");
|
||||
counter = 0;
|
||||
#ifdef CONFIG_SHOW_ACTIVITY
|
||||
extern void show_activity(int arg);
|
||||
show_activity(3);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
ar7240_spi_done();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ar7240_spi_write_enable()
|
||||
{
|
||||
ar7240_reg_wr_nf(AR7240_SPI_FS, 1);
|
||||
ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_WREN);
|
||||
ar7240_spi_go();
|
||||
}
|
||||
|
||||
static void
|
||||
ar7240_spi_poll()
|
||||
{
|
||||
int rd;
|
||||
|
||||
do {
|
||||
ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_RD_STATUS);
|
||||
ar7240_spi_delay_8();
|
||||
rd = (ar7240_reg_rd(AR7240_SPI_RD_STATUS) & 1);
|
||||
} while (rd);
|
||||
}
|
||||
|
||||
#if !defined(ATH_SST_FLASH)
|
||||
static void
|
||||
ar7240_spi_write_page(uint32_t addr, uint8_t *data, int len)
|
||||
{
|
||||
int i;
|
||||
uint8_t ch;
|
||||
|
||||
display(0x77);
|
||||
ar7240_spi_write_enable();
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_PAGE_PROG);
|
||||
ar7240_spi_send_addr(addr);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
ch = *(data + i);
|
||||
ar7240_spi_bit_banger(ch);
|
||||
}
|
||||
|
||||
ar7240_spi_go();
|
||||
display(0x66);
|
||||
ar7240_spi_poll();
|
||||
display(0x6d);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ar7240_spi_sector_erase(uint32_t addr)
|
||||
{
|
||||
ar7240_spi_write_enable();
|
||||
ar7240_spi_bit_banger(AR7240_SPI_CMD_SECTOR_ERASE);
|
||||
ar7240_spi_send_addr(addr);
|
||||
ar7240_spi_go();
|
||||
display(0x7d);
|
||||
ar7240_spi_poll();
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef _FLASH_H
|
||||
#define _FLASH_H
|
||||
|
||||
#include "ar7240_soc.h"
|
||||
|
||||
#define AR7240_SPI_FS 0x1f000000
|
||||
#define AR7240_SPI_CLOCK 0x1f000004
|
||||
#define AR7240_SPI_WRITE 0x1f000008
|
||||
#define AR7240_SPI_READ 0x1f000000
|
||||
#define AR7240_SPI_RD_STATUS 0x1f00000c
|
||||
|
||||
#define AR7240_SPI_CS_DIS 0x70000
|
||||
#define AR7240_SPI_CE_LOW 0x60000
|
||||
#define AR7240_SPI_CE_HIGH 0x60100
|
||||
|
||||
#define AR7240_SPI_CMD_WRITE_SR 0x01
|
||||
#define AR7240_SPI_CMD_WREN 0x06
|
||||
#define AR7240_SPI_CMD_RD_STATUS 0x05
|
||||
#define AR7240_SPI_CMD_FAST_READ 0x0b
|
||||
#define AR7240_SPI_CMD_PAGE_PROG 0x02
|
||||
#define AR7240_SPI_CMD_SECTOR_ERASE 0xd8
|
||||
#define AR7240_SPI_CMD_CHIP_ERASE 0xc7
|
||||
#define AR7240_SPI_CMD_RDID 0x9f
|
||||
|
||||
#define AR7240_SPI_SECTOR_SIZE (1024*64)
|
||||
#define AR7240_SPI_PAGE_SIZE 256
|
||||
|
||||
|
||||
#define display(_x) ar7240_reg_wr_nf(0x18040008, (_x))
|
||||
|
||||
/*
|
||||
* primitives
|
||||
*/
|
||||
|
||||
#define ar7240_be_msb(_val, _i) (((_val) & (1 << (7 - _i))) >> (7 - _i))
|
||||
|
||||
#define ar7240_spi_bit_banger(_byte) do { \
|
||||
int i; \
|
||||
for(i = 0; i < 8; i++) { \
|
||||
ar7240_reg_wr_nf(AR7240_SPI_WRITE, \
|
||||
AR7240_SPI_CE_LOW | ar7240_be_msb(_byte, i)); \
|
||||
ar7240_reg_wr_nf(AR7240_SPI_WRITE, \
|
||||
AR7240_SPI_CE_HIGH | ar7240_be_msb(_byte, i)); \
|
||||
} \
|
||||
}while(0);
|
||||
|
||||
#define ar7240_spi_go() do { \
|
||||
ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CE_LOW); \
|
||||
ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS); \
|
||||
}while(0);
|
||||
|
||||
|
||||
#define ar7240_spi_send_addr(__a) do { \
|
||||
ar7240_spi_bit_banger(((__a & 0xff0000) >> 16)); \
|
||||
ar7240_spi_bit_banger(((__a & 0x00ff00) >> 8)); \
|
||||
ar7240_spi_bit_banger(__a & 0x0000ff); \
|
||||
} while (0)
|
||||
|
||||
#define ar7240_spi_delay_8() ar7240_spi_bit_banger(0)
|
||||
#define ar7240_spi_done() ar7240_reg_wr_nf(AR7240_SPI_FS, 0)
|
||||
|
||||
extern unsigned long flash_get_geom (flash_info_t *flash_info);
|
||||
|
||||
#endif /*_FLASH_H*/
|
|
@ -0,0 +1,916 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright © 2007 Atheros Communications, Inc., All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Manage the atheros ethernet PHY.
|
||||
*
|
||||
* All definitions in this file are operating system independent!
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <linux/types.h>
|
||||
#include <common.h>
|
||||
#include <miiphy.h>
|
||||
#include "phy.h"
|
||||
#include <asm/addrspace.h>
|
||||
#include "ar7240_soc.h"
|
||||
#include "ar7240_s26_phy.h"
|
||||
|
||||
|
||||
/* PHY selections and access functions */
|
||||
|
||||
typedef enum {
|
||||
PHY_SRCPORT_INFO,
|
||||
PHY_PORTINFO_SIZE,
|
||||
} PHY_CAP_TYPE;
|
||||
|
||||
typedef enum {
|
||||
PHY_SRCPORT_NONE,
|
||||
PHY_SRCPORT_VLANTAG,
|
||||
PHY_SRCPORT_TRAILER,
|
||||
} PHY_SRCPORT_TYPE;
|
||||
|
||||
#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
|
||||
#define DRV_MSG(x,a,b,c,d,e,f)
|
||||
#define DRV_PRINT(DBG_SW,X)
|
||||
|
||||
#define ATHR_LAN_PORT_VLAN 1
|
||||
#define ATHR_WAN_PORT_VLAN 2
|
||||
#define ENET_UNIT_LAN 1
|
||||
#define ENET_UNIT_WAN 0
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define ATHR_PHY0_ADDR 0x0
|
||||
#define ATHR_PHY1_ADDR 0x1
|
||||
#define ATHR_PHY2_ADDR 0x2
|
||||
#define ATHR_PHY3_ADDR 0x3
|
||||
#define ATHR_PHY4_ADDR 0x4
|
||||
|
||||
#define MODULE_NAME "ATHRS26"
|
||||
|
||||
/*
|
||||
* Track per-PHY port information.
|
||||
*/
|
||||
typedef struct {
|
||||
BOOL isEnetPort; /* normal enet port */
|
||||
BOOL isPhyAlive; /* last known state of link */
|
||||
int ethUnit; /* MAC associated with this phy port */
|
||||
uint32_t phyBase;
|
||||
uint32_t phyAddr; /* PHY registers associated with this phy port */
|
||||
uint32_t VLANTableSetting; /* Value to be written to VLAN table */
|
||||
} athrPhyInfo_t;
|
||||
|
||||
/*
|
||||
* Per-PHY information, indexed by PHY unit number.
|
||||
*/
|
||||
static athrPhyInfo_t athrPhyInfo[] = {
|
||||
|
||||
{TRUE, /* port 1 -- LAN port 1 */
|
||||
FALSE,
|
||||
ENET_UNIT_LAN,
|
||||
0,
|
||||
ATHR_PHY0_ADDR,
|
||||
ATHR_LAN_PORT_VLAN
|
||||
},
|
||||
|
||||
{TRUE, /* port 2 -- LAN port 2 */
|
||||
FALSE,
|
||||
ENET_UNIT_LAN,
|
||||
0,
|
||||
ATHR_PHY1_ADDR,
|
||||
ATHR_LAN_PORT_VLAN
|
||||
},
|
||||
|
||||
{TRUE, /* port 3 -- LAN port 3 */
|
||||
FALSE,
|
||||
ENET_UNIT_LAN,
|
||||
0,
|
||||
ATHR_PHY2_ADDR,
|
||||
ATHR_LAN_PORT_VLAN
|
||||
},
|
||||
|
||||
{TRUE, /* port 4 -- LAN port 4 */
|
||||
FALSE,
|
||||
ENET_UNIT_LAN,
|
||||
0,
|
||||
ATHR_PHY3_ADDR,
|
||||
ATHR_LAN_PORT_VLAN /* Send to all ports */
|
||||
},
|
||||
|
||||
{TRUE, /* port 5 -- WAN Port 5 */
|
||||
FALSE,
|
||||
ENET_UNIT_WAN,
|
||||
0,
|
||||
ATHR_PHY4_ADDR,
|
||||
ATHR_LAN_PORT_VLAN /* Send to all ports */
|
||||
},
|
||||
|
||||
{FALSE, /* port 0 -- cpu port 0 */
|
||||
TRUE,
|
||||
ENET_UNIT_LAN,
|
||||
0,
|
||||
0x00,
|
||||
ATHR_LAN_PORT_VLAN
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static uint8_t athr26_init_flag = 0,athr26_init_flag1 = 0;
|
||||
|
||||
|
||||
#define ATHR_GLOBALREGBASE 0
|
||||
|
||||
#define ATHR_PHY_MAX 5
|
||||
|
||||
/* Range of valid PHY IDs is [MIN..MAX] */
|
||||
#define ATHR_ID_MIN 0
|
||||
#define ATHR_ID_MAX (ATHR_PHY_MAX-1)
|
||||
|
||||
/* Convenience macros to access myPhyInfo */
|
||||
#define ATHR_IS_ENET_PORT(phyUnit) (athrPhyInfo[phyUnit].isEnetPort)
|
||||
#define ATHR_IS_PHY_ALIVE(phyUnit) (athrPhyInfo[phyUnit].isPhyAlive)
|
||||
#define ATHR_ETHUNIT(phyUnit) (athrPhyInfo[phyUnit].ethUnit)
|
||||
#define ATHR_PHYBASE(phyUnit) (athrPhyInfo[phyUnit].phyBase)
|
||||
#define ATHR_PHYADDR(phyUnit) (athrPhyInfo[phyUnit].phyAddr)
|
||||
#define ATHR_VLAN_TABLE_SETTING(phyUnit) (athrPhyInfo[phyUnit].VLANTableSetting)
|
||||
|
||||
|
||||
#define ATHR_IS_ETHUNIT(phyUnit, ethUnit) \
|
||||
(ATHR_IS_ENET_PORT(phyUnit) && \
|
||||
ATHR_ETHUNIT(phyUnit) == (ethUnit))
|
||||
|
||||
#define ATHR_IS_WAN_PORT(phyUnit) (!(ATHR_ETHUNIT(phyUnit)==ENET_UNIT_LAN))
|
||||
|
||||
/* Forward references */
|
||||
BOOL athrs26_phy_is_link_alive(int phyUnit);
|
||||
uint32_t athrs26_reg_read(uint32_t reg_addr);
|
||||
void athrs26_reg_write(uint32_t reg_addr, uint32_t reg_val);
|
||||
unsigned int s26_rd_phy(unsigned int phy_addr, unsigned int reg_addr);
|
||||
void s26_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data);
|
||||
|
||||
|
||||
void athrs26_powersave_off(int phy_addr)
|
||||
{
|
||||
s26_wr_phy(phy_addr,ATHR_DEBUG_PORT_ADDRESS,0x29);
|
||||
s26_wr_phy(phy_addr,ATHR_DEBUG_PORT_DATA,0x36c0);
|
||||
|
||||
}
|
||||
void athrs26_sleep_off(int phy_addr)
|
||||
{
|
||||
s26_wr_phy(phy_addr,ATHR_DEBUG_PORT_ADDRESS,0xb);
|
||||
s26_wr_phy(phy_addr,ATHR_DEBUG_PORT_DATA,0x3c00);
|
||||
}
|
||||
|
||||
void athrs26_reg_init(void)
|
||||
{
|
||||
|
||||
#if S26_PHY_DEBUG
|
||||
uint32_t rd_val;
|
||||
#endif
|
||||
uint32_t ar7240_revid;
|
||||
/* if using header for register configuration, we have to */
|
||||
/* configure s26 register after frame transmission is enabled */
|
||||
|
||||
if (athr26_init_flag)
|
||||
return;
|
||||
|
||||
ar7240_revid = ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK;
|
||||
if(ar7240_revid == AR7240_REV_1_0) {
|
||||
#ifdef S26_FORCE_100M
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_FUNC_CONTROL,0x800);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL,0xa100);
|
||||
#endif
|
||||
|
||||
#ifdef S26_FORCE_10M
|
||||
athrs26_powersave_off(ATHR_PHY4_ADDR);
|
||||
athrs26_sleep_off(ATHR_PHY4_ADDR);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_FUNC_CONTROL,0x800);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL,0x8100);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_ADDRESS,0x0);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_DATA,0x12ee);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_ADDRESS,0x3);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_DATA,0x3bf0);
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL,0x8100);
|
||||
#endif
|
||||
} else {
|
||||
s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL,0x9000);
|
||||
}
|
||||
|
||||
#if S26_PHY_DEBUG
|
||||
rd_val = s26_rd_phy(ATHR_PHY4_ADDR,ATHR_PHY_FUNC_CONTROL);
|
||||
printf("S26 PHY FUNC CTRL (%d) :%x\n",ATHR_PHY4_ADDR, rd_val);
|
||||
rd_val = s26_rd_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL);
|
||||
printf("S26 PHY CTRL (%d) :%x\n",ATHR_PHY4_ADDR, rd_val);
|
||||
#endif
|
||||
|
||||
athr26_init_flag = 1;
|
||||
}
|
||||
|
||||
void athrs26_reg_init_lan(void)
|
||||
{
|
||||
int i = 60;
|
||||
#if S26_PHY_DEBUG
|
||||
uint32_t rd_val;
|
||||
#endif
|
||||
int phyUnit;
|
||||
uint32_t phyBase = 0;
|
||||
BOOL foundPhy = FALSE;
|
||||
uint32_t phyAddr = 0;
|
||||
uint32_t ar7240_revid;
|
||||
|
||||
/* if using header for register configuration, we have to */
|
||||
/* configure s26 register after frame transmission is enabled */
|
||||
if (athr26_init_flag1)
|
||||
return;
|
||||
|
||||
/* reset switch */
|
||||
debug(MODULE_NAME ": resetting s26\n");
|
||||
athrs26_reg_write(0x0, athrs26_reg_read(0x0)|0x80000000);
|
||||
|
||||
while(i--) {
|
||||
if(!is_ar933x())
|
||||
sysMsDelay(100);
|
||||
if(!(athrs26_reg_read(0x0)&0x80000000))
|
||||
break;
|
||||
}
|
||||
debug(MODULE_NAME ": s26 reset done\n");
|
||||
|
||||
for (phyUnit=0; phyUnit < ATHR_PHY_MAX - 1; phyUnit++) {
|
||||
|
||||
foundPhy = TRUE;
|
||||
phyBase = ATHR_PHYBASE(phyUnit);
|
||||
phyAddr = ATHR_PHYADDR(phyUnit);
|
||||
|
||||
ar7240_revid = ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK;
|
||||
if(ar7240_revid == AR7240_REV_1_0) {
|
||||
#ifdef S26_FORCE_100M
|
||||
/*
|
||||
* Force MDI and MDX to alternate ports
|
||||
* Phy 0 and 2 -- MDI
|
||||
* Phy 1 and 3 -- MDX
|
||||
*/
|
||||
if(phyUnit%2)
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x820);
|
||||
else
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x800);
|
||||
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_CONTROL,0xa100);
|
||||
#endif
|
||||
|
||||
#ifdef S26_FORCE_10M
|
||||
/*
|
||||
* Force MDI and MDX to alternate ports
|
||||
* Phy 0 and 2 -- MDI
|
||||
* Phy 1 and 3 -- MDX
|
||||
*/
|
||||
if(phyUnit%2)
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x820);
|
||||
else
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x800);
|
||||
|
||||
athrs26_powersave_off(phyAddr);
|
||||
athrs26_sleep_off(phyAddr);
|
||||
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_CONTROL,0x8100);
|
||||
s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_ADDRESS,0x0);
|
||||
s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_DATA,0x12ee);
|
||||
s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_ADDRESS,0x3);
|
||||
s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_DATA,0x3bf0);
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_CONTROL,0x8100);
|
||||
#endif
|
||||
} else {
|
||||
s26_wr_phy(phyAddr,ATHR_PHY_CONTROL,0x9000);
|
||||
}
|
||||
|
||||
#if S26_PHY_DEBUG
|
||||
rd_val = s26_rd_phy(phyAddr,ATHR_PHY_ID1);
|
||||
printf("S26 PHY ID (%d) :%x\n",phyAddr,rd_val);
|
||||
rd_val = s26_rd_phy(phyAddr,ATHR_PHY_CONTROL);
|
||||
printf("S26 PHY CTRL (%d) :%x\n",phyAddr,rd_val);
|
||||
rd_val = s26_rd_phy(phyAddr,ATHR_PHY_STATUS);
|
||||
printf("S26 ATHR PHY STATUS (%d) :%x\n",phyAddr,rd_val);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* CPU port Enable
|
||||
*/
|
||||
athrs26_reg_write(CPU_PORT_REGISTER,(1 << 8));
|
||||
|
||||
/*
|
||||
* status[1:0]=2'h2; - (0x10 - 1000 Mbps , 0x0 - 10 Mbps)
|
||||
* status[2]=1'h1; - Tx Mac En
|
||||
* status[3]=1'h1; - Rx Mac En
|
||||
* status[4]=1'h1; - Tx Flow Ctrl En
|
||||
* status[5]=1'h1; - Rx Flow Ctrl En
|
||||
* status[6]=1'h1; - Duplex Mode
|
||||
*/
|
||||
#ifdef CONFIG_AR7240_EMU
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER0, 0x7e); /* CPU Port */
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER1, 0x3c);
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER2, 0x3c);
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER3, 0x3c);
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER4, 0x3c);
|
||||
#else
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER1, 0x200); /* LAN - 1 */
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER2, 0x200); /* LAN - 2 */
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER3, 0x200); /* LAN - 3 */
|
||||
athrs26_reg_write(PORT_STATUS_REGISTER4, 0x200); /* LAN - 4 */
|
||||
#endif
|
||||
|
||||
/* QM Control */
|
||||
athrs26_reg_write(0x38, 0xc000050e);
|
||||
|
||||
/*
|
||||
* status[11]=1'h0; - CPU Disable
|
||||
* status[7] = 1'b1; - Learn One Lock
|
||||
* status[14] = 1'b0; - Learn Enable
|
||||
*/
|
||||
#ifdef CONFIG_AR7240_EMU
|
||||
athrs26_reg_write(PORT_CONTROL_REGISTER0, 0x04);
|
||||
athrs26_reg_write(PORT_CONTROL_REGISTER1, 0x4004);
|
||||
#else
|
||||
/* Atheros Header Disable */
|
||||
athrs26_reg_write(PORT_CONTROL_REGISTER0, 0x4004);
|
||||
#endif
|
||||
|
||||
/* Tag Priority Mapping */
|
||||
athrs26_reg_write(0x70, 0xfa50);
|
||||
|
||||
/* Enable ARP packets to CPU port */
|
||||
athrs26_reg_write(S26_ARL_TBL_CTRL_REG,(athrs26_reg_read(S26_ARL_TBL_CTRL_REG) | 0x100000));
|
||||
|
||||
#if S26_PHY_DEBUG
|
||||
rd_val = athrs26_reg_read ( CPU_PORT_REGISTER );
|
||||
printf("S26 CPU_PORT_REGISTER :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER0 );
|
||||
printf("S26 PORT_STATUS_REGISTER0 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER1 );
|
||||
printf("S26 PORT_STATUS_REGISTER1 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER2 );
|
||||
printf("S26 PORT_STATUS_REGISTER2 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER3 );
|
||||
printf("S26 PORT_STATUS_REGISTER3 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER4 );
|
||||
printf("S26 PORT_STATUS_REGISTER4 :%x\n",rd_val);
|
||||
|
||||
rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER0 );
|
||||
printf("S26 PORT_CONTROL_REGISTER0 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER1 );
|
||||
printf("S26 PORT_CONTROL_REGISTER1 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER2 );
|
||||
printf("S26 PORT_CONTROL_REGISTER2 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER3 );
|
||||
printf("S26 PORT_CONTROL_REGISTER3 :%x\n",rd_val);
|
||||
rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER4 );
|
||||
printf("S26 PORT_CONTROL_REGISTER4 :%x\n",rd_val);
|
||||
#endif
|
||||
|
||||
athr26_init_flag1 = 1;
|
||||
}
|
||||
static unsigned int phy_val_saved = 0;
|
||||
/******************************************************************************
|
||||
*
|
||||
* athrs26_phy_is_link_alive - test to see if the specified link is alive
|
||||
*
|
||||
* RETURNS:
|
||||
* TRUE --> link is alive
|
||||
* FALSE --> link is down
|
||||
*/
|
||||
BOOL
|
||||
athrs26_phy_is_link_alive(int phyUnit)
|
||||
{
|
||||
uint16_t phyHwStatus;
|
||||
uint32_t phyBase;
|
||||
uint32_t phyAddr;
|
||||
phyBase = ATHR_PHYBASE(phyUnit);
|
||||
phyAddr = ATHR_PHYADDR(phyUnit);
|
||||
|
||||
phyHwStatus = s26_rd_phy( phyAddr, ATHR_PHY_SPEC_STATUS);
|
||||
|
||||
if (phyHwStatus & ATHR_STATUS_LINK_PASS)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* athrs26_phy_setup - reset and setup the PHY associated with
|
||||
* the specified MAC unit number.
|
||||
*
|
||||
* Resets the associated PHY port.
|
||||
*
|
||||
* RETURNS:
|
||||
* TRUE --> associated PHY is alive
|
||||
* FALSE --> no LINKs on this ethernet unit
|
||||
*/
|
||||
|
||||
BOOL
|
||||
athrs26_phy_setup(int ethUnit)
|
||||
{
|
||||
int phyUnit;
|
||||
uint16_t phyHwStatus;
|
||||
uint16_t timeout;
|
||||
int liveLinks = 0;
|
||||
uint32_t phyBase = 0;
|
||||
BOOL foundPhy = FALSE;
|
||||
uint32_t phyAddr = 0;
|
||||
#if S26_PHY_DEBUG
|
||||
uint32_t rd_val = 0;
|
||||
#endif
|
||||
uint32_t ar7240_revid;
|
||||
|
||||
|
||||
/* See if there's any configuration data for this enet */
|
||||
/* start auto negogiation on each phy */
|
||||
for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
|
||||
if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foundPhy = TRUE;
|
||||
phyBase = ATHR_PHYBASE(phyUnit);
|
||||
phyAddr = ATHR_PHYADDR(phyUnit);
|
||||
|
||||
s26_wr_phy(phyAddr, ATHR_AUTONEG_ADVERT,ATHR_ADVERTISE_ALL);
|
||||
#if S26_PHY_DEBUG
|
||||
rd_val = s26_rd_phy(phyAddr,ATHR_AUTONEG_ADVERT );
|
||||
printf("%s ATHR_AUTONEG_ADVERT %d :%x\n",__func__,phyAddr, rd_val);
|
||||
#endif
|
||||
|
||||
ar7240_revid = ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK;
|
||||
if(ar7240_revid != AR7240_REV_1_0) {
|
||||
s26_wr_phy( phyAddr, ATHR_PHY_CONTROL,ATHR_CTRL_AUTONEGOTIATION_ENABLE
|
||||
| ATHR_CTRL_SOFTWARE_RESET);
|
||||
}
|
||||
|
||||
#if S26_PHY_DEBUG
|
||||
rd_val = s26_rd_phy(phyAddr,ATHR_AUTONEG_ADVERT );
|
||||
rd_val = s26_rd_phy(phyAddr,ATHR_PHY_CONTROL);
|
||||
printf("%s ATHR_PHY_CONTROL %d :%x\n",__func__,phyAddr, rd_val);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!foundPhy) {
|
||||
return FALSE; /* No PHY's configured for this ethUnit */
|
||||
}
|
||||
|
||||
/*
|
||||
* After the phy is reset, it takes a little while before
|
||||
* it can respond properly.
|
||||
*/
|
||||
if(!is_ar933x()) {
|
||||
if (ethUnit == ENET_UNIT_LAN)
|
||||
sysMsDelay(1000);
|
||||
else
|
||||
sysMsDelay(3000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait up to 3 seconds for ALL associated PHYs to finish
|
||||
* autonegotiation. The only way we get out of here sooner is
|
||||
* if ALL PHYs are connected AND finish autonegotiation.
|
||||
*/
|
||||
for (phyUnit=0; (phyUnit < ATHR_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
|
||||
if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
timeout=20;
|
||||
for (;;) {
|
||||
phyHwStatus = s26_rd_phy(phyAddr, ATHR_PHY_CONTROL);
|
||||
|
||||
if (ATHR_RESET_DONE(phyHwStatus)) {
|
||||
DRV_PRINT(DRV_DEBUG_PHYSETUP,
|
||||
("Port %d, Neg Success\n", phyUnit));
|
||||
break;
|
||||
}
|
||||
if (timeout == 0) {
|
||||
DRV_PRINT(DRV_DEBUG_PHYSETUP,
|
||||
("Port %d, Negogiation timeout\n", phyUnit));
|
||||
break;
|
||||
}
|
||||
if (--timeout == 0) {
|
||||
DRV_PRINT(DRV_DEBUG_PHYSETUP,
|
||||
("Port %d, Negogiation timeout\n", phyUnit));
|
||||
break;
|
||||
}
|
||||
|
||||
if(!is_ar933x())
|
||||
sysMsDelay(150);
|
||||
}
|
||||
|
||||
|
||||
#ifdef S26_VER_1_0
|
||||
//turn off power saving
|
||||
s26_wr_phy(phyUnit, 29, 41);
|
||||
s26_wr_phy(phyUnit, 30, 0);
|
||||
printf("def_ S26_VER_1_0\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* All PHYs have had adequate time to autonegotiate.
|
||||
* Now initialize software status.
|
||||
*
|
||||
* It's possible that some ports may take a bit longer
|
||||
* to autonegotiate; but we can't wait forever. They'll
|
||||
* get noticed by mv_phyCheckStatusChange during regular
|
||||
* polling activities.
|
||||
*/
|
||||
for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
|
||||
if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (athrs26_phy_is_link_alive(phyUnit)) {
|
||||
liveLinks++;
|
||||
ATHR_IS_PHY_ALIVE(phyUnit) = TRUE;
|
||||
} else {
|
||||
ATHR_IS_PHY_ALIVE(phyUnit) = FALSE;
|
||||
}
|
||||
DRV_PRINT(DRV_DEBUG_PHYSETUP,
|
||||
("eth%d: Phy Specific Status=%4.4x\n",
|
||||
ethUnit,
|
||||
s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_SPEC_STATUS)));
|
||||
}
|
||||
|
||||
return (liveLinks > 0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* athrs26_phy_is_fdx - Determines whether the phy ports associated with the
|
||||
* specified device are FULL or HALF duplex.
|
||||
*
|
||||
* RETURNS:
|
||||
* 1 --> FULL
|
||||
* 0 --> HALF
|
||||
*/
|
||||
int
|
||||
athrs26_phy_is_fdx(int ethUnit)
|
||||
{
|
||||
int phyUnit;
|
||||
uint32_t phyBase;
|
||||
uint32_t phyAddr;
|
||||
uint16_t phyHwStatus;
|
||||
int ii = 200;
|
||||
|
||||
if (ethUnit == ENET_UNIT_LAN)
|
||||
return TRUE;
|
||||
|
||||
for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
|
||||
if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (athrs26_phy_is_link_alive(phyUnit)) {
|
||||
|
||||
phyBase = ATHR_PHYBASE(phyUnit);
|
||||
phyAddr = ATHR_PHYADDR(phyUnit);
|
||||
|
||||
do {
|
||||
phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_SPEC_STATUS);
|
||||
sysMsDelay(10);
|
||||
} while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii);
|
||||
|
||||
if (phyHwStatus & ATHER_STATUS_FULL_DEPLEX)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* athrs26_phy_speed - Determines the speed of phy ports associated with the
|
||||
* specified device.
|
||||
*
|
||||
* RETURNS:
|
||||
* _10BASET, _100BASET;
|
||||
* _1000BASET;
|
||||
*/
|
||||
|
||||
int
|
||||
athrs26_phy_speed(int ethUnit)
|
||||
{
|
||||
int phyUnit;
|
||||
uint16_t phyHwStatus;
|
||||
uint32_t phyBase;
|
||||
uint32_t phyAddr;
|
||||
int ii = 200;
|
||||
|
||||
if (ethUnit == ENET_UNIT_LAN)
|
||||
return _1000BASET;
|
||||
|
||||
for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
|
||||
if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (athrs26_phy_is_link_alive(phyUnit)) {
|
||||
|
||||
phyBase = ATHR_PHYBASE(phyUnit);
|
||||
phyAddr = ATHR_PHYADDR(phyUnit);
|
||||
do {
|
||||
phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_SPEC_STATUS);
|
||||
sysMsDelay(10);
|
||||
} while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii);
|
||||
|
||||
phyHwStatus = ((phyHwStatus & ATHER_STATUS_LINK_MASK) >>
|
||||
ATHER_STATUS_LINK_SHIFT);
|
||||
|
||||
switch(phyHwStatus) {
|
||||
case 0:
|
||||
return _10BASET;
|
||||
case 1:
|
||||
#ifdef CONFIG_MACH_HORNET
|
||||
/* For IEEE 100M voltage test */
|
||||
s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_ADDRESS, 0x4);
|
||||
s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_DATA, 0xebbb);
|
||||
s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_ADDRESS, 0x5);
|
||||
s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_DATA, 0x2c47);
|
||||
#endif /* CONFIG_MACH_HORNET */
|
||||
return _100BASET;
|
||||
case 2:
|
||||
return _1000BASET;
|
||||
default:
|
||||
printf("Unkown speed read!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _10BASET;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* athr_phy_is_up -- checks for significant changes in PHY state.
|
||||
*
|
||||
* A "significant change" is:
|
||||
* dropped link (e.g. ethernet cable unplugged) OR
|
||||
* autonegotiation completed + link (e.g. ethernet cable plugged in)
|
||||
*
|
||||
* When a PHY is plugged in, phyLinkGained is called.
|
||||
* When a PHY is unplugged, phyLinkLost is called.
|
||||
*/
|
||||
|
||||
int
|
||||
athrs26_phy_is_up(int ethUnit)
|
||||
{
|
||||
int phyUnit;
|
||||
uint16_t phyHwStatus, phyHwControl;
|
||||
athrPhyInfo_t *lastStatus;
|
||||
int linkCount = 0;
|
||||
int lostLinks = 0;
|
||||
int gainedLinks = 0;
|
||||
uint32_t phyBase;
|
||||
uint32_t phyAddr;
|
||||
|
||||
for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
|
||||
if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
phyBase = ATHR_PHYBASE(phyUnit);
|
||||
phyAddr = ATHR_PHYADDR(phyUnit);
|
||||
|
||||
lastStatus = &athrPhyInfo[phyUnit];
|
||||
|
||||
if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
|
||||
|
||||
phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_SPEC_STATUS);
|
||||
|
||||
/* See if we've lost link */
|
||||
if (phyHwStatus & ATHR_STATUS_LINK_PASS) { /* check realtime link */
|
||||
linkCount++;
|
||||
} else {
|
||||
phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_STATUS);
|
||||
/* If realtime failed check link in latch register before
|
||||
* asserting link down.
|
||||
*/
|
||||
if (phyHwStatus & ATHR_LATCH_LINK_PASS)
|
||||
linkCount++;
|
||||
else {
|
||||
lostLinks++;
|
||||
}
|
||||
DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n",
|
||||
ethUnit, phyUnit));
|
||||
lastStatus->isPhyAlive = FALSE;
|
||||
}
|
||||
} else { /* last known link status was DEAD */
|
||||
|
||||
/* Check for reset complete */
|
||||
|
||||
phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_STATUS);
|
||||
|
||||
if (!ATHR_RESET_DONE(phyHwStatus))
|
||||
continue;
|
||||
|
||||
phyHwControl = s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_CONTROL);
|
||||
|
||||
/* Check for AutoNegotiation complete */
|
||||
|
||||
if ((!(phyHwControl & ATHR_CTRL_AUTONEGOTIATION_ENABLE))
|
||||
|| ATHR_AUTONEG_DONE(phyHwStatus)) {
|
||||
phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_SPEC_STATUS);
|
||||
|
||||
if (phyHwStatus & ATHR_STATUS_LINK_PASS) {
|
||||
gainedLinks++;
|
||||
linkCount++;
|
||||
DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n",
|
||||
ethUnit, phyUnit));
|
||||
lastStatus->isPhyAlive = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (linkCount);
|
||||
|
||||
#if S26_PHY_DEBUG
|
||||
if (linkCount == 0) {
|
||||
if (lostLinks) {
|
||||
/* We just lost the last link for this MAC */
|
||||
phyLinkLost(ethUnit);
|
||||
}
|
||||
} else {
|
||||
if (gainedLinks == linkCount) {
|
||||
/* We just gained our first link(s) for this MAC */
|
||||
phyLinkGained(ethUnit);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t
|
||||
athrs26_reg_read(unsigned int s26_addr)
|
||||
{
|
||||
unsigned int addr_temp;
|
||||
unsigned int s26_rd_csr_low, s26_rd_csr_high, s26_rd_csr;
|
||||
unsigned int data, unit = 0;
|
||||
unsigned int phy_address, reg_address;
|
||||
|
||||
addr_temp = (s26_addr & 0xfffffffc) >>2;
|
||||
data = addr_temp >> 7;
|
||||
|
||||
phy_address = 0x1f;
|
||||
reg_address = 0x10;
|
||||
|
||||
if (is_ar7240()) {
|
||||
unit = 0;
|
||||
}
|
||||
else if (is_ar7241() || is_ar7242() || is_ar933x()) {
|
||||
unit = 1;
|
||||
}
|
||||
|
||||
phy_reg_write(unit,phy_address, reg_address, data);
|
||||
|
||||
phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
|
||||
reg_address = ((addr_temp << 1) & 0x1e);
|
||||
s26_rd_csr_low = (uint32_t) phy_reg_read(unit, phy_address, reg_address);
|
||||
|
||||
reg_address = reg_address | 0x1;
|
||||
s26_rd_csr_high = (uint32_t) phy_reg_read(unit, phy_address, reg_address);
|
||||
s26_rd_csr = (s26_rd_csr_high << 16) | s26_rd_csr_low ;
|
||||
|
||||
return(s26_rd_csr);
|
||||
}
|
||||
|
||||
void
|
||||
athrs26_reg_write(unsigned int s26_addr, unsigned int s26_write_data)
|
||||
{
|
||||
unsigned int addr_temp;
|
||||
unsigned int data, unit = 0;
|
||||
unsigned int phy_address, reg_address;
|
||||
|
||||
|
||||
addr_temp = (s26_addr & 0xfffffffc) >>2;
|
||||
data = addr_temp >> 7;
|
||||
|
||||
phy_address = 0x1f;
|
||||
reg_address = 0x10;
|
||||
|
||||
if (is_ar7240()) {
|
||||
unit = 0;
|
||||
}
|
||||
else if (is_ar7241() || is_ar7242()|| is_ar933x()) {
|
||||
unit = 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MACH_HORNET
|
||||
//The write sequence , 0x98: L->H, 0x40 H->L, 0x50 H->L , others should not care.
|
||||
if(s26_addr!=0x98)
|
||||
{
|
||||
//printf("[%s:%d] unit=%d\n",__FUNCTION__,__LINE__,unit);
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
|
||||
phy_address = 0x17 & ((addr_temp >> 4) | 0x10);
|
||||
reg_address = ((addr_temp << 1) & 0x1e) | 0x1;
|
||||
data = s26_write_data >> 16;
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
|
||||
reg_address = reg_address & 0x1e;
|
||||
data = s26_write_data & 0xffff;
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
|
||||
phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
|
||||
reg_address = ((addr_temp << 1) & 0x1e);
|
||||
|
||||
data = s26_write_data & 0xffff;
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
|
||||
reg_address = (((addr_temp << 1) & 0x1e) | 0x1);
|
||||
data = s26_write_data >> 16;
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
|
||||
}
|
||||
#else
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
|
||||
phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
|
||||
reg_address = ((addr_temp << 1) & 0x1e);
|
||||
data = s26_write_data & 0xffff;
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
|
||||
reg_address = (((addr_temp << 1) & 0x1e) | 0x1);
|
||||
data = s26_write_data >> 16;
|
||||
phy_reg_write(unit, phy_address, reg_address, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
unsigned int s26_rd_phy(unsigned int phy_addr, unsigned int reg_addr)
|
||||
{
|
||||
|
||||
unsigned int rddata;
|
||||
|
||||
// MDIO_CMD is set for read
|
||||
|
||||
rddata = athrs26_reg_read(0x98);
|
||||
rddata = (rddata & 0x0) | (reg_addr<<16) | (phy_addr<<21) | (1<<27) | (1<<30) | (1<<31) ;
|
||||
athrs26_reg_write(0x98, rddata);
|
||||
|
||||
rddata = athrs26_reg_read(0x98);
|
||||
rddata = rddata & (1<<31);
|
||||
|
||||
// Check MDIO_BUSY status
|
||||
while(rddata){
|
||||
rddata = athrs26_reg_read(0x98);
|
||||
rddata = rddata & (1<<31);
|
||||
}
|
||||
|
||||
|
||||
// Read the data from phy
|
||||
|
||||
rddata = athrs26_reg_read(0x98) & 0xffff;
|
||||
|
||||
return(rddata);
|
||||
}
|
||||
|
||||
void s26_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data)
|
||||
{
|
||||
unsigned int rddata;
|
||||
|
||||
// MDIO_CMD is set for read
|
||||
|
||||
rddata = athrs26_reg_read(0x98);
|
||||
rddata = (rddata & 0x0) | (write_data & 0xffff) | (reg_addr<<16) | (phy_addr<<21) | (0<<27) | (1<<30) | (1<<31) ;
|
||||
athrs26_reg_write(0x98, rddata);
|
||||
|
||||
rddata = athrs26_reg_read(0x98);
|
||||
rddata = rddata & (1<<31);
|
||||
|
||||
// Check MDIO_BUSY status
|
||||
while(rddata){
|
||||
rddata = athrs26_reg_read(0x98);
|
||||
rddata = rddata & (1<<31);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
athrs26_mdc_check()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<4000; i++) {
|
||||
if(athrs26_reg_read(0x10c) != 0x18007fff)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
#ifndef _ATHRS26_PHY_H
|
||||
#define _ATHRS26_PHY_H
|
||||
|
||||
|
||||
/*****************/
|
||||
/* PHY Registers */
|
||||
/*****************/
|
||||
#define ATHR_PHY_CONTROL 0
|
||||
#define ATHR_PHY_STATUS 1
|
||||
#define ATHR_PHY_ID1 2
|
||||
#define ATHR_PHY_ID2 3
|
||||
#define ATHR_AUTONEG_ADVERT 4
|
||||
#define ATHR_LINK_PARTNER_ABILITY 5
|
||||
#define ATHR_AUTONEG_EXPANSION 6
|
||||
#define ATHR_NEXT_PAGE_TRANSMIT 7
|
||||
#define ATHR_LINK_PARTNER_NEXT_PAGE 8
|
||||
#define ATHR_1000BASET_CONTROL 9
|
||||
#define ATHR_1000BASET_STATUS 10
|
||||
#define ATHR_PHY_FUNC_CONTROL 16
|
||||
#define ATHR_PHY_SPEC_STATUS 17
|
||||
#define ATHR_DEBUG_PORT_ADDRESS 29
|
||||
#define ATHR_DEBUG_PORT_DATA 30
|
||||
|
||||
/* ATHR_PHY_CONTROL fields */
|
||||
#define ATHR_CTRL_SOFTWARE_RESET 0x8000
|
||||
#define ATHR_CTRL_SPEED_LSB 0x2000
|
||||
#define ATHR_CTRL_AUTONEGOTIATION_ENABLE 0x1000
|
||||
#define ATHR_CTRL_RESTART_AUTONEGOTIATION 0x0200
|
||||
#define ATHR_CTRL_SPEED_FULL_DUPLEX 0x0100
|
||||
#define ATHR_CTRL_SPEED_MSB 0x0040
|
||||
|
||||
#define ATHR_RESET_DONE(phy_control) \
|
||||
(((phy_control) & (ATHR_CTRL_SOFTWARE_RESET)) == 0)
|
||||
|
||||
/* Phy status fields */
|
||||
#define ATHR_STATUS_AUTO_NEG_DONE 0x0020
|
||||
|
||||
#define ATHR_AUTONEG_DONE(ip_phy_status) \
|
||||
(((ip_phy_status) & \
|
||||
(ATHR_STATUS_AUTO_NEG_DONE)) == \
|
||||
(ATHR_STATUS_AUTO_NEG_DONE))
|
||||
|
||||
/* Link Partner ability */
|
||||
#define ATHR_LINK_100BASETX_FULL_DUPLEX 0x0100
|
||||
#define ATHR_LINK_100BASETX 0x0080
|
||||
#define ATHR_LINK_10BASETX_FULL_DUPLEX 0x0040
|
||||
#define ATHR_LINK_10BASETX 0x0020
|
||||
|
||||
/* Advertisement register. */
|
||||
#define ATHR_ADVERTISE_NEXT_PAGE 0x8000
|
||||
#define ATHR_ADVERTISE_ASYM_PAUSE 0x0800
|
||||
#define ATHR_ADVERTISE_PAUSE 0x0400
|
||||
#define ATHR_ADVERTISE_100FULL 0x0100
|
||||
#define ATHR_ADVERTISE_100HALF 0x0080
|
||||
#define ATHR_ADVERTISE_10FULL 0x0040
|
||||
#define ATHR_ADVERTISE_10HALF 0x0020
|
||||
|
||||
#define ATHR_ADVERTISE_ALL (ATHR_ADVERTISE_ASYM_PAUSE | ATHR_ADVERTISE_PAUSE | \
|
||||
ATHR_ADVERTISE_10HALF | ATHR_ADVERTISE_10FULL | \
|
||||
ATHR_ADVERTISE_100HALF | ATHR_ADVERTISE_100FULL)
|
||||
|
||||
/* 1000BASET_CONTROL */
|
||||
#define ATHR_ADVERTISE_1000FULL 0x0200
|
||||
|
||||
/* Phy Specific status fields */
|
||||
#define ATHER_STATUS_LINK_MASK 0xC000
|
||||
#define ATHER_STATUS_LINK_SHIFT 14
|
||||
#define ATHER_STATUS_FULL_DEPLEX 0x2000
|
||||
#define ATHR_STATUS_LINK_PASS 0x0400
|
||||
#define ATHR_LATCH_LINK_PASS 0x0004
|
||||
#define ATHR_STATUS_RESOVLED 0x0800
|
||||
|
||||
/*phy debug port register */
|
||||
#define ATHER_DEBUG_SERDES_REG 5
|
||||
|
||||
/* Serdes debug fields */
|
||||
#define ATHER_SERDES_BEACON 0x0100
|
||||
|
||||
/* S26 CSR Registers */
|
||||
|
||||
#define PORT_STATUS_REGISTER0 0x0100
|
||||
#define PORT_STATUS_REGISTER1 0x0200
|
||||
#define PORT_STATUS_REGISTER2 0x0300
|
||||
#define PORT_STATUS_REGISTER3 0x0400
|
||||
#define PORT_STATUS_REGISTER4 0x0500
|
||||
#define PORT_STATUS_REGISTER5 0x0600
|
||||
|
||||
#define RATE_LIMIT_REGISTER0 0x010C
|
||||
#define RATE_LIMIT_REGISTER1 0x020C
|
||||
#define RATE_LIMIT_REGISTER2 0x030C
|
||||
#define RATE_LIMIT_REGISTER3 0x040C
|
||||
#define RATE_LIMIT_REGISTER4 0x050C
|
||||
#define RATE_LIMIT_REGISTER5 0x060C
|
||||
|
||||
#define PORT_CONTROL_REGISTER0 0x0104
|
||||
#define PORT_CONTROL_REGISTER1 0x0204
|
||||
#define PORT_CONTROL_REGISTER2 0x0204
|
||||
#define PORT_CONTROL_REGISTER3 0x0204
|
||||
#define PORT_CONTROL_REGISTER4 0x0204
|
||||
#define PORT_CONTROL_REGISTER5 0x0204
|
||||
|
||||
#define CPU_PORT_REGISTER 0x0078
|
||||
#define MDIO_CTRL_REGISTER 0x0098
|
||||
|
||||
#define S26_ARL_TBL_FUNC_REG0 0x0050
|
||||
#define S26_ARL_TBL_FUNC_REG1 0x0054
|
||||
#define S26_ARL_TBL_FUNC_REG2 0x0058
|
||||
#define S26_ARL_TBL_CTRL_REG 0x005c
|
||||
|
||||
#ifndef BOOL
|
||||
#define BOOL int
|
||||
#endif
|
||||
|
||||
#define sysMsDelay(_x) udelay((_x) * 1000)
|
||||
#define mdelay(_x) sysMsDelay(_x)
|
||||
|
||||
#define S26_FORCE_100M 1
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
#include <config.h>
|
||||
#include <version.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <ar7240_soc.h>
|
||||
|
||||
/*
|
||||
* Helper macros.
|
||||
* These Clobber t7, t8 and t9
|
||||
*/
|
||||
#define clear_mask(_reg, _mask) \
|
||||
li t7, KSEG1ADDR(_reg); \
|
||||
lw t8, 0(t7); \
|
||||
li t9, ~_mask; \
|
||||
and t8, t8, t9; \
|
||||
sw t8, 0(t7)
|
||||
|
||||
#define set_val(_reg, _mask, _val) \
|
||||
li t7, KSEG1ADDR(_reg); \
|
||||
lw t8, 0(t7); \
|
||||
li t9, ~_mask; \
|
||||
and t8, t8, t9; \
|
||||
li t9, _val; \
|
||||
or t8, t8, t9; \
|
||||
sw t8, 0(t7)
|
||||
|
||||
#define set_val_f(_reg, _mask, _val) \
|
||||
li t7, KSEG1ADDR(_reg); \
|
||||
lw t8, 0(t7); \
|
||||
li t9, ~_mask; \
|
||||
and t8, t8, t9; \
|
||||
li t6, KSEG1ADDR(_val); \
|
||||
lw t9, 0(t6); \
|
||||
or t8, t8, t9; \
|
||||
sw t8, 0(t7)
|
||||
|
||||
|
||||
#define get_val(_reg, _mask, _shift, _res_reg) \
|
||||
li t7, KSEG1ADDR(_reg); \
|
||||
lw t8, 0(t7); \
|
||||
li t9, _mask; \
|
||||
and t8, t8, t9; \
|
||||
srl _res_reg, t8, _shift \
|
||||
|
||||
#define pll_clr(_mask) \
|
||||
clear_mask(AR7240_CPU_PLL_CONFIG, _mask)
|
||||
|
||||
#define pll_set(_mask, _val) \
|
||||
set_val(AR7240_CPU_PLL_CONFIG, _mask, _val)
|
||||
|
||||
#define pll_set_f(_mask, _val) \
|
||||
set_val_f(AR7240_CPU_PLL_CONFIG, _mask, _val)
|
||||
|
||||
#define pll_get(_mask, _shift, _res_reg) \
|
||||
get_val(AR7240_CPU_PLL_CONFIG, _mask, _shift, _res_reg)
|
||||
|
||||
#define clk_clr(_mask) \
|
||||
clear_mask(AR7240_CPU_CLOCK_CONTROL, _mask)
|
||||
|
||||
#define clk_set(_mask, _val) \
|
||||
set_val(AR7240_CPU_CLOCK_CONTROL, _mask, _val)
|
||||
|
||||
#define clk_get(_mask, _shift, _res_reg) \
|
||||
get_val(AR7240_CPU_CLOCK_CONTROL, _mask, _shift, _res_reg)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* first level initialization:
|
||||
*
|
||||
* 0) If clock cntrl reset switch is already set, we're recovering from
|
||||
* "divider reset"; goto 3.
|
||||
* 1) Setup divide ratios.
|
||||
* 2) Reset.
|
||||
* 3) Setup pll's, wait for lock.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
.globl lowlevel_init
|
||||
|
||||
lowlevel_init:
|
||||
|
||||
/*
|
||||
* The code below is for the real chip. Wont work on FPGA
|
||||
*/
|
||||
/* jr ra */
|
||||
|
||||
#if !defined(CONFIG_AR7240_EMU) && defined(CONFIG_WASP_SUPPORT)
|
||||
#if !defined(CONFIG_ATH_NAND_BR)
|
||||
b ar934x_lowlevel_init
|
||||
#endif
|
||||
#else
|
||||
|
||||
#ifndef CONFIG_HORNET_EMU
|
||||
#if defined(CONFIG_MACH_HORNET)
|
||||
b hornet_pll_init
|
||||
#else
|
||||
wdt_reset:
|
||||
#ifndef CONFIG_AR7240_EMU
|
||||
li $3, -1207566336 # 0xffffffffb8060000
|
||||
ori $4, $3, 0x8
|
||||
lw $2, 0($4)
|
||||
bltz $2, $L6
|
||||
nop
|
||||
ori $5, $3, 0xc
|
||||
|
||||
li $3, 300 # 0x4
|
||||
sw $3, 0($5)
|
||||
li $3, 3 # 0x3
|
||||
sw $3, 0($4)
|
||||
$L3:
|
||||
b $L3
|
||||
nop
|
||||
#endif
|
||||
$L6:
|
||||
nop
|
||||
nop
|
||||
#ifndef CONFIG_AR7240_EMU
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
|
||||
/*
|
||||
* WAR for the bug#55574: Set the CKE (bit 7 in DDR_CONFIG2 register)
|
||||
* to low initially
|
||||
*/
|
||||
li t7, KSEG1ADDR(AR7240_DDR_CONFIG2);
|
||||
lw t8, 0(t7);
|
||||
li t9, 0xffffff7f;
|
||||
and t8, t8, t9;
|
||||
sw t8, 0(t7);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check if the PLL is already set and CPU is Reset
|
||||
*/
|
||||
clk_get(CLOCK_CONTROL_RST_SWITCH_MASK, CLOCK_CONTROL_RST_SWITCH_SHIFT, t6)
|
||||
bne zero, t6, initialize_pll
|
||||
nop
|
||||
|
||||
init_pll_values:
|
||||
li a2,PLL_CONFIG_VAL_F # 0xffffffffbf040000
|
||||
lw a0,0(a2)
|
||||
li v1,PLL_MAGIC # 0xffffffffaabb0000
|
||||
beq a0,v1,read_pll_from_flash
|
||||
nop
|
||||
|
||||
#ifdef CONFIG_SUPPORT_AR7241
|
||||
li t7, KSEG1ADDR(AR7240_REV_ID)
|
||||
lw t8, 0(t7)
|
||||
li t9, AR7240_REV_ID_MASK
|
||||
and t8, t8, t9
|
||||
li v1, AR7241_REV_1_0
|
||||
beq t8,v1,init_7241_pll
|
||||
nop
|
||||
li v1, AR7242_REV_1_0
|
||||
beq t8,v1,init_7241_pll
|
||||
nop
|
||||
bne t8,v1,init_default
|
||||
|
||||
init_7241_pll:
|
||||
pll_clr(PLL_CONFIG_PLL_RESET_MASK)
|
||||
pll_set( (PLL_CONFIG_DDR_DIV_MASK | PLL_CONFIG_AHB_DIV_MASK | PLL_CONFIG_PLL_NOPWD_MASK | PLL_CONFIG_PLL_REF_DIV_MASK | PLL_CONFIG_PLL_DIV_MASK) ,( PLL_7241_CONFIG_PLL_REF_DIV_VAL|PLL_7241_CONFIG_PLL_DIV_VAL|PLL_7241_CONFIG_AHB_DIV_VAL|PLL_7241_CONFIG_DDR_DIV_VAL|PLL_CONFIG_PLL_NOPWD_VAL))
|
||||
pll_clr(PLL_CONFIG_PLL_BYPASS_MASK)
|
||||
b wait_for_pll_update
|
||||
nop
|
||||
|
||||
init_default:
|
||||
#endif
|
||||
|
||||
pll_clr(PLL_CONFIG_PLL_RESET_MASK)
|
||||
pll_set( (PLL_CONFIG_DDR_DIV_MASK | PLL_CONFIG_AHB_DIV_MASK | PLL_CONFIG_PLL_NOPWD_MASK | PLL_CONFIG_PLL_REF_DIV_MASK | PLL_CONFIG_PLL_DIV_MASK) ,( PLL_CONFIG_PLL_REF_DIV_VAL|PLL_CONFIG_PLL_DIV_VAL|PLL_CONFIG_AHB_DIV_VAL|PLL_CONFIG_DDR_DIV_VAL|PLL_CONFIG_PLL_NOPWD_VAL))
|
||||
pll_clr(PLL_CONFIG_PLL_BYPASS_MASK)
|
||||
b wait_for_pll_update
|
||||
nop
|
||||
|
||||
read_pll_from_flash:
|
||||
pll_clr(PLL_CONFIG_PLL_RESET_MASK)
|
||||
pll_set_f((PLL_CONFIG_DDR_DIV_MASK | PLL_CONFIG_AHB_DIV_MASK | PLL_CONFIG_PLL_NOPWD_MASK | PLL_CONFIG_PLL_REF_DIV_MASK | PLL_CONFIG_PLL_DIV_MASK) ,((PLL_CONFIG_VAL_F + 4) | PLL_CONFIG_PLL_NOPWD_VAL))
|
||||
pll_clr(PLL_CONFIG_PLL_BYPASS_MASK)
|
||||
b wait_for_pll_update
|
||||
nop
|
||||
|
||||
|
||||
wait_for_pll_update:
|
||||
pll_get(PLL_CONFIG_PLL_UPDATE_MASK, PLL_CONFIG_PLL_UPDATE_SHIFT, t6)
|
||||
bne zero, t6, wait_for_pll_update
|
||||
nop
|
||||
|
||||
/*
|
||||
* Will cause a reset
|
||||
* The RESET_SWITCH need to be set first and then
|
||||
* set the CLOCK_SWITCH for the CPU to boot properly
|
||||
* after RESET.
|
||||
*/
|
||||
pll_locked:
|
||||
clk_set(CLOCK_CONTROL_RST_SWITCH_MASK, 0x2)
|
||||
clk_set(CLOCK_CONTROL_CLOCK_SWITCH_MASK, 0x1)
|
||||
nop
|
||||
|
||||
/*
|
||||
* When the PLL is already set and CPU is RESET
|
||||
* The code will jump here
|
||||
*/
|
||||
initialize_pll:
|
||||
clk_clr(CLOCK_CONTROL_RST_SWITCH_MASK)
|
||||
clk_clr(CLOCK_CONTROL_CLOCK_SWITCH_MASK)
|
||||
#endif
|
||||
#endif /* CONFIG_MACH_HORNET */
|
||||
#endif /* CONFIG_HORNET_EMU */
|
||||
#endif /* CONFIG_MAC_WASP */
|
||||
jr ra
|
||||
nop
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _PHY_H
|
||||
#define _PHY_H
|
||||
|
||||
#include <config.h>
|
||||
/*
|
||||
* This file defines the interface between MAC and various phy switches.
|
||||
*/
|
||||
#define ag7240_unit2name(_unit) _unit ? "eth1" : "eth0"
|
||||
extern int ag7240_miiphy_read(char *devname, uint32_t phaddr,
|
||||
uint8_t reg);
|
||||
extern int ag7240_miiphy_write(char *devname, uint32_t phaddr,
|
||||
uint8_t reg, uint16_t data);
|
||||
|
||||
#define phy_reg_read(base, addr, reg) \
|
||||
ag7240_miiphy_read(ag7240_unit2name(base), addr, reg)
|
||||
#define phy_reg_write(base, addr, reg, data) \
|
||||
ag7240_miiphy_write(ag7240_unit2name(base), addr, reg, data)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,191 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <part.h>
|
||||
#include <usb.h>
|
||||
#include <fs.h>
|
||||
#include <fat.h>
|
||||
|
||||
#define XMK_STR(x) #x
|
||||
#define MK_STR(x) XMK_STR(x)
|
||||
|
||||
|
||||
void usbboot_indicate_recovery(int type)
|
||||
{
|
||||
// type=0 - before recovery
|
||||
// type=1 - after recovery
|
||||
int cnt = 4; // how many times to blink
|
||||
|
||||
if (type) cnt=2;
|
||||
while(cnt--){
|
||||
ar7240_gpio_led_switch(3, 1);
|
||||
mdelay(500);
|
||||
ar7240_gpio_led_switch(3, 0);
|
||||
mdelay(500);
|
||||
}
|
||||
if (!type) mdelay(500); //wait 0.5s after last blink before recovery
|
||||
}
|
||||
|
||||
int usbboot_boot(char * boot_dev_part, char * boot_file_name)
|
||||
{
|
||||
int fat_read_ret;
|
||||
char* bootm_argv[] = {"bootm", MK_STR(CFG_USB_BOOT_LOAD_ADDR)};
|
||||
|
||||
fs_set_blk_dev ("usb", boot_dev_part, FS_TYPE_FAT);
|
||||
fat_read_ret = do_fat_read_at(boot_file_name,
|
||||
0,
|
||||
CFG_USB_BOOT_LOAD_ADDR,
|
||||
CFG_MAX_USB_BOOT_FILE_SIZE,
|
||||
0);
|
||||
if (fat_read_ret > 0){
|
||||
printf ("Booting image %s (%d bytes) from usb device %s \n",
|
||||
boot_file_name , fat_read_ret, boot_dev_part);
|
||||
do_bootm(NULL, 0 , 2, bootm_argv);
|
||||
}
|
||||
return -1; //Boot failed
|
||||
}
|
||||
|
||||
int usbboot_recovery(char * boot_dev_part, char * boot_file_name)
|
||||
{
|
||||
int fat_read_ret;
|
||||
char flash_cmd [128];
|
||||
char image_size[16];
|
||||
|
||||
fs_set_blk_dev ("usb", boot_dev_part, FS_TYPE_FAT);
|
||||
fat_read_ret = do_fat_read_at(boot_file_name,
|
||||
0,
|
||||
CFG_USB_BOOT_LOAD_ADDR,
|
||||
CFG_MAX_USB_RECOVERY_FILE_SIZE,
|
||||
0);
|
||||
|
||||
if (fat_read_ret > 0){
|
||||
usbboot_indicate_recovery(0);
|
||||
//TODO: check image??
|
||||
printf ("Flashing image %s (%d bytes) from usb device %s \n",
|
||||
boot_file_name , fat_read_ret, boot_dev_part);
|
||||
sprintf(image_size,"%x",fat_read_ret);
|
||||
|
||||
// Example command
|
||||
//erase 0x9f050000 +3FA000; cp.b 0x80060000 0x9f050000 3FA000
|
||||
char* load_addr = MK_STR(CFG_USB_BOOT_LOAD_ADDR);
|
||||
sprintf(flash_cmd,"erase %s +%s; cp.b %s %s %s",
|
||||
CFG_USB_RECOVERY_FW_START_IN_FLASH,
|
||||
image_size,
|
||||
load_addr,
|
||||
CFG_USB_RECOVERY_FW_START_IN_FLASH,
|
||||
image_size);
|
||||
printf ("\nFlashing image\n%s\n", flash_cmd);
|
||||
setenv("recovery_flash_cmd", flash_cmd);
|
||||
int argc_flash=2;
|
||||
char* argv_flash[]={"run", "recovery_flash_cmd"};
|
||||
cmd_tbl_t *cmdtp=NULL;
|
||||
|
||||
int flash_ret = do_run ( cmdtp, 0, argc_flash, argv_flash);
|
||||
printf ("\nFlashing sucsessful. Remove USB storage with recovery image.");
|
||||
usbboot_indicate_recovery(1);
|
||||
do_reset(NULL, 0, 0, NULL);
|
||||
}
|
||||
return -1; //Boot failed
|
||||
}
|
||||
|
||||
int usbboot_scan(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
int i;
|
||||
char part_id[8];
|
||||
block_dev_desc_t *stor_dev = NULL;
|
||||
disk_partition_t *info = NULL;
|
||||
|
||||
char* boot_file_name; //Can include directories eg. "boot/vmlinux.uimage"
|
||||
char* recovery_file_name;
|
||||
char* boot_dev_part;
|
||||
/* boot_dev_part format "<usb device>:<partition>",
|
||||
* eg. "0:1" - frst usb storage device's first partition
|
||||
* */
|
||||
|
||||
boot_file_name = getenv ("bootfile");
|
||||
if (boot_file_name == NULL)
|
||||
boot_file_name = CFG_USB_BOOT_FILENAME;
|
||||
|
||||
recovery_file_name = getenv ("recoveryfile");
|
||||
if (recovery_file_name == NULL)
|
||||
recovery_file_name = CFG_USB_RECOVERY_FILENAME;
|
||||
|
||||
boot_dev_part = getenv ("bootdev");
|
||||
|
||||
usb_stop();
|
||||
|
||||
if (usb_init() < 0)
|
||||
return -1;
|
||||
/* try to recognize storage devices immediately */
|
||||
usb_stor_scan(0);
|
||||
|
||||
int devno = 0;
|
||||
|
||||
//if given device name just boot it
|
||||
if (boot_dev_part != NULL){
|
||||
usbboot_recovery(boot_dev_part, recovery_file_name);
|
||||
usbboot_boot(boot_dev_part, boot_file_name);
|
||||
return -2; //if returns, means boot failed
|
||||
}
|
||||
|
||||
// scan all devices and partitions for boot image
|
||||
for (devno = 0; ; ++devno) {
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
if (stor_dev == NULL)
|
||||
break;
|
||||
|
||||
//try boot from full device (no partitions)
|
||||
sprintf(part_id,"%d:%d", devno, 0);
|
||||
usbboot_recovery(part_id, recovery_file_name);
|
||||
usbboot_boot(part_id, boot_file_name);
|
||||
|
||||
//scan partitions
|
||||
if (stor_dev->part_type != PART_TYPE_DOS)
|
||||
continue;
|
||||
for (i=1; i<=CFG_USB_BOOT_MAX_PARTITIONS_SCAN; i++){
|
||||
printf("start %d size %d name %s\n", info->start, info->size, info->name);
|
||||
printf("SCANNING device %d\n",i);
|
||||
if (get_partition_info_dos(stor_dev, i, info) == 0){
|
||||
sprintf(part_id,"%d:%d", devno, i);
|
||||
usbboot_recovery(part_id, recovery_file_name);
|
||||
usbboot_boot(part_id, boot_file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf ("Boot or recovery image (%s or %s) not found in usb storage\n", boot_file_name, recovery_file_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void do_usb_boot (void){
|
||||
char* boot_mode;
|
||||
int s_force=0, s_gpio=0, s_never = 0;
|
||||
|
||||
boot_mode = getenv ("usbboot");
|
||||
if (boot_mode != NULL){
|
||||
s_force = !(strcmp(boot_mode, "force"));
|
||||
s_gpio = !(strcmp(boot_mode, "gpio"));
|
||||
s_never = !(strcmp(boot_mode, "never"));
|
||||
}
|
||||
|
||||
if ( (s_force && s_never == 0) || (boot_mode == NULL))
|
||||
s_gpio = 1;
|
||||
|
||||
if (s_never){
|
||||
printf("USB boot is disabled in environment\n");
|
||||
return;
|
||||
}
|
||||
if (s_force){
|
||||
printf("USB boot is forced in environment\n");
|
||||
usbboot_scan(0,0,0,0);
|
||||
}
|
||||
if ( s_gpio ){
|
||||
debug("USB GPIO: %d\n", button_read(CFG_USB_BOOT_BUTTON_ID));
|
||||
if (button_read(CFG_USB_BOOT_BUTTON_ID)==1)
|
||||
usbboot_scan(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
usb_boot_file, 5, 1, usbboot_scan,
|
||||
"usb_boot_file - Automatic boot/recovery from file in USB drive\n",
|
||||
" "
|
||||
);
|
|
@ -0,0 +1,113 @@
|
|||
#
|
||||
# (C) Copyright 2004
|
||||
# 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 = libcommon.a
|
||||
|
||||
AOBJS =
|
||||
|
||||
ifeq ($(COMPRESSED_UBOOT),1)
|
||||
COBJS = main.o circbuf.o \
|
||||
cmd_boot.o cmd_bootm.o \
|
||||
cmd_cache.o cmd_console.o \
|
||||
cmd_date.o cmd_dcr.o cmd_display.o \
|
||||
cmd_eeprom.o \
|
||||
cmd_flash.o \
|
||||
cmd_immap.o cmd_itest.o \
|
||||
cmd_mem.o \
|
||||
cmd_mii.o cmd_misc.o \
|
||||
cmd_nand.o cmd_net.o cmd_nvedit.o \
|
||||
cmd_reginfo.o cmd_spi.o \
|
||||
command.o console.o devices.o dlmalloc.o \
|
||||
environment.o env_common.o \
|
||||
env_nowhere.o \
|
||||
exports.o \
|
||||
hush.o lcd.o lists.o \
|
||||
memsize.o miiphybb.o miiphyutil.o \
|
||||
serial.o crc16.o
|
||||
else
|
||||
COBJS = main.o circbuf.o \
|
||||
cmd_autoscript.o \
|
||||
cmd_bdinfo.o cmd_boot.o cmd_bootm.o \
|
||||
cmd_cache.o cmd_console.o \
|
||||
cmd_date.o cmd_diag.o cmd_display.o \
|
||||
cmd_eeprom.o cmd_elf.o cmd_ext2.o \
|
||||
cmd_fat.o cmd_fdc.o cmd_fdos.o cmd_flash.o \
|
||||
cmd_i2c.o cmd_ide.o cmd_immap.o cmd_itest.o \
|
||||
cmd_load.o cmd_log.o \
|
||||
cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \
|
||||
cmd_nand.o cmd_net.o cmd_nvedit.o \
|
||||
cmd_pci.o cmd_pcmcia.o cmd_portio.o \
|
||||
cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o \
|
||||
cmd_usb.o cmd_vfd.o cmd_ethreg.o \
|
||||
command.o console.o devices.o dlmalloc.o \
|
||||
environment.o env_common.o \
|
||||
env_nand.o env_dataflash.o env_flash.o env_eeprom.o \
|
||||
env_nvram.o env_nowhere.o \
|
||||
exports.o ft_build.o \
|
||||
hush.o kgdb.o lcd.o lists.o lynxkdi.o \
|
||||
memsize.o miiphybb.o miiphyutil.o \
|
||||
s_record.o serial.o soft_i2c.o soft_spi.o \
|
||||
usb.o usb_hub.o usb_kbd.o usb_storage.o \
|
||||
crc16.o xyzModem.o
|
||||
endif
|
||||
|
||||
ifndef BOOT_FROM_NAND
|
||||
COBJS += flash.o
|
||||
endif
|
||||
|
||||
ifeq ($(VXWORKS_UBOOT),1)
|
||||
COBJS += cmd_elf.o
|
||||
endif
|
||||
|
||||
OBJS = $(AOBJS) $(COBJS)
|
||||
|
||||
CPPFLAGS += -I..
|
||||
|
||||
ifeq ($(DUAL_FIRMWAREIMAGE_SUPPORT),1)
|
||||
CFLAGS += -DCONFIG_DUALIMAGE_SUPPORT
|
||||
OBJS += cmd_bdr.o
|
||||
endif
|
||||
|
||||
all: $(LIB) $(AOBJS)
|
||||
|
||||
$(LIB): .depend $(OBJS)
|
||||
$(AR) crv $@ $(OBJS)
|
||||
|
||||
environment.o: environment.c ../tools/envcrc
|
||||
$(CC) $(AFLAGS) -Wa,--no-warn \
|
||||
-DENV_CRC=$(shell ../tools/envcrc) \
|
||||
-c -o $@ environment.c
|
||||
|
||||
../tools/envcrc:
|
||||
$(MAKE) -C ../tools
|
||||
|
||||
#########################################################################
|
||||
|
||||
.depend: Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@
|
||||
|
||||
sinclude .depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Gerry Hamel, geh@ti.com, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <circbuf.h>
|
||||
|
||||
|
||||
int buf_init (circbuf_t * buf, unsigned int size)
|
||||
{
|
||||
assert (buf != NULL);
|
||||
|
||||
buf->size = 0;
|
||||
buf->totalsize = size;
|
||||
buf->data = (char *) malloc (sizeof (char) * size);
|
||||
assert (buf->data != NULL);
|
||||
|
||||
buf->top = buf->data;
|
||||
buf->tail = buf->data;
|
||||
buf->end = &(buf->data[size]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int buf_free (circbuf_t * buf)
|
||||
{
|
||||
assert (buf != NULL);
|
||||
assert (buf->data != NULL);
|
||||
|
||||
free (buf->data);
|
||||
memset (buf, 0, sizeof (circbuf_t));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int buf_pop (circbuf_t * buf, char *dest, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
char *p = buf->top;
|
||||
|
||||
assert (buf != NULL);
|
||||
assert (dest != NULL);
|
||||
|
||||
/* Cap to number of bytes in buffer */
|
||||
if (len > buf->size)
|
||||
len = buf->size;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
dest[i] = *p++;
|
||||
/* Bounds check. */
|
||||
if (p == buf->end) {
|
||||
p = buf->data;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update 'top' pointer */
|
||||
buf->top = p;
|
||||
buf->size -= len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int buf_push (circbuf_t * buf, const char *src, unsigned int len)
|
||||
{
|
||||
/* NOTE: this function allows push to overwrite old data. */
|
||||
unsigned int i;
|
||||
char *p = buf->tail;
|
||||
|
||||
assert (buf != NULL);
|
||||
assert (src != NULL);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
*p++ = src[i];
|
||||
if (p == buf->end) {
|
||||
p = buf->data;
|
||||
}
|
||||
/* Make sure pushing too much data just replaces old data */
|
||||
if (buf->size < buf->totalsize) {
|
||||
buf->size++;
|
||||
} else {
|
||||
buf->top++;
|
||||
if (buf->top == buf->end) {
|
||||
buf->top = buf->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update 'tail' pointer */
|
||||
buf->tail = p;
|
||||
|
||||
return len;
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Kyle Harris, kharris@nexus-tech.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
|
||||
*/
|
||||
|
||||
/*
|
||||
* autoscript allows a remote host to download a command file and,
|
||||
* optionally, binary data for automatically updating the target. For
|
||||
* example, you create a new kernel image and want the user to be
|
||||
* able to simply download the image and the machine does the rest.
|
||||
* The kernel image is postprocessed with mkimage, which creates an
|
||||
* image with a script file prepended. If enabled, autoscript will
|
||||
* verify the script and contents of the download and execute the
|
||||
* script portion. This would be responsible for erasing flash,
|
||||
* copying the new image, and rebooting the machine.
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/byteorder.h>
|
||||
#if defined(CONFIG_8xx)
|
||||
#include <mpc8xx.h>
|
||||
#endif
|
||||
#ifdef CFG_HUSH_PARSER
|
||||
#include <hush.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AUTOSCRIPT) || \
|
||||
(CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT )
|
||||
|
||||
extern image_header_t header; /* from cmd_bootm.c */
|
||||
int
|
||||
autoscript (ulong addr)
|
||||
{
|
||||
ulong crc, data, len;
|
||||
image_header_t *hdr = &header;
|
||||
ulong *len_ptr;
|
||||
char *cmd;
|
||||
int rcode = 0;
|
||||
int verify;
|
||||
|
||||
cmd = getenv ("verify");
|
||||
verify = (cmd && (*cmd == 'n')) ? 0 : 1;
|
||||
|
||||
|
||||
memmove (hdr, (char *)addr, sizeof(image_header_t));
|
||||
|
||||
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
|
||||
puts ("Bad magic number\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
crc = ntohl(hdr->ih_hcrc);
|
||||
hdr->ih_hcrc = 0;
|
||||
len = sizeof (image_header_t);
|
||||
data = (ulong)hdr;
|
||||
if (crc32(0, (uchar *)data, len) != crc) {
|
||||
puts ("Bad header crc\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
data = addr + sizeof(image_header_t);
|
||||
len = ntohl(hdr->ih_size);
|
||||
|
||||
if (verify) {
|
||||
if (crc32(0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) {
|
||||
puts ("Bad data crc\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hdr->ih_type != IH_TYPE_SCRIPT) {
|
||||
puts ("Bad image type\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get length of script */
|
||||
len_ptr = (ulong *)data;
|
||||
|
||||
if ((len = ntohl(*len_ptr)) == 0) {
|
||||
puts ("Empty Script\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug ("** Script length: %ld\n", len);
|
||||
|
||||
if ((cmd = malloc (len + 1)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (*len_ptr++);
|
||||
|
||||
/* make sure cmd is null terminated */
|
||||
memmove (cmd, (char *)len_ptr, len);
|
||||
*(cmd + len) = 0;
|
||||
|
||||
#ifdef CFG_HUSH_PARSER /*?? */
|
||||
rcode = parse_string_outer (cmd, FLAG_PARSE_SEMICOLON);
|
||||
#else
|
||||
{
|
||||
char *line = cmd;
|
||||
char *next = cmd;
|
||||
|
||||
/*
|
||||
* break into individual lines,
|
||||
* and execute each line;
|
||||
* terminate on error.
|
||||
*/
|
||||
while (*next) {
|
||||
if (*next == '\n') {
|
||||
*next = '\0';
|
||||
/* run only non-empty commands */
|
||||
if ((next - line) > 1) {
|
||||
debug ("** exec: \"%s\"\n",
|
||||
line);
|
||||
if (run_command (line, 0) < 0) {
|
||||
rcode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
line = next + 1;
|
||||
}
|
||||
++next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free (cmd);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AUTOSCRIPT || CFG_CMD_AUTOSCRIPT */
|
||||
/**************************************************/
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT)
|
||||
int
|
||||
do_autoscript (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr;
|
||||
int rcode;
|
||||
|
||||
if (argc < 2) {
|
||||
addr = CFG_LOAD_ADDR;
|
||||
} else {
|
||||
addr = simple_strtoul (argv[1],0,16);
|
||||
}
|
||||
|
||||
printf ("## Executing script at %08lx\n",addr);
|
||||
rcode = autoscript (addr);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_AUTOSCRIPT)
|
||||
U_BOOT_CMD(
|
||||
autoscr, 2, 0, do_autoscript,
|
||||
"autoscr - run script from memory\n",
|
||||
"[addr] - run script starting at addr"
|
||||
" - A valid autoscr header must be present\n"
|
||||
);
|
||||
#endif /* CFG_CMD_AUTOSCRIPT */
|
||||
|
||||
#endif /* CONFIG_AUTOSCRIPT || CFG_CMD_AUTOSCRIPT */
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Boot support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <net.h> /* for print_IPaddr */
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BDI)
|
||||
static void print_num(const char *, ulong);
|
||||
|
||||
#ifndef CONFIG_ARM /* PowerPC and other */
|
||||
|
||||
#ifdef CONFIG_PPC
|
||||
static void print_str(const char *, const char *);
|
||||
|
||||
int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
bd_t *bd = gd->bd;
|
||||
char buf[32];
|
||||
|
||||
#ifdef DEBUG
|
||||
print_num ("bd address", (ulong)bd );
|
||||
#endif
|
||||
print_num ("memstart", bd->bi_memstart );
|
||||
print_num ("memsize", bd->bi_memsize );
|
||||
print_num ("flashstart", bd->bi_flashstart );
|
||||
print_num ("flashsize", bd->bi_flashsize );
|
||||
print_num ("flashoffset", bd->bi_flashoffset );
|
||||
print_num ("sramstart", bd->bi_sramstart );
|
||||
print_num ("sramsize", bd->bi_sramsize );
|
||||
#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || \
|
||||
defined(CONFIG_8260) || defined(CONFIG_E500)
|
||||
print_num ("immr_base", bd->bi_immr_base );
|
||||
#endif
|
||||
print_num ("bootflags", bd->bi_bootflags );
|
||||
#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
|
||||
defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300) || \
|
||||
defined(CONFIG_440EP) || defined(CONFIG_440GR)
|
||||
print_str ("procfreq", strmhz(buf, bd->bi_procfreq));
|
||||
print_str ("plb_busfreq", strmhz(buf, bd->bi_plb_busfreq));
|
||||
#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300) || \
|
||||
defined(CONFIG_440EP) || defined(CONFIG_440GR)
|
||||
print_str ("pci_busfreq", strmhz(buf, bd->bi_pci_busfreq));
|
||||
#endif
|
||||
#else /* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300, CONFIG_440EP CONFIG_440GR */
|
||||
#if defined(CONFIG_CPM2)
|
||||
print_str ("vco", strmhz(buf, bd->bi_vco));
|
||||
print_str ("sccfreq", strmhz(buf, bd->bi_sccfreq));
|
||||
print_str ("brgfreq", strmhz(buf, bd->bi_brgfreq));
|
||||
#endif
|
||||
print_str ("intfreq", strmhz(buf, bd->bi_intfreq));
|
||||
#if defined(CONFIG_CPM2)
|
||||
print_str ("cpmfreq", strmhz(buf, bd->bi_cpmfreq));
|
||||
#endif
|
||||
print_str ("busfreq", strmhz(buf, bd->bi_busfreq));
|
||||
#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300, CONFIG_440EP CONFIG_440GR */
|
||||
#if defined(CONFIG_MPC8220)
|
||||
print_str ("inpfreq", strmhz(buf, bd->bi_inpfreq));
|
||||
print_str ("flbfreq", strmhz(buf, bd->bi_flbfreq));
|
||||
print_str ("pcifreq", strmhz(buf, bd->bi_pcifreq));
|
||||
print_str ("vcofreq", strmhz(buf, bd->bi_vcofreq));
|
||||
print_str ("pevfreq", strmhz(buf, bd->bi_pevfreq));
|
||||
#endif
|
||||
|
||||
puts ("ethaddr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_HAS_ETH1)
|
||||
puts ("\neth1addr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enet1addr[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HAS_ETH2)
|
||||
puts ("\neth2addr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enet2addr[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HAS_ETH3)
|
||||
puts ("\neth3addr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enet3addr[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HERMES
|
||||
print_str ("ethspeed", strmhz(buf, bd->bi_ethspeed));
|
||||
#endif
|
||||
puts ("\nIP addr = "); print_IPaddr (bd->bi_ip_addr);
|
||||
printf ("\nbaudrate = %6ld bps\n", bd->bi_baudrate );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_NIOS) /* NIOS*/
|
||||
|
||||
int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
bd_t *bd = gd->bd;
|
||||
|
||||
print_num ("memstart", (ulong)bd->bi_memstart);
|
||||
print_num ("memsize", (ulong)bd->bi_memsize);
|
||||
print_num ("flashstart", (ulong)bd->bi_flashstart);
|
||||
print_num ("flashsize", (ulong)bd->bi_flashsize);
|
||||
print_num ("flashoffset", (ulong)bd->bi_flashoffset);
|
||||
|
||||
puts ("ethaddr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
|
||||
}
|
||||
puts ("\nip_addr = ");
|
||||
print_IPaddr (bd->bi_ip_addr);
|
||||
printf ("\nbaudrate = %ld bps\n", bd->bi_baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_NIOS2) /* Nios-II */
|
||||
|
||||
int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
bd_t *bd = gd->bd;
|
||||
|
||||
print_num ("mem start", (ulong)bd->bi_memstart);
|
||||
print_num ("mem size", (ulong)bd->bi_memsize);
|
||||
print_num ("flash start", (ulong)bd->bi_flashstart);
|
||||
print_num ("flash size", (ulong)bd->bi_flashsize);
|
||||
print_num ("flash offset", (ulong)bd->bi_flashoffset);
|
||||
|
||||
#if defined(CFG_SRAM_BASE)
|
||||
print_num ("sram start", (ulong)bd->bi_sramstart);
|
||||
print_num ("sram size", (ulong)bd->bi_sramsize);
|
||||
#endif
|
||||
|
||||
#if defined(CFG_CMD_NET)
|
||||
puts ("ethaddr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
|
||||
}
|
||||
puts ("\nip_addr = ");
|
||||
print_IPaddr (bd->bi_ip_addr);
|
||||
#endif
|
||||
|
||||
printf ("\nbaudrate = %ld bps\n", bd->bi_baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* ! PPC, which leaves MIPS */
|
||||
|
||||
int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
bd_t *bd = gd->bd;
|
||||
|
||||
print_num ("boot_params", (ulong)bd->bi_boot_params);
|
||||
print_num ("memstart", (ulong)bd->bi_memstart);
|
||||
print_num ("memsize", (ulong)bd->bi_memsize);
|
||||
print_num ("flashstart", (ulong)bd->bi_flashstart);
|
||||
print_num ("flashsize", (ulong)bd->bi_flashsize);
|
||||
print_num ("flashoffset", (ulong)bd->bi_flashoffset);
|
||||
|
||||
puts ("ethaddr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
|
||||
}
|
||||
puts ("\nip_addr = ");
|
||||
print_IPaddr (bd->bi_ip_addr);
|
||||
printf ("\nbaudrate = %d bps\n", bd->bi_baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MIPS */
|
||||
|
||||
#else /* ARM */
|
||||
|
||||
int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
bd_t *bd = gd->bd;
|
||||
|
||||
print_num ("arch_number", bd->bi_arch_number);
|
||||
print_num ("env_t", (ulong)bd->bi_env);
|
||||
print_num ("boot_params", (ulong)bd->bi_boot_params);
|
||||
|
||||
for (i=0; i<CONFIG_NR_DRAM_BANKS; ++i) {
|
||||
print_num("DRAM bank", i);
|
||||
print_num("-> start", bd->bi_dram[i].start);
|
||||
print_num("-> size", bd->bi_dram[i].size);
|
||||
}
|
||||
|
||||
puts ("ethaddr =");
|
||||
for (i=0; i<6; ++i) {
|
||||
printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
|
||||
}
|
||||
puts ( "\n"
|
||||
"ip_addr = ");
|
||||
print_IPaddr (bd->bi_ip_addr);
|
||||
printf ("\n"
|
||||
"baudrate = %d bps\n", bd->bi_baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
|
||||
|
||||
static void print_num(const char *name, ulong value)
|
||||
{
|
||||
printf ("%-12s= 0x%08lX\n", name, value);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC
|
||||
static void print_str(const char *name, const char *str)
|
||||
{
|
||||
printf ("%-12s= %6s MHz\n", name, str);
|
||||
}
|
||||
#endif /* CONFIG_PPC */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
U_BOOT_CMD(
|
||||
bdinfo, 1, 1, do_bdinfo,
|
||||
"bdinfo - print Board Info structure\n",
|
||||
NULL
|
||||
);
|
||||
#endif /* CFG_CMD_BDI */
|
|
@ -0,0 +1,427 @@
|
|||
/* The module is designed to support a BDR with the highest sequence number in the flash.
|
||||
* If it is successfule, bootloader will choose the BDR to startup.
|
||||
*
|
||||
* Author Tos Xu April 22, 2009
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <flash.h>
|
||||
#include <malloc.h>
|
||||
#include <configs/ap93-hgw.h>
|
||||
|
||||
#define TOTALFLASHSIZE CFG_FLASH_SIZE
|
||||
#define FLASHSTARTADDRESS CFG_FLASH_BASE
|
||||
#define FLASH_BLOCK_SIZE CFG_FLASH_SECTOR_SIZE
|
||||
/*
|
||||
* Boot description record definitions
|
||||
*/
|
||||
#define BDRWordSize 4
|
||||
|
||||
#define BDRHeaderNWords 4
|
||||
#define BDRHeaderNBytes (BDRHeaderNWords * BDRWordSize)
|
||||
#define BDRHeader_OffsetMagic 0 /* bytes */
|
||||
#define BDRHeader_OffsetSize 4 /* bytes */
|
||||
#define BDRHeader_OffsetChecksum 8 /* bytes */
|
||||
#define BDRHeader_OffsetSequence 12 /* bytes */
|
||||
#define BDR_BeginMagic 0xFEEDCAFE
|
||||
|
||||
#define BDRTailerNWords 4
|
||||
#define BDRTailerNBytes (BDRTailerNWords * BDRWordSize)
|
||||
#define BDRTailer_OffsetMagic 4 /* bytes before end */
|
||||
#define BDRTailer_OffsetSize 8 /* bytes before end */
|
||||
#define BDR_EndMagic 0xFEEDFADE
|
||||
|
||||
#define TagWordToSelf(TagWord) (((TagWord)>>24)&0xff)
|
||||
#define TagWordToTag(TagWord) (((TagWord)>>16)&0xff)
|
||||
#define TagWordToNWords(TagWord) ((TagWord)&0x3fff)
|
||||
|
||||
#define BDRTag_STOP 1
|
||||
#define BDRTag_BOOTADDR 2
|
||||
#define BDRTag_BOOTARGS 3
|
||||
#define BDRTag_REQUESTNUMBER 4
|
||||
|
||||
#define BDR_SIZE 256
|
||||
|
||||
unsigned int bdr_bootaddr = 0;
|
||||
unsigned int bdr_seq = 0;
|
||||
char bdr_bootarg[512];
|
||||
|
||||
extern flash_info_t flash_info[];
|
||||
/*
|
||||
* Boot description records can be written at begin and/or end of each
|
||||
* 64KB block of flash (regardless of erase block size)
|
||||
*/
|
||||
#define BDRBlockSize 0x10000
|
||||
|
||||
#define flashaddr(x) (char *)((volatile char *)0xbf000000+(x))
|
||||
|
||||
|
||||
/* big endian -- extract big endian integer from byte stream
|
||||
*/
|
||||
static inline unsigned big_endian(unsigned char *p)
|
||||
{
|
||||
return ((p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]);
|
||||
}
|
||||
|
||||
/*
|
||||
* fix endian
|
||||
*/
|
||||
static inline unsigned fix_endian(unsigned word)
|
||||
{
|
||||
return word;
|
||||
}
|
||||
|
||||
/*
|
||||
* Big endian in the flash.
|
||||
* 0:OK,-1:parameters error,-2: NO STOP tag.
|
||||
*/
|
||||
int parse_tag(int * bdrp,int size){
|
||||
|
||||
int tags = 0,tagname = 0,tagsize = 0,tagno = 0;
|
||||
int i = 0;
|
||||
unsigned data;
|
||||
|
||||
// Reset the value to prevent the failure of parsing the bdr.
|
||||
bdr_bootaddr = 0;
|
||||
memset(bdr_bootarg,0,sizeof(bdr_bootarg));
|
||||
|
||||
for(i = 0;i<size;i++)
|
||||
{
|
||||
data = big_endian((char *)bdrp);
|
||||
printf(" -Tag 0x%x.\n",*bdrp);
|
||||
tagname = (data>>16)&0xff;
|
||||
tagno = (data>>24)&0xff;
|
||||
tagsize = (data & 0xffff) - 1;
|
||||
|
||||
if((tags != tagno)||(tagsize<0)) return -1;
|
||||
|
||||
switch(tagname)
|
||||
{
|
||||
case BDRTag_STOP:
|
||||
if(tagsize==0) return 0;
|
||||
else return -1;
|
||||
|
||||
case BDRTag_BOOTADDR:
|
||||
bdrp++;
|
||||
if(tagsize==1){
|
||||
bdr_bootaddr = big_endian((char *)bdrp);
|
||||
printf(" --Boot address:0x%x at sequence 0x%x.\n",bdr_bootaddr,bdr_seq);
|
||||
bdrp++;
|
||||
break;
|
||||
}else return -1;
|
||||
|
||||
case BDRTag_BOOTARGS:
|
||||
bdrp++;
|
||||
if(tagsize < 130){
|
||||
memcpy(bdr_bootarg,(char *)bdrp,tagsize * BDRWordSize);
|
||||
bdrp += tagsize;
|
||||
break;
|
||||
}else return -1;
|
||||
|
||||
case BDRTag_REQUESTNUMBER:
|
||||
bdrp += tagsize +1;
|
||||
break;
|
||||
|
||||
default:
|
||||
bdrp += tagsize + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
tags++;
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* findBDRstart -- look for BDR at the beginning of 64KB of flash,
|
||||
* return sequence no.
|
||||
* Return 0 if not found (which is not a valid sequence number).
|
||||
*
|
||||
* This is used for searching for existing sequence number so we
|
||||
* can be sure to have a larger one.
|
||||
* Sequence numbers are in BDRs (Boot Description Records) which
|
||||
* can be at the begin or end of any 64KB section of flash
|
||||
* (regardless of the erase block size).
|
||||
*/
|
||||
|
||||
unsigned findBDRstart(int offset)
|
||||
{
|
||||
unsigned magic1;
|
||||
unsigned magic2;
|
||||
unsigned size;
|
||||
unsigned sequence;
|
||||
unsigned char bottom[BDRHeaderNBytes];
|
||||
unsigned char top[BDRTailerNBytes];
|
||||
unsigned topoffset;
|
||||
unsigned bdrblock[BDR_SIZE];
|
||||
|
||||
memcpy(bottom, flashaddr(offset),sizeof(bottom));
|
||||
memcpy(bdrblock,flashaddr(offset),sizeof(bdrblock));
|
||||
magic1 = big_endian(bottom + BDRHeader_OffsetMagic);
|
||||
|
||||
if (magic1 != BDR_BeginMagic)
|
||||
return 0;
|
||||
|
||||
size = BDRWordSize*big_endian( bottom + BDRHeader_OffsetSize);
|
||||
|
||||
if (size <= BDRHeaderNBytes+BDRTailerNBytes)
|
||||
return 0;
|
||||
|
||||
if (size >= BDRBlockSize)
|
||||
return 0;
|
||||
|
||||
topoffset = offset + size;
|
||||
|
||||
memcpy(top, flashaddr(topoffset-sizeof(top)),sizeof(top));
|
||||
|
||||
magic2 = big_endian(top + sizeof(top)-BDRTailer_OffsetMagic);
|
||||
if (magic2 != BDR_EndMagic)
|
||||
return 0;
|
||||
|
||||
if (BDRWordSize*big_endian(
|
||||
top+sizeof(top)-BDRTailer_OffsetSize) != size)
|
||||
return 0;
|
||||
|
||||
sequence = big_endian(bottom + BDRHeader_OffsetSequence);
|
||||
|
||||
if (sequence == 0 || sequence == 0xffffffff)
|
||||
return 0; /* invalid */
|
||||
|
||||
printf("Found starting sequence: 0x%x in offset 0x%x.\n",sequence,offset);
|
||||
if(sequence > bdr_seq){
|
||||
bdr_seq = sequence;
|
||||
parse_tag(bdrblock + BDRHeaderNWords,BDR_SIZE);
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
unsigned findBDRend(int offset) /* offset of begin of 64KB section */
|
||||
{
|
||||
unsigned magic1;
|
||||
unsigned magic2;
|
||||
unsigned size;
|
||||
unsigned sequence;
|
||||
unsigned char bottom[BDRHeaderNBytes];
|
||||
unsigned char top[BDRTailerNBytes];
|
||||
unsigned topoffset;
|
||||
unsigned bottomoffset;
|
||||
unsigned bdrblock[BDR_SIZE];
|
||||
|
||||
topoffset = offset + BDRBlockSize;
|
||||
|
||||
memcpy(top, flashaddr(topoffset-sizeof(top)),sizeof(top));
|
||||
memcpy(bdrblock, flashaddr(topoffset-sizeof(bdrblock)),sizeof(bdrblock));
|
||||
|
||||
magic2 = big_endian(top + sizeof(top)-BDRTailer_OffsetMagic);
|
||||
|
||||
if (magic2 != BDR_EndMagic)
|
||||
return 0;
|
||||
|
||||
size = BDRWordSize*big_endian(top+sizeof(top)-BDRTailer_OffsetSize);
|
||||
|
||||
if (size <= BDRHeaderNBytes+BDRTailerNBytes)
|
||||
return 0;
|
||||
|
||||
if (size >= BDRBlockSize)
|
||||
return 0;
|
||||
|
||||
bottomoffset = topoffset - size;
|
||||
|
||||
memcpy(bottom, flashaddr(bottomoffset),sizeof(bottom));
|
||||
|
||||
magic1 = big_endian(bottom + BDRHeader_OffsetMagic);
|
||||
|
||||
if (magic1 != BDR_BeginMagic)
|
||||
return 0;
|
||||
|
||||
if (BDRWordSize*big_endian(bottom + BDRHeader_OffsetSize) != size)
|
||||
return 0;
|
||||
|
||||
sequence = big_endian(bottom+BDRHeader_OffsetSequence);
|
||||
|
||||
if (sequence == 0 || sequence == 0xffffffff)
|
||||
return 0; /* invalid */
|
||||
|
||||
printf("Found end sequence: 0x%x in offset 0x%x.\n",sequence,offset);
|
||||
if(sequence > bdr_seq){
|
||||
bdr_seq = sequence;
|
||||
parse_tag(bdrblock + BDRTailerNWords,BDR_SIZE);
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
|
||||
/* return 0: no existing valid Boot Description Recorder
|
||||
* 1: Found a valid DBR and set bootm and bootarg.
|
||||
*/
|
||||
unsigned findbdr(unsigned int flashaddr){
|
||||
int offset = 0;
|
||||
char buf[64];
|
||||
|
||||
if(flashaddr >= FLASHSTARTADDRESS) flashaddr -= FLASHSTARTADDRESS;
|
||||
|
||||
printf("findbdr flashaddr 0x%x.\n",flashaddr);
|
||||
bdr_seq = 0;
|
||||
bdr_bootaddr = 0xffffffff;
|
||||
memset(bdr_bootarg,0,sizeof(bdr_bootarg));
|
||||
|
||||
for(offset =flashaddr;offset < TOTALFLASHSIZE;offset += BDRBlockSize)
|
||||
{
|
||||
findBDRstart(offset);
|
||||
findBDRend(offset);
|
||||
}
|
||||
|
||||
// if bootaddr is equal to 0xffffffff or 0x0, it is not valid.
|
||||
if(bdr_seq == 0||bdr_bootaddr==0xffffffff||bdr_bootaddr==0x0){
|
||||
printf("Failed to find a good BDR at seq 0x%x.\n",bdr_seq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(bdr_bootaddr < TOTALFLASHSIZE) bdr_bootaddr |= FLASHSTARTADDRESS;
|
||||
sprintf(buf,"%s 0x%x","bootm",bdr_bootaddr);
|
||||
setenv("bootcmd",buf);
|
||||
setenv("bootargs",bdr_bootarg);
|
||||
printf("Got a good Boot Descriptor Record.\n -Sequence:0x%x.\n",bdr_seq);
|
||||
printf(" -Boot address: 0x%x.\n",bdr_bootaddr);
|
||||
if(strlen(bdr_bootarg) < 512)
|
||||
printf(" -Boot arguments: %s.\n",bdr_bootarg);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int do_findbdr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
unsigned int addr;
|
||||
|
||||
if(argc < 2)
|
||||
err = findbdr(0);
|
||||
else{
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
err = findbdr(addr);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* flashaddr is the aboslute address.(0xbf.....)
|
||||
*/
|
||||
static unsigned writebdr(unsigned int flashaddr,unsigned bootaddr,char * cmdline){
|
||||
unsigned bdrblock[BDR_SIZE];
|
||||
unsigned * bdrp = bdrblock;
|
||||
unsigned flash_offset = flashaddr - FLASHSTARTADDRESS;
|
||||
int err;
|
||||
unsigned seq;
|
||||
unsigned tags;
|
||||
char * p;
|
||||
char buffer[64];
|
||||
|
||||
//Make sure the flashaddr is located at X*1024.
|
||||
if(flashaddr &0x3ff) return 1;
|
||||
|
||||
err = findbdr(0);
|
||||
seq = bdr_seq + 1;
|
||||
|
||||
bdrp[0] = fix_endian(BDR_BeginMagic);
|
||||
bdrp[BDR_SIZE-1] = fix_endian(BDR_EndMagic);
|
||||
bdrp[1] = bdrp[BDR_SIZE-2] = fix_endian(BDR_SIZE);
|
||||
bdrp[2] = 0;
|
||||
bdrp[3] = seq;
|
||||
|
||||
bdrp += 4;
|
||||
tags = 0;
|
||||
|
||||
*bdrp++ = fix_endian(tags++<<24| BDRTag_REQUESTNUMBER<<16|2);
|
||||
*bdrp++ = fix_endian(0);//request number.
|
||||
|
||||
*bdrp++ = fix_endian(tags++<<24| BDRTag_BOOTADDR <<16|2);
|
||||
*bdrp++ = fix_endian(bootaddr);//bootaddr.
|
||||
|
||||
|
||||
*bdrp++ = fix_endian(tags++<<24| BDRTag_BOOTARGS <<16|(1+sizeof(bdr_bootarg)/sizeof(int)));
|
||||
memcpy(bdrp,cmdline,sizeof(bdr_bootarg));
|
||||
bdrp += sizeof(bdr_bootarg)/sizeof(int);//bootarg.
|
||||
|
||||
*bdrp++ = fix_endian(tags++<<24| BDRTag_STOP<<16|1);//STOP tag
|
||||
p = (char *)malloc(FLASH_BLOCK_SIZE);
|
||||
|
||||
memcpy(p,(char *)(((unsigned int )flashaddr/FLASH_BLOCK_SIZE )* FLASH_BLOCK_SIZE),FLASH_BLOCK_SIZE);
|
||||
memcpy(p + ((unsigned int )flashaddr%FLASH_BLOCK_SIZE), bdrblock,BDR_SIZE * 4);
|
||||
|
||||
flash_erase(&flash_info[0],flash_offset/FLASH_BLOCK_SIZE,flash_offset/FLASH_BLOCK_SIZE);
|
||||
err = flash_write(p,((unsigned int )flashaddr/FLASH_BLOCK_SIZE )* FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE);
|
||||
|
||||
free(p);
|
||||
|
||||
if(err){
|
||||
flash_perror(err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(memcmp((char *)flashaddr,bdrblock,BDR_SIZE * 4)){
|
||||
printf("Error when writing bdr into flash.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("BDR has been successfully written.\n");
|
||||
printf("BDR boot address: 0x%x.\n",bootaddr);
|
||||
printf("BDR boot arg: %s.\n",cmdline);
|
||||
|
||||
sprintf(buffer,"%s 0x%x","bootm",bootaddr);
|
||||
setenv("bootcmd",buffer);
|
||||
setenv("bootargs",cmdline);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_writebdr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
unsigned int flashaddr;
|
||||
unsigned int bootaddr;
|
||||
char cmd[512];
|
||||
|
||||
char * s = getenv("bootargs");
|
||||
|
||||
printf("do_writebdr :: size %d bootargs = %s .\n",sizeof(s),s);
|
||||
if(argc < 2)
|
||||
return 1;
|
||||
else{
|
||||
flashaddr = simple_strtoul(argv[1], NULL, 16);
|
||||
if(argc == 3 ) bootaddr = simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
if(flashaddr < TOTALFLASHSIZE) flashaddr |= FLASHSTARTADDRESS;
|
||||
if(flashaddr < (FLASHSTARTADDRESS|0x80000)) return 1;
|
||||
memset(cmd,0,sizeof(cmd));
|
||||
memcpy(cmd,s,sizeof(cmd));
|
||||
//printf("do_writebdr :: bdr_bootargs = %s size %d.\n",bdr_bootarg,sizeof(bdr_bootarg));
|
||||
err = writebdr(flashaddr,bootaddr,cmd);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
writebdr, CFG_MAXARGS, 1, do_writebdr,
|
||||
"writebdr- write a valid bdr in the flash based on existing sequences\n",
|
||||
"[writebdr [arg ...]]\n write a valid bdr based on existing sequences at the designed address - \n"
|
||||
"\tpassing arguments 'flash_offset, bootaddr'; you may assign the flash address,\n"
|
||||
"\t'bootaddr' can be ignored or set it.\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
findbdr, CFG_MAXARGS, 1, do_findbdr,
|
||||
"findbdr - find a valid bdr with the highest sequence in the flash\n",
|
||||
"[findbdr [arg ...]]\n find a valid bdr with the highest sequence in the flash from the starting address - \n"
|
||||
"\tpassing arguments 'arg ...'; you may assign the address or not,\n"
|
||||
"\t'arg' can be the starting address of search.\n"
|
||||
);
|
||||
|
||||
|
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
* BedBug Functions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <net.h>
|
||||
#include <bedbug/type.h>
|
||||
#include <bedbug/bedbug.h>
|
||||
#include <bedbug/regs.h>
|
||||
#include <bedbug/ppc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
extern void show_regs __P ((struct pt_regs *));
|
||||
extern int run_command __P ((const char *, int));
|
||||
extern char console_buffer[];
|
||||
|
||||
ulong dis_last_addr = 0; /* Last address disassembled */
|
||||
ulong dis_last_len = 20; /* Default disassembler length */
|
||||
CPU_DEBUG_CTX bug_ctx; /* Bedbug context structure */
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* U-Boot's puts function does not append a newline, so the bedbug stuff
|
||||
* will use this for the output of the dis/assembler.
|
||||
* ====================================================================== */
|
||||
|
||||
int bedbug_puts (const char *str)
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
printf ("%s\r\n", str);
|
||||
return 0;
|
||||
} /* bedbug_puts */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Initialize the bug_ctx structure used by the bedbug debugger. This is
|
||||
* specific to the CPU since each has different debug registers and
|
||||
* settings.
|
||||
* ====================================================================== */
|
||||
|
||||
void bedbug_init (void)
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_4xx)
|
||||
void bedbug405_init (void);
|
||||
|
||||
bedbug405_init ();
|
||||
#elif defined(CONFIG_8xx)
|
||||
void bedbug860_init (void);
|
||||
|
||||
bedbug860_init ();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260)
|
||||
/* Processors that are 603e core based */
|
||||
void bedbug603e_init (void);
|
||||
|
||||
bedbug603e_init ();
|
||||
#endif
|
||||
|
||||
return;
|
||||
} /* bedbug_init */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Entry point from the interpreter to the disassembler. Repeated calls
|
||||
* will resume from the last disassembled address.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_dis (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr; /* Address to start disassembly from */
|
||||
ulong len; /* # of instructions to disassemble */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
/* Setup to go from the last address if none is given */
|
||||
addr = dis_last_addr;
|
||||
len = dis_last_len;
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0) {
|
||||
/* New command */
|
||||
addr = simple_strtoul (argv[1], NULL, 16);
|
||||
|
||||
/* If an extra param is given then it is the length */
|
||||
if (argc > 2)
|
||||
len = simple_strtoul (argv[2], NULL, 16);
|
||||
}
|
||||
|
||||
/* Run the disassembler */
|
||||
disppc ((unsigned char *) addr, 0, len, bedbug_puts, F_RADHEX);
|
||||
|
||||
dis_last_addr = addr + (len * 4);
|
||||
dis_last_len = len;
|
||||
return 0;
|
||||
} /* do_bedbug_dis */
|
||||
|
||||
U_BOOT_CMD (ds, 3, 1, do_bedbug_dis,
|
||||
"ds - disassemble memory\n",
|
||||
"ds <address> [# instructions]\n");
|
||||
|
||||
/* ======================================================================
|
||||
* Entry point from the interpreter to the assembler. Assembles
|
||||
* instructions in consecutive memory locations until a '.' (period) is
|
||||
* entered on a line by itself.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_asm (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
long mem_addr; /* Address to assemble into */
|
||||
unsigned long instr; /* Machine code for text */
|
||||
char prompt[15]; /* Prompt string for user input */
|
||||
int asm_err; /* Error code from the assembler */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
int rcode = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf ("\nEnter '.' when done\n");
|
||||
mem_addr = simple_strtoul (argv[1], NULL, 16);
|
||||
|
||||
while (1) {
|
||||
putc ('\n');
|
||||
disppc ((unsigned char *) mem_addr, 0, 1, bedbug_puts,
|
||||
F_RADHEX);
|
||||
|
||||
sprintf (prompt, "%08lx: ", mem_addr);
|
||||
readline (prompt);
|
||||
|
||||
if (console_buffer[0] && strcmp (console_buffer, ".")) {
|
||||
if ((instr =
|
||||
asmppc (mem_addr, console_buffer,
|
||||
&asm_err)) != 0) {
|
||||
*(unsigned long *) mem_addr = instr;
|
||||
mem_addr += 4;
|
||||
} else {
|
||||
printf ("*** Error: %s ***\n",
|
||||
asm_error_str (asm_err));
|
||||
rcode = 1;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rcode;
|
||||
} /* do_bedbug_asm */
|
||||
|
||||
U_BOOT_CMD (as, 2, 0, do_bedbug_asm,
|
||||
"as - assemble memory\n", "as <address>\n");
|
||||
|
||||
/* ======================================================================
|
||||
* Used to set a break point from the interpreter. Simply calls into the
|
||||
* CPU-specific break point set routine.
|
||||
* ====================================================================== */
|
||||
|
||||
int do_bedbug_break (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
if (bug_ctx.do_break)
|
||||
(*bug_ctx.do_break) (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
|
||||
} /* do_bedbug_break */
|
||||
|
||||
U_BOOT_CMD (break, 3, 0, do_bedbug_break,
|
||||
"break - set or clear a breakpoint\n",
|
||||
" - Set or clear a breakpoint\n"
|
||||
"break <address> - Break at an address\n"
|
||||
"break off <bp#> - Disable breakpoint.\n"
|
||||
"break show - List breakpoints.\n");
|
||||
|
||||
/* ======================================================================
|
||||
* Called from the debug interrupt routine. Simply calls the CPU-specific
|
||||
* breakpoint handling routine.
|
||||
* ====================================================================== */
|
||||
|
||||
void do_bedbug_breakpoint (struct pt_regs *regs)
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if (bug_ctx.break_isr)
|
||||
(*bug_ctx.break_isr) (regs);
|
||||
|
||||
return;
|
||||
} /* do_bedbug_breakpoint */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Called from the CPU-specific breakpoint handling routine. Enter a
|
||||
* mini main loop until the stopped flag is cleared from the breakpoint
|
||||
* context.
|
||||
*
|
||||
* This handles the parts of the debugger that are common to all CPU's.
|
||||
* ====================================================================== */
|
||||
|
||||
void bedbug_main_loop (unsigned long addr, struct pt_regs *regs)
|
||||
{
|
||||
int len; /* Length of command line */
|
||||
int flag; /* Command flags */
|
||||
int rc = 0; /* Result from run_command */
|
||||
char prompt_str[20]; /* Prompt string */
|
||||
static char lastcommand[CFG_CBSIZE] = { 0 }; /* previous command */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if (bug_ctx.clear)
|
||||
(*bug_ctx.clear) (bug_ctx.current_bp);
|
||||
|
||||
printf ("Breakpoint %d: ", bug_ctx.current_bp);
|
||||
disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX);
|
||||
|
||||
bug_ctx.stopped = 1;
|
||||
bug_ctx.regs = regs;
|
||||
|
||||
sprintf (prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp);
|
||||
|
||||
/* A miniature main loop */
|
||||
while (bug_ctx.stopped) {
|
||||
len = readline (prompt_str);
|
||||
|
||||
flag = 0; /* assume no special flags for now */
|
||||
|
||||
if (len > 0)
|
||||
strcpy (lastcommand, console_buffer);
|
||||
else if (len == 0)
|
||||
flag |= CMD_FLAG_REPEAT;
|
||||
|
||||
if (len == -1)
|
||||
printf ("<INTERRUPT>\n");
|
||||
else
|
||||
rc = run_command (lastcommand, flag);
|
||||
|
||||
if (rc <= 0) {
|
||||
/* invalid command or not repeatable, forget it */
|
||||
lastcommand[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bug_ctx.regs = NULL;
|
||||
bug_ctx.current_bp = 0;
|
||||
|
||||
return;
|
||||
} /* bedbug_main_loop */
|
||||
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to continue from a breakpoint. Just clears the
|
||||
* stopped flag in the context so that the breakpoint routine will
|
||||
* return.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_continue (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if (!bug_ctx.stopped) {
|
||||
printf ("Not at a breakpoint\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bug_ctx.stopped = 0;
|
||||
return 0;
|
||||
} /* do_bedbug_continue */
|
||||
|
||||
U_BOOT_CMD (continue, 1, 0, do_bedbug_continue,
|
||||
"continue- continue from a breakpoint\n",
|
||||
" - continue from a breakpoint.\n");
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to continue to the next instruction, stepping into
|
||||
* subroutines. Works by calling the find_next_addr() routine to compute
|
||||
* the address passes control to the CPU-specific set breakpoint routine
|
||||
* for the current breakpoint number.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_step (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long addr; /* Address to stop at */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if (!bug_ctx.stopped) {
|
||||
printf ("Not at a breakpoint\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!find_next_address ((unsigned char *) &addr, FALSE, bug_ctx.regs))
|
||||
return 1;
|
||||
|
||||
if (bug_ctx.set)
|
||||
(*bug_ctx.set) (bug_ctx.current_bp, addr);
|
||||
|
||||
bug_ctx.stopped = 0;
|
||||
return 0;
|
||||
} /* do_bedbug_step */
|
||||
|
||||
U_BOOT_CMD (step, 1, 1, do_bedbug_step,
|
||||
"step - single step execution.\n",
|
||||
" - single step execution.\n");
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to continue to the next instruction, stepping over
|
||||
* subroutines. Works by calling the find_next_addr() routine to compute
|
||||
* the address passes control to the CPU-specific set breakpoint routine
|
||||
* for the current breakpoint number.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_next (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long addr; /* Address to stop at */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if (!bug_ctx.stopped) {
|
||||
printf ("Not at a breakpoint\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!find_next_address ((unsigned char *) &addr, TRUE, bug_ctx.regs))
|
||||
return 1;
|
||||
|
||||
if (bug_ctx.set)
|
||||
(*bug_ctx.set) (bug_ctx.current_bp, addr);
|
||||
|
||||
bug_ctx.stopped = 0;
|
||||
return 0;
|
||||
} /* do_bedbug_next */
|
||||
|
||||
U_BOOT_CMD (next, 1, 1, do_bedbug_next,
|
||||
"next - single step execution, stepping over subroutines.\n",
|
||||
" - single step execution, stepping over subroutines.\n");
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to print the current stack. This assumes an EABI
|
||||
* architecture, so it starts with GPR R1 and works back up the stack.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_stack (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long sp; /* Stack pointer */
|
||||
unsigned long func; /* LR from stack */
|
||||
int depth; /* Stack iteration level */
|
||||
int skip = 1; /* Flag to skip the first entry */
|
||||
unsigned long top; /* Top of memory address */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if (!bug_ctx.stopped) {
|
||||
printf ("Not at a breakpoint\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
top = gd->bd->bi_memstart + gd->bd->bi_memsize;
|
||||
depth = 0;
|
||||
|
||||
printf ("Depth PC\n");
|
||||
printf ("----- --------\n");
|
||||
printf ("%5d %08lx\n", depth++, bug_ctx.regs->nip);
|
||||
|
||||
sp = bug_ctx.regs->gpr[1];
|
||||
func = *(unsigned long *) (sp + 4);
|
||||
|
||||
while ((func < top) && (sp < top)) {
|
||||
if (!skip)
|
||||
printf ("%5d %08lx\n", depth++, func);
|
||||
else
|
||||
--skip;
|
||||
|
||||
sp = *(unsigned long *) sp;
|
||||
func = *(unsigned long *) (sp + 4);
|
||||
}
|
||||
return 0;
|
||||
} /* do_bedbug_stack */
|
||||
|
||||
U_BOOT_CMD (where, 1, 1, do_bedbug_stack,
|
||||
"where - Print the running stack.\n",
|
||||
" - Print the running stack.\n");
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to dump the registers. Calls the CPU-specific
|
||||
* show registers routine.
|
||||
* ====================================================================== */
|
||||
int do_bedbug_rdump (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
if (!bug_ctx.stopped) {
|
||||
printf ("Not at a breakpoint\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
show_regs (bug_ctx.regs);
|
||||
return 0;
|
||||
} /* do_bedbug_rdump */
|
||||
|
||||
U_BOOT_CMD (rdump, 1, 1, do_bedbug_rdump,
|
||||
"rdump - Show registers.\n", " - Show registers.\n");
|
||||
/* ====================================================================== */
|
||||
#endif /* CFG_CMD_BEDBUG */
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 William L. Pitts
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are freely
|
||||
* permitted provided that the above copyright notice and this
|
||||
* paragraph and the following disclaimer are duplicated in all
|
||||
* such forms.
|
||||
*
|
||||
* This software is provided "AS IS" and without any express or
|
||||
* implied warranties, including, without limitation, the implied
|
||||
* warranties of merchantability and fitness for a particular
|
||||
* purpose.
|
||||
*/
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Detlev Zundel, DENX Software Engineering, dzu@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
|
||||
*/
|
||||
|
||||
/*
|
||||
* BMP handling routines
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <bmp_layout.h>
|
||||
#include <command.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BMP)
|
||||
|
||||
static int bmp_info (ulong addr);
|
||||
static int bmp_display (ulong addr, int x, int y);
|
||||
|
||||
int gunzip(void *, int, unsigned char *, unsigned long *);
|
||||
|
||||
/*
|
||||
* Subroutine: do_bmp
|
||||
*
|
||||
* Description: Handler for 'bmp' command..
|
||||
*
|
||||
* Inputs: argv[1] contains the subcommand
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
int do_bmp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr;
|
||||
int x = 0, y = 0;
|
||||
|
||||
switch (argc) {
|
||||
case 2: /* use load_addr as default address */
|
||||
addr = load_addr;
|
||||
break;
|
||||
case 3: /* use argument */
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
break;
|
||||
case 5:
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
x = simple_strtoul(argv[3], NULL, 10);
|
||||
y = simple_strtoul(argv[4], NULL, 10);
|
||||
break;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Allow for short names
|
||||
* Adjust length if more sub-commands get added
|
||||
*/
|
||||
if (strncmp(argv[1],"info",1) == 0) {
|
||||
return (bmp_info(addr));
|
||||
} else if (strncmp(argv[1],"display",1) == 0) {
|
||||
return (bmp_display(addr, x, y));
|
||||
} else {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
bmp, 5, 1, do_bmp,
|
||||
"bmp - manipulate BMP image data\n",
|
||||
"info <imageAddr> - display image info\n"
|
||||
"bmp display <imageAddr> [x y] - display image at x,y\n"
|
||||
);
|
||||
|
||||
/*
|
||||
* Subroutine: bmp_info
|
||||
*
|
||||
* Description: Show information about bmp file in memory
|
||||
*
|
||||
* Inputs: addr address of the bmp file
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
static int bmp_info(ulong addr)
|
||||
{
|
||||
bmp_image_t *bmp=(bmp_image_t *)addr;
|
||||
#ifdef CONFIG_VIDEO_BMP_GZIP
|
||||
unsigned char *dst = NULL;
|
||||
ulong len;
|
||||
#endif /* CONFIG_VIDEO_BMP_GZIP */
|
||||
|
||||
if (!((bmp->header.signature[0]=='B') &&
|
||||
(bmp->header.signature[1]=='M'))) {
|
||||
|
||||
#ifdef CONFIG_VIDEO_BMP_GZIP
|
||||
/*
|
||||
* Decompress bmp image
|
||||
*/
|
||||
len = CFG_VIDEO_LOGO_MAX_SIZE;
|
||||
dst = malloc(CFG_VIDEO_LOGO_MAX_SIZE);
|
||||
if (dst == NULL) {
|
||||
printf("Error: malloc in gunzip failed!\n");
|
||||
return(1);
|
||||
}
|
||||
if (gunzip(dst, CFG_VIDEO_LOGO_MAX_SIZE, (uchar *)addr, &len) != 0) {
|
||||
printf("There is no valid bmp file at the given address\n");
|
||||
return(1);
|
||||
}
|
||||
if (len == CFG_VIDEO_LOGO_MAX_SIZE) {
|
||||
printf("Image could be truncated (increase CFG_VIDEO_LOGO_MAX_SIZE)!\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set addr to decompressed image
|
||||
*/
|
||||
bmp = (bmp_image_t *)dst;
|
||||
|
||||
/*
|
||||
* Check for bmp mark 'BM'
|
||||
*/
|
||||
if (!((bmp->header.signature[0] == 'B') &&
|
||||
(bmp->header.signature[1] == 'M'))) {
|
||||
printf("There is no valid bmp file at the given address\n");
|
||||
free(dst);
|
||||
return(1);
|
||||
}
|
||||
|
||||
printf("Gzipped BMP image detected!\n");
|
||||
#else /* CONFIG_VIDEO_BMP_GZIP */
|
||||
printf("There is no valid bmp file at the given address\n");
|
||||
return(1);
|
||||
#endif /* CONFIG_VIDEO_BMP_GZIP */
|
||||
}
|
||||
printf("Image size : %d x %d\n", le32_to_cpu(bmp->header.width),
|
||||
le32_to_cpu(bmp->header.height));
|
||||
printf("Bits per pixel: %d\n", le16_to_cpu(bmp->header.bit_count));
|
||||
printf("Compression : %d\n", le32_to_cpu(bmp->header.compression));
|
||||
|
||||
#ifdef CONFIG_VIDEO_BMP_GZIP
|
||||
if (dst) {
|
||||
free(dst);
|
||||
}
|
||||
#endif /* CONFIG_VIDEO_BMP_GZIP */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Subroutine: bmp_display
|
||||
*
|
||||
* Description: Display bmp file located in memory
|
||||
*
|
||||
* Inputs: addr address of the bmp file
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
static int bmp_display(ulong addr, int x, int y)
|
||||
{
|
||||
#if defined(CONFIG_LCD)
|
||||
extern int lcd_display_bitmap (ulong, int, int);
|
||||
|
||||
return (lcd_display_bitmap (addr, x, y));
|
||||
#elif defined(CONFIG_VIDEO)
|
||||
extern int video_display_bitmap (ulong, int, int);
|
||||
return (video_display_bitmap (addr, x, y));
|
||||
#else
|
||||
# error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) */
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2003
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Misc boot support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <net.h>
|
||||
|
||||
#if defined(CONFIG_I386) || defined(CONFIG_MIPS)
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr, rc;
|
||||
int rcode = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
printf ("## Starting application at 0x%08lX ...\n", addr);
|
||||
|
||||
/*
|
||||
* pass address parameter as argv[0] (aka command name),
|
||||
* and all remaining args
|
||||
*/
|
||||
#if defined(CONFIG_I386)
|
||||
/*
|
||||
* x86 does not use a dedicated register to pass the pointer
|
||||
* to the global_data
|
||||
*/
|
||||
argv[0] = (char *)gd;
|
||||
#endif
|
||||
#if !defined(CONFIG_NIOS)
|
||||
if (argc > 2 && argv[2][0] == 'b') {
|
||||
printf ("## Board info at 0x%08lX ...\n", gd->bd);
|
||||
rc = ((ulong (*)(int, int, int, int))addr)(gd->bd, 0, 0, 0);
|
||||
} else {
|
||||
rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Nios function pointers are address >> 1
|
||||
*/
|
||||
rc = ((ulong (*)(int, char *[]))(addr>>1)) (--argc, &argv[1]);
|
||||
#endif
|
||||
if (rc != 0) rcode = 1;
|
||||
|
||||
printf ("## Application terminated, rc = 0x%lX\n", rc);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
U_BOOT_CMD(
|
||||
go, CFG_MAXARGS, 1, do_go,
|
||||
"go - start application at address 'addr'\n",
|
||||
"addr [arg ...]\n - start application at address 'addr'\n"
|
||||
" passing 'arg' as arguments\n"
|
||||
);
|
||||
#endif /* #ifndef COMPRESSED_UBOOT */
|
||||
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
|
||||
|
||||
U_BOOT_CMD(
|
||||
reset, 1, 0, do_reset,
|
||||
"reset - Perform RESET of the CPU\n",
|
||||
NULL
|
||||
);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cache support: switch on or off, get status
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
|
||||
|
||||
static int on_off (const char *);
|
||||
|
||||
int do_icache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
switch (argc) {
|
||||
case 2: /* on / off */
|
||||
switch (on_off(argv[1])) {
|
||||
#if 0 /* prevented by varargs handling; FALLTROUGH is harmless, too */
|
||||
default: printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return;
|
||||
#endif
|
||||
case 0: icache_disable();
|
||||
break;
|
||||
case 1: icache_enable ();
|
||||
break;
|
||||
}
|
||||
/* FALL TROUGH */
|
||||
case 1: /* get status */
|
||||
printf ("Instruction Cache is %s\n",
|
||||
icache_status() ? "ON" : "OFF");
|
||||
return 0;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_dcache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
switch (argc) {
|
||||
case 2: /* on / off */
|
||||
switch (on_off(argv[1])) {
|
||||
#if 0 /* prevented by varargs handling; FALLTROUGH is harmless, too */
|
||||
default: printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return;
|
||||
#endif
|
||||
case 0: dcache_disable();
|
||||
break;
|
||||
case 1: dcache_enable ();
|
||||
break;
|
||||
}
|
||||
/* FALL TROUGH */
|
||||
case 1: /* get status */
|
||||
printf ("Data (writethrough) Cache is %s\n",
|
||||
dcache_status() ? "ON" : "OFF");
|
||||
return 0;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int on_off (const char *s)
|
||||
{
|
||||
if (strcmp(s, "on") == 0) {
|
||||
return (1);
|
||||
} else if (strcmp(s, "off") == 0) {
|
||||
return (0);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
icache, 2, 1, do_icache,
|
||||
"icache - enable or disable instruction cache\n",
|
||||
"[on, off]\n"
|
||||
" - enable or disable instruction cache\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
dcache, 2, 1, do_dcache,
|
||||
"dcache - enable or disable data cache\n",
|
||||
"[on, off]\n"
|
||||
" - enable or disable data (writethrough) cache\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_CACHE */
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Boot support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <devices.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_CONSOLE)
|
||||
|
||||
extern void _do_coninfo (void);
|
||||
int do_coninfo (cmd_tbl_t * cmd, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i, l;
|
||||
|
||||
/* Scan for valid output and input devices */
|
||||
|
||||
puts ("List of available devices:\n");
|
||||
|
||||
for (i = 1; i <= ListNumItems (devlist); i++) {
|
||||
device_t *dev = ListGetPtrToItem (devlist, i);
|
||||
|
||||
printf ("%-8s %08x %c%c%c ",
|
||||
dev->name,
|
||||
dev->flags,
|
||||
(dev->flags & DEV_FLAGS_SYSTEM) ? 'S' : '.',
|
||||
(dev->flags & DEV_FLAGS_INPUT) ? 'I' : '.',
|
||||
(dev->flags & DEV_FLAGS_OUTPUT) ? 'O' : '.');
|
||||
|
||||
for (l = 0; l < MAX_FILES; l++) {
|
||||
if (stdio_devices[l] == dev) {
|
||||
printf ("%s ", stdio_names[l]);
|
||||
}
|
||||
}
|
||||
putc ('\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
coninfo, 3, 1, do_coninfo,
|
||||
"coninfo - print console devices and information\n",
|
||||
""
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_CONSOLE */
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* RTC, Date & Time support: get and set date & time
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <rtc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DATE)
|
||||
|
||||
const char *weekdays[] = {
|
||||
"Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur",
|
||||
};
|
||||
|
||||
#define RELOC(a) ((typeof(a))((unsigned long)(a) + gd->reloc_off))
|
||||
|
||||
int mk_date (char *, struct rtc_time *);
|
||||
|
||||
int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
struct rtc_time tm;
|
||||
int rcode = 0;
|
||||
|
||||
switch (argc) {
|
||||
case 2: /* set date & time */
|
||||
if (strcmp(argv[1],"reset") == 0) {
|
||||
puts ("Reset RTC...\n");
|
||||
rtc_reset ();
|
||||
} else {
|
||||
/* initialize tm with current time */
|
||||
rtc_get (&tm);
|
||||
/* insert new date & time */
|
||||
if (mk_date (argv[1], &tm) != 0) {
|
||||
puts ("## Bad date format\n");
|
||||
return 1;
|
||||
}
|
||||
/* and write to RTC */
|
||||
rtc_set (&tm);
|
||||
}
|
||||
/* FALL TROUGH */
|
||||
case 1: /* get date & time */
|
||||
rtc_get (&tm);
|
||||
|
||||
printf ("Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n",
|
||||
tm.tm_year, tm.tm_mon, tm.tm_mday,
|
||||
(tm.tm_wday<0 || tm.tm_wday>6) ?
|
||||
"unknown " : RELOC(weekdays[tm.tm_wday]),
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
|
||||
return 0;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
rcode = 1;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* simple conversion of two-digit string with error checking
|
||||
*/
|
||||
static int cnvrt2 (char *str, int *valp)
|
||||
{
|
||||
int val;
|
||||
|
||||
if ((*str < '0') || (*str > '9'))
|
||||
return (-1);
|
||||
|
||||
val = *str - '0';
|
||||
|
||||
++str;
|
||||
|
||||
if ((*str < '0') || (*str > '9'))
|
||||
return (-1);
|
||||
|
||||
*valp = 10 * val + (*str - '0');
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert date string: MMDDhhmm[[CC]YY][.ss]
|
||||
*
|
||||
* Some basic checking for valid values is done, but this will not catch
|
||||
* all possible error conditions.
|
||||
*/
|
||||
int mk_date (char *datestr, struct rtc_time *tmp)
|
||||
{
|
||||
int len, val;
|
||||
char *ptr;
|
||||
|
||||
ptr = strchr (datestr,'.');
|
||||
len = strlen (datestr);
|
||||
|
||||
/* Set seconds */
|
||||
if (ptr) {
|
||||
int sec;
|
||||
|
||||
*ptr++ = '\0';
|
||||
if ((len - (ptr - datestr)) != 2)
|
||||
return (-1);
|
||||
|
||||
len = strlen (datestr);
|
||||
|
||||
if (cnvrt2 (ptr, &sec))
|
||||
return (-1);
|
||||
|
||||
tmp->tm_sec = sec;
|
||||
} else {
|
||||
tmp->tm_sec = 0;
|
||||
}
|
||||
|
||||
if (len == 12) { /* MMDDhhmmCCYY */
|
||||
int year, century;
|
||||
|
||||
if (cnvrt2 (datestr+ 8, ¢ury) ||
|
||||
cnvrt2 (datestr+10, &year) ) {
|
||||
return (-1);
|
||||
}
|
||||
tmp->tm_year = 100 * century + year;
|
||||
} else if (len == 10) { /* MMDDhhmmYY */
|
||||
int year, century;
|
||||
|
||||
century = tmp->tm_year / 100;
|
||||
if (cnvrt2 (datestr+ 8, &year))
|
||||
return (-1);
|
||||
tmp->tm_year = 100 * century + year;
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 8: /* MMDDhhmm */
|
||||
/* fall thru */
|
||||
case 10: /* MMDDhhmmYY */
|
||||
/* fall thru */
|
||||
case 12: /* MMDDhhmmCCYY */
|
||||
if (cnvrt2 (datestr+0, &val) ||
|
||||
val > 12) {
|
||||
break;
|
||||
}
|
||||
tmp->tm_mon = val;
|
||||
if (cnvrt2 (datestr+2, &val) ||
|
||||
val > ((tmp->tm_mon==2) ? 29 : 31)) {
|
||||
break;
|
||||
}
|
||||
tmp->tm_mday = val;
|
||||
|
||||
if (cnvrt2 (datestr+4, &val) ||
|
||||
val > 23) {
|
||||
break;
|
||||
}
|
||||
tmp->tm_hour = val;
|
||||
|
||||
if (cnvrt2 (datestr+6, &val) ||
|
||||
val > 59) {
|
||||
break;
|
||||
}
|
||||
tmp->tm_min = val;
|
||||
|
||||
/* calculate day of week */
|
||||
GregorianDay (tmp);
|
||||
|
||||
return (0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
date, 2, 1, do_date,
|
||||
"date - get/set/reset date & time\n",
|
||||
"[MMDDhhmm[[CC]YY][.ss]]\ndate reset\n"
|
||||
" - without arguments: print date & time\n"
|
||||
" - with numeric argument: set the system date & time\n"
|
||||
" - with 'reset' argument: reset the RTC\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_DATE */
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* AMCC 4XX DCR Functions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
|
||||
#if defined(CONFIG_4xx) && (CONFIG_COMMANDS & CFG_CMD_SETGETDCR)
|
||||
|
||||
/* =======================================================================
|
||||
* Interpreter command to retrieve an AMCC PPC 4xx Device Control Register
|
||||
* =======================================================================
|
||||
*/
|
||||
int do_getdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
|
||||
{
|
||||
unsigned short dcrn; /* Device Control Register Num */
|
||||
unsigned long value; /* DCR's value */
|
||||
|
||||
unsigned long get_dcr (unsigned short);
|
||||
|
||||
/* Validate arguments */
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get a DCR */
|
||||
dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16);
|
||||
value = get_dcr (dcrn);
|
||||
|
||||
printf ("%04x: %08lx\n", dcrn, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to set an AMCC PPC 4xx Device Control Register
|
||||
* ======================================================================
|
||||
*/
|
||||
int do_setdcr (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long get_dcr (unsigned short);
|
||||
unsigned long set_dcr (unsigned short, unsigned long);
|
||||
unsigned short dcrn; /* Device Control Register Num */
|
||||
unsigned long value;
|
||||
|
||||
/* DCR's value */
|
||||
int nbytes;
|
||||
extern char console_buffer[];
|
||||
|
||||
/* Validate arguments */
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set a DCR */
|
||||
dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16);
|
||||
do {
|
||||
value = get_dcr (dcrn);
|
||||
printf ("%04x: %08lx", dcrn, value);
|
||||
nbytes = readline (" ? ");
|
||||
if (nbytes == 0) {
|
||||
/*
|
||||
* <CR> pressed as only input, don't modify current
|
||||
* location and exit command.
|
||||
*/
|
||||
nbytes = 1;
|
||||
return 0;
|
||||
} else {
|
||||
unsigned long i;
|
||||
char *endp;
|
||||
|
||||
i = simple_strtoul (console_buffer, &endp, 16);
|
||||
nbytes = endp - console_buffer;
|
||||
if (nbytes)
|
||||
set_dcr (dcrn, i);
|
||||
}
|
||||
} while (nbytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
getdcr, 2, 1, do_getdcr,
|
||||
"getdcr - Get an AMCC PPC 4xx DCR's value\n",
|
||||
"dcrn - return a DCR's value.\n"
|
||||
);
|
||||
U_BOOT_CMD(
|
||||
setdcr, 2, 1, do_setdcr,
|
||||
"setdcr - Set an AMCC PPC 4xx DCR's value\n",
|
||||
"dcrn - set a DCR's value.\n"
|
||||
);
|
||||
|
||||
#endif /* CONFIG_4xx & CFG_CMD_SETGETDCR */
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPI Read/Write Utilities
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <config.h>
|
||||
#include <ar7240_soc.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DDR)
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Definitions
|
||||
*/
|
||||
|
||||
static void prepare_flash(char **buff_ptr,long **val)
|
||||
{
|
||||
if((long)*buff_ptr % 4)
|
||||
*buff_ptr = *buff_ptr + ((long)*buff_ptr % 4);
|
||||
memcpy(*buff_ptr,(void *)((long)UBOOT_ENV_SEC_START),CFG_FLASH_SECTOR_SIZE);
|
||||
flash_sect_erase(UBOOT_ENV_SEC_START,UBOOT_ENV_SEC_START + (CFG_FLASH_SECTOR_SIZE - 1));
|
||||
*val = (long *)(*buff_ptr + CFG_FLASH_SECTOR_SIZE - 0x30);
|
||||
}
|
||||
|
||||
int do_ddr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *buff,*buff_ptr = NULL;
|
||||
int ddr_config,ddr_config2,ext_mod;
|
||||
long *val;
|
||||
|
||||
/*
|
||||
* We use the last specified parameters, unless new ones are
|
||||
* entered.
|
||||
*/
|
||||
|
||||
/* last sector of uboot 0xbf040000 - 0xbf050000
|
||||
* write MAGIC at 0xbf04ffe0
|
||||
* write sector at 0xbf04ffe4
|
||||
* write size at 0xbf04ffe8
|
||||
*/
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0)
|
||||
{
|
||||
if (argc == 2) {
|
||||
ddr_config = simple_strtoul(argv[1], NULL, 10);
|
||||
ddr_config2 = CFG_DDR_CONFIG2_VAL;
|
||||
ext_mod = CFG_DDR_EXT_MODE_VAL;
|
||||
}
|
||||
else if (argc == 3) {
|
||||
ddr_config = simple_strtoul(argv[1], NULL, 10);
|
||||
ddr_config2 = simple_strtoul(argv[2], NULL, 10);
|
||||
ext_mod = CFG_DDR_EXT_MODE_VAL;
|
||||
}
|
||||
else if (argc == 4) {
|
||||
ddr_config = simple_strtoul(argv[1], NULL, 10);
|
||||
ddr_config2 = simple_strtoul(argv[2], NULL, 10);
|
||||
ext_mod = simple_strtoul(argv[3], NULL, 10);
|
||||
}
|
||||
else {
|
||||
printf("Invalid number of arguments:%d\n",argc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
buff = (char *) malloc(CFG_FLASH_SECTOR_SIZE + 4);
|
||||
buff_ptr = buff;
|
||||
|
||||
prepare_flash(&buff_ptr,&val);
|
||||
*val++ = (long)CFG_DDR_MAGIC;
|
||||
*val++ = ddr_config;
|
||||
*val++ = ddr_config2;
|
||||
*val = ext_mod;
|
||||
|
||||
flash_write(buff_ptr,(long)(UBOOT_ENV_SEC_START),CFG_FLASH_SECTOR_SIZE);
|
||||
|
||||
printf("Programed values ext_mod:0x%0.8x ",*val--);
|
||||
printf(" ddr_config2:0x%0.8x ddr_config:0x%0.8x \n",*val--,*val);
|
||||
free(buff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
ddr, 6, 1, do_ddr,
|
||||
"fls - Set to change DDR settings on reboot\n",
|
||||
"<value> - DDR CONFIG\n"
|
||||
"<value> - DDR CONFIG2\n"
|
||||
"<value> - EXT MOD\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_SPI */
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Diagnostics support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <post.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DIAG) && defined(CONFIG_POST)
|
||||
|
||||
int do_diag (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (argc == 1 || strcmp (argv[1], "run") != 0) {
|
||||
/* List test info */
|
||||
if (argc == 1) {
|
||||
puts ("Available hardware tests:\n");
|
||||
post_info (NULL);
|
||||
puts ("Use 'diag [<test1> [<test2> ...]]'"
|
||||
" to get more info.\n");
|
||||
puts ("Use 'diag run [<test1> [<test2> ...]]'"
|
||||
" to run tests.\n");
|
||||
} else {
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (post_info (argv[i]) != 0)
|
||||
printf ("%s - no such test\n", argv[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Run tests */
|
||||
if (argc == 2) {
|
||||
post_run (NULL, POST_RAM | POST_MANUAL);
|
||||
} else {
|
||||
for (i = 2; i < argc; i++) {
|
||||
if (post_run (argv[i], POST_RAM | POST_MANUAL) != 0)
|
||||
printf ("%s - unable to execute the test\n",
|
||||
argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
diag, CFG_MAXARGS, 0, do_diag,
|
||||
"diag - perform board diagnostics\n",
|
||||
" - print list of available tests\n"
|
||||
"diag [test1 [test2]]\n"
|
||||
" - print information about specified tests\n"
|
||||
"diag run - run all available tests\n"
|
||||
"diag run [test1 [test2]]\n"
|
||||
" - run specified tests\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_DIAG */
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* (C) Copyright 2005
|
||||
* 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 <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DISPLAY)
|
||||
|
||||
#undef DEBUG_DISP
|
||||
|
||||
#define DISP_SIZE 8
|
||||
#define CWORD_CLEAR 0x80
|
||||
#define CLEAR_DELAY (110 * 2)
|
||||
|
||||
int do_display (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int pos;
|
||||
|
||||
/* Clear display */
|
||||
*((volatile char*)(CFG_DISP_CWORD)) = CWORD_CLEAR;
|
||||
udelay(1000 * CLEAR_DELAY);
|
||||
|
||||
if (argc < 2)
|
||||
return (0);
|
||||
|
||||
for (pos = 0, i = 1; i < argc && pos < DISP_SIZE; i++) {
|
||||
char *p = argv[i], c;
|
||||
|
||||
if (i > 1) {
|
||||
*((volatile uchar *) (CFG_DISP_CHR_RAM + pos++)) = ' ';
|
||||
#ifdef DEBUG_DISP
|
||||
putc(' ');
|
||||
#endif
|
||||
}
|
||||
|
||||
while ((c = *p++) != '\0' && pos < DISP_SIZE) {
|
||||
*((volatile uchar *) (CFG_DISP_CHR_RAM + pos++)) = c;
|
||||
#ifdef DEBUG_DISP
|
||||
putc(c);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DISP
|
||||
putc('\n');
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
display, CFG_MAXARGS, 1, do_display,
|
||||
"display- display string on dot matrix display\n",
|
||||
"[<string>]\n"
|
||||
" - with <string> argument: display <string> on dot matrix display\n"
|
||||
" - without arguments: clear dot matrix display\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_DISPLAY */
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DTT)
|
||||
|
||||
#include <dtt.h>
|
||||
|
||||
int do_dtt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
unsigned char sensors[] = CONFIG_DTT_SENSORS;
|
||||
|
||||
/*
|
||||
* Loop through sensors, read
|
||||
* temperature, and output it.
|
||||
*/
|
||||
for (i = 0; i < sizeof (sensors); i++) {
|
||||
printf ("DTT%d: %i C\n", i + 1, dtt_get_temp (sensors[i]));
|
||||
}
|
||||
|
||||
return 0;
|
||||
} /* do_dtt() */
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
dtt, 1, 1, do_dtt,
|
||||
"dtt - Digital Thermometer and Themostat\n",
|
||||
" - Read temperature from digital thermometer and thermostat.\n"
|
||||
);
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_DTT */
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* (C) Copyright 2000, 2001
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support for read and write access to EEPROM like memory devices. This
|
||||
* includes regular EEPROM as well as FRAM (ferroelectic nonvolaile RAM).
|
||||
* FRAM devices read and write data at bus speed. In particular, there is no
|
||||
* write delay. Also, there is no limit imposed on the numer of bytes that can
|
||||
* be transferred with a single read or write.
|
||||
*
|
||||
* Use the following configuration options to ensure no unneeded performance
|
||||
* degradation (typical for EEPROM) is incured for FRAM memory:
|
||||
*
|
||||
* #define CFG_I2C_FRAM
|
||||
* #undef CFG_EEPROM_PAGE_WRITE_DELAY_MS
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
|
||||
|
||||
extern void eeprom_init (void);
|
||||
extern int eeprom_read (unsigned dev_addr, unsigned offset,
|
||||
uchar *buffer, unsigned cnt);
|
||||
extern int eeprom_write (unsigned dev_addr, unsigned offset,
|
||||
uchar *buffer, unsigned cnt);
|
||||
#if defined(CFG_EEPROM_WREN)
|
||||
extern int eeprom_write_enable (unsigned dev_addr, int state);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CFG_EEPROM_X40430)
|
||||
/* Maximum number of times to poll for acknowledge after write */
|
||||
#define MAX_ACKNOWLEDGE_POLLS 10
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM)
|
||||
int do_eeprom ( cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
const char *const fmt =
|
||||
"\nEEPROM @0x%lX %s: addr %08lx off %04lx count %ld ... ";
|
||||
|
||||
#if defined(CFG_I2C_MULTI_EEPROMS)
|
||||
if (argc == 6) {
|
||||
ulong dev_addr = simple_strtoul (argv[2], NULL, 16);
|
||||
ulong addr = simple_strtoul (argv[3], NULL, 16);
|
||||
ulong off = simple_strtoul (argv[4], NULL, 16);
|
||||
ulong cnt = simple_strtoul (argv[5], NULL, 16);
|
||||
#else
|
||||
if (argc == 5) {
|
||||
ulong dev_addr = CFG_DEF_EEPROM_ADDR;
|
||||
ulong addr = simple_strtoul (argv[2], NULL, 16);
|
||||
ulong off = simple_strtoul (argv[3], NULL, 16);
|
||||
ulong cnt = simple_strtoul (argv[4], NULL, 16);
|
||||
#endif /* CFG_I2C_MULTI_EEPROMS */
|
||||
|
||||
# ifndef CONFIG_SPI
|
||||
eeprom_init ();
|
||||
# endif /* !CONFIG_SPI */
|
||||
|
||||
if (strcmp (argv[1], "read") == 0) {
|
||||
int rcode;
|
||||
|
||||
printf (fmt, dev_addr, argv[1], addr, off, cnt);
|
||||
|
||||
rcode = eeprom_read (dev_addr, off, (uchar *) addr, cnt);
|
||||
|
||||
puts ("done\n");
|
||||
return rcode;
|
||||
} else if (strcmp (argv[1], "write") == 0) {
|
||||
int rcode;
|
||||
|
||||
printf (fmt, dev_addr, argv[1], addr, off, cnt);
|
||||
|
||||
rcode = eeprom_write (dev_addr, off, (uchar *) addr, cnt);
|
||||
|
||||
puts ("done\n");
|
||||
return rcode;
|
||||
}
|
||||
}
|
||||
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
#endif /* CFG_CMD_EEPROM */
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*
|
||||
* for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
|
||||
* 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
|
||||
*
|
||||
* for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
|
||||
* 0x00000nxx for EEPROM address selectors and page number at n.
|
||||
*/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
|
||||
|
||||
#ifndef CONFIG_SPI
|
||||
#if !defined(CFG_I2C_EEPROM_ADDR_LEN) || CFG_I2C_EEPROM_ADDR_LEN < 1 || CFG_I2C_EEPROM_ADDR_LEN > 2
|
||||
#error CFG_I2C_EEPROM_ADDR_LEN must be 1 or 2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
|
||||
{
|
||||
unsigned end = offset + cnt;
|
||||
unsigned blk_off;
|
||||
int rcode = 0;
|
||||
|
||||
/* Read data until done or would cross a page boundary.
|
||||
* We must write the address again when changing pages
|
||||
* because the next page may be in a different device.
|
||||
*/
|
||||
while (offset < end) {
|
||||
unsigned alen, len;
|
||||
#if !defined(CFG_I2C_FRAM)
|
||||
unsigned maxlen;
|
||||
#endif
|
||||
|
||||
#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
|
||||
uchar addr[2];
|
||||
|
||||
blk_off = offset & 0xFF; /* block offset */
|
||||
|
||||
addr[0] = offset >> 8; /* block number */
|
||||
addr[1] = blk_off; /* block offset */
|
||||
alen = 2;
|
||||
#else
|
||||
uchar addr[3];
|
||||
|
||||
blk_off = offset & 0xFF; /* block offset */
|
||||
|
||||
addr[0] = offset >> 16; /* block number */
|
||||
addr[1] = offset >> 8; /* upper address octet */
|
||||
addr[2] = blk_off; /* lower address octet */
|
||||
alen = 3;
|
||||
#endif /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
|
||||
|
||||
addr[0] |= dev_addr; /* insert device address */
|
||||
|
||||
len = end - offset;
|
||||
|
||||
/*
|
||||
* For a FRAM device there is no limit on the number of the
|
||||
* bytes that can be ccessed with the single read or write
|
||||
* operation.
|
||||
*/
|
||||
#if !defined(CFG_I2C_FRAM)
|
||||
maxlen = 0x100 - blk_off;
|
||||
if (maxlen > I2C_RXTX_LEN)
|
||||
maxlen = I2C_RXTX_LEN;
|
||||
if (len > maxlen)
|
||||
len = maxlen;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPI
|
||||
spi_read (addr, alen, buffer, len);
|
||||
#else
|
||||
if (i2c_read (addr[0], offset, alen-1, buffer, len) != 0)
|
||||
rcode = 1;
|
||||
#endif
|
||||
buffer += len;
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*
|
||||
* for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
|
||||
* 0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
|
||||
*
|
||||
* for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
|
||||
* 0x00000nxx for EEPROM address selectors and page number at n.
|
||||
*/
|
||||
|
||||
int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
|
||||
{
|
||||
unsigned end = offset + cnt;
|
||||
unsigned blk_off;
|
||||
int rcode = 0;
|
||||
|
||||
#if defined(CFG_EEPROM_X40430)
|
||||
uchar contr_r_addr[2];
|
||||
uchar addr_void[2];
|
||||
uchar contr_reg[2];
|
||||
uchar ctrl_reg_v;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
#if defined(CFG_EEPROM_WREN)
|
||||
eeprom_write_enable (dev_addr,1);
|
||||
#endif
|
||||
/* Write data until done or would cross a write page boundary.
|
||||
* We must write the address again when changing pages
|
||||
* because the address counter only increments within a page.
|
||||
*/
|
||||
|
||||
while (offset < end) {
|
||||
unsigned alen, len;
|
||||
#if !defined(CFG_I2C_FRAM)
|
||||
unsigned maxlen;
|
||||
#endif
|
||||
|
||||
#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
|
||||
uchar addr[2];
|
||||
|
||||
blk_off = offset & 0xFF; /* block offset */
|
||||
|
||||
addr[0] = offset >> 8; /* block number */
|
||||
addr[1] = blk_off; /* block offset */
|
||||
alen = 2;
|
||||
#else
|
||||
uchar addr[3];
|
||||
|
||||
blk_off = offset & 0xFF; /* block offset */
|
||||
|
||||
addr[0] = offset >> 16; /* block number */
|
||||
addr[1] = offset >> 8; /* upper address octet */
|
||||
addr[2] = blk_off; /* lower address octet */
|
||||
alen = 3;
|
||||
#endif /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
|
||||
|
||||
addr[0] |= dev_addr; /* insert device address */
|
||||
|
||||
len = end - offset;
|
||||
|
||||
/*
|
||||
* For a FRAM device there is no limit on the number of the
|
||||
* bytes that can be ccessed with the single read or write
|
||||
* operation.
|
||||
*/
|
||||
#if !defined(CFG_I2C_FRAM)
|
||||
|
||||
#if defined(CFG_EEPROM_PAGE_WRITE_BITS)
|
||||
|
||||
#define EEPROM_PAGE_SIZE (1 << CFG_EEPROM_PAGE_WRITE_BITS)
|
||||
#define EEPROM_PAGE_OFFSET(x) ((x) & (EEPROM_PAGE_SIZE - 1))
|
||||
|
||||
maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off);
|
||||
#else
|
||||
maxlen = 0x100 - blk_off;
|
||||
#endif
|
||||
if (maxlen > I2C_RXTX_LEN)
|
||||
maxlen = I2C_RXTX_LEN;
|
||||
|
||||
if (len > maxlen)
|
||||
len = maxlen;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPI
|
||||
spi_write (addr, alen, buffer, len);
|
||||
#else
|
||||
#if defined(CFG_EEPROM_X40430)
|
||||
/* Get the value of the control register.
|
||||
* Set current address (internal pointer in the x40430)
|
||||
* to 0x1ff.
|
||||
*/
|
||||
contr_r_addr[0] = 9;
|
||||
contr_r_addr[1] = 0xff;
|
||||
addr_void[0] = 0;
|
||||
addr_void[1] = addr[1];
|
||||
#ifdef CFG_I2C_EEPROM_ADDR
|
||||
contr_r_addr[0] |= CFG_I2C_EEPROM_ADDR;
|
||||
addr_void[0] |= CFG_I2C_EEPROM_ADDR;
|
||||
#endif
|
||||
contr_reg[0] = 0xff;
|
||||
if (i2c_read (contr_r_addr[0], contr_r_addr[1], 1, contr_reg, 1) != 0) {
|
||||
rcode = 1;
|
||||
}
|
||||
ctrl_reg_v = contr_reg[0];
|
||||
|
||||
/* Are any of the eeprom blocks write protected?
|
||||
*/
|
||||
if (ctrl_reg_v & 0x18) {
|
||||
ctrl_reg_v &= ~0x18; /* reset block protect bits */
|
||||
ctrl_reg_v |= 0x02; /* set write enable latch */
|
||||
ctrl_reg_v &= ~0x04; /* clear RWEL */
|
||||
|
||||
/* Set write enable latch.
|
||||
*/
|
||||
contr_reg[0] = 0x02;
|
||||
if (i2c_write (contr_r_addr[0], 0xff, 1, contr_reg, 1) != 0) {
|
||||
rcode = 1;
|
||||
}
|
||||
|
||||
/* Set register write enable latch.
|
||||
*/
|
||||
contr_reg[0] = 0x06;
|
||||
if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
|
||||
rcode = 1;
|
||||
}
|
||||
|
||||
/* Modify ctrl register.
|
||||
*/
|
||||
contr_reg[0] = ctrl_reg_v;
|
||||
if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
|
||||
rcode = 1;
|
||||
}
|
||||
|
||||
/* The write (above) is an operation on NV memory.
|
||||
* These can take some time (~5ms), and the device
|
||||
* will not respond to further I2C messages till
|
||||
* it's completed the write.
|
||||
* So poll device for an I2C acknowledge.
|
||||
* When we get one we know we can continue with other
|
||||
* operations.
|
||||
*/
|
||||
contr_reg[0] = 0;
|
||||
for (i = 0; i < MAX_ACKNOWLEDGE_POLLS; i++) {
|
||||
if (i2c_read (addr_void[0], addr_void[1], 1, contr_reg, 1) == 0)
|
||||
break; /* got ack */
|
||||
#if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
|
||||
udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
|
||||
#endif
|
||||
}
|
||||
if (i == MAX_ACKNOWLEDGE_POLLS) {
|
||||
puts ("EEPROM poll acknowledge failed\n");
|
||||
rcode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is the write enable latch on?.
|
||||
*/
|
||||
else if (!(ctrl_reg_v & 0x02)) {
|
||||
/* Set write enable latch.
|
||||
*/
|
||||
contr_reg[0] = 0x02;
|
||||
if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
|
||||
rcode = 1;
|
||||
}
|
||||
}
|
||||
/* Write is enabled ... now write eeprom value.
|
||||
*/
|
||||
#endif
|
||||
if (i2c_write (addr[0], offset, alen-1, buffer, len) != 0)
|
||||
rcode = 1;
|
||||
|
||||
#endif
|
||||
buffer += len;
|
||||
offset += len;
|
||||
|
||||
#if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
|
||||
udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
|
||||
#endif
|
||||
}
|
||||
#if defined(CFG_EEPROM_WREN)
|
||||
eeprom_write_enable (dev_addr,0);
|
||||
#endif
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPI
|
||||
int
|
||||
eeprom_probe (unsigned dev_addr, unsigned offset)
|
||||
{
|
||||
unsigned char chip;
|
||||
|
||||
/* Probe the chip address
|
||||
*/
|
||||
#if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
|
||||
chip = offset >> 8; /* block number */
|
||||
#else
|
||||
chip = offset >> 16; /* block number */
|
||||
#endif /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
|
||||
|
||||
chip |= dev_addr; /* insert device address */
|
||||
|
||||
return (i2c_probe (chip));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Set default values
|
||||
*/
|
||||
#ifndef CFG_I2C_SPEED
|
||||
#define CFG_I2C_SPEED 50000
|
||||
#endif
|
||||
|
||||
#ifndef CFG_I2C_SLAVE
|
||||
#define CFG_I2C_SLAVE 0xFE
|
||||
#endif
|
||||
|
||||
void eeprom_init (void)
|
||||
{
|
||||
#if defined(CONFIG_SPI)
|
||||
spi_init_f ();
|
||||
#endif
|
||||
#if defined(CONFIG_HARD_I2C) || \
|
||||
defined(CONFIG_SOFT_I2C)
|
||||
i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
#endif /* CFG_CMD_EEPROM */
|
||||
/***************************************************/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM)
|
||||
|
||||
#ifdef CFG_I2C_MULTI_EEPROMS
|
||||
U_BOOT_CMD(
|
||||
eeprom, 6, 1, do_eeprom,
|
||||
"eeprom - EEPROM sub-system\n",
|
||||
"read devaddr addr off cnt\n"
|
||||
"eeprom write devaddr addr off cnt\n"
|
||||
" - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'\n"
|
||||
);
|
||||
#else /* One EEPROM */
|
||||
U_BOOT_CMD(
|
||||
eeprom, 5, 1, do_eeprom,
|
||||
"eeprom - EEPROM sub-system\n",
|
||||
"read addr off cnt\n"
|
||||
"eeprom write addr off cnt\n"
|
||||
" - read/write `cnt' bytes at EEPROM offset `off'\n"
|
||||
);
|
||||
#endif /* CFG_I2C_MULTI_EEPROMS */
|
||||
|
||||
#endif /* CFG_CMD_EEPROM */
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
* Copyright (c) 2001 William L. Pitts
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are freely
|
||||
* permitted provided that the above copyright notice and this
|
||||
* paragraph and the following disclaimer are duplicated in all
|
||||
* such forms.
|
||||
*
|
||||
* This software is provided "AS IS" and without any express or
|
||||
* implied warranties, including, without limitation, the implied
|
||||
* warranties of merchantability and fitness for a particular
|
||||
* purpose.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <net.h>
|
||||
#include <elf.h>
|
||||
|
||||
#if defined(CONFIG_WALNUT) || defined(CFG_VXWORKS_MAC_PTR)
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ELF)
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
int valid_elf_image (unsigned long addr);
|
||||
unsigned long load_elf_image (unsigned long addr);
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to boot an arbitrary ELF image from memory.
|
||||
* ====================================================================== */
|
||||
int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long addr; /* Address of the ELF image */
|
||||
unsigned long rc; /* Return value from user code */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
int rcode = 0;
|
||||
|
||||
if (argc < 2)
|
||||
addr = load_addr;
|
||||
else
|
||||
addr = simple_strtoul (argv[1], NULL, 16);
|
||||
|
||||
if (!valid_elf_image (addr))
|
||||
return 1;
|
||||
|
||||
addr = load_elf_image (addr);
|
||||
|
||||
printf ("## Starting application at 0x%08lx ...\n", addr);
|
||||
|
||||
/*
|
||||
* QNX images require the data cache is disabled.
|
||||
* Data cache is already flushed, so just turn it off.
|
||||
*/
|
||||
if (dcache_status ())
|
||||
dcache_disable ();
|
||||
|
||||
/*
|
||||
* pass address parameter as argv[0] (aka command name),
|
||||
* and all remaining args
|
||||
*/
|
||||
rc = ((ulong (*)(int, char *[])) addr) (--argc, &argv[1]);
|
||||
if (rc != 0)
|
||||
rcode = 1;
|
||||
|
||||
printf ("## Application terminated, rc = 0x%lx\n", rc);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* Interpreter command to boot VxWorks from a memory image. The image can
|
||||
* be either an ELF image or a raw binary. Will attempt to setup the
|
||||
* bootline and other parameters correctly.
|
||||
* ====================================================================== */
|
||||
int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unsigned long addr; /* Address of image */
|
||||
unsigned long bootaddr; /* Address to put the bootline */
|
||||
char *bootline; /* Text of the bootline */
|
||||
char *tmp; /* Temporary char pointer */
|
||||
|
||||
#if defined(CONFIG_4xx) || defined(CONFIG_IOP480)
|
||||
char build_buf[80]; /* Buffer for building the bootline */
|
||||
#endif
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Check the loadaddr variable.
|
||||
* If we don't know where the image is then we're done.
|
||||
*/
|
||||
|
||||
if ((tmp = getenv ("loadaddr")) != NULL) {
|
||||
addr = simple_strtoul (tmp, NULL, 16);
|
||||
} else {
|
||||
puts ("No load address provided\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
/* Check to see if we need to tftp the image ourselves before starting */
|
||||
|
||||
if ((argc == 2) && (strcmp (argv[1], "tftp") == 0)) {
|
||||
if (NetLoop (TFTP) <= 0)
|
||||
return 1;
|
||||
printf ("Automatic boot of VxWorks image at address 0x%08lx ... \n", addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This should equate
|
||||
* to NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
|
||||
* from the VxWorks BSP header files.
|
||||
* This will vary from board to board
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_WALNUT)
|
||||
tmp = (char *) CFG_NVRAM_BASE_ADDR + 0x500;
|
||||
memcpy ((char *) tmp, (char *) &gd->bd->bi_enetaddr[3], 3);
|
||||
#elif defined(CFG_VXWORKS_MAC_PTR)
|
||||
tmp = (char *) CFG_VXWORKS_MAC_PTR;
|
||||
memcpy ((char *) tmp, (char *) &gd->bd->bi_enetaddr[0], 6);
|
||||
#else
|
||||
puts ("## Ethernet MAC address not copied to NV RAM\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use bootaddr to find the location in memory that VxWorks
|
||||
* will look for the bootline string. The default value for
|
||||
* PowerPC is LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET which
|
||||
* defaults to 0x4200
|
||||
*/
|
||||
|
||||
if ((tmp = getenv ("bootaddr")) == NULL)
|
||||
bootaddr = 0x4200;
|
||||
else
|
||||
bootaddr = simple_strtoul (tmp, NULL, 16);
|
||||
|
||||
/*
|
||||
* Check to see if the bootline is defined in the 'bootargs'
|
||||
* parameter. If it is not defined, we may be able to
|
||||
* construct the info
|
||||
*/
|
||||
|
||||
if ((bootline = getenv ("bootargs")) != NULL) {
|
||||
memcpy ((void *) bootaddr, bootline, MAX(strlen(bootline), 255));
|
||||
flush_cache (bootaddr, MAX(strlen(bootline), 255));
|
||||
} else {
|
||||
#if defined(CONFIG_4xx)
|
||||
sprintf (build_buf, "ibmEmac(0,0)");
|
||||
|
||||
if ((tmp = getenv ("hostname")) != NULL) {
|
||||
sprintf (&build_buf[strlen (build_buf - 1)],
|
||||
"host:%s ", tmp);
|
||||
} else {
|
||||
sprintf (&build_buf[strlen (build_buf - 1)],
|
||||
": ");
|
||||
}
|
||||
|
||||
if ((tmp = getenv ("ipaddr")) != NULL) {
|
||||
sprintf (&build_buf[strlen (build_buf - 1)],
|
||||
"e=%s ", tmp);
|
||||
}
|
||||
memcpy ((void *)bootaddr, build_buf, MAX(strlen(build_buf), 255));
|
||||
flush_cache (bootaddr, MAX(strlen(build_buf), 255));
|
||||
#elif defined(CONFIG_IOP480)
|
||||
sprintf (build_buf, "dc(0,0)");
|
||||
|
||||
if ((tmp = getenv ("hostname")) != NULL) {
|
||||
sprintf (&build_buf[strlen (build_buf - 1)],
|
||||
"host:%s ", tmp);
|
||||
} else {
|
||||
sprintf (&build_buf[strlen (build_buf - 1)],
|
||||
": ");
|
||||
}
|
||||
|
||||
if ((tmp = getenv ("ipaddr")) != NULL) {
|
||||
sprintf (&build_buf[strlen (build_buf - 1)],
|
||||
"e=%s ", tmp);
|
||||
}
|
||||
memcpy ((void *) bootaddr, build_buf, MAX(strlen(build_buf), 255));
|
||||
flush_cache (bootaddr, MAX(strlen(build_buf), 255));
|
||||
#else
|
||||
|
||||
/*
|
||||
* I'm not sure what the device should be for other
|
||||
* PPC flavors, the hostname and ipaddr should be ok
|
||||
* to just copy
|
||||
*/
|
||||
|
||||
puts ("No bootargs defined\n");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* If the data at the load address is an elf image, then
|
||||
* treat it like an elf image. Otherwise, assume that it is a
|
||||
* binary image
|
||||
*/
|
||||
|
||||
if (valid_elf_image (addr)) {
|
||||
addr = load_elf_image (addr);
|
||||
} else {
|
||||
puts ("## Not an ELF image, assuming binary\n");
|
||||
/* leave addr as load_addr */
|
||||
}
|
||||
|
||||
printf ("## Using bootline (@ 0x%lx): %s\n", bootaddr,
|
||||
(char *) bootaddr);
|
||||
printf ("## Starting vxWorks at 0x%08lx ...\n", addr);
|
||||
|
||||
((void (*)(void)) addr) ();
|
||||
|
||||
puts ("## vxWorks terminated\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ======================================================================
|
||||
* Determine if a valid ELF image exists at the given memory location.
|
||||
* First looks at the ELF header magic field, the makes sure that it is
|
||||
* executable and makes sure that it is for a PowerPC.
|
||||
* ====================================================================== */
|
||||
int valid_elf_image (unsigned long addr)
|
||||
{
|
||||
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
ehdr = (Elf32_Ehdr *) addr;
|
||||
|
||||
if (!IS_ELF (*ehdr)) {
|
||||
printf ("## No elf image at address 0x%08lx\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ehdr->e_type != ET_EXEC) {
|
||||
printf ("## Not a 32-bit elf image at address 0x%08lx\n",
|
||||
addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (ehdr->e_machine != EM_PPC) {
|
||||
printf ("## Not a PowerPC elf image at address 0x%08lx\n",
|
||||
addr);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ======================================================================
|
||||
* A very simple elf loader, assumes the image is valid, returns the
|
||||
* entry point address.
|
||||
* ====================================================================== */
|
||||
unsigned long load_elf_image (unsigned long addr)
|
||||
{
|
||||
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
|
||||
Elf32_Shdr *shdr; /* Section header structure pointer */
|
||||
unsigned char *strtab = 0; /* String table pointer */
|
||||
unsigned char *image; /* Binary image pointer */
|
||||
int i; /* Loop counter */
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
ehdr = (Elf32_Ehdr *) addr;
|
||||
|
||||
/* Find the section header string table for output info */
|
||||
shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff +
|
||||
(ehdr->e_shstrndx * sizeof (Elf32_Shdr)));
|
||||
|
||||
if (shdr->sh_type == SHT_STRTAB)
|
||||
strtab = (unsigned char *) (addr + shdr->sh_offset);
|
||||
|
||||
/* Load each appropriate section */
|
||||
for (i = 0; i < ehdr->e_shnum; ++i) {
|
||||
shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff +
|
||||
(i * sizeof (Elf32_Shdr)));
|
||||
|
||||
if (!(shdr->sh_flags & SHF_ALLOC)
|
||||
|| shdr->sh_addr == 0 || shdr->sh_size == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strtab) {
|
||||
printf ("%sing %s @ 0x%08lx (%ld bytes)\n",
|
||||
(shdr->sh_type == SHT_NOBITS) ?
|
||||
"Clear" : "Load",
|
||||
&strtab[shdr->sh_name],
|
||||
(unsigned long) shdr->sh_addr,
|
||||
(long) shdr->sh_size);
|
||||
}
|
||||
|
||||
if (shdr->sh_type == SHT_NOBITS) {
|
||||
memset ((void *)shdr->sh_addr, 0, shdr->sh_size);
|
||||
} else {
|
||||
image = (unsigned char *) addr + shdr->sh_offset;
|
||||
memcpy ((void *) shdr->sh_addr,
|
||||
(const void *) image,
|
||||
shdr->sh_size);
|
||||
}
|
||||
flush_cache (shdr->sh_addr, shdr->sh_size);
|
||||
}
|
||||
|
||||
return ehdr->e_entry;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
U_BOOT_CMD(
|
||||
bootelf, 2, 0, do_bootelf,
|
||||
"bootelf - Boot from an ELF image in memory\n",
|
||||
" [address] - load address of ELF image.\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
bootvx, 2, 0, do_bootvx,
|
||||
"bootvx - Boot vxWorks from an ELF image\n",
|
||||
" [address] - load address of vxWorks ELF image.\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_ELF */
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPI Read/Write Utilities
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ETHREG)
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Definitions
|
||||
*/
|
||||
#ifdef CFG_ATHRS26_PHY
|
||||
extern unsigned int s26_rd_phy(unsigned int phy_addr, unsigned int reg_addr);
|
||||
extern void s26_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data);
|
||||
extern uint32_t athrs26_reg_read(uint32_t reg_addr);
|
||||
extern void athrs26_reg_write(uint32_t reg_addr, uint32_t reg_val);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_ATHRS27_PHY
|
||||
extern unsigned int s27_rd_phy(unsigned int phy_addr, unsigned int reg_addr);
|
||||
extern void s27_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data);
|
||||
extern uint32_t athrs27_reg_read(uint32_t reg_addr);
|
||||
extern void athrs27_reg_write(uint32_t reg_addr, uint32_t reg_val);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AR7242_S16_PHY
|
||||
extern uint32_t athrs16_reg_read(uint32_t reg_addr);
|
||||
extern void athrs16_reg_write(uint32_t reg_addr, uint32_t reg_val);
|
||||
extern int ag7240_miiphy_read(char *devname, uint32_t phaddr,
|
||||
uint8_t reg);
|
||||
extern int ag7240_miiphy_write(char *devname, uint32_t phaddr,
|
||||
uint8_t reg, uint16_t data);
|
||||
#endif
|
||||
|
||||
|
||||
#define READ_MAC 0x01
|
||||
#define WRITE_MAC 0x02
|
||||
#define READ_PHY 0x10
|
||||
#define WRITE_PHY 0x20
|
||||
|
||||
/*
|
||||
* Values from last command.
|
||||
*/
|
||||
static int reg;
|
||||
static int val,rd_value;
|
||||
static int phyaddr;
|
||||
static int portnum;
|
||||
|
||||
int do_ethreg (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int rcode = 0;
|
||||
|
||||
/*
|
||||
* We use the last specified parameters, unless new ones are
|
||||
* entered.
|
||||
*/
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0)
|
||||
{
|
||||
if (argc == 2) {
|
||||
reg = simple_strtoul(argv[1], NULL, 10);
|
||||
rcode = READ_MAC;
|
||||
}
|
||||
if (argc == 3) {
|
||||
reg = simple_strtoul(argv[1], NULL, 10);
|
||||
val = simple_strtoul(argv[2],NULL,10);
|
||||
rcode = WRITE_MAC;
|
||||
}
|
||||
if (argc == 4) {
|
||||
if(*argv[1] == 'p') {
|
||||
portnum = simple_strtoul(argv[2], NULL, 10);
|
||||
reg = simple_strtoul(argv[3],NULL,10);
|
||||
rcode = READ_PHY;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
if (argc == 5) {
|
||||
if(*argv[1] == 'p') {
|
||||
portnum = simple_strtoul(argv[2], NULL, 10);
|
||||
reg = simple_strtoul(argv[3],NULL,10);
|
||||
val = simple_strtoul(argv[4],NULL,10);
|
||||
rcode = WRITE_PHY;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((argc > 4) && (argc < 2))
|
||||
return 1;
|
||||
}
|
||||
#ifdef CONFIG_AR7242_S16_PHY
|
||||
if(rcode == READ_PHY) {
|
||||
rd_value = ag7240_miiphy_read("eth0",portnum,reg);
|
||||
printf("Read Reg: 0x%08x = 0x%08x\n",reg,rd_value);
|
||||
}
|
||||
else if(rcode == READ_MAC) {
|
||||
rd_value = athrs16_reg_read(reg);
|
||||
printf("Read Reg: 0x%08x = 0x%08x\n",reg,rd_value);
|
||||
}
|
||||
else if(rcode == WRITE_PHY) {
|
||||
rd_value = ag7240_miiphy_read("eth0",portnum,reg);
|
||||
ag7240_miiphy_write("eth0",portnum,reg,val);
|
||||
printf("Write Reg: 0x%08x: Oldval = 0x%08x Newval = 0x%08x\n", reg, rd_value, val);
|
||||
}
|
||||
else if(rcode == WRITE_MAC) {
|
||||
rd_value = athrs16_reg_read(reg);
|
||||
athrs16_reg_write(reg,val);
|
||||
printf("Write Reg: 0x%08x: Oldval = 0x%08x Newval = 0x%08x\n", reg, rd_value, val);
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef CFG_ATHRS26_PHY
|
||||
if(rcode == READ_PHY) {
|
||||
rd_value = s26_rd_phy(portnum,reg);
|
||||
printf("Read Reg: 0x%08x = 0x%08x\n",reg,rd_value);
|
||||
}
|
||||
else if(rcode == READ_MAC) {
|
||||
rd_value = athrs26_reg_read(reg);
|
||||
printf("Read Reg: 0x%08x = 0x%08x\n",reg,rd_value);
|
||||
}
|
||||
else if(rcode == WRITE_PHY) {
|
||||
rd_value = s26_rd_phy(portnum,reg);
|
||||
s26_wr_phy(portnum,reg,val);
|
||||
printf("Write Reg: 0x%08x: Oldval = 0x%08x Newval = 0x%08x\n", reg, rd_value, val);
|
||||
}
|
||||
else if(rcode == WRITE_MAC) {
|
||||
rd_value = athrs26_reg_read(reg);
|
||||
athrs26_reg_write(reg,val);
|
||||
printf("Write Reg: 0x%08x: Oldval = 0x%08x Newval = 0x%08x\n", reg, rd_value, val);
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef CFG_ATHRS27_PHY
|
||||
if(rcode == READ_PHY) {
|
||||
rd_value = s27_rd_phy(portnum,reg);
|
||||
printf("Read Reg: 0x%08x = 0x%08x\n",reg,rd_value);
|
||||
}
|
||||
else if(rcode == READ_MAC) {
|
||||
rd_value = athrs27_reg_read(reg);
|
||||
printf("Read Reg: 0x%08x = 0x%08x\n",reg,rd_value);
|
||||
}
|
||||
else if(rcode == WRITE_PHY) {
|
||||
rd_value = s27_rd_phy(portnum,reg);
|
||||
s27_wr_phy(portnum,reg,val);
|
||||
printf("Write Reg: 0x%08x: Oldval = 0x%08x Newval = 0x%08x\n", reg, rd_value, val);
|
||||
}
|
||||
else if(rcode == WRITE_MAC) {
|
||||
rd_value = athrs27_reg_read(reg);
|
||||
athrs27_reg_write(reg,val);
|
||||
printf("Write Reg: 0x%08x: Oldval = 0x%08x Newval = 0x%08x\n", reg, rd_value, val);
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
ethreg, 6, 1, do_ethreg,
|
||||
"ethreg - S26 PHY Reg rd/wr utility\n",
|
||||
"<p> <phyaddr> <reg> <value> - Send <bit_len> bits from <dout> out the SPI\n"
|
||||
"<p> - operates on the phy; by default is rd/wr s26 mac registers\n"
|
||||
"<phyaddr> - Address of the phy\n"
|
||||
"<reg> - Register offset\n"
|
||||
"<value> - value to write\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_SPI */
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* (C) Copyright 2004
|
||||
* esd gmbh <www.esd-electronics.com>
|
||||
* Reinhard Arlt <reinhard.arlt@esd-electronics.com>
|
||||
*
|
||||
* made from cmd_reiserfs by
|
||||
*
|
||||
* (C) Copyright 2003 - 2004
|
||||
* Sysgo Real-Time Solutions, AG <www.elinos.com>
|
||||
* Pavel Bartusek <pba@sysgo.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ext2fs support
|
||||
*/
|
||||
#include <common.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_EXT2)
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <ext2fs.h>
|
||||
#if ((CONFIG_COMMANDS & CFG_CMD_USB) && defined(CONFIG_USB_STORAGE))
|
||||
#include <usb.h>
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DOS_PARTITION
|
||||
#error DOS partition support must be selected
|
||||
#endif
|
||||
|
||||
/* #define EXT2_DEBUG */
|
||||
|
||||
#ifdef EXT2_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
static block_dev_desc_t *get_dev (char* ifname, int dev)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IDE)
|
||||
if (strncmp(ifname,"ide",3)==0) {
|
||||
extern block_dev_desc_t * ide_get_dev(int dev);
|
||||
return((dev >= CFG_IDE_MAXDEVICE) ? NULL : ide_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
|
||||
if (strncmp(ifname,"scsi",4)==0) {
|
||||
extern block_dev_desc_t * scsi_get_dev(int dev);
|
||||
return((dev >= CFG_SCSI_MAXDEVICE) ? NULL : scsi_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if ((CONFIG_COMMANDS & CFG_CMD_USB) && defined(CONFIG_USB_STORAGE))
|
||||
if (strncmp(ifname,"usb",3)==0) {
|
||||
extern block_dev_desc_t * usb_stor_get_dev(int dev);
|
||||
return((dev >= USB_MAX_STOR_DEV) ? NULL : usb_stor_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_MMC)
|
||||
if (strncmp(ifname,"mmc",3)==0) {
|
||||
extern block_dev_desc_t * mmc_get_dev(int dev);
|
||||
return((dev >= 1) ? NULL : mmc_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_SYSTEMACE)
|
||||
if (strcmp(ifname,"ace")==0) {
|
||||
extern block_dev_desc_t * systemace_get_dev(int dev);
|
||||
return((dev >= 1) ? NULL : systemace_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int do_ext2ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *filename = "/";
|
||||
int dev=0;
|
||||
int part=1;
|
||||
char *ep;
|
||||
block_dev_desc_t *dev_desc=NULL;
|
||||
int part_length;
|
||||
|
||||
if (argc < 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return(1);
|
||||
}
|
||||
dev = (int)simple_strtoul (argv[2], &ep, 16);
|
||||
dev_desc=get_dev(argv[1],dev);
|
||||
|
||||
if (dev_desc == NULL) {
|
||||
printf ("\n** Block device %s %d not supported\n", argv[1], dev);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (*ep) {
|
||||
if (*ep != ':') {
|
||||
puts ("\n** Invalid boot device, use `dev[:part]' **\n");
|
||||
return(1);
|
||||
}
|
||||
part = (int)simple_strtoul(++ep, NULL, 16);
|
||||
}
|
||||
|
||||
if (argc == 4) {
|
||||
filename = argv[3];
|
||||
}
|
||||
|
||||
PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
|
||||
|
||||
if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
|
||||
printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part);
|
||||
ext2fs_close();
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (!ext2fs_mount(part_length)) {
|
||||
printf ("** Bad ext2 partition or disk - %s %d:%d **\n", argv[1], dev, part);
|
||||
ext2fs_close();
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (ext2fs_ls (filename)) {
|
||||
printf ("** Error ext2fs_ls() **\n");
|
||||
ext2fs_close();
|
||||
return(1);
|
||||
};
|
||||
|
||||
ext2fs_close();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
ext2ls, 4, 1, do_ext2ls,
|
||||
"ext2ls - list files in a directory (default /)\n",
|
||||
"<interface> <dev[:part]> [directory]\n"
|
||||
" - list files from 'dev' on 'interface' in a 'directory'\n"
|
||||
);
|
||||
|
||||
/******************************************************************************
|
||||
* Ext2fs boot command intepreter. Derived from diskboot
|
||||
*/
|
||||
int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *filename = NULL;
|
||||
char *ep;
|
||||
int dev, part = 1;
|
||||
ulong addr = 0, part_length, filelen;
|
||||
disk_partition_t info;
|
||||
block_dev_desc_t *dev_desc = NULL;
|
||||
char buf [12];
|
||||
unsigned long count;
|
||||
char *addr_str;
|
||||
|
||||
switch (argc) {
|
||||
case 3:
|
||||
addr_str = getenv("loadaddr");
|
||||
if (addr_str != NULL) {
|
||||
addr = simple_strtoul (addr_str, NULL, 16);
|
||||
} else {
|
||||
addr = CFG_LOAD_ADDR;
|
||||
}
|
||||
filename = getenv ("bootfile");
|
||||
count = 0;
|
||||
break;
|
||||
case 4:
|
||||
addr = simple_strtoul (argv[3], NULL, 16);
|
||||
filename = getenv ("bootfile");
|
||||
count = 0;
|
||||
break;
|
||||
case 5:
|
||||
addr = simple_strtoul (argv[3], NULL, 16);
|
||||
filename = argv[4];
|
||||
count = 0;
|
||||
break;
|
||||
case 6:
|
||||
addr = simple_strtoul (argv[3], NULL, 16);
|
||||
filename = argv[4];
|
||||
count = simple_strtoul (argv[5], NULL, 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
puts ("\n** No boot file defined **\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
dev = (int)simple_strtoul (argv[2], &ep, 16);
|
||||
dev_desc=get_dev(argv[1],dev);
|
||||
if (dev_desc==NULL) {
|
||||
printf ("\n** Block device %s %d not supported\n", argv[1], dev);
|
||||
return(1);
|
||||
}
|
||||
if (*ep) {
|
||||
if (*ep != ':') {
|
||||
puts ("\n** Invalid boot device, use `dev[:part]' **\n");
|
||||
return(1);
|
||||
}
|
||||
part = (int)simple_strtoul(++ep, NULL, 16);
|
||||
}
|
||||
|
||||
PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part);
|
||||
|
||||
if (part != 0) {
|
||||
if (get_partition_info (dev_desc, part, &info)) {
|
||||
printf ("** Bad partition %d **\n", part);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
|
||||
printf ("\n** Invalid partition type \"%.32s\""
|
||||
" (expect \"" BOOT_PART_TYPE "\")\n",
|
||||
info.type);
|
||||
return(1);
|
||||
}
|
||||
PRINTF ("\nLoading from block device %s device %d, partition %d: "
|
||||
"Name: %.32s Type: %.32s File:%s\n",
|
||||
argv[1], dev, part, info.name, info.type, filename);
|
||||
} else {
|
||||
PRINTF ("\nLoading from block device %s device %d, File:%s\n",
|
||||
argv[1], dev, filename);
|
||||
}
|
||||
|
||||
|
||||
if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) {
|
||||
printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part);
|
||||
ext2fs_close();
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (!ext2fs_mount(part_length)) {
|
||||
printf ("** Bad ext2 partition or disk - %s %d:%d **\n", argv[1], dev, part);
|
||||
ext2fs_close();
|
||||
return(1);
|
||||
}
|
||||
|
||||
filelen = ext2fs_open(filename);
|
||||
if (filelen < 0) {
|
||||
printf("** File not found %s\n", filename);
|
||||
ext2fs_close();
|
||||
return(1);
|
||||
}
|
||||
if ((count < filelen) && (count != 0)) {
|
||||
filelen = count;
|
||||
}
|
||||
|
||||
if (ext2fs_read((char *)addr, filelen) != filelen) {
|
||||
printf("\n** Unable to read \"%s\" from %s %d:%d **\n", filename, argv[1], dev, part);
|
||||
ext2fs_close();
|
||||
return(1);
|
||||
}
|
||||
|
||||
ext2fs_close();
|
||||
|
||||
/* Loading ok, update default load address */
|
||||
load_addr = addr;
|
||||
|
||||
printf ("\n%ld bytes read\n", filelen);
|
||||
sprintf(buf, "%lX", filelen);
|
||||
setenv("filesize", buf);
|
||||
|
||||
return(filelen);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
ext2load, 6, 0, do_ext2load,
|
||||
"ext2load- load binary file from a Ext2 filesystem\n",
|
||||
"<interface> <dev[:part]> [addr] [filename] [bytes]\n"
|
||||
" - load binary file 'filename' from 'dev' on 'interface'\n"
|
||||
" to address 'addr' from ext2 filesystem\n"
|
||||
);
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_EXT2 */
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Richard Jones, rjones@nexus-tech.net
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* Boot support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <s_record.h>
|
||||
#include <net.h>
|
||||
#include <ata.h>
|
||||
#include <part.h>
|
||||
#include <fat.h>
|
||||
#include <fs.h>
|
||||
|
||||
int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
return do_load(cmdtp, flag, argc, argv, FS_TYPE_FAT, 16);
|
||||
}
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
fatload, 7, 0, do_fat_fsload,
|
||||
"fatload - load binary file from a dos filesystem\n",
|
||||
"<interface> [<dev[:part]>] <addr> <filename> [bytes [pos]]\n"
|
||||
" - Load binary file 'filename' from 'dev' on 'interface'\n"
|
||||
" to address 'addr' from dos filesystem.\n"
|
||||
" 'pos' gives the file position to start loading from.\n"
|
||||
" If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
|
||||
" 'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
|
||||
" the load stops on end of file.\n"
|
||||
" If either 'pos' or 'bytes' are not aligned to\n"
|
||||
" ARCH_DMA_MINALIGN then a misaligned buffer warning will\n"
|
||||
" be printed and performance will suffer for the load.\n"
|
||||
" All numeric parameters are assumed to be hex."
|
||||
);
|
||||
|
||||
static int do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
return do_ls(cmdtp, flag, argc, argv, FS_TYPE_FAT);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
fatls, 4, 1, do_fat_ls,
|
||||
"fatls - list files in a directory (default /)\n",
|
||||
"<interface> [<dev[:part]>] [directory]\n"
|
||||
" - list files from 'dev' on 'interface' in a 'directory'"
|
||||
);
|
||||
|
||||
static int do_fat_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
int dev, part;
|
||||
block_dev_desc_t *dev_desc;
|
||||
disk_partition_t info;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("usage: fatinfo <interface> [<dev[:part]>]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
|
||||
if (part < 0)
|
||||
return 1;
|
||||
|
||||
dev = dev_desc->dev;
|
||||
if (fat_set_blk_dev(dev_desc, &info) != 0) {
|
||||
printf("\n** Unable to use %s %d:%d for fatinfo **\n",
|
||||
argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
return file_fat_detectfs();
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
fatinfo, 3, 1, do_fat_fsinfo,
|
||||
"fatinfo - print information about filesystem\n",
|
||||
"<interface> [<dev[:part]>]\n"
|
||||
" - print information about filesystem from 'dev' on 'interface'"
|
||||
);
|
||||
|
||||
#ifdef CONFIG_FAT_WRITE
|
||||
static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
long size;
|
||||
unsigned long addr;
|
||||
unsigned long count;
|
||||
block_dev_desc_t *dev_desc = NULL;
|
||||
disk_partition_t info;
|
||||
int dev = 0;
|
||||
int part = 1;
|
||||
|
||||
if (argc < 5)
|
||||
return cmd_usage(cmdtp);
|
||||
|
||||
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
|
||||
if (part < 0)
|
||||
return 1;
|
||||
|
||||
dev = dev_desc->dev;
|
||||
|
||||
if (fat_set_blk_dev(dev_desc, &info) != 0) {
|
||||
printf("\n** Unable to use %s %d:%d for fatwrite **\n",
|
||||
argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
addr = simple_strtoul(argv[3], NULL, 16);
|
||||
count = simple_strtoul(argv[5], NULL, 16);
|
||||
|
||||
size = file_fat_write(argv[4], (void *)addr, count);
|
||||
if (size == -1) {
|
||||
printf("\n** Unable to write \"%s\" from %s %d:%d **\n",
|
||||
argv[4], argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%ld bytes written\n", size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
fatwrite, 6, 0, do_fat_fswrite,
|
||||
"fatwrite- write file into a dos filesystem\n",
|
||||
"<interface> <dev[:part]> <addr> <filename> <bytes>\n"
|
||||
" - write file 'filename' from the address 'addr' in RAM\n"
|
||||
" to 'dev' on 'interface'"
|
||||
);
|
||||
#endif
|
|
@ -0,0 +1,896 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG, d.peter@mpl.ch.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Floppy Disk support
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
|
||||
|
||||
#undef FDC_DEBUG
|
||||
|
||||
#ifdef FDC_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
|
||||
/*#if (CONFIG_COMMANDS & CFG_CMD_DATE) */
|
||||
/*#include <rtc.h> */
|
||||
/*#endif */
|
||||
|
||||
#if ((CONFIG_COMMANDS & CFG_CMD_FDC) || (CONFIG_COMMANDS & CFG_CMD_FDOS))
|
||||
|
||||
|
||||
typedef struct {
|
||||
int flags; /* connected drives ect */
|
||||
unsigned long blnr; /* Logical block nr */
|
||||
uchar drive; /* drive no */
|
||||
uchar cmdlen; /* cmd length */
|
||||
uchar cmd[16]; /* cmd desc */
|
||||
uchar dma; /* if > 0 dma enabled */
|
||||
uchar result[11];/* status information */
|
||||
uchar resultlen; /* lenght of result */
|
||||
} FDC_COMMAND_STRUCT;
|
||||
/* flags: only the lower 8bit used:
|
||||
* bit 0 if set drive 0 is present
|
||||
* bit 1 if set drive 1 is present
|
||||
* bit 2 if set drive 2 is present
|
||||
* bit 3 if set drive 3 is present
|
||||
* bit 4 if set disk in drive 0 is inserted
|
||||
* bit 5 if set disk in drive 1 is inserted
|
||||
* bit 6 if set disk in drive 2 is inserted
|
||||
* bit 7 if set disk in drive 4 is inserted
|
||||
*/
|
||||
|
||||
|
||||
/* cmd indexes */
|
||||
#define COMMAND 0
|
||||
#define DRIVE 1
|
||||
#define CONFIG0 1
|
||||
#define SPEC_HUTSRT 1
|
||||
#define TRACK 2
|
||||
#define CONFIG1 2
|
||||
#define SPEC_HLT 2
|
||||
#define HEAD 3
|
||||
#define CONFIG2 3
|
||||
#define SECTOR 4
|
||||
#define SECTOR_SIZE 5
|
||||
#define LAST_TRACK 6
|
||||
#define GAP 7
|
||||
#define DTL 8
|
||||
/* result indexes */
|
||||
#define STATUS_0 0
|
||||
#define STATUS_PCN 1
|
||||
#define STATUS_1 1
|
||||
#define STATUS_2 2
|
||||
#define STATUS_TRACK 3
|
||||
#define STATUS_HEAD 4
|
||||
#define STATUS_SECT 5
|
||||
#define STATUS_SECT_SIZE 6
|
||||
|
||||
|
||||
/* Register addresses */
|
||||
#define FDC_BASE 0x3F0
|
||||
#define FDC_SRA FDC_BASE + 0 /* Status Register A */
|
||||
#define FDC_SRB FDC_BASE + 1 /* Status Register B */
|
||||
#define FDC_DOR FDC_BASE + 2 /* Digital Output Register */
|
||||
#define FDC_TDR FDC_BASE + 3 /* Tape Drive Register */
|
||||
#define FDC_DSR FDC_BASE + 4 /* Data rate Register */
|
||||
#define FDC_MSR FDC_BASE + 4 /* Main Status Register */
|
||||
#define FDC_FIFO FDC_BASE + 5 /* FIFO */
|
||||
#define FDC_DIR FDC_BASE + 6 /* Digital Input Register */
|
||||
#define FDC_CCR FDC_BASE + 7 /* Configuration Control */
|
||||
/* Commands */
|
||||
#define FDC_CMD_SENSE_INT 0x08
|
||||
#define FDC_CMD_CONFIGURE 0x13
|
||||
#define FDC_CMD_SPECIFY 0x03
|
||||
#define FDC_CMD_RECALIBRATE 0x07
|
||||
#define FDC_CMD_READ 0x06
|
||||
#define FDC_CMD_READ_TRACK 0x02
|
||||
#define FDC_CMD_READ_ID 0x0A
|
||||
#define FDC_CMD_DUMP_REG 0x0E
|
||||
#define FDC_CMD_SEEK 0x0F
|
||||
|
||||
#define FDC_CMD_SENSE_INT_LEN 0x01
|
||||
#define FDC_CMD_CONFIGURE_LEN 0x04
|
||||
#define FDC_CMD_SPECIFY_LEN 0x03
|
||||
#define FDC_CMD_RECALIBRATE_LEN 0x02
|
||||
#define FDC_CMD_READ_LEN 0x09
|
||||
#define FDC_CMD_READ_TRACK_LEN 0x09
|
||||
#define FDC_CMD_READ_ID_LEN 0x02
|
||||
#define FDC_CMD_DUMP_REG_LEN 0x01
|
||||
#define FDC_CMD_SEEK_LEN 0x03
|
||||
|
||||
#define FDC_FIFO_THR 0x0C
|
||||
#define FDC_FIFO_DIS 0x00
|
||||
#define FDC_IMPLIED_SEEK 0x01
|
||||
#define FDC_POLL_DIS 0x00
|
||||
#define FDC_PRE_TRK 0x00
|
||||
#define FDC_CONFIGURE FDC_FIFO_THR | (FDC_POLL_DIS<<4) | (FDC_FIFO_DIS<<5) | (FDC_IMPLIED_SEEK << 6)
|
||||
#define FDC_MFM_MODE 0x01 /* MFM enable */
|
||||
#define FDC_SKIP_MODE 0x00 /* skip enable */
|
||||
|
||||
#define FDC_TIME_OUT 100000 /* time out */
|
||||
#define FDC_RW_RETRIES 3 /* read write retries */
|
||||
#define FDC_CAL_RETRIES 3 /* calibration and seek retries */
|
||||
|
||||
|
||||
/* Disk structure */
|
||||
typedef struct {
|
||||
unsigned int size; /* nr of sectors total */
|
||||
unsigned int sect; /* sectors per track */
|
||||
unsigned int head; /* nr of heads */
|
||||
unsigned int track; /* nr of tracks */
|
||||
unsigned int stretch; /* !=0 means double track steps */
|
||||
unsigned char gap; /* gap1 size */
|
||||
unsigned char rate; /* data rate. |= 0x40 for perpendicular */
|
||||
unsigned char spec1; /* stepping rate, head unload time */
|
||||
unsigned char fmt_gap; /* gap2 size */
|
||||
unsigned char hlt; /* head load time */
|
||||
unsigned char sect_code; /* Sector Size code */
|
||||
const char * name; /* used only for predefined formats */
|
||||
} FD_GEO_STRUCT;
|
||||
|
||||
|
||||
/* supported Floppy types (currently only one) */
|
||||
const static FD_GEO_STRUCT floppy_type[2] = {
|
||||
{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,16,2,"H1440" }, /* 7 1.44MB 3.5" */
|
||||
{ 0, 0,0, 0,0,0x00,0x00,0x00,0x00, 0,0,NULL }, /* end of table */
|
||||
};
|
||||
|
||||
static FDC_COMMAND_STRUCT cmd; /* global command struct */
|
||||
|
||||
/* If the boot drive number is undefined, we assume it's drive 0 */
|
||||
#ifndef CFG_FDC_DRIVE_NUMBER
|
||||
#define CFG_FDC_DRIVE_NUMBER 0
|
||||
#endif
|
||||
|
||||
/* Hardware access */
|
||||
#ifndef CFG_ISA_IO_STRIDE
|
||||
#define CFG_ISA_IO_STRIDE 1
|
||||
#endif
|
||||
|
||||
#ifndef CFG_ISA_IO_OFFSET
|
||||
#define CFG_ISA_IO_OFFSET 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
unsigned char INT6_Status;
|
||||
|
||||
void fdc_interrupt(void)
|
||||
{
|
||||
INT6_Status = 0x80;
|
||||
}
|
||||
|
||||
/* waits for an interrupt (polling) */
|
||||
int wait_for_fdc_int(void)
|
||||
{
|
||||
unsigned long timeout;
|
||||
timeout = FDC_TIME_OUT;
|
||||
while(((volatile)INT6_Status & 0x80) == 0) {
|
||||
timeout--;
|
||||
udelay(10);
|
||||
if(timeout == 0) /* timeout occured */
|
||||
return FALSE;
|
||||
}
|
||||
INT6_Status = 0;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Supporting Functions */
|
||||
/* reads a Register of the FDC */
|
||||
unsigned char read_fdc_reg(unsigned int addr)
|
||||
{
|
||||
volatile unsigned char *val =
|
||||
(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +
|
||||
(addr * CFG_ISA_IO_STRIDE) +
|
||||
CFG_ISA_IO_OFFSET);
|
||||
|
||||
return val [0];
|
||||
}
|
||||
|
||||
/* writes a Register of the FDC */
|
||||
void write_fdc_reg(unsigned int addr, unsigned char val)
|
||||
{
|
||||
volatile unsigned char *tmp =
|
||||
(volatile unsigned char *)(CFG_ISA_IO_BASE_ADDRESS +
|
||||
(addr * CFG_ISA_IO_STRIDE) +
|
||||
CFG_ISA_IO_OFFSET);
|
||||
tmp[0]=val;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_AMIGAONEG3SE
|
||||
/* waits for an interrupt (polling) */
|
||||
int wait_for_fdc_int(void)
|
||||
{
|
||||
unsigned long timeout;
|
||||
timeout = FDC_TIME_OUT;
|
||||
while((read_fdc_reg(FDC_SRA)&0x80)==0) {
|
||||
timeout--;
|
||||
udelay(10);
|
||||
if(timeout==0) /* timeout occured */
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* reads a byte from the FIFO of the FDC and checks direction and RQM bit
|
||||
of the MSR. returns -1 if timeout, or byte if ok */
|
||||
int read_fdc_byte(void)
|
||||
{
|
||||
unsigned long timeout;
|
||||
timeout = FDC_TIME_OUT;
|
||||
while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
|
||||
/* direction out and ready */
|
||||
udelay(10);
|
||||
timeout--;
|
||||
if(timeout==0) /* timeout occured */
|
||||
return -1;
|
||||
}
|
||||
return read_fdc_reg(FDC_FIFO);
|
||||
}
|
||||
|
||||
/* if the direction of the FIFO is wrong, this routine is used to
|
||||
empty the FIFO. Should _not_ be used */
|
||||
int fdc_need_more_output(void)
|
||||
{
|
||||
unsigned char c;
|
||||
while((read_fdc_reg(FDC_MSR)&0xC0)==0xC0) {
|
||||
c=(unsigned char)read_fdc_byte();
|
||||
printf("Error: more output: %x\n",c);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* writes a byte to the FIFO of the FDC and checks direction and RQM bit
|
||||
of the MSR */
|
||||
int write_fdc_byte(unsigned char val)
|
||||
{
|
||||
unsigned long timeout;
|
||||
timeout = FDC_TIME_OUT;
|
||||
while((read_fdc_reg(FDC_MSR)&0xC0)!=0x80) {
|
||||
/* direction in and ready for byte */
|
||||
timeout--;
|
||||
udelay(10);
|
||||
fdc_need_more_output();
|
||||
if(timeout==0) /* timeout occured */
|
||||
return FALSE;
|
||||
}
|
||||
write_fdc_reg(FDC_FIFO,val);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* sets up all FDC commands and issues it to the FDC. If
|
||||
the command causes direct results (no Execution Phase)
|
||||
the result is be read as well. */
|
||||
|
||||
int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
|
||||
{
|
||||
int i;
|
||||
unsigned long head,track,sect,timeout;
|
||||
track = pCMD->blnr / (pFG->sect * pFG->head); /* track nr */
|
||||
sect = pCMD->blnr % (pFG->sect * pFG->head); /* remaining blocks */
|
||||
head = sect / pFG->sect; /* head nr */
|
||||
sect = sect % pFG->sect; /* remaining blocks */
|
||||
sect++; /* sectors are 1 based */
|
||||
PRINTF("Cmd 0x%02x Track %ld, Head %ld, Sector %ld, Drive %d (blnr %ld)\n",
|
||||
pCMD->cmd[0],track,head,sect,pCMD->drive,pCMD->blnr);
|
||||
|
||||
if(head|=0) { /* max heads = 2 */
|
||||
pCMD->cmd[DRIVE]=pCMD->drive | 0x04; /* head 1 */
|
||||
pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
|
||||
}
|
||||
else {
|
||||
pCMD->cmd[DRIVE]=pCMD->drive; /* head 0 */
|
||||
pCMD->cmd[HEAD]=(unsigned char) head; /* head register */
|
||||
}
|
||||
pCMD->cmd[TRACK]=(unsigned char) track; /* track */
|
||||
switch (pCMD->cmd[COMMAND]) {
|
||||
case FDC_CMD_READ:
|
||||
pCMD->cmd[SECTOR]=(unsigned char) sect; /* sector */
|
||||
pCMD->cmd[SECTOR_SIZE]=pFG->sect_code; /* sector size code */
|
||||
pCMD->cmd[LAST_TRACK]=pFG->sect; /* End of track */
|
||||
pCMD->cmd[GAP]=pFG->gap; /* gap */
|
||||
pCMD->cmd[DTL]=0xFF; /* DTL */
|
||||
pCMD->cmdlen=FDC_CMD_READ_LEN;
|
||||
pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
|
||||
pCMD->cmd[COMMAND]|=(FDC_SKIP_MODE<<5); /* set Skip bit */
|
||||
pCMD->resultlen=0; /* result only after execution */
|
||||
break;
|
||||
case FDC_CMD_SEEK:
|
||||
pCMD->cmdlen=FDC_CMD_SEEK_LEN;
|
||||
pCMD->resultlen=0; /* no result */
|
||||
break;
|
||||
case FDC_CMD_CONFIGURE:
|
||||
pCMD->cmd[CONFIG0]=0;
|
||||
pCMD->cmd[CONFIG1]=FDC_CONFIGURE; /* FIFO Threshold, Poll, Enable FIFO */
|
||||
pCMD->cmd[CONFIG2]=FDC_PRE_TRK; /* Precompensation Track */
|
||||
pCMD->cmdlen=FDC_CMD_CONFIGURE_LEN;
|
||||
pCMD->resultlen=0; /* no result */
|
||||
break;
|
||||
case FDC_CMD_SPECIFY:
|
||||
pCMD->cmd[SPEC_HUTSRT]=pFG->spec1;
|
||||
pCMD->cmd[SPEC_HLT]=(pFG->hlt)<<1; /* head load time */
|
||||
if(pCMD->dma==0)
|
||||
pCMD->cmd[SPEC_HLT]|=0x1; /* no dma */
|
||||
pCMD->cmdlen=FDC_CMD_SPECIFY_LEN;
|
||||
pCMD->resultlen=0; /* no result */
|
||||
break;
|
||||
case FDC_CMD_DUMP_REG:
|
||||
pCMD->cmdlen=FDC_CMD_DUMP_REG_LEN;
|
||||
pCMD->resultlen=10; /* 10 byte result */
|
||||
break;
|
||||
case FDC_CMD_READ_ID:
|
||||
pCMD->cmd[COMMAND]|=(FDC_MFM_MODE<<6); /* set MFM bit */
|
||||
pCMD->cmdlen=FDC_CMD_READ_ID_LEN;
|
||||
pCMD->resultlen=7; /* 7 byte result */
|
||||
break;
|
||||
case FDC_CMD_RECALIBRATE:
|
||||
pCMD->cmd[DRIVE]&=0x03; /* don't set the head bit */
|
||||
pCMD->cmdlen=FDC_CMD_RECALIBRATE_LEN;
|
||||
pCMD->resultlen=0; /* no result */
|
||||
break;
|
||||
break;
|
||||
case FDC_CMD_SENSE_INT:
|
||||
pCMD->cmdlen=FDC_CMD_SENSE_INT_LEN;
|
||||
pCMD->resultlen=2;
|
||||
break;
|
||||
}
|
||||
for(i=0;i<pCMD->cmdlen;i++) {
|
||||
/* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */
|
||||
if(write_fdc_byte(pCMD->cmd[i])==FALSE) {
|
||||
PRINTF("Error: timeout while issue cmd%d\n",i);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
timeout=FDC_TIME_OUT;
|
||||
for(i=0;i<pCMD->resultlen;i++) {
|
||||
while((read_fdc_reg(FDC_MSR)&0xC0)!=0xC0) {
|
||||
timeout--;
|
||||
if(timeout==0) {
|
||||
PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
pCMD->result[i]=(unsigned char)read_fdc_byte();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* selects the drive assigned in the cmd structur and
|
||||
switches on the Motor */
|
||||
void select_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
val=(1<<(4+pCMD->drive))|pCMD->drive|0xC; /* set reset, dma gate and motor bits */
|
||||
if((read_fdc_reg(FDC_DOR)&val)!=val) {
|
||||
write_fdc_reg(FDC_DOR,val);
|
||||
for(val=0;val<255;val++)
|
||||
udelay(500); /* wait some time to start motor */
|
||||
}
|
||||
}
|
||||
|
||||
/* switches off the Motor of the specified drive */
|
||||
void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
val=(1<<(4+pCMD->drive))|pCMD->drive; /* sets motor bits */
|
||||
write_fdc_reg(FDC_DOR,(read_fdc_reg(FDC_DOR)&~val));
|
||||
}
|
||||
|
||||
/* issues a recalibrate command, waits for interrupt and
|
||||
* issues a sense_interrupt */
|
||||
int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
|
||||
{
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE;
|
||||
if(fdc_issue_cmd(pCMD,pFG)==FALSE)
|
||||
return FALSE;
|
||||
while(wait_for_fdc_int()!=TRUE);
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
|
||||
return(fdc_issue_cmd(pCMD,pFG));
|
||||
}
|
||||
|
||||
/* issues a recalibrate command, waits for interrupt and
|
||||
* issues a sense_interrupt */
|
||||
int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)
|
||||
{
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_SEEK;
|
||||
if(fdc_issue_cmd(pCMD,pFG)==FALSE)
|
||||
return FALSE;
|
||||
while(wait_for_fdc_int()!=TRUE);
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
|
||||
return(fdc_issue_cmd(pCMD,pFG));
|
||||
}
|
||||
|
||||
#ifndef CONFIG_AMIGAONEG3SE
|
||||
/* terminates current command, by not servicing the FIFO
|
||||
* waits for interrupt and fills in the result bytes */
|
||||
int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<100;i++)
|
||||
udelay(500); /* wait 500usec for fifo overrun */
|
||||
while((read_fdc_reg(FDC_SRA)&0x80)==0x00); /* wait as long as no int has occured */
|
||||
for(i=0;i<7;i++) {
|
||||
pCMD->result[i]=(unsigned char)read_fdc_byte();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<100;i++)
|
||||
udelay(500); /* wait 500usec for fifo overrun */
|
||||
while((INT6_Status&0x80)==0x00); /* wait as long as no int has occured */
|
||||
for(i=0;i<7;i++) {
|
||||
pCMD->result[i]=(unsigned char)read_fdc_byte();
|
||||
}
|
||||
INT6_Status = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
#define disable_interrupts() 0
|
||||
#define enable_interrupts() (void)0
|
||||
#endif
|
||||
|
||||
/* reads data from FDC, seek commands are issued automatic */
|
||||
int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
|
||||
{
|
||||
/* first seek to start address */
|
||||
unsigned long len,lastblk,readblk,i,timeout,ii,offset;
|
||||
unsigned char pcn,c,retriesrw,retriescal;
|
||||
unsigned char *bufferw; /* working buffer */
|
||||
int sect_size;
|
||||
int flags;
|
||||
|
||||
flags=disable_interrupts(); /* switch off all Interrupts */
|
||||
select_fdc_drive(pCMD); /* switch on drive */
|
||||
sect_size=0x080<<pFG->sect_code;
|
||||
retriesrw=0;
|
||||
retriescal=0;
|
||||
offset=0;
|
||||
if(fdc_seek(pCMD,pFG)==FALSE) {
|
||||
stop_fdc_drive(pCMD);
|
||||
enable_interrupts();
|
||||
return FALSE;
|
||||
}
|
||||
if((pCMD->result[STATUS_0]&0x20)!=0x20) {
|
||||
printf("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
|
||||
stop_fdc_drive(pCMD);
|
||||
enable_interrupts();
|
||||
return FALSE;
|
||||
}
|
||||
pcn=pCMD->result[STATUS_PCN]; /* current track */
|
||||
/* now determine the next seek point */
|
||||
lastblk=pCMD->blnr + blocks;
|
||||
/* readblk=(pFG->head*pFG->sect)-(pCMD->blnr%(pFG->head*pFG->sect)); */
|
||||
readblk=pFG->sect-(pCMD->blnr%pFG->sect);
|
||||
PRINTF("1st nr of block possible read %ld start %ld\n",readblk,pCMD->blnr);
|
||||
if(readblk>blocks) /* is end within 1st track */
|
||||
readblk=blocks; /* yes, correct it */
|
||||
PRINTF("we read %ld blocks start %ld\n",readblk,pCMD->blnr);
|
||||
bufferw=&buffer[0]; /* setup working buffer */
|
||||
do {
|
||||
retryrw:
|
||||
len=sect_size * readblk;
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_READ;
|
||||
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
|
||||
stop_fdc_drive(pCMD);
|
||||
enable_interrupts();
|
||||
return FALSE;
|
||||
}
|
||||
for (i=0;i<len;i++) {
|
||||
timeout=FDC_TIME_OUT;
|
||||
do {
|
||||
c=read_fdc_reg(FDC_MSR);
|
||||
if((c&0xC0)==0xC0) {
|
||||
bufferw[i]=read_fdc_reg(FDC_FIFO);
|
||||
break;
|
||||
}
|
||||
if((c&0xC0)==0x80) { /* output */
|
||||
PRINTF("Transfer error transfered: at %ld, MSR=%02X\n",i,c);
|
||||
if(i>6) {
|
||||
for(ii=0;ii<7;ii++) {
|
||||
pCMD->result[ii]=bufferw[(i-7+ii)];
|
||||
} /* for */
|
||||
}
|
||||
if(retriesrw++>FDC_RW_RETRIES) {
|
||||
if (retriescal++>FDC_CAL_RETRIES) {
|
||||
stop_fdc_drive(pCMD);
|
||||
enable_interrupts();
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
PRINTF(" trying to recalibrate Try %d\n",retriescal);
|
||||
if(fdc_recalibrate(pCMD,pFG)==FALSE) {
|
||||
stop_fdc_drive(pCMD);
|
||||
enable_interrupts();
|
||||
return FALSE;
|
||||
}
|
||||
retriesrw=0;
|
||||
goto retrycal;
|
||||
} /* else >FDC_CAL_RETRIES */
|
||||
}
|
||||
else {
|
||||
PRINTF("Read retry %d\n",retriesrw);
|
||||
goto retryrw;
|
||||
} /* else >FDC_RW_RETRIES */
|
||||
}/* if output */
|
||||
timeout--;
|
||||
}while(TRUE);
|
||||
} /* for len */
|
||||
/* the last sector of a track or all data has been read,
|
||||
* we need to get the results */
|
||||
fdc_terminate(pCMD);
|
||||
offset+=(sect_size*readblk); /* set up buffer pointer */
|
||||
bufferw=&buffer[offset];
|
||||
pCMD->blnr+=readblk; /* update current block nr */
|
||||
blocks-=readblk; /* update blocks */
|
||||
if(blocks==0)
|
||||
break; /* we are finish */
|
||||
/* setup new read blocks */
|
||||
/* readblk=pFG->head*pFG->sect; */
|
||||
readblk=pFG->sect;
|
||||
if(readblk>blocks)
|
||||
readblk=blocks;
|
||||
retrycal:
|
||||
/* a seek is necessary */
|
||||
if(fdc_seek(pCMD,pFG)==FALSE) {
|
||||
stop_fdc_drive(pCMD);
|
||||
enable_interrupts();
|
||||
return FALSE;
|
||||
}
|
||||
if((pCMD->result[STATUS_0]&0x20)!=0x20) {
|
||||
PRINTF("Seek error Status: %02X\n",pCMD->result[STATUS_0]);
|
||||
stop_fdc_drive(pCMD);
|
||||
return FALSE;
|
||||
}
|
||||
pcn=pCMD->result[STATUS_PCN]; /* current track */
|
||||
}while(TRUE); /* start over */
|
||||
stop_fdc_drive(pCMD); /* switch off drive */
|
||||
enable_interrupts();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
#undef disable_interrupts()
|
||||
#undef enable_interrupts()
|
||||
#endif
|
||||
|
||||
/* Scan all drives and check if drive is present and disk is inserted */
|
||||
int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
|
||||
{
|
||||
int i,drives,state;
|
||||
/* OK procedure of data book is satisfied.
|
||||
* trying to get some information over the drives */
|
||||
state=0; /* no drives, no disks */
|
||||
for(drives=0;drives<4;drives++) {
|
||||
pCMD->drive=drives;
|
||||
select_fdc_drive(pCMD);
|
||||
pCMD->blnr=0; /* set to the 1st block */
|
||||
if(fdc_recalibrate(pCMD,pFG)==FALSE)
|
||||
continue;
|
||||
if((pCMD->result[STATUS_0]&0x10)==0x10)
|
||||
continue;
|
||||
/* ok drive connected check for disk */
|
||||
state|=(1<<drives);
|
||||
pCMD->blnr=pFG->size; /* set to the last block */
|
||||
if(fdc_seek(pCMD,pFG)==FALSE)
|
||||
continue;
|
||||
pCMD->blnr=0; /* set to the 1st block */
|
||||
if(fdc_recalibrate(pCMD,pFG)==FALSE)
|
||||
continue;
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_READ_ID;
|
||||
if(fdc_issue_cmd(pCMD,pFG)==FALSE)
|
||||
continue;
|
||||
state|=(0x10<<drives);
|
||||
}
|
||||
stop_fdc_drive(pCMD);
|
||||
for(i=0;i<4;i++) {
|
||||
PRINTF("Floppy Drive %d %sconnected %sDisk inserted %s\n",i,
|
||||
((state&(1<<i))==(1<<i)) ? "":"not ",
|
||||
((state&(0x10<<i))==(0x10<<i)) ? "":"no ",
|
||||
((state&(0x10<<i))==(0x10<<i)) ? pFG->name : "");
|
||||
}
|
||||
pCMD->flags=state;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* int fdc_setup
|
||||
* setup the fdc according the datasheet
|
||||
* assuming in PS2 Mode
|
||||
*/
|
||||
int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
irq_install_handler(6, (interrupt_handler_t *)fdc_interrupt, NULL);
|
||||
i8259_unmask_irq(6);
|
||||
#endif
|
||||
|
||||
#ifdef CFG_FDC_HW_INIT
|
||||
fdc_hw_init ();
|
||||
#endif
|
||||
/* first, we reset the FDC via the DOR */
|
||||
write_fdc_reg(FDC_DOR,0x00);
|
||||
for(i=0; i<255; i++) /* then we wait some time */
|
||||
udelay(500);
|
||||
/* then, we clear the reset in the DOR */
|
||||
pCMD->drive=drive;
|
||||
select_fdc_drive(pCMD);
|
||||
/* initialize the CCR */
|
||||
write_fdc_reg(FDC_CCR,pFG->rate);
|
||||
/* then initialize the DSR */
|
||||
write_fdc_reg(FDC_DSR,pFG->rate);
|
||||
if(wait_for_fdc_int()==FALSE) {
|
||||
PRINTF("Time Out after writing CCR\n");
|
||||
return FALSE;
|
||||
}
|
||||
/* now issue sense Interrupt and status command
|
||||
* assuming only one drive present (drive 0) */
|
||||
pCMD->dma=0; /* we don't use any dma at all */
|
||||
for(i=0;i<4;i++) {
|
||||
/* issue sense interrupt for all 4 possible drives */
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;
|
||||
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
|
||||
PRINTF("Sense Interrupt for drive %d failed\n",i);
|
||||
}
|
||||
}
|
||||
/* issue the configure command */
|
||||
pCMD->drive=drive;
|
||||
select_fdc_drive(pCMD);
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE;
|
||||
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
|
||||
PRINTF(" configure timeout\n");
|
||||
stop_fdc_drive(pCMD);
|
||||
return FALSE;
|
||||
}
|
||||
/* issue specify command */
|
||||
pCMD->cmd[COMMAND]=FDC_CMD_SPECIFY;
|
||||
if(fdc_issue_cmd(pCMD,pFG)==FALSE) {
|
||||
PRINTF(" specify timeout\n");
|
||||
stop_fdc_drive(pCMD);
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
/* then, we clear the reset in the DOR */
|
||||
/* fdc_check_drive(pCMD,pFG); */
|
||||
/* write_fdc_reg(FDC_DOR,0x04); */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* ((CONFIG_COMMANDS & CFG_CMD_FDC)||(CONFIG_COMMANDS & CFG_CMD_FDOS))*/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
|
||||
|
||||
/* Low level functions for the Floppy-DOS layer */
|
||||
|
||||
/**************************************************************************
|
||||
* int fdc_fdos_init
|
||||
* initialize the FDC layer
|
||||
*
|
||||
*/
|
||||
int fdc_fdos_init (int drive)
|
||||
{
|
||||
FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
|
||||
FDC_COMMAND_STRUCT *pCMD = &cmd;
|
||||
|
||||
/* setup FDC and scan for drives */
|
||||
if(fdc_setup(drive,pCMD,pFG)==FALSE) {
|
||||
printf("\n** Error in setup FDC **\n");
|
||||
return FALSE;
|
||||
}
|
||||
if(fdc_check_drive(pCMD,pFG)==FALSE) {
|
||||
printf("\n** Error in check_drives **\n");
|
||||
return FALSE;
|
||||
}
|
||||
if((pCMD->flags&(1<<drive))==0) {
|
||||
/* drive not available */
|
||||
printf("\n** Drive %d not available **\n",drive);
|
||||
return FALSE;
|
||||
}
|
||||
if((pCMD->flags&(0x10<<drive))==0) {
|
||||
/* no disk inserted */
|
||||
printf("\n** No disk inserted in drive %d **\n",drive);
|
||||
return FALSE;
|
||||
}
|
||||
/* ok, we have a valid source */
|
||||
pCMD->drive=drive;
|
||||
|
||||
/* read first block */
|
||||
pCMD->blnr=0;
|
||||
return TRUE;
|
||||
}
|
||||
/**************************************************************************
|
||||
* int fdc_fdos_seek
|
||||
* parameter is a block number
|
||||
*/
|
||||
int fdc_fdos_seek (int where)
|
||||
{
|
||||
FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
|
||||
FDC_COMMAND_STRUCT *pCMD = &cmd;
|
||||
|
||||
pCMD -> blnr = where ;
|
||||
return (fdc_seek (pCMD, pFG));
|
||||
}
|
||||
/**************************************************************************
|
||||
* int fdc_fdos_read
|
||||
* the length is in block number
|
||||
*/
|
||||
int fdc_fdos_read (void *buffer, int len)
|
||||
{
|
||||
FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
|
||||
FDC_COMMAND_STRUCT *pCMD = &cmd;
|
||||
|
||||
return (fdc_read_data (buffer, len, pCMD, pFG));
|
||||
}
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_FDOS) */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_FDC)
|
||||
/****************************************************************************
|
||||
* main routine do_fdcboot
|
||||
*/
|
||||
int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
FD_GEO_STRUCT *pFG = (FD_GEO_STRUCT *)floppy_type;
|
||||
FDC_COMMAND_STRUCT *pCMD = &cmd;
|
||||
unsigned long addr,imsize;
|
||||
image_header_t *hdr; /* used for fdc boot */
|
||||
unsigned char boot_drive;
|
||||
int i,nrofblk;
|
||||
char *ep;
|
||||
int rcode = 0;
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
addr = CFG_LOAD_ADDR;
|
||||
boot_drive=CFG_FDC_DRIVE_NUMBER;
|
||||
break;
|
||||
case 2:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_drive=CFG_FDC_DRIVE_NUMBER;
|
||||
break;
|
||||
case 3:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_drive=simple_strtoul(argv[2], NULL, 10);
|
||||
break;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
/* setup FDC and scan for drives */
|
||||
if(fdc_setup(boot_drive,pCMD,pFG)==FALSE) {
|
||||
printf("\n** Error in setup FDC **\n");
|
||||
return 1;
|
||||
}
|
||||
if(fdc_check_drive(pCMD,pFG)==FALSE) {
|
||||
printf("\n** Error in check_drives **\n");
|
||||
return 1;
|
||||
}
|
||||
if((pCMD->flags&(1<<boot_drive))==0) {
|
||||
/* drive not available */
|
||||
printf("\n** Drive %d not availabe **\n",boot_drive);
|
||||
return 1;
|
||||
}
|
||||
if((pCMD->flags&(0x10<<boot_drive))==0) {
|
||||
/* no disk inserted */
|
||||
printf("\n** No disk inserted in drive %d **\n",boot_drive);
|
||||
return 1;
|
||||
}
|
||||
/* ok, we have a valid source */
|
||||
pCMD->drive=boot_drive;
|
||||
/* read first block */
|
||||
pCMD->blnr=0;
|
||||
if(fdc_read_data((unsigned char *)addr,1,pCMD,pFG)==FALSE) {
|
||||
printf("\nRead error:");
|
||||
for(i=0;i<7;i++)
|
||||
printf("result%d: 0x%02X\n",i,pCMD->result[i]);
|
||||
return 1;
|
||||
}
|
||||
hdr = (image_header_t *)addr;
|
||||
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
|
||||
printf ("Bad Magic Number\n");
|
||||
return 1;
|
||||
}
|
||||
print_image_hdr(hdr);
|
||||
|
||||
imsize= ntohl(hdr->ih_size)+sizeof(image_header_t);
|
||||
nrofblk=imsize/512;
|
||||
if((imsize%512)>0)
|
||||
nrofblk++;
|
||||
printf("Loading %ld Bytes (%d blocks) at 0x%08lx..\n",imsize,nrofblk,addr);
|
||||
pCMD->blnr=0;
|
||||
if(fdc_read_data((unsigned char *)addr,nrofblk,pCMD,pFG)==FALSE) {
|
||||
/* read image block */
|
||||
printf("\nRead error:");
|
||||
for(i=0;i<7;i++)
|
||||
printf("result%d: 0x%02X\n",i,pCMD->result[i]);
|
||||
return 1;
|
||||
}
|
||||
printf("OK %ld Bytes loaded.\n",imsize);
|
||||
|
||||
flush_cache (addr, imsize);
|
||||
/* Loading ok, update default load address */
|
||||
|
||||
load_addr = addr;
|
||||
if(hdr->ih_type == IH_TYPE_KERNEL) {
|
||||
/* Check if we should attempt an auto-start */
|
||||
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
|
||||
char *local_args[2];
|
||||
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
|
||||
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = NULL;
|
||||
|
||||
printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
|
||||
|
||||
do_bootm (cmdtp, 0, 1, local_args);
|
||||
rcode ++;
|
||||
}
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_FDC */
|
||||
|
||||
|
||||
/***************************************************/
|
||||
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_FDC)
|
||||
|
||||
U_BOOT_CMD(
|
||||
fdcboot, 3, 1, do_fdcboot,
|
||||
"fdcboot - boot from floppy device\n",
|
||||
"loadAddr drive\n"
|
||||
);
|
||||
#endif
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Stäubli Faverges - <www.staubli.com>
|
||||
* Pierre AUBERT p.aubert@staubli.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dos floppy support
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
#include <fdc.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* do_fdosboot --
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
int do_fdosboot(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *name;
|
||||
char *ep;
|
||||
int size;
|
||||
int rcode = 0;
|
||||
char buf [12];
|
||||
int drive = CFG_FDC_DRIVE_NUMBER;
|
||||
|
||||
/* pre-set load_addr */
|
||||
if ((ep = getenv("loadaddr")) != NULL) {
|
||||
load_addr = simple_strtoul(ep, NULL, 16);
|
||||
}
|
||||
|
||||
/* pre-set Boot file name */
|
||||
if ((name = getenv("bootfile")) == NULL) {
|
||||
name = "uImage";
|
||||
}
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
/* only one arg - accept two forms:
|
||||
* just load address, or just boot file name.
|
||||
* The latter form must be written "filename" here.
|
||||
*/
|
||||
if (argv[1][0] == '"') { /* just boot filename */
|
||||
name = argv [1];
|
||||
} else { /* load address */
|
||||
load_addr = simple_strtoul(argv[1], NULL, 16);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
load_addr = simple_strtoul(argv[1], NULL, 16);
|
||||
name = argv [2];
|
||||
break;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Init physical layer */
|
||||
if (!fdc_fdos_init (drive)) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Open file */
|
||||
if (dos_open (name) < 0) {
|
||||
printf ("Unable to open %s\n", name);
|
||||
return 1;
|
||||
}
|
||||
if ((size = dos_read (load_addr)) < 0) {
|
||||
printf ("boot error\n");
|
||||
return 1;
|
||||
}
|
||||
flush_cache (load_addr, size);
|
||||
|
||||
sprintf(buf, "%x", size);
|
||||
setenv("filesize", buf);
|
||||
|
||||
printf("Floppy DOS load complete: %d bytes loaded to 0x%lx\n",
|
||||
size, load_addr);
|
||||
|
||||
/* Check if we should attempt an auto-start */
|
||||
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
|
||||
char *local_args[2];
|
||||
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = NULL;
|
||||
printf ("Automatic boot of image at addr 0x%08lX ...\n", load_addr);
|
||||
rcode = do_bootm (cmdtp, 0, 1, local_args);
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* do_fdosls --
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
int do_fdosls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *path = "";
|
||||
int drive = CFG_FDC_DRIVE_NUMBER;
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
path = argv [1];
|
||||
break;
|
||||
}
|
||||
|
||||
/* Init physical layer */
|
||||
if (!fdc_fdos_init (drive)) {
|
||||
return (-1);
|
||||
}
|
||||
/* Open directory */
|
||||
if (dos_open (path) < 0) {
|
||||
printf ("Unable to open %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
return (dos_dir ());
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
fdosboot, 3, 0, do_fdosboot,
|
||||
"fdosboot- boot from a dos floppy file\n",
|
||||
"[loadAddr] [filename]\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
fdosls, 2, 0, do_fdosls,
|
||||
"fdosls - list files in a directory\n",
|
||||
"[directory]\n"
|
||||
);
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_FDOS */
|
|
@ -0,0 +1,751 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* FLASH support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#ifdef CONFIG_HAS_DATAFLASH
|
||||
#include <dataflash.h>
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
|
||||
#include <jffs2/jffs2.h>
|
||||
|
||||
/* parition handling routines */
|
||||
int mtdparts_init(void);
|
||||
int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
|
||||
int find_dev_and_part(const char *id, struct mtd_device **dev,
|
||||
u8 *part_num, struct part_info **part);
|
||||
#endif
|
||||
|
||||
extern flash_info_t flash_info[]; /* info for FLASH chips */
|
||||
|
||||
/*
|
||||
* The user interface starts numbering for Flash banks with 1
|
||||
* for historical reasons.
|
||||
*/
|
||||
|
||||
/*
|
||||
* this routine looks for an abbreviated flash range specification.
|
||||
* the syntax is B:SF[-SL], where B is the bank number, SF is the first
|
||||
* sector to erase, and SL is the last sector to erase (defaults to SF).
|
||||
* bank numbers start at 1 to be consistent with other specs, sector numbers
|
||||
* start at zero.
|
||||
*
|
||||
* returns: 1 - correct spec; *pinfo, *psf and *psl are
|
||||
* set appropriately
|
||||
* 0 - doesn't look like an abbreviated spec
|
||||
* -1 - looks like an abbreviated spec, but got
|
||||
* a parsing error, a number out of range,
|
||||
* or an invalid flash bank.
|
||||
*/
|
||||
static int
|
||||
abbrev_spec (char *str, flash_info_t ** pinfo, int *psf, int *psl)
|
||||
{
|
||||
flash_info_t *fp;
|
||||
int bank, first, last;
|
||||
char *p, *ep;
|
||||
|
||||
if ((p = strchr (str, ':')) == NULL)
|
||||
return 0;
|
||||
*p++ = '\0';
|
||||
|
||||
bank = simple_strtoul (str, &ep, 10);
|
||||
if (ep == str || *ep != '\0' ||
|
||||
bank < 1 || bank > CFG_MAX_FLASH_BANKS ||
|
||||
(fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
|
||||
return -1;
|
||||
|
||||
str = p;
|
||||
if ((p = strchr (str, '-')) != NULL)
|
||||
*p++ = '\0';
|
||||
|
||||
first = simple_strtoul (str, &ep, 10);
|
||||
if (ep == str || *ep != '\0' || first >= fp->sector_count)
|
||||
return -1;
|
||||
|
||||
if (p != NULL) {
|
||||
last = simple_strtoul (p, &ep, 10);
|
||||
if (ep == p || *ep != '\0' ||
|
||||
last < first || last >= fp->sector_count)
|
||||
return -1;
|
||||
} else {
|
||||
last = first;
|
||||
}
|
||||
|
||||
*pinfo = fp;
|
||||
*psf = first;
|
||||
*psl = last;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function computes the start and end addresses for both
|
||||
* erase and protect commands. The range of the addresses on which
|
||||
* either of the commands is to operate can be given in two forms:
|
||||
* 1. <cmd> start end - operate on <'start', 'end')
|
||||
* 2. <cmd> start +length - operate on <'start', start + length)
|
||||
* If the second form is used and the end address doesn't fall on the
|
||||
* sector boundary, than it will be adjusted to the next sector boundary.
|
||||
* If it isn't in the flash, the function will fail (return -1).
|
||||
* Input:
|
||||
* arg1, arg2: address specification (i.e. both command arguments)
|
||||
* Output:
|
||||
* addr_first, addr_last: computed address range
|
||||
* Return:
|
||||
* 1: success
|
||||
* -1: failure (bad format, bad address).
|
||||
*/
|
||||
static int
|
||||
addr_spec(char *arg1, char *arg2, ulong *addr_first, ulong *addr_last)
|
||||
{
|
||||
char len_used = 0; /* indicates if the "start +length" form used */
|
||||
char *ep;
|
||||
|
||||
*addr_first = simple_strtoul(arg1, &ep, 16);
|
||||
if (ep == arg1 || *ep != '\0')
|
||||
return -1;
|
||||
|
||||
if (arg2 && *arg2 == '+'){
|
||||
len_used = 1;
|
||||
++arg2;
|
||||
}
|
||||
|
||||
*addr_last = simple_strtoul(arg2, &ep, 16);
|
||||
if (ep == arg2 || *ep != '\0')
|
||||
return -1;
|
||||
|
||||
if (len_used){
|
||||
char found = 0;
|
||||
ulong bank;
|
||||
|
||||
/*
|
||||
* *addr_last has the length, compute correct *addr_last
|
||||
* XXX watch out for the integer overflow! Right now it is
|
||||
* checked for in both the callers.
|
||||
*/
|
||||
*addr_last = *addr_first + *addr_last - 1;
|
||||
|
||||
/*
|
||||
* It may happen that *addr_last doesn't fall on the sector
|
||||
* boundary. We want to round such an address to the next
|
||||
* sector boundary, so that the commands don't fail later on.
|
||||
*/
|
||||
/* find the end addr of the sector where the *addr_last is */
|
||||
for (bank = 0; bank < CFG_MAX_FLASH_BANKS && !found; ++bank){
|
||||
int i;
|
||||
flash_info_t *info = &flash_info[bank];
|
||||
for (i = 0; i < info->sector_count && !found; ++i){
|
||||
/* get the end address of the sector */
|
||||
ulong sector_end_addr;
|
||||
if (i == info->sector_count - 1){
|
||||
sector_end_addr =
|
||||
info->start[0] + info->size - 1;
|
||||
} else {
|
||||
sector_end_addr =
|
||||
info->start[i+1] - 1;
|
||||
}
|
||||
if (*addr_last <= sector_end_addr &&
|
||||
*addr_last >= info->start[i]){
|
||||
/* sector found */
|
||||
found = 1;
|
||||
/* adjust *addr_last if necessary */
|
||||
if (*addr_last < sector_end_addr){
|
||||
*addr_last = sector_end_addr;
|
||||
}
|
||||
}
|
||||
} /* sector */
|
||||
} /* bank */
|
||||
if (!found){
|
||||
/* error, addres not in flash */
|
||||
printf("Error: end address (0x%08lx) not in flash!\n",
|
||||
*addr_last);
|
||||
return -1;
|
||||
}
|
||||
} /* "start +length" from used */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
flash_fill_sect_ranges (ulong addr_first, ulong addr_last,
|
||||
int *s_first, int *s_last,
|
||||
int *s_count )
|
||||
{
|
||||
flash_info_t *info;
|
||||
ulong bank;
|
||||
int rcode = 0;
|
||||
|
||||
*s_count = 0;
|
||||
|
||||
for (bank=0; bank < CFG_MAX_FLASH_BANKS; ++bank) {
|
||||
s_first[bank] = -1; /* first sector to erase */
|
||||
s_last [bank] = -1; /* last sector to erase */
|
||||
}
|
||||
|
||||
for (bank=0,info=&flash_info[0];
|
||||
(bank < CFG_MAX_FLASH_BANKS) && (addr_first <= addr_last);
|
||||
++bank, ++info) {
|
||||
ulong b_end;
|
||||
int sect;
|
||||
short s_end;
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
b_end = info->start[0] + info->size - 1; /* bank end addr */
|
||||
s_end = info->sector_count - 1; /* last sector */
|
||||
|
||||
|
||||
for (sect=0; sect < info->sector_count; ++sect) {
|
||||
ulong end; /* last address in current sect */
|
||||
|
||||
end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
|
||||
|
||||
if (addr_first > end)
|
||||
continue;
|
||||
if (addr_last < info->start[sect])
|
||||
continue;
|
||||
|
||||
if (addr_first == info->start[sect]) {
|
||||
s_first[bank] = sect;
|
||||
}
|
||||
if (addr_last == end) {
|
||||
s_last[bank] = sect;
|
||||
}
|
||||
}
|
||||
if (s_first[bank] >= 0) {
|
||||
if (s_last[bank] < 0) {
|
||||
if (addr_last > b_end) {
|
||||
s_last[bank] = s_end;
|
||||
} else {
|
||||
puts ("Error: end address"
|
||||
" not on sector boundary\n");
|
||||
rcode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s_last[bank] < s_first[bank]) {
|
||||
puts ("Error: end sector"
|
||||
" precedes start sector\n");
|
||||
rcode = 1;
|
||||
break;
|
||||
}
|
||||
sect = s_last[bank];
|
||||
addr_first = (sect == s_end) ? b_end + 1: info->start[sect + 1];
|
||||
(*s_count) += s_last[bank] - s_first[bank] + 1;
|
||||
} else if (addr_first >= info->start[0] && addr_first < b_end) {
|
||||
puts ("Error: start address not on sector boundary\n");
|
||||
rcode = 1;
|
||||
break;
|
||||
} else if (s_last[bank] >= 0) {
|
||||
puts ("Error: cannot span across banks when they are"
|
||||
" mapped in reverse order\n");
|
||||
rcode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
int do_flinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong bank;
|
||||
|
||||
#ifdef CONFIG_HAS_DATAFLASH
|
||||
dataflash_print_info();
|
||||
#endif
|
||||
|
||||
if (argc == 1) { /* print info for all FLASH banks */
|
||||
for (bank=0; bank <CFG_MAX_FLASH_BANKS; ++bank) {
|
||||
printf ("\nBank # %ld: ", bank+1);
|
||||
|
||||
flash_print_info (&flash_info[bank]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bank = simple_strtoul(argv[1], NULL, 16);
|
||||
if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
|
||||
printf ("Only FLASH Banks # 1 ... # %d supported\n",
|
||||
CFG_MAX_FLASH_BANKS);
|
||||
return 1;
|
||||
}
|
||||
printf ("\nBank # %ld: ", bank);
|
||||
flash_print_info (&flash_info[bank-1]);
|
||||
return 0;
|
||||
}
|
||||
#endif /* #ifndef COMPRESSED_UBOOT */
|
||||
|
||||
int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
flash_info_t *info;
|
||||
ulong bank, addr_first, addr_last;
|
||||
int n, sect_first, sect_last;
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
|
||||
struct mtd_device *dev;
|
||||
struct part_info *part;
|
||||
u8 dev_type, dev_num, pnum;
|
||||
#endif
|
||||
int rcode = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "all") == 0) {
|
||||
for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
|
||||
#ifdef FLASH_DEBUG
|
||||
printf ("Erase Flash Bank # %ld ", bank);
|
||||
#endif
|
||||
info = &flash_info[bank-1];
|
||||
rcode = flash_erase (info, 0, info->sector_count-1);
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
if ((n = abbrev_spec(argv[1], &info, §_first, §_last)) != 0) {
|
||||
if (n < 0) {
|
||||
puts ("Bad sector specification\n");
|
||||
return 1;
|
||||
}
|
||||
#ifdef FLASH_DEBUG
|
||||
printf ("Erase Flash Sectors %d-%d in Bank # %d ",
|
||||
sect_first, sect_last, (info-flash_info)+1);
|
||||
#endif
|
||||
rcode = flash_erase(info, sect_first, sect_last);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
|
||||
/* erase <part-id> - erase partition */
|
||||
if ((argc == 2) && (id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
|
||||
mtdparts_init();
|
||||
if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
|
||||
if (dev->id->type == MTD_DEV_TYPE_NOR) {
|
||||
bank = dev->id->num;
|
||||
info = &flash_info[bank];
|
||||
addr_first = part->offset + info->start[0];
|
||||
addr_last = addr_first + part->size - 1;
|
||||
#ifdef FLASH_DEBUG
|
||||
printf ("Erase Flash Parition %s, "
|
||||
"bank %d, 0x%08lx - 0x%08lx ",
|
||||
argv[1], bank, addr_first,
|
||||
addr_last);
|
||||
#endif
|
||||
rcode = flash_sect_erase(addr_first, addr_last);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
printf("cannot erase, not a NOR device\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (argc != 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "bank") == 0) {
|
||||
bank = simple_strtoul(argv[2], NULL, 16);
|
||||
if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
|
||||
printf ("Only FLASH Banks # 1 ... # %d supported\n",
|
||||
CFG_MAX_FLASH_BANKS);
|
||||
return 1;
|
||||
}
|
||||
#ifdef FLASH_DEBUG
|
||||
printf ("Erase Flash Bank # %ld ", bank);
|
||||
#endif
|
||||
info = &flash_info[bank-1];
|
||||
rcode = flash_erase (info, 0, info->sector_count-1);
|
||||
return rcode;
|
||||
}
|
||||
if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0){
|
||||
printf ("Bad address format\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (addr_first >= addr_last) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rcode = flash_sect_erase(addr_first, addr_last);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
int flash_sect_erase (ulong addr_first, ulong addr_last)
|
||||
{
|
||||
flash_info_t *info;
|
||||
ulong bank;
|
||||
#ifdef CFG_MAX_FLASH_BANKS_DETECT
|
||||
int s_first[CFG_MAX_FLASH_BANKS_DETECT], s_last[CFG_MAX_FLASH_BANKS_DETECT];
|
||||
#else
|
||||
int s_first[CFG_MAX_FLASH_BANKS], s_last[CFG_MAX_FLASH_BANKS];
|
||||
#endif
|
||||
int erased = 0;
|
||||
int planned;
|
||||
int rcode = 0;
|
||||
|
||||
rcode = flash_fill_sect_ranges (addr_first, addr_last,
|
||||
s_first, s_last, &planned );
|
||||
|
||||
if (planned && (rcode == 0)) {
|
||||
for (bank=0,info=&flash_info[0];
|
||||
(bank < CFG_MAX_FLASH_BANKS) && (rcode == 0);
|
||||
++bank, ++info) {
|
||||
if (s_first[bank]>=0) {
|
||||
erased += s_last[bank] - s_first[bank] + 1;
|
||||
#ifdef FLASH_DEBUG
|
||||
debug ("Erase Flash from 0x%08lx to 0x%08lx "
|
||||
"in Bank # %ld ",
|
||||
info->start[s_first[bank]],
|
||||
(s_last[bank] == info->sector_count) ?
|
||||
info->start[0] + info->size - 1:
|
||||
info->start[s_last[bank]+1] - 1,
|
||||
bank+1);
|
||||
#else
|
||||
debug( "Erasing flash... ");
|
||||
#endif
|
||||
rcode = flash_erase (info, s_first[bank], s_last[bank]);
|
||||
}
|
||||
}
|
||||
debug ("Erased %d sectors\n", erased);
|
||||
} else if (rcode == 0) {
|
||||
puts ("Error: start and/or end address"
|
||||
" not on sector boundary\n");
|
||||
rcode = 1;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
flash_info_t *info;
|
||||
ulong bank, addr_first, addr_last;
|
||||
int i, p, n, sect_first, sect_last;
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
|
||||
struct mtd_device *dev;
|
||||
struct part_info *part;
|
||||
u8 dev_type, dev_num, pnum;
|
||||
#endif
|
||||
int rcode = 0;
|
||||
#ifdef CONFIG_HAS_DATAFLASH
|
||||
int status;
|
||||
#endif
|
||||
|
||||
if (argc < 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "off") == 0) {
|
||||
p = 0;
|
||||
} else if (strcmp(argv[1], "on") == 0) {
|
||||
p = 1;
|
||||
} else {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAS_DATAFLASH
|
||||
if ((strcmp(argv[2], "all") != 0) && (strcmp(argv[2], "bank") != 0)) {
|
||||
addr_first = simple_strtoul(argv[2], NULL, 16);
|
||||
addr_last = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
if (addr_dataflash(addr_first) && addr_dataflash(addr_last)) {
|
||||
status = dataflash_real_protect(p,addr_first,addr_last);
|
||||
if (status < 0){
|
||||
puts ("Bad DataFlash sector specification\n");
|
||||
return 1;
|
||||
}
|
||||
printf("%sProtect %d DataFlash Sectors\n",
|
||||
p ? "" : "Un-", status);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(argv[2], "all") == 0) {
|
||||
for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
|
||||
info = &flash_info[bank-1];
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
continue;
|
||||
}
|
||||
printf ("%sProtect Flash Bank # %ld\n",
|
||||
p ? "" : "Un-", bank);
|
||||
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
if (flash_real_protect(info, i, p))
|
||||
rcode = 1;
|
||||
putc ('.');
|
||||
#else
|
||||
info->protect[i] = p;
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
if (!rcode) puts (" done\n");
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
if ((n = abbrev_spec(argv[2], &info, §_first, §_last)) != 0) {
|
||||
if (n < 0) {
|
||||
puts ("Bad sector specification\n");
|
||||
return 1;
|
||||
}
|
||||
printf("%sProtect Flash Sectors %d-%d in Bank # %d\n",
|
||||
p ? "" : "Un-", sect_first, sect_last,
|
||||
(info-flash_info)+1);
|
||||
for (i = sect_first; i <= sect_last; i++) {
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
if (flash_real_protect(info, i, p))
|
||||
rcode = 1;
|
||||
putc ('.');
|
||||
#else
|
||||
info->protect[i] = p;
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
}
|
||||
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
if (!rcode) puts (" done\n");
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
|
||||
/* protect on/off <part-id> */
|
||||
if ((argc == 3) && (id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) {
|
||||
mtdparts_init();
|
||||
if (find_dev_and_part(argv[2], &dev, &pnum, &part) == 0) {
|
||||
if (dev->id->type == MTD_DEV_TYPE_NOR) {
|
||||
bank = dev->id->num;
|
||||
info = &flash_info[bank];
|
||||
addr_first = part->offset + info->start[0];
|
||||
addr_last = addr_first + part->size - 1;
|
||||
|
||||
printf ("%sProtect Flash Parition %s, "
|
||||
"bank %d, 0x%08lx - 0x%08lx\n",
|
||||
p ? "" : "Un", argv[1],
|
||||
bank, addr_first, addr_last);
|
||||
|
||||
rcode = flash_sect_protect (p, addr_first, addr_last);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
printf("cannot %sprotect, not a NOR device\n",
|
||||
p ? "" : "un");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (argc != 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[2], "bank") == 0) {
|
||||
bank = simple_strtoul(argv[3], NULL, 16);
|
||||
if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
|
||||
printf ("Only FLASH Banks # 1 ... # %d supported\n",
|
||||
CFG_MAX_FLASH_BANKS);
|
||||
return 1;
|
||||
}
|
||||
printf ("%sProtect Flash Bank # %ld\n",
|
||||
p ? "" : "Un-", bank);
|
||||
info = &flash_info[bank-1];
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
puts ("missing or unknown FLASH type\n");
|
||||
return 1;
|
||||
}
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
if (flash_real_protect(info, i, p))
|
||||
rcode = 1;
|
||||
putc ('.');
|
||||
#else
|
||||
info->protect[i] = p;
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
}
|
||||
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
if (!rcode) puts (" done\n");
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
if (addr_spec(argv[2], argv[3], &addr_first, &addr_last) < 0){
|
||||
printf("Bad address format\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (addr_first >= addr_last) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
rcode = flash_sect_protect (p, addr_first, addr_last);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
|
||||
int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
|
||||
{
|
||||
flash_info_t *info;
|
||||
ulong bank;
|
||||
#ifdef CFG_MAX_FLASH_BANKS_DETECT
|
||||
int s_first[CFG_MAX_FLASH_BANKS_DETECT], s_last[CFG_MAX_FLASH_BANKS_DETECT];
|
||||
#else
|
||||
int s_first[CFG_MAX_FLASH_BANKS], s_last[CFG_MAX_FLASH_BANKS];
|
||||
#endif
|
||||
int protected, i;
|
||||
int planned;
|
||||
int rcode;
|
||||
|
||||
rcode = flash_fill_sect_ranges( addr_first, addr_last, s_first, s_last, &planned );
|
||||
|
||||
protected = 0;
|
||||
|
||||
if (planned && (rcode == 0)) {
|
||||
for (bank=0,info=&flash_info[0]; bank < CFG_MAX_FLASH_BANKS; ++bank, ++info) {
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_first[bank]>=0 && s_first[bank]<=s_last[bank]) {
|
||||
debug ("%sProtecting sectors %d..%d in bank %ld\n",
|
||||
p ? "" : "Un-",
|
||||
s_first[bank], s_last[bank], bank+1);
|
||||
protected += s_last[bank] - s_first[bank] + 1;
|
||||
for (i=s_first[bank]; i<=s_last[bank]; ++i) {
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
if (flash_real_protect(info, i, p))
|
||||
rcode = 1;
|
||||
putc ('.');
|
||||
#else
|
||||
info->protect[i] = p;
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
puts (" done\n");
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
|
||||
debug ("%sProtected %d sectors\n",
|
||||
p ? "" : "Un-", protected);
|
||||
} else if (rcode == 0) {
|
||||
puts ("Error: start and/or end address"
|
||||
" not on sector boundary\n");
|
||||
rcode = 1;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
#endif /* #ifndef COMPRESSED_UBOOT */
|
||||
|
||||
/**************************************************/
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
|
||||
# define TMP_ERASE "erase <part-id>\n - erase partition\n"
|
||||
# define TMP_PROT_ON "protect on <part-id>\n - protect partition\n"
|
||||
# define TMP_PROT_OFF "protect off <part-id>\n - make partition writable\n"
|
||||
#else
|
||||
# define TMP_ERASE /* empty */
|
||||
# define TMP_PROT_ON /* empty */
|
||||
# define TMP_PROT_OFF /* empty */
|
||||
#endif
|
||||
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
U_BOOT_CMD(
|
||||
flinfo, 2, 1, do_flinfo,
|
||||
"flinfo - print FLASH memory information\n",
|
||||
"\n - print information for all FLASH memory banks\n"
|
||||
"flinfo N\n - print information for FLASH memory bank # N\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
protect, 4, 1, do_protect,
|
||||
"protect - enable or disable FLASH write protection\n",
|
||||
"on start end\n"
|
||||
" - protect FLASH from addr 'start' to addr 'end'\n"
|
||||
"protect on start +len\n"
|
||||
" - protect FLASH from addr 'start' to end of sect "
|
||||
"w/addr 'start'+'len'-1\n"
|
||||
"protect on N:SF[-SL]\n"
|
||||
" - protect sectors SF-SL in FLASH bank # N\n"
|
||||
"protect on bank N\n - protect FLASH bank # N\n"
|
||||
TMP_PROT_ON
|
||||
"protect on all\n - protect all FLASH banks\n"
|
||||
"protect off start end\n"
|
||||
" - make FLASH from addr 'start' to addr 'end' writable\n"
|
||||
"protect off start +len\n"
|
||||
" - make FLASH from addr 'start' to end of sect "
|
||||
"w/addr 'start'+'len'-1 wrtable\n"
|
||||
"protect off N:SF[-SL]\n"
|
||||
" - make sectors SF-SL writable in FLASH bank # N\n"
|
||||
"protect off bank N\n - make FLASH bank # N writable\n"
|
||||
TMP_PROT_OFF
|
||||
"protect off all\n - make all FLASH banks writable\n"
|
||||
);
|
||||
|
||||
#endif /* #ifndef COMPRESSED_UBOOT */
|
||||
|
||||
U_BOOT_CMD(
|
||||
erase, 3, 1, do_flerase,
|
||||
"erase - erase FLASH memory\n",
|
||||
"start end\n"
|
||||
" - erase FLASH from addr 'start' to addr 'end'\n"
|
||||
"erase start +len\n"
|
||||
" - erase FLASH from addr 'start' to the end of sect "
|
||||
"w/addr 'start'+'len'-1\n"
|
||||
"erase N:SF[-SL]\n - erase sectors SF-SL in FLASH bank # N\n"
|
||||
"erase bank N\n - erase FLASH bank # N\n"
|
||||
TMP_ERASE
|
||||
"erase all\n - erase all FLASH banks\n"
|
||||
);
|
||||
|
||||
|
||||
|
||||
#undef TMP_ERASE
|
||||
#undef TMP_PROT_ON
|
||||
#undef TMP_PROT_OFF
|
||||
|
||||
#endif /* CFG_CMD_FLASH */
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* (C) Copyright 2000, 2001
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* FPGA support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#include <net.h>
|
||||
#endif
|
||||
#include <fpga.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#if 0
|
||||
#define FPGA_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_FPGA) && ( CONFIG_COMMANDS & CFG_CMD_FPGA )
|
||||
|
||||
/* Local functions */
|
||||
static void fpga_usage (cmd_tbl_t * cmdtp);
|
||||
static int fpga_get_op (char *opstr);
|
||||
|
||||
/* Local defines */
|
||||
#define FPGA_NONE -1
|
||||
#define FPGA_INFO 0
|
||||
#define FPGA_LOAD 1
|
||||
#define FPGA_LOADB 2
|
||||
#define FPGA_DUMP 3
|
||||
|
||||
/* Convert bitstream data and load into the fpga */
|
||||
int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
|
||||
{
|
||||
unsigned int length;
|
||||
unsigned char* swapdata;
|
||||
unsigned int swapsize;
|
||||
char buffer[80];
|
||||
unsigned char *ptr;
|
||||
unsigned char *dataptr;
|
||||
unsigned char data;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
dataptr = (unsigned char *)fpgadata;
|
||||
|
||||
#if CFG_FPGA_XILINX
|
||||
/* skip the first bytes of the bitsteam, their meaning is unknown */
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr+=2;
|
||||
dataptr+=length;
|
||||
|
||||
/* get design name (identifier, length, string) */
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr+=2;
|
||||
if (*dataptr++ != 0x61) {
|
||||
PRINTF ("%s: Design name identifier not recognized in bitstream\n",
|
||||
__FUNCTION__ );
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr+=2;
|
||||
for(i=0;i<length;i++)
|
||||
buffer[i]=*dataptr++;
|
||||
|
||||
printf(" design filename = \"%s\"\n", buffer);
|
||||
|
||||
/* get part number (identifier, length, string) */
|
||||
if (*dataptr++ != 0x62) {
|
||||
printf("%s: Part number identifier not recognized in bitstream\n",
|
||||
__FUNCTION__ );
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr+=2;
|
||||
for(i=0;i<length;i++)
|
||||
buffer[i]=*dataptr++;
|
||||
printf(" part number = \"%s\"\n", buffer);
|
||||
|
||||
/* get date (identifier, length, string) */
|
||||
if (*dataptr++ != 0x63) {
|
||||
printf("%s: Date identifier not recognized in bitstream\n",
|
||||
__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr+=2;
|
||||
for(i=0;i<length;i++)
|
||||
buffer[i]=*dataptr++;
|
||||
printf(" date = \"%s\"\n", buffer);
|
||||
|
||||
/* get time (identifier, length, string) */
|
||||
if (*dataptr++ != 0x64) {
|
||||
printf("%s: Time identifier not recognized in bitstream\n",__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
length = (*dataptr << 8) + *(dataptr+1);
|
||||
dataptr+=2;
|
||||
for(i=0;i<length;i++)
|
||||
buffer[i]=*dataptr++;
|
||||
printf(" time = \"%s\"\n", buffer);
|
||||
|
||||
/* get fpga data length (identifier, length) */
|
||||
if (*dataptr++ != 0x65) {
|
||||
printf("%s: Data length identifier not recognized in bitstream\n",
|
||||
__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
swapsize = ((unsigned int) *dataptr <<24) +
|
||||
((unsigned int) *(dataptr+1) <<16) +
|
||||
((unsigned int) *(dataptr+2) <<8 ) +
|
||||
((unsigned int) *(dataptr+3) ) ;
|
||||
dataptr+=4;
|
||||
printf(" bytes in bitstream = %d\n", swapsize);
|
||||
|
||||
/* check consistency of length obtained */
|
||||
if (swapsize >= size) {
|
||||
printf("%s: Could not find right length of data in bitstream\n",
|
||||
__FUNCTION__);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
/* allocate memory */
|
||||
swapdata = (unsigned char *)malloc(swapsize);
|
||||
if (swapdata == NULL) {
|
||||
printf("%s: Could not allocate %d bytes memory !\n",
|
||||
__FUNCTION__, swapsize);
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
|
||||
/* read data into memory and swap bits */
|
||||
ptr = swapdata;
|
||||
for (i = 0; i < swapsize; i++) {
|
||||
data = 0x00;
|
||||
data |= (*dataptr & 0x01) << 7;
|
||||
data |= (*dataptr & 0x02) << 5;
|
||||
data |= (*dataptr & 0x04) << 3;
|
||||
data |= (*dataptr & 0x08) << 1;
|
||||
data |= (*dataptr & 0x10) >> 1;
|
||||
data |= (*dataptr & 0x20) >> 3;
|
||||
data |= (*dataptr & 0x40) >> 5;
|
||||
data |= (*dataptr & 0x80) >> 7;
|
||||
*ptr++ = data;
|
||||
dataptr++;
|
||||
}
|
||||
|
||||
rc = fpga_load(dev, swapdata, swapsize);
|
||||
free(swapdata);
|
||||
return rc;
|
||||
#else
|
||||
printf("Bitstream support only for Xilinx devices\n");
|
||||
return FPGA_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* command form:
|
||||
* fpga <op> <device number> <data addr> <datasize>
|
||||
* where op is 'load', 'dump', or 'info'
|
||||
* If there is no device number field, the fpga environment variable is used.
|
||||
* If there is no data addr field, the fpgadata environment variable is used.
|
||||
* The info command requires no data address field.
|
||||
*/
|
||||
int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int op, dev = FPGA_INVALID_DEVICE;
|
||||
size_t data_size = 0;
|
||||
void *fpga_data = NULL;
|
||||
char *devstr = getenv ("fpga");
|
||||
char *datastr = getenv ("fpgadata");
|
||||
int rc = FPGA_FAIL;
|
||||
|
||||
if (devstr)
|
||||
dev = (int) simple_strtoul (devstr, NULL, 16);
|
||||
if (datastr)
|
||||
fpga_data = (void *) simple_strtoul (datastr, NULL, 16);
|
||||
|
||||
switch (argc) {
|
||||
case 5: /* fpga <op> <dev> <data> <datasize> */
|
||||
data_size = simple_strtoul (argv[4], NULL, 16);
|
||||
case 4: /* fpga <op> <dev> <data> */
|
||||
fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
|
||||
PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data);
|
||||
case 3: /* fpga <op> <dev | data addr> */
|
||||
dev = (int) simple_strtoul (argv[2], NULL, 16);
|
||||
PRINTF ("%s: device = %d\n", __FUNCTION__, dev);
|
||||
/* FIXME - this is a really weak test */
|
||||
if ((argc == 3) && (dev > fpga_count ())) { /* must be buffer ptr */
|
||||
PRINTF ("%s: Assuming buffer pointer in arg 3\n",
|
||||
__FUNCTION__);
|
||||
fpga_data = (void *) dev;
|
||||
PRINTF ("%s: fpga_data = 0x%x\n",
|
||||
__FUNCTION__, (uint) fpga_data);
|
||||
dev = FPGA_INVALID_DEVICE; /* reset device num */
|
||||
}
|
||||
case 2: /* fpga <op> */
|
||||
op = (int) fpga_get_op (argv[1]);
|
||||
break;
|
||||
default:
|
||||
PRINTF ("%s: Too many or too few args (%d)\n",
|
||||
__FUNCTION__, argc);
|
||||
op = FPGA_NONE; /* force usage display */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case FPGA_NONE:
|
||||
fpga_usage (cmdtp);
|
||||
break;
|
||||
|
||||
case FPGA_INFO:
|
||||
rc = fpga_info (dev);
|
||||
break;
|
||||
|
||||
case FPGA_LOAD:
|
||||
rc = fpga_load (dev, fpga_data, data_size);
|
||||
break;
|
||||
|
||||
case FPGA_LOADB:
|
||||
rc = fpga_loadbitstream(dev, fpga_data, data_size);
|
||||
break;
|
||||
|
||||
case FPGA_DUMP:
|
||||
rc = fpga_dump (dev, fpga_data, data_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("Unknown operation\n");
|
||||
fpga_usage (cmdtp);
|
||||
break;
|
||||
}
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static void fpga_usage (cmd_tbl_t * cmdtp)
|
||||
{
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Map op to supported operations. We don't use a table since we
|
||||
* would just have to relocate it from flash anyway.
|
||||
*/
|
||||
static int fpga_get_op (char *opstr)
|
||||
{
|
||||
int op = FPGA_NONE;
|
||||
|
||||
if (!strcmp ("info", opstr)) {
|
||||
op = FPGA_INFO;
|
||||
} else if (!strcmp ("loadb", opstr)) {
|
||||
op = FPGA_LOADB;
|
||||
} else if (!strcmp ("load", opstr)) {
|
||||
op = FPGA_LOAD;
|
||||
} else if (!strcmp ("dump", opstr)) {
|
||||
op = FPGA_DUMP;
|
||||
}
|
||||
|
||||
if (op == FPGA_NONE) {
|
||||
printf ("Unknown fpga operation \"%s\"\n", opstr);
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
U_BOOT_CMD (fpga, 6, 1, do_fpga,
|
||||
"fpga - loadable FPGA image support\n",
|
||||
"fpga [operation type] [device number] [image address] [image size]\n"
|
||||
"fpga operations:\n"
|
||||
"\tinfo\tlist known device information\n"
|
||||
"\tload\tLoad device from memory buffer\n"
|
||||
"\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"
|
||||
"\tdump\tLoad device to memory buffer\n");
|
||||
#endif /* CONFIG_FPGA && CONFIG_COMMANDS & CFG_CMD_FPGA */
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* I2C Functions similar to the standard memory functions.
|
||||
*
|
||||
* There are several parameters in many of the commands that bear further
|
||||
* explanations:
|
||||
*
|
||||
* Two of the commands (imm and imw) take a byte/word/long modifier
|
||||
* (e.g. imm.w specifies the word-length modifier). This was done to
|
||||
* allow manipulating word-length registers. It was not done on any other
|
||||
* commands because it was not deemed useful.
|
||||
*
|
||||
* {i2c_chip} is the I2C chip address (the first byte sent on the bus).
|
||||
* Each I2C chip on the bus has a unique address. On the I2C data bus,
|
||||
* the address is the upper seven bits and the LSB is the "read/write"
|
||||
* bit. Note that the {i2c_chip} address specified on the command
|
||||
* line is not shifted up: e.g. a typical EEPROM memory chip may have
|
||||
* an I2C address of 0x50, but the data put on the bus will be 0xA0
|
||||
* for write and 0xA1 for read. This "non shifted" address notation
|
||||
* matches at least half of the data sheets :-/.
|
||||
*
|
||||
* {addr} is the address (or offset) within the chip. Small memory
|
||||
* chips have 8 bit addresses. Large memory chips have 16 bit
|
||||
* addresses. Other memory chips have 9, 10, or 11 bit addresses.
|
||||
* Many non-memory chips have multiple registers and {addr} is used
|
||||
* as the register index. Some non-memory chips have only one register
|
||||
* and therefore don't need any {addr} parameter.
|
||||
*
|
||||
* The default {addr} parameter is one byte (.1) which works well for
|
||||
* memories and registers with 8 bits of address space.
|
||||
*
|
||||
* You can specify the length of the {addr} field with the optional .0,
|
||||
* .1, or .2 modifier (similar to the .b, .w, .l modifier). If you are
|
||||
* manipulating a single register device which doesn't use an address
|
||||
* field, use "0.0" for the address and the ".0" length field will
|
||||
* suppress the address in the I2C data stream. This also works for
|
||||
* successive reads using the I2C auto-incrementing memory pointer.
|
||||
*
|
||||
* If you are manipulating a large memory with 2-byte addresses, use
|
||||
* the .2 address modifier, e.g. 210.2 addresses location 528 (decimal).
|
||||
*
|
||||
* Then there are the unfortunate memory chips that spill the most
|
||||
* significant 1, 2, or 3 bits of address into the chip address byte.
|
||||
* This effectively makes one chip (logically) look like 2, 4, or
|
||||
* 8 chips. This is handled (awkwardly) by #defining
|
||||
* CFG_I2C_EEPROM_ADDR_OVERFLOW and using the .1 modifier on the
|
||||
* {addr} field (since .1 is the default, it doesn't actually have to
|
||||
* be specified). Examples: given a memory chip at I2C chip address
|
||||
* 0x50, the following would happen...
|
||||
* imd 50 0 10 display 16 bytes starting at 0x000
|
||||
* On the bus: <S> A0 00 <E> <S> A1 <rd> ... <rd>
|
||||
* imd 50 100 10 display 16 bytes starting at 0x100
|
||||
* On the bus: <S> A2 00 <E> <S> A3 <rd> ... <rd>
|
||||
* imd 50 210 10 display 16 bytes starting at 0x210
|
||||
* On the bus: <S> A4 10 <E> <S> A5 <rd> ... <rd>
|
||||
* This is awfully ugly. It would be nice if someone would think up
|
||||
* a better way of handling this.
|
||||
*
|
||||
* Adapted from cmd_mem.c which is copyright Wolfgang Denk (wd@denx.de).
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_I2C)
|
||||
|
||||
|
||||
/* Display values from last command.
|
||||
* Memory modify remembered values are different from display memory.
|
||||
*/
|
||||
static uchar i2c_dp_last_chip;
|
||||
static uint i2c_dp_last_addr;
|
||||
static uint i2c_dp_last_alen;
|
||||
static uint i2c_dp_last_length = 0x10;
|
||||
|
||||
static uchar i2c_mm_last_chip;
|
||||
static uint i2c_mm_last_addr;
|
||||
static uint i2c_mm_last_alen;
|
||||
|
||||
#if defined(CFG_I2C_NOPROBES)
|
||||
static uchar i2c_no_probes[] = CFG_I2C_NOPROBES;
|
||||
#endif
|
||||
|
||||
static int
|
||||
mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]);
|
||||
extern int cmd_get_data_size(char* arg, int default_size);
|
||||
|
||||
/*
|
||||
* Syntax:
|
||||
* imd {i2c_chip} {addr}{.0, .1, .2} {len}
|
||||
*/
|
||||
#define DISP_LINE_LEN 16
|
||||
|
||||
int do_i2c_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
u_char chip;
|
||||
uint addr, alen, length;
|
||||
int j, nbytes, linebytes;
|
||||
|
||||
/* We use the last specified parameters, unless new ones are
|
||||
* entered.
|
||||
*/
|
||||
chip = i2c_dp_last_chip;
|
||||
addr = i2c_dp_last_addr;
|
||||
alen = i2c_dp_last_alen;
|
||||
length = i2c_dp_last_length;
|
||||
|
||||
if (argc < 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0) {
|
||||
/*
|
||||
* New command specified.
|
||||
*/
|
||||
alen = 1;
|
||||
|
||||
/*
|
||||
* I2C chip address
|
||||
*/
|
||||
chip = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
/*
|
||||
* I2C data address within the chip. This can be 1 or
|
||||
* 2 bytes long. Some day it might be 3 bytes long :-).
|
||||
*/
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
alen = 1;
|
||||
for(j = 0; j < 8; j++) {
|
||||
if (argv[2][j] == '.') {
|
||||
alen = argv[2][j+1] - '0';
|
||||
if (alen > 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (argv[2][j] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If another parameter, it is the length to display.
|
||||
* Length is the number of objects, not number of bytes.
|
||||
*/
|
||||
if (argc > 3)
|
||||
length = simple_strtoul(argv[3], NULL, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the lines.
|
||||
*
|
||||
* We buffer all read data, so we can make sure data is read only
|
||||
* once.
|
||||
*/
|
||||
nbytes = length;
|
||||
do {
|
||||
unsigned char linebuf[DISP_LINE_LEN];
|
||||
unsigned char *cp;
|
||||
|
||||
linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
|
||||
|
||||
if(i2c_read(chip, addr, alen, linebuf, linebytes) != 0) {
|
||||
puts ("Error reading the chip.\n");
|
||||
} else {
|
||||
printf("%04x:", addr);
|
||||
cp = linebuf;
|
||||
for (j=0; j<linebytes; j++) {
|
||||
printf(" %02x", *cp++);
|
||||
addr++;
|
||||
}
|
||||
puts (" ");
|
||||
cp = linebuf;
|
||||
for (j=0; j<linebytes; j++) {
|
||||
if ((*cp < 0x20) || (*cp > 0x7e))
|
||||
puts (".");
|
||||
else
|
||||
printf("%c", *cp);
|
||||
cp++;
|
||||
}
|
||||
putc ('\n');
|
||||
}
|
||||
nbytes -= linebytes;
|
||||
} while (nbytes > 0);
|
||||
|
||||
i2c_dp_last_chip = chip;
|
||||
i2c_dp_last_addr = addr;
|
||||
i2c_dp_last_alen = alen;
|
||||
i2c_dp_last_length = length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_i2c_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
return mod_i2c_mem (cmdtp, 1, flag, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
int do_i2c_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
return mod_i2c_mem (cmdtp, 0, flag, argc, argv);
|
||||
}
|
||||
|
||||
/* Write (fill) memory
|
||||
*
|
||||
* Syntax:
|
||||
* imw {i2c_chip} {addr}{.0, .1, .2} {data} [{count}]
|
||||
*/
|
||||
int do_i2c_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
uchar chip;
|
||||
ulong addr;
|
||||
uint alen;
|
||||
uchar byte;
|
||||
int count;
|
||||
int j;
|
||||
|
||||
if ((argc < 4) || (argc > 5)) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Chip is always specified.
|
||||
*/
|
||||
chip = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
/*
|
||||
* Address is always specified.
|
||||
*/
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
alen = 1;
|
||||
for(j = 0; j < 8; j++) {
|
||||
if (argv[2][j] == '.') {
|
||||
alen = argv[2][j+1] - '0';
|
||||
if(alen > 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (argv[2][j] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Value to write is always specified.
|
||||
*/
|
||||
byte = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
/*
|
||||
* Optional count
|
||||
*/
|
||||
if(argc == 5) {
|
||||
count = simple_strtoul(argv[4], NULL, 16);
|
||||
} else {
|
||||
count = 1;
|
||||
}
|
||||
|
||||
while (count-- > 0) {
|
||||
if(i2c_write(chip, addr++, alen, &byte, 1) != 0) {
|
||||
puts ("Error writing the chip.\n");
|
||||
}
|
||||
/*
|
||||
* Wait for the write to complete. The write can take
|
||||
* up to 10mSec (we allow a little more time).
|
||||
*
|
||||
* On some chips, while the write is in progress, the
|
||||
* chip doesn't respond. This apparently isn't a
|
||||
* universal feature so we don't take advantage of it.
|
||||
*/
|
||||
/*
|
||||
* No write delay with FRAM devices.
|
||||
*/
|
||||
#if !defined(CFG_I2C_FRAM)
|
||||
udelay(11000);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for(timeout = 0; timeout < 10; timeout++) {
|
||||
udelay(2000);
|
||||
if(i2c_probe(chip) == 0)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Calculate a CRC on memory
|
||||
*
|
||||
* Syntax:
|
||||
* icrc32 {i2c_chip} {addr}{.0, .1, .2} {count}
|
||||
*/
|
||||
int do_i2c_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
uchar chip;
|
||||
ulong addr;
|
||||
uint alen;
|
||||
int count;
|
||||
uchar byte;
|
||||
ulong crc;
|
||||
ulong err;
|
||||
int j;
|
||||
|
||||
if (argc < 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Chip is always specified.
|
||||
*/
|
||||
chip = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
/*
|
||||
* Address is always specified.
|
||||
*/
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
alen = 1;
|
||||
for(j = 0; j < 8; j++) {
|
||||
if (argv[2][j] == '.') {
|
||||
alen = argv[2][j+1] - '0';
|
||||
if(alen > 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (argv[2][j] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Count is always specified
|
||||
*/
|
||||
count = simple_strtoul(argv[3], NULL, 16);
|
||||
|
||||
printf ("CRC32 for %08lx ... %08lx ==> ", addr, addr + count - 1);
|
||||
/*
|
||||
* CRC a byte at a time. This is going to be slooow, but hey, the
|
||||
* memories are small and slow too so hopefully nobody notices.
|
||||
*/
|
||||
crc = 0;
|
||||
err = 0;
|
||||
while(count-- > 0) {
|
||||
if(i2c_read(chip, addr, alen, &byte, 1) != 0) {
|
||||
err++;
|
||||
}
|
||||
crc = crc32 (crc, &byte, 1);
|
||||
addr++;
|
||||
}
|
||||
if(err > 0)
|
||||
{
|
||||
puts ("Error reading the chip,\n");
|
||||
} else {
|
||||
printf ("%08lx\n", crc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Modify memory.
|
||||
*
|
||||
* Syntax:
|
||||
* imm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
|
||||
* inm{.b, .w, .l} {i2c_chip} {addr}{.0, .1, .2}
|
||||
*/
|
||||
|
||||
static int
|
||||
mod_i2c_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
|
||||
{
|
||||
uchar chip;
|
||||
ulong addr;
|
||||
uint alen;
|
||||
ulong data;
|
||||
int size = 1;
|
||||
int nbytes;
|
||||
int j;
|
||||
extern char console_buffer[];
|
||||
|
||||
if (argc != 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOT_RETRY_TIME
|
||||
reset_cmd_timeout(); /* got a good command to get here */
|
||||
#endif
|
||||
/*
|
||||
* We use the last specified parameters, unless new ones are
|
||||
* entered.
|
||||
*/
|
||||
chip = i2c_mm_last_chip;
|
||||
addr = i2c_mm_last_addr;
|
||||
alen = i2c_mm_last_alen;
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0) {
|
||||
/*
|
||||
* New command specified. Check for a size specification.
|
||||
* Defaults to byte if no or incorrect specification.
|
||||
*/
|
||||
size = cmd_get_data_size(argv[0], 1);
|
||||
|
||||
/*
|
||||
* Chip is always specified.
|
||||
*/
|
||||
chip = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
/*
|
||||
* Address is always specified.
|
||||
*/
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
alen = 1;
|
||||
for(j = 0; j < 8; j++) {
|
||||
if (argv[2][j] == '.') {
|
||||
alen = argv[2][j+1] - '0';
|
||||
if(alen > 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (argv[2][j] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the address, followed by value. Then accept input for
|
||||
* the next value. A non-converted value exits.
|
||||
*/
|
||||
do {
|
||||
printf("%08lx:", addr);
|
||||
if(i2c_read(chip, addr, alen, (uchar *)&data, size) != 0) {
|
||||
puts ("\nError reading the chip,\n");
|
||||
} else {
|
||||
data = cpu_to_be32(data);
|
||||
if(size == 1) {
|
||||
printf(" %02lx", (data >> 24) & 0x000000FF);
|
||||
} else if(size == 2) {
|
||||
printf(" %04lx", (data >> 16) & 0x0000FFFF);
|
||||
} else {
|
||||
printf(" %08lx", data);
|
||||
}
|
||||
}
|
||||
|
||||
nbytes = readline (" ? ");
|
||||
if (nbytes == 0) {
|
||||
/*
|
||||
* <CR> pressed as only input, don't modify current
|
||||
* location and move to next.
|
||||
*/
|
||||
if (incrflag)
|
||||
addr += size;
|
||||
nbytes = size;
|
||||
#ifdef CONFIG_BOOT_RETRY_TIME
|
||||
reset_cmd_timeout(); /* good enough to not time out */
|
||||
#endif
|
||||
}
|
||||
#ifdef CONFIG_BOOT_RETRY_TIME
|
||||
else if (nbytes == -2) {
|
||||
break; /* timed out, exit the command */
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
char *endp;
|
||||
|
||||
data = simple_strtoul(console_buffer, &endp, 16);
|
||||
if(size == 1) {
|
||||
data = data << 24;
|
||||
} else if(size == 2) {
|
||||
data = data << 16;
|
||||
}
|
||||
data = be32_to_cpu(data);
|
||||
nbytes = endp - console_buffer;
|
||||
if (nbytes) {
|
||||
#ifdef CONFIG_BOOT_RETRY_TIME
|
||||
/*
|
||||
* good enough to not time out
|
||||
*/
|
||||
reset_cmd_timeout();
|
||||
#endif
|
||||
if(i2c_write(chip, addr, alen, (uchar *)&data, size) != 0) {
|
||||
puts ("Error writing the chip.\n");
|
||||
}
|
||||
#ifdef CFG_EEPROM_PAGE_WRITE_DELAY_MS
|
||||
udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
|
||||
#endif
|
||||
if (incrflag)
|
||||
addr += size;
|
||||
}
|
||||
}
|
||||
} while (nbytes);
|
||||
|
||||
chip = i2c_mm_last_chip;
|
||||
addr = i2c_mm_last_addr;
|
||||
alen = i2c_mm_last_alen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Syntax:
|
||||
* iprobe {addr}{.0, .1, .2}
|
||||
*/
|
||||
int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int j;
|
||||
#if defined(CFG_I2C_NOPROBES)
|
||||
int k, skip;
|
||||
#endif
|
||||
|
||||
puts ("Valid chip addresses:");
|
||||
for(j = 0; j < 128; j++) {
|
||||
#if defined(CFG_I2C_NOPROBES)
|
||||
skip = 0;
|
||||
for (k = 0; k < sizeof(i2c_no_probes); k++){
|
||||
if (j == i2c_no_probes[k]){
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
#endif
|
||||
if(i2c_probe(j) == 0) {
|
||||
printf(" %02X", j);
|
||||
}
|
||||
}
|
||||
putc ('\n');
|
||||
|
||||
#if defined(CFG_I2C_NOPROBES)
|
||||
puts ("Excluded chip addresses:");
|
||||
for( k = 0; k < sizeof(i2c_no_probes); k++ )
|
||||
printf(" %02X", i2c_no_probes[k] );
|
||||
putc ('\n');
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Syntax:
|
||||
* iloop {i2c_chip} {addr}{.0, .1, .2} [{length}] [{delay}]
|
||||
* {length} - Number of bytes to read
|
||||
* {delay} - A DECIMAL number and defaults to 1000 uSec
|
||||
*/
|
||||
int do_i2c_loop(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
u_char chip;
|
||||
ulong alen;
|
||||
uint addr;
|
||||
uint length;
|
||||
u_char bytes[16];
|
||||
int delay;
|
||||
int j;
|
||||
|
||||
if (argc < 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Chip is always specified.
|
||||
*/
|
||||
chip = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
/*
|
||||
* Address is always specified.
|
||||
*/
|
||||
addr = simple_strtoul(argv[2], NULL, 16);
|
||||
alen = 1;
|
||||
for(j = 0; j < 8; j++) {
|
||||
if (argv[2][j] == '.') {
|
||||
alen = argv[2][j+1] - '0';
|
||||
if (alen > 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (argv[2][j] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Length is the number of objects, not number of bytes.
|
||||
*/
|
||||
length = 1;
|
||||
length = simple_strtoul(argv[3], NULL, 16);
|
||||
if(length > sizeof(bytes)) {
|
||||
length = sizeof(bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
* The delay time (uSec) is optional.
|
||||
*/
|
||||
delay = 1000;
|
||||
if (argc > 3) {
|
||||
delay = simple_strtoul(argv[4], NULL, 10);
|
||||
}
|
||||
/*
|
||||
* Run the loop...
|
||||
*/
|
||||
while(1) {
|
||||
if(i2c_read(chip, addr, alen, bytes, length) != 0) {
|
||||
puts ("Error reading the chip.\n");
|
||||
}
|
||||
udelay(delay);
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The SDRAM command is separately configured because many
|
||||
* (most?) embedded boards don't use SDRAM DIMMs.
|
||||
*/
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SDRAM)
|
||||
|
||||
/*
|
||||
* Syntax:
|
||||
* sdram {i2c_chip}
|
||||
*/
|
||||
int do_sdram ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
u_char chip;
|
||||
u_char data[128];
|
||||
u_char cksum;
|
||||
int j;
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Chip is always specified.
|
||||
*/
|
||||
chip = simple_strtoul(argv[1], NULL, 16);
|
||||
|
||||
if(i2c_read(chip, 0, 1, data, sizeof(data)) != 0) {
|
||||
puts ("No SDRAM Serial Presence Detect found.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cksum = 0;
|
||||
for (j = 0; j < 63; j++) {
|
||||
cksum += data[j];
|
||||
}
|
||||
if(cksum != data[63]) {
|
||||
printf ("WARNING: Configuration data checksum failure:\n"
|
||||
" is 0x%02x, calculated 0x%02x\n",
|
||||
data[63], cksum);
|
||||
}
|
||||
printf("SPD data revision %d.%d\n",
|
||||
(data[62] >> 4) & 0x0F, data[62] & 0x0F);
|
||||
printf("Bytes used 0x%02X\n", data[0]);
|
||||
printf("Serial memory size 0x%02X\n", 1 << data[1]);
|
||||
puts ("Memory type ");
|
||||
switch(data[2]) {
|
||||
case 2: puts ("EDO\n"); break;
|
||||
case 4: puts ("SDRAM\n"); break;
|
||||
default: puts ("unknown\n"); break;
|
||||
}
|
||||
puts ("Row address bits ");
|
||||
if((data[3] & 0x00F0) == 0) {
|
||||
printf("%d\n", data[3] & 0x0F);
|
||||
} else {
|
||||
printf("%d/%d\n", data[3] & 0x0F, (data[3] >> 4) & 0x0F);
|
||||
}
|
||||
puts ("Column address bits ");
|
||||
if((data[4] & 0x00F0) == 0) {
|
||||
printf("%d\n", data[4] & 0x0F);
|
||||
} else {
|
||||
printf("%d/%d\n", data[4] & 0x0F, (data[4] >> 4) & 0x0F);
|
||||
}
|
||||
printf("Module rows %d\n", data[5]);
|
||||
printf("Module data width %d bits\n", (data[7] << 8) | data[6]);
|
||||
puts ("Interface signal levels ");
|
||||
switch(data[8]) {
|
||||
case 0: puts ("5.0v/TTL\n"); break;
|
||||
case 1: puts ("LVTTL\n"); break;
|
||||
case 2: puts ("HSTL 1.5\n"); break;
|
||||
case 3: puts ("SSTL 3.3\n"); break;
|
||||
case 4: puts ("SSTL 2.5\n"); break;
|
||||
default: puts ("unknown\n"); break;
|
||||
}
|
||||
printf("SDRAM cycle time %d.%d nS\n",
|
||||
(data[9] >> 4) & 0x0F, data[9] & 0x0F);
|
||||
printf("SDRAM access time %d.%d nS\n",
|
||||
(data[10] >> 4) & 0x0F, data[10] & 0x0F);
|
||||
puts ("EDC configuration ");
|
||||
switch(data[11]) {
|
||||
case 0: puts ("None\n"); break;
|
||||
case 1: puts ("Parity\n"); break;
|
||||
case 2: puts ("ECC\n"); break;
|
||||
default: puts ("unknown\n"); break;
|
||||
}
|
||||
if((data[12] & 0x80) == 0) {
|
||||
puts ("No self refresh, rate ");
|
||||
} else {
|
||||
puts ("Self refresh, rate ");
|
||||
}
|
||||
switch(data[12] & 0x7F) {
|
||||
case 0: puts ("15.625uS\n"); break;
|
||||
case 1: puts ("3.9uS\n"); break;
|
||||
case 2: puts ("7.8uS\n"); break;
|
||||
case 3: puts ("31.3uS\n"); break;
|
||||
case 4: puts ("62.5uS\n"); break;
|
||||
case 5: puts ("125uS\n"); break;
|
||||
default: puts ("unknown\n"); break;
|
||||
}
|
||||
printf("SDRAM width (primary) %d\n", data[13] & 0x7F);
|
||||
if((data[13] & 0x80) != 0) {
|
||||
printf(" (second bank) %d\n",
|
||||
2 * (data[13] & 0x7F));
|
||||
}
|
||||
if(data[14] != 0) {
|
||||
printf("EDC width %d\n",
|
||||
data[14] & 0x7F);
|
||||
if((data[14] & 0x80) != 0) {
|
||||
printf(" (second bank) %d\n",
|
||||
2 * (data[14] & 0x7F));
|
||||
}
|
||||
}
|
||||
printf("Min clock delay, back-to-back random column addresses %d\n",
|
||||
data[15]);
|
||||
puts ("Burst length(s) ");
|
||||
if (data[16] & 0x80) puts (" Page");
|
||||
if (data[16] & 0x08) puts (" 8");
|
||||
if (data[16] & 0x04) puts (" 4");
|
||||
if (data[16] & 0x02) puts (" 2");
|
||||
if (data[16] & 0x01) puts (" 1");
|
||||
putc ('\n');
|
||||
printf("Number of banks %d\n", data[17]);
|
||||
puts ("CAS latency(s) ");
|
||||
if (data[18] & 0x80) puts (" TBD");
|
||||
if (data[18] & 0x40) puts (" 7");
|
||||
if (data[18] & 0x20) puts (" 6");
|
||||
if (data[18] & 0x10) puts (" 5");
|
||||
if (data[18] & 0x08) puts (" 4");
|
||||
if (data[18] & 0x04) puts (" 3");
|
||||
if (data[18] & 0x02) puts (" 2");
|
||||
if (data[18] & 0x01) puts (" 1");
|
||||
putc ('\n');
|
||||
puts ("CS latency(s) ");
|
||||
if (data[19] & 0x80) puts (" TBD");
|
||||
if (data[19] & 0x40) puts (" 6");
|
||||
if (data[19] & 0x20) puts (" 5");
|
||||
if (data[19] & 0x10) puts (" 4");
|
||||
if (data[19] & 0x08) puts (" 3");
|
||||
if (data[19] & 0x04) puts (" 2");
|
||||
if (data[19] & 0x02) puts (" 1");
|
||||
if (data[19] & 0x01) puts (" 0");
|
||||
putc ('\n');
|
||||
puts ("WE latency(s) ");
|
||||
if (data[20] & 0x80) puts (" TBD");
|
||||
if (data[20] & 0x40) puts (" 6");
|
||||
if (data[20] & 0x20) puts (" 5");
|
||||
if (data[20] & 0x10) puts (" 4");
|
||||
if (data[20] & 0x08) puts (" 3");
|
||||
if (data[20] & 0x04) puts (" 2");
|
||||
if (data[20] & 0x02) puts (" 1");
|
||||
if (data[20] & 0x01) puts (" 0");
|
||||
putc ('\n');
|
||||
puts ("Module attributes:\n");
|
||||
if (!data[21]) puts (" (none)\n");
|
||||
if (data[21] & 0x80) puts (" TBD (bit 7)\n");
|
||||
if (data[21] & 0x40) puts (" Redundant row address\n");
|
||||
if (data[21] & 0x20) puts (" Differential clock input\n");
|
||||
if (data[21] & 0x10) puts (" Registerd DQMB inputs\n");
|
||||
if (data[21] & 0x08) puts (" Buffered DQMB inputs\n");
|
||||
if (data[21] & 0x04) puts (" On-card PLL\n");
|
||||
if (data[21] & 0x02) puts (" Registered address/control lines\n");
|
||||
if (data[21] & 0x01) puts (" Buffered address/control lines\n");
|
||||
puts ("Device attributes:\n");
|
||||
if (data[22] & 0x80) puts (" TBD (bit 7)\n");
|
||||
if (data[22] & 0x40) puts (" TBD (bit 6)\n");
|
||||
if (data[22] & 0x20) puts (" Upper Vcc tolerance 5%\n");
|
||||
else puts (" Upper Vcc tolerance 10%\n");
|
||||
if (data[22] & 0x10) puts (" Lower Vcc tolerance 5%\n");
|
||||
else puts (" Lower Vcc tolerance 10%\n");
|
||||
if (data[22] & 0x08) puts (" Supports write1/read burst\n");
|
||||
if (data[22] & 0x04) puts (" Supports precharge all\n");
|
||||
if (data[22] & 0x02) puts (" Supports auto precharge\n");
|
||||
if (data[22] & 0x01) puts (" Supports early RAS# precharge\n");
|
||||
printf("SDRAM cycle time (2nd highest CAS latency) %d.%d nS\n",
|
||||
(data[23] >> 4) & 0x0F, data[23] & 0x0F);
|
||||
printf("SDRAM access from clock (2nd highest CAS latency) %d.%d nS\n",
|
||||
(data[24] >> 4) & 0x0F, data[24] & 0x0F);
|
||||
printf("SDRAM cycle time (3rd highest CAS latency) %d.%d nS\n",
|
||||
(data[25] >> 4) & 0x0F, data[25] & 0x0F);
|
||||
printf("SDRAM access from clock (3rd highest CAS latency) %d.%d nS\n",
|
||||
(data[26] >> 4) & 0x0F, data[26] & 0x0F);
|
||||
printf("Minimum row precharge %d nS\n", data[27]);
|
||||
printf("Row active to row active min %d nS\n", data[28]);
|
||||
printf("RAS to CAS delay min %d nS\n", data[29]);
|
||||
printf("Minimum RAS pulse width %d nS\n", data[30]);
|
||||
puts ("Density of each row ");
|
||||
if (data[31] & 0x80) puts (" 512");
|
||||
if (data[31] & 0x40) puts (" 256");
|
||||
if (data[31] & 0x20) puts (" 128");
|
||||
if (data[31] & 0x10) puts (" 64");
|
||||
if (data[31] & 0x08) puts (" 32");
|
||||
if (data[31] & 0x04) puts (" 16");
|
||||
if (data[31] & 0x02) puts (" 8");
|
||||
if (data[31] & 0x01) puts (" 4");
|
||||
puts ("MByte\n");
|
||||
printf("Command and Address setup %c%d.%d nS\n",
|
||||
(data[32] & 0x80) ? '-' : '+',
|
||||
(data[32] >> 4) & 0x07, data[32] & 0x0F);
|
||||
printf("Command and Address hold %c%d.%d nS\n",
|
||||
(data[33] & 0x80) ? '-' : '+',
|
||||
(data[33] >> 4) & 0x07, data[33] & 0x0F);
|
||||
printf("Data signal input setup %c%d.%d nS\n",
|
||||
(data[34] & 0x80) ? '-' : '+',
|
||||
(data[34] >> 4) & 0x07, data[34] & 0x0F);
|
||||
printf("Data signal input hold %c%d.%d nS\n",
|
||||
(data[35] & 0x80) ? '-' : '+',
|
||||
(data[35] >> 4) & 0x07, data[35] & 0x0F);
|
||||
puts ("Manufacturer's JEDEC ID ");
|
||||
for(j = 64; j <= 71; j++)
|
||||
printf("%02X ", data[j]);
|
||||
putc ('\n');
|
||||
printf("Manufacturing Location %02X\n", data[72]);
|
||||
puts ("Manufacturer's Part Number ");
|
||||
for(j = 73; j <= 90; j++)
|
||||
printf("%02X ", data[j]);
|
||||
putc ('\n');
|
||||
printf("Revision Code %02X %02X\n", data[91], data[92]);
|
||||
printf("Manufacturing Date %02X %02X\n", data[93], data[94]);
|
||||
puts ("Assembly Serial Number ");
|
||||
for(j = 95; j <= 98; j++)
|
||||
printf("%02X ", data[j]);
|
||||
putc ('\n');
|
||||
printf("Speed rating PC%d\n",
|
||||
data[126] == 0x66 ? 66 : data[126]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CFG_CMD_SDRAM */
|
||||
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
imd, 4, 1, do_i2c_md, \
|
||||
"imd - i2c memory display\n", \
|
||||
"chip address[.0, .1, .2] [# of objects]\n - i2c memory display\n" \
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
imm, 3, 1, do_i2c_mm,
|
||||
"imm - i2c memory modify (auto-incrementing)\n",
|
||||
"chip address[.0, .1, .2]\n"
|
||||
" - memory modify, auto increment address\n"
|
||||
);
|
||||
U_BOOT_CMD(
|
||||
inm, 3, 1, do_i2c_nm,
|
||||
"inm - memory modify (constant address)\n",
|
||||
"chip address[.0, .1, .2]\n - memory modify, read and keep address\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
imw, 5, 1, do_i2c_mw,
|
||||
"imw - memory write (fill)\n",
|
||||
"chip address[.0, .1, .2] value [count]\n - memory write (fill)\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
icrc32, 5, 1, do_i2c_crc,
|
||||
"icrc32 - checksum calculation\n",
|
||||
"chip address[.0, .1, .2] count\n - compute CRC32 checksum\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
iprobe, 1, 1, do_i2c_probe,
|
||||
"iprobe - probe to discover valid I2C chip addresses\n",
|
||||
"\n -discover valid I2C chip addresses\n"
|
||||
);
|
||||
|
||||
/*
|
||||
* Require full name for "iloop" because it is an infinite loop!
|
||||
*/
|
||||
U_BOOT_CMD(
|
||||
iloop, 5, 1, do_i2c_loop,
|
||||
"iloop - infinite loop on address range\n",
|
||||
"chip address[.0, .1, .2] [# of objects]\n"
|
||||
" - loop, reading a set of addresses\n"
|
||||
);
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SDRAM)
|
||||
U_BOOT_CMD(
|
||||
isdram, 2, 1, do_sdram,
|
||||
"isdram - print SDRAM configuration information\n",
|
||||
"chip\n - print SDRAM configuration information\n"
|
||||
" (valid chip values 50..57)\n"
|
||||
);
|
||||
#endif
|
||||
#endif /* CFG_CMD_I2C */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,723 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2003
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* MPC8xx/MPC8260 Internal Memory Map Functions
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IMMAP) && \
|
||||
(defined(CONFIG_8xx) || defined(CONFIG_8260))
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
#include <asm/8xx_immap.h>
|
||||
#include <commproc.h>
|
||||
#include <asm/iopin_8xx.h>
|
||||
#elif defined(CONFIG_8260)
|
||||
#include <asm/immap_8260.h>
|
||||
#include <asm/cpm_8260.h>
|
||||
#include <asm/iopin_8260.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_8xx) || defined(CONFIG_8260)
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
|
||||
static void
|
||||
unimplemented ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
printf ("Sorry, but the '%s' command has not been implemented\n",
|
||||
cmdtp->name);
|
||||
}
|
||||
|
||||
int
|
||||
do_siuinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
volatile sysconf8xx_t *sc = &immap->im_siu_conf;
|
||||
#elif defined(CONFIG_8260)
|
||||
volatile sysconf8260_t *sc = &immap->im_siu_conf;
|
||||
#endif
|
||||
|
||||
printf ("SIUMCR= %08x SYPCR = %08x\n", sc->sc_siumcr, sc->sc_sypcr);
|
||||
#if defined(CONFIG_8xx)
|
||||
printf ("SWT = %08x\n", sc->sc_swt);
|
||||
printf ("SIPEND= %08x SIMASK= %08x\n", sc->sc_sipend, sc->sc_simask);
|
||||
printf ("SIEL = %08x SIVEC = %08x\n", sc->sc_siel, sc->sc_sivec);
|
||||
printf ("TESR = %08x SDCR = %08x\n", sc->sc_tesr, sc->sc_sdcr);
|
||||
#elif defined(CONFIG_8260)
|
||||
printf ("BCR = %08x\n", sc->sc_bcr);
|
||||
printf ("P_ACR = %02x P_ALRH= %08x P_ALRL= %08x\n",
|
||||
sc->sc_ppc_acr, sc->sc_ppc_alrh, sc->sc_ppc_alrl);
|
||||
printf ("L_ACR = %02x L_ALRH= %08x L_ALRL= %08x\n",
|
||||
sc->sc_lcl_acr, sc->sc_lcl_alrh, sc->sc_lcl_alrl);
|
||||
printf ("PTESR1= %08x PTESR2= %08x\n", sc->sc_tescr1, sc->sc_tescr2);
|
||||
printf ("LTESR1= %08x LTESR2= %08x\n", sc->sc_ltescr1, sc->sc_ltescr2);
|
||||
printf ("PDTEA = %08x PDTEM = %02x\n", sc->sc_pdtea, sc->sc_pdtem);
|
||||
printf ("LDTEA = %08x LDTEM = %02x\n", sc->sc_ldtea, sc->sc_ldtem);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_memcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
volatile memctl8xx_t *memctl = &immap->im_memctl;
|
||||
int nbanks = 8;
|
||||
#elif defined(CONFIG_8260)
|
||||
volatile memctl8260_t *memctl = &immap->im_memctl;
|
||||
int nbanks = 12;
|
||||
#endif
|
||||
volatile uint *p = &memctl->memc_br0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nbanks; i++, p += 2) {
|
||||
if (i < 10) {
|
||||
printf ("BR%d = %08x OR%d = %08x\n",
|
||||
i, p[0], i, p[1]);
|
||||
} else {
|
||||
printf ("BR%d = %08x OR%d = %08x\n",
|
||||
i, p[0], i, p[1]);
|
||||
}
|
||||
}
|
||||
|
||||
printf ("MAR = %08x", memctl->memc_mar);
|
||||
#if defined(CONFIG_8xx)
|
||||
printf (" MCR = %08x\n", memctl->memc_mcr);
|
||||
#elif defined(CONFIG_8260)
|
||||
putc ('\n');
|
||||
#endif
|
||||
printf ("MAMR = %08x MBMR = %08x",
|
||||
memctl->memc_mamr, memctl->memc_mbmr);
|
||||
#if defined(CONFIG_8xx)
|
||||
printf ("\nMSTAT = %04x\n", memctl->memc_mstat);
|
||||
#elif defined(CONFIG_8260)
|
||||
printf (" MCMR = %08x\n", memctl->memc_mcmr);
|
||||
#endif
|
||||
printf ("MPTPR = %04x MDR = %08x\n",
|
||||
memctl->memc_mptpr, memctl->memc_mdr);
|
||||
#if defined(CONFIG_8260)
|
||||
printf ("PSDMR = %08x LSDMR = %08x\n",
|
||||
memctl->memc_psdmr, memctl->memc_lsdmr);
|
||||
printf ("PURT = %02x PSRT = %02x\n",
|
||||
memctl->memc_purt, memctl->memc_psrt);
|
||||
printf ("LURT = %02x LSRT = %02x\n",
|
||||
memctl->memc_lurt, memctl->memc_lsrt);
|
||||
printf ("IMMR = %08x\n", memctl->memc_immr);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_sitinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_8260
|
||||
int
|
||||
do_icinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
do_carinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
volatile car8xx_t *car = &immap->im_clkrst;
|
||||
#elif defined(CONFIG_8260)
|
||||
volatile car8260_t *car = &immap->im_clkrst;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
printf ("SCCR = %08x\n", car->car_sccr);
|
||||
printf ("PLPRCR= %08x\n", car->car_plprcr);
|
||||
printf ("RSR = %08x\n", car->car_rsr);
|
||||
#elif defined(CONFIG_8260)
|
||||
printf ("SCCR = %08x\n", car->car_sccr);
|
||||
printf ("SCMR = %08x\n", car->car_scmr);
|
||||
printf ("RSR = %08x\n", car->car_rsr);
|
||||
printf ("RMR = %08x\n", car->car_rmr);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int counter;
|
||||
|
||||
static void
|
||||
header(void)
|
||||
{
|
||||
char *data = "\
|
||||
-------------------------------- --------------------------------\
|
||||
00000000001111111111222222222233 00000000001111111111222222222233\
|
||||
01234567890123456789012345678901 01234567890123456789012345678901\
|
||||
-------------------------------- --------------------------------\
|
||||
";
|
||||
int i;
|
||||
|
||||
if (counter % 2)
|
||||
putc('\n');
|
||||
counter = 0;
|
||||
|
||||
for (i = 0; i < 4; i++, data += 79)
|
||||
printf("%.79s\n", data);
|
||||
}
|
||||
|
||||
static void binary (char *label, uint value, int nbits)
|
||||
{
|
||||
uint mask = 1 << (nbits - 1);
|
||||
int i, second = (counter++ % 2);
|
||||
|
||||
if (second)
|
||||
putc (' ');
|
||||
puts (label);
|
||||
for (i = 32 + 1; i != nbits; i--)
|
||||
putc (' ');
|
||||
|
||||
while (mask != 0) {
|
||||
if (value & mask)
|
||||
putc ('1');
|
||||
else
|
||||
putc ('0');
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
if (second)
|
||||
putc ('\n');
|
||||
}
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
#define PA_NBITS 16
|
||||
#define PA_NB_ODR 8
|
||||
#define PB_NBITS 18
|
||||
#define PB_NB_ODR 16
|
||||
#define PC_NBITS 12
|
||||
#define PD_NBITS 13
|
||||
#elif defined(CONFIG_8260)
|
||||
#define PA_NBITS 32
|
||||
#define PA_NB_ODR 32
|
||||
#define PB_NBITS 28
|
||||
#define PB_NB_ODR 28
|
||||
#define PC_NBITS 32
|
||||
#define PD_NBITS 28
|
||||
#endif
|
||||
|
||||
int
|
||||
do_iopinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
volatile iop8xx_t *iop = &immap->im_ioport;
|
||||
volatile ushort *l, *r;
|
||||
#elif defined(CONFIG_8260)
|
||||
volatile iop8260_t *iop = &immap->im_ioport;
|
||||
volatile uint *l, *r;
|
||||
#endif
|
||||
volatile uint *R;
|
||||
|
||||
counter = 0;
|
||||
header ();
|
||||
|
||||
/*
|
||||
* Ports A & B
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
l = &iop->iop_padir;
|
||||
R = &immap->im_cpm.cp_pbdir;
|
||||
#elif defined(CONFIG_8260)
|
||||
l = &iop->iop_pdira;
|
||||
R = &iop->iop_pdirb;
|
||||
#endif
|
||||
binary ("PA_DIR", *l++, PA_NBITS);
|
||||
binary ("PB_DIR", *R++, PB_NBITS);
|
||||
binary ("PA_PAR", *l++, PA_NBITS);
|
||||
binary ("PB_PAR", *R++, PB_NBITS);
|
||||
#if defined(CONFIG_8260)
|
||||
binary ("PA_SOR", *l++, PA_NBITS);
|
||||
binary ("PB_SOR", *R++, PB_NBITS);
|
||||
#endif
|
||||
binary ("PA_ODR", *l++, PA_NB_ODR);
|
||||
binary ("PB_ODR", *R++, PB_NB_ODR);
|
||||
binary ("PA_DAT", *l++, PA_NBITS);
|
||||
binary ("PB_DAT", *R++, PB_NBITS);
|
||||
|
||||
header ();
|
||||
|
||||
/*
|
||||
* Ports C & D
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
l = &iop->iop_pcdir;
|
||||
r = &iop->iop_pddir;
|
||||
#elif defined(CONFIG_8260)
|
||||
l = &iop->iop_pdirc;
|
||||
r = &iop->iop_pdird;
|
||||
#endif
|
||||
binary ("PC_DIR", *l++, PC_NBITS);
|
||||
binary ("PD_DIR", *r++, PD_NBITS);
|
||||
binary ("PC_PAR", *l++, PC_NBITS);
|
||||
binary ("PD_PAR", *r++, PD_NBITS);
|
||||
#if defined(CONFIG_8xx)
|
||||
binary ("PC_SO ", *l++, PC_NBITS);
|
||||
binary (" ", 0, 0);
|
||||
r++;
|
||||
#elif defined(CONFIG_8260)
|
||||
binary ("PC_SOR", *l++, PC_NBITS);
|
||||
binary ("PD_SOR", *r++, PD_NBITS);
|
||||
binary ("PC_ODR", *l++, PC_NBITS);
|
||||
binary ("PD_ODR", *r++, PD_NBITS);
|
||||
#endif
|
||||
binary ("PC_DAT", *l++, PC_NBITS);
|
||||
binary ("PD_DAT", *r++, PD_NBITS);
|
||||
#if defined(CONFIG_8xx)
|
||||
binary ("PC_INT", *l++, PC_NBITS);
|
||||
#endif
|
||||
|
||||
header ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set the io pins
|
||||
* this needs a clean up for smaller tighter code
|
||||
* use *uint and set the address based on cmd + port
|
||||
*/
|
||||
int
|
||||
do_iopset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
uint rcode = 0;
|
||||
iopin_t iopin;
|
||||
static uint port = 0;
|
||||
static uint pin = 0;
|
||||
static uint value = 0;
|
||||
static enum {
|
||||
DIR,
|
||||
PAR,
|
||||
SOR,
|
||||
ODR,
|
||||
DAT,
|
||||
#if defined(CONFIG_8xx)
|
||||
INT
|
||||
#endif
|
||||
} cmd = DAT;
|
||||
|
||||
if (argc != 5) {
|
||||
puts ("iopset PORT PIN CMD VALUE\n");
|
||||
return 1;
|
||||
}
|
||||
port = argv[1][0] - 'A';
|
||||
if (port > 3)
|
||||
port -= 0x20;
|
||||
if (port > 3)
|
||||
rcode = 1;
|
||||
pin = simple_strtol (argv[2], NULL, 10);
|
||||
if (pin > 31)
|
||||
rcode = 1;
|
||||
|
||||
|
||||
switch (argv[3][0]) {
|
||||
case 'd':
|
||||
if (argv[3][1] == 'a')
|
||||
cmd = DAT;
|
||||
else if (argv[3][1] == 'i')
|
||||
cmd = DIR;
|
||||
else
|
||||
rcode = 1;
|
||||
break;
|
||||
case 'p':
|
||||
cmd = PAR;
|
||||
break;
|
||||
case 'o':
|
||||
cmd = ODR;
|
||||
break;
|
||||
case 's':
|
||||
cmd = SOR;
|
||||
break;
|
||||
#if defined(CONFIG_8xx)
|
||||
case 'i':
|
||||
cmd = INT;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf ("iopset: unknown command %s\n", argv[3]);
|
||||
rcode = 1;
|
||||
}
|
||||
if (argv[4][0] == '1')
|
||||
value = 1;
|
||||
else if (argv[4][0] == '0')
|
||||
value = 0;
|
||||
else
|
||||
rcode = 1;
|
||||
if (rcode == 0) {
|
||||
iopin.port = port;
|
||||
iopin.pin = pin;
|
||||
iopin.flag = 0;
|
||||
switch (cmd) {
|
||||
case DIR:
|
||||
if (value)
|
||||
iopin_set_out (&iopin);
|
||||
else
|
||||
iopin_set_in (&iopin);
|
||||
break;
|
||||
case PAR:
|
||||
if (value)
|
||||
iopin_set_ded (&iopin);
|
||||
else
|
||||
iopin_set_gen (&iopin);
|
||||
break;
|
||||
case SOR:
|
||||
if (value)
|
||||
iopin_set_opt2 (&iopin);
|
||||
else
|
||||
iopin_set_opt1 (&iopin);
|
||||
break;
|
||||
case ODR:
|
||||
if (value)
|
||||
iopin_set_odr (&iopin);
|
||||
else
|
||||
iopin_set_act (&iopin);
|
||||
break;
|
||||
case DAT:
|
||||
if (value)
|
||||
iopin_set_high (&iopin);
|
||||
else
|
||||
iopin_set_low (&iopin);
|
||||
break;
|
||||
#if defined(CONFIG_8xx)
|
||||
case INT:
|
||||
if (value)
|
||||
iopin_set_falledge (&iopin);
|
||||
else
|
||||
iopin_set_anyedge (&iopin);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
int
|
||||
do_dmainfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_fccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void prbrg (int n, uint val)
|
||||
{
|
||||
uint extc = (val >> 14) & 3;
|
||||
uint cd = (val & CPM_BRG_CD_MASK) >> 1;
|
||||
uint div16 = (val & CPM_BRG_DIV16) != 0;
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
ulong clock = gd->cpu_clk;
|
||||
#elif defined(CONFIG_8260)
|
||||
ulong clock = gd->brg_clk;
|
||||
#endif
|
||||
|
||||
printf ("BRG%d:", n);
|
||||
|
||||
if (val & CPM_BRG_RST)
|
||||
puts (" RESET");
|
||||
else
|
||||
puts (" ");
|
||||
|
||||
if (val & CPM_BRG_EN)
|
||||
puts (" ENABLED");
|
||||
else
|
||||
puts (" DISABLED");
|
||||
|
||||
printf (" EXTC=%d", extc);
|
||||
|
||||
if (val & CPM_BRG_ATB)
|
||||
puts (" ATB");
|
||||
else
|
||||
puts (" ");
|
||||
|
||||
printf (" DIVIDER=%4d", cd);
|
||||
if (extc == 0 && cd != 0) {
|
||||
uint baudrate;
|
||||
|
||||
if (div16)
|
||||
baudrate = (clock / 16) / (cd + 1);
|
||||
else
|
||||
baudrate = clock / (cd + 1);
|
||||
|
||||
printf ("=%6d bps", baudrate);
|
||||
} else {
|
||||
puts (" ");
|
||||
}
|
||||
|
||||
if (val & CPM_BRG_DIV16)
|
||||
puts (" DIV16");
|
||||
else
|
||||
puts (" ");
|
||||
|
||||
putc ('\n');
|
||||
}
|
||||
|
||||
int
|
||||
do_brginfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
volatile cpm8xx_t *cp = &immap->im_cpm;
|
||||
volatile uint *p = &cp->cp_brgc1;
|
||||
#elif defined(CONFIG_8260)
|
||||
volatile uint *p = &immap->im_brgc1;
|
||||
#endif
|
||||
int i = 1;
|
||||
|
||||
while (i <= 4)
|
||||
prbrg (i++, *p++);
|
||||
|
||||
#if defined(CONFIG_8260)
|
||||
p = &immap->im_brgc5;
|
||||
while (i <= 8)
|
||||
prbrg (i++, *p++);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_i2cinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
volatile immap_t *immap = (immap_t *) CFG_IMMR;
|
||||
|
||||
#if defined(CONFIG_8xx)
|
||||
volatile i2c8xx_t *i2c = &immap->im_i2c;
|
||||
volatile cpm8xx_t *cp = &immap->im_cpm;
|
||||
volatile iic_t *iip = (iic_t *) & cp->cp_dparam[PROFF_IIC];
|
||||
#elif defined(CONFIG_8260)
|
||||
volatile i2c8260_t *i2c = &immap->im_i2c;
|
||||
volatile iic_t *iip;
|
||||
uint dpaddr;
|
||||
|
||||
dpaddr = *((unsigned short *) (&immap->im_dprambase[PROFF_I2C_BASE]));
|
||||
if (dpaddr == 0)
|
||||
iip = NULL;
|
||||
else
|
||||
iip = (iic_t *) & immap->im_dprambase[dpaddr];
|
||||
#endif
|
||||
|
||||
printf ("I2MOD = %02x I2ADD = %02x\n", i2c->i2c_i2mod, i2c->i2c_i2add);
|
||||
printf ("I2BRG = %02x I2COM = %02x\n", i2c->i2c_i2brg, i2c->i2c_i2com);
|
||||
printf ("I2CER = %02x I2CMR = %02x\n", i2c->i2c_i2cer, i2c->i2c_i2cmr);
|
||||
|
||||
if (iip == NULL)
|
||||
puts ("i2c parameter ram not allocated\n");
|
||||
else {
|
||||
printf ("RBASE = %08x TBASE = %08x\n",
|
||||
iip->iic_rbase, iip->iic_tbase);
|
||||
printf ("RFCR = %02x TFCR = %02x\n",
|
||||
iip->iic_rfcr, iip->iic_tfcr);
|
||||
printf ("MRBLR = %04x\n", iip->iic_mrblr);
|
||||
printf ("RSTATE= %08x RDP = %08x\n",
|
||||
iip->iic_rstate, iip->iic_rdp);
|
||||
printf ("RBPTR = %04x RBC = %04x\n",
|
||||
iip->iic_rbptr, iip->iic_rbc);
|
||||
printf ("RXTMP = %08x\n", iip->iic_rxtmp);
|
||||
printf ("TSTATE= %08x TDP = %08x\n",
|
||||
iip->iic_tstate, iip->iic_tdp);
|
||||
printf ("TBPTR = %04x TBC = %04x\n",
|
||||
iip->iic_tbptr, iip->iic_tbc);
|
||||
printf ("TXTMP = %08x\n", iip->iic_txtmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_sccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_smcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_spiinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_muxinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_siinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
do_mccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
unimplemented (cmdtp, flag, argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
siuinfo, 1, 1, do_siuinfo,
|
||||
"siuinfo - print System Interface Unit (SIU) registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
memcinfo, 1, 1, do_memcinfo,
|
||||
"memcinfo- print Memory Controller registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
sitinfo, 1, 1, do_sitinfo,
|
||||
"sitinfo - print System Integration Timers (SIT) registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
#ifdef CONFIG_8260
|
||||
U_BOOT_CMD(
|
||||
icinfo, 1, 1, do_icinfo,
|
||||
"icinfo - print Interrupt Controller registers\n",
|
||||
NULL
|
||||
);
|
||||
#endif
|
||||
|
||||
U_BOOT_CMD(
|
||||
carinfo, 1, 1, do_carinfo,
|
||||
"carinfo - print Clocks and Reset registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
iopinfo, 1, 1, do_iopinfo,
|
||||
"iopinfo - print I/O Port registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
iopset, 5, 0, do_iopset,
|
||||
"iopset - set I/O Port registers\n",
|
||||
"PORT PIN CMD VALUE\nPORT: A-D, PIN: 0-31, CMD: [dat|dir|odr|sor], VALUE: 0|1"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
dmainfo, 1, 1, do_dmainfo,
|
||||
"dmainfo - print SDMA/IDMA registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
fccinfo, 1, 1, do_fccinfo,
|
||||
"fccinfo - print FCC registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
brginfo, 1, 1, do_brginfo,
|
||||
"brginfo - print Baud Rate Generator (BRG) registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
i2cinfo, 1, 1, do_i2cinfo,
|
||||
"i2cinfo - print I2C registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
sccinfo, 1, 1, do_sccinfo,
|
||||
"sccinfo - print SCC registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
smcinfo, 1, 1, do_smcinfo,
|
||||
"smcinfo - print SMC registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
spiinfo, 1, 1, do_spiinfo,
|
||||
"spiinfo - print Serial Peripheral Interface (SPI) registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
muxinfo, 1, 1, do_muxinfo,
|
||||
"muxinfo - print CPM Multiplexing registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
siinfo, 1, 1, do_siinfo,
|
||||
"siinfo - print Serial Interface (SI) registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
mccinfo, 1, 1, do_mccinfo,
|
||||
"mccinfo - print MCC registers\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
|
||||
#endif /* CFG_CMD_IMMAP && (CONFIG_8xx || CONFIG_8260) */
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Tait Electronics Limited, Christchurch, New Zealand
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file provides a shell like 'test' function to return
|
||||
* true/false from an integer or string compare of two memory
|
||||
* locations or a location and a scalar/literal.
|
||||
* A few parts were lifted from bash 'test' command
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ITEST)
|
||||
|
||||
#define EQ 0
|
||||
#define NE 1
|
||||
#define LT 2
|
||||
#define GT 3
|
||||
#define LE 4
|
||||
#define GE 5
|
||||
|
||||
struct op_tbl_s {
|
||||
char *op; /* operator string */
|
||||
int opcode; /* internal representation of opcode */
|
||||
};
|
||||
|
||||
typedef struct op_tbl_s op_tbl_t;
|
||||
|
||||
op_tbl_t op_table [] = {
|
||||
{ "-lt", LT },
|
||||
{ "<" , LT },
|
||||
{ "-gt", GT },
|
||||
{ ">" , GT },
|
||||
{ "-eq", EQ },
|
||||
{ "==" , EQ },
|
||||
{ "-ne", NE },
|
||||
{ "!=" , NE },
|
||||
{ "<>" , NE },
|
||||
{ "-ge", GE },
|
||||
{ ">=" , GE },
|
||||
{ "-le", LE },
|
||||
{ "<=" , LE },
|
||||
};
|
||||
|
||||
#define op_tbl_size (sizeof(op_table)/sizeof(op_table[0]))
|
||||
|
||||
extern int cmd_get_data_size(char* arg, int default_size);
|
||||
|
||||
static long evalexp(char *s, int w)
|
||||
{
|
||||
long l, *p;
|
||||
|
||||
/* if the parameter starts with a * then assume is a pointer to the value we want */
|
||||
if (s[0] == '*') {
|
||||
p = (long *)simple_strtoul(&s[1], NULL, 16);
|
||||
l = *p;
|
||||
} else {
|
||||
l = simple_strtoul(s, NULL, 16);
|
||||
}
|
||||
|
||||
return (l & ((1 << (w * 8)) - 1));
|
||||
}
|
||||
|
||||
static char * evalstr(char *s)
|
||||
{
|
||||
/* if the parameter starts with a * then assume a string pointer else its a literal */
|
||||
if (s[0] == '*') {
|
||||
return (char *)simple_strtoul(&s[1], NULL, 16);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
static int stringcomp(char *s, char *t, int op)
|
||||
{
|
||||
int n, p;
|
||||
char *l, *r;
|
||||
|
||||
l = evalstr(s);
|
||||
r = evalstr(t);
|
||||
|
||||
/* we'll do a compare based on the length of the shortest string */
|
||||
n = min(strlen(l), strlen(r));
|
||||
|
||||
p = strncmp(l, r, n);
|
||||
switch (op) {
|
||||
case EQ: return (p == 0);
|
||||
case NE: return (p != 0);
|
||||
case LT: return (p < 0);
|
||||
case GT: return (p > 0);
|
||||
case LE: return (p <= 0);
|
||||
case GE: return (p >= 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int arithcomp (char *s, char *t, int op, int w)
|
||||
{
|
||||
long l, r;
|
||||
|
||||
l = evalexp (s, w);
|
||||
r = evalexp (t, w);
|
||||
|
||||
switch (op) {
|
||||
case EQ: return (l == r);
|
||||
case NE: return (l != r);
|
||||
case LT: return (l < r);
|
||||
case GT: return (l > r);
|
||||
case LE: return (l <= r);
|
||||
case GE: return (l >= r);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int binary_test (char *op, char *arg1, char *arg2, int w)
|
||||
{
|
||||
int len, i;
|
||||
op_tbl_t *optp;
|
||||
|
||||
len = strlen(op);
|
||||
|
||||
for (optp = (op_tbl_t *)&op_table, i = 0;
|
||||
i < op_tbl_size;
|
||||
optp++, i++) {
|
||||
|
||||
if ((strncmp (op, optp->op, len) == 0) && (len == strlen (optp->op))) {
|
||||
if (w == 0) {
|
||||
return (stringcomp(arg1, arg2, optp->opcode));
|
||||
} else {
|
||||
return (arithcomp (arg1, arg2, optp->opcode, w));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Unknown operator '%s'\n", op);
|
||||
return 0; /* op code not found */
|
||||
}
|
||||
|
||||
/* command line interface to the shell test */
|
||||
int do_itest ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
|
||||
{
|
||||
int value, w;
|
||||
|
||||
/* Validate arguments */
|
||||
if ((argc != 4)){
|
||||
printf("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check for a data width specification.
|
||||
* Defaults to long (4) if no specification.
|
||||
* Uses -2 as 'width' for .s (string) so as not to upset existing code
|
||||
*/
|
||||
switch (w = cmd_get_data_size(argv[0], 4)) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
value = binary_test (argv[2], argv[1], argv[3], w);
|
||||
break;
|
||||
case -2:
|
||||
value = binary_test (argv[2], argv[1], argv[3], 0);
|
||||
break;
|
||||
case -1:
|
||||
default:
|
||||
puts("Invalid data width specifier\n");
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return !value;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
itest, 4, 0, do_itest,
|
||||
"itest\t- return true/false on integer compare\n",
|
||||
"[.b, .w, .l, .s] [*]value1 <op> [*]value2\n"
|
||||
);
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_ITEST */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Detlev Zundel, DENX Software Engineering, dzu@denx.de.
|
||||
*
|
||||
* Code used from linux/kernel/printk.c
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Comments:
|
||||
*
|
||||
* After relocating the code, the environment variable "loglevel" is
|
||||
* copied to console_loglevel. The functionality is similar to the
|
||||
* handling in the Linux kernel, i.e. messages logged with a priority
|
||||
* less than console_loglevel are also output to stdout.
|
||||
*
|
||||
* If you want messages with the default level (e.g. POST messages) to
|
||||
* appear on stdout also, make sure the environment variable
|
||||
* "loglevel" is set at boot time to a number higher than
|
||||
* default_message_loglevel below.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Logbuffer handling routines
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <devices.h>
|
||||
#include <post.h>
|
||||
#include <logbuff.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if defined(CONFIG_LOGBUFFER)
|
||||
|
||||
/* Local prototypes */
|
||||
static void logbuff_putc (const char c);
|
||||
static void logbuff_puts (const char *s);
|
||||
static int logbuff_printk(const char *line);
|
||||
|
||||
static char buf[1024];
|
||||
|
||||
/* This combination will not print messages with the default loglevel */
|
||||
static unsigned console_loglevel = 3;
|
||||
static unsigned default_message_loglevel = 4;
|
||||
static unsigned char *log_buf = NULL;
|
||||
static unsigned long *ext_log_size;
|
||||
static unsigned long *ext_log_start;
|
||||
static unsigned long *ext_logged_chars;
|
||||
#define log_size (*ext_log_size)
|
||||
#define log_start (*ext_log_start)
|
||||
#define logged_chars (*ext_logged_chars)
|
||||
|
||||
/* Forced by code, eh! */
|
||||
#define LOGBUFF_MAGIC 0xc0de4ced
|
||||
|
||||
/* The mapping used here has to be the same as in setup_ext_logbuff ()
|
||||
in linux/kernel/printk */
|
||||
void logbuff_init_ptrs (void)
|
||||
{
|
||||
unsigned long *ext_tag;
|
||||
unsigned long post_word;
|
||||
char *s;
|
||||
|
||||
log_buf = (unsigned char *)(gd->bd->bi_memsize-LOGBUFF_LEN);
|
||||
ext_tag = (unsigned long *)(log_buf)-4;
|
||||
ext_log_start = (unsigned long *)(log_buf)-3;
|
||||
ext_log_size = (unsigned long *)(log_buf)-2;
|
||||
ext_logged_chars = (unsigned long *)(log_buf)-1;
|
||||
post_word = post_word_load();
|
||||
#ifdef CONFIG_POST
|
||||
/* The post routines have setup the word so we can simply test it */
|
||||
if (post_word_load () & POST_COLDBOOT) {
|
||||
logged_chars = log_size = log_start = 0;
|
||||
*ext_tag = LOGBUFF_MAGIC;
|
||||
}
|
||||
#else
|
||||
/* No post routines, so we do our own checking */
|
||||
if (post_word != LOGBUFF_MAGIC) {
|
||||
logged_chars = log_size = log_start = 0;
|
||||
post_word_store (LOGBUFF_MAGIC);
|
||||
*ext_tag = LOGBUFF_MAGIC;
|
||||
}
|
||||
#endif
|
||||
/* Initialize default loglevel if present */
|
||||
if ((s = getenv ("loglevel")) != NULL)
|
||||
console_loglevel = (int)simple_strtoul (s, NULL, 10);
|
||||
|
||||
gd->post_log_word |= LOGBUFF_INITIALIZED;
|
||||
}
|
||||
|
||||
int drv_logbuff_init (void)
|
||||
{
|
||||
device_t logdev;
|
||||
int rc;
|
||||
|
||||
/* Device initialization */
|
||||
memset (&logdev, 0, sizeof (logdev));
|
||||
|
||||
strcpy (logdev.name, "logbuff");
|
||||
logdev.ext = 0; /* No extensions */
|
||||
logdev.flags = DEV_FLAGS_OUTPUT; /* Output only */
|
||||
logdev.putc = logbuff_putc; /* 'putc' function */
|
||||
logdev.puts = logbuff_puts; /* 'puts' function */
|
||||
|
||||
rc = device_register (&logdev);
|
||||
|
||||
return (rc == 0) ? 1 : rc;
|
||||
}
|
||||
|
||||
static void logbuff_putc (const char c)
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = '\0';
|
||||
logbuff_printk (buf);
|
||||
}
|
||||
|
||||
static void logbuff_puts (const char *s)
|
||||
{
|
||||
logbuff_printk (s);
|
||||
}
|
||||
|
||||
void logbuff_log(char *msg)
|
||||
{
|
||||
if ((gd->post_log_word & LOGBUFF_INITIALIZED)) {
|
||||
logbuff_printk (msg);
|
||||
} else {
|
||||
/* Can happen only for pre-relocated errors as logging */
|
||||
/* at that stage should be disabled */
|
||||
puts (msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Subroutine: do_log
|
||||
*
|
||||
* Description: Handler for 'log' command..
|
||||
*
|
||||
* Inputs: argv[1] contains the subcommand
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
int do_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *s;
|
||||
unsigned long i;
|
||||
|
||||
if (strcmp(argv[1],"append") == 0) {
|
||||
/* Log concatenation of all arguments separated by spaces */
|
||||
for (i=2; i<argc; i++) {
|
||||
logbuff_printk (argv[i]);
|
||||
logbuff_putc ((i<argc-1) ? ' ' : '\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (argc) {
|
||||
|
||||
case 2:
|
||||
if (strcmp(argv[1],"show") == 0) {
|
||||
for (i=0; i < (log_size&LOGBUFF_MASK); i++) {
|
||||
s = (char *)log_buf+((log_start+i)&LOGBUFF_MASK);
|
||||
putc (*s);
|
||||
}
|
||||
return 0;
|
||||
} else if (strcmp(argv[1],"reset") == 0) {
|
||||
log_start = 0;
|
||||
log_size = 0;
|
||||
logged_chars = 0;
|
||||
return 0;
|
||||
} else if (strcmp(argv[1],"info") == 0) {
|
||||
printf ("Logbuffer at %08lx\n", (unsigned long)log_buf);
|
||||
printf ("log_start = %08lx\n", log_start);
|
||||
printf ("log_size = %08lx\n", log_size);
|
||||
printf ("logged_chars = %08lx\n", logged_chars);
|
||||
return 0;
|
||||
}
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#if defined(CONFIG_LOGBUFFER)
|
||||
U_BOOT_CMD(
|
||||
log, 255, 1, do_log,
|
||||
"log - manipulate logbuffer\n",
|
||||
"info - show pointer details\n"
|
||||
"log reset - clear contents\n"
|
||||
"log show - show contents\n"
|
||||
"log append <msg> - append <msg> to the logbuffer\n"
|
||||
);
|
||||
#endif /* CONFIG_LOGBUFFER */
|
||||
static int logbuff_printk(const char *line)
|
||||
{
|
||||
int i;
|
||||
char *msg, *p, *buf_end;
|
||||
int line_feed;
|
||||
static signed char msg_level = -1;
|
||||
|
||||
strcpy (buf + 3, line);
|
||||
i = strlen (line);
|
||||
buf_end = buf + 3 + i;
|
||||
for (p = buf + 3; p < buf_end; p++) {
|
||||
msg = p;
|
||||
if (msg_level < 0) {
|
||||
if (
|
||||
p[0] != '<' ||
|
||||
p[1] < '0' ||
|
||||
p[1] > '7' ||
|
||||
p[2] != '>'
|
||||
) {
|
||||
p -= 3;
|
||||
p[0] = '<';
|
||||
p[1] = default_message_loglevel + '0';
|
||||
p[2] = '>';
|
||||
} else
|
||||
msg += 3;
|
||||
msg_level = p[1] - '0';
|
||||
}
|
||||
line_feed = 0;
|
||||
for (; p < buf_end; p++) {
|
||||
log_buf[(log_start+log_size) & LOGBUFF_MASK] = *p;
|
||||
if (log_size < LOGBUFF_LEN)
|
||||
log_size++;
|
||||
else
|
||||
log_start++;
|
||||
|
||||
logged_chars++;
|
||||
if (*p == '\n') {
|
||||
line_feed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (msg_level < console_loglevel) {
|
||||
printf("%s", msg);
|
||||
}
|
||||
if (line_feed)
|
||||
msg_level = -1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif /* (CONFIG_LOGBUFFER) */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* MII Utilities
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#ifdef CONFIG_ATH_NAND_BR
|
||||
#include <nand.h>
|
||||
#endif
|
||||
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||
#include <miiphy.h>
|
||||
|
||||
#ifdef CONFIG_TERSE_MII
|
||||
/*
|
||||
* Display values from last command.
|
||||
*/
|
||||
uint last_op;
|
||||
uint last_addr;
|
||||
uint last_data;
|
||||
uint last_reg;
|
||||
|
||||
/*
|
||||
* MII device/info/read/write
|
||||
*
|
||||
* Syntax:
|
||||
* mii device {devname}
|
||||
* mii info {addr}
|
||||
* mii read {addr} {reg}
|
||||
* mii write {addr} {reg} {data}
|
||||
*/
|
||||
int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char op;
|
||||
unsigned char addr, reg;
|
||||
unsigned short data;
|
||||
int rcode = 0;
|
||||
char *devname;
|
||||
|
||||
#if defined(CONFIG_8xx) || defined(CONFIG_MCF52x2)
|
||||
mii_init ();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use the last specified parameters, unless new ones are
|
||||
* entered.
|
||||
*/
|
||||
op = last_op;
|
||||
addr = last_addr;
|
||||
data = last_data;
|
||||
reg = last_reg;
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0) {
|
||||
op = argv[1][0];
|
||||
if (argc >= 3)
|
||||
addr = simple_strtoul (argv[2], NULL, 16);
|
||||
if (argc >= 4)
|
||||
reg = simple_strtoul (argv[3], NULL, 16);
|
||||
if (argc >= 5)
|
||||
data = simple_strtoul (argv[4], NULL, 16);
|
||||
}
|
||||
|
||||
/* use current device */
|
||||
devname = miiphy_get_current_dev();
|
||||
|
||||
/*
|
||||
* check device/read/write/list.
|
||||
*/
|
||||
if (op == 'i') {
|
||||
unsigned char j, start, end;
|
||||
unsigned int oui;
|
||||
unsigned char model;
|
||||
unsigned char rev;
|
||||
|
||||
/*
|
||||
* Look for any and all PHYs. Valid addresses are 0..31.
|
||||
*/
|
||||
if (argc >= 3) {
|
||||
start = addr; end = addr + 1;
|
||||
} else {
|
||||
start = 0; end = 31;
|
||||
}
|
||||
|
||||
for (j = start; j < end; j++) {
|
||||
if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {
|
||||
printf ("PHY 0x%02X: "
|
||||
"OUI = 0x%04X, "
|
||||
"Model = 0x%02X, "
|
||||
"Rev = 0x%02X, "
|
||||
"%3dbaseT, %s\n",
|
||||
j, oui, model, rev,
|
||||
miiphy_speed (devname, j),
|
||||
(miiphy_duplex (devname, j) == FULL)
|
||||
? "FDX" : "HDX");
|
||||
} else {
|
||||
puts ("Error reading info from the PHY\n");
|
||||
}
|
||||
}
|
||||
} else if (op == 'r') {
|
||||
if (miiphy_read (devname, addr, reg, &data) != 0) {
|
||||
puts ("Error reading from the PHY\n");
|
||||
rcode = 1;
|
||||
} else {
|
||||
printf ("%04X\n", data & 0x0000FFFF);
|
||||
}
|
||||
} else if (op == 'w') {
|
||||
if (miiphy_write (devname, addr, reg, data) != 0) {
|
||||
puts ("Error writing to the PHY\n");
|
||||
rcode = 1;
|
||||
}
|
||||
} else if (op == 'd') {
|
||||
if (argc == 2)
|
||||
miiphy_listdev ();
|
||||
else
|
||||
miiphy_set_current_dev (argv[2]);
|
||||
} else {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the parameters for repeats.
|
||||
*/
|
||||
last_op = op;
|
||||
last_addr = addr;
|
||||
last_data = data;
|
||||
last_reg = reg;
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
mii, 5, 1, do_mii,
|
||||
"mii - MII utility commands\n",
|
||||
"device - list available devices\n"
|
||||
"mii device <devname> - set current device\n"
|
||||
"mii info <addr> - display MII PHY info\n"
|
||||
"mii read <addr> <reg> - read MII PHY <addr> register <reg>\n"
|
||||
"mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
|
||||
);
|
||||
|
||||
#else /* ! CONFIG_TERSE_MII ================================================= */
|
||||
|
||||
typedef struct _MII_reg_desc_t {
|
||||
ushort regno;
|
||||
char * name;
|
||||
} MII_reg_desc_t;
|
||||
|
||||
MII_reg_desc_t reg_0_5_desc_tbl[] = {
|
||||
{ 0, "PHY control register" },
|
||||
{ 1, "PHY status register" },
|
||||
{ 2, "PHY ID 1 register" },
|
||||
{ 3, "PHY ID 2 register" },
|
||||
{ 4, "Autonegotiation advertisement register" },
|
||||
{ 5, "Autonegotiation partner abilities register" },
|
||||
};
|
||||
|
||||
typedef struct _MII_field_desc_t {
|
||||
ushort hi;
|
||||
ushort lo;
|
||||
ushort mask;
|
||||
char * name;
|
||||
} MII_field_desc_t;
|
||||
|
||||
MII_field_desc_t reg_0_desc_tbl[] = {
|
||||
{ 15, 15, 0x01, "reset" },
|
||||
{ 14, 14, 0x01, "loopback" },
|
||||
{ 13, 6, 0x81, "speed selection" }, /* special */
|
||||
{ 12, 12, 0x01, "A/N enable" },
|
||||
{ 11, 11, 0x01, "power-down" },
|
||||
{ 10, 10, 0x01, "isolate" },
|
||||
{ 9, 9, 0x01, "restart A/N" },
|
||||
{ 8, 8, 0x01, "duplex" }, /* special */
|
||||
{ 7, 7, 0x01, "collision test enable" },
|
||||
{ 5, 0, 0x3f, "(reserved)" }
|
||||
};
|
||||
|
||||
MII_field_desc_t reg_1_desc_tbl[] = {
|
||||
{ 15, 15, 0x01, "100BASE-T4 able" },
|
||||
{ 14, 14, 0x01, "100BASE-X full duplex able" },
|
||||
{ 13, 13, 0x01, "100BASE-X half duplex able" },
|
||||
{ 12, 12, 0x01, "10 Mbps full duplex able" },
|
||||
{ 11, 11, 0x01, "10 Mbps half duplex able" },
|
||||
{ 10, 10, 0x01, "100BASE-T2 full duplex able" },
|
||||
{ 9, 9, 0x01, "100BASE-T2 half duplex able" },
|
||||
{ 8, 8, 0x01, "extended status" },
|
||||
{ 7, 7, 0x01, "(reserved)" },
|
||||
{ 6, 6, 0x01, "MF preamble suppression" },
|
||||
{ 5, 5, 0x01, "A/N complete" },
|
||||
{ 4, 4, 0x01, "remote fault" },
|
||||
{ 3, 3, 0x01, "A/N able" },
|
||||
{ 2, 2, 0x01, "link status" },
|
||||
{ 1, 1, 0x01, "jabber detect" },
|
||||
{ 0, 0, 0x01, "extended capabilities" },
|
||||
};
|
||||
|
||||
MII_field_desc_t reg_2_desc_tbl[] = {
|
||||
{ 15, 0, 0xffff, "OUI portion" },
|
||||
};
|
||||
|
||||
MII_field_desc_t reg_3_desc_tbl[] = {
|
||||
{ 15, 10, 0x3f, "OUI portion" },
|
||||
{ 9, 4, 0x3f, "manufacturer part number" },
|
||||
{ 3, 0, 0x0f, "manufacturer rev. number" },
|
||||
};
|
||||
|
||||
MII_field_desc_t reg_4_desc_tbl[] = {
|
||||
{ 15, 15, 0x01, "next page able" },
|
||||
{ 14, 14, 0x01, "reserved" },
|
||||
{ 13, 13, 0x01, "remote fault" },
|
||||
{ 12, 12, 0x01, "reserved" },
|
||||
{ 11, 11, 0x01, "asymmetric pause" },
|
||||
{ 10, 10, 0x01, "pause enable" },
|
||||
{ 9, 9, 0x01, "100BASE-T4 able" },
|
||||
{ 8, 8, 0x01, "100BASE-TX full duplex able" },
|
||||
{ 7, 7, 0x01, "100BASE-TX able" },
|
||||
{ 6, 6, 0x01, "10BASE-T full duplex able" },
|
||||
{ 5, 5, 0x01, "10BASE-T able" },
|
||||
{ 4, 0, 0x1f, "xxx to do" },
|
||||
};
|
||||
|
||||
MII_field_desc_t reg_5_desc_tbl[] = {
|
||||
{ 15, 15, 0x01, "next page able" },
|
||||
{ 14, 14, 0x01, "acknowledge" },
|
||||
{ 13, 13, 0x01, "remote fault" },
|
||||
{ 12, 12, 0x01, "(reserved)" },
|
||||
{ 11, 11, 0x01, "asymmetric pause able" },
|
||||
{ 10, 10, 0x01, "pause able" },
|
||||
{ 9, 9, 0x01, "100BASE-T4 able" },
|
||||
{ 8, 8, 0x01, "100BASE-X full duplex able" },
|
||||
{ 7, 7, 0x01, "100BASE-TX able" },
|
||||
{ 6, 6, 0x01, "10BASE-T full duplex able" },
|
||||
{ 5, 5, 0x01, "10BASE-T able" },
|
||||
{ 4, 0, 0x1f, "xxx to do" },
|
||||
};
|
||||
|
||||
#define DESC0LEN (sizeof(reg_0_desc_tbl)/sizeof(reg_0_desc_tbl[0]))
|
||||
#define DESC1LEN (sizeof(reg_1_desc_tbl)/sizeof(reg_1_desc_tbl[0]))
|
||||
#define DESC2LEN (sizeof(reg_2_desc_tbl)/sizeof(reg_2_desc_tbl[0]))
|
||||
#define DESC3LEN (sizeof(reg_3_desc_tbl)/sizeof(reg_3_desc_tbl[0]))
|
||||
#define DESC4LEN (sizeof(reg_4_desc_tbl)/sizeof(reg_4_desc_tbl[0]))
|
||||
#define DESC5LEN (sizeof(reg_5_desc_tbl)/sizeof(reg_5_desc_tbl[0]))
|
||||
|
||||
typedef struct _MII_field_desc_and_len_t {
|
||||
MII_field_desc_t * pdesc;
|
||||
ushort len;
|
||||
} MII_field_desc_and_len_t;
|
||||
|
||||
MII_field_desc_and_len_t desc_and_len_tbl[] = {
|
||||
{ reg_0_desc_tbl, DESC0LEN },
|
||||
{ reg_1_desc_tbl, DESC1LEN },
|
||||
{ reg_2_desc_tbl, DESC2LEN },
|
||||
{ reg_3_desc_tbl, DESC3LEN },
|
||||
{ reg_4_desc_tbl, DESC4LEN },
|
||||
{ reg_5_desc_tbl, DESC5LEN },
|
||||
};
|
||||
|
||||
static void dump_reg(
|
||||
ushort regval,
|
||||
MII_reg_desc_t * prd,
|
||||
MII_field_desc_and_len_t * pdl);
|
||||
|
||||
static int special_field(
|
||||
ushort regno,
|
||||
MII_field_desc_t * pdesc,
|
||||
ushort regval);
|
||||
|
||||
void MII_dump_0_to_5(
|
||||
ushort regvals[6],
|
||||
uchar reglo,
|
||||
uchar reghi)
|
||||
{
|
||||
ulong i;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
if ((reglo <= i) && (i <= reghi))
|
||||
dump_reg(regvals[i], ®_0_5_desc_tbl[i],
|
||||
&desc_and_len_tbl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_reg(
|
||||
ushort regval,
|
||||
MII_reg_desc_t * prd,
|
||||
MII_field_desc_and_len_t * pdl)
|
||||
{
|
||||
ulong i;
|
||||
ushort mask_in_place;
|
||||
MII_field_desc_t * pdesc;
|
||||
|
||||
printf("%u. (%04hx) -- %s --\n",
|
||||
prd->regno, regval, prd->name);
|
||||
|
||||
for (i = 0; i < pdl->len; i++) {
|
||||
pdesc = &pdl->pdesc[i];
|
||||
|
||||
mask_in_place = pdesc->mask << pdesc->lo;
|
||||
|
||||
printf(" (%04hx:%04hx) %u.",
|
||||
mask_in_place,
|
||||
regval & mask_in_place,
|
||||
prd->regno);
|
||||
|
||||
if (special_field(prd->regno, pdesc, regval)) {
|
||||
}
|
||||
else {
|
||||
if (pdesc->hi == pdesc->lo)
|
||||
printf("%2u ", pdesc->lo);
|
||||
else
|
||||
printf("%2u-%2u", pdesc->hi, pdesc->lo);
|
||||
printf(" = %5u %s",
|
||||
(regval & mask_in_place) >> pdesc->lo,
|
||||
pdesc->name);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Special fields:
|
||||
** 0.6,13
|
||||
** 0.8
|
||||
** 2.15-0
|
||||
** 3.15-0
|
||||
** 4.4-0
|
||||
** 5.4-0
|
||||
*/
|
||||
|
||||
static int special_field(
|
||||
ushort regno,
|
||||
MII_field_desc_t * pdesc,
|
||||
ushort regval)
|
||||
{
|
||||
if ((regno == 0) && (pdesc->lo == 6)) {
|
||||
ushort speed_bits = regval & PHY_BMCR_SPEED_MASK;
|
||||
printf("%2u,%2u = b%u%u speed selection = %s Mbps",
|
||||
6, 13,
|
||||
(regval >> 6) & 1,
|
||||
(regval >> 13) & 1,
|
||||
speed_bits == PHY_BMCR_1000_MBPS ? "1000" :
|
||||
speed_bits == PHY_BMCR_100_MBPS ? "100" :
|
||||
speed_bits == PHY_BMCR_10_MBPS ? "10" :
|
||||
"???");
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if ((regno == 0) && (pdesc->lo == 8)) {
|
||||
printf("%2u = %5u duplex = %s",
|
||||
pdesc->lo,
|
||||
(regval >> pdesc->lo) & 1,
|
||||
((regval >> pdesc->lo) & 1) ? "full" : "half");
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if ((regno == 4) && (pdesc->lo == 0)) {
|
||||
ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
|
||||
printf("%2u-%2u = %5u selector = %s",
|
||||
pdesc->hi, pdesc->lo, sel_bits,
|
||||
sel_bits == PHY_ANLPAR_PSB_802_3 ?
|
||||
"IEEE 802.3" :
|
||||
sel_bits == PHY_ANLPAR_PSB_802_9 ?
|
||||
"IEEE 802.9 ISLAN-16T" :
|
||||
"???");
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if ((regno == 5) && (pdesc->lo == 0)) {
|
||||
ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
|
||||
printf("%2u-%2u = %u selector = %s",
|
||||
pdesc->hi, pdesc->lo, sel_bits,
|
||||
sel_bits == PHY_ANLPAR_PSB_802_3 ?
|
||||
"IEEE 802.3" :
|
||||
sel_bits == PHY_ANLPAR_PSB_802_9 ?
|
||||
"IEEE 802.9 ISLAN-16T" :
|
||||
"???");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char last_op[2];
|
||||
uint last_data;
|
||||
uint last_addr_lo;
|
||||
uint last_addr_hi;
|
||||
uint last_reg_lo;
|
||||
uint last_reg_hi;
|
||||
|
||||
static void extract_range(
|
||||
char * input,
|
||||
unsigned char * plo,
|
||||
unsigned char * phi)
|
||||
{
|
||||
char * end;
|
||||
*plo = simple_strtoul(input, &end, 16);
|
||||
if (*end == '-') {
|
||||
end++;
|
||||
*phi = simple_strtoul(end, NULL, 16);
|
||||
}
|
||||
else {
|
||||
*phi = *plo;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char op[2];
|
||||
unsigned char addrlo, addrhi, reglo, reghi;
|
||||
unsigned char addr, reg;
|
||||
unsigned short data;
|
||||
int rcode = 0;
|
||||
char *devname;
|
||||
|
||||
#ifdef CONFIG_8xx
|
||||
mii_init ();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We use the last specified parameters, unless new ones are
|
||||
* entered.
|
||||
*/
|
||||
op[0] = last_op[0];
|
||||
op[1] = last_op[1];
|
||||
addrlo = last_addr_lo;
|
||||
addrhi = last_addr_hi;
|
||||
reglo = last_reg_lo;
|
||||
reghi = last_reg_hi;
|
||||
data = last_data;
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0) {
|
||||
op[0] = argv[1][0];
|
||||
if (strlen(argv[1]) > 1)
|
||||
op[1] = argv[1][1];
|
||||
else
|
||||
op[1] = '\0';
|
||||
|
||||
if (argc >= 3)
|
||||
extract_range(argv[2], &addrlo, &addrhi);
|
||||
if (argc >= 4)
|
||||
extract_range(argv[3], ®lo, ®hi);
|
||||
if (argc >= 5)
|
||||
data = simple_strtoul (argv[4], NULL, 16);
|
||||
}
|
||||
|
||||
/* use current device */
|
||||
devname = miiphy_get_current_dev();
|
||||
|
||||
/*
|
||||
* check info/read/write.
|
||||
*/
|
||||
if (op[0] == 'i') {
|
||||
unsigned char j, start, end;
|
||||
unsigned int oui;
|
||||
unsigned char model;
|
||||
unsigned char rev;
|
||||
|
||||
/*
|
||||
* Look for any and all PHYs. Valid addresses are 0..31.
|
||||
*/
|
||||
if (argc >= 3) {
|
||||
start = addrlo; end = addrhi;
|
||||
} else {
|
||||
start = 0; end = 31;
|
||||
}
|
||||
|
||||
for (j = start; j <= end; j++) {
|
||||
if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {
|
||||
printf("PHY 0x%02X: "
|
||||
"OUI = 0x%04X, "
|
||||
"Model = 0x%02X, "
|
||||
"Rev = 0x%02X, "
|
||||
"%3dbaseT, %s\n",
|
||||
j, oui, model, rev,
|
||||
miiphy_speed (devname, j),
|
||||
(miiphy_duplex (devname, j) == FULL)
|
||||
? "FDX" : "HDX");
|
||||
} else {
|
||||
puts ("Error reading info from the PHY\n");
|
||||
}
|
||||
}
|
||||
} else if (op[0] == 'r') {
|
||||
for (addr = addrlo; addr <= addrhi; addr++) {
|
||||
for (reg = reglo; reg <= reghi; reg++) {
|
||||
data = 0xffff;
|
||||
if (miiphy_read (devname, addr, reg, &data) != 0) {
|
||||
printf(
|
||||
"Error reading from the PHY addr=%02x reg=%02x\n",
|
||||
addr, reg);
|
||||
rcode = 1;
|
||||
} else {
|
||||
if ((addrlo != addrhi) || (reglo != reghi))
|
||||
printf("addr=%02x reg=%02x data=",
|
||||
(uint)addr, (uint)reg);
|
||||
printf("%04X\n", data & 0x0000FFFF);
|
||||
}
|
||||
}
|
||||
if ((addrlo != addrhi) && (reglo != reghi))
|
||||
printf("\n");
|
||||
}
|
||||
} else if (op[0] == 'w') {
|
||||
for (addr = addrlo; addr <= addrhi; addr++) {
|
||||
for (reg = reglo; reg <= reghi; reg++) {
|
||||
if (miiphy_write (devname, addr, reg, data) != 0) {
|
||||
printf("Error writing to the PHY addr=%02x reg=%02x\n",
|
||||
addr, reg);
|
||||
rcode = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (strncmp(op, "du", 2) == 0) {
|
||||
ushort regs[6];
|
||||
int ok = 1;
|
||||
if ((reglo > 5) || (reghi > 5)) {
|
||||
printf(
|
||||
"The MII dump command only formats the "
|
||||
"standard MII registers, 0-5.\n");
|
||||
return 1;
|
||||
}
|
||||
for (addr = addrlo; addr <= addrhi; addr++) {
|
||||
for (reg = reglo; reg < reghi + 1; reg++) {
|
||||
if (miiphy_read(devname, addr, reg, ®s[reg]) != 0) {
|
||||
ok = 0;
|
||||
printf(
|
||||
"Error reading from the PHY addr=%02x reg=%02x\n",
|
||||
addr, reg);
|
||||
rcode = 1;
|
||||
}
|
||||
}
|
||||
if (ok)
|
||||
MII_dump_0_to_5(regs, reglo, reghi);
|
||||
printf("\n");
|
||||
}
|
||||
} else if (strncmp(op, "de", 2) == 0) {
|
||||
if (argc == 2)
|
||||
miiphy_listdev ();
|
||||
else
|
||||
miiphy_set_current_dev (argv[2]);
|
||||
} else {
|
||||
printf("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the parameters for repeats.
|
||||
*/
|
||||
last_op[0] = op[0];
|
||||
last_op[1] = op[1];
|
||||
last_addr_lo = addrlo;
|
||||
last_addr_hi = addrhi;
|
||||
last_reg_lo = reglo;
|
||||
last_reg_hi = reghi;
|
||||
last_data = data;
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
mii, 5, 1, do_mii,
|
||||
"mii - MII utility commands\n",
|
||||
"device - list available devices\n"
|
||||
"mii device <devname> - set current device\n"
|
||||
"mii info <addr> - display MII PHY info\n"
|
||||
"mii read <addr> <reg> - read MII PHY <addr> register <reg>\n"
|
||||
"mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
|
||||
"mii dump <addr> <reg> - pretty-print <addr> <reg> (0-5 only)\n"
|
||||
"Addr and/or reg may be ranges, e.g. 2-7.\n"
|
||||
);
|
||||
|
||||
#endif /* CONFIG_TERSE_MII */
|
||||
#endif /* CFG_CMD_MII */
|
||||
#endif /* #ifndef COMPRESSED_UBOOT */
|
||||
|
||||
#ifdef BOARDCAL
|
||||
extern flash_info_t flash_info[]; /* info for FLASH chips */
|
||||
|
||||
/**********************************************************************************
|
||||
** do_mac_setting
|
||||
**
|
||||
** This is the executable portion of the progmac command. This will process the
|
||||
** MAC address strings, and program them into the appropriate flash sector..
|
||||
**
|
||||
*/
|
||||
#ifdef CONFIG_ATH_NAND_BR
|
||||
|
||||
#define ATH_NAND_NAND_PART "ath-nand"
|
||||
|
||||
|
||||
unsigned long long
|
||||
ath_nand_get_cal_offset(const char *ba)
|
||||
{
|
||||
char *mtdparts, ch, *pn, *end;
|
||||
unsigned long long off = 0, size;
|
||||
|
||||
mtdparts = strstr(ba, ATH_NAND_NAND_PART);
|
||||
if (!mtdparts) {
|
||||
goto bad;
|
||||
}
|
||||
mtdparts = strstr(mtdparts, ":");
|
||||
if (!mtdparts) {
|
||||
goto bad;
|
||||
}
|
||||
end = strstr(mtdparts, " ");
|
||||
if (!end) {
|
||||
end = mtdparts + strlen(mtdparts);
|
||||
}
|
||||
|
||||
for (;mtdparts && mtdparts < end;) {
|
||||
mtdparts ++;
|
||||
size = simple_strtoul(mtdparts, &mtdparts, 0);
|
||||
ch = *mtdparts;
|
||||
switch (ch) {
|
||||
case 'g': case 'G': size = size * 1024;
|
||||
case 'm': case 'M': size = size * 1024;
|
||||
case 'k': case 'K': size = size * 1024;
|
||||
}
|
||||
pn = mtdparts + 2;
|
||||
if (strncmp(pn, ATH_CAL_NAND_PARTITION,
|
||||
sizeof(ATH_CAL_NAND_PARTITION) - 1) == 0) {
|
||||
return off;
|
||||
}
|
||||
off += size;
|
||||
mtdparts = strstr(mtdparts, ",");
|
||||
}
|
||||
|
||||
bad:
|
||||
return ATH_CAL_OFF_INVAL;
|
||||
}
|
||||
|
||||
/**********************************************************************************
|
||||
** do_mac_setting
|
||||
**
|
||||
** This is the executable portion of the progmac command. This will process the
|
||||
** MAC address strings, and program them into the appropriate flash sector..
|
||||
**
|
||||
*/
|
||||
|
||||
int do_mac (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char sectorBuff[256*1024];
|
||||
int serno;
|
||||
int product_id;
|
||||
int ret;
|
||||
ulong off, size;
|
||||
nand_info_t *nand;
|
||||
|
||||
/*
|
||||
* caldata partition is of 128k
|
||||
*
|
||||
*/
|
||||
nand = &nand_info[nand_curr_device];
|
||||
size = nand->erasesize;
|
||||
/*
|
||||
* Argv[1] contains the value string. Convert to binary, and
|
||||
* program the values in flash
|
||||
*/
|
||||
|
||||
serno = simple_strtoul(argv[1],0,10);
|
||||
|
||||
/*
|
||||
* If the serial number is less than 0, or greater than
|
||||
* 0x1fff, it's out of range
|
||||
*/
|
||||
|
||||
if(serno < 0 || serno > 0x1fff) {
|
||||
printf("Serno out of range\n",serno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
product_id = simple_strtoul(argv[2], 0, 10);
|
||||
} else {
|
||||
product_id = ATHEROS_PRODUCT_ID;
|
||||
}
|
||||
|
||||
if(product_id < 0 || product_id > 0x7ff) {
|
||||
printf("product id out of range %d\n", product_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the 24 bit number that composes the lower 3 bytes of
|
||||
* the MAC address
|
||||
*/
|
||||
|
||||
serno = 0xFFFFFF & ( (product_id << 13) | (serno & 0x1fff));
|
||||
|
||||
/*
|
||||
* Get the Offset of Caldata partition
|
||||
*/
|
||||
off = ath_nand_get_cal_offset(getenv("bootargs"));
|
||||
if(off == ATH_CAL_OFF_INVAL) {
|
||||
printf("Invalid CAL offset \n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the values from flash, and program into the MAC address
|
||||
* registers
|
||||
*/
|
||||
ret = nand_read(nand, (loff_t)off, &size, (u_char *)sectorBuff);
|
||||
printf(" %d bytes %s: %s\n", size,
|
||||
"read", ret ? "ERROR" : "OK");
|
||||
if(ret != 0 ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the first and second values
|
||||
*/
|
||||
|
||||
sectorBuff[0] = 0x00;
|
||||
sectorBuff[1] = 0x03;
|
||||
sectorBuff[2] = 0x7f;
|
||||
|
||||
sectorBuff[3] = 0xFF & (serno >> 16);
|
||||
sectorBuff[4] = 0xFF & (serno >> 8);
|
||||
sectorBuff[5] = 0xFF & serno;
|
||||
|
||||
/*
|
||||
* Increment by 1 for the second MAC address
|
||||
*/
|
||||
|
||||
serno++;
|
||||
memcpy(§orBuff[6],§orBuff[0],3);
|
||||
sectorBuff[9] = 0xFF & (serno >> 16);
|
||||
sectorBuff[10] = 0xFF & (serno >> 8);
|
||||
sectorBuff[11] = 0xFF & serno;
|
||||
|
||||
ret = nand_erase(nand,(loff_t)off, size);
|
||||
printf(" %d bytes %s: %s\n", size,
|
||||
"erase", ret ? "ERROR" : "OK");
|
||||
|
||||
if(ret != 0 ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = nand_write(nand, (loff_t)off, &size, (u_char *)sectorBuff);
|
||||
printf(" %d bytes %s: %s\n", size,
|
||||
"write", ret ? "ERROR" : "OK");
|
||||
if(ret != 0 ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /*CONFIG_ATH_NAND_BR */
|
||||
|
||||
int do_mac (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char sectorBuff[CFG_FLASH_SECTOR_SIZE];
|
||||
int serno;
|
||||
int product_id;
|
||||
|
||||
/*
|
||||
* Argv[1] contains the value string. Convert to binary, and
|
||||
* program the values in flash
|
||||
*/
|
||||
|
||||
serno = simple_strtoul(argv[1],0,10);
|
||||
|
||||
/*
|
||||
* If the serial number is less than 0, or greater than
|
||||
* 0x1fff, it's out of range
|
||||
*/
|
||||
|
||||
if(serno < 0 || serno > 0x1fff) {
|
||||
printf("Serno out of range\n",serno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
product_id = simple_strtoul(argv[2], 0, 10);
|
||||
} else {
|
||||
product_id = ATHEROS_PRODUCT_ID;
|
||||
}
|
||||
|
||||
if(product_id < 0 || product_id > 0x7ff) {
|
||||
printf("product id out of range %d\n", product_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the 24 bit number that composes the lower 3 bytes of
|
||||
* the MAC address
|
||||
*/
|
||||
|
||||
serno = 0xFFFFFF & ( (product_id << 13) | (serno & 0x1fff));
|
||||
|
||||
/*
|
||||
* Get the values from flash, and program into the MAC address
|
||||
* registers
|
||||
*/
|
||||
|
||||
memcpy(sectorBuff,(void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE);
|
||||
|
||||
/*
|
||||
* Set the first and second values
|
||||
*/
|
||||
|
||||
sectorBuff[0] = 0x00;
|
||||
sectorBuff[1] = 0x03;
|
||||
sectorBuff[2] = 0x7f;
|
||||
|
||||
sectorBuff[3] = 0xFF & (serno >> 16);
|
||||
sectorBuff[4] = 0xFF & (serno >> 8);
|
||||
sectorBuff[5] = 0xFF & serno;
|
||||
|
||||
/*
|
||||
* Increment by 1 for the second MAC address
|
||||
*/
|
||||
|
||||
serno++;
|
||||
memcpy(§orBuff[6],§orBuff[0],3);
|
||||
sectorBuff[9] = 0xFF & (serno >> 16);
|
||||
sectorBuff[10] = 0xFF & (serno >> 8);
|
||||
sectorBuff[11] = 0xFF & serno;
|
||||
|
||||
flash_erase(flash_info,CAL_SECTOR,CAL_SECTOR);
|
||||
write_buff(flash_info,sectorBuff, BOARDCAL, CFG_FLASH_SECTOR_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /*CONFIG_ATH_NAND_BR */
|
||||
|
||||
U_BOOT_CMD(
|
||||
progmac, 3, 0, do_mac,
|
||||
"progmac - Set ethernet MAC addresses\n",
|
||||
"progmac <serno> [<product_id>] - Program the MAC addresses\n"
|
||||
" <serno> is the value of the last\n"
|
||||
" 4 digits (decimal) of the serial number.\n"
|
||||
" Optional parameter <product_id> specifies\n"
|
||||
" the board's product ID (decimal)\n"
|
||||
);
|
||||
|
||||
#endif /* BOARDCAL */
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Misc functions
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MISC)
|
||||
|
||||
int do_sleep (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong start = get_timer(0);
|
||||
ulong delay;
|
||||
|
||||
if (argc != 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
delay = simple_strtoul(argv[1], NULL, 10) * CFG_HZ;
|
||||
|
||||
while (get_timer(start) < delay) {
|
||||
if (ctrlc ()) {
|
||||
return (-1);
|
||||
}
|
||||
udelay (100);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Implemented in $(CPU)/interrupts.c */
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
|
||||
int do_irqinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
|
||||
|
||||
U_BOOT_CMD(
|
||||
irqinfo, 1, 1, do_irqinfo,
|
||||
"irqinfo - print information about IRQs\n",
|
||||
NULL
|
||||
);
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */
|
||||
|
||||
U_BOOT_CMD(
|
||||
sleep , 2, 2, do_sleep,
|
||||
"sleep - delay execution for some time\n",
|
||||
"N\n"
|
||||
" - delay execution for N seconds (N is _decimal_ !!!)\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_MISC */
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Kyle Harris, kharris@nexus-tech.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 <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_MMC)
|
||||
|
||||
#include <mmc.h>
|
||||
|
||||
int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
if (mmc_init (1) != 0) {
|
||||
printf ("No MMC card found\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
mmcinit, 1, 0, do_mmc,
|
||||
"mmcinit - init mmc card\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_MMC */
|
|
@ -0,0 +1,773 @@
|
|||
/*
|
||||
* Driver for NAND support, Rick Bronson
|
||||
* borrowed heavily from:
|
||||
* (c) 1999 Machine Vision Holdings, Inc.
|
||||
* (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
|
||||
*
|
||||
* Added 16-bit nand support
|
||||
* (C) 2004 Texas Instruments
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
|
||||
#ifndef CFG_NAND_LEGACY
|
||||
/*
|
||||
*
|
||||
* New NAND support
|
||||
*
|
||||
*/
|
||||
#include <common.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
|
||||
|
||||
#include <command.h>
|
||||
#include <watchdog.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
# include <status_led.h>
|
||||
# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
|
||||
#else
|
||||
# define SHOW_BOOT_PROGRESS(arg)
|
||||
#endif
|
||||
|
||||
#include <jffs2/jffs2.h>
|
||||
#include <nand.h>
|
||||
|
||||
extern nand_info_t nand_info[]; /* info for NAND chips */
|
||||
|
||||
static int nand_raw_dump(nand_info_t *nand, ulong off, int page)
|
||||
{
|
||||
int i;
|
||||
u_char *buf, *p;
|
||||
|
||||
buf = malloc(nand->oobblock + nand->oobsize);
|
||||
if (!buf) {
|
||||
puts("No memory for page buffer\n");
|
||||
return 1;
|
||||
}
|
||||
off &= ~(nand->oobblock - 1);
|
||||
i = nand_read_raw(nand, buf, off, nand->oobblock, nand->oobsize);
|
||||
if (i < 0) {
|
||||
printf("Error (%d) reading page %08x\n", i, off);
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
printf("Page %08x dump:\n", off);
|
||||
i = nand->oobblock >> 4; p = buf;
|
||||
while (i--) {
|
||||
if (page) {
|
||||
printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x"
|
||||
" %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
|
||||
p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
|
||||
}
|
||||
p += 16;
|
||||
}
|
||||
puts("OOB:\n");
|
||||
i = nand->oobsize >> 3;
|
||||
while (i--) {
|
||||
printf( "\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
|
||||
p += 8;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nand_dump_oob(nand_info_t *nand, ulong off)
|
||||
{
|
||||
return nand_raw_dump(nand, off, 0);
|
||||
}
|
||||
|
||||
static int nand_dump(nand_info_t *nand, ulong off)
|
||||
{
|
||||
return nand_raw_dump(nand, off, 1);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize)
|
||||
{
|
||||
*off = 0;
|
||||
*size = 0;
|
||||
|
||||
#if defined(CONFIG_JFFS2_NAND) && defined(CFG_JFFS_CUSTOM_PART)
|
||||
if (argc >= 1 && strcmp(argv[0], "partition") == 0) {
|
||||
int part_num;
|
||||
struct part_info *part;
|
||||
const char *partstr;
|
||||
|
||||
if (argc >= 2)
|
||||
partstr = argv[1];
|
||||
else
|
||||
partstr = getenv("partition");
|
||||
|
||||
if (partstr)
|
||||
part_num = (int)simple_strtoul(partstr, NULL, 10);
|
||||
else
|
||||
part_num = 0;
|
||||
|
||||
part = jffs2_part_info(part_num);
|
||||
if (part == NULL) {
|
||||
printf("\nInvalid partition %d\n", part_num);
|
||||
return;
|
||||
}
|
||||
*size = part->size;
|
||||
*off = (ulong)part->offset;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (argc >= 1)
|
||||
*off = (ulong)simple_strtoul(argv[0], NULL, 16);
|
||||
else
|
||||
*off = 0;
|
||||
|
||||
if (argc >= 2)
|
||||
*size = (ulong)simple_strtoul(argv[1], NULL, 16);
|
||||
else
|
||||
*size = totsize - *off;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i, dev, ret;
|
||||
ulong addr, off, size;
|
||||
char *cmd, *s;
|
||||
nand_info_t *nand;
|
||||
|
||||
/* at least two arguments please */
|
||||
if (argc < 2)
|
||||
goto usage;
|
||||
|
||||
cmd = argv[1];
|
||||
|
||||
if (strcmp(cmd, "info") == 0) {
|
||||
|
||||
putc('\n');
|
||||
for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
|
||||
if (nand_info[i].name)
|
||||
printf("Device %d: %s, sector size %lu KiB\n",
|
||||
i, nand_info[i].name,
|
||||
nand_info[i].erasesize >> 10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "device") == 0) {
|
||||
|
||||
if (argc < 3) {
|
||||
if ((nand_curr_device < 0) ||
|
||||
(nand_curr_device >= CFG_MAX_NAND_DEVICE))
|
||||
puts("\nno devices available\n");
|
||||
else
|
||||
printf("\nDevice %d: %s\n", nand_curr_device,
|
||||
nand_info[nand_curr_device].name);
|
||||
return 0;
|
||||
}
|
||||
dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
|
||||
puts("No such device\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Device %d: %s", dev, nand_info[dev].name);
|
||||
puts("... is now current device\n");
|
||||
nand_curr_device = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
|
||||
strncmp(cmd, "dump", 4) != 0 &&
|
||||
strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0)
|
||||
goto usage;
|
||||
|
||||
/* the following commands operate on the current device */
|
||||
if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
|
||||
!nand_info[nand_curr_device].name) {
|
||||
puts("\nno devices available\n");
|
||||
return 1;
|
||||
}
|
||||
nand = &nand_info[nand_curr_device];
|
||||
|
||||
if (strcmp(cmd, "bad") == 0) {
|
||||
printf("\nDevice %d bad blocks:\n", nand_curr_device);
|
||||
for (off = 0; off < nand->size; off += nand->erasesize)
|
||||
if (nand_block_isbad(nand, off))
|
||||
printf(" %08x\n", off);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "erase") == 0) {
|
||||
arg_off_size(argc - 2, argv + 2, &off, &size, nand->size);
|
||||
if (off == 0 && size == 0)
|
||||
return 1;
|
||||
|
||||
printf("\nNAND erase: device %d offset 0x%x, size 0x%x ",
|
||||
nand_curr_device, off, size);
|
||||
ret = nand_erase(nand, off, size);
|
||||
printf("\n%s\n", ret ? "ERROR" : "OK");
|
||||
|
||||
return ret == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, "dump", 4) == 0) {
|
||||
if (argc < 3)
|
||||
goto usage;
|
||||
|
||||
s = strchr(cmd, '.');
|
||||
off = (int)simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
if (s != NULL && strcmp(s, ".oob") == 0)
|
||||
ret = nand_dump_oob(nand, off);
|
||||
else
|
||||
ret = nand_dump(nand, off);
|
||||
|
||||
return ret == 0 ? 1 : 0;
|
||||
|
||||
}
|
||||
|
||||
/* read write */
|
||||
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
|
||||
if (argc < 4)
|
||||
goto usage;
|
||||
/*
|
||||
s = strchr(cmd, '.');
|
||||
clean = CLEAN_NONE;
|
||||
if (s != NULL) {
|
||||
if (strcmp(s, ".jffs2") == 0 || strcmp(s, ".e") == 0
|
||||
|| strcmp(s, ".i"))
|
||||
clean = CLEAN_JFFS2;
|
||||
}
|
||||
*/
|
||||
addr = (ulong)simple_strtoul(argv[2], NULL, 16);
|
||||
|
||||
arg_off_size(argc - 3, argv + 3, &off, &size, nand->size);
|
||||
if (off == 0 && size == 0)
|
||||
return 1;
|
||||
|
||||
i = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
|
||||
printf("\nNAND %s: device %d offset 0x%x, size %u ... ",
|
||||
i ? "read" : "write", nand_curr_device, off, size);
|
||||
|
||||
if (i)
|
||||
ret = nand_read(nand, (loff_t)off, &size, (u_char *)addr);
|
||||
else
|
||||
ret = nand_write(nand, (loff_t)off, &size, (u_char *)addr);
|
||||
|
||||
printf(" %d bytes %s: %s\n", size,
|
||||
i ? "read" : "written", ret ? "ERROR" : "OK");
|
||||
|
||||
return ret == 0 ? 0 : 1;
|
||||
}
|
||||
usage:
|
||||
printf("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(nand, 5, 1, do_nand,
|
||||
"nand - NAND sub-system\n",
|
||||
"info - show available NAND devices\n"
|
||||
"nand device [dev] - show or set current device\n"
|
||||
"nand read[.jffs2] - addr off size\n"
|
||||
"nand write[.jffs2] - addr off size - read/write `size' bytes starting\n"
|
||||
" at offset `off' to/from memory address `addr'\n"
|
||||
"nand erase [clean] [off size] - erase `size' bytes from\n"
|
||||
" offset `off' (entire device if not specified)\n"
|
||||
"nand bad - show bad blocks\n"
|
||||
"nand dump[.oob] off - dump page\n"
|
||||
"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
|
||||
"nand markbad off - mark bad block at offset (UNSAFE)\n"
|
||||
"nand biterr off - make a bit error at offset (UNSAFE)\n");
|
||||
|
||||
int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *boot_device = NULL;
|
||||
char *ep;
|
||||
int dev;
|
||||
int r;
|
||||
ulong addr, cnt, offset = 0;
|
||||
image_header_t *hdr;
|
||||
nand_info_t *nand;
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
addr = CFG_LOAD_ADDR;
|
||||
boot_device = getenv("bootdevice");
|
||||
break;
|
||||
case 2:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = getenv("bootdevice");
|
||||
break;
|
||||
case 3:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = argv[2];
|
||||
break;
|
||||
case 4:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = argv[2];
|
||||
offset = simple_strtoul(argv[3], NULL, 16);
|
||||
break;
|
||||
default:
|
||||
printf("Usage:\n%s\n", cmdtp->usage);
|
||||
SHOW_BOOT_PROGRESS(-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boot_device) {
|
||||
puts("\n** No boot device **\n");
|
||||
SHOW_BOOT_PROGRESS(-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = simple_strtoul(boot_device, &ep, 16);
|
||||
|
||||
if (dev < 0 || dev >= CFG_MAX_NAND_DEVICE || !nand_info[dev].name) {
|
||||
printf("\n** Device %d not available\n", dev);
|
||||
SHOW_BOOT_PROGRESS(-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nand = &nand_info[dev];
|
||||
printf("\nLoading from device %d: %s (offset 0x%lx)\n",
|
||||
dev, nand->name, offset);
|
||||
|
||||
cnt = nand->oobblock;
|
||||
r = nand_read(nand, offset, &cnt, (u_char *) addr);
|
||||
if (r) {
|
||||
printf("** Read error on %d\n", dev);
|
||||
SHOW_BOOT_PROGRESS(-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hdr = (image_header_t *) addr;
|
||||
|
||||
if (ntohl(hdr->ih_magic) != IH_MAGIC) {
|
||||
printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic);
|
||||
SHOW_BOOT_PROGRESS(-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_image_hdr(hdr);
|
||||
|
||||
cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t));
|
||||
|
||||
r = nand_read(nand, offset, &cnt, (u_char *) addr);
|
||||
if (r) {
|
||||
printf("** Read error on %d\n", dev);
|
||||
SHOW_BOOT_PROGRESS(-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Loading ok, update default load address */
|
||||
|
||||
load_addr = addr;
|
||||
#ifndef CONFIG_ATH_NAND_SUPPORT
|
||||
/* Check if we should attempt an auto-start */
|
||||
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
|
||||
#endif
|
||||
char *local_args[2];
|
||||
extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
|
||||
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = NULL;
|
||||
|
||||
#ifndef CONFIG_ATH_NAND_SUPPORT
|
||||
printf("Automatic boot of image at addr 0x%08lx ...\n", addr);
|
||||
#endif
|
||||
|
||||
do_bootm(cmdtp, 0, 1, local_args);
|
||||
return 1;
|
||||
#ifndef CONFIG_ATH_NAND_SUPPORT
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(nboot, 4, 1, do_nandboot,
|
||||
"nboot - boot from NAND device\n", "loadAddr dev\n");
|
||||
|
||||
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
|
||||
|
||||
#else /* CFG_NAND_LEGACY */
|
||||
/*
|
||||
*
|
||||
* Legacy NAND support - to be phased out
|
||||
*
|
||||
*/
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
# include <status_led.h>
|
||||
# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
|
||||
#else
|
||||
# define SHOW_BOOT_PROGRESS(arg)
|
||||
#endif
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
|
||||
#include <linux/mtd/nand_legacy.h>
|
||||
#if 0
|
||||
#include <linux/mtd/nand_ids.h>
|
||||
#include <jffs2/jffs2.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OMAP1510
|
||||
void archflashwp(void *archdata, int wp);
|
||||
#endif
|
||||
|
||||
#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
|
||||
|
||||
#undef NAND_DEBUG
|
||||
#undef PSYCHO_DEBUG
|
||||
|
||||
/* ****************** WARNING *********************
|
||||
* When ALLOW_ERASE_BAD_DEBUG is non-zero the erase command will
|
||||
* erase (or at least attempt to erase) blocks that are marked
|
||||
* bad. This can be very handy if you are _sure_ that the block
|
||||
* is OK, say because you marked a good block bad to test bad
|
||||
* block handling and you are done testing, or if you have
|
||||
* accidentally marked blocks bad.
|
||||
*
|
||||
* Erasing factory marked bad blocks is a _bad_ idea. If the
|
||||
* erase succeeds there is no reliable way to find them again,
|
||||
* and attempting to program or erase bad blocks can affect
|
||||
* the data in _other_ (good) blocks.
|
||||
*/
|
||||
#define ALLOW_ERASE_BAD_DEBUG 0
|
||||
|
||||
#define CONFIG_MTD_NAND_ECC /* enable ECC */
|
||||
#define CONFIG_MTD_NAND_ECC_JFFS2
|
||||
|
||||
/* bits for nand_legacy_rw() `cmd'; or together as needed */
|
||||
#define NANDRW_READ 0x01
|
||||
#define NANDRW_WRITE 0x00
|
||||
#define NANDRW_JFFS2 0x02
|
||||
#define NANDRW_JFFS2_SKIP 0x04
|
||||
|
||||
/*
|
||||
* Imports from nand_legacy.c
|
||||
*/
|
||||
extern struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE];
|
||||
extern int curr_device;
|
||||
extern int nand_legacy_erase(struct nand_chip *nand, size_t ofs,
|
||||
size_t len, int clean);
|
||||
extern int nand_legacy_rw(struct nand_chip *nand, int cmd, size_t start,
|
||||
size_t len, size_t *retlen, u_char *buf);
|
||||
extern void nand_print(struct nand_chip *nand);
|
||||
extern void nand_print_bad(struct nand_chip *nand);
|
||||
extern int nand_read_oob(struct nand_chip *nand, size_t ofs,
|
||||
size_t len, size_t *retlen, u_char *buf);
|
||||
extern int nand_write_oob(struct nand_chip *nand, size_t ofs,
|
||||
size_t len, size_t *retlen, const u_char *buf);
|
||||
|
||||
|
||||
int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int rcode = 0;
|
||||
|
||||
switch (argc) {
|
||||
case 0:
|
||||
case 1:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
case 2:
|
||||
if (strcmp(argv[1],"info") == 0) {
|
||||
int i;
|
||||
|
||||
putc ('\n');
|
||||
|
||||
for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) {
|
||||
if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN)
|
||||
continue; /* list only known devices */
|
||||
printf ("Device %d: ", i);
|
||||
nand_print(&nand_dev_desc[i]);
|
||||
}
|
||||
return 0;
|
||||
|
||||
} else if (strcmp(argv[1],"device") == 0) {
|
||||
if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
|
||||
puts ("\nno devices available\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("\nDevice %d: ", curr_device);
|
||||
nand_print(&nand_dev_desc[curr_device]);
|
||||
return 0;
|
||||
|
||||
} else if (strcmp(argv[1],"bad") == 0) {
|
||||
if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) {
|
||||
puts ("\nno devices available\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("\nDevice %d bad blocks:\n", curr_device);
|
||||
nand_print_bad(&nand_dev_desc[curr_device]);
|
||||
return 0;
|
||||
|
||||
}
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
case 3:
|
||||
if (strcmp(argv[1],"device") == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
|
||||
printf ("\nDevice %d: ", dev);
|
||||
if (dev >= CFG_MAX_NAND_DEVICE) {
|
||||
puts ("unknown device\n");
|
||||
return 1;
|
||||
}
|
||||
nand_print(&nand_dev_desc[dev]);
|
||||
/*nand_print (dev);*/
|
||||
|
||||
if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
curr_device = dev;
|
||||
|
||||
puts ("... is now current device\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(argv[1],"erase") == 0 && strcmp(argv[2], "clean") == 0) {
|
||||
struct nand_chip* nand = &nand_dev_desc[curr_device];
|
||||
ulong off = 0;
|
||||
ulong size = nand->totlen;
|
||||
int ret;
|
||||
|
||||
printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
|
||||
curr_device, off, size);
|
||||
|
||||
ret = nand_legacy_erase (nand, off, size, 1);
|
||||
|
||||
printf("%s\n", ret ? "ERROR" : "OK");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
default:
|
||||
/* at least 4 args */
|
||||
|
||||
if (strncmp(argv[1], "read", 4) == 0 ||
|
||||
strncmp(argv[1], "write", 5) == 0) {
|
||||
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
||||
ulong off = simple_strtoul(argv[3], NULL, 16);
|
||||
ulong size = simple_strtoul(argv[4], NULL, 16);
|
||||
int cmd = (strncmp(argv[1], "read", 4) == 0) ?
|
||||
NANDRW_READ : NANDRW_WRITE;
|
||||
int ret, total;
|
||||
char* cmdtail = strchr(argv[1], '.');
|
||||
|
||||
if (cmdtail && !strncmp(cmdtail, ".oob", 2)) {
|
||||
/* read out-of-band data */
|
||||
if (cmd & NANDRW_READ) {
|
||||
ret = nand_read_oob(nand_dev_desc + curr_device,
|
||||
off, size, (size_t *)&total,
|
||||
(u_char*)addr);
|
||||
}
|
||||
else {
|
||||
ret = nand_write_oob(nand_dev_desc + curr_device,
|
||||
off, size, (size_t *)&total,
|
||||
(u_char*)addr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else if (cmdtail && !strncmp(cmdtail, ".jffs2", 2))
|
||||
cmd |= NANDRW_JFFS2; /* skip bad blocks */
|
||||
else if (cmdtail && !strncmp(cmdtail, ".jffs2s", 2)) {
|
||||
cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
|
||||
if (cmd & NANDRW_READ)
|
||||
cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
|
||||
}
|
||||
#ifdef SXNI855T
|
||||
/* need ".e" same as ".j" for compatibility with older units */
|
||||
else if (cmdtail && !strcmp(cmdtail, ".e"))
|
||||
cmd |= NANDRW_JFFS2; /* skip bad blocks */
|
||||
#endif
|
||||
#ifdef CFG_NAND_SKIP_BAD_DOT_I
|
||||
/* need ".i" same as ".jffs2s" for compatibility with older units (esd) */
|
||||
/* ".i" for image -> read skips bad block (no 0xff) */
|
||||
else if (cmdtail && !strcmp(cmdtail, ".i")) {
|
||||
cmd |= NANDRW_JFFS2; /* skip bad blocks (on read too) */
|
||||
if (cmd & NANDRW_READ)
|
||||
cmd |= NANDRW_JFFS2_SKIP; /* skip bad blocks (on read too) */
|
||||
}
|
||||
#endif /* CFG_NAND_SKIP_BAD_DOT_I */
|
||||
else if (cmdtail) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf ("\nNAND %s: device %d offset %ld, size %ld ... ",
|
||||
(cmd & NANDRW_READ) ? "read" : "write",
|
||||
curr_device, off, size);
|
||||
|
||||
ret = nand_legacy_rw(nand_dev_desc + curr_device, cmd, off, size,
|
||||
(size_t *)&total, (u_char*)addr);
|
||||
|
||||
printf (" %d bytes %s: %s\n", total,
|
||||
(cmd & NANDRW_READ) ? "read" : "written",
|
||||
ret ? "ERROR" : "OK");
|
||||
|
||||
return ret;
|
||||
} else if (strcmp(argv[1],"erase") == 0 &&
|
||||
(argc == 4 || strcmp("clean", argv[2]) == 0)) {
|
||||
int clean = argc == 5;
|
||||
ulong off = simple_strtoul(argv[2 + clean], NULL, 16);
|
||||
ulong size = simple_strtoul(argv[3 + clean], NULL, 16);
|
||||
int ret;
|
||||
|
||||
printf ("\nNAND erase: device %d offset %ld, size %ld ... ",
|
||||
curr_device, off, size);
|
||||
|
||||
ret = nand_legacy_erase (nand_dev_desc + curr_device,
|
||||
off, size, clean);
|
||||
|
||||
printf("%s\n", ret ? "ERROR" : "OK");
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
rcode = 1;
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
nand, 5, 1, do_nand,
|
||||
"nand - NAND sub-system\n",
|
||||
"info - show available NAND devices\n"
|
||||
"nand device [dev] - show or set current device\n"
|
||||
"nand read[.jffs2[s]] addr off size\n"
|
||||
"nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
|
||||
" at offset `off' to/from memory address `addr'\n"
|
||||
"nand erase [clean] [off size] - erase `size' bytes from\n"
|
||||
" offset `off' (entire device if not specified)\n"
|
||||
"nand bad - show bad blocks\n"
|
||||
"nand read.oob addr off size - read out-of-band data\n"
|
||||
"nand write.oob addr off size - read out-of-band data\n"
|
||||
);
|
||||
|
||||
int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *boot_device = NULL;
|
||||
char *ep;
|
||||
int dev;
|
||||
ulong cnt;
|
||||
ulong addr;
|
||||
ulong offset = 0;
|
||||
image_header_t *hdr;
|
||||
int rcode = 0;
|
||||
switch (argc) {
|
||||
case 1:
|
||||
addr = CFG_LOAD_ADDR;
|
||||
boot_device = getenv ("bootdevice");
|
||||
break;
|
||||
case 2:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = getenv ("bootdevice");
|
||||
break;
|
||||
case 3:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = argv[2];
|
||||
break;
|
||||
case 4:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = argv[2];
|
||||
offset = simple_strtoul(argv[3], NULL, 16);
|
||||
break;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boot_device) {
|
||||
puts ("\n** No boot device **\n");
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = simple_strtoul(boot_device, &ep, 16);
|
||||
|
||||
if ((dev >= CFG_MAX_NAND_DEVICE) ||
|
||||
(nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) {
|
||||
printf ("\n** Device %d not available\n", dev);
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf ("\nLoading from device %d: %s at 0x%lx (offset 0x%lx)\n",
|
||||
dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR,
|
||||
offset);
|
||||
|
||||
if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ, offset,
|
||||
SECTORSIZE, NULL, (u_char *)addr)) {
|
||||
printf ("** Read error on %d\n", dev);
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hdr = (image_header_t *)addr;
|
||||
|
||||
if (ntohl(hdr->ih_magic) == IH_MAGIC) {
|
||||
|
||||
print_image_hdr (hdr);
|
||||
|
||||
cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
|
||||
cnt -= SECTORSIZE;
|
||||
} else {
|
||||
printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic));
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nand_legacy_rw (nand_dev_desc + dev, NANDRW_READ,
|
||||
offset + SECTORSIZE, cnt, NULL,
|
||||
(u_char *)(addr+SECTORSIZE))) {
|
||||
printf ("** Read error on %d\n", dev);
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Loading ok, update default load address */
|
||||
|
||||
load_addr = addr;
|
||||
|
||||
/* Check if we should attempt an auto-start */
|
||||
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
|
||||
char *local_args[2];
|
||||
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
|
||||
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = NULL;
|
||||
|
||||
printf ("Automatic boot of image at addr 0x%08lx ...\n", addr);
|
||||
|
||||
do_bootm (cmdtp, 0, 1, local_args);
|
||||
rcode = 1;
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
nboot, 4, 1, do_nandboot,
|
||||
"nboot - boot from NAND device\n",
|
||||
"loadAddr dev\n"
|
||||
);
|
||||
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */
|
||||
|
||||
#endif /* CFG_NAND_LEGACY */
|
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Boot support
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <net.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
|
||||
|
||||
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
|
||||
|
||||
static int netboot_common (proto_t, cmd_tbl_t *, int , char *[]);
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
int do_bootp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
return netboot_common (BOOTP, cmdtp, argc, argv);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
bootp, 3, 1, do_bootp,
|
||||
"bootp\t- boot image via network using BootP/TFTP protocol\n",
|
||||
"[loadAddress] [bootfilename]\n"
|
||||
);
|
||||
|
||||
int do_rarpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
return netboot_common (RARP, cmdtp, argc, argv);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
rarpboot, 3, 1, do_rarpb,
|
||||
"rarpboot- boot image via network using RARP/TFTP protocol\n",
|
||||
"[loadAddress] [bootfilename]\n"
|
||||
);
|
||||
#endif /* #ifndef COMPRESSED_UBOOT */
|
||||
int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
return netboot_common (TFTP, cmdtp, argc, argv);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
tftpboot, 3, 1, do_tftpb,
|
||||
"tftpboot- boot image via network using TFTP protocol\n",
|
||||
"[loadAddress] [bootfilename]\n"
|
||||
);
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
|
||||
int do_dhcp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
return netboot_common(DHCP, cmdtp, argc, argv);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
dhcp, 3, 1, do_dhcp,
|
||||
"dhcp\t- invoke DHCP client to obtain IP/boot params\n",
|
||||
"\n"
|
||||
);
|
||||
#endif /* CFG_CMD_DHCP */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NFS)
|
||||
int do_nfs (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
return netboot_common(NFS, cmdtp, argc, argv);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
nfs, 3, 1, do_nfs,
|
||||
"nfs\t- boot image via network using NFS protocol\n",
|
||||
"[loadAddress] [host ip addr:bootfilename]\n"
|
||||
);
|
||||
#endif /* CFG_CMD_NFS */
|
||||
|
||||
static void netboot_update_env (void)
|
||||
{
|
||||
char tmp[22];
|
||||
|
||||
if (NetOurGatewayIP) {
|
||||
ip_to_string (NetOurGatewayIP, tmp);
|
||||
setenv ("gatewayip", tmp);
|
||||
}
|
||||
|
||||
if (NetOurSubnetMask) {
|
||||
ip_to_string (NetOurSubnetMask, tmp);
|
||||
setenv ("netmask", tmp);
|
||||
}
|
||||
|
||||
if (NetOurHostName[0])
|
||||
setenv ("hostname", NetOurHostName);
|
||||
|
||||
if (NetOurRootPath[0])
|
||||
setenv ("rootpath", NetOurRootPath);
|
||||
|
||||
if (NetOurIP) {
|
||||
ip_to_string (NetOurIP, tmp);
|
||||
setenv ("ipaddr", tmp);
|
||||
}
|
||||
|
||||
if (NetServerIP) {
|
||||
ip_to_string (NetServerIP, tmp);
|
||||
setenv ("serverip", tmp);
|
||||
}
|
||||
|
||||
if (NetOurDNSIP) {
|
||||
ip_to_string (NetOurDNSIP, tmp);
|
||||
setenv ("dnsip", tmp);
|
||||
}
|
||||
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
|
||||
if (NetOurDNS2IP) {
|
||||
ip_to_string (NetOurDNS2IP, tmp);
|
||||
setenv ("dnsip2", tmp);
|
||||
}
|
||||
#endif
|
||||
if (NetOurNISDomain[0])
|
||||
setenv ("domain", NetOurNISDomain);
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SNTP) && (CONFIG_BOOTP_MASK & CONFIG_BOOTP_TIMEOFFSET)
|
||||
if (NetTimeOffset) {
|
||||
sprintf (tmp, "%d", NetTimeOffset);
|
||||
setenv ("timeoffset", tmp);
|
||||
}
|
||||
#endif
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SNTP) && (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NTPSERVER)
|
||||
if (NetNtpServerIP) {
|
||||
ip_to_string (NetNtpServerIP, tmp);
|
||||
setenv ("ntpserverip", tmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[])
|
||||
{
|
||||
char *s;
|
||||
int rcode = 0;
|
||||
int size;
|
||||
|
||||
/* pre-set load_addr */
|
||||
if ((s = getenv("loadaddr")) != NULL) {
|
||||
load_addr = simple_strtoul(s, NULL, 16);
|
||||
}
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
break;
|
||||
|
||||
case 2: /* only one arg - accept two forms:
|
||||
* just load address, or just boot file name.
|
||||
* The latter form must be written "filename" here.
|
||||
*/
|
||||
if (argv[1][0] == '"') { /* just boot filename */
|
||||
copy_filename (BootFile, argv[1], sizeof(BootFile));
|
||||
} else { /* load address */
|
||||
load_addr = simple_strtoul(argv[1], NULL, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: load_addr = simple_strtoul(argv[1], NULL, 16);
|
||||
copy_filename (BootFile, argv[2], sizeof(BootFile));
|
||||
|
||||
break;
|
||||
|
||||
default: printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((size = NetLoop(proto)) < 0)
|
||||
return 1;
|
||||
|
||||
/* NetLoop ok, update environment */
|
||||
netboot_update_env();
|
||||
|
||||
/* done if no file was loaded (no errors though) */
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
/* flush cache */
|
||||
flush_cache(load_addr, size);
|
||||
|
||||
/* Loading ok, check if we should attempt an auto-start */
|
||||
if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) {
|
||||
char *local_args[2];
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = NULL;
|
||||
|
||||
printf ("Automatic boot of image at addr 0x%08lX ...\n",
|
||||
load_addr);
|
||||
rcode = do_bootm (cmdtp, 0, 1, local_args);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AUTOSCRIPT
|
||||
if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
|
||||
printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
|
||||
rcode = autoscript (load_addr);
|
||||
}
|
||||
#endif
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PING)
|
||||
int do_ping (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
return -1;
|
||||
|
||||
NetPingIP = string_to_ip(argv[1]);
|
||||
if (NetPingIP == 0) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NetLoop(PING) < 0) {
|
||||
printf("ping failed; host %s is not alive\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("host %s is alive\n", argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
ping, 2, 1, do_ping,
|
||||
"ping\t- send ICMP ECHO_REQUEST to network host\n",
|
||||
"pingAddress\n"
|
||||
);
|
||||
#endif /* CFG_CMD_PING */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_CDP)
|
||||
|
||||
static void cdp_update_env(void)
|
||||
{
|
||||
char tmp[16];
|
||||
|
||||
if (CDPApplianceVLAN != htons(-1)) {
|
||||
printf("CDP offered appliance VLAN %d\n", ntohs(CDPApplianceVLAN));
|
||||
VLAN_to_string(CDPApplianceVLAN, tmp);
|
||||
setenv("vlan", tmp);
|
||||
NetOurVLAN = CDPApplianceVLAN;
|
||||
}
|
||||
|
||||
if (CDPNativeVLAN != htons(-1)) {
|
||||
printf("CDP offered native VLAN %d\n", ntohs(CDPNativeVLAN));
|
||||
VLAN_to_string(CDPNativeVLAN, tmp);
|
||||
setenv("nvlan", tmp);
|
||||
NetOurNativeVLAN = CDPNativeVLAN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int do_cdp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int r;
|
||||
|
||||
r = NetLoop(CDP);
|
||||
if (r < 0) {
|
||||
printf("cdp failed; perhaps not a CISCO switch?\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
cdp_update_env();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
cdp, 1, 1, do_cdp,
|
||||
"cdp\t- Perform CDP network configuration\n",
|
||||
);
|
||||
#endif /* CFG_CMD_CDP */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SNTP)
|
||||
int do_sntp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *toff;
|
||||
|
||||
if (argc < 2) {
|
||||
NetNtpServerIP = getenv_IPaddr ("ntpserverip");
|
||||
if (NetNtpServerIP == 0) {
|
||||
printf ("ntpserverip not set\n");
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
NetNtpServerIP = string_to_ip(argv[1]);
|
||||
if (NetNtpServerIP == 0) {
|
||||
printf ("Bad NTP server IP address\n");
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
toff = getenv ("timeoffset");
|
||||
if (toff == NULL) NetTimeOffset = 0;
|
||||
else NetTimeOffset = simple_strtol (toff, NULL, 10);
|
||||
|
||||
if (NetLoop(SNTP) < 0) {
|
||||
printf("SNTP failed: host %s not responding\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
sntp, 2, 1, do_sntp,
|
||||
"sntp\t- synchronize RTC via network\n",
|
||||
"[NTP server IP]\n"
|
||||
);
|
||||
#endif /* CFG_CMD_SNTP */
|
||||
|
||||
#endif /* CFG_CMD_NET */
|
|
@ -0,0 +1,627 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.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
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Support for persistent environment data
|
||||
*
|
||||
* The "environment" is stored as a list of '\0' terminated
|
||||
* "name=value" strings. The end of the list is marked by a double
|
||||
* '\0'. New entries are always added at the end. Deleting an entry
|
||||
* shifts the remaining entries to the front. Replacing an entry is a
|
||||
* combination of deleting the old value and adding the new one.
|
||||
*
|
||||
* The environment is preceeded by a 32 bit CRC over the data part.
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <watchdog.h>
|
||||
#include <serial.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <asm/byteorder.h>
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
#include <net.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if !defined(CFG_ENV_IS_IN_NVRAM) && \
|
||||
!defined(CFG_ENV_IS_IN_EEPROM) && \
|
||||
!defined(CFG_ENV_IS_IN_FLASH) && \
|
||||
!defined(CFG_ENV_IS_IN_DATAFLASH) && \
|
||||
!defined(CFG_ENV_IS_IN_NAND) && \
|
||||
!defined(CFG_ENV_IS_NOWHERE)
|
||||
# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE}
|
||||
#endif
|
||||
|
||||
#define XMK_STR(x) #x
|
||||
#define MK_STR(x) XMK_STR(x)
|
||||
|
||||
/************************************************************************
|
||||
************************************************************************/
|
||||
|
||||
/* Function that returns a character from the environment */
|
||||
extern uchar (*env_get_char)(int);
|
||||
|
||||
/* Function that returns a pointer to a value from the environment */
|
||||
/* (Only memory version supported / needed). */
|
||||
extern uchar *env_get_addr(int);
|
||||
|
||||
/* Function that updates CRC of the enironment */
|
||||
extern void env_crc_update (void);
|
||||
|
||||
/************************************************************************
|
||||
************************************************************************/
|
||||
|
||||
static int envmatch (uchar *, int);
|
||||
|
||||
/*
|
||||
* Table with supported baudrates (defined in config_xyz.h)
|
||||
*/
|
||||
static const unsigned long baudrate_table[] = CFG_BAUDRATE_TABLE;
|
||||
#define N_BAUDRATES (sizeof(baudrate_table) / sizeof(baudrate_table[0]))
|
||||
|
||||
/************************************************************************
|
||||
* Command interface: print one or all environment variables
|
||||
*/
|
||||
|
||||
int do_printenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i, j, k, nxt;
|
||||
int rcode = 0;
|
||||
|
||||
if (argc == 1) { /* Print all env variables */
|
||||
for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
|
||||
for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)
|
||||
;
|
||||
for (k=i; k<nxt; ++k)
|
||||
putc(env_get_char(k));
|
||||
putc ('\n');
|
||||
|
||||
if (ctrlc()) {
|
||||
puts ("\n ** Abort\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nEnvironment size: %d/%d bytes\n", i, ENV_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=1; i<argc; ++i) { /* print single env variables */
|
||||
char *name = argv[i];
|
||||
|
||||
k = -1;
|
||||
|
||||
for (j=0; env_get_char(j) != '\0'; j=nxt+1) {
|
||||
|
||||
for (nxt=j; env_get_char(nxt) != '\0'; ++nxt)
|
||||
;
|
||||
k = envmatch((uchar *)name, j);
|
||||
if (k < 0) {
|
||||
continue;
|
||||
}
|
||||
puts (name);
|
||||
putc ('=');
|
||||
while (k < nxt)
|
||||
putc(env_get_char(k++));
|
||||
putc ('\n');
|
||||
break;
|
||||
}
|
||||
if (k < 0) {
|
||||
printf ("## Error: \"%s\" not defined\n", name);
|
||||
rcode ++;
|
||||
}
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Set a new environment variable,
|
||||
* or replace or delete an existing one.
|
||||
*
|
||||
* This function will ONLY work with a in-RAM copy of the environment
|
||||
*/
|
||||
|
||||
int _do_setenv (int flag, int argc, char *argv[])
|
||||
{
|
||||
int i, len, oldval;
|
||||
int console = -1;
|
||||
uchar *env, *nxt = NULL;
|
||||
char *name;
|
||||
bd_t *bd = gd->bd;
|
||||
|
||||
uchar *env_data = env_get_addr(0);
|
||||
|
||||
if (!env_data) /* need copy in RAM */
|
||||
return 1;
|
||||
|
||||
name = argv[1];
|
||||
|
||||
/*
|
||||
* search if variable with this name already exists
|
||||
*/
|
||||
oldval = -1;
|
||||
for (env=env_data; *env; env=nxt+1) {
|
||||
for (nxt=env; *nxt; ++nxt)
|
||||
;
|
||||
if ((oldval = envmatch((uchar *)name, env-env_data)) >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete any existing definition
|
||||
*/
|
||||
if (oldval >= 0) {
|
||||
#ifndef CONFIG_ENV_OVERWRITE
|
||||
|
||||
/*
|
||||
* Ethernet Address and serial# can be set only once,
|
||||
* ver is readonly.
|
||||
*/
|
||||
if ( (strcmp (name, "serial#") == 0) ||
|
||||
((strcmp (name, "ethaddr") == 0)
|
||||
#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
|
||||
&& (strcmp ((char *)env_get_addr(oldval),MK_STR(CONFIG_ETHADDR)) != 0)
|
||||
#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
|
||||
) ) {
|
||||
printf ("Can't overwrite \"%s\"\n", name);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for console redirection */
|
||||
if (strcmp(name,"stdin") == 0) {
|
||||
console = stdin;
|
||||
} else if (strcmp(name,"stdout") == 0) {
|
||||
console = stdout;
|
||||
} else if (strcmp(name,"stderr") == 0) {
|
||||
console = stderr;
|
||||
}
|
||||
|
||||
if (console != -1) {
|
||||
if (argc < 3) { /* Cannot delete it! */
|
||||
printf("Can't delete \"%s\"\n", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Try assigning specified device */
|
||||
if (console_assign (console, argv[2]) < 0)
|
||||
return 1;
|
||||
|
||||
#ifdef CONFIG_SERIAL_MULTI
|
||||
if (serial_assign (argv[2]) < 0)
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch to new baudrate if new baudrate is supported
|
||||
*/
|
||||
if (strcmp(argv[1],"baudrate") == 0) {
|
||||
int baudrate = simple_strtoul(argv[2], NULL, 10);
|
||||
int i;
|
||||
for (i=0; i<N_BAUDRATES; ++i) {
|
||||
if (baudrate == baudrate_table[i])
|
||||
break;
|
||||
}
|
||||
if (i == N_BAUDRATES) {
|
||||
printf ("## Baudrate %d bps not supported\n",
|
||||
baudrate);
|
||||
return 1;
|
||||
}
|
||||
printf ("## Switch baudrate to %d bps and press ENTER ...\n",
|
||||
baudrate);
|
||||
udelay(50000);
|
||||
gd->baudrate = baudrate;
|
||||
#ifdef CONFIG_PPC
|
||||
gd->bd->bi_baudrate = baudrate;
|
||||
#endif
|
||||
|
||||
serial_setbrg ();
|
||||
udelay(50000);
|
||||
for (;;) {
|
||||
if (getc() == '\r')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*++nxt == '\0') {
|
||||
if (env > env_data) {
|
||||
env--;
|
||||
} else {
|
||||
*env = '\0';
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
*env = *nxt++;
|
||||
if ((*env == '\0') && (*nxt == '\0'))
|
||||
break;
|
||||
++env;
|
||||
}
|
||||
}
|
||||
*++env = '\0';
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_MULTI
|
||||
if (strncmp(name, "eth", 3) == 0) {
|
||||
char *end;
|
||||
int num = simple_strtoul(name+3, &end, 10);
|
||||
|
||||
if (strcmp(end, "addr") == 0) {
|
||||
eth_set_enetaddr(num, argv[2]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Delete only ? */
|
||||
if ((argc < 3) || argv[2] == NULL) {
|
||||
env_crc_update ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append new definition at the end
|
||||
*/
|
||||
for (env=env_data; *env || *(env+1); ++env)
|
||||
;
|
||||
if (env > env_data)
|
||||
++env;
|
||||
/*
|
||||
* Overflow when:
|
||||
* "name" + "=" + "val" +"\0\0" > ENV_SIZE - (env-env_data)
|
||||
*/
|
||||
len = strlen(name) + 2;
|
||||
/* add '=' for first arg, ' ' for all others */
|
||||
for (i=2; i<argc; ++i) {
|
||||
len += strlen(argv[i]) + 1;
|
||||
}
|
||||
if (len > (&env_data[ENV_SIZE]-env)) {
|
||||
printf ("## Error: environment overflow, \"%s\" deleted\n", name);
|
||||
return 1;
|
||||
}
|
||||
while ((*env = *name++) != '\0')
|
||||
env++;
|
||||
for (i=2; i<argc; ++i) {
|
||||
char *val = argv[i];
|
||||
|
||||
*env = (i==2) ? '=' : ' ';
|
||||
while ((*++env = *val++) != '\0')
|
||||
;
|
||||
}
|
||||
|
||||
/* end is marked with double '\0' */
|
||||
*++env = '\0';
|
||||
|
||||
/* Update CRC */
|
||||
env_crc_update ();
|
||||
|
||||
/*
|
||||
* Some variables should be updated when the corresponding
|
||||
* entry in the enviornment is changed
|
||||
*/
|
||||
|
||||
if (strcmp(argv[1],"ethaddr") == 0) {
|
||||
char *s = argv[2]; /* always use only one arg */
|
||||
char *e;
|
||||
for (i=0; i<6; ++i) {
|
||||
bd->bi_enetaddr[i] = s ? simple_strtoul(s, &e, 16) : 0;
|
||||
if (s) s = (*e) ? e+1 : e;
|
||||
}
|
||||
#ifdef CONFIG_NET_MULTI
|
||||
eth_set_enetaddr(0, argv[2]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1],"ipaddr") == 0) {
|
||||
char *s = argv[2]; /* always use only one arg */
|
||||
char *e;
|
||||
unsigned long addr;
|
||||
bd->bi_ip_addr = 0;
|
||||
for (addr=0, i=0; i<4; ++i) {
|
||||
ulong val = s ? simple_strtoul(s, &e, 10) : 0;
|
||||
addr <<= 8;
|
||||
addr |= (val & 0xFF);
|
||||
if (s) s = (*e) ? e+1 : e;
|
||||
}
|
||||
bd->bi_ip_addr = htonl(addr);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[1],"loadaddr") == 0) {
|
||||
load_addr = simple_strtoul(argv[2], NULL, 16);
|
||||
return 0;
|
||||
}
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_NET)
|
||||
if (strcmp(argv[1],"bootfile") == 0) {
|
||||
copy_filename (BootFile, argv[2], sizeof(BootFile));
|
||||
return 0;
|
||||
}
|
||||
#endif /* CFG_CMD_NET */
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
if (strcmp(argv[1], "vga_fg_color") == 0 ||
|
||||
strcmp(argv[1], "vga_bg_color") == 0 ) {
|
||||
extern void video_set_color(unsigned char attr);
|
||||
extern unsigned char video_get_attr(void);
|
||||
|
||||
video_set_color(video_get_attr());
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_AMIGAONEG3SE */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setenv (char *varname, char *varvalue)
|
||||
{
|
||||
char *argv[4] = { "setenv", varname, varvalue, NULL };
|
||||
_do_setenv (0, 3, argv);
|
||||
}
|
||||
|
||||
int do_setenv ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return _do_setenv (flag, argc, argv);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Prompt for environment variable
|
||||
*/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ASKENV)
|
||||
int do_askenv ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
extern char console_buffer[CFG_CBSIZE];
|
||||
char message[CFG_CBSIZE];
|
||||
int size = CFG_CBSIZE - 1;
|
||||
int len;
|
||||
char *local_args[4];
|
||||
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = argv[1];
|
||||
local_args[2] = NULL;
|
||||
local_args[3] = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
/* Check the syntax */
|
||||
switch (argc) {
|
||||
case 1:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
|
||||
case 2: /* askenv envname */
|
||||
sprintf (message, "Please enter '%s':", argv[1]);
|
||||
break;
|
||||
|
||||
case 3: /* askenv envname size */
|
||||
sprintf (message, "Please enter '%s':", argv[1]);
|
||||
size = simple_strtoul (argv[2], NULL, 10);
|
||||
break;
|
||||
|
||||
default: /* askenv envname message1 ... messagen size */
|
||||
{
|
||||
int i;
|
||||
int pos = 0;
|
||||
|
||||
for (i = 2; i < argc - 1; i++) {
|
||||
if (pos) {
|
||||
message[pos++] = ' ';
|
||||
}
|
||||
strcpy (message+pos, argv[i]);
|
||||
pos += strlen(argv[i]);
|
||||
}
|
||||
message[pos] = '\0';
|
||||
size = simple_strtoul (argv[argc - 1], NULL, 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (size >= CFG_CBSIZE)
|
||||
size = CFG_CBSIZE - 1;
|
||||
|
||||
if (size <= 0)
|
||||
return 1;
|
||||
|
||||
/* prompt for input */
|
||||
len = readline (message);
|
||||
|
||||
if (size < len)
|
||||
console_buffer[size] = '\0';
|
||||
|
||||
len = 2;
|
||||
if (console_buffer[0] != '\0') {
|
||||
local_args[2] = console_buffer;
|
||||
len = 3;
|
||||
}
|
||||
|
||||
/* Continue calling setenv code */
|
||||
return _do_setenv (flag, len, local_args);
|
||||
}
|
||||
#endif /* CFG_CMD_ASKENV */
|
||||
|
||||
/************************************************************************
|
||||
* Look up variable from environment,
|
||||
* return address of storage for that variable,
|
||||
* or NULL if not found
|
||||
*/
|
||||
|
||||
char *getenv (char *name)
|
||||
{
|
||||
int i, nxt;
|
||||
|
||||
WATCHDOG_RESET();
|
||||
|
||||
for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
|
||||
int val;
|
||||
|
||||
for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {
|
||||
if (nxt >= CFG_ENV_SIZE) {
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
if ((val=envmatch((uchar *)name, i)) < 0)
|
||||
continue;
|
||||
return ((char *)env_get_addr(val));
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int getenv_r (char *name, char *buf, unsigned len)
|
||||
{
|
||||
int i, nxt;
|
||||
|
||||
for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
|
||||
int val, n;
|
||||
|
||||
for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {
|
||||
if (nxt >= CFG_ENV_SIZE) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if ((val=envmatch((uchar *)name, i)) < 0)
|
||||
continue;
|
||||
/* found; copy out */
|
||||
n = 0;
|
||||
while ((len > n++) && (*buf++ = env_get_char(val++)) != '\0')
|
||||
;
|
||||
if (len == n)
|
||||
*buf = '\0';
|
||||
return (n);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \
|
||||
((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \
|
||||
(CFG_CMD_ENV|CFG_CMD_FLASH)) || \
|
||||
((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_NAND)) == \
|
||||
(CFG_CMD_ENV|CFG_CMD_NAND))
|
||||
int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
extern char * env_name_spec;
|
||||
|
||||
printf ("Saving Environment to %s...\n", env_name_spec);
|
||||
|
||||
return (saveenv() ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Match a name / name=value pair
|
||||
*
|
||||
* s1 is either a simple 'name', or a 'name=value' pair.
|
||||
* i2 is the environment index for a 'name2=value2' pair.
|
||||
* If the names match, return the index for the value2, else NULL.
|
||||
*/
|
||||
|
||||
static int
|
||||
envmatch (uchar *s1, int i2)
|
||||
{
|
||||
|
||||
while (*s1 == env_get_char(i2++))
|
||||
if (*s1++ == '=')
|
||||
return(i2);
|
||||
if (*s1 == '\0' && env_get_char(i2-1) == '=')
|
||||
return(i2);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************/
|
||||
U_BOOT_CMD(
|
||||
printenv, CFG_MAXARGS, 1, do_printenv,
|
||||
"printenv- print environment variables\n",
|
||||
"\n - print values of all environment variables\n"
|
||||
"printenv name ...\n"
|
||||
" - print value of environment variable 'name'\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
setenv, CFG_MAXARGS, 0, do_setenv,
|
||||
"setenv - set environment variables\n",
|
||||
"name value ...\n"
|
||||
" - set environment variable 'name' to 'value ...'\n"
|
||||
"setenv name\n"
|
||||
" - delete environment variable 'name'\n"
|
||||
);
|
||||
|
||||
#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \
|
||||
((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \
|
||||
(CFG_CMD_ENV|CFG_CMD_FLASH)) || \
|
||||
((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_NAND)) == \
|
||||
(CFG_CMD_ENV|CFG_CMD_NAND))
|
||||
U_BOOT_CMD(
|
||||
saveenv, 1, 0, do_saveenv,
|
||||
"saveenv - save environment variables to persistent storage\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_ENV */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ASKENV)
|
||||
|
||||
U_BOOT_CMD(
|
||||
askenv, CFG_MAXARGS, 1, do_askenv,
|
||||
"askenv - get environment variables from stdin\n",
|
||||
"name [message] [size]\n"
|
||||
" - get environment variable 'name' from stdin (max 'size' chars)\n"
|
||||
"askenv name\n"
|
||||
" - get environment variable 'name' from stdin\n"
|
||||
"askenv name size\n"
|
||||
" - get environment variable 'name' from stdin (max 'size' chars)\n"
|
||||
"askenv name [message] size\n"
|
||||
" - display 'message' string and get environment variable 'name'"
|
||||
"from stdin (max 'size' chars)\n"
|
||||
);
|
||||
#endif /* CFG_CMD_ASKENV */
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_RUN)
|
||||
int do_run (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
|
||||
U_BOOT_CMD(
|
||||
run, CFG_MAXARGS, 1, do_run,
|
||||
"run - run commands in an environment variable\n",
|
||||
"var [...]\n"
|
||||
" - run the commands in the environment variable(s) 'var'\n"
|
||||
);
|
||||
#endif /* CFG_CMD_RUN */
|
|
@ -0,0 +1,570 @@
|
|||
/*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.de>
|
||||
*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
* Wolfgang Grandegger, DENX Software Engineering, wg@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
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCI routines
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/io.h>
|
||||
#include <pci.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PCI)
|
||||
|
||||
extern int cmd_get_data_size(char* arg, int default_size);
|
||||
|
||||
unsigned char ShortPCIListing = 1;
|
||||
|
||||
/*
|
||||
* Follows routines for the output of infos about devices on PCI bus.
|
||||
*/
|
||||
|
||||
void pci_header_show(pci_dev_t dev);
|
||||
void pci_header_show_brief(pci_dev_t dev);
|
||||
|
||||
/*
|
||||
* Subroutine: pciinfo
|
||||
*
|
||||
* Description: Show information about devices on PCI bus.
|
||||
* Depending on the define CFG_SHORT_PCI_LISTING
|
||||
* the output will be more or less exhaustive.
|
||||
*
|
||||
* Inputs: bus_no the number of the bus to be scanned.
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void pciinfo(int BusNum, int ShortPCIListing)
|
||||
{
|
||||
int Device;
|
||||
int Function;
|
||||
unsigned char HeaderType;
|
||||
unsigned short VendorID;
|
||||
pci_dev_t dev;
|
||||
|
||||
printf("Scanning PCI devices on bus %d\n", BusNum);
|
||||
|
||||
if (ShortPCIListing) {
|
||||
printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
|
||||
printf("_____________________________________________________________\n");
|
||||
}
|
||||
|
||||
for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) {
|
||||
HeaderType = 0;
|
||||
VendorID = 0;
|
||||
for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) {
|
||||
/*
|
||||
* If this is not a multi-function device, we skip the rest.
|
||||
*/
|
||||
if (Function && !(HeaderType & 0x80))
|
||||
break;
|
||||
|
||||
dev = PCI_BDF(BusNum, Device, Function);
|
||||
|
||||
pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID);
|
||||
if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
|
||||
continue;
|
||||
|
||||
if (!Function) pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType);
|
||||
|
||||
if (ShortPCIListing)
|
||||
{
|
||||
printf("%02x.%02x.%02x ", BusNum, Device, Function);
|
||||
pci_header_show_brief(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\nFound PCI device %02x.%02x.%02x:\n",
|
||||
BusNum, Device, Function);
|
||||
pci_header_show(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *pci_classes_str(u8 class)
|
||||
{
|
||||
switch (class) {
|
||||
case PCI_CLASS_NOT_DEFINED:
|
||||
return "Build before PCI Rev2.0";
|
||||
break;
|
||||
case PCI_BASE_CLASS_STORAGE:
|
||||
return "Mass storage controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_NETWORK:
|
||||
return "Network controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_DISPLAY:
|
||||
return "Display controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_MULTIMEDIA:
|
||||
return "Multimedia device";
|
||||
break;
|
||||
case PCI_BASE_CLASS_MEMORY:
|
||||
return "Memory controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_BRIDGE:
|
||||
return "Bridge device";
|
||||
break;
|
||||
case PCI_BASE_CLASS_COMMUNICATION:
|
||||
return "Simple comm. controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_SYSTEM:
|
||||
return "Base system peripheral";
|
||||
break;
|
||||
case PCI_BASE_CLASS_INPUT:
|
||||
return "Input device";
|
||||
break;
|
||||
case PCI_BASE_CLASS_DOCKING:
|
||||
return "Docking station";
|
||||
break;
|
||||
case PCI_BASE_CLASS_PROCESSOR:
|
||||
return "Processor";
|
||||
break;
|
||||
case PCI_BASE_CLASS_SERIAL:
|
||||
return "Serial bus controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_INTELLIGENT:
|
||||
return "Intelligent controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_SATELLITE:
|
||||
return "Satellite controller";
|
||||
break;
|
||||
case PCI_BASE_CLASS_CRYPT:
|
||||
return "Cryptographic device";
|
||||
break;
|
||||
case PCI_BASE_CLASS_SIGNAL_PROCESSING:
|
||||
return "DSP";
|
||||
break;
|
||||
case PCI_CLASS_OTHERS:
|
||||
return "Does not fit any class";
|
||||
break;
|
||||
default:
|
||||
return "???";
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Subroutine: pci_header_show_brief
|
||||
*
|
||||
* Description: Reads and prints the header of the
|
||||
* specified PCI device in short form.
|
||||
*
|
||||
* Inputs: dev Bus+Device+Function number
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void pci_header_show_brief(pci_dev_t dev)
|
||||
{
|
||||
u16 vendor, device;
|
||||
u8 class, subclass;
|
||||
|
||||
pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
|
||||
pci_read_config_word(dev, PCI_DEVICE_ID, &device);
|
||||
pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
|
||||
pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass);
|
||||
|
||||
printf("0x%.4x 0x%.4x %-23s 0x%.2x\n",
|
||||
vendor, device,
|
||||
pci_classes_str(class), subclass);
|
||||
}
|
||||
|
||||
/*
|
||||
* Subroutine: PCI_Header_Show
|
||||
*
|
||||
* Description: Reads the header of the specified PCI device.
|
||||
*
|
||||
* Inputs: BusDevFunc Bus+Device+Function number
|
||||
*
|
||||
* Return: None
|
||||
*
|
||||
*/
|
||||
void pci_header_show(pci_dev_t dev)
|
||||
{
|
||||
u8 _byte, header_type;
|
||||
u16 _word;
|
||||
u32 _dword;
|
||||
|
||||
#define PRINT(msg, type, reg) \
|
||||
pci_read_config_##type(dev, reg, &_##type); \
|
||||
printf(msg, _##type)
|
||||
|
||||
#define PRINT2(msg, type, reg, func) \
|
||||
pci_read_config_##type(dev, reg, &_##type); \
|
||||
printf(msg, _##type, func(_##type))
|
||||
|
||||
pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
PRINT (" vendor ID = 0x%.4x\n", word, PCI_VENDOR_ID);
|
||||
PRINT (" device ID = 0x%.4x\n", word, PCI_DEVICE_ID);
|
||||
PRINT (" command register = 0x%.4x\n", word, PCI_COMMAND);
|
||||
PRINT (" status register = 0x%.4x\n", word, PCI_STATUS);
|
||||
PRINT (" revision ID = 0x%.2x\n", byte, PCI_REVISION_ID);
|
||||
PRINT2(" class code = 0x%.2x (%s)\n", byte, PCI_CLASS_CODE,
|
||||
pci_classes_str);
|
||||
PRINT (" sub class code = 0x%.2x\n", byte, PCI_CLASS_SUB_CODE);
|
||||
PRINT (" programming interface = 0x%.2x\n", byte, PCI_CLASS_PROG);
|
||||
PRINT (" cache line = 0x%.2x\n", byte, PCI_CACHE_LINE_SIZE);
|
||||
PRINT (" latency time = 0x%.2x\n", byte, PCI_LATENCY_TIMER);
|
||||
PRINT (" header type = 0x%.2x\n", byte, PCI_HEADER_TYPE);
|
||||
PRINT (" BIST = 0x%.2x\n", byte, PCI_BIST);
|
||||
PRINT (" base address 0 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_0);
|
||||
|
||||
switch (header_type & 0x03) {
|
||||
case PCI_HEADER_TYPE_NORMAL: /* "normal" PCI device */
|
||||
PRINT (" base address 1 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
|
||||
PRINT (" base address 2 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_2);
|
||||
PRINT (" base address 3 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_3);
|
||||
PRINT (" base address 4 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_4);
|
||||
PRINT (" base address 5 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_5);
|
||||
PRINT (" cardBus CIS pointer = 0x%.8x\n", dword, PCI_CARDBUS_CIS);
|
||||
PRINT (" sub system vendor ID = 0x%.4x\n", word, PCI_SUBSYSTEM_VENDOR_ID);
|
||||
PRINT (" sub system ID = 0x%.4x\n", word, PCI_SUBSYSTEM_ID);
|
||||
PRINT (" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS);
|
||||
PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
|
||||
PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
|
||||
PRINT (" min Grant = 0x%.2x\n", byte, PCI_MIN_GNT);
|
||||
PRINT (" max Latency = 0x%.2x\n", byte, PCI_MAX_LAT);
|
||||
break;
|
||||
|
||||
case PCI_HEADER_TYPE_BRIDGE: /* PCI-to-PCI bridge */
|
||||
|
||||
PRINT (" base address 1 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
|
||||
PRINT (" primary bus number = 0x%.2x\n", byte, PCI_PRIMARY_BUS);
|
||||
PRINT (" secondary bus number = 0x%.2x\n", byte, PCI_SECONDARY_BUS);
|
||||
PRINT (" subordinate bus number = 0x%.2x\n", byte, PCI_SUBORDINATE_BUS);
|
||||
PRINT (" secondary latency timer = 0x%.2x\n", byte, PCI_SEC_LATENCY_TIMER);
|
||||
PRINT (" IO base = 0x%.2x\n", byte, PCI_IO_BASE);
|
||||
PRINT (" IO limit = 0x%.2x\n", byte, PCI_IO_LIMIT);
|
||||
PRINT (" secondary status = 0x%.4x\n", word, PCI_SEC_STATUS);
|
||||
PRINT (" memory base = 0x%.4x\n", word, PCI_MEMORY_BASE);
|
||||
PRINT (" memory limit = 0x%.4x\n", word, PCI_MEMORY_LIMIT);
|
||||
PRINT (" prefetch memory base = 0x%.4x\n", word, PCI_PREF_MEMORY_BASE);
|
||||
PRINT (" prefetch memory limit = 0x%.4x\n", word, PCI_PREF_MEMORY_LIMIT);
|
||||
PRINT (" prefetch memory base upper = 0x%.8x\n", dword, PCI_PREF_BASE_UPPER32);
|
||||
PRINT (" prefetch memory limit upper = 0x%.8x\n", dword, PCI_PREF_LIMIT_UPPER32);
|
||||
PRINT (" IO base upper 16 bits = 0x%.4x\n", word, PCI_IO_BASE_UPPER16);
|
||||
PRINT (" IO limit upper 16 bits = 0x%.4x\n", word, PCI_IO_LIMIT_UPPER16);
|
||||
PRINT (" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS1);
|
||||
PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
|
||||
PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
|
||||
PRINT (" bridge control = 0x%.4x\n", word, PCI_BRIDGE_CONTROL);
|
||||
break;
|
||||
|
||||
case PCI_HEADER_TYPE_CARDBUS: /* PCI-to-CardBus bridge */
|
||||
|
||||
PRINT (" capabilities = 0x%.2x\n", byte, PCI_CB_CAPABILITY_LIST);
|
||||
PRINT (" secondary status = 0x%.4x\n", word, PCI_CB_SEC_STATUS);
|
||||
PRINT (" primary bus number = 0x%.2x\n", byte, PCI_CB_PRIMARY_BUS);
|
||||
PRINT (" CardBus number = 0x%.2x\n", byte, PCI_CB_CARD_BUS);
|
||||
PRINT (" subordinate bus number = 0x%.2x\n", byte, PCI_CB_SUBORDINATE_BUS);
|
||||
PRINT (" CardBus latency timer = 0x%.2x\n", byte, PCI_CB_LATENCY_TIMER);
|
||||
PRINT (" CardBus memory base 0 = 0x%.8x\n", dword, PCI_CB_MEMORY_BASE_0);
|
||||
PRINT (" CardBus memory limit 0 = 0x%.8x\n", dword, PCI_CB_MEMORY_LIMIT_0);
|
||||
PRINT (" CardBus memory base 1 = 0x%.8x\n", dword, PCI_CB_MEMORY_BASE_1);
|
||||
PRINT (" CardBus memory limit 1 = 0x%.8x\n", dword, PCI_CB_MEMORY_LIMIT_1);
|
||||
PRINT (" CardBus IO base 0 = 0x%.4x\n", word, PCI_CB_IO_BASE_0);
|
||||
PRINT (" CardBus IO base high 0 = 0x%.4x\n", word, PCI_CB_IO_BASE_0_HI);
|
||||
PRINT (" CardBus IO limit 0 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_0);
|
||||
PRINT (" CardBus IO limit high 0 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_0_HI);
|
||||
PRINT (" CardBus IO base 1 = 0x%.4x\n", word, PCI_CB_IO_BASE_1);
|
||||
PRINT (" CardBus IO base high 1 = 0x%.4x\n", word, PCI_CB_IO_BASE_1_HI);
|
||||
PRINT (" CardBus IO limit 1 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_1);
|
||||
PRINT (" CardBus IO limit high 1 = 0x%.4x\n", word, PCI_CB_IO_LIMIT_1_HI);
|
||||
PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE);
|
||||
PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN);
|
||||
PRINT (" bridge control = 0x%.4x\n", word, PCI_CB_BRIDGE_CONTROL);
|
||||
PRINT (" subvendor ID = 0x%.4x\n", word, PCI_CB_SUBSYSTEM_VENDOR_ID);
|
||||
PRINT (" subdevice ID = 0x%.4x\n", word, PCI_CB_SUBSYSTEM_ID);
|
||||
PRINT (" PC Card 16bit base address = 0x%.8x\n", dword, PCI_CB_LEGACY_MODE_BASE);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unknown header\n");
|
||||
break;
|
||||
}
|
||||
|
||||
#undef PRINT
|
||||
#undef PRINT2
|
||||
}
|
||||
|
||||
/* Convert the "bus.device.function" identifier into a number.
|
||||
*/
|
||||
static pci_dev_t get_pci_dev(char* name)
|
||||
{
|
||||
char cnum[12];
|
||||
int len, i, iold, n;
|
||||
int bdfs[3] = {0,0,0};
|
||||
|
||||
len = strlen(name);
|
||||
if (len > 8)
|
||||
return -1;
|
||||
for (i = 0, iold = 0, n = 0; i < len; i++) {
|
||||
if (name[i] == '.') {
|
||||
memcpy(cnum, &name[iold], i - iold);
|
||||
cnum[i - iold] = '\0';
|
||||
bdfs[n++] = simple_strtoul(cnum, NULL, 16);
|
||||
iold = i + 1;
|
||||
}
|
||||
}
|
||||
strcpy(cnum, &name[iold]);
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
bdfs[n] = simple_strtoul(cnum, NULL, 16);
|
||||
return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]);
|
||||
}
|
||||
|
||||
static int pci_cfg_display(pci_dev_t bdf, ulong addr, ulong size, ulong length)
|
||||
{
|
||||
#define DISP_LINE_LEN 16
|
||||
ulong i, nbytes, linebytes;
|
||||
int rc = 0;
|
||||
|
||||
if (length == 0)
|
||||
length = 0x40 / size; /* Standard PCI configuration space */
|
||||
|
||||
/* Print the lines.
|
||||
* once, and all accesses are with the specified bus width.
|
||||
*/
|
||||
nbytes = length * size;
|
||||
do {
|
||||
uint val4;
|
||||
ushort val2;
|
||||
u_char val1;
|
||||
|
||||
printf("%08lx:", addr);
|
||||
linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
|
||||
for (i=0; i<linebytes; i+= size) {
|
||||
if (size == 4) {
|
||||
pci_read_config_dword(bdf, addr, &val4);
|
||||
printf(" %08x", val4);
|
||||
} else if (size == 2) {
|
||||
pci_read_config_word(bdf, addr, &val2);
|
||||
printf(" %04x", val2);
|
||||
} else {
|
||||
pci_read_config_byte(bdf, addr, &val1);
|
||||
printf(" %02x", val1);
|
||||
}
|
||||
addr += size;
|
||||
}
|
||||
printf("\n");
|
||||
nbytes -= linebytes;
|
||||
if (ctrlc()) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
} while (nbytes > 0);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value)
|
||||
{
|
||||
if (size == 4) {
|
||||
pci_write_config_dword(bdf, addr, value);
|
||||
}
|
||||
else if (size == 2) {
|
||||
ushort val = value & 0xffff;
|
||||
pci_write_config_word(bdf, addr, val);
|
||||
}
|
||||
else {
|
||||
u_char val = value & 0xff;
|
||||
pci_write_config_byte(bdf, addr, val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag)
|
||||
{
|
||||
ulong i;
|
||||
int nbytes;
|
||||
extern char console_buffer[];
|
||||
uint val4;
|
||||
ushort val2;
|
||||
u_char val1;
|
||||
|
||||
/* Print the address, followed by value. Then accept input for
|
||||
* the next value. A non-converted value exits.
|
||||
*/
|
||||
do {
|
||||
printf("%08lx:", addr);
|
||||
if (size == 4) {
|
||||
pci_read_config_dword(bdf, addr, &val4);
|
||||
printf(" %08x", val4);
|
||||
}
|
||||
else if (size == 2) {
|
||||
pci_read_config_word(bdf, addr, &val2);
|
||||
printf(" %04x", val2);
|
||||
}
|
||||
else {
|
||||
pci_read_config_byte(bdf, addr, &val1);
|
||||
printf(" %02x", val1);
|
||||
}
|
||||
|
||||
nbytes = readline (" ? ");
|
||||
if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
|
||||
/* <CR> pressed as only input, don't modify current
|
||||
* location and move to next. "-" pressed will go back.
|
||||
*/
|
||||
if (incrflag)
|
||||
addr += nbytes ? -size : size;
|
||||
nbytes = 1;
|
||||
#ifdef CONFIG_BOOT_RETRY_TIME
|
||||
reset_cmd_timeout(); /* good enough to not time out */
|
||||
#endif
|
||||
}
|
||||
#ifdef CONFIG_BOOT_RETRY_TIME
|
||||
else if (nbytes == -2) {
|
||||
break; /* timed out, exit the command */
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
char *endp;
|
||||
i = simple_strtoul(console_buffer, &endp, 16);
|
||||
nbytes = endp - console_buffer;
|
||||
if (nbytes) {
|
||||
#ifdef CONFIG_BOOT_RETRY_TIME
|
||||
/* good enough to not time out
|
||||
*/
|
||||
reset_cmd_timeout();
|
||||
#endif
|
||||
pci_cfg_write (bdf, addr, size, i);
|
||||
if (incrflag)
|
||||
addr += size;
|
||||
}
|
||||
}
|
||||
} while (nbytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PCI Configuration Space access commands
|
||||
*
|
||||
* Syntax:
|
||||
* pci display[.b, .w, .l] bus.device.function} [addr] [len]
|
||||
* pci next[.b, .w, .l] bus.device.function [addr]
|
||||
* pci modify[.b, .w, .l] bus.device.function [addr]
|
||||
* pci write[.b, .w, .l] bus.device.function addr value
|
||||
*/
|
||||
int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr = 0, value = 0, size = 0;
|
||||
pci_dev_t bdf = 0;
|
||||
char cmd = 's';
|
||||
|
||||
if (argc > 1)
|
||||
cmd = argv[1][0];
|
||||
|
||||
switch (cmd) {
|
||||
case 'd': /* display */
|
||||
case 'n': /* next */
|
||||
case 'm': /* modify */
|
||||
case 'w': /* write */
|
||||
/* Check for a size specification. */
|
||||
size = cmd_get_data_size(argv[1], 4);
|
||||
if (argc > 3)
|
||||
addr = simple_strtoul(argv[3], NULL, 16);
|
||||
if (argc > 4)
|
||||
value = simple_strtoul(argv[4], NULL, 16);
|
||||
case 'h': /* header */
|
||||
if (argc < 3)
|
||||
goto usage;
|
||||
if ((bdf = get_pci_dev(argv[2])) == -1)
|
||||
return 1;
|
||||
break;
|
||||
default: /* scan bus */
|
||||
value = 1; /* short listing */
|
||||
bdf = 0; /* bus number */
|
||||
if (argc > 1) {
|
||||
if (argv[argc-1][0] == 'l') {
|
||||
value = 0;
|
||||
argc--;
|
||||
}
|
||||
if (argc > 1)
|
||||
bdf = simple_strtoul(argv[1], NULL, 16);
|
||||
}
|
||||
pciinfo(bdf, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (argv[1][0]) {
|
||||
case 'h': /* header */
|
||||
pci_header_show(bdf);
|
||||
return 0;
|
||||
case 'd': /* display */
|
||||
return pci_cfg_display(bdf, addr, size, value);
|
||||
case 'n': /* next */
|
||||
if (argc < 4)
|
||||
goto usage;
|
||||
return pci_cfg_modify(bdf, addr, size, value, 0);
|
||||
case 'm': /* modify */
|
||||
if (argc < 4)
|
||||
goto usage;
|
||||
return pci_cfg_modify(bdf, addr, size, value, 1);
|
||||
case 'w': /* write */
|
||||
if (argc < 5)
|
||||
goto usage;
|
||||
return pci_cfg_write(bdf, addr, size, value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
usage:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
pci, 5, 1, do_pci,
|
||||
"pci - list and access PCI Configuration Space\n",
|
||||
"[bus] [long]\n"
|
||||
" - short or long list of PCI devices on bus 'bus'\n"
|
||||
"pci header b.d.f\n"
|
||||
" - show header of PCI device 'bus.device.function'\n"
|
||||
"pci display[.b, .w, .l] b.d.f [address] [# of objects]\n"
|
||||
" - display PCI configuration space (CFG)\n"
|
||||
"pci next[.b, .w, .l] b.d.f address\n"
|
||||
" - modify, read and keep CFG address\n"
|
||||
"pci modify[.b, .w, .l] b.d.f address\n"
|
||||
" - modify, auto increment CFG address\n"
|
||||
"pci write[.b, .w, .l] b.d.f address value\n"
|
||||
" - write to CFG address\n"
|
||||
);
|
||||
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_PCI) */
|
||||
|
||||
#endif /* CONFIG_PCI */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Marc Singer, elf@buici.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Port I/O Functions
|
||||
*
|
||||
* Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_PORTIO)
|
||||
|
||||
extern int cmd_get_data_size (char *arg, int default_size);
|
||||
|
||||
/* Display values from last command.
|
||||
* Memory modify remembered values are different from display memory.
|
||||
*/
|
||||
static uint in_last_addr, in_last_size;
|
||||
static uint out_last_addr, out_last_size, out_last_value;
|
||||
|
||||
|
||||
int do_portio_out (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
uint addr = out_last_addr;
|
||||
uint size = out_last_size;
|
||||
uint value = out_last_value;
|
||||
|
||||
if (argc != 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0) {
|
||||
/* New command specified. Check for a size specification.
|
||||
* Defaults to long if no or incorrect specification.
|
||||
*/
|
||||
size = cmd_get_data_size (argv[0], 1);
|
||||
addr = simple_strtoul (argv[1], NULL, 16);
|
||||
value = simple_strtoul (argv[2], NULL, 16);
|
||||
}
|
||||
#if defined (CONFIG_X86)
|
||||
|
||||
{
|
||||
unsigned short port = addr;
|
||||
|
||||
switch (size) {
|
||||
default:
|
||||
case 1:
|
||||
{
|
||||
unsigned char ch = value;
|
||||
__asm__ volatile ("out %0, %%dx"::"a" (ch), "d" (port));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
unsigned short w = value;
|
||||
__asm__ volatile ("out %0, %%dx"::"a" (w), "d" (port));
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
__asm__ volatile ("out %0, %%dx"::"a" (value), "d" (port));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_X86 */
|
||||
|
||||
out_last_addr = addr;
|
||||
out_last_size = size;
|
||||
out_last_value = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
out, 3, 1, do_portio_out,
|
||||
"out - write datum to IO port\n",
|
||||
"[.b, .w, .l] port value\n - output to IO port\n"
|
||||
);
|
||||
|
||||
int do_portio_in (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
uint addr = in_last_addr;
|
||||
uint size = in_last_size;
|
||||
|
||||
if (argc != 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0) {
|
||||
/* New command specified. Check for a size specification.
|
||||
* Defaults to long if no or incorrect specification.
|
||||
*/
|
||||
size = cmd_get_data_size (argv[0], 1);
|
||||
addr = simple_strtoul (argv[1], NULL, 16);
|
||||
}
|
||||
#if defined (CONFIG_X86)
|
||||
|
||||
{
|
||||
unsigned short port = addr;
|
||||
|
||||
switch (size) {
|
||||
default:
|
||||
case 1:
|
||||
{
|
||||
unsigned char ch;
|
||||
__asm__ volatile ("in %%dx, %0":"=a" (ch):"d" (port));
|
||||
|
||||
printf (" %02x\n", ch);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
unsigned short w;
|
||||
__asm__ volatile ("in %%dx, %0":"=a" (w):"d" (port));
|
||||
|
||||
printf (" %04x\n", w);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
unsigned long l;
|
||||
__asm__ volatile ("in %%dx, %0":"=a" (l):"d" (port));
|
||||
|
||||
printf (" %08lx\n", l);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_X86 */
|
||||
|
||||
in_last_addr = addr;
|
||||
in_last_size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
in, 2, 1, do_portio_in,
|
||||
"in - read data from an IO port\n",
|
||||
"[.b, .w, .l] port\n"
|
||||
" - read datum from IO port\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_PORTIO */
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* Subodh Nijsure, SkyStream Networks, snijsure@skystream.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#if defined(CONFIG_8xx)
|
||||
#include <mpc8xx.h>
|
||||
#elif defined (CONFIG_405GP) || defined(CONFIG_405EP)
|
||||
#include <asm/processor.h>
|
||||
#elif defined (CONFIG_5xx)
|
||||
#include <mpc5xx.h>
|
||||
#elif defined (CONFIG_MPC5200)
|
||||
#include <mpc5xxx.h>
|
||||
#endif
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_REGINFO)
|
||||
|
||||
int do_reginfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
#if defined(CONFIG_8xx)
|
||||
volatile immap_t *immap = (immap_t *)CFG_IMMR;
|
||||
volatile memctl8xx_t *memctl = &immap->im_memctl;
|
||||
volatile sysconf8xx_t *sysconf = &immap->im_siu_conf;
|
||||
volatile sit8xx_t *timers = &immap->im_sit;
|
||||
|
||||
/* Hopefully more PowerPC knowledgable people will add code to display
|
||||
* other useful registers
|
||||
*/
|
||||
|
||||
printf ("\nSystem Configuration registers\n"
|
||||
|
||||
"\tIMMR\t0x%08X\n", get_immr(0));
|
||||
|
||||
printf("\tSIUMCR\t0x%08X", sysconf->sc_siumcr);
|
||||
printf("\tSYPCR\t0x%08X\n",sysconf->sc_sypcr);
|
||||
|
||||
printf("\tSWT\t0x%08X", sysconf->sc_swt);
|
||||
printf("\tSWSR\t0x%04X\n", sysconf->sc_swsr);
|
||||
|
||||
printf("\tSIPEND\t0x%08X\tSIMASK\t0x%08X\n",
|
||||
sysconf->sc_sipend, sysconf->sc_simask);
|
||||
printf("\tSIEL\t0x%08X\tSIVEC\t0x%08X\n",
|
||||
sysconf->sc_siel, sysconf->sc_sivec);
|
||||
printf("\tTESR\t0x%08X\tSDCR\t0x%08X\n",
|
||||
sysconf->sc_tesr, sysconf->sc_sdcr);
|
||||
|
||||
printf ("Memory Controller Registers\n"
|
||||
|
||||
"\tBR0\t0x%08X\tOR0\t0x%08X \n", memctl->memc_br0, memctl->memc_or0);
|
||||
printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", memctl->memc_br1, memctl->memc_or1);
|
||||
printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", memctl->memc_br2, memctl->memc_or2);
|
||||
printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", memctl->memc_br3, memctl->memc_or3);
|
||||
printf("\tBR4\t0x%08X\tOR4\t0x%08X \n", memctl->memc_br4, memctl->memc_or4);
|
||||
printf("\tBR5\t0x%08X\tOR5\t0x%08X \n", memctl->memc_br5, memctl->memc_or5);
|
||||
printf("\tBR6\t0x%08X\tOR6\t0x%08X \n", memctl->memc_br6, memctl->memc_or6);
|
||||
printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", memctl->memc_br7, memctl->memc_or7);
|
||||
printf ("\n"
|
||||
"\tmamr\t0x%08X\tmbmr\t0x%08X \n",
|
||||
memctl->memc_mamr, memctl->memc_mbmr );
|
||||
printf("\tmstat\t0x%08X\tmptpr\t0x%08X \n",
|
||||
memctl->memc_mstat, memctl->memc_mptpr );
|
||||
printf("\tmdr\t0x%08X \n", memctl->memc_mdr);
|
||||
|
||||
printf ("\nSystem Integration Timers\n"
|
||||
"\tTBSCR\t0x%08X\tRTCSC\t0x%08X \n",
|
||||
timers->sit_tbscr, timers->sit_rtcsc);
|
||||
printf("\tPISCR\t0x%08X \n", timers->sit_piscr);
|
||||
|
||||
/*
|
||||
* May be some CPM info here?
|
||||
*/
|
||||
|
||||
#elif defined (CONFIG_405GP)
|
||||
printf ("\n405GP registers; MSR=%08x\n",mfmsr());
|
||||
printf ("\nUniversal Interrupt Controller Regs\n"
|
||||
"uicsr uicsrs uicer uiccr uicpr uictr uicmsr uicvr uicvcr"
|
||||
"\n"
|
||||
"%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
mfdcr(uicsr),
|
||||
mfdcr(uicsrs),
|
||||
mfdcr(uicer),
|
||||
mfdcr(uiccr),
|
||||
mfdcr(uicpr),
|
||||
mfdcr(uictr),
|
||||
mfdcr(uicmsr),
|
||||
mfdcr(uicvr),
|
||||
mfdcr(uicvcr));
|
||||
|
||||
puts ("\nMemory (SDRAM) Configuration\n"
|
||||
"besra besrsa besrb besrsb bear mcopt1 rtr pmit\n");
|
||||
|
||||
mtdcr(memcfga,mem_besra); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_besrsa); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_besrb); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_besrsb); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_bear); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_mcopt1); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_rtr); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_pmit); printf ("%08x ", mfdcr(memcfgd));
|
||||
|
||||
puts ("\n"
|
||||
"mb0cf mb1cf mb2cf mb3cf sdtr1 ecccf eccerr\n");
|
||||
mtdcr(memcfga,mem_mb0cf); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_mb1cf); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_mb2cf); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_mb3cf); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_sdtr1); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_ecccf); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_eccerr); printf ("%08x ", mfdcr(memcfgd));
|
||||
|
||||
printf ("\n\n"
|
||||
"DMA Channels\n"
|
||||
"dmasr dmasgc dmaadr\n"
|
||||
"%08x %08x %08x\n"
|
||||
"dmacr_0 dmact_0 dmada_0 dmasa_0 dmasb_0\n"
|
||||
"%08x %08x %08x %08x %08x\n"
|
||||
"dmacr_1 dmact_1 dmada_1 dmasa_1 dmasb_1\n"
|
||||
"%08x %08x %08x %08x %08x\n",
|
||||
mfdcr(dmasr), mfdcr(dmasgc),mfdcr(dmaadr),
|
||||
mfdcr(dmacr0), mfdcr(dmact0),mfdcr(dmada0), mfdcr(dmasa0), mfdcr(dmasb0),
|
||||
mfdcr(dmacr1), mfdcr(dmact1),mfdcr(dmada1), mfdcr(dmasa1), mfdcr(dmasb1));
|
||||
|
||||
printf (
|
||||
"dmacr_2 dmact_2 dmada_2 dmasa_2 dmasb_2\n" "%08x %08x %08x %08x %08x\n"
|
||||
"dmacr_3 dmact_3 dmada_3 dmasa_3 dmasb_3\n" "%08x %08x %08x %08x %08x\n",
|
||||
mfdcr(dmacr2), mfdcr(dmact2),mfdcr(dmada2), mfdcr(dmasa2), mfdcr(dmasb2),
|
||||
mfdcr(dmacr3), mfdcr(dmact3),mfdcr(dmada3), mfdcr(dmasa3), mfdcr(dmasb3) );
|
||||
|
||||
puts ("\n"
|
||||
"External Bus\n"
|
||||
"pbear pbesr0 pbesr1 epcr\n");
|
||||
mtdcr(ebccfga,pbear); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pbesr0); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pbesr1); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,epcr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
|
||||
puts ("\n"
|
||||
"pb0cr pb0ap pb1cr pb1ap pb2cr pb2ap pb3cr pb3ap\n");
|
||||
mtdcr(ebccfga,pb0cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb0ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb1cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb1ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb2cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb2ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb3cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb3ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
|
||||
puts ("\n"
|
||||
"pb4cr pb4ap pb5cr bp5ap pb6cr pb6ap pb7cr pb7ap\n");
|
||||
mtdcr(ebccfga,pb4cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb4ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb5cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb5ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb6cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb6ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb7cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb7ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
|
||||
puts ("\n\n");
|
||||
|
||||
#elif defined(CONFIG_405EP)
|
||||
printf ("\n405EP registers; MSR=%08x\n",mfmsr());
|
||||
printf ("\nUniversal Interrupt Controller Regs\n"
|
||||
"uicsr uicer uiccr uicpr uictr uicmsr uicvr uicvcr"
|
||||
"\n"
|
||||
"%08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
mfdcr(uicsr),
|
||||
mfdcr(uicer),
|
||||
mfdcr(uiccr),
|
||||
mfdcr(uicpr),
|
||||
mfdcr(uictr),
|
||||
mfdcr(uicmsr),
|
||||
mfdcr(uicvr),
|
||||
mfdcr(uicvcr));
|
||||
|
||||
puts ("\nMemory (SDRAM) Configuration\n"
|
||||
"mcopt1 rtr pmit mb0cf mb1cf sdtr1\n");
|
||||
|
||||
mtdcr(memcfga,mem_mcopt1); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_rtr); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_pmit); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_mb0cf); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_mb1cf); printf ("%08x ", mfdcr(memcfgd));
|
||||
mtdcr(memcfga,mem_sdtr1); printf ("%08x ", mfdcr(memcfgd));
|
||||
|
||||
printf ("\n\n"
|
||||
"DMA Channels\n"
|
||||
"dmasr dmasgc dmaadr\n" "%08x %08x %08x\n"
|
||||
"dmacr_0 dmact_0 dmada_0 dmasa_0 dmasb_0\n" "%08x %08x %08x %08x %08x\n"
|
||||
"dmacr_1 dmact_1 dmada_1 dmasa_1 dmasb_1\n" "%08x %08x %08x %08x %08x\n",
|
||||
mfdcr(dmasr), mfdcr(dmasgc),mfdcr(dmaadr),
|
||||
mfdcr(dmacr0), mfdcr(dmact0),mfdcr(dmada0), mfdcr(dmasa0), mfdcr(dmasb0),
|
||||
mfdcr(dmacr1), mfdcr(dmact1),mfdcr(dmada1), mfdcr(dmasa1), mfdcr(dmasb1));
|
||||
|
||||
printf (
|
||||
"dmacr_2 dmact_2 dmada_2 dmasa_2 dmasb_2\n" "%08x %08x %08x %08x %08x\n"
|
||||
"dmacr_3 dmact_3 dmada_3 dmasa_3 dmasb_3\n" "%08x %08x %08x %08x %08x\n",
|
||||
mfdcr(dmacr2), mfdcr(dmact2),mfdcr(dmada2), mfdcr(dmasa2), mfdcr(dmasb2),
|
||||
mfdcr(dmacr3), mfdcr(dmact3),mfdcr(dmada3), mfdcr(dmasa3), mfdcr(dmasb3) );
|
||||
|
||||
puts ("\n"
|
||||
"External Bus\n"
|
||||
"pbear pbesr0 pbesr1 epcr\n");
|
||||
mtdcr(ebccfga,pbear); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pbesr0); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pbesr1); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,epcr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
|
||||
puts ("\n"
|
||||
"pb0cr pb0ap pb1cr pb1ap pb2cr pb2ap pb3cr pb3ap\n");
|
||||
mtdcr(ebccfga,pb0cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb0ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb1cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb1ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb2cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb2ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb3cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb3ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
|
||||
puts ("\n"
|
||||
"pb4cr pb4ap\n");
|
||||
mtdcr(ebccfga,pb4cr); printf ("%08x ", mfdcr(ebccfgd));
|
||||
mtdcr(ebccfga,pb4ap); printf ("%08x ", mfdcr(ebccfgd));
|
||||
|
||||
puts ("\n\n");
|
||||
#elif defined(CONFIG_5xx)
|
||||
|
||||
volatile immap_t *immap = (immap_t *)CFG_IMMR;
|
||||
volatile memctl5xx_t *memctl = &immap->im_memctl;
|
||||
volatile sysconf5xx_t *sysconf = &immap->im_siu_conf;
|
||||
volatile sit5xx_t *timers = &immap->im_sit;
|
||||
volatile car5xx_t *car = &immap->im_clkrst;
|
||||
volatile uimb5xx_t *uimb = &immap->im_uimb;
|
||||
|
||||
puts ("\nSystem Configuration registers\n");
|
||||
printf("\tIMMR\t0x%08X\tSIUMCR\t0x%08X \n", get_immr(0), sysconf->sc_siumcr);
|
||||
printf("\tSYPCR\t0x%08X\tSWSR\t0x%04X \n" ,sysconf->sc_sypcr, sysconf->sc_swsr);
|
||||
printf("\tSIPEND\t0x%08X\tSIMASK\t0x%08X \n", sysconf->sc_sipend, sysconf->sc_simask);
|
||||
printf("\tSIEL\t0x%08X\tSIVEC\t0x%08X \n", sysconf->sc_siel, sysconf->sc_sivec);
|
||||
printf("\tTESR\t0x%08X\n", sysconf->sc_tesr);
|
||||
|
||||
puts ("\nMemory Controller Registers\n");
|
||||
printf("\tBR0\t0x%08X\tOR0\t0x%08X \n", memctl->memc_br0, memctl->memc_or0);
|
||||
printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", memctl->memc_br1, memctl->memc_or1);
|
||||
printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", memctl->memc_br2, memctl->memc_or2);
|
||||
printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", memctl->memc_br3, memctl->memc_or3);
|
||||
printf("\tDMBR\t0x%08X\tDMOR\t0x%08X \n", memctl->memc_dmbr, memctl->memc_dmor );
|
||||
printf("\tMSTAT\t0x%08X\n", memctl->memc_mstat);
|
||||
|
||||
puts ("\nSystem Integration Timers\n");
|
||||
printf("\tTBSCR\t0x%08X\tRTCSC\t0x%08X \n", timers->sit_tbscr, timers->sit_rtcsc);
|
||||
printf("\tPISCR\t0x%08X \n", timers->sit_piscr);
|
||||
|
||||
puts ("\nClocks and Reset\n");
|
||||
printf("\tSCCR\t0x%08X\tPLPRCR\t0x%08X \n", car->car_sccr, car->car_plprcr);
|
||||
|
||||
puts ("\nU-Bus to IMB3 Bus Interface\n");
|
||||
printf("\tUMCR\t0x%08X\tUIPEND\t0x%08X \n", uimb->uimb_umcr, uimb->uimb_uipend);
|
||||
puts ("\n\n");
|
||||
|
||||
#elif defined(CONFIG_MPC5200)
|
||||
puts ("\nMPC5200 registers\n");
|
||||
printf ("MBAR=%08x\n", CFG_MBAR);
|
||||
puts ("Memory map registers\n");
|
||||
printf ("\tCS0: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS0_START,
|
||||
*(volatile ulong*)MPC5XXX_CS0_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS0_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x00010000) ? 1 : 0);
|
||||
printf ("\tCS1: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS1_START,
|
||||
*(volatile ulong*)MPC5XXX_CS1_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS1_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x00020000) ? 1 : 0);
|
||||
printf ("\tCS2: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS2_START,
|
||||
*(volatile ulong*)MPC5XXX_CS2_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS2_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x00040000) ? 1 : 0);
|
||||
printf ("\tCS3: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS3_START,
|
||||
*(volatile ulong*)MPC5XXX_CS3_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS3_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x00080000) ? 1 : 0);
|
||||
printf ("\tCS4: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS4_START,
|
||||
*(volatile ulong*)MPC5XXX_CS4_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS4_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x00100000) ? 1 : 0);
|
||||
printf ("\tCS5: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS5_START,
|
||||
*(volatile ulong*)MPC5XXX_CS5_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS5_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x00200000) ? 1 : 0);
|
||||
printf ("\tCS6: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS6_START,
|
||||
*(volatile ulong*)MPC5XXX_CS6_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS6_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x04000000) ? 1 : 0);
|
||||
printf ("\tCS7: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_CS7_START,
|
||||
*(volatile ulong*)MPC5XXX_CS7_STOP,
|
||||
*(volatile ulong*)MPC5XXX_CS7_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x08000000) ? 1 : 0);
|
||||
printf ("\tBOOTCS: start %08X\tstop %08X\tconfig %08X\ten %d\n",
|
||||
*(volatile ulong*)MPC5XXX_BOOTCS_START,
|
||||
*(volatile ulong*)MPC5XXX_BOOTCS_STOP,
|
||||
*(volatile ulong*)MPC5XXX_BOOTCS_CFG,
|
||||
(*(volatile ulong*)MPC5XXX_ADDECR & 0x02000000) ? 1 : 0);
|
||||
printf ("\tSDRAMCS0: %08X\n",
|
||||
*(volatile ulong*)MPC5XXX_SDRAM_CS0CFG);
|
||||
printf ("\tSDRAMCS0: %08X\n",
|
||||
*(volatile ulong*)MPC5XXX_SDRAM_CS1CFG);
|
||||
#endif /* CONFIG_MPC5200 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_REGINFO */
|
||||
|
||||
|
||||
/**************************************************/
|
||||
|
||||
#if ( defined(CONFIG_8xx) || defined(CONFIG_405GP) || \
|
||||
defined(CONFIG_405EP) || defined(CONFIG_MPC5200) ) && \
|
||||
(CONFIG_COMMANDS & CFG_CMD_REGINFO)
|
||||
|
||||
U_BOOT_CMD(
|
||||
reginfo, 2, 1, do_reginfo,
|
||||
"reginfo - print register information\n",
|
||||
);
|
||||
#endif
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* (C) Copyright 2003 - 2004
|
||||
* Sysgo Real-Time Solutions, AG <www.elinos.com>
|
||||
* Pavel Bartusek <pba@sysgo.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reiserfs support
|
||||
*/
|
||||
#include <common.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_REISER)
|
||||
#include <config.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <reiserfs.h>
|
||||
|
||||
#ifndef CONFIG_DOS_PARTITION
|
||||
#error DOS partition support must be selected
|
||||
#endif
|
||||
|
||||
/* #define REISER_DEBUG */
|
||||
|
||||
#ifdef REISER_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
static block_dev_desc_t *get_dev (char* ifname, int dev)
|
||||
{
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_IDE)
|
||||
if (strncmp(ifname,"ide",3)==0) {
|
||||
extern block_dev_desc_t * ide_get_dev(int dev);
|
||||
return((dev >= CFG_IDE_MAXDEVICE) ? NULL : ide_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
|
||||
if (strncmp(ifname,"scsi",4)==0) {
|
||||
extern block_dev_desc_t * scsi_get_dev(int dev);
|
||||
return((dev >= CFG_SCSI_MAXDEVICE) ? NULL : scsi_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if ((CONFIG_COMMANDS & CFG_CMD_USB) && defined(CONFIG_USB_STORAGE))
|
||||
if (strncmp(ifname,"usb",3)==0) {
|
||||
extern block_dev_desc_t * usb_stor_get_dev(int dev);
|
||||
return((dev >= USB_MAX_STOR_DEV) ? NULL : usb_stor_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_MMC)
|
||||
if (strncmp(ifname,"mmc",3)==0) {
|
||||
extern block_dev_desc_t * mmc_get_dev(int dev);
|
||||
return((dev >= 1) ? NULL : mmc_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_SYSTEMACE)
|
||||
if (strcmp(ifname,"ace")==0) {
|
||||
extern block_dev_desc_t * systemace_get_dev(int dev);
|
||||
return((dev >= 1) ? NULL : systemace_get_dev(dev));
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int do_reiserls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *filename = "/";
|
||||
int dev=0;
|
||||
int part=1;
|
||||
char *ep;
|
||||
block_dev_desc_t *dev_desc=NULL;
|
||||
int part_length;
|
||||
|
||||
if (argc < 3) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
dev = (int)simple_strtoul (argv[2], &ep, 16);
|
||||
dev_desc=get_dev(argv[1],dev);
|
||||
|
||||
if (dev_desc == NULL) {
|
||||
printf ("\n** Block device %s %d not supported\n", argv[1], dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*ep) {
|
||||
if (*ep != ':') {
|
||||
puts ("\n** Invalid boot device, use `dev[:part]' **\n");
|
||||
return 1;
|
||||
}
|
||||
part = (int)simple_strtoul(++ep, NULL, 16);
|
||||
}
|
||||
|
||||
if (argc == 4) {
|
||||
filename = argv[3];
|
||||
}
|
||||
|
||||
PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
|
||||
|
||||
if ((part_length = reiserfs_set_blk_dev(dev_desc, part)) == 0) {
|
||||
printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!reiserfs_mount(part_length)) {
|
||||
printf ("** Bad Reisefs partition or disk - %s %d:%d **\n", argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (reiserfs_ls (filename)) {
|
||||
printf ("** Error reiserfs_ls() **\n");
|
||||
return 1;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
reiserls, 4, 1, do_reiserls,
|
||||
"reiserls- list files in a directory (default /)\n",
|
||||
"<interface> <dev[:part]> [directory]\n"
|
||||
" - list files from 'dev' on 'interface' in a 'directory'\n"
|
||||
);
|
||||
|
||||
/******************************************************************************
|
||||
* Reiserfs boot command intepreter. Derived from diskboot
|
||||
*/
|
||||
int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *filename = NULL;
|
||||
char *ep;
|
||||
int dev, part = 0;
|
||||
ulong addr = 0, part_length, filelen;
|
||||
disk_partition_t info;
|
||||
block_dev_desc_t *dev_desc = NULL;
|
||||
char buf [12];
|
||||
unsigned long count;
|
||||
char *addr_str;
|
||||
|
||||
switch (argc) {
|
||||
case 3:
|
||||
addr_str = getenv("loadaddr");
|
||||
if (addr_str != NULL) {
|
||||
addr = simple_strtoul (addr_str, NULL, 16);
|
||||
} else {
|
||||
addr = CFG_LOAD_ADDR;
|
||||
}
|
||||
filename = getenv ("bootfile");
|
||||
count = 0;
|
||||
break;
|
||||
case 4:
|
||||
addr = simple_strtoul (argv[3], NULL, 16);
|
||||
filename = getenv ("bootfile");
|
||||
count = 0;
|
||||
break;
|
||||
case 5:
|
||||
addr = simple_strtoul (argv[3], NULL, 16);
|
||||
filename = argv[4];
|
||||
count = 0;
|
||||
break;
|
||||
case 6:
|
||||
addr = simple_strtoul (argv[3], NULL, 16);
|
||||
filename = argv[4];
|
||||
count = simple_strtoul (argv[5], NULL, 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
puts ("\n** No boot file defined **\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = (int)simple_strtoul (argv[2], &ep, 16);
|
||||
dev_desc=get_dev(argv[1],dev);
|
||||
if (dev_desc==NULL) {
|
||||
printf ("\n** Block device %s %d not supported\n", argv[1], dev);
|
||||
return 1;
|
||||
}
|
||||
if (*ep) {
|
||||
if (*ep != ':') {
|
||||
puts ("\n** Invalid boot device, use `dev[:part]' **\n");
|
||||
return 1;
|
||||
}
|
||||
part = (int)simple_strtoul(++ep, NULL, 16);
|
||||
}
|
||||
|
||||
PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part);
|
||||
|
||||
if (part != 0) {
|
||||
if (get_partition_info (dev_desc, part, &info)) {
|
||||
printf ("** Bad partition %d **\n", part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
|
||||
printf ("\n** Invalid partition type \"%.32s\""
|
||||
" (expect \"" BOOT_PART_TYPE "\")\n",
|
||||
info.type);
|
||||
return 1;
|
||||
}
|
||||
PRINTF ("\nLoading from block device %s device %d, partition %d: "
|
||||
"Name: %.32s Type: %.32s File:%s\n",
|
||||
argv[1], dev, part, info.name, info.type, filename);
|
||||
} else {
|
||||
PRINTF ("\nLoading from block device %s device %d, File:%s\n",
|
||||
argv[1], dev, filename);
|
||||
}
|
||||
|
||||
|
||||
if ((part_length = reiserfs_set_blk_dev(dev_desc, part)) == 0) {
|
||||
printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!reiserfs_mount(part_length)) {
|
||||
printf ("** Bad Reisefs partition or disk - %s %d:%d **\n", argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
filelen = reiserfs_open(filename);
|
||||
if (filelen < 0) {
|
||||
printf("** File not found %s\n", filename);
|
||||
return 1;
|
||||
}
|
||||
if ((count < filelen) && (count != 0)) {
|
||||
filelen = count;
|
||||
}
|
||||
|
||||
if (reiserfs_read((char *)addr, filelen) != filelen) {
|
||||
printf("\n** Unable to read \"%s\" from %s %d:%d **\n", filename, argv[1], dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Loading ok, update default load address */
|
||||
load_addr = addr;
|
||||
|
||||
printf ("\n%ld bytes read\n", filelen);
|
||||
sprintf(buf, "%lX", filelen);
|
||||
setenv("filesize", buf);
|
||||
|
||||
return filelen;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
reiserload, 6, 0, do_reiserload,
|
||||
"reiserload- load binary file from a Reiser filesystem\n",
|
||||
"<interface> <dev[:part]> [addr] [filename] [bytes]\n"
|
||||
" - load binary file 'filename' from 'dev' on 'interface'\n"
|
||||
" to address 'addr' from dos filesystem\n"
|
||||
);
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_REISER */
|
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI support.
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/processor.h>
|
||||
#include <scsi.h>
|
||||
#include <image.h>
|
||||
#include <pci.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
|
||||
|
||||
#ifdef CONFIG_SCSI_SYM53C8XX
|
||||
#define SCSI_VEND_ID 0x1000
|
||||
#ifndef CONFIG_SCSI_DEV_ID
|
||||
#define SCSI_DEV_ID 0x0001
|
||||
#else
|
||||
#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID
|
||||
#endif
|
||||
#else
|
||||
#error CONFIG_SCSI_SYM53C8XX must be defined
|
||||
#endif
|
||||
|
||||
|
||||
static ccb tempccb; /* temporary scsi command buffer */
|
||||
|
||||
static unsigned char tempbuff[512]; /* temporary data buffer */
|
||||
|
||||
static int scsi_max_devs; /* number of highest available scsi device */
|
||||
|
||||
static int scsi_curr_dev; /* current device */
|
||||
|
||||
static block_dev_desc_t scsi_dev_desc[CFG_SCSI_MAX_DEVICE];
|
||||
|
||||
/********************************************************************************
|
||||
* forward declerations of some Setup Routines
|
||||
*/
|
||||
void scsi_setup_test_unit_ready(ccb * pccb);
|
||||
void scsi_setup_read_capacity(ccb * pccb);
|
||||
void scsi_setup_read6(ccb * pccb, unsigned long start, unsigned short blocks);
|
||||
void scsi_setup_read_ext(ccb * pccb, unsigned long start, unsigned short blocks);
|
||||
void scsi_setup_inquiry(ccb * pccb);
|
||||
void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len);
|
||||
|
||||
|
||||
ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer);
|
||||
|
||||
|
||||
/*********************************************************************************
|
||||
* (re)-scan the scsi bus and reports scsi device info
|
||||
* to the user if mode = 1
|
||||
*/
|
||||
void scsi_scan(int mode)
|
||||
{
|
||||
unsigned char i,perq,modi,lun;
|
||||
unsigned long capacity,blksz;
|
||||
ccb* pccb=(ccb *)&tempccb;
|
||||
|
||||
if(mode==1) {
|
||||
printf("scanning bus for devices...\n");
|
||||
}
|
||||
for(i=0;i<CFG_SCSI_MAX_DEVICE;i++) {
|
||||
scsi_dev_desc[i].target=0xff;
|
||||
scsi_dev_desc[i].lun=0xff;
|
||||
scsi_dev_desc[i].lba=0;
|
||||
scsi_dev_desc[i].blksz=0;
|
||||
scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN;
|
||||
scsi_dev_desc[i].vendor[0]=0;
|
||||
scsi_dev_desc[i].product[0]=0;
|
||||
scsi_dev_desc[i].revision[0]=0;
|
||||
scsi_dev_desc[i].removable=FALSE;
|
||||
scsi_dev_desc[i].if_type=IF_TYPE_SCSI;
|
||||
scsi_dev_desc[i].dev=i;
|
||||
scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN;
|
||||
scsi_dev_desc[i].block_read=scsi_read;
|
||||
}
|
||||
scsi_max_devs=0;
|
||||
for(i=0;i<CFG_SCSI_MAX_SCSI_ID;i++) {
|
||||
pccb->target=i;
|
||||
for(lun=0;lun<CFG_SCSI_MAX_LUN;lun++) {
|
||||
pccb->lun=lun;
|
||||
pccb->pdata=(unsigned char *)&tempbuff;
|
||||
pccb->datalen=512;
|
||||
scsi_setup_inquiry(pccb);
|
||||
if(scsi_exec(pccb)!=TRUE) {
|
||||
if(pccb->contr_stat==SCSI_SEL_TIME_OUT) {
|
||||
debug ("Selection timeout ID %d\n",pccb->target);
|
||||
continue; /* selection timeout => assuming no device present */
|
||||
}
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
perq=tempbuff[0];
|
||||
modi=tempbuff[1];
|
||||
if((perq & 0x1f)==0x1f) {
|
||||
continue; /* skip unknown devices */
|
||||
}
|
||||
if((modi&0x80)==0x80) /* drive is removable */
|
||||
scsi_dev_desc[scsi_max_devs].removable=TRUE;
|
||||
/* get info for this device */
|
||||
scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].vendor[0],&tempbuff[8],8);
|
||||
scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].product[0],&tempbuff[16],16);
|
||||
scsi_ident_cpy(&scsi_dev_desc[scsi_max_devs].revision[0],&tempbuff[32],4);
|
||||
scsi_dev_desc[scsi_max_devs].target=pccb->target;
|
||||
scsi_dev_desc[scsi_max_devs].lun=pccb->lun;
|
||||
|
||||
pccb->datalen=0;
|
||||
scsi_setup_test_unit_ready(pccb);
|
||||
if(scsi_exec(pccb)!=TRUE) {
|
||||
if(scsi_dev_desc[scsi_max_devs].removable==TRUE) {
|
||||
scsi_dev_desc[scsi_max_devs].type=perq;
|
||||
goto removable;
|
||||
}
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
pccb->datalen=8;
|
||||
scsi_setup_read_capacity(pccb);
|
||||
if(scsi_exec(pccb)!=TRUE) {
|
||||
scsi_print_error(pccb);
|
||||
continue;
|
||||
}
|
||||
capacity=((unsigned long)tempbuff[0]<<24)|((unsigned long)tempbuff[1]<<16)|
|
||||
((unsigned long)tempbuff[2]<<8)|((unsigned long)tempbuff[3]);
|
||||
blksz=((unsigned long)tempbuff[4]<<24)|((unsigned long)tempbuff[5]<<16)|
|
||||
((unsigned long)tempbuff[6]<<8)|((unsigned long)tempbuff[7]);
|
||||
scsi_dev_desc[scsi_max_devs].lba=capacity;
|
||||
scsi_dev_desc[scsi_max_devs].blksz=blksz;
|
||||
scsi_dev_desc[scsi_max_devs].type=perq;
|
||||
init_part(&scsi_dev_desc[scsi_max_devs]);
|
||||
removable:
|
||||
if(mode==1) {
|
||||
printf (" Device %d: ", scsi_max_devs);
|
||||
dev_print(&scsi_dev_desc[scsi_max_devs]);
|
||||
} /* if mode */
|
||||
scsi_max_devs++;
|
||||
} /* next LUN */
|
||||
}
|
||||
if(scsi_max_devs>0)
|
||||
scsi_curr_dev=0;
|
||||
else
|
||||
scsi_curr_dev=-1;
|
||||
}
|
||||
|
||||
|
||||
void scsi_init(void)
|
||||
{
|
||||
int busdevfunc;
|
||||
|
||||
busdevfunc=pci_find_device(SCSI_VEND_ID,SCSI_DEV_ID,0); /* get PCI Device ID */
|
||||
if(busdevfunc==-1) {
|
||||
printf("Error SCSI Controller (%04X,%04X) not found\n",SCSI_VEND_ID,SCSI_DEV_ID);
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n",SCSI_VEND_ID,SCSI_DEV_ID,(busdevfunc>>16)&0xFF,(busdevfunc>>11)&0x1F,(busdevfunc>>8)&0x7);
|
||||
}
|
||||
#endif
|
||||
scsi_low_level_init(busdevfunc);
|
||||
scsi_scan(1);
|
||||
}
|
||||
|
||||
block_dev_desc_t * scsi_get_dev(int dev)
|
||||
{
|
||||
return((block_dev_desc_t *)&scsi_dev_desc[dev]);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* scsi boot command intepreter. Derived from diskboot
|
||||
*/
|
||||
int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *boot_device = NULL;
|
||||
char *ep;
|
||||
int dev, part = 0;
|
||||
ulong addr, cnt, checksum;
|
||||
disk_partition_t info;
|
||||
image_header_t *hdr;
|
||||
int rcode = 0;
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
addr = CFG_LOAD_ADDR;
|
||||
boot_device = getenv ("bootdevice");
|
||||
break;
|
||||
case 2:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = getenv ("bootdevice");
|
||||
break;
|
||||
case 3:
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
boot_device = argv[2];
|
||||
break;
|
||||
default:
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!boot_device) {
|
||||
puts ("\n** No boot device **\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = simple_strtoul(boot_device, &ep, 16);
|
||||
printf("booting from dev %d\n",dev);
|
||||
if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
|
||||
printf ("\n** Device %d not available\n", dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*ep) {
|
||||
if (*ep != ':') {
|
||||
puts ("\n** Invalid boot device, use `dev[:part]' **\n");
|
||||
return 1;
|
||||
}
|
||||
part = simple_strtoul(++ep, NULL, 16);
|
||||
}
|
||||
if (get_partition_info (scsi_dev_desc, part, &info)) {
|
||||
printf("error reading partinfo\n");
|
||||
return 1;
|
||||
}
|
||||
if ((strncmp((char *)(info.type), BOOT_PART_TYPE, sizeof(info.type)) != 0) &&
|
||||
(strncmp((char *)(info.type), BOOT_PART_COMP, sizeof(info.type)) != 0)) {
|
||||
printf ("\n** Invalid partition type \"%.32s\""
|
||||
" (expect \"" BOOT_PART_TYPE "\")\n",
|
||||
info.type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf ("\nLoading from SCSI device %d, partition %d: "
|
||||
"Name: %.32s Type: %.32s\n",
|
||||
dev, part, info.name, info.type);
|
||||
|
||||
debug ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n",
|
||||
info.start, info.size, info.blksz);
|
||||
|
||||
if (scsi_read (dev, info.start, 1, (ulong *)addr) != 1) {
|
||||
printf ("** Read error on %d:%d\n", dev, part);
|
||||
return 1;
|
||||
}
|
||||
|
||||
hdr = (image_header_t *)addr;
|
||||
|
||||
if (ntohl(hdr->ih_magic) == IH_MAGIC) {
|
||||
printf("\n** Bad Magic Number **\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
checksum = ntohl(hdr->ih_hcrc);
|
||||
hdr->ih_hcrc = 0;
|
||||
|
||||
if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) {
|
||||
puts ("\n** Bad Header Checksum **\n");
|
||||
return 1;
|
||||
}
|
||||
hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */
|
||||
|
||||
print_image_hdr (hdr);
|
||||
cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t));
|
||||
cnt += info.blksz - 1;
|
||||
cnt /= info.blksz;
|
||||
cnt -= 1;
|
||||
|
||||
if (scsi_read (dev, info.start+1, cnt,
|
||||
(ulong *)(addr+info.blksz)) != cnt) {
|
||||
printf ("** Read error on %d:%d\n", dev, part);
|
||||
return 1;
|
||||
}
|
||||
/* Loading ok, update default load address */
|
||||
load_addr = addr;
|
||||
|
||||
flush_cache (addr, (cnt+1)*info.blksz);
|
||||
|
||||
/* Check if we should attempt an auto-start */
|
||||
if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
|
||||
char *local_args[2];
|
||||
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
|
||||
local_args[0] = argv[0];
|
||||
local_args[1] = NULL;
|
||||
printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
|
||||
rcode = do_bootm (cmdtp, 0, 1, local_args);
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
* scsi command intepreter
|
||||
*/
|
||||
int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
switch (argc) {
|
||||
case 0:
|
||||
case 1: printf ("Usage:\n%s\n", cmdtp->usage); return 1;
|
||||
case 2:
|
||||
if (strncmp(argv[1],"res",3) == 0) {
|
||||
printf("\nReset SCSI\n");
|
||||
scsi_bus_reset();
|
||||
scsi_scan(1);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"inf",3) == 0) {
|
||||
int i;
|
||||
for (i=0; i<CFG_SCSI_MAX_DEVICE; ++i) {
|
||||
if(scsi_dev_desc[i].type==DEV_TYPE_UNKNOWN)
|
||||
continue; /* list only known devices */
|
||||
printf ("SCSI dev. %d: ", i);
|
||||
dev_print(&scsi_dev_desc[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"dev",3) == 0) {
|
||||
if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CFG_SCSI_MAX_DEVICE)) {
|
||||
printf("\nno SCSI devices available\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("\n Device %d: ", scsi_curr_dev);
|
||||
dev_print(&scsi_dev_desc[scsi_curr_dev]);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"scan",4) == 0) {
|
||||
scsi_scan(1);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"part",4) == 0) {
|
||||
int dev, ok;
|
||||
for (ok=0, dev=0; dev<CFG_SCSI_MAX_DEVICE; ++dev) {
|
||||
if (scsi_dev_desc[dev].type!=DEV_TYPE_UNKNOWN) {
|
||||
ok++;
|
||||
if (dev)
|
||||
printf("\n");
|
||||
debug ("print_part of %x\n",dev);
|
||||
print_part(&scsi_dev_desc[dev]);
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
printf("\nno SCSI devices available\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
case 3:
|
||||
if (strncmp(argv[1],"dev",3) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
printf ("\nSCSI device %d: ", dev);
|
||||
if (dev >= CFG_SCSI_MAX_DEVICE) {
|
||||
printf("unknown device\n");
|
||||
return 1;
|
||||
}
|
||||
printf ("\n Device %d: ", dev);
|
||||
dev_print(&scsi_dev_desc[dev]);
|
||||
if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) {
|
||||
return 1;
|
||||
}
|
||||
scsi_curr_dev = dev;
|
||||
printf("... is now current device\n");
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1],"part",4) == 0) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) {
|
||||
print_part(&scsi_dev_desc[dev]);
|
||||
}
|
||||
else {
|
||||
printf ("\nSCSI device %d not available\n", dev);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
default:
|
||||
/* at least 4 args */
|
||||
if (strcmp(argv[1],"read") == 0) {
|
||||
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
||||
ulong blk = simple_strtoul(argv[3], NULL, 16);
|
||||
ulong cnt = simple_strtoul(argv[4], NULL, 16);
|
||||
ulong n;
|
||||
printf ("\nSCSI read: device %d block # %ld, count %ld ... ",
|
||||
scsi_curr_dev, blk, cnt);
|
||||
n = scsi_read(scsi_curr_dev, blk, cnt, (ulong *)addr);
|
||||
printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR");
|
||||
return 0;
|
||||
}
|
||||
} /* switch */
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* scsi_read
|
||||
*/
|
||||
|
||||
#define SCSI_MAX_READ_BLK 0xFFFF /* almost the maximum amount of the scsi_ext command.. */
|
||||
|
||||
ulong scsi_read(int device, ulong blknr, ulong blkcnt, ulong *buffer)
|
||||
{
|
||||
ulong start,blks, buf_addr;
|
||||
unsigned short smallblks;
|
||||
ccb* pccb=(ccb *)&tempccb;
|
||||
device&=0xff;
|
||||
/* Setup device
|
||||
*/
|
||||
pccb->target=scsi_dev_desc[device].target;
|
||||
pccb->lun=scsi_dev_desc[device].lun;
|
||||
buf_addr=(unsigned long)buffer;
|
||||
start=blknr;
|
||||
blks=blkcnt;
|
||||
debug ("\nscsi_read: dev %d startblk %lx, blccnt %lx buffer %lx\n",device,start,blks,(unsigned long)buffer);
|
||||
do {
|
||||
pccb->pdata=(unsigned char *)buf_addr;
|
||||
if(blks>SCSI_MAX_READ_BLK) {
|
||||
pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK;
|
||||
smallblks=SCSI_MAX_READ_BLK;
|
||||
scsi_setup_read_ext(pccb,start,smallblks);
|
||||
start+=SCSI_MAX_READ_BLK;
|
||||
blks-=SCSI_MAX_READ_BLK;
|
||||
}
|
||||
else {
|
||||
pccb->datalen=scsi_dev_desc[device].blksz * blks;
|
||||
smallblks=(unsigned short) blks;
|
||||
scsi_setup_read_ext(pccb,start,smallblks);
|
||||
start+=blks;
|
||||
blks=0;
|
||||
}
|
||||
debug ("scsi_read_ext: startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
|
||||
if(scsi_exec(pccb)!=TRUE) {
|
||||
scsi_print_error(pccb);
|
||||
blkcnt-=blks;
|
||||
break;
|
||||
}
|
||||
buf_addr+=pccb->datalen;
|
||||
} while(blks!=0);
|
||||
debug ("scsi_read_ext: end startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
|
||||
return(blkcnt);
|
||||
}
|
||||
|
||||
/* copy src to dest, skipping leading and trailing blanks
|
||||
* and null terminate the string
|
||||
*/
|
||||
void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len)
|
||||
{
|
||||
int start,end;
|
||||
|
||||
start=0;
|
||||
while(start<len) {
|
||||
if(src[start]!=' ')
|
||||
break;
|
||||
start++;
|
||||
}
|
||||
end=len-1;
|
||||
while(end>start) {
|
||||
if(src[end]!=' ')
|
||||
break;
|
||||
end--;
|
||||
}
|
||||
for( ; start<=end; start++) {
|
||||
*dest++=src[start];
|
||||
}
|
||||
*dest='\0';
|
||||
}
|
||||
|
||||
|
||||
/* Trim trailing blanks, and NUL-terminate string
|
||||
*/
|
||||
void scsi_trim_trail (unsigned char *str, unsigned int len)
|
||||
{
|
||||
unsigned char *p = str + len - 1;
|
||||
|
||||
while (len-- > 0) {
|
||||
*p-- = '\0';
|
||||
if (*p != ' ') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
* Some setup (fill-in) routines
|
||||
*/
|
||||
void scsi_setup_test_unit_ready(ccb * pccb)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_TST_U_RDY;
|
||||
pccb->cmd[1]=pccb->lun<<5;
|
||||
pccb->cmd[2]=0;
|
||||
pccb->cmd[3]=0;
|
||||
pccb->cmd[4]=0;
|
||||
pccb->cmd[5]=0;
|
||||
pccb->cmdlen=6;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
}
|
||||
|
||||
void scsi_setup_read_capacity(ccb * pccb)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_RD_CAPAC;
|
||||
pccb->cmd[1]=pccb->lun<<5;
|
||||
pccb->cmd[2]=0;
|
||||
pccb->cmd[3]=0;
|
||||
pccb->cmd[4]=0;
|
||||
pccb->cmd[5]=0;
|
||||
pccb->cmd[6]=0;
|
||||
pccb->cmd[7]=0;
|
||||
pccb->cmd[8]=0;
|
||||
pccb->cmd[9]=0;
|
||||
pccb->cmdlen=10;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
|
||||
}
|
||||
|
||||
void scsi_setup_read_ext(ccb * pccb, unsigned long start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_READ10;
|
||||
pccb->cmd[1]=pccb->lun<<5;
|
||||
pccb->cmd[2]=((unsigned char) (start>>24))&0xff;
|
||||
pccb->cmd[3]=((unsigned char) (start>>16))&0xff;
|
||||
pccb->cmd[4]=((unsigned char) (start>>8))&0xff;
|
||||
pccb->cmd[5]=((unsigned char) (start))&0xff;
|
||||
pccb->cmd[6]=0;
|
||||
pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff;
|
||||
pccb->cmd[8]=(unsigned char) blocks & 0xff;
|
||||
pccb->cmd[6]=0;
|
||||
pccb->cmdlen=10;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n",
|
||||
pccb->cmd[0],pccb->cmd[1],
|
||||
pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5],
|
||||
pccb->cmd[7],pccb->cmd[8]);
|
||||
}
|
||||
|
||||
void scsi_setup_read6(ccb * pccb, unsigned long start, unsigned short blocks)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_READ6;
|
||||
pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f);
|
||||
pccb->cmd[2]=((unsigned char) (start>>8))&0xff;
|
||||
pccb->cmd[3]=((unsigned char) (start))&0xff;
|
||||
pccb->cmd[4]=(unsigned char) blocks & 0xff;
|
||||
pccb->cmd[5]=0;
|
||||
pccb->cmdlen=6;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n",
|
||||
pccb->cmd[0],pccb->cmd[1],
|
||||
pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]);
|
||||
}
|
||||
|
||||
|
||||
void scsi_setup_inquiry(ccb * pccb)
|
||||
{
|
||||
pccb->cmd[0]=SCSI_INQUIRY;
|
||||
pccb->cmd[1]=pccb->lun<<5;
|
||||
pccb->cmd[2]=0;
|
||||
pccb->cmd[3]=0;
|
||||
if(pccb->datalen>255)
|
||||
pccb->cmd[4]=255;
|
||||
else
|
||||
pccb->cmd[4]=(unsigned char)pccb->datalen;
|
||||
pccb->cmd[5]=0;
|
||||
pccb->cmdlen=6;
|
||||
pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */
|
||||
}
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
scsi, 5, 1, do_scsi,
|
||||
"scsi - SCSI sub-system\n",
|
||||
"reset - reset SCSI controller\n"
|
||||
"scsi info - show available SCSI devices\n"
|
||||
"scsi scan - (re-)scan SCSI bus\n"
|
||||
"scsi device [dev] - show or set current device\n"
|
||||
"scsi part [dev] - print partition table of one or all SCSI devices\n"
|
||||
"scsi read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
|
||||
" to memory address `addr'\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(
|
||||
scsiboot, 3, 1, do_scsiboot,
|
||||
"scsiboot- boot from SCSI device\n",
|
||||
"loadAddr dev:part\n"
|
||||
);
|
||||
|
||||
#endif /* #if (CONFIG_COMMANDS & CFG_CMD_SCSI) */
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPI Read/Write Utilities
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <spi.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_SPI)
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Definitions
|
||||
*/
|
||||
|
||||
#ifndef MAX_SPI_BYTES
|
||||
# define MAX_SPI_BYTES 32 /* Maximum number of bytes we can handle */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* External table of chip select functions (see the appropriate board
|
||||
* support for the actual definition of the table).
|
||||
*/
|
||||
extern spi_chipsel_type spi_chipsel[];
|
||||
extern int spi_chipsel_cnt;
|
||||
|
||||
/*
|
||||
* Values from last command.
|
||||
*/
|
||||
static int device;
|
||||
static int bitlen;
|
||||
static uchar dout[MAX_SPI_BYTES];
|
||||
static uchar din[MAX_SPI_BYTES];
|
||||
|
||||
/*
|
||||
* SPI read/write
|
||||
*
|
||||
* Syntax:
|
||||
* spi {dev} {num_bits} {dout}
|
||||
* {dev} is the device number for controlling chip select (see TBD)
|
||||
* {num_bits} is the number of bits to send & receive (base 10)
|
||||
* {dout} is a hexadecimal string of data to send
|
||||
* The command prints out the hexadecimal string received via SPI.
|
||||
*/
|
||||
|
||||
int do_spi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char *cp = 0;
|
||||
uchar tmp;
|
||||
int j;
|
||||
int rcode = 0;
|
||||
|
||||
/*
|
||||
* We use the last specified parameters, unless new ones are
|
||||
* entered.
|
||||
*/
|
||||
|
||||
if ((flag & CMD_FLAG_REPEAT) == 0)
|
||||
{
|
||||
if (argc >= 2)
|
||||
device = simple_strtoul(argv[1], NULL, 10);
|
||||
if (argc >= 3)
|
||||
bitlen = simple_strtoul(argv[2], NULL, 10);
|
||||
if (argc >= 4) {
|
||||
cp = argv[3];
|
||||
for(j = 0; *cp; j++, cp++) {
|
||||
tmp = *cp - '0';
|
||||
if(tmp > 9)
|
||||
tmp -= ('A' - '0') - 10;
|
||||
if(tmp > 15)
|
||||
tmp -= ('a' - 'A');
|
||||
if(tmp > 15) {
|
||||
printf("Hex conversion error on %c, giving up.\n", *cp);
|
||||
return 1;
|
||||
}
|
||||
if((j % 2) == 0)
|
||||
dout[j / 2] = (tmp << 4);
|
||||
else
|
||||
dout[j / 2] |= tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((device < 0) || (device >= spi_chipsel_cnt)) {
|
||||
printf("Invalid device %d, giving up.\n", device);
|
||||
return 1;
|
||||
}
|
||||
if ((bitlen < 0) || (bitlen > (MAX_SPI_BYTES * 8))) {
|
||||
printf("Invalid bitlen %d, giving up.\n", bitlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug ("spi_chipsel[%d] = %08X\n",
|
||||
device, (uint)spi_chipsel[device]);
|
||||
|
||||
if(spi_xfer(spi_chipsel[device], bitlen, dout, din) != 0) {
|
||||
printf("Error with the SPI transaction.\n");
|
||||
rcode = 1;
|
||||
} else {
|
||||
cp = (char *)din;
|
||||
for(j = 0; j < ((bitlen + 7) / 8); j++) {
|
||||
printf("%02X", *cp++);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
sspi, 5, 1, do_spi,
|
||||
"sspi - SPI utility commands\n",
|
||||
"<device> <bit_len> <dout> - Send <bit_len> bits from <dout> out the SPI\n"
|
||||
"<device> - Identifies the chip select of the device\n"
|
||||
"<bit_len> - Number of bits to send (base 10)\n"
|
||||
"<dout> - Hexadecimal string that gets sent\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_SPI */
|
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* (C) Copyright 2003 Stefan Roese, stefan.roese@esd-electronics.com
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <pci.h>
|
||||
|
||||
#include <universe.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_UNIVERSE)
|
||||
|
||||
#define PCI_VENDOR PCI_VENDOR_ID_TUNDRA
|
||||
#define PCI_DEVICE PCI_DEVICE_ID_TUNDRA_CA91C042
|
||||
|
||||
|
||||
typedef struct _UNI_DEV UNI_DEV;
|
||||
|
||||
struct _UNI_DEV {
|
||||
int bus;
|
||||
pci_dev_t busdevfn;
|
||||
UNIVERSE *uregs;
|
||||
unsigned int pci_bs;
|
||||
};
|
||||
|
||||
static UNI_DEV *dev;
|
||||
|
||||
|
||||
int universe_init(void)
|
||||
{
|
||||
int j, result, lastError = 0;
|
||||
pci_dev_t busdevfn;
|
||||
unsigned int val;
|
||||
|
||||
busdevfn = pci_find_device(PCI_VENDOR, PCI_DEVICE, 0);
|
||||
if (busdevfn == -1) {
|
||||
puts("No Tundra Universe found!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Lets turn Latency off */
|
||||
pci_write_config_dword(busdevfn, 0x0c, 0);
|
||||
|
||||
dev = malloc(sizeof(*dev));
|
||||
if (NULL == dev) {
|
||||
puts("UNIVERSE: No memory!\n");
|
||||
result = -1;
|
||||
goto break_20;
|
||||
}
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->busdevfn = busdevfn;
|
||||
|
||||
pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_1, &val);
|
||||
if (val & 1) {
|
||||
pci_read_config_dword(busdevfn, PCI_BASE_ADDRESS_0, &val);
|
||||
}
|
||||
val &= ~0xf;
|
||||
dev->uregs = (UNIVERSE *)val;
|
||||
|
||||
debug ("UNIVERSE-Base : %p\n", dev->uregs);
|
||||
|
||||
/* check mapping */
|
||||
debug (" Read via mapping, PCI_ID = %08X\n", readl(&dev->uregs->pci_id));
|
||||
if (((PCI_DEVICE <<16) | PCI_VENDOR) != readl(&dev->uregs->pci_id)) {
|
||||
printf ("UNIVERSE: Cannot read PCI-ID via Mapping: %08x\n",
|
||||
readl(&dev->uregs->pci_id));
|
||||
result = -1;
|
||||
goto break_30;
|
||||
}
|
||||
|
||||
debug ("PCI_BS = %08X\n", readl(&dev->uregs->pci_bs));
|
||||
|
||||
dev->pci_bs = readl(&dev->uregs->pci_bs);
|
||||
|
||||
/* turn off windows */
|
||||
for (j=0; j <4; j ++) {
|
||||
writel(0x00800000, &dev->uregs->lsi[j].ctl);
|
||||
writel(0x00800000, &dev->uregs->vsi[j].ctl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to Misc Register
|
||||
* Set VME Bus Time-out
|
||||
* Arbitration Mode
|
||||
* DTACK Enable
|
||||
*/
|
||||
writel(0x15040000 | (readl(&dev->uregs->misc_ctl) & 0x00020000), &dev->uregs->misc_ctl);
|
||||
|
||||
if (readl(&dev->uregs->misc_ctl) & 0x00020000) {
|
||||
debug ("System Controller!\n"); /* test-only */
|
||||
} else {
|
||||
debug ("Not System Controller!\n"); /* test-only */
|
||||
}
|
||||
|
||||
/*
|
||||
* Lets turn off interrupts
|
||||
*/
|
||||
writel(0x00000000,&dev->uregs->lint_en); /* Disable interrupts in the Universe first */
|
||||
writel(0x0000FFFF,&dev->uregs->lint_stat); /* Clear Any Pending Interrupts */
|
||||
eieio();
|
||||
writel(0x0000, &dev->uregs->lint_map0); /* Map all ints to 0 */
|
||||
writel(0x0000, &dev->uregs->lint_map1); /* Map all ints to 0 */
|
||||
eieio();
|
||||
|
||||
return 0;
|
||||
|
||||
break_30:
|
||||
free(dev);
|
||||
break_20:
|
||||
lastError = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create pci slave window (access: pci -> vme)
|
||||
*/
|
||||
int universe_pci_slave_window(unsigned int pciAddr, unsigned int vmeAddr, int size, int vam, int pms, int vdw)
|
||||
{
|
||||
int result, i;
|
||||
unsigned int ctl = 0;
|
||||
|
||||
if (NULL == dev) {
|
||||
result = -1;
|
||||
goto exit_10;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (0x00800000 == readl(&dev->uregs->lsi[i].ctl))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 4) {
|
||||
printf ("universe: No Image available\n");
|
||||
result = -1;
|
||||
goto exit_10;
|
||||
}
|
||||
|
||||
debug ("universe: Using image %d\n", i);
|
||||
|
||||
writel(pciAddr , &dev->uregs->lsi[i].bs);
|
||||
writel((pciAddr + size), &dev->uregs->lsi[i].bd);
|
||||
writel((vmeAddr - pciAddr), &dev->uregs->lsi[i].to);
|
||||
|
||||
switch (vam & VME_AM_Axx) {
|
||||
case VME_AM_A16:
|
||||
ctl = 0x00000000;
|
||||
break;
|
||||
case VME_AM_A24:
|
||||
ctl = 0x00010000;
|
||||
break;
|
||||
case VME_AM_A32:
|
||||
ctl = 0x00020000;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (vam & VME_AM_Mxx) {
|
||||
case VME_AM_DATA:
|
||||
ctl |= 0x00000000;
|
||||
break;
|
||||
case VME_AM_PROG:
|
||||
ctl |= 0x00008000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (vam & VME_AM_SUP) {
|
||||
ctl |= 0x00001000;
|
||||
|
||||
}
|
||||
|
||||
switch (vdw & VME_FLAG_Dxx) {
|
||||
case VME_FLAG_D8:
|
||||
ctl |= 0x00000000;
|
||||
break;
|
||||
case VME_FLAG_D16:
|
||||
ctl |= 0x00400000;
|
||||
break;
|
||||
case VME_FLAG_D32:
|
||||
ctl |= 0x00800000;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pms & PCI_MS_Mxx) {
|
||||
case PCI_MS_MEM:
|
||||
ctl |= 0x00000000;
|
||||
break;
|
||||
case PCI_MS_IO:
|
||||
ctl |= 0x00000001;
|
||||
break;
|
||||
case PCI_MS_CONFIG:
|
||||
ctl |= 0x00000002;
|
||||
break;
|
||||
}
|
||||
|
||||
ctl |= 0x80000000; /* enable */
|
||||
|
||||
writel(ctl, &dev->uregs->lsi[i].ctl);
|
||||
|
||||
debug ("universe: window-addr=%p\n", &dev->uregs->lsi[i].ctl);
|
||||
debug ("universe: pci slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->lsi[i].ctl));
|
||||
debug ("universe: pci slave window[%d] bs=%08x\n", i, readl(&dev->uregs->lsi[i].bs));
|
||||
debug ("universe: pci slave window[%d] bd=%08x\n", i, readl(&dev->uregs->lsi[i].bd));
|
||||
debug ("universe: pci slave window[%d] to=%08x\n", i, readl(&dev->uregs->lsi[i].to));
|
||||
|
||||
return 0;
|
||||
|
||||
exit_10:
|
||||
return -result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create vme slave window (access: vme -> pci)
|
||||
*/
|
||||
int universe_vme_slave_window(unsigned int vmeAddr, unsigned int pciAddr, int size, int vam, int pms)
|
||||
{
|
||||
int result, i;
|
||||
unsigned int ctl = 0;
|
||||
|
||||
if (NULL == dev) {
|
||||
result = -1;
|
||||
goto exit_10;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (0x00800000 == readl(&dev->uregs->vsi[i].ctl))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 4) {
|
||||
printf ("universe: No Image available\n");
|
||||
result = -1;
|
||||
goto exit_10;
|
||||
}
|
||||
|
||||
debug ("universe: Using image %d\n", i);
|
||||
|
||||
writel(vmeAddr , &dev->uregs->vsi[i].bs);
|
||||
writel((vmeAddr + size), &dev->uregs->vsi[i].bd);
|
||||
writel((pciAddr - vmeAddr), &dev->uregs->vsi[i].to);
|
||||
|
||||
switch (vam & VME_AM_Axx) {
|
||||
case VME_AM_A16:
|
||||
ctl = 0x00000000;
|
||||
break;
|
||||
case VME_AM_A24:
|
||||
ctl = 0x00010000;
|
||||
break;
|
||||
case VME_AM_A32:
|
||||
ctl = 0x00020000;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (vam & VME_AM_Mxx) {
|
||||
case VME_AM_DATA:
|
||||
ctl |= 0x00000000;
|
||||
break;
|
||||
case VME_AM_PROG:
|
||||
ctl |= 0x00800000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (vam & VME_AM_SUP) {
|
||||
ctl |= 0x00100000;
|
||||
|
||||
}
|
||||
|
||||
switch (pms & PCI_MS_Mxx) {
|
||||
case PCI_MS_MEM:
|
||||
ctl |= 0x00000000;
|
||||
break;
|
||||
case PCI_MS_IO:
|
||||
ctl |= 0x00000001;
|
||||
break;
|
||||
case PCI_MS_CONFIG:
|
||||
ctl |= 0x00000002;
|
||||
break;
|
||||
}
|
||||
|
||||
ctl |= 0x80f00000; /* enable */
|
||||
|
||||
writel(ctl, &dev->uregs->vsi[i].ctl);
|
||||
|
||||
debug ("universe: window-addr=%p\n", &dev->uregs->vsi[i].ctl);
|
||||
debug ("universe: vme slave window[%d] ctl=%08x\n", i, readl(&dev->uregs->vsi[i].ctl));
|
||||
debug ("universe: vme slave window[%d] bs=%08x\n", i, readl(&dev->uregs->vsi[i].bs));
|
||||
debug ("universe: vme slave window[%d] bd=%08x\n", i, readl(&dev->uregs->vsi[i].bd));
|
||||
debug ("universe: vme slave window[%d] to=%08x\n", i, readl(&dev->uregs->vsi[i].to));
|
||||
|
||||
return 0;
|
||||
|
||||
exit_10:
|
||||
return -result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Tundra Universe configuration
|
||||
*/
|
||||
int do_universe(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr1 = 0, addr2 = 0, size = 0, vam = 0, pms = 0, vdw = 0;
|
||||
char cmd = 'x';
|
||||
|
||||
/* get parameter */
|
||||
if (argc > 1)
|
||||
cmd = argv[1][0];
|
||||
if (argc > 2)
|
||||
addr1 = simple_strtoul(argv[2], NULL, 16);
|
||||
if (argc > 3)
|
||||
addr2 = simple_strtoul(argv[3], NULL, 16);
|
||||
if (argc > 4)
|
||||
size = simple_strtoul(argv[4], NULL, 16);
|
||||
if (argc > 5)
|
||||
vam = simple_strtoul(argv[5], NULL, 16);
|
||||
if (argc > 6)
|
||||
pms = simple_strtoul(argv[6], NULL, 16);
|
||||
if (argc > 7)
|
||||
vdw = simple_strtoul(argv[7], NULL, 16);
|
||||
|
||||
switch (cmd) {
|
||||
case 'i': /* init */
|
||||
universe_init();
|
||||
break;
|
||||
case 'v': /* vme */
|
||||
printf("Configuring Universe VME Slave Window (VME->PCI):\n");
|
||||
printf(" vme=%08lx pci=%08lx size=%08lx vam=%02lx pms=%02lx\n",
|
||||
addr1, addr2, size, vam, pms);
|
||||
universe_vme_slave_window(addr1, addr2, size, vam, pms);
|
||||
break;
|
||||
case 'p': /* pci */
|
||||
printf("Configuring Universe PCI Slave Window (PCI->VME):\n");
|
||||
printf(" pci=%08lx vme=%08lx size=%08lx vam=%02lx pms=%02lx vdw=%02lx\n",
|
||||
addr1, addr2, size, vam, pms, vdw);
|
||||
universe_pci_slave_window(addr1, addr2, size, vam, pms, vdw);
|
||||
break;
|
||||
default:
|
||||
printf("Universe command %s not supported!\n", argv[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
universe, 8, 1, do_universe,
|
||||
"universe- initialize and configure Turndra Universe\n",
|
||||
"init\n"
|
||||
" - initialize universe\n"
|
||||
"universe vme [vme_addr] [pci_addr] [size] [vam] [pms]\n"
|
||||
" - create vme slave window (access: vme->pci)\n"
|
||||
"universe pci [pci_addr] [vme_addr] [size] [vam] [pms] [vdw]\n"
|
||||
" - create pci slave window (access: pci->vme)\n"
|
||||
" [vam] = VMEbus Address-Modifier: 01 -> A16 Address Space\n"
|
||||
" 02 -> A24 Address Space\n"
|
||||
" 03 -> A32 Address Space\n"
|
||||
" 04 -> Supervisor AM Code\n"
|
||||
" 10 -> Data AM Code\n"
|
||||
" 20 -> Program AM Code\n"
|
||||
" [pms] = PCI Memory Space: 01 -> Memory Space\n"
|
||||
" 02 -> I/O Space\n"
|
||||
" 03 -> Configuration Space\n"
|
||||
" [vdw] = VMEbus Maximum Datawidth: 01 -> D8 Data Width\n"
|
||||
" 02 -> D16 Data Width\n"
|
||||
" 03 -> D32 Data Width\n"
|
||||
);
|
||||
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_UNIVERSE) */
|
|
@ -0,0 +1,679 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Denis Peter, MPL AG Switzerland
|
||||
*
|
||||
* Most of this source has been derived from the Linux USB
|
||||
* project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <part.h>
|
||||
#include <usb.h>
|
||||
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
static int usb_stor_curr_dev = -1; /* current device */
|
||||
#endif
|
||||
#ifdef CONFIG_USB_HOST_ETHER
|
||||
static int usb_ether_curr_dev = -1; /* current ethernet device */
|
||||
#endif
|
||||
|
||||
/* some display routines (info command) */
|
||||
static char *usb_get_class_desc(unsigned char dclass)
|
||||
{
|
||||
switch (dclass) {
|
||||
case USB_CLASS_PER_INTERFACE:
|
||||
return "See Interface";
|
||||
case USB_CLASS_AUDIO:
|
||||
return "Audio";
|
||||
case USB_CLASS_COMM:
|
||||
return "Communication";
|
||||
case USB_CLASS_HID:
|
||||
return "Human Interface";
|
||||
case USB_CLASS_PRINTER:
|
||||
return "Printer";
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
return "Mass Storage";
|
||||
case USB_CLASS_HUB:
|
||||
return "Hub";
|
||||
case USB_CLASS_DATA:
|
||||
return "CDC Data";
|
||||
case USB_CLASS_VENDOR_SPEC:
|
||||
return "Vendor specific";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_display_class_sub(unsigned char dclass, unsigned char subclass,
|
||||
unsigned char proto)
|
||||
{
|
||||
switch (dclass) {
|
||||
case USB_CLASS_PER_INTERFACE:
|
||||
printf("See Interface");
|
||||
break;
|
||||
case USB_CLASS_HID:
|
||||
printf("Human Interface, Subclass: ");
|
||||
switch (subclass) {
|
||||
case USB_SUB_HID_NONE:
|
||||
printf("None");
|
||||
break;
|
||||
case USB_SUB_HID_BOOT:
|
||||
printf("Boot ");
|
||||
switch (proto) {
|
||||
case USB_PROT_HID_NONE:
|
||||
printf("None");
|
||||
break;
|
||||
case USB_PROT_HID_KEYBOARD:
|
||||
printf("Keyboard");
|
||||
break;
|
||||
case USB_PROT_HID_MOUSE:
|
||||
printf("Mouse");
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
printf("Mass Storage, ");
|
||||
switch (subclass) {
|
||||
case US_SC_RBC:
|
||||
printf("RBC ");
|
||||
break;
|
||||
case US_SC_8020:
|
||||
printf("SFF-8020i (ATAPI)");
|
||||
break;
|
||||
case US_SC_QIC:
|
||||
printf("QIC-157 (Tape)");
|
||||
break;
|
||||
case US_SC_UFI:
|
||||
printf("UFI");
|
||||
break;
|
||||
case US_SC_8070:
|
||||
printf("SFF-8070");
|
||||
break;
|
||||
case US_SC_SCSI:
|
||||
printf("Transp. SCSI");
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
printf(", ");
|
||||
switch (proto) {
|
||||
case US_PR_CB:
|
||||
printf("Command/Bulk");
|
||||
break;
|
||||
case US_PR_CBI:
|
||||
printf("Command/Bulk/Int");
|
||||
break;
|
||||
case US_PR_BULK:
|
||||
printf("Bulk only");
|
||||
break;
|
||||
default:
|
||||
printf("reserved");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("%s", usb_get_class_desc(dclass));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_display_string(struct usb_device *dev, int index)
|
||||
{
|
||||
ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256);
|
||||
|
||||
if (index != 0) {
|
||||
if (usb_string(dev, index, &buffer[0], 256) > 0)
|
||||
printf("String: \"%s\"", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_display_desc(struct usb_device *dev)
|
||||
{
|
||||
if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) {
|
||||
printf("%d: %s, USB Revision %x.%x\n", dev->devnum,
|
||||
usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass),
|
||||
(dev->descriptor.bcdUSB>>8) & 0xff,
|
||||
dev->descriptor.bcdUSB & 0xff);
|
||||
|
||||
if (strlen(dev->mf) || strlen(dev->prod) ||
|
||||
strlen(dev->serial))
|
||||
printf(" - %s %s %s\n", dev->mf, dev->prod,
|
||||
dev->serial);
|
||||
if (dev->descriptor.bDeviceClass) {
|
||||
printf(" - Class: ");
|
||||
usb_display_class_sub(dev->descriptor.bDeviceClass,
|
||||
dev->descriptor.bDeviceSubClass,
|
||||
dev->descriptor.bDeviceProtocol);
|
||||
printf("\n");
|
||||
} else {
|
||||
printf(" - Class: (from Interface) %s\n",
|
||||
usb_get_class_desc(
|
||||
dev->config.if_desc[0].desc.bInterfaceClass));
|
||||
}
|
||||
printf(" - PacketSize: %d Configurations: %d\n",
|
||||
dev->descriptor.bMaxPacketSize0,
|
||||
dev->descriptor.bNumConfigurations);
|
||||
printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n",
|
||||
dev->descriptor.idVendor, dev->descriptor.idProduct,
|
||||
(dev->descriptor.bcdDevice>>8) & 0xff,
|
||||
dev->descriptor.bcdDevice & 0xff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void usb_display_conf_desc(struct usb_config_descriptor *config,
|
||||
struct usb_device *dev)
|
||||
{
|
||||
printf(" Configuration: %d\n", config->bConfigurationValue);
|
||||
printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces,
|
||||
(config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
|
||||
(config->bmAttributes & 0x20) ? "Remote Wakeup " : "",
|
||||
config->bMaxPower*2);
|
||||
if (config->iConfiguration) {
|
||||
printf(" - ");
|
||||
usb_display_string(dev, config->iConfiguration);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,
|
||||
struct usb_device *dev)
|
||||
{
|
||||
printf(" Interface: %d\n", ifdesc->bInterfaceNumber);
|
||||
printf(" - Alternate Setting %d, Endpoints: %d\n",
|
||||
ifdesc->bAlternateSetting, ifdesc->bNumEndpoints);
|
||||
printf(" - Class ");
|
||||
usb_display_class_sub(ifdesc->bInterfaceClass,
|
||||
ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol);
|
||||
printf("\n");
|
||||
if (ifdesc->iInterface) {
|
||||
printf(" - ");
|
||||
usb_display_string(dev, ifdesc->iInterface);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
|
||||
{
|
||||
printf(" - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf,
|
||||
(epdesc->bEndpointAddress & 0x80) ? "In" : "Out");
|
||||
switch ((epdesc->bmAttributes & 0x03)) {
|
||||
case 0:
|
||||
printf("Control");
|
||||
break;
|
||||
case 1:
|
||||
printf("Isochronous");
|
||||
break;
|
||||
case 2:
|
||||
printf("Bulk");
|
||||
break;
|
||||
case 3:
|
||||
printf("Interrupt");
|
||||
break;
|
||||
}
|
||||
printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize));
|
||||
if ((epdesc->bmAttributes & 0x03) == 0x3)
|
||||
printf(" Interval %dms", epdesc->bInterval);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* main routine to diasplay the configs, interfaces and endpoints */
|
||||
static void usb_display_config(struct usb_device *dev)
|
||||
{
|
||||
struct usb_config *config;
|
||||
struct usb_interface *ifdesc;
|
||||
struct usb_endpoint_descriptor *epdesc;
|
||||
int i, ii;
|
||||
|
||||
config = &dev->config;
|
||||
usb_display_conf_desc(&config->desc, dev);
|
||||
for (i = 0; i < config->no_of_if; i++) {
|
||||
ifdesc = &config->if_desc[i];
|
||||
usb_display_if_desc(&ifdesc->desc, dev);
|
||||
for (ii = 0; ii < ifdesc->no_of_ep; ii++) {
|
||||
epdesc = &ifdesc->ep_desc[ii];
|
||||
usb_display_ep_desc(epdesc);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static struct usb_device *usb_find_device(int devnum)
|
||||
{
|
||||
struct usb_device *dev;
|
||||
int d;
|
||||
|
||||
for (d = 0; d < USB_MAX_DEVICE; d++) {
|
||||
dev = usb_get_dev_index(d);
|
||||
if (dev == NULL)
|
||||
return NULL;
|
||||
if (dev->devnum == devnum)
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char *portspeed(int speed)
|
||||
{
|
||||
char *speed_str;
|
||||
|
||||
switch (speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
speed_str = "5 Gb/s";
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
speed_str = "480 Mb/s";
|
||||
break;
|
||||
case USB_SPEED_LOW:
|
||||
speed_str = "1.5 Mb/s";
|
||||
break;
|
||||
default:
|
||||
speed_str = "12 Mb/s";
|
||||
break;
|
||||
}
|
||||
|
||||
return speed_str;
|
||||
}
|
||||
|
||||
/* shows the device tree recursively */
|
||||
static void usb_show_tree_graph(struct usb_device *dev, char *pre)
|
||||
{
|
||||
int i, index;
|
||||
int has_child, last_child;
|
||||
|
||||
index = strlen(pre);
|
||||
printf(" %s", pre);
|
||||
/* check if the device has connected children */
|
||||
has_child = 0;
|
||||
for (i = 0; i < dev->maxchild; i++) {
|
||||
if (dev->children[i] != NULL)
|
||||
has_child = 1;
|
||||
}
|
||||
/* check if we are the last one */
|
||||
last_child = 1;
|
||||
if (dev->parent != NULL) {
|
||||
for (i = 0; i < dev->parent->maxchild; i++) {
|
||||
/* search for children */
|
||||
if (dev->parent->children[i] == dev) {
|
||||
/* found our pointer, see if we have a
|
||||
* little sister
|
||||
*/
|
||||
while (i++ < dev->parent->maxchild) {
|
||||
if (dev->parent->children[i] != NULL) {
|
||||
/* found a sister */
|
||||
last_child = 0;
|
||||
break;
|
||||
} /* if */
|
||||
} /* while */
|
||||
} /* device found */
|
||||
} /* for all children of the parent */
|
||||
printf("\b+-");
|
||||
/* correct last child */
|
||||
if (last_child)
|
||||
pre[index-1] = ' ';
|
||||
} /* if not root hub */
|
||||
else
|
||||
printf(" ");
|
||||
printf("%d ", dev->devnum);
|
||||
pre[index++] = ' ';
|
||||
pre[index++] = has_child ? '|' : ' ';
|
||||
pre[index] = 0;
|
||||
printf(" %s (%s, %dmA)\n", usb_get_class_desc(
|
||||
dev->config.if_desc[0].desc.bInterfaceClass),
|
||||
portspeed(dev->speed),
|
||||
dev->config.desc.bMaxPower * 2);
|
||||
if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
|
||||
printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
|
||||
printf(" %s\n", pre);
|
||||
if (dev->maxchild > 0) {
|
||||
for (i = 0; i < dev->maxchild; i++) {
|
||||
if (dev->children[i] != NULL) {
|
||||
usb_show_tree_graph(dev->children[i], pre);
|
||||
pre[index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* main routine for the tree command */
|
||||
static void usb_show_tree(struct usb_device *dev)
|
||||
{
|
||||
char preamble[32];
|
||||
|
||||
memset(preamble, 0, 32);
|
||||
usb_show_tree_graph(dev, &preamble[0]);
|
||||
}
|
||||
|
||||
static int usb_test(struct usb_device *dev, int port, char* arg)
|
||||
{
|
||||
int mode;
|
||||
|
||||
if (port > dev->maxchild) {
|
||||
printf("Device is no hub or does not have %d ports.\n", port);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (arg[0]) {
|
||||
case 'J':
|
||||
case 'j':
|
||||
printf("Setting Test_J mode");
|
||||
mode = USB_TEST_MODE_J;
|
||||
break;
|
||||
case 'K':
|
||||
case 'k':
|
||||
printf("Setting Test_K mode");
|
||||
mode = USB_TEST_MODE_K;
|
||||
break;
|
||||
case 'S':
|
||||
case 's':
|
||||
printf("Setting Test_SE0_NAK mode");
|
||||
mode = USB_TEST_MODE_SE0_NAK;
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
printf("Setting Test_Packet mode");
|
||||
mode = USB_TEST_MODE_PACKET;
|
||||
break;
|
||||
case 'F':
|
||||
case 'f':
|
||||
printf("Setting Test_Force_Enable mode");
|
||||
mode = USB_TEST_MODE_FORCE_ENABLE;
|
||||
break;
|
||||
default:
|
||||
printf("Unrecognized test mode: %s\nAvailable modes: "
|
||||
"J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (port)
|
||||
printf(" on downstream facing port %d...\n", port);
|
||||
else
|
||||
printf(" on upstream facing port...\n");
|
||||
|
||||
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE,
|
||||
port ? USB_RT_PORT : USB_RECIP_DEVICE,
|
||||
port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST,
|
||||
(mode << 8) | port,
|
||||
NULL, 0, USB_CNTL_TIMEOUT) == -1) {
|
||||
printf("Error during SET_FEATURE.\n");
|
||||
return 1;
|
||||
} else {
|
||||
printf("Test mode successfully set. Use 'usb start' "
|
||||
"to return to normal operation.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* usb boot command intepreter. Derived from diskboot
|
||||
*/
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
return common_diskboot(cmdtp, "usb", argc, argv);
|
||||
}
|
||||
#endif /* CONFIG_USB_STORAGE */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* usb command intepreter
|
||||
*/
|
||||
static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
|
||||
int i;
|
||||
struct usb_device *dev = NULL;
|
||||
extern char usb_started;
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
block_dev_desc_t *stor_dev;
|
||||
#endif
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if ((strncmp(argv[1], "reset", 5) == 0) ||
|
||||
(strncmp(argv[1], "start", 5) == 0)) {
|
||||
bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
|
||||
usb_stop();
|
||||
printf("(Re)start USB...\n");
|
||||
if (usb_init() >= 0) {
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
/* try to recognize storage devices immediately */
|
||||
usb_stor_curr_dev = usb_stor_scan(1);
|
||||
#endif
|
||||
#ifdef CONFIG_USB_HOST_ETHER
|
||||
/* try to recognize ethernet devices immediately */
|
||||
usb_ether_curr_dev = usb_host_eth_scan(1);
|
||||
#endif
|
||||
#ifdef CONFIG_USB_KEYBOARD
|
||||
drv_usb_kbd_init();
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "stop", 4) == 0) {
|
||||
#ifdef CONFIG_USB_KEYBOARD
|
||||
if (argc == 2) {
|
||||
if (usb_kbd_deregister() != 0) {
|
||||
printf("USB not stopped: usbkbd still"
|
||||
" using USB\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* forced stop, switch console in to serial */
|
||||
console_assign(stdin, "serial");
|
||||
usb_kbd_deregister();
|
||||
}
|
||||
#endif
|
||||
printf("stopping USB..\n");
|
||||
usb_stop();
|
||||
return 0;
|
||||
}
|
||||
if (!usb_started) {
|
||||
printf("USB is stopped. Please issue 'usb start' first.\n");
|
||||
return 1;
|
||||
}
|
||||
if (strncmp(argv[1], "tree", 4) == 0) {
|
||||
puts("USB device tree:\n");
|
||||
for (i = 0; i < USB_MAX_DEVICE; i++) {
|
||||
dev = usb_get_dev_index(i);
|
||||
if (dev == NULL)
|
||||
break;
|
||||
if (dev->parent == NULL)
|
||||
usb_show_tree(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "inf", 3) == 0) {
|
||||
int d;
|
||||
if (argc == 2) {
|
||||
for (d = 0; d < USB_MAX_DEVICE; d++) {
|
||||
dev = usb_get_dev_index(d);
|
||||
if (dev == NULL)
|
||||
break;
|
||||
usb_display_desc(dev);
|
||||
usb_display_config(dev);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
i = simple_strtoul(argv[2], NULL, 10);
|
||||
printf("config for device %d\n", i);
|
||||
dev = usb_find_device(i);
|
||||
if (dev == NULL) {
|
||||
printf("*** No device available ***\n");
|
||||
return 0;
|
||||
} else {
|
||||
usb_display_desc(dev);
|
||||
usb_display_config(dev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(argv[1], "test", 4) == 0) {
|
||||
if (argc < 5)
|
||||
return CMD_RET_USAGE;
|
||||
i = simple_strtoul(argv[2], NULL, 10);
|
||||
dev = usb_find_device(i);
|
||||
if (dev == NULL) {
|
||||
printf("Device %d does not exist.\n", i);
|
||||
return 1;
|
||||
}
|
||||
i = simple_strtoul(argv[3], NULL, 10);
|
||||
return usb_test(dev, i, argv[4]);
|
||||
}
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
if (strncmp(argv[1], "stor", 4) == 0)
|
||||
return usb_stor_info();
|
||||
|
||||
if (strncmp(argv[1], "part", 4) == 0) {
|
||||
int devno, ok = 0;
|
||||
if (argc == 2) {
|
||||
for (devno = 0; ; ++devno) {
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
if (stor_dev == NULL)
|
||||
break;
|
||||
if (stor_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
ok++;
|
||||
if (devno)
|
||||
printf("\n");
|
||||
debug("print_part of %x\n", devno);
|
||||
print_part(stor_dev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
devno = simple_strtoul(argv[2], NULL, 16);
|
||||
stor_dev = usb_stor_get_dev(devno);
|
||||
if (stor_dev != NULL &&
|
||||
stor_dev->type != DEV_TYPE_UNKNOWN) {
|
||||
ok++;
|
||||
debug("print_part of %x\n", devno);
|
||||
print_part(stor_dev);
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
printf("\nno USB devices available\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[1], "read") == 0) {
|
||||
if (usb_stor_curr_dev < 0) {
|
||||
printf("no current device selected\n");
|
||||
return 1;
|
||||
}
|
||||
if (argc == 5) {
|
||||
unsigned long addr = simple_strtoul(argv[2], NULL, 16);
|
||||
unsigned long blk = simple_strtoul(argv[3], NULL, 16);
|
||||
unsigned long cnt = simple_strtoul(argv[4], NULL, 16);
|
||||
unsigned long n;
|
||||
printf("\nUSB read: device %d block # %ld, count %ld"
|
||||
" ... ", usb_stor_curr_dev, blk, cnt);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt,
|
||||
(ulong *)addr);
|
||||
printf("%ld blocks read: %s\n", n,
|
||||
(n == cnt) ? "OK" : "ERROR");
|
||||
if (n == cnt)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (strcmp(argv[1], "write") == 0) {
|
||||
if (usb_stor_curr_dev < 0) {
|
||||
printf("no current device selected\n");
|
||||
return 1;
|
||||
}
|
||||
if (argc == 5) {
|
||||
unsigned long addr = simple_strtoul(argv[2], NULL, 16);
|
||||
unsigned long blk = simple_strtoul(argv[3], NULL, 16);
|
||||
unsigned long cnt = simple_strtoul(argv[4], NULL, 16);
|
||||
unsigned long n;
|
||||
printf("\nUSB write: device %d block # %ld, count %ld"
|
||||
" ... ", usb_stor_curr_dev, blk, cnt);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
n = stor_dev->block_write(usb_stor_curr_dev, blk, cnt,
|
||||
(ulong *)addr);
|
||||
printf("%ld blocks write: %s\n", n,
|
||||
(n == cnt) ? "OK" : "ERROR");
|
||||
if (n == cnt)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (strncmp(argv[1], "dev", 3) == 0) {
|
||||
if (argc == 3) {
|
||||
int dev = (int)simple_strtoul(argv[2], NULL, 10);
|
||||
printf("\nUSB device %d: ", dev);
|
||||
stor_dev = usb_stor_get_dev(dev);
|
||||
if (stor_dev == NULL) {
|
||||
printf("unknown device\n");
|
||||
return 1;
|
||||
}
|
||||
printf("\n Device %d: ", dev);
|
||||
dev_print(stor_dev);
|
||||
if (stor_dev->type == DEV_TYPE_UNKNOWN)
|
||||
return 1;
|
||||
usb_stor_curr_dev = dev;
|
||||
printf("... is now current device\n");
|
||||
return 0;
|
||||
} else {
|
||||
printf("\nUSB device %d: ", usb_stor_curr_dev);
|
||||
stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
|
||||
dev_print(stor_dev);
|
||||
if (stor_dev->type == DEV_TYPE_UNKNOWN)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_USB_STORAGE */
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
usb, 5, 1, do_usb,
|
||||
"usb - usb sub-system\n",
|
||||
"start - start (scan) USB controller\n"
|
||||
"usb reset - reset (rescan) USB controller\n"
|
||||
"usb stop [f] - stop USB [f]=force stop\n"
|
||||
"usb tree - show USB device tree\n"
|
||||
"usb info [dev] - show available USB devices\n"
|
||||
"usb test [dev] [port] [mode] - set USB 2.0 test mode\n"
|
||||
" (specify port 0 to indicate the device's upstream port)\n"
|
||||
" Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n"
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
"usb storage - show details of USB storage devices\n"
|
||||
"usb dev [dev] - show or set current USB storage device\n"
|
||||
"usb part [dev] - print partition table of one or all USB storage"
|
||||
" devices\n"
|
||||
"usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
|
||||
" to memory address `addr'\n"
|
||||
"usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
|
||||
" from memory address `addr'"
|
||||
#endif /* CONFIG_USB_STORAGE */
|
||||
);
|
||||
|
||||
/*
|
||||
#ifdef CONFIG_USB_STORAGE
|
||||
U_BOOT_CMD(
|
||||
usbboot, 3, 1, do_usbboot,
|
||||
"boot from USB device",
|
||||
"loadAddr dev:part"
|
||||
);
|
||||
#endif /* CONFIG_USB_STORAGE */
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Samsung Electronics
|
||||
* Lukasz Majewski <l.majewski@samsung.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <g_dnl.h>
|
||||
#include <usb_mass_storage.h>
|
||||
|
||||
int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
|
||||
int argc, char * const argv[])
|
||||
{
|
||||
char *ep;
|
||||
unsigned int dev_num = 0, offset = 0, part_size = 0;
|
||||
int rc;
|
||||
|
||||
struct ums_board_info *ums_info;
|
||||
static char *s = "ums";
|
||||
|
||||
if (argc < 2) {
|
||||
printf("usage: ums <dev> - e.g. ums 0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_num = (int)simple_strtoul(argv[1], &ep, 16);
|
||||
|
||||
if (dev_num) {
|
||||
puts("\nSet eMMC device to 0! - e.g. ums 0\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
board_usb_init();
|
||||
ums_info = board_ums_init(dev_num, offset, part_size);
|
||||
|
||||
if (!ums_info) {
|
||||
printf("MMC: %d -> NOT available\n", dev_num);
|
||||
goto fail;
|
||||
}
|
||||
rc = fsg_init(ums_info);
|
||||
if (rc) {
|
||||
printf("cmd ums: fsg_init failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
g_dnl_register(s);
|
||||
|
||||
while (1) {
|
||||
/* Handle control-c and timeouts */
|
||||
if (ctrlc()) {
|
||||
printf("The remote end did not respond in time.\n");
|
||||
goto exit;
|
||||
}
|
||||
usb_gadget_handle_interrupts();
|
||||
/* Check if USB cable has been detached */
|
||||
if (fsg_main_thread(NULL) == EIO)
|
||||
goto exit;
|
||||
}
|
||||
exit:
|
||||
g_dnl_unregister();
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(ums, CONFIG_SYS_MAXARGS, 1, do_usb_mass_storage,
|
||||
"Use the UMS [User Mass Storage]",
|
||||
"ums - User Mass Storage Gadget"
|
||||
);
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Command to load a splash screen to the VFDs.
|
||||
* NOTE that this will be controlled by a key combination when
|
||||
* the keyboard stuff works. For now the user has to enter a
|
||||
* bitmap number (only VFD_TEST_LOGO is supported now - 16.10.2002).
|
||||
* Added VFD_REMOTE_LOGO (same as VFD_TEST_LOGO but a different color)
|
||||
* on 20.10.2002.
|
||||
*
|
||||
* This rather crudely requires that each bitmap be included as a
|
||||
* header file.
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_VFD)
|
||||
|
||||
#include <vfd_logo.h>
|
||||
#define VFD_TEST_LOGO_BMPNR 0
|
||||
#define VFD_REMOTE_LOGO_BMPNR 1
|
||||
|
||||
extern int transfer_pic(unsigned char, unsigned char *, int, int);
|
||||
|
||||
int trab_vfd (ulong bitmap);
|
||||
|
||||
int do_vfd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong bitmap;
|
||||
|
||||
if (argc != 2) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argv[1][0] == '/') { /* select bitmap by number */
|
||||
bitmap = simple_strtoul(argv[1]+1, NULL, 10);
|
||||
return (trab_vfd(bitmap));
|
||||
}
|
||||
|
||||
/* display bitmap at given address */
|
||||
bitmap = simple_strtoul(argv[1], NULL, 16);
|
||||
transfer_pic(3, (uchar *)bitmap, VFD_LOGO_HEIGHT, VFD_LOGO_WIDTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
vfd, 2, 0, do_vfd,
|
||||
"vfd - load a bitmap to the VFDs on TRAB\n",
|
||||
"/N\n"
|
||||
" - load bitmap N to the VFDs (N is _decimal_ !!!)\n"
|
||||
"vfd ADDR\n"
|
||||
" - load bitmap at address ADDR\n"
|
||||
);
|
||||
#endif /* CFG_CMD_VFD */
|
||||
|
||||
#ifdef CONFIG_VFD
|
||||
int trab_vfd (ulong bitmap)
|
||||
{
|
||||
uchar *addr;
|
||||
char *s;
|
||||
|
||||
switch (bitmap) {
|
||||
case VFD_TEST_LOGO_BMPNR:
|
||||
if ((s = getenv ("bitmap0")) != NULL) {
|
||||
addr = (uchar *)simple_strtoul (s, NULL, 16);
|
||||
} else {
|
||||
addr = &vfd_test_logo_bitmap[0];
|
||||
}
|
||||
break;
|
||||
case VFD_REMOTE_LOGO_BMPNR:
|
||||
if ((s = getenv ("bitmap1")) != NULL) {
|
||||
addr = (uchar *)simple_strtoul (s, NULL, 16);
|
||||
} else {
|
||||
addr = &vfd_remote_logo_bitmap[0];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Unknown bitmap %ld\n", bitmap);
|
||||
return 1;
|
||||
}
|
||||
transfer_pic(3, addr, VFD_LOGO_HEIGHT, VFD_LOGO_WIDTH);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_VFD */
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2004
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2003
|
||||
* Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.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
|
||||
*/
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_XIMG)
|
||||
|
||||
/*
|
||||
* Multi Image extract
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <image.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
int
|
||||
do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
ulong addr = load_addr, dest = 0;
|
||||
ulong data, len, checksum;
|
||||
ulong *len_ptr;
|
||||
int i, verify, part = 0;
|
||||
char pbuf[10], *s;
|
||||
image_header_t header;
|
||||
|
||||
s = getenv("verify");
|
||||
verify = (s && (*s == 'n')) ? 0 : 1;
|
||||
|
||||
if (argc > 1) {
|
||||
addr = simple_strtoul(argv[1], NULL, 16);
|
||||
}
|
||||
if (argc > 2) {
|
||||
part = simple_strtoul(argv[2], NULL, 16);
|
||||
}
|
||||
if (argc > 3) {
|
||||
dest = simple_strtoul(argv[3], NULL, 16);
|
||||
}
|
||||
|
||||
printf("## Copying from image at %08lx ...\n", addr);
|
||||
|
||||
/* Copy header so we can blank CRC field for re-calculation */
|
||||
memmove(&header, (char *) addr, sizeof (image_header_t));
|
||||
|
||||
if (ntohl(header.ih_magic) != IH_MAGIC) {
|
||||
printf("Bad Magic Number\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
data = (ulong) & header;
|
||||
len = sizeof (image_header_t);
|
||||
|
||||
checksum = ntohl(header.ih_hcrc);
|
||||
header.ih_hcrc = 0;
|
||||
|
||||
if (crc32(0, (char *) data, len) != checksum) {
|
||||
printf("Bad Header Checksum\n");
|
||||
return 1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
print_image_hdr((image_header_t *) addr);
|
||||
#endif
|
||||
|
||||
data = addr + sizeof (image_header_t);
|
||||
len = ntohl(header.ih_size);
|
||||
|
||||
if (header.ih_type != IH_TYPE_MULTI) {
|
||||
printf("Wrong Image Type for %s command\n", cmdtp->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (header.ih_comp != IH_COMP_NONE) {
|
||||
printf("Wrong Compression Type for %s command\n", cmdtp->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
printf(" Verifying Checksum ... ");
|
||||
if (crc32(0, (char *) data, len) != ntohl(header.ih_dcrc)) {
|
||||
printf("Bad Data CRC\n");
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
}
|
||||
|
||||
len_ptr = (ulong *) data;
|
||||
|
||||
data += 4; /* terminator */
|
||||
for (i = 0; len_ptr[i]; ++i) {
|
||||
data += 4;
|
||||
if (argc > 2 && part > i) {
|
||||
u_long tail;
|
||||
len = ntohl(len_ptr[i]);
|
||||
tail = len % 4;
|
||||
data += len;
|
||||
if (tail) {
|
||||
data += 4 - tail;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (argc > 2 && part >= i) {
|
||||
printf("Bad Image Part\n");
|
||||
return 1;
|
||||
}
|
||||
len = ntohl(len_ptr[part]);
|
||||
|
||||
if (argc > 3) {
|
||||
memcpy((char *) dest, (char *) data, len);
|
||||
}
|
||||
|
||||
sprintf(pbuf, "%8lx", data);
|
||||
setenv("fileaddr", pbuf);
|
||||
sprintf(pbuf, "%8lx", len);
|
||||
setenv("filesize", pbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(imxtract, 4, 1, do_imgextract,
|
||||
"imxtract- extract a part of a multi-image\n",
|
||||
"addr part [dest]\n"
|
||||
" - extract <part> from image at <addr> and copy to <dest>\n");
|
||||
|
||||
#endif /* CONFIG_COMMANDS & CFG_CMD_XIMG */
|
|
@ -0,0 +1,660 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2003
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Command Processor Table
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
|
||||
int
|
||||
do_version (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
extern char version_string[];
|
||||
printf ("\n%s\n", version_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
version, 1, 1, do_version,
|
||||
"version - print monitor version\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_ECHO)
|
||||
|
||||
int
|
||||
do_echo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i, putnl = 1;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *p = argv[i], c;
|
||||
|
||||
if (i > 1)
|
||||
putc(' ');
|
||||
while ((c = *p++) != '\0') {
|
||||
if (c == '\\' && *p == 'c') {
|
||||
putnl = 0;
|
||||
p++;
|
||||
} else {
|
||||
putc(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (putnl)
|
||||
putc('\n');
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
echo, CFG_MAXARGS, 1, do_echo,
|
||||
"echo - echo args to console\n",
|
||||
"[args..]\n"
|
||||
" - echo args to console; \\c suppresses newline\n"
|
||||
);
|
||||
|
||||
#endif /* CFG_CMD_ECHO */
|
||||
|
||||
#ifndef COMPRESSED_UBOOT
|
||||
#ifdef CFG_HUSH_PARSER
|
||||
|
||||
int
|
||||
do_test (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
char **ap;
|
||||
int left, adv, expr, last_expr, neg, last_cmp;
|
||||
|
||||
/* args? */
|
||||
if (argc < 3)
|
||||
return 1;
|
||||
|
||||
#if 0
|
||||
{
|
||||
printf("test:");
|
||||
left = 1;
|
||||
while (argv[left])
|
||||
printf(" %s", argv[left++]);
|
||||
}
|
||||
#endif
|
||||
|
||||
last_expr = 0;
|
||||
left = argc - 1; ap = argv + 1;
|
||||
if (left > 0 && strcmp(ap[0], "!") == 0) {
|
||||
neg = 1;
|
||||
ap++;
|
||||
left--;
|
||||
} else
|
||||
neg = 0;
|
||||
|
||||
expr = -1;
|
||||
last_cmp = -1;
|
||||
last_expr = -1;
|
||||
while (left > 0) {
|
||||
|
||||
if (strcmp(ap[0], "-o") == 0 || strcmp(ap[0], "-a") == 0)
|
||||
adv = 1;
|
||||
else if (strcmp(ap[0], "-z") == 0 || strcmp(ap[0], "-n") == 0)
|
||||
adv = 2;
|
||||
else
|
||||
adv = 3;
|
||||
|
||||
if (left < adv) {
|
||||
expr = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (adv == 1) {
|
||||
if (strcmp(ap[0], "-o") == 0) {
|
||||
last_expr = expr;
|
||||
last_cmp = 0;
|
||||
} else if (strcmp(ap[0], "-a") == 0) {
|
||||
last_expr = expr;
|
||||
last_cmp = 1;
|
||||
} else {
|
||||
expr = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (adv == 2) {
|
||||
if (strcmp(ap[0], "-z") == 0)
|
||||
expr = strlen(ap[1]) == 0 ? 1 : 0;
|
||||
else if (strcmp(ap[0], "-n") == 0)
|
||||
expr = strlen(ap[1]) == 0 ? 0 : 1;
|
||||
else {
|
||||
expr = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (last_cmp == 0)
|
||||
expr = last_expr || expr;
|
||||
else if (last_cmp == 1)
|
||||
expr = last_expr && expr;
|
||||
last_cmp = -1;
|
||||
}
|
||||
|
||||
if (adv == 3) {
|
||||
if (strcmp(ap[1], "=") == 0)
|
||||
expr = strcmp(ap[0], ap[2]) == 0;
|
||||
else if (strcmp(ap[1], "!=") == 0)
|
||||
expr = strcmp(ap[0], ap[2]) != 0;
|
||||
else if (strcmp(ap[1], ">") == 0)
|
||||
expr = strcmp(ap[0], ap[2]) > 0;
|
||||
else if (strcmp(ap[1], "<") == 0)
|
||||
expr = strcmp(ap[0], ap[2]) < 0;
|
||||
else if (strcmp(ap[1], "-eq") == 0)
|
||||
expr = simple_strtol(ap[0], NULL, 10) == simple_strtol(ap[2], NULL, 10);
|
||||
else if (strcmp(ap[1], "-ne") == 0)
|
||||
expr = simple_strtol(ap[0], NULL, 10) != simple_strtol(ap[2], NULL, 10);
|
||||
else if (strcmp(ap[1], "-lt") == 0)
|
||||
expr = simple_strtol(ap[0], NULL, 10) < simple_strtol(ap[2], NULL, 10);
|
||||
else if (strcmp(ap[1], "-le") == 0)
|
||||
expr = simple_strtol(ap[0], NULL, 10) <= simple_strtol(ap[2], NULL, 10);
|
||||
else if (strcmp(ap[1], "-gt") == 0)
|
||||
expr = simple_strtol(ap[0], NULL, 10) > simple_strtol(ap[2], NULL, 10);
|
||||
else if (strcmp(ap[1], "-ge") == 0)
|
||||
expr = simple_strtol(ap[0], NULL, 10) >= simple_strtol(ap[2], NULL, 10);
|
||||
else {
|
||||
expr = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (last_cmp == 0)
|
||||
expr = last_expr || expr;
|
||||
else if (last_cmp == 1)
|
||||
expr = last_expr && expr;
|
||||
last_cmp = -1;
|
||||
}
|
||||
|
||||
ap += adv; left -= adv;
|
||||
}
|
||||
|
||||
if (neg)
|
||||
expr = !expr;
|
||||
|
||||
expr = !expr;
|
||||
|
||||
#if 0
|
||||
printf(": returns %d\n", expr);
|
||||
#endif
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
test, CFG_MAXARGS, 1, do_test,
|
||||
"test - minimal test like /bin/sh\n",
|
||||
"[args..]\n"
|
||||
" - test functionality\n"
|
||||
);
|
||||
|
||||
int
|
||||
do_exit (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int r;
|
||||
|
||||
r = 0;
|
||||
if (argc > 1)
|
||||
r = simple_strtoul(argv[1], NULL, 10);
|
||||
|
||||
return -r - 2;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
exit, 2, 1, do_exit,
|
||||
"exit - exit script\n",
|
||||
" - exit functionality\n"
|
||||
);
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* #ifdef COMPRESSED_UBOOT */
|
||||
|
||||
/*
|
||||
* Use puts() instead of printf() to avoid printf buffer overflow
|
||||
* for long help messages
|
||||
*/
|
||||
int do_help (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
int rcode = 0;
|
||||
|
||||
if (argc == 1) { /*show list of commands */
|
||||
|
||||
int cmd_items = &__u_boot_cmd_end -
|
||||
&__u_boot_cmd_start; /* pointer arith! */
|
||||
cmd_tbl_t *cmd_array[cmd_items];
|
||||
int i, j, swaps;
|
||||
|
||||
/* Make array of commands from .uboot_cmd section */
|
||||
cmdtp = &__u_boot_cmd_start;
|
||||
for (i = 0; i < cmd_items; i++) {
|
||||
cmd_array[i] = cmdtp++;
|
||||
}
|
||||
|
||||
/* Sort command list (trivial bubble sort) */
|
||||
for (i = cmd_items - 1; i > 0; --i) {
|
||||
swaps = 0;
|
||||
for (j = 0; j < i; ++j) {
|
||||
if (strcmp (cmd_array[j]->name,
|
||||
cmd_array[j + 1]->name) > 0) {
|
||||
cmd_tbl_t *tmp;
|
||||
tmp = cmd_array[j];
|
||||
cmd_array[j] = cmd_array[j + 1];
|
||||
cmd_array[j + 1] = tmp;
|
||||
++swaps;
|
||||
}
|
||||
}
|
||||
if (!swaps)
|
||||
break;
|
||||
}
|
||||
|
||||
/* print short help (usage) */
|
||||
for (i = 0; i < cmd_items; i++) {
|
||||
const char *usage = cmd_array[i]->usage;
|
||||
|
||||
/* allow user abort */
|
||||
if (ctrlc ())
|
||||
return 1;
|
||||
if (usage == NULL)
|
||||
continue;
|
||||
puts (usage);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* command help (long version)
|
||||
*/
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if ((cmdtp = find_cmd (argv[i])) != NULL) {
|
||||
#ifdef CFG_LONGHELP
|
||||
/* found - print (long) help info */
|
||||
puts (cmdtp->name);
|
||||
putc (' ');
|
||||
if (cmdtp->help) {
|
||||
puts (cmdtp->help);
|
||||
} else {
|
||||
puts ("- No help available.\n");
|
||||
rcode = 1;
|
||||
}
|
||||
putc ('\n');
|
||||
#else /* no long help available */
|
||||
if (cmdtp->usage)
|
||||
puts (cmdtp->usage);
|
||||
#endif /* CFG_LONGHELP */
|
||||
} else {
|
||||
printf ("Unknown command '%s' - try 'help'"
|
||||
" without arguments for list of all"
|
||||
" known commands\n\n", argv[i]
|
||||
);
|
||||
rcode = 1;
|
||||
}
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
|
||||
U_BOOT_CMD(
|
||||
help, CFG_MAXARGS, 1, do_help,
|
||||
"help - print online help\n",
|
||||
"[command ...]\n"
|
||||
" - show help information (for 'command')\n"
|
||||
"'help' prints online help for the monitor commands.\n\n"
|
||||
"Without arguments, it prints a short usage message for all commands.\n\n"
|
||||
"To get detailed help information for specific commands you can type\n"
|
||||
"'help' with one or more command names as arguments.\n"
|
||||
);
|
||||
|
||||
/* This do not ust the U_BOOT_CMD macro as ? can't be used in symbol names */
|
||||
#ifdef CFG_LONGHELP
|
||||
cmd_tbl_t __u_boot_cmd_question_mark Struct_Section = {
|
||||
"?", CFG_MAXARGS, 1, do_help,
|
||||
"? - alias for 'help'\n",
|
||||
NULL
|
||||
};
|
||||
#else
|
||||
cmd_tbl_t __u_boot_cmd_question_mark Struct_Section = {
|
||||
"?", CFG_MAXARGS, 1, do_help,
|
||||
"? - alias for 'help'\n"
|
||||
};
|
||||
#endif /* CFG_LONGHELP */
|
||||
|
||||
/***************************************************************************
|
||||
* find command table entry for a command
|
||||
*/
|
||||
cmd_tbl_t *find_cmd (const char *cmd)
|
||||
{
|
||||
cmd_tbl_t *cmdtp;
|
||||
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
|
||||
const char *p;
|
||||
int len;
|
||||
int n_found = 0;
|
||||
|
||||
/*
|
||||
* Some commands allow length modifiers (like "cp.b");
|
||||
* compare command name only until first dot.
|
||||
*/
|
||||
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
|
||||
|
||||
for (cmdtp = &__u_boot_cmd_start;
|
||||
cmdtp != &__u_boot_cmd_end;
|
||||
cmdtp++) {
|
||||
if (strncmp (cmd, cmdtp->name, len) == 0) {
|
||||
if (len == strlen (cmdtp->name))
|
||||
return cmdtp; /* full match */
|
||||
|
||||
cmdtp_temp = cmdtp; /* abbreviated command ? */
|
||||
n_found++;
|
||||
}
|
||||
}
|
||||
if (n_found == 1) { /* exactly one match */
|
||||
return cmdtp_temp;
|
||||
}
|
||||
|
||||
return NULL; /* not found or ambiguous command */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AUTO_COMPLETE
|
||||
|
||||
int var_complete(int argc, char *argv[], char last_char, int maxv, char *cmdv[])
|
||||
{
|
||||
static char tmp_buf[512];
|
||||
int space;
|
||||
|
||||
space = last_char == '\0' || last_char == ' ' || last_char == '\t';
|
||||
|
||||
if (space && argc == 1)
|
||||
return env_complete("", maxv, cmdv, sizeof(tmp_buf), tmp_buf);
|
||||
|
||||
if (!space && argc == 2)
|
||||
return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void install_auto_complete_handler(const char *cmd,
|
||||
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]))
|
||||
{
|
||||
cmd_tbl_t *cmdtp;
|
||||
|
||||
cmdtp = find_cmd(cmd);
|
||||
if (cmdtp == NULL)
|
||||
return;
|
||||
|
||||
cmdtp->complete = complete;
|
||||
}
|
||||
|
||||
void install_auto_complete(void)
|
||||
{
|
||||
install_auto_complete_handler("printenv", var_complete);
|
||||
install_auto_complete_handler("setenv", var_complete);
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_RUN)
|
||||
install_auto_complete_handler("run", var_complete);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
|
||||
static int complete_cmdv(int argc, char *argv[], char last_char, int maxv, char *cmdv[])
|
||||
{
|
||||
cmd_tbl_t *cmdtp;
|
||||
const char *p;
|
||||
int len, clen;
|
||||
int n_found = 0;
|
||||
const char *cmd;
|
||||
|
||||
/* sanity? */
|
||||
if (maxv < 2)
|
||||
return -2;
|
||||
|
||||
cmdv[0] = NULL;
|
||||
|
||||
if (argc == 0) {
|
||||
/* output full list of commands */
|
||||
for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) {
|
||||
if (n_found >= maxv - 2) {
|
||||
cmdv[n_found++] = "...";
|
||||
break;
|
||||
}
|
||||
cmdv[n_found++] = cmdtp->name;
|
||||
}
|
||||
cmdv[n_found] = NULL;
|
||||
return n_found;
|
||||
}
|
||||
|
||||
/* more than one arg or one but the start of the next */
|
||||
if (argc > 1 || (last_char == '\0' || last_char == ' ' || last_char == '\t')) {
|
||||
cmdtp = find_cmd(argv[0]);
|
||||
if (cmdtp == NULL || cmdtp->complete == NULL) {
|
||||
cmdv[0] = NULL;
|
||||
return 0;
|
||||
}
|
||||
return (*cmdtp->complete)(argc, argv, last_char, maxv, cmdv);
|
||||
}
|
||||
|
||||
cmd = argv[0];
|
||||
/*
|
||||
* Some commands allow length modifiers (like "cp.b");
|
||||
* compare command name only until first dot.
|
||||
*/
|
||||
p = strchr(cmd, '.');
|
||||
if (p == NULL)
|
||||
len = strlen(cmd);
|
||||
else
|
||||
len = p - cmd;
|
||||
|
||||
/* return the partial matches */
|
||||
for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) {
|
||||
|
||||
clen = strlen(cmdtp->name);
|
||||
if (clen < len)
|
||||
continue;
|
||||
|
||||
if (memcmp(cmd, cmdtp->name, len) != 0)
|
||||
continue;
|
||||
|
||||
/* too many! */
|
||||
if (n_found >= maxv - 2) {
|
||||
cmdv[n_found++] = "...";
|
||||
break;
|
||||
}
|
||||
|
||||
cmdv[n_found++] = cmdtp->name;
|
||||
}
|
||||
|
||||
cmdv[n_found] = NULL;
|
||||
return n_found;
|
||||
}
|
||||
|
||||
static int make_argv(char *s, int argvsz, char *argv[])
|
||||
{
|
||||
int argc = 0;
|
||||
|
||||
/* split into argv */
|
||||
while (argc < argvsz - 1) {
|
||||
|
||||
/* skip any white space */
|
||||
while ((*s == ' ') || (*s == '\t'))
|
||||
++s;
|
||||
|
||||
if (*s == '\0') /* end of s, no more args */
|
||||
break;
|
||||
|
||||
argv[argc++] = s; /* begin of argument string */
|
||||
|
||||
/* find end of string */
|
||||
while (*s && (*s != ' ') && (*s != '\t'))
|
||||
++s;
|
||||
|
||||
if (*s == '\0') /* end of s, no more args */
|
||||
break;
|
||||
|
||||
*s++ = '\0'; /* terminate current arg */
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
static void print_argv(const char *banner, const char *leader, const char *sep, int linemax, char *argv[])
|
||||
{
|
||||
int ll = leader != NULL ? strlen(leader) : 0;
|
||||
int sl = sep != NULL ? strlen(sep) : 0;
|
||||
int len, i;
|
||||
|
||||
if (banner) {
|
||||
puts("\n");
|
||||
puts(banner);
|
||||
}
|
||||
|
||||
i = linemax; /* force leader and newline */
|
||||
while (*argv != NULL) {
|
||||
len = strlen(*argv) + sl;
|
||||
if (i + len >= linemax) {
|
||||
puts("\n");
|
||||
if (leader)
|
||||
puts(leader);
|
||||
i = ll - sl;
|
||||
} else if (sep)
|
||||
puts(sep);
|
||||
puts(*argv++);
|
||||
i += len;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int find_common_prefix(char *argv[])
|
||||
{
|
||||
int i, len;
|
||||
char *anchor, *s, *t;
|
||||
|
||||
if (*argv == NULL)
|
||||
return 0;
|
||||
|
||||
/* begin with max */
|
||||
anchor = *argv++;
|
||||
len = strlen(anchor);
|
||||
while ((t = *argv++) != NULL) {
|
||||
s = anchor;
|
||||
for (i = 0; i < len; i++, t++, s++) {
|
||||
if (*t != *s)
|
||||
break;
|
||||
}
|
||||
len = s - anchor;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static char tmp_buf[CFG_CBSIZE]; /* copy of console I/O buffer */
|
||||
|
||||
int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp)
|
||||
{
|
||||
int n = *np, col = *colp;
|
||||
char *argv[CFG_MAXARGS + 1]; /* NULL terminated */
|
||||
char *cmdv[20];
|
||||
char *s, *t;
|
||||
const char *sep;
|
||||
int i, j, k, len, seplen, argc;
|
||||
int cnt;
|
||||
char last_char;
|
||||
|
||||
if (strcmp(prompt, CFG_PROMPT) != 0)
|
||||
return 0; /* not in normal console */
|
||||
|
||||
cnt = strlen(buf);
|
||||
if (cnt >= 1)
|
||||
last_char = buf[cnt - 1];
|
||||
else
|
||||
last_char = '\0';
|
||||
|
||||
/* copy to secondary buffer which will be affected */
|
||||
strcpy(tmp_buf, buf);
|
||||
|
||||
/* separate into argv */
|
||||
argc = make_argv(tmp_buf, sizeof(argv)/sizeof(argv[0]), argv);
|
||||
|
||||
/* do the completion and return the possible completions */
|
||||
i = complete_cmdv(argc, argv, last_char, sizeof(cmdv)/sizeof(cmdv[0]), cmdv);
|
||||
|
||||
/* no match; bell and out */
|
||||
if (i == 0) {
|
||||
if (argc > 1) /* allow tab for non command */
|
||||
return 0;
|
||||
putc('\a');
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = NULL;
|
||||
len = 0;
|
||||
sep = NULL;
|
||||
seplen = 0;
|
||||
if (i == 1) { /* one match; perfect */
|
||||
k = strlen(argv[argc - 1]);
|
||||
s = cmdv[0] + k;
|
||||
len = strlen(s);
|
||||
sep = " ";
|
||||
seplen = 1;
|
||||
} else if (i > 1 && (j = find_common_prefix(cmdv)) != 0) { /* more */
|
||||
k = strlen(argv[argc - 1]);
|
||||
j -= k;
|
||||
if (j > 0) {
|
||||
s = cmdv[0] + k;
|
||||
len = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (s != NULL) {
|
||||
k = len + seplen;
|
||||
/* make sure it fits */
|
||||
if (n + k >= CFG_CBSIZE - 2) {
|
||||
putc('\a');
|
||||
return 1;
|
||||
}
|
||||
|
||||
t = buf + cnt;
|
||||
for (i = 0; i < len; i++)
|
||||
*t++ = *s++;
|
||||
if (sep != NULL)
|
||||
for (i = 0; i < seplen; i++)
|
||||
*t++ = sep[i];
|
||||
*t = '\0';
|
||||
n += k;
|
||||
col += k;
|
||||
puts(t - k);
|
||||
if (sep == NULL)
|
||||
putc('\a');
|
||||
*np = n;
|
||||
*colp = col;
|
||||
} else {
|
||||
print_argv(NULL, " ", " ", 78, cmdv);
|
||||
|
||||
puts(prompt);
|
||||
puts(buf);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,572 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
|
||||
*
|
||||
* 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 <stdarg.h>
|
||||
#include <malloc.h>
|
||||
#include <console.h>
|
||||
#include <exports.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
int console_changed = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CFG_CONSOLE_IS_IN_ENV
|
||||
/*
|
||||
* if overwrite_console returns 1, the stdin, stderr and stdout
|
||||
* are switched to the serial port, else the settings in the
|
||||
* environment are used
|
||||
*/
|
||||
#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
|
||||
extern int overwrite_console (void);
|
||||
#define OVERWRITE_CONSOLE overwrite_console ()
|
||||
#else
|
||||
#define OVERWRITE_CONSOLE 0
|
||||
#endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */
|
||||
|
||||
#endif /* CFG_CONSOLE_IS_IN_ENV */
|
||||
|
||||
static int console_setfile (int file, device_t * dev)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (dev == NULL)
|
||||
return -1;
|
||||
|
||||
switch (file) {
|
||||
case stdin:
|
||||
case stdout:
|
||||
case stderr:
|
||||
/* Start new device */
|
||||
if (dev->start) {
|
||||
error = dev->start ();
|
||||
/* If it's not started dont use it */
|
||||
if (error < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Assign the new device (leaving the existing one started) */
|
||||
stdio_devices[file] = dev;
|
||||
|
||||
/*
|
||||
* Update monitor functions
|
||||
* (to use the console stuff by other applications)
|
||||
*/
|
||||
switch (file) {
|
||||
case stdin:
|
||||
gd->jt[XF_getc] = dev->getc;
|
||||
gd->jt[XF_tstc] = dev->tstc;
|
||||
break;
|
||||
case stdout:
|
||||
gd->jt[XF_putc] = dev->putc;
|
||||
gd->jt[XF_puts] = dev->puts;
|
||||
gd->jt[XF_printf] = printf;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* Invalid file ID */
|
||||
error = -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
|
||||
|
||||
void serial_printf (const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
serial_puts (printbuffer);
|
||||
}
|
||||
|
||||
int fgetc (int file)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
return stdio_devices[file]->getc ();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ftstc (int file)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
return stdio_devices[file]->tstc ();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void fputc (int file, const char c)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
stdio_devices[file]->putc (c);
|
||||
}
|
||||
|
||||
void fputs (int file, const char *s)
|
||||
{
|
||||
if (file < MAX_FILES)
|
||||
stdio_devices[file]->puts (s);
|
||||
}
|
||||
|
||||
void fprintf (int file, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
/* Send to desired file */
|
||||
fputs (file, printbuffer);
|
||||
}
|
||||
|
||||
/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
|
||||
|
||||
int getc (void)
|
||||
{
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Get from the standard input */
|
||||
return fgetc (stdin);
|
||||
}
|
||||
|
||||
/* Send directly to the handler */
|
||||
return serial_getc ();
|
||||
}
|
||||
|
||||
int tstc (void)
|
||||
{
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Test the standard input */
|
||||
return ftstc (stdin);
|
||||
}
|
||||
|
||||
/* Send directly to the handler */
|
||||
return serial_tstc ();
|
||||
}
|
||||
|
||||
void putc (const char c)
|
||||
{
|
||||
#ifdef CONFIG_SILENT_CONSOLE
|
||||
if (gd->flags & GD_FLG_SILENT)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Send to the standard output */
|
||||
fputc (stdout, c);
|
||||
} else {
|
||||
/* Send directly to the handler */
|
||||
serial_putc (c);
|
||||
}
|
||||
}
|
||||
|
||||
void puts (const char *s)
|
||||
{
|
||||
#ifdef CONFIG_SILENT_CONSOLE
|
||||
if (gd->flags & GD_FLG_SILENT)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (gd->flags & GD_FLG_DEVINIT) {
|
||||
/* Send to the standard output */
|
||||
fputs (stdout, s);
|
||||
} else {
|
||||
/* Send directly to the handler */
|
||||
serial_puts (s);
|
||||
}
|
||||
}
|
||||
|
||||
void printf (const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
/* Print the string */
|
||||
puts (printbuffer);
|
||||
}
|
||||
|
||||
void vprintf (const char *fmt, va_list args)
|
||||
{
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
|
||||
/* Print the string */
|
||||
puts (printbuffer);
|
||||
}
|
||||
|
||||
/* test if ctrl-c was pressed */
|
||||
static int ctrlc_disabled = 0; /* see disable_ctrl() */
|
||||
static int ctrlc_was_pressed = 0;
|
||||
int ctrlc (void)
|
||||
{
|
||||
if (!ctrlc_disabled && gd->have_console) {
|
||||
if (tstc ()) {
|
||||
switch (getc ()) {
|
||||
case 0x03: /* ^C - Control C */
|
||||
ctrlc_was_pressed = 1;
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pass 1 to disable ctrlc() checking, 0 to enable.
|
||||
* returns previous state
|
||||
*/
|
||||
int disable_ctrlc (int disable)
|
||||
{
|
||||
int prev = ctrlc_disabled; /* save previous state */
|
||||
|
||||
ctrlc_disabled = disable;
|
||||
return prev;
|
||||
}
|
||||
|
||||
int had_ctrlc (void)
|
||||
{
|
||||
return ctrlc_was_pressed;
|
||||
}
|
||||
|
||||
void clear_ctrlc (void)
|
||||
{
|
||||
ctrlc_was_pressed = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODEM_SUPPORT_DEBUG
|
||||
char screen[1024];
|
||||
char *cursor = screen;
|
||||
int once = 0;
|
||||
inline void dbg(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[CFG_PBSIZE];
|
||||
|
||||
if (!once) {
|
||||
memset(screen, 0, sizeof(screen));
|
||||
once++;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf(printbuffer, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) {
|
||||
memset(screen, 0, sizeof(screen));
|
||||
cursor = screen;
|
||||
}
|
||||
sprintf(cursor, printbuffer);
|
||||
cursor += strlen(printbuffer);
|
||||
|
||||
}
|
||||
#else
|
||||
inline void dbg(const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/** U-Boot INIT FUNCTIONS *************************************************/
|
||||
|
||||
int console_assign (int file, char *devname)
|
||||
{
|
||||
int flag, i;
|
||||
|
||||
/* Check for valid file */
|
||||
switch (file) {
|
||||
case stdin:
|
||||
flag = DEV_FLAGS_INPUT;
|
||||
break;
|
||||
case stdout:
|
||||
case stderr:
|
||||
flag = DEV_FLAGS_OUTPUT;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check for valid device name */
|
||||
|
||||
for (i = 1; i <= ListNumItems (devlist); i++) {
|
||||
device_t *dev = ListGetPtrToItem (devlist, i);
|
||||
|
||||
if (strcmp (devname, dev->name) == 0) {
|
||||
if (dev->flags & flag)
|
||||
return console_setfile (file, dev);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Called before relocation - use serial functions */
|
||||
int console_init_f (void)
|
||||
{
|
||||
gd->have_console = 1;
|
||||
|
||||
#ifdef CONFIG_SILENT_CONSOLE
|
||||
if (getenv("silent") != NULL)
|
||||
gd->flags |= GD_FLG_SILENT;
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(CFG_CONSOLE_IS_IN_ENV) || defined(CONFIG_SPLASH_SCREEN) || defined(CONFIG_SILENT_CONSOLE)
|
||||
/* search a device */
|
||||
device_t *search_device (int flags, char *name)
|
||||
{
|
||||
int i, items;
|
||||
device_t *dev = NULL;
|
||||
|
||||
items = ListNumItems (devlist);
|
||||
if (name == NULL)
|
||||
return dev;
|
||||
|
||||
for (i = 1; i <= items; i++) {
|
||||
dev = ListGetPtrToItem (devlist, i);
|
||||
if ((dev->flags & flags) && (strcmp (name, dev->name) == 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
#endif /* CFG_CONSOLE_IS_IN_ENV || CONFIG_SPLASH_SCREEN */
|
||||
|
||||
#ifdef CFG_CONSOLE_IS_IN_ENV
|
||||
/* Called after the relocation - use desired console functions */
|
||||
int console_init_r (void)
|
||||
{
|
||||
char *stdinname, *stdoutname, *stderrname;
|
||||
device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
|
||||
#ifdef CFG_CONSOLE_ENV_OVERWRITE
|
||||
int i;
|
||||
#endif /* CFG_CONSOLE_ENV_OVERWRITE */
|
||||
|
||||
/* set default handlers at first */
|
||||
gd->jt[XF_getc] = serial_getc;
|
||||
gd->jt[XF_tstc] = serial_tstc;
|
||||
gd->jt[XF_putc] = serial_putc;
|
||||
gd->jt[XF_puts] = serial_puts;
|
||||
gd->jt[XF_printf] = serial_printf;
|
||||
|
||||
/* stdin stdout and stderr are in environment */
|
||||
/* scan for it */
|
||||
stdinname = getenv ("stdin");
|
||||
stdoutname = getenv ("stdout");
|
||||
stderrname = getenv ("stderr");
|
||||
|
||||
if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */
|
||||
inputdev = search_device (DEV_FLAGS_INPUT, stdinname);
|
||||
outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname);
|
||||
errdev = search_device (DEV_FLAGS_OUTPUT, stderrname);
|
||||
}
|
||||
/* if the devices are overwritten or not found, use default device */
|
||||
if (inputdev == NULL) {
|
||||
inputdev = search_device (DEV_FLAGS_INPUT, "serial");
|
||||
}
|
||||
if (outputdev == NULL) {
|
||||
outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
|
||||
}
|
||||
if (errdev == NULL) {
|
||||
errdev = search_device (DEV_FLAGS_OUTPUT, "serial");
|
||||
}
|
||||
/* Initializes output console first */
|
||||
if (outputdev != NULL) {
|
||||
console_setfile (stdout, outputdev);
|
||||
}
|
||||
if (errdev != NULL) {
|
||||
console_setfile (stderr, errdev);
|
||||
}
|
||||
if (inputdev != NULL) {
|
||||
console_setfile (stdin, inputdev);
|
||||
}
|
||||
|
||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||
|
||||
#ifndef CFG_CONSOLE_INFO_QUIET
|
||||
/* Print information */
|
||||
puts ("In: ");
|
||||
if (stdio_devices[stdin] == NULL) {
|
||||
puts ("No input devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdin]->name);
|
||||
}
|
||||
|
||||
puts ("Out: ");
|
||||
if (stdio_devices[stdout] == NULL) {
|
||||
puts ("No output devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdout]->name);
|
||||
}
|
||||
|
||||
puts ("Err: ");
|
||||
if (stdio_devices[stderr] == NULL) {
|
||||
puts ("No error devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stderr]->name);
|
||||
}
|
||||
#endif /* CFG_CONSOLE_INFO_QUIET */
|
||||
|
||||
#ifdef CFG_CONSOLE_ENV_OVERWRITE
|
||||
/* set the environment variables (will overwrite previous env settings) */
|
||||
for (i = 0; i < 3; i++) {
|
||||
setenv (stdio_names[i], stdio_devices[i]->name);
|
||||
}
|
||||
#endif /* CFG_CONSOLE_ENV_OVERWRITE */
|
||||
|
||||
#if 0
|
||||
/* If nothing usable installed, use only the initial console */
|
||||
if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else /* CFG_CONSOLE_IS_IN_ENV */
|
||||
|
||||
/* Called after the relocation - use desired console functions */
|
||||
int console_init_r (void)
|
||||
{
|
||||
device_t *inputdev = NULL, *outputdev = NULL;
|
||||
int i, items = ListNumItems (devlist);
|
||||
|
||||
#ifdef CONFIG_SPLASH_SCREEN
|
||||
/* suppress all output if splash screen is enabled and we have
|
||||
a bmp to display */
|
||||
if (getenv("splashimage") != NULL)
|
||||
outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SILENT_CONSOLE
|
||||
/* Suppress all output if "silent" mode requested */
|
||||
if (gd->flags & GD_FLG_SILENT)
|
||||
outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev");
|
||||
#endif
|
||||
|
||||
/* Scan devices looking for input and output devices */
|
||||
for (i = 1;
|
||||
(i <= items) && ((inputdev == NULL) || (outputdev == NULL));
|
||||
i++
|
||||
) {
|
||||
device_t *dev = ListGetPtrToItem (devlist, i);
|
||||
|
||||
if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
|
||||
inputdev = dev;
|
||||
}
|
||||
if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
|
||||
outputdev = dev;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes output console first */
|
||||
if (outputdev != NULL) {
|
||||
console_setfile (stdout, outputdev);
|
||||
console_setfile (stderr, outputdev);
|
||||
}
|
||||
|
||||
/* Initializes input console */
|
||||
if (inputdev != NULL) {
|
||||
console_setfile (stdin, inputdev);
|
||||
}
|
||||
|
||||
gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
|
||||
|
||||
#ifndef CFG_CONSOLE_INFO_QUIET
|
||||
/* Print information */
|
||||
puts ("In: ");
|
||||
if (stdio_devices[stdin] == NULL) {
|
||||
puts ("No input devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdin]->name);
|
||||
}
|
||||
|
||||
puts ("Out: ");
|
||||
if (stdio_devices[stdout] == NULL) {
|
||||
puts ("No output devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stdout]->name);
|
||||
}
|
||||
|
||||
puts ("Err: ");
|
||||
if (stdio_devices[stderr] == NULL) {
|
||||
puts ("No error devices available!\n");
|
||||
} else {
|
||||
printf ("%s\n", stdio_devices[stderr]->name);
|
||||
}
|
||||
#endif /* CFG_CONSOLE_INFO_QUIET */
|
||||
|
||||
/* Setting environment variables */
|
||||
for (i = 0; i < 3; i++) {
|
||||
setenv (stdio_names[i], stdio_devices[i]->name);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* If nothing usable installed, use only the initial console */
|
||||
if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* CFG_CONSOLE_IS_IN_ENV */
|
|
@ -0,0 +1,106 @@
|
|||
//==========================================================================
|
||||
//
|
||||
// crc16.c
|
||||
//
|
||||
// 16 bit CRC with polynomial x^16+x^12+x^5+1
|
||||
//
|
||||
//==========================================================================
|
||||
//####ECOSGPLCOPYRIGHTBEGIN####
|
||||
// -------------------------------------------
|
||||
// This file is part of eCos, the Embedded Configurable Operating System.
|
||||
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
||||
// Copyright (C) 2002 Gary Thomas
|
||||
//
|
||||
// eCos 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 or (at your option) any later version.
|
||||
//
|
||||
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
//
|
||||
// As a special exception, if other files instantiate templates or use macros
|
||||
// or inline functions from this file, or you compile this file and link it
|
||||
// with other works to produce a work based on this file, this file does not
|
||||
// by itself cause the resulting work to be covered by the GNU General Public
|
||||
// License. However the source code for this file must still be made available
|
||||
// in accordance with section (3) of the GNU General Public License.
|
||||
//
|
||||
// This exception does not invalidate any other reasons why a work based on
|
||||
// this file might be covered by the GNU General Public License.
|
||||
//
|
||||
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
||||
// at http://sources.redhat.com/ecos/ecos-license/
|
||||
// -------------------------------------------
|
||||
//####ECOSGPLCOPYRIGHTEND####
|
||||
//==========================================================================
|
||||
//#####DESCRIPTIONBEGIN####
|
||||
//
|
||||
// Author(s): gthomas
|
||||
// Contributors: gthomas,asl
|
||||
// Date: 2001-01-31
|
||||
// Purpose:
|
||||
// Description:
|
||||
//
|
||||
// This code is part of eCos (tm).
|
||||
//
|
||||
//####DESCRIPTIONEND####
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
// Table of CRC constants - implements x^16+x^12+x^5+1
|
||||
static const uint16_t crc16_tab[] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
|
||||
};
|
||||
|
||||
uint16_t
|
||||
cyg_crc16(unsigned char *buf, int len)
|
||||
{
|
||||
int i;
|
||||
uint16_t cksum;
|
||||
|
||||
cksum = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
cksum = crc16_tab[((cksum>>8) ^ *buf++) & 0xFF] ^ (cksum << 8);
|
||||
}
|
||||
return cksum;
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
|
||||
*
|
||||
* 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>
|
||||
#include <common.h>
|
||||
#include <stdarg.h>
|
||||
#include <malloc.h>
|
||||
#include <devices.h>
|
||||
#include <serial.h>
|
||||
#ifdef CONFIG_LOGBUFFER
|
||||
#include <logbuff.h>
|
||||
#endif
|
||||
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
|
||||
#include <i2c.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
list_t devlist = 0;
|
||||
device_t *stdio_devices[] = { NULL, NULL, NULL };
|
||||
char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" };
|
||||
|
||||
#if defined(CONFIG_SPLASH_SCREEN) && !defined(CFG_DEVICE_NULLDEV)
|
||||
#define CFG_DEVICE_NULLDEV 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CFG_DEVICE_NULLDEV
|
||||
void nulldev_putc(const char c)
|
||||
{
|
||||
/* nulldev is empty! */
|
||||
}
|
||||
|
||||
void nulldev_puts(const char *s)
|
||||
{
|
||||
/* nulldev is empty! */
|
||||
}
|
||||
|
||||
int nulldev_input(void)
|
||||
{
|
||||
/* nulldev is empty! */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************************************************
|
||||
* SYSTEM DRIVERS
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
static void drv_system_init (void)
|
||||
{
|
||||
device_t dev;
|
||||
|
||||
memset (&dev, 0, sizeof (dev));
|
||||
|
||||
strcpy (dev.name, "serial");
|
||||
dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
|
||||
#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
|
||||
dev.putc = serial_buffered_putc;
|
||||
dev.puts = serial_buffered_puts;
|
||||
dev.getc = serial_buffered_getc;
|
||||
dev.tstc = serial_buffered_tstc;
|
||||
#else
|
||||
dev.putc = serial_putc;
|
||||
dev.puts = serial_puts;
|
||||
dev.getc = serial_getc;
|
||||
dev.tstc = serial_tstc;
|
||||
#endif
|
||||
|
||||
device_register (&dev);
|
||||
|
||||
#ifdef CFG_DEVICE_NULLDEV
|
||||
memset (&dev, 0, sizeof (dev));
|
||||
|
||||
strcpy (dev.name, "nulldev");
|
||||
dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
|
||||
dev.putc = nulldev_putc;
|
||||
dev.puts = nulldev_puts;
|
||||
dev.getc = nulldev_input;
|
||||
dev.tstc = nulldev_input;
|
||||
|
||||
device_register (&dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* DEVICES
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
int device_register (device_t * dev)
|
||||
{
|
||||
ListInsertItem (devlist, dev, LIST_END);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* deregister the device "devname".
|
||||
* returns 0 if success, -1 if device is assigned and 1 if devname not found
|
||||
*/
|
||||
#ifdef CFG_DEVICE_DEREGISTER
|
||||
int device_deregister(char *devname)
|
||||
{
|
||||
int i,l,dev_index;
|
||||
device_t *dev = NULL;
|
||||
char temp_names[3][8];
|
||||
|
||||
dev_index=-1;
|
||||
for (i=1; i<=ListNumItems(devlist); i++) {
|
||||
dev = ListGetPtrToItem (devlist, i);
|
||||
if(strcmp(dev->name,devname)==0) {
|
||||
dev_index=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dev_index<0) /* device not found */
|
||||
return 0;
|
||||
/* get stdio devices (ListRemoveItem changes the dev list) */
|
||||
for (l=0 ; l< MAX_FILES; l++) {
|
||||
if (stdio_devices[l] == dev) {
|
||||
/* Device is assigned -> report error */
|
||||
return -1;
|
||||
}
|
||||
memcpy (&temp_names[l][0],
|
||||
stdio_devices[l]->name,
|
||||
sizeof(stdio_devices[l]->name));
|
||||
}
|
||||
ListRemoveItem(devlist,NULL,dev_index);
|
||||
/* reassign Device list */
|
||||
for (i=1; i<=ListNumItems(devlist); i++) {
|
||||
dev = ListGetPtrToItem (devlist, i);
|
||||
for (l=0 ; l< MAX_FILES; l++) {
|
||||
if(strcmp(dev->name,temp_names[l])==0) {
|
||||
stdio_devices[l] = dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CFG_DEVICE_DEREGISTER */
|
||||
|
||||
int devices_init (void)
|
||||
{
|
||||
#ifndef CONFIG_ARM /* already relocated for current ARM implementation */
|
||||
ulong relocation_offset = gd->reloc_off;
|
||||
int i;
|
||||
|
||||
/* relocate device name pointers */
|
||||
for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
|
||||
stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
|
||||
relocation_offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the list */
|
||||
devlist = ListCreate (sizeof (device_t));
|
||||
|
||||
if (devlist == NULL) {
|
||||
eputs ("Cannot initialize the list of devices!\n");
|
||||
return -1;
|
||||
}
|
||||
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
|
||||
i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
|
||||
#endif
|
||||
#ifdef CONFIG_LCD
|
||||
drv_lcd_init ();
|
||||
#endif
|
||||
#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
|
||||
drv_video_init ();
|
||||
#endif
|
||||
#ifdef CONFIG_KEYBOARD
|
||||
drv_keyboard_init ();
|
||||
#endif
|
||||
#ifdef CONFIG_LOGBUFFER
|
||||
drv_logbuff_init ();
|
||||
#endif
|
||||
drv_system_init ();
|
||||
#ifdef CONFIG_SERIAL_MULTI
|
||||
serial_devices_init ();
|
||||
#endif
|
||||
#ifdef CONFIG_USB_TTY
|
||||
drv_usbtty_init ();
|
||||
#endif
|
||||
#ifdef CONFIG_NETCONSOLE
|
||||
drv_nc_init ();
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int devices_done (void)
|
||||
{
|
||||
ListDispose (devlist);
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.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>
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#ifdef CONFIG_SHOW_BOOT_PROGRESS
|
||||
# include <status_led.h>
|
||||
# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg)
|
||||
#else
|
||||
# define SHOW_BOOT_PROGRESS(arg)
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
extern void enable_nvram(void);
|
||||
extern void disable_nvram(void);
|
||||
#endif
|
||||
|
||||
#undef DEBUG_ENV
|
||||
#ifdef DEBUG_ENV
|
||||
#define DEBUGF(fmt,args...) printf(fmt ,##args)
|
||||
#else
|
||||
#define DEBUGF(fmt,args...)
|
||||
#endif
|
||||
|
||||
extern env_t *env_ptr;
|
||||
|
||||
extern void env_relocate_spec (void);
|
||||
extern uchar env_get_char_spec(int);
|
||||
|
||||
static uchar env_get_char_init (int index);
|
||||
uchar (*env_get_char)(int) = env_get_char_init;
|
||||
|
||||
/************************************************************************
|
||||
* Default settings to be used when no valid environment is found
|
||||
*/
|
||||
#define XMK_STR(x) #x
|
||||
#define MK_STR(x) XMK_STR(x)
|
||||
|
||||
uchar default_environment[] = {
|
||||
#ifdef CONFIG_BOOTARGS
|
||||
"bootargs=" CONFIG_BOOTARGS "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTCOMMAND
|
||||
"bootcmd=" CONFIG_BOOTCOMMAND "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_RAMBOOTCOMMAND
|
||||
"ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_NFSBOOTCOMMAND
|
||||
"nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
|
||||
"bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
|
||||
"baudrate=" MK_STR(CONFIG_BAUDRATE) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_LOADS_ECHO
|
||||
"loads_echo=" MK_STR(CONFIG_LOADS_ECHO) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETHADDR
|
||||
"ethaddr=" MK_STR(CONFIG_ETHADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETH1ADDR
|
||||
"eth1addr=" MK_STR(CONFIG_ETH1ADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETH2ADDR
|
||||
"eth2addr=" MK_STR(CONFIG_ETH2ADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETH3ADDR
|
||||
"eth3addr=" MK_STR(CONFIG_ETH3ADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_IPADDR
|
||||
"ipaddr=" MK_STR(CONFIG_IPADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_SERVERIP
|
||||
"serverip=" MK_STR(CONFIG_SERVERIP) "\0"
|
||||
#endif
|
||||
#ifdef CFG_AUTOLOAD
|
||||
"autoload=" CFG_AUTOLOAD "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_PREBOOT
|
||||
"preboot=" CONFIG_PREBOOT "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ROOTPATH
|
||||
"rootpath=" MK_STR(CONFIG_ROOTPATH) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_GATEWAYIP
|
||||
"gatewayip=" MK_STR(CONFIG_GATEWAYIP) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_NETMASK
|
||||
"netmask=" MK_STR(CONFIG_NETMASK) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_HOSTNAME
|
||||
"hostname=" MK_STR(CONFIG_HOSTNAME) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTFILE
|
||||
"bootfile=" MK_STR(CONFIG_BOOTFILE) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_LOADADDR
|
||||
"loadaddr=" MK_STR(CONFIG_LOADADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_CLOCKS_IN_MHZ
|
||||
"clocks_in_mhz=1\0"
|
||||
#endif
|
||||
#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
|
||||
"pcidelay=" MK_STR(CONFIG_PCI_BOOTDELAY) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_EXTRA_ENV_SETTINGS
|
||||
CONFIG_EXTRA_ENV_SETTINGS
|
||||
#endif
|
||||
"\0"
|
||||
};
|
||||
|
||||
#if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */
|
||||
int default_environment_size = sizeof(default_environment);
|
||||
#endif
|
||||
|
||||
void env_crc_update (void)
|
||||
{
|
||||
env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE);
|
||||
}
|
||||
|
||||
static uchar env_get_char_init (int index)
|
||||
{
|
||||
uchar c;
|
||||
|
||||
/* if crc was bad, use the default environment */
|
||||
if (gd->env_valid)
|
||||
{
|
||||
c = env_get_char_spec(index);
|
||||
} else {
|
||||
c = default_environment[index];
|
||||
}
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
uchar env_get_char_memory (int index)
|
||||
{
|
||||
uchar retval;
|
||||
enable_nvram();
|
||||
if (gd->env_valid) {
|
||||
retval = ( *((uchar *)(gd->env_addr + index)) );
|
||||
} else {
|
||||
retval = ( default_environment[index] );
|
||||
}
|
||||
disable_nvram();
|
||||
return retval;
|
||||
}
|
||||
#else
|
||||
uchar env_get_char_memory (int index)
|
||||
{
|
||||
if (gd->env_valid) {
|
||||
return ( *((uchar *)(gd->env_addr + index)) );
|
||||
} else {
|
||||
return ( default_environment[index] );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uchar *env_get_addr (int index)
|
||||
{
|
||||
if (gd->env_valid) {
|
||||
return ( ((uchar *)(gd->env_addr + index)) );
|
||||
} else {
|
||||
return (&default_environment[index]);
|
||||
}
|
||||
}
|
||||
|
||||
void env_relocate (void)
|
||||
{
|
||||
DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__,
|
||||
gd->reloc_off);
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
enable_nvram();
|
||||
#endif
|
||||
|
||||
#if defined(ENV_IS_EMBEDDED)
|
||||
/*
|
||||
* The environment buffer is embedded with the text segment,
|
||||
* just relocate the environment pointer
|
||||
*/
|
||||
env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);
|
||||
DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
|
||||
#else
|
||||
/*
|
||||
* We must allocate a buffer for the environment
|
||||
*/
|
||||
env_ptr = (env_t *)malloc (CFG_ENV_SIZE);
|
||||
DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* After relocation to RAM, we can always use the "memory" functions
|
||||
*/
|
||||
env_get_char = env_get_char_memory;
|
||||
|
||||
if (gd->env_valid == 0) {
|
||||
#if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE) /* Environment not changable */
|
||||
puts ("Using default environment\n\n");
|
||||
#else
|
||||
puts ("*** Warning - bad CRC, using default environment\n\n");
|
||||
SHOW_BOOT_PROGRESS (-1);
|
||||
#endif
|
||||
|
||||
if (sizeof(default_environment) > ENV_SIZE)
|
||||
{
|
||||
puts ("*** Error - default environment is too large\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset (env_ptr, 0, sizeof(env_t));
|
||||
memcpy (env_ptr->data,
|
||||
default_environment,
|
||||
sizeof(default_environment));
|
||||
#ifdef CFG_REDUNDAND_ENVIRONMENT
|
||||
env_ptr->flags = 0xFF;
|
||||
#endif
|
||||
env_crc_update ();
|
||||
gd->env_valid = 1;
|
||||
}
|
||||
else {
|
||||
env_relocate_spec ();
|
||||
}
|
||||
gd->env_addr = (ulong)&(env_ptr->data);
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
disable_nvram();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AUTO_COMPLETE
|
||||
int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
|
||||
{
|
||||
int i, nxt, len, vallen, found;
|
||||
const char *lval, *rval;
|
||||
|
||||
found = 0;
|
||||
cmdv[0] = NULL;
|
||||
|
||||
len = strlen(var);
|
||||
/* now iterate over the variables and select those that match */
|
||||
for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
|
||||
|
||||
for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)
|
||||
;
|
||||
|
||||
lval = (char *)env_get_addr(i);
|
||||
rval = strchr(lval, '=');
|
||||
if (rval != NULL) {
|
||||
vallen = rval - lval;
|
||||
rval++;
|
||||
} else
|
||||
vallen = strlen(lval);
|
||||
|
||||
if (len > 0 && (vallen < len || memcmp(lval, var, len) != 0))
|
||||
continue;
|
||||
|
||||
if (found >= maxv - 2 || bufsz < vallen + 1) {
|
||||
cmdv[found++] = "...";
|
||||
break;
|
||||
}
|
||||
cmdv[found++] = buf;
|
||||
memcpy(buf, lval, vallen); buf += vallen; bufsz -= vallen;
|
||||
*buf++ = '\0'; bufsz--;
|
||||
}
|
||||
|
||||
cmdv[found] = NULL;
|
||||
return found;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,103 @@
|
|||
/* LowLevel function for DataFlash environment support
|
||||
* Author : Gilles Gastaldi (Atmel)
|
||||
*
|
||||
* 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(CFG_ENV_IS_IN_DATAFLASH) /* Environment is in DataFlash */
|
||||
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <dataflash.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
env_t *env_ptr = NULL;
|
||||
|
||||
char * env_name_spec = "dataflash";
|
||||
|
||||
extern int read_dataflash (unsigned long addr, unsigned long size, char
|
||||
*result);
|
||||
extern int write_dataflash (unsigned long addr_dest, unsigned long addr_src,
|
||||
unsigned long size);
|
||||
extern int AT91F_DataflashInit (void);
|
||||
extern uchar default_environment[];
|
||||
/* extern int default_environment_size; */
|
||||
|
||||
|
||||
uchar env_get_char_spec (int index)
|
||||
{
|
||||
uchar c;
|
||||
read_dataflash (CFG_ENV_ADDR+index+offsetof(env_t,data),1,&c);
|
||||
return (c);
|
||||
}
|
||||
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
read_dataflash (CFG_ENV_ADDR,CFG_ENV_SIZE,(uchar *)env_ptr);
|
||||
}
|
||||
|
||||
int saveenv(void)
|
||||
{
|
||||
/* env must be copied to do not alter env structure in memory*/
|
||||
unsigned char temp[CFG_ENV_SIZE];
|
||||
int i;
|
||||
memcpy(temp, env_ptr, CFG_ENV_SIZE);
|
||||
return write_dataflash (CFG_ENV_ADDR, (unsigned long)temp, CFG_ENV_SIZE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Initialize Environment use
|
||||
*
|
||||
* We are still running from ROM, so data use is limited
|
||||
* Use a (moderately small) buffer on the stack
|
||||
*/
|
||||
int env_init(void)
|
||||
{
|
||||
ulong crc, len, new;
|
||||
unsigned off;
|
||||
uchar buf[64];
|
||||
if (gd->env_valid == 0){
|
||||
AT91F_DataflashInit(); /* prepare for DATAFLASH read/write */
|
||||
|
||||
/* read old CRC */
|
||||
read_dataflash (CFG_ENV_ADDR+offsetof(env_t,crc),sizeof(ulong),&crc);
|
||||
new = 0;
|
||||
len = ENV_SIZE;
|
||||
off = offsetof(env_t,data);
|
||||
while (len > 0) {
|
||||
int n = (len > sizeof(buf)) ? sizeof(buf) : len;
|
||||
read_dataflash (CFG_ENV_ADDR+off,n , buf);
|
||||
new = crc32 (new, buf, n);
|
||||
len -= n;
|
||||
off += n;
|
||||
}
|
||||
if (crc == new) {
|
||||
gd->env_addr = offsetof(env_t,data);
|
||||
gd->env_valid = 1;
|
||||
} else {
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
gd->env_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* CFG_ENV_IS_IN_DATAFLASH */
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.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(CFG_ENV_IS_IN_EEPROM) /* Environment is in EEPROM */
|
||||
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <linux/stddef.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
env_t *env_ptr = NULL;
|
||||
|
||||
char * env_name_spec = "EEPROM";
|
||||
|
||||
extern uchar (*env_get_char)(int);
|
||||
extern uchar env_get_char_memory (int index);
|
||||
|
||||
|
||||
uchar env_get_char_spec (int index)
|
||||
{
|
||||
uchar c;
|
||||
|
||||
eeprom_read (CFG_DEF_EEPROM_ADDR,
|
||||
CFG_ENV_OFFSET+index+offsetof(env_t,data),
|
||||
&c, 1);
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
eeprom_read (CFG_DEF_EEPROM_ADDR,
|
||||
CFG_ENV_OFFSET,
|
||||
(uchar*)env_ptr,
|
||||
CFG_ENV_SIZE);
|
||||
}
|
||||
|
||||
int saveenv(void)
|
||||
{
|
||||
return eeprom_write (CFG_DEF_EEPROM_ADDR,
|
||||
CFG_ENV_OFFSET,
|
||||
(uchar *)env_ptr,
|
||||
CFG_ENV_SIZE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Initialize Environment use
|
||||
*
|
||||
* We are still running from ROM, so data use is limited
|
||||
* Use a (moderately small) buffer on the stack
|
||||
*/
|
||||
int env_init(void)
|
||||
{
|
||||
ulong crc, len, new;
|
||||
unsigned off;
|
||||
uchar buf[64];
|
||||
|
||||
eeprom_init (); /* prepare for EEPROM read/write */
|
||||
|
||||
/* read old CRC */
|
||||
eeprom_read (CFG_DEF_EEPROM_ADDR,
|
||||
CFG_ENV_OFFSET+offsetof(env_t,crc),
|
||||
(uchar *)&crc, sizeof(ulong));
|
||||
|
||||
new = 0;
|
||||
len = ENV_SIZE;
|
||||
off = offsetof(env_t,data);
|
||||
while (len > 0) {
|
||||
int n = (len > sizeof(buf)) ? sizeof(buf) : len;
|
||||
|
||||
eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, buf, n);
|
||||
new = crc32 (new, buf, n);
|
||||
len -= n;
|
||||
off += n;
|
||||
}
|
||||
|
||||
if (crc == new) {
|
||||
gd->env_addr = offsetof(env_t,data);
|
||||
gd->env_valid = 1;
|
||||
} else {
|
||||
gd->env_addr = 0;
|
||||
gd->env_valid = 0;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* CFG_ENV_IS_IN_EEPROM */
|
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.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
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#if defined(CFG_ENV_IS_IN_FLASH) /* Environment is in Flash */
|
||||
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <malloc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_FLASH)) == (CFG_CMD_ENV|CFG_CMD_FLASH))
|
||||
#define CMD_SAVEENV
|
||||
#elif defined(CFG_ENV_ADDR_REDUND)
|
||||
#error Cannot use CFG_ENV_ADDR_REDUND without CFG_CMD_ENV & CFG_CMD_FLASH
|
||||
#endif
|
||||
|
||||
#if defined(CFG_ENV_SIZE_REDUND) && (CFG_ENV_SIZE_REDUND < CFG_ENV_SIZE)
|
||||
#error CFG_ENV_SIZE_REDUND should not be less then CFG_ENV_SIZE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INFERNO
|
||||
# ifdef CFG_ENV_ADDR_REDUND
|
||||
#error CFG_ENV_ADDR_REDUND is not implemented for CONFIG_INFERNO
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char * env_name_spec = "Flash";
|
||||
|
||||
#ifdef ENV_IS_EMBEDDED
|
||||
|
||||
extern uchar environment[];
|
||||
env_t *env_ptr = (env_t *)(&environment[0]);
|
||||
|
||||
#ifdef CMD_SAVEENV
|
||||
/* static env_t *flash_addr = (env_t *)(&environment[0]);-broken on ARM-wd-*/
|
||||
static env_t *flash_addr = (env_t *)CFG_ENV_ADDR;
|
||||
#endif
|
||||
|
||||
#else /* ! ENV_IS_EMBEDDED */
|
||||
|
||||
env_t *env_ptr = (env_t *)CFG_ENV_ADDR;
|
||||
|
||||
#ifdef CMD_SAVEENV
|
||||
static env_t *flash_addr = (env_t *)CFG_ENV_ADDR;
|
||||
#endif
|
||||
|
||||
#endif /* ENV_IS_EMBEDDED */
|
||||
|
||||
#ifdef CFG_ENV_ADDR_REDUND
|
||||
static env_t *flash_addr_new = (env_t *)CFG_ENV_ADDR_REDUND;
|
||||
|
||||
/* CFG_ENV_ADDR is supposed to be on sector boundary */
|
||||
static ulong end_addr = CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1;
|
||||
static ulong end_addr_new = CFG_ENV_ADDR_REDUND + CFG_ENV_SECT_SIZE - 1;
|
||||
|
||||
#define ACTIVE_FLAG 1
|
||||
#define OBSOLETE_FLAG 0
|
||||
#endif /* CFG_ENV_ADDR_REDUND */
|
||||
|
||||
extern uchar default_environment[];
|
||||
extern int default_environment_size;
|
||||
|
||||
|
||||
uchar env_get_char_spec (int index)
|
||||
{
|
||||
return ( *((uchar *)(gd->env_addr + index)) );
|
||||
}
|
||||
|
||||
#ifdef CFG_ENV_ADDR_REDUND
|
||||
|
||||
int env_init(void)
|
||||
{
|
||||
int crc1_ok = 0, crc2_ok = 0;
|
||||
|
||||
uchar flag1 = flash_addr->flags;
|
||||
uchar flag2 = flash_addr_new->flags;
|
||||
|
||||
ulong addr_default = (ulong)&default_environment[0];
|
||||
ulong addr1 = (ulong)&(flash_addr->data);
|
||||
ulong addr2 = (ulong)&(flash_addr_new->data);
|
||||
|
||||
#ifdef CONFIG_OMAP2420H4
|
||||
int flash_probe(void);
|
||||
|
||||
if(flash_probe() == 0)
|
||||
goto bad_flash;
|
||||
#endif
|
||||
|
||||
crc1_ok = (crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc);
|
||||
crc2_ok = (crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc);
|
||||
|
||||
if (crc1_ok && ! crc2_ok) {
|
||||
gd->env_addr = addr1;
|
||||
gd->env_valid = 1;
|
||||
} else if (! crc1_ok && crc2_ok) {
|
||||
gd->env_addr = addr2;
|
||||
gd->env_valid = 1;
|
||||
} else if (! crc1_ok && ! crc2_ok) {
|
||||
gd->env_addr = addr_default;
|
||||
gd->env_valid = 0;
|
||||
} else if (flag1 == ACTIVE_FLAG && flag2 == OBSOLETE_FLAG) {
|
||||
gd->env_addr = addr1;
|
||||
gd->env_valid = 1;
|
||||
} else if (flag1 == OBSOLETE_FLAG && flag2 == ACTIVE_FLAG) {
|
||||
gd->env_addr = addr2;
|
||||
gd->env_valid = 1;
|
||||
} else if (flag1 == flag2) {
|
||||
gd->env_addr = addr1;
|
||||
gd->env_valid = 2;
|
||||
} else if (flag1 == 0xFF) {
|
||||
gd->env_addr = addr1;
|
||||
gd->env_valid = 2;
|
||||
} else if (flag2 == 0xFF) {
|
||||
gd->env_addr = addr2;
|
||||
gd->env_valid = 2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP2420H4
|
||||
bad_flash:
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef CMD_SAVEENV
|
||||
int saveenv(void)
|
||||
{
|
||||
char *saved_data = NULL;
|
||||
int rc = 1;
|
||||
char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
|
||||
#if CFG_ENV_SECT_SIZE > CFG_ENV_SIZE
|
||||
ulong up_data = 0;
|
||||
#endif
|
||||
|
||||
debug ("Protect off %08lX ... %08lX\n",
|
||||
(ulong)flash_addr, end_addr);
|
||||
|
||||
if (flash_sect_protect (0, (ulong)flash_addr, end_addr)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
debug ("Protect off %08lX ... %08lX\n",
|
||||
(ulong)flash_addr_new, end_addr_new);
|
||||
|
||||
if (flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
#if CFG_ENV_SECT_SIZE > CFG_ENV_SIZE
|
||||
up_data = (end_addr_new + 1 - ((long)flash_addr_new + CFG_ENV_SIZE));
|
||||
debug ("Data to save 0x%x\n", up_data);
|
||||
if (up_data) {
|
||||
if ((saved_data = malloc(up_data)) == NULL) {
|
||||
printf("Unable to save the rest of sector (%ld)\n",
|
||||
up_data);
|
||||
goto Done;
|
||||
}
|
||||
memcpy(saved_data,
|
||||
(void *)((long)flash_addr_new + CFG_ENV_SIZE), up_data);
|
||||
debug ("Data (start 0x%x, len 0x%x) saved at 0x%x\n",
|
||||
(long)flash_addr_new + CFG_ENV_SIZE,
|
||||
up_data, saved_data);
|
||||
}
|
||||
#endif
|
||||
debug ("Erasing Flash...");
|
||||
debug (" %08lX ... %08lX ...",
|
||||
(ulong)flash_addr_new, end_addr_new);
|
||||
|
||||
if (flash_sect_erase ((ulong)flash_addr_new, end_addr_new)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
debug ("Writing to Flash... ");
|
||||
debug (" %08lX ... %08lX ...",
|
||||
(ulong)&(flash_addr_new->data),
|
||||
sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data));
|
||||
if ((rc = flash_write((char *)env_ptr->data,
|
||||
(ulong)&(flash_addr_new->data),
|
||||
sizeof(env_ptr->data))) ||
|
||||
(rc = flash_write((char *)&(env_ptr->crc),
|
||||
(ulong)&(flash_addr_new->crc),
|
||||
sizeof(env_ptr->crc))) ||
|
||||
(rc = flash_write(&flag,
|
||||
(ulong)&(flash_addr->flags),
|
||||
sizeof(flash_addr->flags))) ||
|
||||
(rc = flash_write(&new_flag,
|
||||
(ulong)&(flash_addr_new->flags),
|
||||
sizeof(flash_addr_new->flags))))
|
||||
{
|
||||
flash_perror (rc);
|
||||
goto Done;
|
||||
}
|
||||
debug ("done\n");
|
||||
|
||||
#if CFG_ENV_SECT_SIZE > CFG_ENV_SIZE
|
||||
if (up_data) { /* restore the rest of sector */
|
||||
debug ("Restoring the rest of data to 0x%x len 0x%x\n",
|
||||
(long)flash_addr_new + CFG_ENV_SIZE, up_data);
|
||||
if (flash_write(saved_data,
|
||||
(long)flash_addr_new + CFG_ENV_SIZE,
|
||||
up_data)) {
|
||||
flash_perror(rc);
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
{
|
||||
env_t * etmp = flash_addr;
|
||||
ulong ltmp = end_addr;
|
||||
|
||||
flash_addr = flash_addr_new;
|
||||
flash_addr_new = etmp;
|
||||
|
||||
end_addr = end_addr_new;
|
||||
end_addr_new = ltmp;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
Done:
|
||||
|
||||
if (saved_data)
|
||||
free (saved_data);
|
||||
/* try to re-protect */
|
||||
(void) flash_sect_protect (1, (ulong)flash_addr, end_addr);
|
||||
(void) flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* CMD_SAVEENV */
|
||||
|
||||
#else /* ! CFG_ENV_ADDR_REDUND */
|
||||
|
||||
int env_init(void)
|
||||
{
|
||||
#ifdef CONFIG_OMAP2420H4
|
||||
int flash_probe(void);
|
||||
|
||||
if(flash_probe() == 0)
|
||||
goto bad_flash;
|
||||
#endif
|
||||
if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
|
||||
gd->env_addr = (ulong)&(env_ptr->data);
|
||||
gd->env_valid = 1;
|
||||
return(0);
|
||||
}
|
||||
#ifdef CONFIG_OMAP2420H4
|
||||
bad_flash:
|
||||
#endif
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
gd->env_valid = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef CMD_SAVEENV
|
||||
|
||||
int saveenv(void)
|
||||
{
|
||||
int len, rc;
|
||||
ulong end_addr;
|
||||
ulong flash_sect_addr;
|
||||
#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
|
||||
ulong flash_offset;
|
||||
uchar env_buffer[CFG_ENV_SECT_SIZE];
|
||||
#else
|
||||
uchar *env_buffer = (uchar *)env_ptr;
|
||||
#endif /* CFG_ENV_SECT_SIZE */
|
||||
int rcode = 0;
|
||||
|
||||
#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
|
||||
|
||||
flash_offset = ((ulong)flash_addr) & (CFG_ENV_SECT_SIZE-1);
|
||||
flash_sect_addr = ((ulong)flash_addr) & ~(CFG_ENV_SECT_SIZE-1);
|
||||
|
||||
debug ( "copy old content: "
|
||||
"sect_addr: %08lX env_addr: %08lX offset: %08lX\n",
|
||||
flash_sect_addr, (ulong)flash_addr, flash_offset);
|
||||
|
||||
/* copy old contents to temporary buffer */
|
||||
memcpy (env_buffer, (void *)flash_sect_addr, CFG_ENV_SECT_SIZE);
|
||||
|
||||
/* copy current environment to temporary buffer */
|
||||
memcpy ((uchar *)((unsigned long)env_buffer + flash_offset),
|
||||
env_ptr,
|
||||
CFG_ENV_SIZE);
|
||||
|
||||
len = CFG_ENV_SECT_SIZE;
|
||||
#else
|
||||
flash_sect_addr = (ulong)flash_addr;
|
||||
len = CFG_ENV_SIZE;
|
||||
#endif /* CFG_ENV_SECT_SIZE */
|
||||
|
||||
#ifndef CONFIG_INFERNO
|
||||
end_addr = flash_sect_addr + len - 1;
|
||||
#else
|
||||
/* this is the last sector, and the size is hardcoded here */
|
||||
/* otherwise we will get stack problems on loading 128 KB environment */
|
||||
end_addr = flash_sect_addr + 0x20000 - 1;
|
||||
#endif
|
||||
|
||||
debug ("Protect off %08lX ... %08lX\n",
|
||||
(ulong)flash_sect_addr, end_addr);
|
||||
|
||||
if (flash_sect_protect (0, flash_sect_addr, end_addr))
|
||||
return 1;
|
||||
|
||||
debug ("Erasing Flash...");
|
||||
if (flash_sect_erase (flash_sect_addr, end_addr))
|
||||
return 1;
|
||||
|
||||
debug ("Writing to Flash... ");
|
||||
rc = flash_write((char *)env_buffer, flash_sect_addr, len);
|
||||
if (rc != 0) {
|
||||
flash_perror (rc);
|
||||
rcode = 1;
|
||||
} else {
|
||||
debug ("done\n");
|
||||
}
|
||||
|
||||
/* try to re-protect */
|
||||
(void) flash_sect_protect (1, flash_sect_addr, end_addr);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
#endif /* CMD_SAVEENV */
|
||||
|
||||
#endif /* CFG_ENV_ADDR_REDUND */
|
||||
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
#if !defined(ENV_IS_EMBEDDED) || defined(CFG_ENV_ADDR_REDUND)
|
||||
#ifdef CFG_ENV_ADDR_REDUND
|
||||
if (gd->env_addr != (ulong)&(flash_addr->data)) {
|
||||
env_t * etmp = flash_addr;
|
||||
ulong ltmp = end_addr;
|
||||
|
||||
flash_addr = flash_addr_new;
|
||||
flash_addr_new = etmp;
|
||||
|
||||
end_addr = end_addr_new;
|
||||
end_addr_new = ltmp;
|
||||
}
|
||||
|
||||
if (flash_addr_new->flags != OBSOLETE_FLAG &&
|
||||
crc32(0, flash_addr_new->data, ENV_SIZE) ==
|
||||
flash_addr_new->crc) {
|
||||
char flag = OBSOLETE_FLAG;
|
||||
|
||||
gd->env_valid = 2;
|
||||
flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new);
|
||||
flash_write(&flag,
|
||||
(ulong)&(flash_addr_new->flags),
|
||||
sizeof(flash_addr_new->flags));
|
||||
flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new);
|
||||
}
|
||||
|
||||
if (flash_addr->flags != ACTIVE_FLAG &&
|
||||
(flash_addr->flags & ACTIVE_FLAG) == ACTIVE_FLAG) {
|
||||
char flag = ACTIVE_FLAG;
|
||||
|
||||
gd->env_valid = 2;
|
||||
flash_sect_protect (0, (ulong)flash_addr, end_addr);
|
||||
flash_write(&flag,
|
||||
(ulong)&(flash_addr->flags),
|
||||
sizeof(flash_addr->flags));
|
||||
flash_sect_protect (1, (ulong)flash_addr, end_addr);
|
||||
}
|
||||
|
||||
if (gd->env_valid == 2)
|
||||
puts ("*** Warning - some problems detected "
|
||||
"reading environment; recovered successfully\n\n");
|
||||
#endif /* CFG_ENV_ADDR_REDUND */
|
||||
memcpy (env_ptr, (void*)flash_addr, CFG_ENV_SIZE);
|
||||
#endif /* ! ENV_IS_EMBEDDED || CFG_ENV_ADDR_REDUND */
|
||||
}
|
||||
|
||||
#endif /* CFG_ENV_IS_IN_FLASH */
|
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* (C) Copyright 2004
|
||||
* Jian Zhang, Texas Instruments, jzhang@ti.com.
|
||||
|
||||
* (C) Copyright 2000-2004
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.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
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */
|
||||
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <malloc.h>
|
||||
#include <nand.h>
|
||||
|
||||
#if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_NAND)) == (CFG_CMD_ENV|CFG_CMD_NAND))
|
||||
#define CMD_SAVEENV
|
||||
#elif defined(CFG_ENV_OFFSET_REDUND)
|
||||
#error Cannot use CFG_ENV_OFFSET_REDUND without CFG_CMD_ENV & CFG_CMD_NAND
|
||||
#endif
|
||||
|
||||
#if defined(CFG_ENV_SIZE_REDUND) && (CFG_ENV_SIZE_REDUND != CFG_ENV_SIZE)
|
||||
#error CFG_ENV_SIZE_REDUND should be the same as CFG_ENV_SIZE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INFERNO
|
||||
#error CONFIG_INFERNO not supported yet
|
||||
#endif
|
||||
|
||||
int nand_legacy_rw (struct nand_chip* nand, int cmd,
|
||||
size_t start, size_t len,
|
||||
size_t * retlen, u_char * buf);
|
||||
|
||||
/* info for NAND chips, defined in drivers/nand/nand.c */
|
||||
extern nand_info_t nand_info[];
|
||||
|
||||
/* references to names in env_common.c */
|
||||
extern uchar default_environment[];
|
||||
extern int default_environment_size;
|
||||
|
||||
char * env_name_spec = "NAND";
|
||||
|
||||
|
||||
#ifdef ENV_IS_EMBEDDED
|
||||
extern uchar environment[];
|
||||
env_t *env_ptr = (env_t *)(&environment[0]);
|
||||
#else /* ! ENV_IS_EMBEDDED */
|
||||
env_t *env_ptr = 0;
|
||||
#endif /* ENV_IS_EMBEDDED */
|
||||
|
||||
|
||||
/* local functions */
|
||||
static void use_default(void);
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
uchar env_get_char_spec (int index)
|
||||
{
|
||||
return ( *((uchar *)(gd->env_addr + index)) );
|
||||
}
|
||||
|
||||
|
||||
/* this is called before nand_init()
|
||||
* so we can't read Nand to validate env data.
|
||||
* Mark it OK for now. env_relocate() in env_common.c
|
||||
* will call our relocate function which will does
|
||||
* the real validation.
|
||||
*/
|
||||
int env_init(void)
|
||||
{
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
gd->env_valid = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef CMD_SAVEENV
|
||||
/*
|
||||
* The legacy NAND code saved the environment in the first NAND device i.e.,
|
||||
* nand_dev_desc + 0. This is also the behaviour using the new NAND code.
|
||||
*/
|
||||
#ifdef CFG_ENV_OFFSET_REDUND
|
||||
int saveenv(void)
|
||||
{
|
||||
ulong total;
|
||||
int ret = 0;
|
||||
|
||||
env_ptr->flags++;
|
||||
total = CFG_ENV_SIZE;
|
||||
|
||||
if(gd->env_valid == 1) {
|
||||
puts ("Erasing redundant Nand...");
|
||||
if (nand_erase(&nand_info[0],
|
||||
CFG_ENV_OFFSET_REDUND, CFG_ENV_SIZE))
|
||||
return 1;
|
||||
puts ("Writing to redundant Nand... ");
|
||||
ret = nand_write(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total,
|
||||
(u_char*) env_ptr);
|
||||
} else {
|
||||
puts ("Erasing Nand...");
|
||||
if (nand_erase(&nand_info[0],
|
||||
CFG_ENV_OFFSET, CFG_ENV_SIZE))
|
||||
return 1;
|
||||
|
||||
puts ("Writing to Nand... ");
|
||||
ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total,
|
||||
(u_char*) env_ptr);
|
||||
}
|
||||
if (ret || total != CFG_ENV_SIZE)
|
||||
return 1;
|
||||
|
||||
puts ("done\n");
|
||||
gd->env_valid = (gd->env_valid == 2 ? 1 : 2);
|
||||
return ret;
|
||||
}
|
||||
#else /* ! CFG_ENV_OFFSET_REDUND */
|
||||
int saveenv(void)
|
||||
{
|
||||
ulong total;
|
||||
int ret = 0;
|
||||
|
||||
puts ("Erasing Nand...");
|
||||
if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE))
|
||||
return 1;
|
||||
|
||||
puts ("Writing to Nand... ");
|
||||
total = CFG_ENV_SIZE;
|
||||
ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);
|
||||
if (ret || total != CFG_ENV_SIZE)
|
||||
return 1;
|
||||
|
||||
puts ("done\n");
|
||||
return ret;
|
||||
}
|
||||
#endif /* CFG_ENV_OFFSET_REDUND */
|
||||
#endif /* CMD_SAVEENV */
|
||||
|
||||
#ifdef CFG_ENV_OFFSET_REDUND
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
#if !defined(ENV_IS_EMBEDDED)
|
||||
ulong total;
|
||||
int crc1_ok = 0, crc2_ok = 0;
|
||||
env_t *tmp_env1, *tmp_env2;
|
||||
|
||||
total = CFG_ENV_SIZE;
|
||||
|
||||
tmp_env1 = (env_t *) malloc(CFG_ENV_SIZE);
|
||||
tmp_env2 = (env_t *) malloc(CFG_ENV_SIZE);
|
||||
|
||||
nand_read(&nand_info[0], CFG_ENV_OFFSET, &total,
|
||||
(u_char*) tmp_env1);
|
||||
nand_read(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total,
|
||||
(u_char*) tmp_env2);
|
||||
|
||||
crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
|
||||
crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
|
||||
|
||||
if(!crc1_ok && !crc2_ok)
|
||||
return use_default();
|
||||
else if(crc1_ok && !crc2_ok)
|
||||
gd->env_valid = 1;
|
||||
else if(!crc1_ok && crc2_ok)
|
||||
gd->env_valid = 2;
|
||||
else {
|
||||
/* both ok - check serial */
|
||||
if(tmp_env1->flags == 255 && tmp_env2->flags == 0)
|
||||
gd->env_valid = 2;
|
||||
else if(tmp_env2->flags == 255 && tmp_env1->flags == 0)
|
||||
gd->env_valid = 1;
|
||||
else if(tmp_env1->flags > tmp_env2->flags)
|
||||
gd->env_valid = 1;
|
||||
else if(tmp_env2->flags > tmp_env1->flags)
|
||||
gd->env_valid = 2;
|
||||
else /* flags are equal - almost impossible */
|
||||
gd->env_valid = 1;
|
||||
|
||||
}
|
||||
|
||||
free(env_ptr);
|
||||
if(gd->env_valid == 1) {
|
||||
env_ptr = tmp_env1;
|
||||
free(tmp_env2);
|
||||
} else {
|
||||
env_ptr = tmp_env2;
|
||||
free(tmp_env1);
|
||||
}
|
||||
|
||||
#endif /* ! ENV_IS_EMBEDDED */
|
||||
}
|
||||
#else /* ! CFG_ENV_OFFSET_REDUND */
|
||||
/*
|
||||
* The legacy NAND code saved the environment in the first NAND device i.e.,
|
||||
* nand_dev_desc + 0. This is also the behaviour using the new NAND code.
|
||||
*/
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
#if !defined(ENV_IS_EMBEDDED)
|
||||
ulong total;
|
||||
int ret;
|
||||
|
||||
total = CFG_ENV_SIZE;
|
||||
ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);
|
||||
if (ret || total != CFG_ENV_SIZE)
|
||||
return use_default();
|
||||
|
||||
if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
|
||||
return use_default();
|
||||
#endif /* ! ENV_IS_EMBEDDED */
|
||||
}
|
||||
#endif /* CFG_ENV_OFFSET_REDUND */
|
||||
|
||||
static void use_default()
|
||||
{
|
||||
puts ("*** Warning - bad CRC or NAND, using default environment\n\n");
|
||||
|
||||
if (default_environment_size > CFG_ENV_SIZE){
|
||||
puts ("*** Error - default environment is too large\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset (env_ptr, 0, sizeof(env_t));
|
||||
memcpy (env_ptr->data,
|
||||
default_environment,
|
||||
default_environment_size);
|
||||
env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE);
|
||||
gd->env_valid = 1;
|
||||
|
||||
}
|
||||
|
||||
#endif /* CFG_ENV_IS_IN_NAND */
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.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(CFG_ENV_IS_NOWHERE) /* Environment is nowhere */
|
||||
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <linux/stddef.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
env_t *env_ptr = NULL;
|
||||
|
||||
extern uchar default_environment[];
|
||||
extern int default_environment_size;
|
||||
|
||||
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
}
|
||||
|
||||
uchar env_get_char_spec (int index)
|
||||
{
|
||||
return ( *((uchar *)(gd->env_addr + index)) );
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Initialize Environment use
|
||||
*
|
||||
* We are still running from ROM, so data use is limited
|
||||
*/
|
||||
int env_init(void)
|
||||
{
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
gd->env_valid = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* CFG_ENV_IS_NOWHERE) */
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* (C) Copyright 2000-2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
|
||||
* Andreas Heppel <aheppel@sysgo.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
|
||||
*/
|
||||
|
||||
/*
|
||||
* 09-18-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de>
|
||||
*
|
||||
* It might not be possible in all cases to use 'memcpy()' to copy
|
||||
* the environment to NVRAM, as the NVRAM might not be mapped into
|
||||
* the memory space. (I.e. this is the case for the BAB750). In those
|
||||
* cases it might be possible to access the NVRAM using a different
|
||||
* method. For example, the RTC on the BAB750 is accessible in IO
|
||||
* space using its address and data registers. To enable usage of
|
||||
* NVRAM in those cases I invented the functions 'nvram_read()' and
|
||||
* 'nvram_write()', which will be activated upon the configuration
|
||||
* #define CFG_NVRAM_ACCESS_ROUTINE. Note, that those functions are
|
||||
* strongly dependent on the used HW, and must be redefined for each
|
||||
* board that wants to use them.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CFG_ENV_IS_IN_NVRAM /* Environment is in NVRAM */
|
||||
|
||||
#include <command.h>
|
||||
#include <environment.h>
|
||||
#include <linux/stddef.h>
|
||||
|
||||
#ifdef CFG_NVRAM_ACCESS_ROUTINE
|
||||
extern void *nvram_read(void *dest, const long src, size_t count);
|
||||
extern void nvram_write(long dest, const void *src, size_t count);
|
||||
env_t *env_ptr = NULL;
|
||||
#else
|
||||
env_t *env_ptr = (env_t *)CFG_ENV_ADDR;
|
||||
#endif
|
||||
|
||||
char * env_name_spec = "NVRAM";
|
||||
|
||||
extern uchar default_environment[];
|
||||
extern int default_environment_size;
|
||||
|
||||
extern uchar (*env_get_char)(int);
|
||||
extern uchar env_get_char_memory (int index);
|
||||
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
uchar env_get_char_spec (int index)
|
||||
{
|
||||
#ifdef CFG_NVRAM_ACCESS_ROUTINE
|
||||
uchar c;
|
||||
|
||||
nvram_read(&c, CFG_ENV_ADDR+index, 1);
|
||||
|
||||
return c;
|
||||
#else
|
||||
uchar retval;
|
||||
enable_nvram();
|
||||
retval = *((uchar *)(gd->env_addr + index));
|
||||
disable_nvram();
|
||||
return retval;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
uchar env_get_char_spec (int index)
|
||||
{
|
||||
#ifdef CFG_NVRAM_ACCESS_ROUTINE
|
||||
uchar c;
|
||||
|
||||
nvram_read(&c, CFG_ENV_ADDR+index, 1);
|
||||
|
||||
return c;
|
||||
#else
|
||||
return *((uchar *)(gd->env_addr + index));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
#if defined(CFG_NVRAM_ACCESS_ROUTINE)
|
||||
nvram_read(env_ptr, CFG_ENV_ADDR, CFG_ENV_SIZE);
|
||||
#else
|
||||
memcpy (env_ptr, (void*)CFG_ENV_ADDR, CFG_ENV_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
int saveenv (void)
|
||||
{
|
||||
int rcode = 0;
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
enable_nvram();
|
||||
#endif
|
||||
#ifdef CFG_NVRAM_ACCESS_ROUTINE
|
||||
nvram_write(CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE);
|
||||
#else
|
||||
if (memcpy ((char *)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE) == NULL)
|
||||
rcode = 1 ;
|
||||
#endif
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
udelay(10000);
|
||||
disable_nvram();
|
||||
#endif
|
||||
return rcode;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Initialize Environment use
|
||||
*
|
||||
* We are still running from ROM, so data use is limited
|
||||
*/
|
||||
int env_init (void)
|
||||
{
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
enable_nvram();
|
||||
#endif
|
||||
#if defined(CFG_NVRAM_ACCESS_ROUTINE)
|
||||
ulong crc;
|
||||
uchar data[ENV_SIZE];
|
||||
nvram_read (&crc, CFG_ENV_ADDR, sizeof(ulong));
|
||||
nvram_read (data, CFG_ENV_ADDR+sizeof(ulong), ENV_SIZE);
|
||||
|
||||
if (crc32(0, data, ENV_SIZE) == crc) {
|
||||
gd->env_addr = (ulong)CFG_ENV_ADDR + sizeof(long);
|
||||
#else
|
||||
if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
|
||||
gd->env_addr = (ulong)&(env_ptr->data);
|
||||
#endif
|
||||
gd->env_valid = 1;
|
||||
} else {
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
gd->env_valid = 0;
|
||||
}
|
||||
#ifdef CONFIG_AMIGAONEG3SE
|
||||
disable_nvram();
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* CFG_ENV_IS_IN_NVRAM */
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#define __ASSEMBLY__ /* Dirty trick to get only #defines */
|
||||
#endif
|
||||
#define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */
|
||||
#include <config.h>
|
||||
#undef __ASSEMBLY__
|
||||
#include <environment.h>
|
||||
|
||||
/*
|
||||
* Handle HOSTS that have prepended
|
||||
* crap on symbol names, not TARGETS.
|
||||
*/
|
||||
#if defined(__APPLE__)
|
||||
/* Leading underscore on symbols */
|
||||
# define SYM_CHAR "_"
|
||||
#else /* No leading character on symbols */
|
||||
# define SYM_CHAR
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generate embedded environment table
|
||||
* inside U-Boot image, if needed.
|
||||
*/
|
||||
#if defined(ENV_IS_EMBEDDED)
|
||||
/*
|
||||
* Only put the environment in it's own section when we are building
|
||||
* U-Boot proper. The host based program "tools/envcrc" does not need
|
||||
* a seperate section. Note that ENV_CRC is only defined when building
|
||||
* U-Boot itself.
|
||||
*/
|
||||
#if (defined(CONFIG_CMI) || \
|
||||
defined(CONFIG_FADS) || \
|
||||
defined(CONFIG_HYMOD) || \
|
||||
defined(CONFIG_ICU862) || \
|
||||
defined(CONFIG_R360MPI) || \
|
||||
defined(CONFIG_TQM8xxL) || \
|
||||
defined(CONFIG_RRVISION) || \
|
||||
defined(CONFIG_TRAB) || \
|
||||
defined(CONFIG_PPCHAMELEONEVB) ) && \
|
||||
defined(ENV_CRC) /* Environment embedded in U-Boot .ppcenv section */
|
||||
/* XXX - This only works with GNU C */
|
||||
# define __PPCENV__ __attribute__ ((section(".ppcenv")))
|
||||
# define __PPCTEXT__ __attribute__ ((section(".text")))
|
||||
|
||||
#elif defined(USE_HOSTCC) /* Native for 'tools/envcrc' */
|
||||
# define __PPCENV__ /*XXX DO_NOT_DEL_THIS_COMMENT*/
|
||||
# define __PPCTEXT__ /*XXX DO_NOT_DEL_THIS_COMMENT*/
|
||||
|
||||
#else /* Environment is embedded in U-Boot's .text section */
|
||||
/* XXX - This only works with GNU C */
|
||||
# define __PPCENV__ __attribute__ ((section(".text")))
|
||||
# define __PPCTEXT__ __attribute__ ((section(".text")))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros to generate global absolutes.
|
||||
*/
|
||||
#define GEN_SYMNAME(str) SYM_CHAR #str
|
||||
#define GEN_VALUE(str) #str
|
||||
#define GEN_ABS(name, value) \
|
||||
asm (".globl " GEN_SYMNAME(name)); \
|
||||
asm (GEN_SYMNAME(name) " = " GEN_VALUE(value))
|
||||
|
||||
/*
|
||||
* Macros to transform values
|
||||
* into environment strings.
|
||||
*/
|
||||
#define XMK_STR(x) #x
|
||||
#define MK_STR(x) XMK_STR(x)
|
||||
|
||||
/*
|
||||
* Check to see if we are building with a
|
||||
* computed CRC. Otherwise define it as ~0.
|
||||
*/
|
||||
#if !defined(ENV_CRC)
|
||||
# define ENV_CRC ~0
|
||||
#endif
|
||||
|
||||
env_t environment __PPCENV__ = {
|
||||
ENV_CRC, /* CRC Sum */
|
||||
#ifdef CFG_REDUNDAND_ENVIRONMENT
|
||||
1, /* Flags: valid */
|
||||
#endif
|
||||
{
|
||||
#if defined(CONFIG_BOOTARGS)
|
||||
"bootargs=" CONFIG_BOOTARGS "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_BOOTCOMMAND)
|
||||
"bootcmd=" CONFIG_BOOTCOMMAND "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_RAMBOOTCOMMAND)
|
||||
"ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_NFSBOOTCOMMAND)
|
||||
"nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
|
||||
"bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
|
||||
"baudrate=" MK_STR(CONFIG_BAUDRATE) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_LOADS_ECHO
|
||||
"loads_echo=" MK_STR(CONFIG_LOADS_ECHO) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETHADDR
|
||||
"ethaddr=" MK_STR(CONFIG_ETHADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETH1ADDR
|
||||
"eth1addr=" MK_STR(CONFIG_ETH1ADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETH2ADDR
|
||||
"eth2addr=" MK_STR(CONFIG_ETH2ADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETH3ADDR
|
||||
"eth3addr=" MK_STR(CONFIG_ETH3ADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ETHPRIME
|
||||
"ethprime=" CONFIG_ETHPRIME "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_IPADDR
|
||||
"ipaddr=" MK_STR(CONFIG_IPADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_SERVERIP
|
||||
"serverip=" MK_STR(CONFIG_SERVERIP) "\0"
|
||||
#endif
|
||||
#ifdef CFG_AUTOLOAD
|
||||
"autoload=" CFG_AUTOLOAD "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_ROOTPATH
|
||||
"rootpath=" MK_STR(CONFIG_ROOTPATH) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_GATEWAYIP
|
||||
"gatewayip=" MK_STR(CONFIG_GATEWAYIP) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_NETMASK
|
||||
"netmask=" MK_STR(CONFIG_NETMASK) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_HOSTNAME
|
||||
"hostname=" MK_STR(CONFIG_HOSTNAME) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTFILE
|
||||
"bootfile=" MK_STR(CONFIG_BOOTFILE) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_LOADADDR
|
||||
"loadaddr=" MK_STR(CONFIG_LOADADDR) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_PREBOOT
|
||||
"preboot=" CONFIG_PREBOOT "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_CLOCKS_IN_MHZ
|
||||
"clocks_in_mhz=" "1" "\0"
|
||||
#endif
|
||||
#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
|
||||
"pcidelay=" MK_STR(CONFIG_PCI_BOOTDELAY) "\0"
|
||||
#endif
|
||||
#ifdef CONFIG_EXTRA_ENV_SETTINGS
|
||||
CONFIG_EXTRA_ENV_SETTINGS
|
||||
#endif
|
||||
"\0" /* Term. env_t.data with 2 NULs */
|
||||
}
|
||||
};
|
||||
#ifdef CFG_ENV_ADDR_REDUND
|
||||
env_t redundand_environment __PPCENV__ = {
|
||||
0, /* CRC Sum: invalid */
|
||||
0, /* Flags: invalid */
|
||||
{
|
||||
"\0"
|
||||
}
|
||||
};
|
||||
#endif /* CFG_ENV_ADDR_REDUND */
|
||||
|
||||
/*
|
||||
* These will end up in the .text section
|
||||
* if the environment strings are embedded
|
||||
* in the image. When this is used for
|
||||
* tools/envcrc, they are placed in the
|
||||
* .data/.sdata section.
|
||||
*
|
||||
*/
|
||||
unsigned long env_size __PPCTEXT__ = sizeof(env_t);
|
||||
|
||||
/*
|
||||
* Add in absolutes.
|
||||
*/
|
||||
GEN_ABS(env_offset, CFG_ENV_OFFSET);
|
||||
|
||||
#endif /* ENV_IS_EMBEDDED */
|
|
@ -0,0 +1,36 @@
|
|||
#include <common.h>
|
||||
#include <exports.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static void dummy(void)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long get_version(void)
|
||||
{
|
||||
return XF_VERSION;
|
||||
}
|
||||
|
||||
void jumptable_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
gd->jt = (void **) malloc (XF_MAX * sizeof (void *));
|
||||
for (i = 0; i < XF_MAX; i++)
|
||||
gd->jt[i] = (void *) dummy;
|
||||
|
||||
gd->jt[XF_get_version] = (void *) get_version;
|
||||
gd->jt[XF_malloc] = (void *) malloc;
|
||||
gd->jt[XF_free] = (void *) free;
|
||||
gd->jt[XF_get_timer] = (void *)get_timer;
|
||||
gd->jt[XF_udelay] = (void *)udelay;
|
||||
#if defined(CONFIG_I386) || defined(CONFIG_PPC)
|
||||
gd->jt[XF_install_hdlr] = (void *) irq_install_handler;
|
||||
gd->jt[XF_free_hdlr] = (void *) irq_free_handler;
|
||||
#endif /* I386 || PPC */
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_I2C)
|
||||
gd->jt[XF_i2c_write] = (void *) i2c_write;
|
||||
gd->jt[XF_i2c_read] = (void *) i2c_read;
|
||||
#endif /* CFG_CMD_I2C */
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <common.h>
|
||||
#include <flash.h>
|
||||
|
||||
#if !defined(CFG_NO_FLASH)
|
||||
|
||||
extern flash_info_t flash_info[]; /* info for FLASH chips */
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Set protection status for monitor sectors
|
||||
*
|
||||
* The monitor is always located in the _first_ Flash bank.
|
||||
* If necessary you have to map the second bank at lower addresses.
|
||||
*/
|
||||
void
|
||||
flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
|
||||
{
|
||||
ulong b_end = info->start[0] + info->size - 1; /* bank end address */
|
||||
short s_end = info->sector_count - 1; /* index of last sector */
|
||||
int i;
|
||||
|
||||
debug ("flash_protect %s: from 0x%08lX to 0x%08lX\n",
|
||||
(flag & FLAG_PROTECT_SET) ? "ON" :
|
||||
(flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???",
|
||||
from, to);
|
||||
|
||||
/* Do nothing if input data is bad. */
|
||||
if (info->sector_count == 0 || info->size == 0 || to < from) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* There is nothing to do if we have no data about the flash
|
||||
* or the protect range and flash range don't overlap.
|
||||
*/
|
||||
if (info->flash_id == FLASH_UNKNOWN ||
|
||||
to < info->start[0] || from > b_end) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
ulong end; /* last address in current sect */
|
||||
|
||||
end = (i == s_end) ? b_end : info->start[i + 1] - 1;
|
||||
|
||||
/* Update protection if any part of the sector
|
||||
* is in the specified range.
|
||||
*/
|
||||
if (from <= end && to >= info->start[i]) {
|
||||
if (flag & FLAG_PROTECT_CLEAR) {
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
flash_real_protect(info, i, 0);
|
||||
#else
|
||||
info->protect[i] = 0;
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
debug ("protect off %d\n", i);
|
||||
}
|
||||
else if (flag & FLAG_PROTECT_SET) {
|
||||
#if defined(CFG_FLASH_PROTECTION)
|
||||
flash_real_protect(info, i, 1);
|
||||
#else
|
||||
info->protect[i] = 1;
|
||||
#endif /* CFG_FLASH_PROTECTION */
|
||||
debug ("protect on %d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
flash_info_t *
|
||||
addr2info (ulong addr)
|
||||
{
|
||||
#ifndef CONFIG_SPD823TS
|
||||
flash_info_t *info;
|
||||
int i;
|
||||
|
||||
for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
|
||||
if (info->flash_id != FLASH_UNKNOWN &&
|
||||
addr >= info->start[0] &&
|
||||
/* WARNING - The '- 1' is needed if the flash
|
||||
* is at the end of the address space, since
|
||||
* info->start[0] + info->size wraps back to 0.
|
||||
* Please don't change this unless you understand this.
|
||||
*/
|
||||
addr <= info->start[0] + info->size - 1) {
|
||||
return (info);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SPD823TS */
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Copy memory to flash.
|
||||
* Make sure all target addresses are within Flash bounds,
|
||||
* and no protected sectors are hit.
|
||||
* Returns:
|
||||
* ERR_OK 0 - OK
|
||||
* ERR_TIMOUT 1 - write timeout
|
||||
* ERR_NOT_ERASED 2 - Flash not erased
|
||||
* ERR_PROTECTED 4 - target range includes protected sectors
|
||||
* ERR_INVAL 8 - target address not in Flash memory
|
||||
* ERR_ALIGN 16 - target address not aligned on boundary
|
||||
* (only some targets require alignment)
|
||||
*/
|
||||
int
|
||||
flash_write (char *src, ulong addr, ulong cnt)
|
||||
{
|
||||
#ifdef CONFIG_SPD823TS
|
||||
return (ERR_TIMOUT); /* any other error codes are possible as well */
|
||||
#else
|
||||
int i;
|
||||
ulong end = addr + cnt - 1;
|
||||
flash_info_t *info_first = addr2info (addr);
|
||||
flash_info_t *info_last = addr2info (end );
|
||||
flash_info_t *info;
|
||||
|
||||
if (cnt == 0) {
|
||||
return (ERR_OK);
|
||||
}
|
||||
|
||||
if (!info_first || !info_last) {
|
||||
return (ERR_INVAL);
|
||||
}
|
||||
|
||||
for (info = info_first; info <= info_last; ++info) {
|
||||
ulong b_end = info->start[0] + info->size; /* bank end addr */
|
||||
short s_end = info->sector_count - 1;
|
||||
for (i=0; i<info->sector_count; ++i) {
|
||||
ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
|
||||
|
||||
if ((end >= info->start[i]) && (addr < e_addr) &&
|
||||
(info->protect[i] != 0) ) {
|
||||
return (ERR_PROTECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* finally write data to flash */
|
||||
for (info = info_first; info <= info_last && cnt>0; ++info) {
|
||||
ulong len;
|
||||
|
||||
len = info->start[0] + info->size - addr;
|
||||
if (len > cnt)
|
||||
len = cnt;
|
||||
if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) {
|
||||
return (i);
|
||||
}
|
||||
cnt -= len;
|
||||
addr += len;
|
||||
src += len;
|
||||
}
|
||||
return (ERR_OK);
|
||||
#endif /* CONFIG_SPD823TS */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void flash_perror (int err)
|
||||
{
|
||||
switch (err) {
|
||||
case ERR_OK:
|
||||
break;
|
||||
case ERR_TIMOUT:
|
||||
puts ("Timeout writing to Flash\n");
|
||||
break;
|
||||
case ERR_NOT_ERASED:
|
||||
puts ("Flash not Erased\n");
|
||||
break;
|
||||
case ERR_PROTECTED:
|
||||
puts ("Can't write to protected Flash sectors\n");
|
||||
break;
|
||||
case ERR_INVAL:
|
||||
puts ("Outside available Flash\n");
|
||||
break;
|
||||
case ERR_ALIGN:
|
||||
puts ("Start and/or end address not on sector boundary\n");
|
||||
break;
|
||||
case ERR_UNKNOWN_FLASH_VENDOR:
|
||||
puts ("Unknown Vendor of Flash\n");
|
||||
break;
|
||||
case ERR_UNKNOWN_FLASH_TYPE:
|
||||
puts ("Unknown Type of Flash\n");
|
||||
break;
|
||||
case ERR_PROG_ERROR:
|
||||
puts ("General Flash Programming Error\n");
|
||||
break;
|
||||
default:
|
||||
printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
#endif /* !CFG_NO_FLASH */
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Rich Ireland, Enterasys Networks, rireland@enterasys.com.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic FPGA support
|
||||
*/
|
||||
#include <common.h> /* core U-Boot definitions */
|
||||
#include <xilinx.h> /* xilinx specific definitions */
|
||||
#include <altera.h> /* altera specific definitions */
|
||||
|
||||
#if defined(CONFIG_FPGA)
|
||||
|
||||
#if 0
|
||||
#define FPGA_DEBUG /* define FPGA_DEBUG to get debug messages */
|
||||
#endif
|
||||
|
||||
/* Local definitions */
|
||||
#ifndef CONFIG_MAX_FPGA_DEVICES
|
||||
#define CONFIG_MAX_FPGA_DEVICES 5
|
||||
#endif
|
||||
|
||||
/* Enable/Disable debug console messages */
|
||||
#ifdef FPGA_DEBUG
|
||||
#define PRINTF(fmt,args...) printf (fmt ,##args)
|
||||
#else
|
||||
#define PRINTF(fmt,args...)
|
||||
#endif
|
||||
|
||||
/* Local static data */
|
||||
static ulong relocation_offset = 0;
|
||||
static int next_desc = FPGA_INVALID_DEVICE;
|
||||
static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES];
|
||||
|
||||
/* Local static functions */
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum );
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate( int devnum, void *buf,
|
||||
size_t bsize, char *fn );
|
||||
static int fpga_dev_info( int devnum );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* fpga_no_sup
|
||||
* 'no support' message function
|
||||
*/
|
||||
static void fpga_no_sup( char *fn, char *msg )
|
||||
{
|
||||
if ( fn && msg ) {
|
||||
printf( "%s: No support for %s. CONFIG_FPGA defined as 0x%x.\n",
|
||||
fn, msg, CONFIG_FPGA );
|
||||
} else if ( msg ) {
|
||||
printf( "No support for %s. CONFIG_FPGA defined as 0x%x.\n",
|
||||
msg, CONFIG_FPGA );
|
||||
} else {
|
||||
printf( "No FPGA suport! CONFIG_FPGA defined as 0x%x.\n",
|
||||
CONFIG_FPGA );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* fpga_get_desc
|
||||
* map a device number to a descriptor
|
||||
*/
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_get_desc( int devnum )
|
||||
{
|
||||
fpga_desc *desc = (fpga_desc * )NULL;
|
||||
|
||||
if (( devnum >= 0 ) && (devnum < next_desc )) {
|
||||
desc = &desc_table[devnum];
|
||||
PRINTF( "%s: found fpga descriptor #%d @ 0x%p\n",
|
||||
__FUNCTION__, devnum, desc );
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_validate
|
||||
* generic parameter checking code
|
||||
*/
|
||||
static __attribute__((__const__)) fpga_desc * __attribute__((__const__)) fpga_validate( int devnum, void *buf,
|
||||
size_t bsize, char *fn )
|
||||
{
|
||||
fpga_desc * desc = fpga_get_desc( devnum );
|
||||
|
||||
if ( !desc ) {
|
||||
printf( "%s: Invalid device number %d\n", fn, devnum );
|
||||
}
|
||||
|
||||
if ( !buf ) {
|
||||
printf( "%s: Null buffer.\n", fn );
|
||||
return (fpga_desc * const)NULL;
|
||||
}
|
||||
if ( !bsize ) {
|
||||
printf( "%s: Null buffer size.\n", fn );
|
||||
return (fpga_desc * const)NULL;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_dev_info
|
||||
* generic multiplexing code
|
||||
*/
|
||||
static int fpga_dev_info( int devnum )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
const fpga_desc * const desc = fpga_get_desc( devnum );
|
||||
|
||||
if ( desc ) {
|
||||
PRINTF( "%s: Device Descriptor @ 0x%p\n",
|
||||
__FUNCTION__, desc->devdesc );
|
||||
|
||||
switch ( desc->devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if CONFIG_FPGA & CFG_FPGA_XILINX
|
||||
printf( "Xilinx Device\nDescriptor @ 0x%p\n", desc );
|
||||
ret_val = xilinx_info( desc->devdesc );
|
||||
#else
|
||||
fpga_no_sup( __FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if CONFIG_FPGA & CFG_FPGA_ALTERA
|
||||
printf( "Altera Device\nDescriptor @ 0x%p\n", desc );
|
||||
ret_val = altera_info( desc->devdesc );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, desc->devtype );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: Invalid device number %d\n",
|
||||
__FUNCTION__, devnum );
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_reloc
|
||||
* generic multiplexing code
|
||||
*/
|
||||
int fpga_reloc( fpga_type devtype, void *desc, ulong reloc_off )
|
||||
{
|
||||
int ret_val = FPGA_FAIL;
|
||||
|
||||
PRINTF( "%s: Relocating Device of type %d @ 0x%p with offset %lx\n",
|
||||
__FUNCTION__, devtype, desc, reloc_off );
|
||||
|
||||
switch ( devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if CONFIG_FPGA & CFG_FPGA_XILINX
|
||||
ret_val = xilinx_reloc( desc, reloc_off );
|
||||
#else
|
||||
fpga_no_sup( __FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if CONFIG_FPGA & CFG_FPGA_ALTERA
|
||||
ret_val = altera_reloc( desc, reloc_off );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, devtype );
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* fgpa_init is usually called from misc_init_r() and MUST be called
|
||||
* before any of the other fpga functions are used.
|
||||
*/
|
||||
void fpga_init( ulong reloc_off )
|
||||
{
|
||||
relocation_offset = reloc_off;
|
||||
next_desc = 0;
|
||||
memset( desc_table, 0, sizeof(desc_table));
|
||||
|
||||
PRINTF( "%s: CONFIG_FPGA = 0x%x\n", __FUNCTION__, CONFIG_FPGA );
|
||||
#if 0
|
||||
PRINTF( "%s: CFG_FPGA_XILINX = 0x%x\n", __FUNCTION__, CFG_FPGA_XILINX );
|
||||
PRINTF( "%s: CFG_FPGA_ALTERA = 0x%x\n", __FUNCTION__, CFG_FPGA_ALTERA );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* fpga_count
|
||||
* Basic interface function to get the current number of devices available.
|
||||
*/
|
||||
int fpga_count( void )
|
||||
{
|
||||
return next_desc;
|
||||
}
|
||||
|
||||
/* fpga_add
|
||||
* Attempts to relocate the device/board specific interface code
|
||||
* to the proper RAM locations and adds the device descriptor to
|
||||
* the device table.
|
||||
*/
|
||||
int fpga_add( fpga_type devtype, void *desc )
|
||||
{
|
||||
int devnum = FPGA_INVALID_DEVICE;
|
||||
|
||||
if ( next_desc < 0 ) {
|
||||
printf( "%s: FPGA support not initialized!\n", __FUNCTION__ );
|
||||
} else if (( devtype > fpga_min_type ) && ( devtype < fpga_undefined )) {
|
||||
if ( desc ) {
|
||||
if ( next_desc < CONFIG_MAX_FPGA_DEVICES ) {
|
||||
if ( fpga_reloc( devtype, desc, relocation_offset )
|
||||
== FPGA_SUCCESS ) {
|
||||
devnum = next_desc;
|
||||
desc_table[next_desc].devtype = devtype;
|
||||
desc_table[next_desc++].devdesc = desc;
|
||||
} else {
|
||||
printf( "%s: Unable to relocate device interface table!\n",
|
||||
__FUNCTION__ );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: Exceeded Max FPGA device count\n", __FUNCTION__ );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: NULL device descriptor\n", __FUNCTION__ );
|
||||
}
|
||||
} else {
|
||||
printf( "%s: Unsupported FPGA type %d\n", __FUNCTION__, devtype );
|
||||
}
|
||||
|
||||
return devnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic multiplexing code
|
||||
*/
|
||||
int fpga_load( int devnum, void *buf, size_t bsize )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ );
|
||||
|
||||
if ( desc ) {
|
||||
switch ( desc->devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if CONFIG_FPGA & CFG_FPGA_XILINX
|
||||
ret_val = xilinx_load( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( __FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if CONFIG_FPGA & CFG_FPGA_ALTERA
|
||||
ret_val = altera_load( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, desc->devtype );
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* fpga_dump
|
||||
* generic multiplexing code
|
||||
*/
|
||||
int fpga_dump( int devnum, void *buf, size_t bsize )
|
||||
{
|
||||
int ret_val = FPGA_FAIL; /* assume failure */
|
||||
fpga_desc * desc = fpga_validate( devnum, buf, bsize, (char *)__FUNCTION__ );
|
||||
|
||||
if ( desc ) {
|
||||
switch ( desc->devtype ) {
|
||||
case fpga_xilinx:
|
||||
#if CONFIG_FPGA & CFG_FPGA_XILINX
|
||||
ret_val = xilinx_dump( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( __FUNCTION__, "Xilinx devices" );
|
||||
#endif
|
||||
break;
|
||||
case fpga_altera:
|
||||
#if CONFIG_FPGA & CFG_FPGA_ALTERA
|
||||
ret_val = altera_dump( desc->devdesc, buf, bsize );
|
||||
#else
|
||||
fpga_no_sup( (char *)__FUNCTION__, "Altera devices" );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printf( "%s: Invalid or unsupported device type %d\n",
|
||||
__FUNCTION__, desc->devtype );
|
||||
}
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/* fpga_info
|
||||
* front end to fpga_dev_info. If devnum is invalid, report on all
|
||||
* available devices.
|
||||
*/
|
||||
int fpga_info( int devnum )
|
||||
{
|
||||
if ( devnum == FPGA_INVALID_DEVICE ) {
|
||||
if ( next_desc > 0 ) {
|
||||
int dev;
|
||||
|
||||
for ( dev = 0; dev < next_desc; dev++ ) {
|
||||
fpga_dev_info( dev );
|
||||
}
|
||||
return FPGA_SUCCESS;
|
||||
} else {
|
||||
printf( "%s: No FPGA devices available.\n", __FUNCTION__ );
|
||||
return FPGA_FAIL;
|
||||
}
|
||||
}
|
||||
else return fpga_dev_info( devnum );
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#endif /* CONFIG_FPGA */
|
|
@ -0,0 +1,722 @@
|
|||
/*
|
||||
* OF flat tree builder
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <environment.h>
|
||||
|
||||
#ifdef CONFIG_OF_FLAT_TREE
|
||||
|
||||
#include <asm/errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <ft_build.h>
|
||||
|
||||
/* align addr on a size boundary - adjust address up if needed -- Cort */
|
||||
#define _ALIGN(addr,size) (((addr)+(size)-1)&(~((size)-1)))
|
||||
|
||||
static void ft_put_word(struct ft_cxt *cxt, u32 v)
|
||||
{
|
||||
if (cxt->overflow) /* do nothing */
|
||||
return;
|
||||
|
||||
/* check for overflow */
|
||||
if (cxt->p + 4 > cxt->pstr) {
|
||||
cxt->overflow = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
*(u32 *) cxt->p = cpu_to_be32(v);
|
||||
cxt->p += 4;
|
||||
}
|
||||
|
||||
static inline void ft_put_bin(struct ft_cxt *cxt, const void *data, int sz)
|
||||
{
|
||||
u8 *p;
|
||||
|
||||
if (cxt->overflow) /* do nothing */
|
||||
return;
|
||||
|
||||
/* next pointer pos */
|
||||
p = (u8 *) _ALIGN((unsigned long)cxt->p + sz, 4);
|
||||
|
||||
/* check for overflow */
|
||||
if (p > cxt->pstr) {
|
||||
cxt->overflow = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(cxt->p, data, sz);
|
||||
if ((sz & 3) != 0)
|
||||
memset(cxt->p + sz, 0, 4 - (sz & 3));
|
||||
cxt->p = p;
|
||||
}
|
||||
|
||||
void ft_begin_node(struct ft_cxt *cxt, const char *name)
|
||||
{
|
||||
ft_put_word(cxt, OF_DT_BEGIN_NODE);
|
||||
ft_put_bin(cxt, name, strlen(name) + 1);
|
||||
}
|
||||
|
||||
void ft_end_node(struct ft_cxt *cxt)
|
||||
{
|
||||
ft_put_word(cxt, OF_DT_END_NODE);
|
||||
}
|
||||
|
||||
void ft_nop(struct ft_cxt *cxt)
|
||||
{
|
||||
ft_put_word(cxt, OF_DT_NOP);
|
||||
}
|
||||
|
||||
static int lookup_string(struct ft_cxt *cxt, const char *name)
|
||||
{
|
||||
u8 *p;
|
||||
|
||||
p = cxt->pstr;
|
||||
while (p < cxt->pstr_begin) {
|
||||
if (strcmp(p, name) == 0)
|
||||
return p - cxt->p_begin;
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ft_prop(struct ft_cxt *cxt, const char *name, const void *data, int sz)
|
||||
{
|
||||
int len, off;
|
||||
|
||||
if (cxt->overflow)
|
||||
return;
|
||||
|
||||
len = strlen(name) + 1;
|
||||
|
||||
off = lookup_string(cxt, name);
|
||||
if (off == -1) {
|
||||
/* check if we have space */
|
||||
if (cxt->p + 12 + sz + len > cxt->pstr) {
|
||||
cxt->overflow = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
cxt->pstr -= len;
|
||||
memcpy(cxt->pstr, name, len);
|
||||
off = cxt->pstr - cxt->p_begin;
|
||||
}
|
||||
|
||||
/* now put offset from beginning of *STRUCTURE* */
|
||||
/* will be fixed up at the end */
|
||||
ft_put_word(cxt, OF_DT_PROP);
|
||||
ft_put_word(cxt, sz);
|
||||
ft_put_word(cxt, off);
|
||||
ft_put_bin(cxt, data, sz);
|
||||
}
|
||||
|
||||
void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
|
||||
{
|
||||
ft_prop(cxt, name, str, strlen(str) + 1);
|
||||
}
|
||||
|
||||
void ft_prop_int(struct ft_cxt *cxt, const char *name, int val)
|
||||
{
|
||||
u32 v = cpu_to_be32((u32) val);
|
||||
|
||||
ft_prop(cxt, name, &v, 4);
|
||||
}
|
||||
|
||||
/* start construction of the flat OF tree */
|
||||
void ft_begin(struct ft_cxt *cxt, void *blob, int max_size)
|
||||
{
|
||||
struct boot_param_header *bph = blob;
|
||||
u32 off;
|
||||
|
||||
/* clear the cxt */
|
||||
memset(cxt, 0, sizeof(*cxt));
|
||||
|
||||
cxt->bph = bph;
|
||||
cxt->max_size = max_size;
|
||||
|
||||
/* zero everything in the header area */
|
||||
memset(bph, 0, sizeof(*bph));
|
||||
|
||||
bph->magic = cpu_to_be32(OF_DT_HEADER);
|
||||
bph->version = cpu_to_be32(0x10);
|
||||
bph->last_comp_version = cpu_to_be32(0x10);
|
||||
|
||||
/* start pointers */
|
||||
cxt->pres_begin = (u8 *) _ALIGN((unsigned long)(bph + 1), 8);
|
||||
cxt->pres = cxt->pres_begin;
|
||||
|
||||
off = (unsigned long)cxt->pres_begin - (unsigned long)bph;
|
||||
bph->off_mem_rsvmap = cpu_to_be32(off);
|
||||
|
||||
((u64 *) cxt->pres)[0] = 0; /* phys = 0, size = 0, terminate */
|
||||
((u64 *) cxt->pres)[1] = 0;
|
||||
|
||||
cxt->p_anchor = cxt->pres + 16; /* over the terminator */
|
||||
}
|
||||
|
||||
/* add a reserver physical area to the rsvmap */
|
||||
void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
|
||||
{
|
||||
((u64 *) cxt->pres)[0] = cpu_to_be64(physaddr); /* phys = 0, size = 0, terminate */
|
||||
((u64 *) cxt->pres)[1] = cpu_to_be64(size);
|
||||
|
||||
cxt->pres += 16; /* advance */
|
||||
|
||||
((u64 *) cxt->pres)[0] = 0; /* phys = 0, size = 0, terminate */
|
||||
((u64 *) cxt->pres)[1] = 0;
|
||||
|
||||
/* keep track of size */
|
||||
cxt->res_size = cxt->pres + 16 - cxt->pres_begin;
|
||||
|
||||
cxt->p_anchor = cxt->pres + 16; /* over the terminator */
|
||||
}
|
||||
|
||||
void ft_begin_tree(struct ft_cxt *cxt)
|
||||
{
|
||||
cxt->p_begin = cxt->p_anchor;
|
||||
cxt->pstr_begin = (char *)cxt->bph + cxt->max_size; /* point at the end */
|
||||
|
||||
cxt->p = cxt->p_begin;
|
||||
cxt->pstr = cxt->pstr_begin;
|
||||
}
|
||||
|
||||
int ft_end_tree(struct ft_cxt *cxt)
|
||||
{
|
||||
struct boot_param_header *bph = cxt->bph;
|
||||
int off, sz, sz1;
|
||||
u32 tag, v;
|
||||
u8 *p;
|
||||
|
||||
ft_put_word(cxt, OF_DT_END);
|
||||
|
||||
if (cxt->overflow)
|
||||
return -ENOMEM;
|
||||
|
||||
/* size of the areas */
|
||||
cxt->struct_size = cxt->p - cxt->p_begin;
|
||||
cxt->strings_size = cxt->pstr_begin - cxt->pstr;
|
||||
|
||||
/* the offset we must move */
|
||||
off = (cxt->pstr_begin - cxt->p_begin) - cxt->strings_size;
|
||||
|
||||
/* the new strings start */
|
||||
cxt->pstr_begin = cxt->p_begin + cxt->struct_size;
|
||||
|
||||
/* move the whole string area */
|
||||
memmove(cxt->pstr_begin, cxt->pstr, cxt->strings_size);
|
||||
|
||||
/* now perform the fixup of the strings */
|
||||
p = cxt->p_begin;
|
||||
while ((tag = be32_to_cpu(*(u32 *) p)) != OF_DT_END) {
|
||||
p += 4;
|
||||
|
||||
if (tag == OF_DT_BEGIN_NODE) {
|
||||
p = (u8 *) _ALIGN((unsigned long)p + strlen(p) + 1, 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag == OF_DT_END_NODE || tag == OF_DT_NOP)
|
||||
continue;
|
||||
|
||||
if (tag != OF_DT_PROP)
|
||||
return -EINVAL;
|
||||
|
||||
sz = be32_to_cpu(*(u32 *) p);
|
||||
p += 4;
|
||||
|
||||
v = be32_to_cpu(*(u32 *) p);
|
||||
v -= off;
|
||||
*(u32 *) p = cpu_to_be32(v); /* move down */
|
||||
p += 4;
|
||||
|
||||
p = (u8 *) _ALIGN((unsigned long)p + sz, 4);
|
||||
}
|
||||
|
||||
/* fix sizes */
|
||||
p = (char *)cxt->bph;
|
||||
sz = (cxt->pstr_begin + cxt->strings_size) - p;
|
||||
sz1 = _ALIGN(sz, 16); /* align at 16 bytes */
|
||||
if (sz != sz1)
|
||||
memset(p + sz, 0, sz1 - sz);
|
||||
bph->totalsize = cpu_to_be32(sz1);
|
||||
bph->off_dt_struct = cpu_to_be32(cxt->p_begin - p);
|
||||
bph->off_dt_strings = cpu_to_be32(cxt->pstr_begin - p);
|
||||
|
||||
/* the new strings start */
|
||||
cxt->pstr_begin = cxt->p_begin + cxt->struct_size;
|
||||
cxt->pstr = cxt->pstr_begin + cxt->strings_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static inline int isprint(int c)
|
||||
{
|
||||
return c >= 0x20 && c <= 0x7e;
|
||||
}
|
||||
|
||||
static int is_printable_string(const void *data, int len)
|
||||
{
|
||||
const char *s = data;
|
||||
const char *ss;
|
||||
|
||||
/* zero length is not */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* must terminate with zero */
|
||||
if (s[len - 1] != '\0')
|
||||
return 0;
|
||||
|
||||
ss = s;
|
||||
while (*s && isprint(*s))
|
||||
s++;
|
||||
|
||||
/* not zero, or not done yet */
|
||||
if (*s != '\0' || (s + 1 - ss) < len)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_data(const void *data, int len)
|
||||
{
|
||||
int i;
|
||||
const u8 *s;
|
||||
|
||||
/* no data, don't print */
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (is_printable_string(data, len)) {
|
||||
printf(" = \"%s\"", (char *)data);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 1: /* byte */
|
||||
printf(" = <0x%02x>", (*(u8 *) data) & 0xff);
|
||||
break;
|
||||
case 2: /* half-word */
|
||||
printf(" = <0x%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);
|
||||
break;
|
||||
case 4: /* word */
|
||||
printf(" = <0x%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
|
||||
break;
|
||||
case 8: /* double-word */
|
||||
printf(" = <0x%16llx>", be64_to_cpu(*(uint64_t *) data));
|
||||
break;
|
||||
default: /* anything else... hexdump */
|
||||
printf(" = [");
|
||||
for (i = 0, s = data; i < len; i++)
|
||||
printf("%02x%s", s[i], i < len - 1 ? " " : "");
|
||||
printf("]");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ft_dump_blob(const void *bphp)
|
||||
{
|
||||
const struct boot_param_header *bph = bphp;
|
||||
const uint64_t *p_rsvmap = (const uint64_t *)
|
||||
((const char *)bph + be32_to_cpu(bph->off_mem_rsvmap));
|
||||
const u32 *p_struct = (const u32 *)
|
||||
((const char *)bph + be32_to_cpu(bph->off_dt_struct));
|
||||
const u32 *p_strings = (const u32 *)
|
||||
((const char *)bph + be32_to_cpu(bph->off_dt_strings));
|
||||
u32 tag;
|
||||
const u32 *p;
|
||||
const char *s, *t;
|
||||
int depth, sz, shift;
|
||||
int i;
|
||||
uint64_t addr, size;
|
||||
|
||||
if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
|
||||
/* not valid tree */
|
||||
return;
|
||||
}
|
||||
|
||||
depth = 0;
|
||||
shift = 4;
|
||||
|
||||
for (i = 0;; i++) {
|
||||
addr = be64_to_cpu(p_rsvmap[i * 2]);
|
||||
size = be64_to_cpu(p_rsvmap[i * 2 + 1]);
|
||||
if (addr == 0 && size == 0)
|
||||
break;
|
||||
|
||||
printf("/memreserve/ 0x%llx 0x%llx;\n", addr, size);
|
||||
}
|
||||
|
||||
p = p_struct;
|
||||
while ((tag = be32_to_cpu(*p++)) != OF_DT_END) {
|
||||
|
||||
/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
|
||||
|
||||
if (tag == OF_DT_BEGIN_NODE) {
|
||||
s = (const char *)p;
|
||||
p = (u32 *) _ALIGN((unsigned long)p + strlen(s) + 1, 4);
|
||||
|
||||
printf("%*s%s {\n", depth * shift, "", s);
|
||||
|
||||
depth++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag == OF_DT_END_NODE) {
|
||||
depth--;
|
||||
|
||||
printf("%*s};\n", depth * shift, "");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag == OF_DT_NOP) {
|
||||
printf("%*s[NOP]\n", depth * shift, "");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag != OF_DT_PROP) {
|
||||
fprintf(stderr, "%*s ** Unknown tag 0x%08x\n",
|
||||
depth * shift, "", tag);
|
||||
break;
|
||||
}
|
||||
sz = be32_to_cpu(*p++);
|
||||
s = (const char *)p_strings + be32_to_cpu(*p++);
|
||||
t = (const char *)p;
|
||||
p = (const u32 *)_ALIGN((unsigned long)p + sz, 4);
|
||||
printf("%*s%s", depth * shift, "", s);
|
||||
print_data(t, sz);
|
||||
printf(";\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ft_backtrack_node(struct ft_cxt *cxt)
|
||||
{
|
||||
if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE)
|
||||
return; /* XXX only for node */
|
||||
|
||||
cxt->p -= 4;
|
||||
}
|
||||
|
||||
/* note that the root node of the blob is "peeled" off */
|
||||
void ft_merge_blob(struct ft_cxt *cxt, void *blob)
|
||||
{
|
||||
struct boot_param_header *bph = (struct boot_param_header *)blob;
|
||||
u32 *p_struct = (u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_struct));
|
||||
u32 *p_strings =
|
||||
(u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_strings));
|
||||
u32 tag, *p;
|
||||
char *s, *t;
|
||||
int depth, sz;
|
||||
|
||||
if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE)
|
||||
return; /* XXX only for node */
|
||||
|
||||
cxt->p -= 4;
|
||||
|
||||
depth = 0;
|
||||
p = p_struct;
|
||||
while ((tag = be32_to_cpu(*p++)) != OF_DT_END) {
|
||||
|
||||
/* printf("tag: 0x%08x (%d) - %d\n", tag, p - p_struct, depth); */
|
||||
|
||||
if (tag == OF_DT_BEGIN_NODE) {
|
||||
s = (char *)p;
|
||||
p = (u32 *) _ALIGN((unsigned long)p + strlen(s) + 1, 4);
|
||||
|
||||
if (depth++ > 0)
|
||||
ft_begin_node(cxt, s);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag == OF_DT_END_NODE) {
|
||||
ft_end_node(cxt);
|
||||
if (--depth == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag == OF_DT_NOP)
|
||||
continue;
|
||||
|
||||
if (tag != OF_DT_PROP)
|
||||
break;
|
||||
|
||||
sz = be32_to_cpu(*p++);
|
||||
s = (char *)p_strings + be32_to_cpu(*p++);
|
||||
t = (char *)p;
|
||||
p = (u32 *) _ALIGN((unsigned long)p + sz, 4);
|
||||
|
||||
ft_prop(cxt, s, t, sz);
|
||||
}
|
||||
}
|
||||
|
||||
void *ft_get_prop(void *bphp, const char *propname, int *szp)
|
||||
{
|
||||
struct boot_param_header *bph = bphp;
|
||||
uint32_t *p_struct =
|
||||
(uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_struct));
|
||||
uint32_t *p_strings =
|
||||
(uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_strings));
|
||||
uint32_t version = be32_to_cpu(bph->version);
|
||||
uint32_t tag;
|
||||
uint32_t *p;
|
||||
char *s, *t;
|
||||
char *ss;
|
||||
int sz;
|
||||
static char path[256], prop[256];
|
||||
|
||||
path[0] = '\0';
|
||||
|
||||
p = p_struct;
|
||||
while ((tag = be32_to_cpu(*p++)) != OF_DT_END) {
|
||||
|
||||
if (tag == OF_DT_BEGIN_NODE) {
|
||||
s = (char *)p;
|
||||
p = (uint32_t *) _ALIGN((unsigned long)p + strlen(s) +
|
||||
1, 4);
|
||||
strcat(path, s);
|
||||
strcat(path, "/");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag == OF_DT_END_NODE) {
|
||||
path[strlen(path) - 1] = '\0';
|
||||
ss = strrchr(path, '/');
|
||||
if (ss != NULL)
|
||||
ss[1] = '\0';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag == OF_DT_NOP)
|
||||
continue;
|
||||
|
||||
if (tag != OF_DT_PROP)
|
||||
break;
|
||||
|
||||
sz = be32_to_cpu(*p++);
|
||||
s = (char *)p_strings + be32_to_cpu(*p++);
|
||||
if (version < 0x10 && sz >= 8)
|
||||
p = (uint32_t *) _ALIGN((unsigned long)p, 8);
|
||||
t = (char *)p;
|
||||
p = (uint32_t *) _ALIGN((unsigned long)p + sz, 4);
|
||||
|
||||
strcpy(prop, path);
|
||||
strcat(prop, s);
|
||||
|
||||
if (strcmp(prop, propname) == 0) {
|
||||
*szp = sz;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
extern unsigned char oftree_dtb[];
|
||||
extern unsigned int oftree_dtb_len;
|
||||
|
||||
/* Function that returns a character from the environment */
|
||||
extern uchar(*env_get_char) (int);
|
||||
|
||||
#define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
|
||||
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
static const struct {
|
||||
const char *name;
|
||||
int offset;
|
||||
} bd_map[] = {
|
||||
BDM(memstart),
|
||||
BDM(memsize),
|
||||
BDM(flashstart),
|
||||
BDM(flashsize),
|
||||
BDM(flashoffset),
|
||||
BDM(sramstart),
|
||||
BDM(sramsize),
|
||||
#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
|
||||
|| defined(CONFIG_E500)
|
||||
BDM(immr_base),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
BDM(mbar_base),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC83XX)
|
||||
BDM(immrbar),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC8220)
|
||||
BDM(mbar_base),
|
||||
BDM(inpfreq),
|
||||
BDM(pcifreq),
|
||||
BDM(pevfreq),
|
||||
BDM(flbfreq),
|
||||
BDM(vcofreq),
|
||||
#endif
|
||||
BDM(bootflags),
|
||||
BDM(ip_addr),
|
||||
BDM(intfreq),
|
||||
BDM(busfreq),
|
||||
#ifdef CONFIG_CPM2
|
||||
BDM(cpmfreq),
|
||||
BDM(brgfreq),
|
||||
BDM(sccfreq),
|
||||
BDM(vco),
|
||||
#endif
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
BDM(ipbfreq),
|
||||
BDM(pcifreq),
|
||||
#endif
|
||||
BDM(baudrate),
|
||||
};
|
||||
#endif
|
||||
|
||||
void ft_setup(void *blob, int size, bd_t * bd, ulong initrd_start, ulong initrd_end)
|
||||
{
|
||||
u32 *p;
|
||||
int len;
|
||||
struct ft_cxt cxt;
|
||||
ulong clock;
|
||||
#if defined(CONFIG_OF_HAS_UBOOT_ENV)
|
||||
int k, nxt;
|
||||
#endif
|
||||
#if defined(CONFIG_OF_HAS_BD_T)
|
||||
u8 *end;
|
||||
#endif
|
||||
#if defined(CONFIG_OF_HAS_UBOOT_ENV) || defined(CONFIG_OF_HAS_BD_T)
|
||||
int i;
|
||||
static char tmpenv[256];
|
||||
#endif
|
||||
|
||||
/* disable OF tree; booting old kernel */
|
||||
if (getenv("disable_of") != NULL) {
|
||||
memcpy(blob, bd, sizeof(*bd));
|
||||
return;
|
||||
}
|
||||
|
||||
ft_begin(&cxt, blob, size);
|
||||
|
||||
if (initrd_start && initrd_end)
|
||||
ft_add_rsvmap(&cxt, initrd_start, initrd_end - initrd_start + 1);
|
||||
|
||||
ft_begin_tree(&cxt);
|
||||
|
||||
ft_begin_node(&cxt, "");
|
||||
|
||||
ft_end_node(&cxt);
|
||||
|
||||
/* copy RO tree */
|
||||
ft_merge_blob(&cxt, oftree_dtb);
|
||||
|
||||
/* back into root */
|
||||
ft_backtrack_node(&cxt);
|
||||
|
||||
#ifdef CONFIG_OF_HAS_UBOOT_ENV
|
||||
ft_begin_node(&cxt, "u-boot-env");
|
||||
|
||||
for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
|
||||
char *s, *lval, *rval;
|
||||
|
||||
for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) ;
|
||||
s = tmpenv;
|
||||
for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k)
|
||||
*s++ = env_get_char(k);
|
||||
*s++ = '\0';
|
||||
lval = tmpenv;
|
||||
s = strchr(tmpenv, '=');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
rval = s;
|
||||
} else
|
||||
continue;
|
||||
ft_prop_str(&cxt, lval, rval);
|
||||
}
|
||||
|
||||
ft_end_node(&cxt);
|
||||
#endif
|
||||
|
||||
ft_begin_node(&cxt, "chosen");
|
||||
|
||||
ft_prop_str(&cxt, "name", "chosen");
|
||||
ft_prop_str(&cxt, "bootargs", getenv("bootargs"));
|
||||
ft_prop_int(&cxt, "linux,platform", 0x600); /* what is this? */
|
||||
if (initrd_start && initrd_end) {
|
||||
ft_prop_int(&cxt, "linux,initrd-start", initrd_start);
|
||||
ft_prop_int(&cxt, "linux,initrd-end", initrd_end);
|
||||
}
|
||||
#ifdef OF_STDOUT_PATH
|
||||
ft_prop_str(&cxt, "linux,stdout-path", OF_STDOUT_PATH);
|
||||
#endif
|
||||
|
||||
ft_end_node(&cxt);
|
||||
|
||||
ft_end_node(&cxt); /* end root */
|
||||
|
||||
ft_end_tree(&cxt);
|
||||
|
||||
/*
|
||||
printf("merged OF-tree\n");
|
||||
ft_dump_blob(blob);
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
/* paste the bd_t at the end of the flat tree */
|
||||
end = (char *)blob +
|
||||
be32_to_cpu(((struct boot_param_header *)blob)->totalsize);
|
||||
memcpy(end, bd, sizeof(*bd));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC
|
||||
|
||||
#ifdef CONFIG_OF_HAS_BD_T
|
||||
for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
|
||||
uint32_t v;
|
||||
|
||||
sprintf(tmpenv, "/bd_t/%s", bd_map[i].name);
|
||||
v = *(uint32_t *)((char *)bd + bd_map[i].offset);
|
||||
|
||||
p = ft_get_prop(blob, tmpenv, &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(v);
|
||||
}
|
||||
|
||||
p = ft_get_prop(blob, "/bd_t/enetaddr", &len);
|
||||
if (p != NULL)
|
||||
memcpy(p, bd->bi_enetaddr, 6);
|
||||
|
||||
p = ft_get_prop(blob, "/bd_t/ethspeed", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32((uint32_t) bd->bi_ethspeed);
|
||||
#endif
|
||||
|
||||
clock = bd->bi_intfreq;
|
||||
p = ft_get_prop(blob, "/cpus/" OF_CPU "/clock-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
|
||||
#ifdef OF_TBCLK
|
||||
clock = OF_TBCLK;
|
||||
p = ft_get_prop(blob, "/cpus/" OF_CPU "/timebase-frequency", &len);
|
||||
if (p != NULL)
|
||||
*p = cpu_to_be32(clock);
|
||||
#endif
|
||||
#endif /* __powerpc__ */
|
||||
|
||||
#ifdef CONFIG_OF_BOARD_SETUP
|
||||
ft_board_setup(blob, bd);
|
||||
#endif
|
||||
|
||||
/*
|
||||
printf("final OF-tree\n");
|
||||
ft_dump_blob(blob);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,594 @@
|
|||
/* taken from arch/ppc/kernel/ppc-stub.c */
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
THIS SOFTWARE IS NOT COPYRIGHTED
|
||||
|
||||
HP offers the following for use in the public domain. HP makes no
|
||||
warranty with regard to the software or its performance and the
|
||||
user accepts the software "AS IS" with all faults.
|
||||
|
||||
HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
|
||||
*
|
||||
* Module name: remcom.c $
|
||||
* Revision: 1.34 $
|
||||
* Date: 91/03/09 12:29:49 $
|
||||
* Contributor: Lake Stevens Instrument Division$
|
||||
*
|
||||
* Description: low level support for gdb debugger. $
|
||||
*
|
||||
* Considerations: only works on target hardware $
|
||||
*
|
||||
* Written by: Glenn Engel $
|
||||
* ModuleState: Experimental $
|
||||
*
|
||||
* NOTES: See Below $
|
||||
*
|
||||
* Modified for SPARC by Stu Grossman, Cygnus Support.
|
||||
*
|
||||
* This code has been extensively tested on the Fujitsu SPARClite demo board.
|
||||
*
|
||||
* To enable debugger support, two things need to happen. One, a
|
||||
* call to set_debug_traps() is necessary in order to allow any breakpoints
|
||||
* or error conditions to be properly intercepted and reported to gdb.
|
||||
* Two, a breakpoint needs to be generated to begin communication. This
|
||||
* is most easily accomplished by a call to breakpoint(). Breakpoint()
|
||||
* simulates a breakpoint by executing a trap #1.
|
||||
*
|
||||
*************
|
||||
*
|
||||
* The following gdb commands are supported:
|
||||
*
|
||||
* command function Return value
|
||||
*
|
||||
* g return the value of the CPU registers hex data or ENN
|
||||
* G set the value of the CPU registers OK or ENN
|
||||
* qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
|
||||
*
|
||||
* mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
|
||||
* MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
|
||||
*
|
||||
* c Resume at current address SNN ( signal NN)
|
||||
* cAA..AA Continue at address AA..AA SNN
|
||||
*
|
||||
* s Step one instruction SNN
|
||||
* sAA..AA Step one instruction from AA..AA SNN
|
||||
*
|
||||
* k kill
|
||||
*
|
||||
* ? What was the last sigval ? SNN (signal NN)
|
||||
*
|
||||
* bBB..BB Set baud rate to BB..BB OK or BNN, then sets
|
||||
* baud rate
|
||||
*
|
||||
* All commands and responses are sent with a packet which includes a
|
||||
* checksum. A packet consists of
|
||||
*
|
||||
* $<packet info>#<checksum>.
|
||||
*
|
||||
* where
|
||||
* <packet info> :: <characters representing the command or response>
|
||||
* <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
|
||||
*
|
||||
* When a packet is received, it is first acknowledged with either '+' or '-'.
|
||||
* '+' indicates a successful transfer. '-' indicates a failed transfer.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Host: Reply:
|
||||
* $m0,10#2a +$00010203040506070809101112131415#42
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#include <kgdb.h>
|
||||
#include <command.h>
|
||||
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
|
||||
|
||||
#undef KGDB_DEBUG
|
||||
|
||||
/*
|
||||
* BUFMAX defines the maximum number of characters in inbound/outbound buffers
|
||||
*/
|
||||
#define BUFMAX 1024
|
||||
static char remcomInBuffer[BUFMAX];
|
||||
static char remcomOutBuffer[BUFMAX];
|
||||
static char remcomRegBuffer[BUFMAX];
|
||||
|
||||
static int initialized = 0;
|
||||
static int kgdb_active = 0, first_entry = 1;
|
||||
static struct pt_regs entry_regs;
|
||||
static u_int error_jmp_buf[BUFMAX/2];
|
||||
static int longjmp_on_fault = 0;
|
||||
#ifdef KGDB_DEBUG
|
||||
static int kdebug = 1;
|
||||
#endif
|
||||
|
||||
static const char hexchars[]="0123456789abcdef";
|
||||
|
||||
/* Convert ch from a hex digit to an int */
|
||||
static int
|
||||
hex(unsigned char ch)
|
||||
{
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
return ch-'a'+10;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch-'0';
|
||||
if (ch >= 'A' && ch <= 'F')
|
||||
return ch-'A'+10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert the memory pointed to by mem into hex, placing result in buf.
|
||||
* Return a pointer to the last char put in buf (null).
|
||||
*/
|
||||
static unsigned char *
|
||||
mem2hex(char *mem, char *buf, int count)
|
||||
{
|
||||
unsigned char ch;
|
||||
|
||||
longjmp_on_fault = 1;
|
||||
while (count-- > 0) {
|
||||
ch = *mem++;
|
||||
*buf++ = hexchars[ch >> 4];
|
||||
*buf++ = hexchars[ch & 0xf];
|
||||
}
|
||||
*buf = 0;
|
||||
longjmp_on_fault = 0;
|
||||
return (unsigned char *)buf;
|
||||
}
|
||||
|
||||
/* convert the hex array pointed to by buf into binary to be placed in mem
|
||||
* return a pointer to the character AFTER the last byte fetched from buf.
|
||||
*/
|
||||
static char *
|
||||
hex2mem(char *buf, char *mem, int count)
|
||||
{
|
||||
int i, hexValue;
|
||||
unsigned char ch;
|
||||
char *mem_start = mem;
|
||||
|
||||
longjmp_on_fault = 1;
|
||||
for (i=0; i<count; i++) {
|
||||
if ((hexValue = hex(*buf++)) < 0)
|
||||
kgdb_error(KGDBERR_NOTHEXDIG);
|
||||
ch = hexValue << 4;
|
||||
if ((hexValue = hex(*buf++)) < 0)
|
||||
kgdb_error(KGDBERR_NOTHEXDIG);
|
||||
ch |= hexValue;
|
||||
*mem++ = ch;
|
||||
}
|
||||
kgdb_flush_cache_range((void *)mem_start, (void *)(mem - 1));
|
||||
longjmp_on_fault = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* While we find nice hex chars, build an int.
|
||||
* Return number of chars processed.
|
||||
*/
|
||||
static int
|
||||
hexToInt(char **ptr, int *intValue)
|
||||
{
|
||||
int numChars = 0;
|
||||
int hexValue;
|
||||
|
||||
*intValue = 0;
|
||||
|
||||
longjmp_on_fault = 1;
|
||||
while (**ptr) {
|
||||
hexValue = hex(**ptr);
|
||||
if (hexValue < 0)
|
||||
break;
|
||||
|
||||
*intValue = (*intValue << 4) | hexValue;
|
||||
numChars ++;
|
||||
|
||||
(*ptr)++;
|
||||
}
|
||||
longjmp_on_fault = 0;
|
||||
|
||||
return (numChars);
|
||||
}
|
||||
|
||||
/* scan for the sequence $<data>#<checksum> */
|
||||
static void
|
||||
getpacket(char *buffer)
|
||||
{
|
||||
unsigned char checksum;
|
||||
unsigned char xmitcsum;
|
||||
int i;
|
||||
int count;
|
||||
unsigned char ch;
|
||||
|
||||
do {
|
||||
/* wait around for the start character, ignore all other
|
||||
* characters */
|
||||
while ((ch = (getDebugChar() & 0x7f)) != '$') {
|
||||
#ifdef KGDB_DEBUG
|
||||
if (kdebug)
|
||||
putc(ch);
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
checksum = 0;
|
||||
xmitcsum = -1;
|
||||
|
||||
count = 0;
|
||||
|
||||
/* now, read until a # or end of buffer is found */
|
||||
while (count < BUFMAX) {
|
||||
ch = getDebugChar() & 0x7f;
|
||||
if (ch == '#')
|
||||
break;
|
||||
checksum = checksum + ch;
|
||||
buffer[count] = ch;
|
||||
count = count + 1;
|
||||
}
|
||||
|
||||
if (count >= BUFMAX)
|
||||
continue;
|
||||
|
||||
buffer[count] = 0;
|
||||
|
||||
if (ch == '#') {
|
||||
xmitcsum = hex(getDebugChar() & 0x7f) << 4;
|
||||
xmitcsum |= hex(getDebugChar() & 0x7f);
|
||||
if (checksum != xmitcsum)
|
||||
putDebugChar('-'); /* failed checksum */
|
||||
else {
|
||||
putDebugChar('+'); /* successful transfer */
|
||||
/* if a sequence char is present, reply the ID */
|
||||
if (buffer[2] == ':') {
|
||||
putDebugChar(buffer[0]);
|
||||
putDebugChar(buffer[1]);
|
||||
/* remove sequence chars from buffer */
|
||||
count = strlen(buffer);
|
||||
for (i=3; i <= count; i++)
|
||||
buffer[i-3] = buffer[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (checksum != xmitcsum);
|
||||
}
|
||||
|
||||
/* send the packet in buffer. */
|
||||
static void
|
||||
putpacket(unsigned char *buffer)
|
||||
{
|
||||
unsigned char checksum;
|
||||
int count;
|
||||
unsigned char ch, recv;
|
||||
|
||||
/* $<packet info>#<checksum>. */
|
||||
do {
|
||||
putDebugChar('$');
|
||||
checksum = 0;
|
||||
count = 0;
|
||||
|
||||
while ((ch = buffer[count])) {
|
||||
putDebugChar(ch);
|
||||
checksum += ch;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
putDebugChar('#');
|
||||
putDebugChar(hexchars[checksum >> 4]);
|
||||
putDebugChar(hexchars[checksum & 0xf]);
|
||||
recv = getDebugChar();
|
||||
} while ((recv & 0x7f) != '+');
|
||||
}
|
||||
|
||||
/*
|
||||
* This function does all command processing for interfacing to gdb.
|
||||
*/
|
||||
static int
|
||||
handle_exception (struct pt_regs *regs)
|
||||
{
|
||||
int addr;
|
||||
int length;
|
||||
char *ptr;
|
||||
kgdb_data kd;
|
||||
int i;
|
||||
|
||||
if (!initialized) {
|
||||
printf("kgdb: exception before kgdb is initialized! huh?\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* probably should check which exception occured as well */
|
||||
if (longjmp_on_fault) {
|
||||
longjmp_on_fault = 0;
|
||||
kgdb_longjmp((long*)error_jmp_buf, KGDBERR_MEMFAULT);
|
||||
panic("kgdb longjump failed!\n");
|
||||
}
|
||||
|
||||
if (kgdb_active) {
|
||||
printf("kgdb: unexpected exception from within kgdb\n");
|
||||
return (0);
|
||||
}
|
||||
kgdb_active = 1;
|
||||
|
||||
kgdb_interruptible(0);
|
||||
|
||||
printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));
|
||||
|
||||
if (kgdb_setjmp((long*)error_jmp_buf) != 0)
|
||||
panic("kgdb: error or fault in entry init!\n");
|
||||
|
||||
kgdb_enter(regs, &kd);
|
||||
|
||||
if (first_entry) {
|
||||
/*
|
||||
* the first time we enter kgdb, we save the processor
|
||||
* state so that we can return to the monitor if the
|
||||
* remote end quits gdb (or at least, tells us to quit
|
||||
* with the 'k' packet)
|
||||
*/
|
||||
entry_regs = *regs;
|
||||
first_entry = 0;
|
||||
}
|
||||
|
||||
ptr = remcomOutBuffer;
|
||||
|
||||
*ptr++ = 'T';
|
||||
|
||||
*ptr++ = hexchars[kd.sigval >> 4];
|
||||
*ptr++ = hexchars[kd.sigval & 0xf];
|
||||
|
||||
for (i = 0; i < kd.nregs; i++) {
|
||||
kgdb_reg *rp = &kd.regs[i];
|
||||
|
||||
*ptr++ = hexchars[rp->num >> 4];
|
||||
*ptr++ = hexchars[rp->num & 0xf];
|
||||
*ptr++ = ':';
|
||||
ptr = (char *)mem2hex((char *)&rp->val, ptr, 4);
|
||||
*ptr++ = ';';
|
||||
}
|
||||
|
||||
*ptr = 0;
|
||||
|
||||
#ifdef KGDB_DEBUG
|
||||
if (kdebug)
|
||||
printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
|
||||
#endif
|
||||
|
||||
putpacket((unsigned char *)&remcomOutBuffer);
|
||||
|
||||
while (1) {
|
||||
volatile int errnum;
|
||||
|
||||
remcomOutBuffer[0] = 0;
|
||||
|
||||
getpacket(remcomInBuffer);
|
||||
ptr = &remcomInBuffer[1];
|
||||
|
||||
#ifdef KGDB_DEBUG
|
||||
if (kdebug)
|
||||
printf("kgdb: remcomInBuffer: %s\n", remcomInBuffer);
|
||||
#endif
|
||||
|
||||
errnum = kgdb_setjmp((long*)error_jmp_buf);
|
||||
|
||||
if (errnum == 0) switch (remcomInBuffer[0]) {
|
||||
|
||||
case '?': /* report most recent signal */
|
||||
remcomOutBuffer[0] = 'S';
|
||||
remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
|
||||
remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
|
||||
remcomOutBuffer[3] = 0;
|
||||
break;
|
||||
|
||||
#ifdef KGDB_DEBUG
|
||||
case 'd':
|
||||
/* toggle debug flag */
|
||||
kdebug ^= 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'g': /* return the value of the CPU registers. */
|
||||
length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
|
||||
mem2hex(remcomRegBuffer, remcomOutBuffer, length);
|
||||
break;
|
||||
|
||||
case 'G': /* set the value of the CPU registers */
|
||||
length = strlen(ptr);
|
||||
if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
|
||||
hex2mem(ptr, remcomRegBuffer, length/2);
|
||||
kgdb_putregs(regs, remcomRegBuffer, length/2);
|
||||
strcpy(remcomOutBuffer,"OK");
|
||||
break;
|
||||
|
||||
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
|
||||
/* Try to read %x,%x. */
|
||||
|
||||
if (hexToInt(&ptr, &addr)
|
||||
&& *ptr++ == ','
|
||||
&& hexToInt(&ptr, &length)) {
|
||||
mem2hex((char *)addr, remcomOutBuffer, length);
|
||||
} else {
|
||||
kgdb_error(KGDBERR_BADPARAMS);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
|
||||
/* Try to read '%x,%x:'. */
|
||||
|
||||
if (hexToInt(&ptr, &addr)
|
||||
&& *ptr++ == ','
|
||||
&& hexToInt(&ptr, &length)
|
||||
&& *ptr++ == ':') {
|
||||
hex2mem(ptr, (char *)addr, length);
|
||||
strcpy(remcomOutBuffer, "OK");
|
||||
} else {
|
||||
kgdb_error(KGDBERR_BADPARAMS);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'k': /* kill the program, actually return to monitor */
|
||||
kd.extype = KGDBEXIT_KILL;
|
||||
*regs = entry_regs;
|
||||
first_entry = 1;
|
||||
goto doexit;
|
||||
|
||||
case 'C': /* CSS continue with signal SS */
|
||||
*ptr = '\0'; /* ignore the signal number for now */
|
||||
/* fall through */
|
||||
|
||||
case 'c': /* cAA..AA Continue; address AA..AA optional */
|
||||
/* try to read optional parameter, pc unchanged if no parm */
|
||||
kd.extype = KGDBEXIT_CONTINUE;
|
||||
|
||||
if (hexToInt(&ptr, &addr)) {
|
||||
kd.exaddr = addr;
|
||||
kd.extype |= KGDBEXIT_WITHADDR;
|
||||
}
|
||||
|
||||
goto doexit;
|
||||
|
||||
case 'S': /* SSS single step with signal SS */
|
||||
*ptr = '\0'; /* ignore the signal number for now */
|
||||
/* fall through */
|
||||
|
||||
case 's':
|
||||
kd.extype = KGDBEXIT_SINGLE;
|
||||
|
||||
if (hexToInt(&ptr, &addr)) {
|
||||
kd.exaddr = addr;
|
||||
kd.extype |= KGDBEXIT_WITHADDR;
|
||||
}
|
||||
|
||||
doexit:
|
||||
/* Need to flush the instruction cache here, as we may have deposited a
|
||||
* breakpoint, and the icache probably has no way of knowing that a data ref to
|
||||
* some location may have changed something that is in the instruction cache.
|
||||
*/
|
||||
kgdb_flush_cache_all();
|
||||
kgdb_exit(regs, &kd);
|
||||
kgdb_active = 0;
|
||||
kgdb_interruptible(1);
|
||||
return (1);
|
||||
|
||||
case 'r': /* Reset (if user process..exit ???)*/
|
||||
panic("kgdb reset.");
|
||||
break;
|
||||
|
||||
case 'P': /* Pr=v set reg r to value v (r and v are hex) */
|
||||
if (hexToInt(&ptr, &addr)
|
||||
&& *ptr++ == '='
|
||||
&& ((length = strlen(ptr)) & 1) == 0) {
|
||||
hex2mem(ptr, remcomRegBuffer, length/2);
|
||||
kgdb_putreg(regs, addr,
|
||||
remcomRegBuffer, length/2);
|
||||
strcpy(remcomOutBuffer,"OK");
|
||||
} else {
|
||||
kgdb_error(KGDBERR_BADPARAMS);
|
||||
}
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
if (errnum != 0)
|
||||
sprintf(remcomOutBuffer, "E%02d", errnum);
|
||||
|
||||
#ifdef KGDB_DEBUG
|
||||
if (kdebug)
|
||||
printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
|
||||
#endif
|
||||
|
||||
/* reply to the request */
|
||||
putpacket((unsigned char *)&remcomOutBuffer);
|
||||
|
||||
} /* while(1) */
|
||||
}
|
||||
|
||||
/*
|
||||
* kgdb_init must be called *after* the
|
||||
* monitor is relocated into ram
|
||||
*/
|
||||
void
|
||||
kgdb_init(void)
|
||||
{
|
||||
kgdb_serial_init();
|
||||
debugger_exception_handler = handle_exception;
|
||||
initialized = 1;
|
||||
|
||||
putDebugStr("kgdb ready\n");
|
||||
puts("ready\n");
|
||||
}
|
||||
|
||||
void
|
||||
kgdb_error(int errnum)
|
||||
{
|
||||
longjmp_on_fault = 0;
|
||||
kgdb_longjmp((long*)error_jmp_buf, errnum);
|
||||
panic("kgdb_error: longjmp failed!\n");
|
||||
}
|
||||
|
||||
/* Output string in GDB O-packet format if GDB has connected. If nothing
|
||||
output, returns 0 (caller must then handle output). */
|
||||
int
|
||||
kgdb_output_string (const char* s, unsigned int count)
|
||||
{
|
||||
char buffer[512];
|
||||
|
||||
count = (count <= (sizeof(buffer) / 2 - 2))
|
||||
? count : (sizeof(buffer) / 2 - 2);
|
||||
|
||||
buffer[0] = 'O';
|
||||
mem2hex ((char *)s, &buffer[1], count);
|
||||
putpacket((unsigned char *)&buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
breakpoint(void)
|
||||
{
|
||||
if (!initialized) {
|
||||
printf("breakpoint() called b4 kgdb init\n");
|
||||
return;
|
||||
}
|
||||
|
||||
kgdb_breakpoint(0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
do_kgdb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
printf("Entering KGDB mode via exception handler...\n\n");
|
||||
kgdb_breakpoint(argc - 1, argv + 1);
|
||||
printf("\nReturned from KGDB mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
kgdb, CFG_MAXARGS, 1, do_kgdb,
|
||||
"kgdb - enter gdb remote debug mode\n",
|
||||
"[arg0 arg1 .. argN]\n"
|
||||
" - executes a breakpoint so that kgdb mode is\n"
|
||||
" entered via the exception handler. To return\n"
|
||||
" to the monitor, the remote gdb debugger must\n"
|
||||
" execute a \"continue\" or \"quit\" command.\n"
|
||||
"\n"
|
||||
" if a program is loaded by the remote gdb, any args\n"
|
||||
" passed to the kgdb command are given to the loaded\n"
|
||||
" program if it is executed (see the \"hello_world\"\n"
|
||||
" example program in the U-Boot examples directory)."
|
||||
);
|
||||
#else
|
||||
|
||||
int kgdb_not_configured = 1;
|
||||
|
||||
#endif /* CFG_CMD_KGDB */
|
|
@ -0,0 +1,753 @@
|
|||
/*
|
||||
* Common LCD routines for supported CPUs
|
||||
*
|
||||
* (C) Copyright 2001-2002
|
||||
* 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
|
||||
*/
|
||||
|
||||
/************************************************************************/
|
||||
/* ** HEADER FILES */
|
||||
/************************************************************************/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <version.h>
|
||||
#include <stdarg.h>
|
||||
#include <linux/types.h>
|
||||
#include <devices.h>
|
||||
#if defined(CONFIG_POST)
|
||||
#include <post.h>
|
||||
#endif
|
||||
#include <lcd.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
#if defined(CONFIG_PXA250)
|
||||
#include <asm/byteorder.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPC823)
|
||||
#include <lcdvideo.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LCD
|
||||
|
||||
/************************************************************************/
|
||||
/* ** FONT DATA */
|
||||
/************************************************************************/
|
||||
#include <video_font.h> /* Get font data, width and height */
|
||||
|
||||
/************************************************************************/
|
||||
/* ** LOGO DATA */
|
||||
/************************************************************************/
|
||||
#ifdef CONFIG_LCD_LOGO
|
||||
# include <bmp_logo.h> /* Get logo data, width and height */
|
||||
# if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET)
|
||||
# error Default Color Map overlaps with Logo Color Map
|
||||
# endif
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
ulong lcd_setmem (ulong addr);
|
||||
|
||||
static void lcd_drawchars (ushort x, ushort y, uchar *str, int count);
|
||||
static inline void lcd_puts_xy (ushort x, ushort y, uchar *s);
|
||||
static inline void lcd_putc_xy (ushort x, ushort y, uchar c);
|
||||
|
||||
static int lcd_init (void *lcdbase);
|
||||
|
||||
static int lcd_clear (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
|
||||
extern void lcd_ctrl_init (void *lcdbase);
|
||||
extern void lcd_enable (void);
|
||||
static void *lcd_logo (void);
|
||||
|
||||
|
||||
#if LCD_BPP == LCD_COLOR8
|
||||
extern void lcd_setcolreg (ushort regno,
|
||||
ushort red, ushort green, ushort blue);
|
||||
#endif
|
||||
#if LCD_BPP == LCD_MONOCHROME
|
||||
extern void lcd_initcolregs (void);
|
||||
#endif
|
||||
|
||||
static int lcd_getbgcolor (void);
|
||||
static void lcd_setfgcolor (int color);
|
||||
static void lcd_setbgcolor (int color);
|
||||
|
||||
char lcd_is_enabled = 0;
|
||||
extern vidinfo_t panel_info;
|
||||
|
||||
#ifdef NOT_USED_SO_FAR
|
||||
static void lcd_getcolreg (ushort regno,
|
||||
ushort *red, ushort *green, ushort *blue);
|
||||
static int lcd_getfgcolor (void);
|
||||
#endif /* NOT_USED_SO_FAR */
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static void console_scrollup (void)
|
||||
{
|
||||
#if 1
|
||||
/* Copy up rows ignoring the first one */
|
||||
memcpy (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE);
|
||||
|
||||
/* Clear the last one */
|
||||
memset (CONSOLE_ROW_LAST, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE);
|
||||
#else
|
||||
/*
|
||||
* Poor attempt to optimize speed by moving "long"s.
|
||||
* But the code is ugly, and not a bit faster :-(
|
||||
*/
|
||||
ulong *t = (ulong *)CONSOLE_ROW_FIRST;
|
||||
ulong *s = (ulong *)CONSOLE_ROW_SECOND;
|
||||
ulong l = CONSOLE_SCROLL_SIZE / sizeof(ulong);
|
||||
uchar c = lcd_color_bg & 0xFF;
|
||||
ulong val= (c<<24) | (c<<16) | (c<<8) | c;
|
||||
|
||||
while (l--)
|
||||
*t++ = *s++;
|
||||
|
||||
t = (ulong *)CONSOLE_ROW_LAST;
|
||||
l = CONSOLE_ROW_SIZE / sizeof(ulong);
|
||||
|
||||
while (l-- > 0)
|
||||
*t++ = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static inline void console_back (void)
|
||||
{
|
||||
if (--console_col < 0) {
|
||||
console_col = CONSOLE_COLS-1 ;
|
||||
if (--console_row < 0) {
|
||||
console_row = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lcd_putc_xy (console_col * VIDEO_FONT_WIDTH,
|
||||
console_row * VIDEO_FONT_HEIGHT,
|
||||
' ');
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static inline void console_newline (void)
|
||||
{
|
||||
++console_row;
|
||||
console_col = 0;
|
||||
|
||||
/* Check if we need to scroll the terminal */
|
||||
if (console_row >= CONSOLE_ROWS) {
|
||||
/* Scroll everything up */
|
||||
console_scrollup () ;
|
||||
--console_row;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void lcd_putc (const char c)
|
||||
{
|
||||
if (!lcd_is_enabled) {
|
||||
serial_putc(c);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '\r': console_col = 0;
|
||||
return;
|
||||
|
||||
case '\n': console_newline();
|
||||
return;
|
||||
|
||||
case '\t': /* Tab (8 chars alignment) */
|
||||
console_col |= 8;
|
||||
console_col &= ~7;
|
||||
|
||||
if (console_col >= CONSOLE_COLS) {
|
||||
console_newline();
|
||||
}
|
||||
return;
|
||||
|
||||
case '\b': console_back();
|
||||
return;
|
||||
|
||||
default: lcd_putc_xy (console_col * VIDEO_FONT_WIDTH,
|
||||
console_row * VIDEO_FONT_HEIGHT,
|
||||
c);
|
||||
if (++console_col >= CONSOLE_COLS) {
|
||||
console_newline();
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void lcd_puts (const char *s)
|
||||
{
|
||||
if (!lcd_is_enabled) {
|
||||
serial_puts (s);
|
||||
return;
|
||||
}
|
||||
|
||||
while (*s) {
|
||||
lcd_putc (*s++);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ** Low-Level Graphics Routines */
|
||||
/************************************************************************/
|
||||
|
||||
static void lcd_drawchars (ushort x, ushort y, uchar *str, int count)
|
||||
{
|
||||
uchar *dest;
|
||||
ushort off, row;
|
||||
|
||||
dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
|
||||
off = x * (1 << LCD_BPP) % 8;
|
||||
|
||||
for (row=0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
|
||||
uchar *s = str;
|
||||
uchar *d = dest;
|
||||
int i;
|
||||
|
||||
#if LCD_BPP == LCD_MONOCHROME
|
||||
uchar rest = *d & -(1 << (8-off));
|
||||
uchar sym;
|
||||
#endif
|
||||
for (i=0; i<count; ++i) {
|
||||
uchar c, bits;
|
||||
|
||||
c = *s++;
|
||||
bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
|
||||
|
||||
#if LCD_BPP == LCD_MONOCHROME
|
||||
sym = (COLOR_MASK(lcd_color_fg) & bits) |
|
||||
(COLOR_MASK(lcd_color_bg) & ~bits);
|
||||
|
||||
*d++ = rest | (sym >> off);
|
||||
rest = sym << (8-off);
|
||||
#elif LCD_BPP == LCD_COLOR8
|
||||
for (c=0; c<8; ++c) {
|
||||
*d++ = (bits & 0x80) ?
|
||||
lcd_color_fg : lcd_color_bg;
|
||||
bits <<= 1;
|
||||
}
|
||||
#elif LCD_BPP == LCD_COLOR16
|
||||
for (c=0; c<16; ++c) {
|
||||
*d++ = (bits & 0x80) ?
|
||||
lcd_color_fg : lcd_color_bg;
|
||||
bits <<= 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if LCD_BPP == LCD_MONOCHROME
|
||||
*d = rest | (*d & ((1 << (8-off)) - 1));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static inline void lcd_puts_xy (ushort x, ushort y, uchar *s)
|
||||
{
|
||||
#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
|
||||
lcd_drawchars (x, y+BMP_LOGO_HEIGHT, s, strlen ((char *)s));
|
||||
#else
|
||||
lcd_drawchars (x, y, s, strlen ((char *)s));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static inline void lcd_putc_xy (ushort x, ushort y, uchar c)
|
||||
{
|
||||
#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
|
||||
lcd_drawchars (x, y+BMP_LOGO_HEIGHT, &c, 1);
|
||||
#else
|
||||
lcd_drawchars (x, y, &c, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/** Small utility to check that you got the colours right */
|
||||
/************************************************************************/
|
||||
#ifdef LCD_TEST_PATTERN
|
||||
|
||||
#define N_BLK_VERT 2
|
||||
#define N_BLK_HOR 3
|
||||
|
||||
static int test_colors[N_BLK_HOR*N_BLK_VERT] = {
|
||||
CONSOLE_COLOR_RED, CONSOLE_COLOR_GREEN, CONSOLE_COLOR_YELLOW,
|
||||
CONSOLE_COLOR_BLUE, CONSOLE_COLOR_MAGENTA, CONSOLE_COLOR_CYAN,
|
||||
};
|
||||
|
||||
static void test_pattern (void)
|
||||
{
|
||||
ushort v_max = panel_info.vl_row;
|
||||
ushort h_max = panel_info.vl_col;
|
||||
ushort v_step = (v_max + N_BLK_VERT - 1) / N_BLK_VERT;
|
||||
ushort h_step = (h_max + N_BLK_HOR - 1) / N_BLK_HOR;
|
||||
ushort v, h;
|
||||
uchar *pix = (uchar *)lcd_base;
|
||||
|
||||
printf ("[LCD] Test Pattern: %d x %d [%d x %d]\n",
|
||||
h_max, v_max, h_step, v_step);
|
||||
|
||||
/* WARNING: Code silently assumes 8bit/pixel */
|
||||
for (v=0; v<v_max; ++v) {
|
||||
uchar iy = v / v_step;
|
||||
for (h=0; h<h_max; ++h) {
|
||||
uchar ix = N_BLK_HOR * iy + (h/h_step);
|
||||
*pix++ = test_colors[ix];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LCD_TEST_PATTERN */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* ** GENERIC Initialization Routines */
|
||||
/************************************************************************/
|
||||
|
||||
int drv_lcd_init (void)
|
||||
{
|
||||
device_t lcddev;
|
||||
int rc;
|
||||
|
||||
lcd_base = (void *)(gd->fb_base);
|
||||
|
||||
lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
|
||||
|
||||
lcd_init (lcd_base); /* LCD initialization */
|
||||
|
||||
/* Device initialization */
|
||||
memset (&lcddev, 0, sizeof (lcddev));
|
||||
|
||||
strcpy (lcddev.name, "lcd");
|
||||
lcddev.ext = 0; /* No extensions */
|
||||
lcddev.flags = DEV_FLAGS_OUTPUT; /* Output only */
|
||||
lcddev.putc = lcd_putc; /* 'putc' function */
|
||||
lcddev.puts = lcd_puts; /* 'puts' function */
|
||||
|
||||
rc = device_register (&lcddev);
|
||||
|
||||
return (rc == 0) ? 1 : rc;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int lcd_clear (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
#if LCD_BPP == LCD_MONOCHROME
|
||||
/* Setting the palette */
|
||||
lcd_initcolregs();
|
||||
|
||||
#elif LCD_BPP == LCD_COLOR8
|
||||
/* Setting the palette */
|
||||
lcd_setcolreg (CONSOLE_COLOR_BLACK, 0, 0, 0);
|
||||
lcd_setcolreg (CONSOLE_COLOR_RED, 0xFF, 0, 0);
|
||||
lcd_setcolreg (CONSOLE_COLOR_GREEN, 0, 0xFF, 0);
|
||||
lcd_setcolreg (CONSOLE_COLOR_YELLOW, 0xFF, 0xFF, 0);
|
||||
lcd_setcolreg (CONSOLE_COLOR_BLUE, 0, 0, 0xFF);
|
||||
lcd_setcolreg (CONSOLE_COLOR_MAGENTA, 0xFF, 0, 0xFF);
|
||||
lcd_setcolreg (CONSOLE_COLOR_CYAN, 0, 0xFF, 0xFF);
|
||||
lcd_setcolreg (CONSOLE_COLOR_GREY, 0xAA, 0xAA, 0xAA);
|
||||
lcd_setcolreg (CONSOLE_COLOR_WHITE, 0xFF, 0xFF, 0xFF);
|
||||
#endif
|
||||
|
||||
#ifndef CFG_WHITE_ON_BLACK
|
||||
lcd_setfgcolor (CONSOLE_COLOR_BLACK);
|
||||
lcd_setbgcolor (CONSOLE_COLOR_WHITE);
|
||||
#else
|
||||
lcd_setfgcolor (CONSOLE_COLOR_WHITE);
|
||||
lcd_setbgcolor (CONSOLE_COLOR_BLACK);
|
||||
#endif /* CFG_WHITE_ON_BLACK */
|
||||
|
||||
#ifdef LCD_TEST_PATTERN
|
||||
test_pattern();
|
||||
#else
|
||||
/* set framebuffer to background color */
|
||||
memset ((char *)lcd_base,
|
||||
COLOR_MASK(lcd_getbgcolor()),
|
||||
lcd_line_length*panel_info.vl_row);
|
||||
#endif
|
||||
/* Paint the logo and retrieve LCD base address */
|
||||
debug ("[LCD] Drawing the logo...\n");
|
||||
lcd_console_address = lcd_logo ();
|
||||
|
||||
console_col = 0;
|
||||
console_row = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
cls, 1, 1, lcd_clear,
|
||||
"cls - clear screen\n",
|
||||
NULL
|
||||
);
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static int lcd_init (void *lcdbase)
|
||||
{
|
||||
/* Initialize the lcd controller */
|
||||
debug ("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
|
||||
|
||||
lcd_ctrl_init (lcdbase);
|
||||
lcd_clear (NULL, 1, 1, NULL); /* dummy args */
|
||||
lcd_enable ();
|
||||
|
||||
/* Initialize the console */
|
||||
console_col = 0;
|
||||
#ifdef CONFIG_LCD_INFO_BELOW_LOGO
|
||||
console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;
|
||||
#else
|
||||
console_row = 1; /* leave 1 blank line below logo */
|
||||
#endif
|
||||
lcd_is_enabled = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* ** ROM capable initialization part - needed to reserve FB memory */
|
||||
/************************************************************************/
|
||||
/*
|
||||
* This is called early in the system initialization to grab memory
|
||||
* for the LCD controller.
|
||||
* Returns new address for monitor, after reserving LCD buffer memory
|
||||
*
|
||||
* Note that this is running from ROM, so no write access to global data.
|
||||
*/
|
||||
ulong lcd_setmem (ulong addr)
|
||||
{
|
||||
ulong size;
|
||||
int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
|
||||
|
||||
debug ("LCD panel info: %d x %d, %d bit/pix\n",
|
||||
panel_info.vl_col, panel_info.vl_row, NBITS (panel_info.vl_bpix) );
|
||||
|
||||
size = line_length * panel_info.vl_row;
|
||||
|
||||
/* Round up to nearest full page */
|
||||
size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
|
||||
|
||||
/* Allocate pages for the frame buffer. */
|
||||
addr -= size;
|
||||
|
||||
debug ("Reserving %ldk for LCD Framebuffer at: %08lx\n", size>>10, addr);
|
||||
|
||||
return (addr);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static void lcd_setfgcolor (int color)
|
||||
{
|
||||
lcd_color_fg = color & 0x0F;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static void lcd_setbgcolor (int color)
|
||||
{
|
||||
lcd_color_bg = color & 0x0F;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifdef NOT_USED_SO_FAR
|
||||
static int lcd_getfgcolor (void)
|
||||
{
|
||||
return lcd_color_fg;
|
||||
}
|
||||
#endif /* NOT_USED_SO_FAR */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static int lcd_getbgcolor (void)
|
||||
{
|
||||
return lcd_color_bg;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/************************************************************************/
|
||||
/* ** Chipset depending Bitmap / Logo stuff... */
|
||||
/************************************************************************/
|
||||
#ifdef CONFIG_LCD_LOGO
|
||||
void bitmap_plot (int x, int y)
|
||||
{
|
||||
ushort *cmap;
|
||||
ushort i, j;
|
||||
uchar *bmap;
|
||||
uchar *fb;
|
||||
ushort *fb16;
|
||||
#if defined(CONFIG_PXA250)
|
||||
struct pxafb_info *fbi = &panel_info.pxa;
|
||||
#elif defined(CONFIG_MPC823)
|
||||
volatile immap_t *immr = (immap_t *) CFG_IMMR;
|
||||
volatile cpm8xx_t *cp = &(immr->im_cpm);
|
||||
#endif
|
||||
|
||||
debug ("Logo: width %d height %d colors %d cmap %d\n",
|
||||
BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS,
|
||||
sizeof(bmp_logo_palette)/(sizeof(ushort)));
|
||||
|
||||
bmap = &bmp_logo_bitmap[0];
|
||||
fb = (uchar *)(lcd_base + y * lcd_line_length + x);
|
||||
|
||||
if (NBITS(panel_info.vl_bpix) < 12) {
|
||||
/* Leave room for default color map */
|
||||
#if defined(CONFIG_PXA250)
|
||||
cmap = (ushort *)fbi->palette;
|
||||
#elif defined(CONFIG_MPC823)
|
||||
cmap = (ushort *)&(cp->lcd_cmap[BMP_LOGO_OFFSET*sizeof(ushort)]);
|
||||
#endif
|
||||
|
||||
WATCHDOG_RESET();
|
||||
|
||||
/* Set color map */
|
||||
for (i=0; i<(sizeof(bmp_logo_palette)/(sizeof(ushort))); ++i) {
|
||||
ushort colreg = bmp_logo_palette[i];
|
||||
#ifdef CFG_INVERT_COLORS
|
||||
*cmap++ = 0xffff - colreg;
|
||||
#else
|
||||
*cmap++ = colreg;
|
||||
#endif
|
||||
}
|
||||
|
||||
WATCHDOG_RESET();
|
||||
|
||||
for (i=0; i<BMP_LOGO_HEIGHT; ++i) {
|
||||
memcpy (fb, bmap, BMP_LOGO_WIDTH);
|
||||
bmap += BMP_LOGO_WIDTH;
|
||||
fb += panel_info.vl_col;
|
||||
}
|
||||
}
|
||||
else { /* true color mode */
|
||||
fb16 = (ushort *)(lcd_base + y * lcd_line_length + x);
|
||||
for (i=0; i<BMP_LOGO_HEIGHT; ++i) {
|
||||
for (j=0; j<BMP_LOGO_WIDTH; j++) {
|
||||
fb16[j] = bmp_logo_palette[(bmap[j])];
|
||||
}
|
||||
bmap += BMP_LOGO_WIDTH;
|
||||
fb16 += panel_info.vl_col;
|
||||
}
|
||||
}
|
||||
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
#endif /* CONFIG_LCD_LOGO */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
#if (CONFIG_COMMANDS & CFG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
|
||||
/*
|
||||
* Display the BMP file located at address bmp_image.
|
||||
* Only uncompressed.
|
||||
*/
|
||||
int lcd_display_bitmap(ulong bmp_image, int x, int y)
|
||||
{
|
||||
ushort *cmap;
|
||||
ushort i, j;
|
||||
uchar *fb;
|
||||
bmp_image_t *bmp=(bmp_image_t *)bmp_image;
|
||||
uchar *bmap;
|
||||
ushort padded_line;
|
||||
unsigned long width, height;
|
||||
unsigned colors,bpix;
|
||||
unsigned long compression;
|
||||
#if defined(CONFIG_PXA250)
|
||||
struct pxafb_info *fbi = &panel_info.pxa;
|
||||
#elif defined(CONFIG_MPC823)
|
||||
volatile immap_t *immr = (immap_t *) CFG_IMMR;
|
||||
volatile cpm8xx_t *cp = &(immr->im_cpm);
|
||||
#endif
|
||||
|
||||
if (!((bmp->header.signature[0]=='B') &&
|
||||
(bmp->header.signature[1]=='M'))) {
|
||||
printf ("Error: no valid bmp image at %lx\n", bmp_image);
|
||||
return 1;
|
||||
}
|
||||
|
||||
width = le32_to_cpu (bmp->header.width);
|
||||
height = le32_to_cpu (bmp->header.height);
|
||||
colors = 1<<le16_to_cpu (bmp->header.bit_count);
|
||||
compression = le32_to_cpu (bmp->header.compression);
|
||||
|
||||
bpix = NBITS(panel_info.vl_bpix);
|
||||
|
||||
if ((bpix != 1) && (bpix != 8)) {
|
||||
printf ("Error: %d bit/pixel mode not supported by U-Boot\n",
|
||||
bpix);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bpix != le16_to_cpu(bmp->header.bit_count)) {
|
||||
printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
|
||||
bpix,
|
||||
le16_to_cpu(bmp->header.bit_count));
|
||||
return 1;
|
||||
}
|
||||
|
||||
debug ("Display-bmp: %d x %d with %d colors\n",
|
||||
(int)width, (int)height, (int)colors);
|
||||
|
||||
if (bpix==8) {
|
||||
#if defined(CONFIG_PXA250)
|
||||
cmap = (ushort *)fbi->palette;
|
||||
#elif defined(CONFIG_MPC823)
|
||||
cmap = (ushort *)&(cp->lcd_cmap[255*sizeof(ushort)]);
|
||||
#else
|
||||
# error "Don't know location of color map"
|
||||
#endif
|
||||
|
||||
/* Set color map */
|
||||
for (i=0; i<colors; ++i) {
|
||||
bmp_color_table_entry_t cte = bmp->color_table[i];
|
||||
ushort colreg =
|
||||
( ((cte.red) << 8) & 0xf800) |
|
||||
( ((cte.green) << 3) & 0x07e0) |
|
||||
( ((cte.blue) >> 3) & 0x001f) ;
|
||||
#ifdef CFG_INVERT_COLORS
|
||||
*cmap = 0xffff - colreg;
|
||||
#else
|
||||
*cmap = colreg;
|
||||
#endif
|
||||
#if defined(CONFIG_PXA250)
|
||||
cmap++;
|
||||
#elif defined(CONFIG_MPC823)
|
||||
cmap--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
padded_line = (width&0x3) ? ((width&~0x3)+4) : (width);
|
||||
if ((x + width)>panel_info.vl_col)
|
||||
width = panel_info.vl_col - x;
|
||||
if ((y + height)>panel_info.vl_row)
|
||||
height = panel_info.vl_row - y;
|
||||
|
||||
bmap = (uchar *)bmp + le32_to_cpu (bmp->header.data_offset);
|
||||
fb = (uchar *) (lcd_base +
|
||||
(y + height - 1) * lcd_line_length + x);
|
||||
for (i = 0; i < height; ++i) {
|
||||
WATCHDOG_RESET();
|
||||
for (j = 0; j < width ; j++)
|
||||
#if defined(CONFIG_PXA250)
|
||||
*(fb++)=*(bmap++);
|
||||
#elif defined(CONFIG_MPC823)
|
||||
*(fb++)=255-*(bmap++);
|
||||
#endif
|
||||
bmap += (width - padded_line);
|
||||
fb -= (width + lcd_line_length);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif /* (CONFIG_COMMANDS & CFG_CMD_BMP) || CONFIG_SPLASH_SCREEN */
|
||||
|
||||
|
||||
static void *lcd_logo (void)
|
||||
{
|
||||
#ifdef CONFIG_LCD_INFO
|
||||
char info[80];
|
||||
char temp[32];
|
||||
#endif /* CONFIG_LCD_INFO */
|
||||
|
||||
#ifdef CONFIG_SPLASH_SCREEN
|
||||
char *s;
|
||||
ulong addr;
|
||||
static int do_splash = 1;
|
||||
|
||||
if (do_splash && (s = getenv("splashimage")) != NULL) {
|
||||
addr = simple_strtoul(s, NULL, 16);
|
||||
do_splash = 0;
|
||||
|
||||
if (lcd_display_bitmap (addr, 0, 0) == 0) {
|
||||
return ((void *)lcd_base);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SPLASH_SCREEN */
|
||||
|
||||
#ifdef CONFIG_LCD_LOGO
|
||||
bitmap_plot (0, 0);
|
||||
#endif /* CONFIG_LCD_LOGO */
|
||||
|
||||
#ifdef CONFIG_MPC823
|
||||
# ifdef CONFIG_LCD_INFO
|
||||
sprintf (info, "%s (%s - %s) ", U_BOOT_VERSION, __DATE__, __TIME__);
|
||||
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y, (uchar *)info, strlen(info));
|
||||
|
||||
sprintf (info, "(C) 2004 DENX Software Engineering");
|
||||
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT,
|
||||
(uchar *)info, strlen(info));
|
||||
|
||||
sprintf (info, " Wolfgang DENK, wd@denx.de");
|
||||
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 2,
|
||||
(uchar *)info, strlen(info));
|
||||
# ifdef CONFIG_LCD_INFO_BELOW_LOGO
|
||||
sprintf (info, "MPC823 CPU at %s MHz",
|
||||
strmhz(temp, gd->cpu_clk));
|
||||
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 3,
|
||||
info, strlen(info));
|
||||
sprintf (info, " %ld MB RAM, %ld MB Flash",
|
||||
gd->ram_size >> 20,
|
||||
gd->bd->bi_flashsize >> 20 );
|
||||
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
|
||||
info, strlen(info));
|
||||
# else
|
||||
/* leave one blank line */
|
||||
|
||||
sprintf (info, "MPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash",
|
||||
strmhz(temp, gd->cpu_clk),
|
||||
gd->ram_size >> 20,
|
||||
gd->bd->bi_flashsize >> 20 );
|
||||
lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4,
|
||||
(uchar *)info, strlen(info));
|
||||
|
||||
# endif /* CONFIG_LCD_INFO_BELOW_LOGO */
|
||||
# endif /* CONFIG_LCD_INFO */
|
||||
#endif /* CONFIG_MPC823 */
|
||||
|
||||
#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
|
||||
return ((void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length));
|
||||
#else
|
||||
return ((void *)lcd_base);
|
||||
#endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
#endif /* CONFIG_LCD */
|
|
@ -0,0 +1,734 @@
|
|||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <lists.h>
|
||||
|
||||
#define MAX(a,b) (((a)>(b)) ? (a) : (b))
|
||||
#define MIN(a,b) (((a)<(b)) ? (a) : (b))
|
||||
#define CAT4CHARS(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d)
|
||||
|
||||
/* increase list size by 10% every time it is full */
|
||||
#define kDefaultAllocationPercentIncrease 10
|
||||
|
||||
/* always increase list size by 4 items when it is full */
|
||||
#define kDefaultAllocationminNumItemsIncrease 4
|
||||
|
||||
/*
|
||||
* how many items to expand the list by when it becomes full
|
||||
* = current listSize (in items) + (hiword percent of list size) + loword
|
||||
*/
|
||||
#define NUMITEMSPERALLOC(list) MAX(((*list)->listSize * \
|
||||
((*list)->percentIncrease + 100)) / 100, \
|
||||
(*list)->minNumItemsIncrease )
|
||||
|
||||
#define ITEMPTR(list,item) &(((char *)&(*list)->itemList)[(*(list))->itemSize * (item)])
|
||||
|
||||
#define LIST_SIGNATURE CAT4CHARS('L', 'I', 'S', 'T');
|
||||
|
||||
#define calloc(size,num) malloc(size*num)
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
Handle NewHandle (unsigned int numBytes)
|
||||
{
|
||||
void *memPtr;
|
||||
HandleRecord *hanPtr;
|
||||
|
||||
memPtr = calloc (numBytes, 1);
|
||||
hanPtr = (HandleRecord *) calloc (sizeof (HandleRecord), 1);
|
||||
if (hanPtr && (memPtr || numBytes == 0)) {
|
||||
hanPtr->ptr = memPtr;
|
||||
hanPtr->size = numBytes;
|
||||
return (Handle) hanPtr;
|
||||
} else {
|
||||
free (memPtr);
|
||||
free (hanPtr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
void DisposeHandle (Handle handle)
|
||||
{
|
||||
if (handle) {
|
||||
free (*handle);
|
||||
free ((void *) handle);
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
unsigned int GetHandleSize (Handle handle)
|
||||
{
|
||||
return ((HandleRecord *) handle)->size;
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
int SetHandleSize (Handle handle, unsigned int newSize)
|
||||
{
|
||||
HandleRecord *hanRecPtr = (HandleRecord *) handle;
|
||||
void *newPtr, *oldPtr;
|
||||
unsigned int oldSize;
|
||||
|
||||
|
||||
oldPtr = hanRecPtr->ptr;
|
||||
oldSize = hanRecPtr->size;
|
||||
|
||||
if (oldSize == newSize)
|
||||
return 1;
|
||||
|
||||
if (oldPtr == NULL) {
|
||||
newPtr = malloc (newSize);
|
||||
} else {
|
||||
newPtr = realloc (oldPtr, newSize);
|
||||
}
|
||||
if (newPtr || (newSize == 0)) {
|
||||
hanRecPtr->ptr = newPtr;
|
||||
hanRecPtr->size = newSize;
|
||||
if (newSize > oldSize)
|
||||
memset ((char *) newPtr + oldSize, 0, newSize - oldSize);
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CFG_ALL_LIST_FUNCTIONS
|
||||
|
||||
/* Used to compare list elements by their raw data contents */
|
||||
static int ListMemBlockCmp (void *a, void *b, int size)
|
||||
{
|
||||
return memcmp (a, b, size);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* Binary search numElements of size elementSize in array for a match
|
||||
* to the. item. Return the index of the element that matches
|
||||
* (0 - numElements - 1). If no match is found return the -i-1 where
|
||||
* i is the index (0 - numElements) where the item should be placed.
|
||||
* (*theCmp)(a,b) should return <0 if a<b, 0 if a==b, >0 if a>b.
|
||||
*
|
||||
* This function is like the C-Library function bsearch() except that
|
||||
* this function returns the index where the item should be placed if
|
||||
* it is not found.
|
||||
*/
|
||||
int BinSearch ( void *array, int numElements, int elementSize,
|
||||
void *itemPtr, CompareFunction compareFunction)
|
||||
{
|
||||
int low, high, mid, cmp;
|
||||
void *arrayItemPtr;
|
||||
|
||||
for (low = 0, high = numElements - 1, mid = 0, cmp = -1; low <= high;) {
|
||||
mid = (low + high) >> 1;
|
||||
|
||||
arrayItemPtr = (void *) (((char *) array) + (mid * elementSize));
|
||||
cmp = compareFunction
|
||||
? compareFunction (itemPtr, arrayItemPtr)
|
||||
: ListMemBlockCmp (itemPtr, arrayItemPtr, elementSize);
|
||||
if (cmp == 0) {
|
||||
return mid;
|
||||
} else if (cmp < 0) {
|
||||
high = mid - 1;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
if (cmp > 0)
|
||||
mid++;
|
||||
|
||||
return -mid - 1;
|
||||
}
|
||||
|
||||
#endif /* CFG_ALL_LIST_FUNCTIONS */
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
/*
|
||||
* If numNewItems == 0 then expand the list by the number of items
|
||||
* indicated by its allocation policy.
|
||||
* If numNewItems > 0 then expand the list by exactly the number of
|
||||
* items indicated.
|
||||
* If numNewItems < 0 then expand the list by the absolute value of
|
||||
* numNewItems plus the number of items indicated by its allocation
|
||||
* policy.
|
||||
* Returns 1 for success, 0 if out of memory
|
||||
*/
|
||||
static int ExpandListSpace (list_t list, int numNewItems)
|
||||
{
|
||||
if (numNewItems == 0) {
|
||||
numNewItems = NUMITEMSPERALLOC (list);
|
||||
} else if (numNewItems < 0) {
|
||||
numNewItems = (-numNewItems) + NUMITEMSPERALLOC (list);
|
||||
}
|
||||
|
||||
if (SetHandleSize ((Handle) list,
|
||||
sizeof (ListStruct) +
|
||||
((*list)->listSize +
|
||||
numNewItems) * (*list)->itemSize)) {
|
||||
(*list)->listSize += numNewItems;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
#ifdef CFG_ALL_LIST_FUNCTIONS
|
||||
|
||||
/*
|
||||
* This function reallocate the list, minus any currently unused
|
||||
* portion of its allotted memory.
|
||||
*/
|
||||
void ListCompact (list_t list)
|
||||
{
|
||||
|
||||
if (!SetHandleSize ((Handle) list,
|
||||
sizeof (ListStruct) +
|
||||
(*list)->numItems * (*list)->itemSize)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*list)->listSize = (*list)->numItems;
|
||||
}
|
||||
|
||||
#endif /* CFG_ALL_LIST_FUNCTIONS */
|
||||
|
||||
/*******************************/
|
||||
|
||||
list_t ListCreate (int elementSize)
|
||||
{
|
||||
list_t list;
|
||||
|
||||
list = (list_t) (NewHandle (sizeof (ListStruct))); /* create empty list */
|
||||
if (list) {
|
||||
(*list)->signature = LIST_SIGNATURE;
|
||||
(*list)->numItems = 0;
|
||||
(*list)->listSize = 0;
|
||||
(*list)->itemSize = elementSize;
|
||||
(*list)->percentIncrease = kDefaultAllocationPercentIncrease;
|
||||
(*list)->minNumItemsIncrease =
|
||||
kDefaultAllocationminNumItemsIncrease;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
void ListSetAllocationPolicy (list_t list, int minItemsPerAlloc,
|
||||
int percentIncreasePerAlloc)
|
||||
{
|
||||
(*list)->percentIncrease = percentIncreasePerAlloc;
|
||||
(*list)->minNumItemsIncrease = minItemsPerAlloc;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
void ListDispose (list_t list)
|
||||
{
|
||||
DisposeHandle ((Handle) list);
|
||||
}
|
||||
/*******************************/
|
||||
|
||||
#ifdef CFG_ALL_LIST_FUNCTIONS
|
||||
|
||||
void ListDisposePtrList (list_t list)
|
||||
{
|
||||
int index;
|
||||
int numItems;
|
||||
|
||||
if (list) {
|
||||
numItems = ListNumItems (list);
|
||||
|
||||
for (index = 1; index <= numItems; index++)
|
||||
free (*(void **) ListGetPtrToItem (list, index));
|
||||
|
||||
ListDispose (list);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
/*
|
||||
* keeps memory, resets the number of items to 0
|
||||
*/
|
||||
void ListClear (list_t list)
|
||||
{
|
||||
if (!list)
|
||||
return;
|
||||
(*list)->numItems = 0;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
/*
|
||||
* copy is only as large as necessary
|
||||
*/
|
||||
list_t ListCopy (list_t originalList)
|
||||
{
|
||||
list_t tempList = NULL;
|
||||
int numItems;
|
||||
|
||||
if (!originalList)
|
||||
return NULL;
|
||||
|
||||
tempList = ListCreate ((*originalList)->itemSize);
|
||||
if (tempList) {
|
||||
numItems = ListNumItems (originalList);
|
||||
|
||||
if (!SetHandleSize ((Handle) tempList,
|
||||
sizeof (ListStruct) +
|
||||
numItems * (*tempList)->itemSize)) {
|
||||
ListDispose (tempList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*tempList)->numItems = (*originalList)->numItems;
|
||||
(*tempList)->listSize = (*originalList)->numItems;
|
||||
(*tempList)->itemSize = (*originalList)->itemSize;
|
||||
(*tempList)->percentIncrease = (*originalList)->percentIncrease;
|
||||
(*tempList)->minNumItemsIncrease =
|
||||
(*originalList)->minNumItemsIncrease;
|
||||
|
||||
memcpy (ITEMPTR (tempList, 0), ITEMPTR (originalList, 0),
|
||||
numItems * (*tempList)->itemSize);
|
||||
}
|
||||
|
||||
return tempList;
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
||||
/*
|
||||
* list1 = list1 + list2
|
||||
*/
|
||||
int ListAppend (list_t list1, list_t list2)
|
||||
{
|
||||
int numItemsL1, numItemsL2;
|
||||
|
||||
if (!list2)
|
||||
return 1;
|
||||
|
||||
if (!list1)
|
||||
return 0;
|
||||
if ((*list1)->itemSize != (*list2)->itemSize)
|
||||
return 0;
|
||||
|
||||
numItemsL1 = ListNumItems (list1);
|
||||
numItemsL2 = ListNumItems (list2);
|
||||
|
||||
if (numItemsL2 == 0)
|
||||
return 1;
|
||||
|
||||
if (!SetHandleSize ((Handle) list1,
|
||||
sizeof (ListStruct) + (numItemsL1 + numItemsL2) *
|
||||
(*list1)->itemSize)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*list1)->numItems = numItemsL1 + numItemsL2;
|
||||
(*list1)->listSize = numItemsL1 + numItemsL2;
|
||||
|
||||
memmove (ITEMPTR (list1, numItemsL1),
|
||||
ITEMPTR (list2, 0),
|
||||
numItemsL2 * (*list2)->itemSize);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* CFG_ALL_LIST_FUNCTIONS */
|
||||
|
||||
/*******************************/
|
||||
|
||||
/*
|
||||
* returns 1 if the item is inserted, returns 0 if out of memory or
|
||||
* bad arguments were passed.
|
||||
*/
|
||||
int ListInsertItem (list_t list, void *ptrToItem, int itemPosition)
|
||||
{
|
||||
return ListInsertItems (list, ptrToItem, itemPosition, 1);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
int ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition,
|
||||
int numItemsToInsert)
|
||||
{
|
||||
int numItems = (*list)->numItems;
|
||||
|
||||
if (firstItemPosition == numItems + 1)
|
||||
firstItemPosition = LIST_END;
|
||||
else if (firstItemPosition > numItems)
|
||||
return 0;
|
||||
|
||||
if ((*list)->numItems >= (*list)->listSize) {
|
||||
if (!ExpandListSpace (list, -numItemsToInsert))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (firstItemPosition == LIST_START) {
|
||||
if (numItems == 0) {
|
||||
/* special case for empty list */
|
||||
firstItemPosition = LIST_END;
|
||||
} else {
|
||||
firstItemPosition = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstItemPosition == LIST_END) { /* add at the end of the list */
|
||||
if (ptrToItems)
|
||||
memcpy (ITEMPTR (list, numItems), ptrToItems,
|
||||
(*list)->itemSize * numItemsToInsert);
|
||||
else
|
||||
memset (ITEMPTR (list, numItems), 0,
|
||||
(*list)->itemSize * numItemsToInsert);
|
||||
|
||||
(*list)->numItems += numItemsToInsert;
|
||||
} else { /* move part of list up to make room for new item */
|
||||
memmove (ITEMPTR (list, firstItemPosition - 1 + numItemsToInsert),
|
||||
ITEMPTR (list, firstItemPosition - 1),
|
||||
(numItems + 1 - firstItemPosition) * (*list)->itemSize);
|
||||
|
||||
if (ptrToItems)
|
||||
memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
|
||||
(*list)->itemSize * numItemsToInsert);
|
||||
else
|
||||
memset (ITEMPTR (list, firstItemPosition - 1), 0,
|
||||
(*list)->itemSize * numItemsToInsert);
|
||||
|
||||
(*list)->numItems += numItemsToInsert;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CFG_ALL_LIST_FUNCTIONS
|
||||
|
||||
/*******************************/
|
||||
|
||||
int ListEqual (list_t list1, list_t list2)
|
||||
{
|
||||
if (list1 == list2)
|
||||
return 1;
|
||||
|
||||
if (list1 == NULL || list2 == NULL)
|
||||
return 0;
|
||||
|
||||
if ((*list1)->itemSize == (*list1)->itemSize) {
|
||||
if ((*list1)->numItems == (*list2)->numItems) {
|
||||
return (memcmp (ITEMPTR (list1, 0), ITEMPTR (list2, 0),
|
||||
(*list1)->itemSize * (*list1)->numItems) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
/*
|
||||
* The item pointed to by ptrToItem is copied over the current item
|
||||
* at itemPosition
|
||||
*/
|
||||
void ListReplaceItem (list_t list, void *ptrToItem, int itemPosition)
|
||||
{
|
||||
ListReplaceItems (list, ptrToItem, itemPosition, 1);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
/*
|
||||
* The item pointed to by ptrToItems is copied over the current item
|
||||
* at itemPosition
|
||||
*/
|
||||
void ListReplaceItems ( list_t list, void *ptrToItems,
|
||||
int firstItemPosition, int numItemsToReplace)
|
||||
{
|
||||
|
||||
if (firstItemPosition == LIST_END)
|
||||
firstItemPosition = (*list)->numItems;
|
||||
else if (firstItemPosition == LIST_START)
|
||||
firstItemPosition = 1;
|
||||
|
||||
memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
|
||||
(*list)->itemSize * numItemsToReplace);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
void ListGetItem (list_t list, void *itemDestination, int itemPosition)
|
||||
{
|
||||
ListGetItems (list, itemDestination, itemPosition, 1);
|
||||
}
|
||||
|
||||
#endif /* CFG_ALL_LIST_FUNCTIONS */
|
||||
|
||||
/*******************************/
|
||||
|
||||
#if defined(CFG_ALL_LIST_FUNCTIONS) || defined(CFG_DEVICE_DEREGISTER)
|
||||
|
||||
void ListRemoveItem (list_t list, void *itemDestination, int itemPosition)
|
||||
{
|
||||
ListRemoveItems (list, itemDestination, itemPosition, 1);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
void ListRemoveItems (list_t list, void *itemsDestination,
|
||||
int firstItemPosition, int numItemsToRemove)
|
||||
{
|
||||
int firstItemAfterChunk, numToMove;
|
||||
|
||||
if (firstItemPosition == LIST_START)
|
||||
firstItemPosition = 1;
|
||||
else if (firstItemPosition == LIST_END)
|
||||
firstItemPosition = (*list)->numItems;
|
||||
|
||||
if (itemsDestination != NULL)
|
||||
memcpy (itemsDestination, ITEMPTR (list, firstItemPosition - 1),
|
||||
(*list)->itemSize * numItemsToRemove);
|
||||
|
||||
firstItemAfterChunk = firstItemPosition + numItemsToRemove;
|
||||
numToMove = (*list)->numItems - (firstItemAfterChunk - 1);
|
||||
|
||||
if (numToMove > 0) {
|
||||
/*
|
||||
* move part of list down to cover hole left by removed item
|
||||
*/
|
||||
memmove (ITEMPTR (list, firstItemPosition - 1),
|
||||
ITEMPTR (list, firstItemAfterChunk - 1),
|
||||
(*list)->itemSize * numToMove);
|
||||
}
|
||||
|
||||
(*list)->numItems -= numItemsToRemove;
|
||||
}
|
||||
#endif /* CFG_ALL_LIST_FUNCTIONS || CFG_DEVICE_DEREGISTER */
|
||||
|
||||
/*******************************/
|
||||
|
||||
void ListGetItems (list_t list, void *itemsDestination,
|
||||
int firstItemPosition, int numItemsToGet)
|
||||
{
|
||||
|
||||
if (firstItemPosition == LIST_START)
|
||||
firstItemPosition = 1;
|
||||
else if (firstItemPosition == LIST_END)
|
||||
firstItemPosition = (*list)->numItems;
|
||||
|
||||
memcpy (itemsDestination,
|
||||
ITEMPTR (list, firstItemPosition - 1),
|
||||
(*list)->itemSize * numItemsToGet);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
/*
|
||||
* Returns a pointer to the item at itemPosition. returns null if an
|
||||
* errors occurred.
|
||||
*/
|
||||
void *ListGetPtrToItem (list_t list, int itemPosition)
|
||||
{
|
||||
if (itemPosition == LIST_START)
|
||||
itemPosition = 1;
|
||||
else if (itemPosition == LIST_END)
|
||||
itemPosition = (*list)->numItems;
|
||||
|
||||
return ITEMPTR (list, itemPosition - 1);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
/*
|
||||
* returns a pointer the lists data (abstraction violation for
|
||||
* optimization)
|
||||
*/
|
||||
void *ListGetDataPtr (list_t list)
|
||||
{
|
||||
return &((*list)->itemList[0]);
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
||||
#ifdef CFG_ALL_LIST_FUNCTIONS
|
||||
|
||||
int ListApplyToEach (list_t list, int ascending,
|
||||
ListApplicationFunc funcToApply,
|
||||
void *callbackData)
|
||||
{
|
||||
int result = 0, index;
|
||||
|
||||
if (!list || !funcToApply)
|
||||
goto Error;
|
||||
|
||||
if (ascending) {
|
||||
for (index = 1; index <= ListNumItems (list); index++) {
|
||||
result = funcToApply (index,
|
||||
ListGetPtrToItem (list, index),
|
||||
callbackData);
|
||||
if (result < 0)
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
for (index = ListNumItems (list);
|
||||
index > 0 && index <= ListNumItems (list);
|
||||
index--) {
|
||||
result = funcToApply (index,
|
||||
ListGetPtrToItem (list, index),
|
||||
callbackData);
|
||||
if (result < 0)
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
Error:
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* CFG_ALL_LIST_FUNCTIONS */
|
||||
|
||||
/********************************/
|
||||
|
||||
int ListGetItemSize (list_t list)
|
||||
{
|
||||
return (*list)->itemSize;
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
||||
int ListNumItems (list_t list)
|
||||
{
|
||||
return (*list)->numItems;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
#ifdef CFG_ALL_LIST_FUNCTIONS
|
||||
|
||||
void ListRemoveDuplicates (list_t list, CompareFunction compareFunction)
|
||||
{
|
||||
int numItems, index, startIndexForFind, duplicatesIndex;
|
||||
|
||||
numItems = ListNumItems (list);
|
||||
|
||||
for (index = 1; index < numItems; index++) {
|
||||
startIndexForFind = index + 1;
|
||||
while (startIndexForFind <= numItems) {
|
||||
duplicatesIndex =
|
||||
ListFindItem (list,
|
||||
ListGetPtrToItem (list, index),
|
||||
startIndexForFind,
|
||||
compareFunction);
|
||||
if (duplicatesIndex > 0) {
|
||||
ListRemoveItem (list, NULL, duplicatesIndex);
|
||||
numItems--;
|
||||
startIndexForFind = duplicatesIndex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
|
||||
/*******************************/
|
||||
|
||||
int ListFindItem (list_t list, void *ptrToItem, int startingPosition,
|
||||
CompareFunction compareFunction)
|
||||
{
|
||||
int numItems, size, index, cmp;
|
||||
void *listItemPtr;
|
||||
|
||||
if ((numItems = (*list)->numItems) == 0)
|
||||
return 0;
|
||||
|
||||
size = (*list)->itemSize;
|
||||
|
||||
if (startingPosition == LIST_START)
|
||||
startingPosition = 1;
|
||||
else if (startingPosition == LIST_END)
|
||||
startingPosition = numItems;
|
||||
|
||||
for (index = startingPosition; index <= numItems; index++) {
|
||||
listItemPtr = ITEMPTR (list, index - 1);
|
||||
cmp = compareFunction
|
||||
? compareFunction (ptrToItem, listItemPtr)
|
||||
: ListMemBlockCmp (ptrToItem, listItemPtr, size);
|
||||
if (cmp == 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
int ShortCompare (void *a, void *b)
|
||||
{
|
||||
if (*(short *) a < *(short *) b)
|
||||
return -1;
|
||||
if (*(short *) a > *(short *) b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
int IntCompare (void *a, void *b)
|
||||
{
|
||||
if (*(int *) a < *(int *) b)
|
||||
return -1;
|
||||
if (*(int *) a > *(int *) b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
int CStringCompare (void *a, void *b)
|
||||
{
|
||||
return strcmp (*(char **) a, *(char **) b);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
|
||||
|
||||
int ListBinSearch (list_t list, void *ptrToItem,
|
||||
CompareFunction compareFunction)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = BinSearch (ITEMPTR (list, 0),
|
||||
(int) (*list)->numItems,
|
||||
(int) (*list)->itemSize, ptrToItem,
|
||||
compareFunction);
|
||||
|
||||
if (index >= 0)
|
||||
index++; /* lists start from 1 */
|
||||
else
|
||||
index = 0; /* item not found */
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
* Reserves memory for numItems in the list. If it succeeds then
|
||||
* numItems items can be inserted without possibility of an out of
|
||||
* memory error (useful to simplify error recovery in complex
|
||||
* functions). Returns 1 if success, 0 if out of memory.
|
||||
*/
|
||||
int ListPreAllocate (list_t list, int numItems)
|
||||
{
|
||||
if ((*list)->listSize - (*list)->numItems < numItems) {
|
||||
return ExpandListSpace (list,
|
||||
numItems - ((*list)->listSize -
|
||||
(*list)->numItems));
|
||||
} else {
|
||||
return 1; /* enough items are already pre-allocated */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CFG_ALL_LIST_FUNCTIONS */
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) Orbacom Systems, Inc <www.orbacom.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are freely
|
||||
* permitted provided that the above copyright notice and this
|
||||
* paragraph and the following disclaimer are duplicated in all
|
||||
* such forms.
|
||||
*
|
||||
* This software is provided "AS IS" and without any express or
|
||||
* implied warranties, including, without limitation, the implied
|
||||
* warranties of merchantability and fitness for a particular
|
||||
* purpose.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/processor.h>
|
||||
#include <image.h>
|
||||
|
||||
#if defined(CONFIG_LYNXKDI)
|
||||
#include <lynxkdi.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#if defined(CONFIG_MPC8260) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
|
||||
void lynxkdi_boot ( image_header_t *hdr )
|
||||
{
|
||||
void (*lynxkdi)(void) = (void(*)(void)) ntohl(hdr->ih_ep);
|
||||
lynxos_bootparms_t *parms = (lynxos_bootparms_t *)0x0020;
|
||||
bd_t *kbd;
|
||||
u32 *psz = (u32 *)(ntohl(hdr->ih_load) + 0x0204);
|
||||
|
||||
memset( parms, 0, sizeof(*parms));
|
||||
kbd = gd->bd;
|
||||
parms->clock_ref = kbd->bi_busfreq;
|
||||
parms->dramsz = kbd->bi_memsize;
|
||||
memcpy(parms->ethaddr, kbd->bi_enetaddr, 6);
|
||||
mtspr(SPRN_SPRG2, 0x0020);
|
||||
|
||||
/* Do a simple check for Bluecat so we can pass the
|
||||
* kernel command line parameters.
|
||||
*/
|
||||
if( le32_to_cpu(*psz) == ntohl(hdr->ih_size) ){ /* FIXME: NOT SURE HERE ! */
|
||||
char *args;
|
||||
char *cmdline = (char *)(ntohl(hdr->ih_load) + 0x020c);
|
||||
int len;
|
||||
|
||||
printf("Booting Bluecat KDI ...\n");
|
||||
udelay(200*1000); /* Allow serial port to flush */
|
||||
if ((args = getenv("bootargs")) == NULL)
|
||||
args = "";
|
||||
/* Prepend the cmdline */
|
||||
len = strlen(args);
|
||||
if( len && (len + strlen(cmdline) + 2 < (0x0400 - 0x020c))) {
|
||||
memmove( cmdline + strlen(args) + 1, cmdline, strlen(cmdline) );
|
||||
strcpy( cmdline, args );
|
||||
cmdline[len] = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Booting LynxOS KDI ...\n");
|
||||
}
|
||||
|
||||
lynxkdi();
|
||||
}
|
||||
#else
|
||||
#error "Lynx KDI support not implemented for configured CPU"
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_LYNXKDI */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* (C) Copyright 2004
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Check memory range for valid RAM. A simple memory test determines
|
||||
* the actually available RAM size between addresses `base' and
|
||||
* `base + maxsize'.
|
||||
*/
|
||||
long get_ram_size(volatile long *base, long maxsize)
|
||||
{
|
||||
volatile long *addr;
|
||||
long save[32];
|
||||
long cnt;
|
||||
long val;
|
||||
long size;
|
||||
int i = 0;
|
||||
|
||||
for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) {
|
||||
addr = base + cnt; /* pointer arith! */
|
||||
save[i++] = *addr;
|
||||
*addr = ~cnt;
|
||||
}
|
||||
|
||||
addr = base;
|
||||
save[i] = *addr;
|
||||
*addr = 0;
|
||||
|
||||
if ((val = *addr) != 0) {
|
||||
/* Restore the original data before leaving the function.
|
||||
*/
|
||||
*addr = save[i];
|
||||
for (cnt = 1; cnt < maxsize / sizeof(long); cnt <<= 1) {
|
||||
addr = base + cnt;
|
||||
*addr = save[--i];
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
|
||||
addr = base + cnt; /* pointer arith! */
|
||||
val = *addr;
|
||||
*addr = save[--i];
|
||||
if (val != ~cnt) {
|
||||
size = cnt * sizeof (long);
|
||||
/* Restore the original data before leaving the function.
|
||||
*/
|
||||
for (cnt <<= 1; cnt < maxsize / sizeof (long); cnt <<= 1) {
|
||||
addr = base + cnt;
|
||||
*addr = save[--i];
|
||||
}
|
||||
return (size);
|
||||
}
|
||||
}
|
||||
|
||||
return (maxsize);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue