1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2025-04-21 12:27:27 +03:00

renamed 'xburst-tools' utility back to 'usbboot'

This commit is contained in:
Wolfgang Spraul
2009-06-30 13:49:11 +08:00
parent aa534592e2
commit 6d4212b643
61 changed files with 55 additions and 50 deletions

11
usbboot/.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
Makefile
Makefile.in
aclocal.m4
config.h
config.h.in
config.log
config.status
configure
stamp-h1
m4
autom4te.cache

674
usbboot/COPYING Normal file
View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 3 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, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

4
usbboot/ChangeLog Normal file
View File

@@ -0,0 +1,4 @@
* xburst-tools ChangeLog
25Jun2009 [WS] some cleanup in directory structure and build system

2
usbboot/Makefile.am Normal file
View File

@@ -0,0 +1,2 @@
SUBDIRS = src
EXTRA_DIST = autogen.sh

41
usbboot/README Normal file
View File

@@ -0,0 +1,41 @@
*
* usbboot
*
* Utility to respond to the Ingenic XBurst USB boot protocol, provide
* initial boot stages and ability to access NAND on device.
*
Authors: Ingenic Semiconductor, Inc.
Xiangfu Liu <xiangfu.z@gmail.com>
Marek Lindner <lindner_marek@yahoo.de>
Wolfgang Spraul <wolfgang@qi-hardware.com>
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
3 of the License, or (at your option) any later version.
usbboot is the Linux version and rewrite of a Windows utility from Ingenic also called usbboot.
Homepage: http://www.ingenic.cn/eng/productServ/kfyd/compiler/pffaqContents.aspx#questionAnchor8
Windows Binary: ftp://ftp.ingenic.cn/3sw/00tools/usb_boot/tools/usbboot1.4b-tools.zip
Windows Sources: ftp://ftp.ingenic.cn/3sw/00tools/usb_boot/tools/usbboot1.4b-sources.zip
Manual: ftp://ftp.ingenic.cn/3sw/00tools/usb_boot/manual/USB_Boot_Tool_Manual_1.4_EN.pdf
Build Requirements: libusb-dev, libconfuse-dev
Build and Installation:
./autogen.sh
./configure
make
make install
*) make install will install the 'usbboot' binary to /usr/bin/usbboot
and the stage 1 and 2 bootloaders as well as usbboot.cfg configuration
file into /usr/share/xburst-tools
Configuration file: /usr/share/xburst-tools/usbboot.cfg
Examples:
sudo usbboot (invoking usbboot without options will let you enter commands at the usbboot prompt)
sudo usbboot -c "boot"
sudo usbboot -c "nprog 0 u-boot-nand.bin 0 0 -n"
sudo usbboot -c "nprog 2048 uImage 0 0 -n"

3
usbboot/autogen.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
export AUTOMAKE="automake --foreign --add-missing --copy"
autoreconf

41
usbboot/configure.ac Normal file
View File

@@ -0,0 +1,41 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.63)
AC_INIT([xburst-tools], [0.1])
AC_CONFIG_AUX_DIR(m4)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
AM_CONFIG_HEADER([config.h])
AM_MAINTAINER_MODE
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
# Checks for libraries.
AC_CHECK_LIB([c], [main])
AC_CHECK_LIB([confuse], [main])
AC_CHECK_LIB([gcc], [main])
AC_CHECK_LIB([m], [main])
AC_CHECK_LIB([usb], [main])
LIBS="$LIBS $USB_LIBS"
CFLAGS="$CFLAGS $USB_CFLAGS"
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
AC_TYPE_SIZE_T
AC_TYPE_UINT8_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_MEMCMP
AC_CHECK_FUNCS([memset strerror])
AC_CONFIG_FILES(Makefile src/Makefile )
AC_OUTPUT

5
usbboot/debian/changelog Normal file
View File

@@ -0,0 +1,5 @@
xburst-tools (20090630-1) unstable; urgency=low
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
-- xiangfu <xiangfu.z@gmail.com> Mon, 29 Jun 2009 16:27:20 +0800

1
usbboot/debian/compat Normal file
View File

@@ -0,0 +1 @@
7

16
usbboot/debian/control Normal file
View File

@@ -0,0 +1,16 @@
Source: xburst-tools
Section: misc
Priority: extra
Maintainer: xiangfu liu <xiangfu.z@gmail.com>
Build-Depends: debhelper (>= 7), libusb-dev, libconfuse-dev
Standards-Version: 3.8.0
Homepage: http://code.google.com/p/pi-project
Package: xburst-tools
Architecture: any
Depends: ${shlibs:Depends}, libusb, libconfuse
Description: host tool for Ingenic XBurst CPU USB boot and NAND flash access.
xburst-tools is a host tool for Ingenic XBurst CPU device usb boot.
it's can flash bootloader, kernel, rootfs to Ingenic XBurst CPU
device nand. also have some test function for Ingenic XBurst CPU
device.

19
usbboot/debian/copyright Normal file
View File

@@ -0,0 +1,19 @@
This package was debianized by Xiangfu Liu<xiangfu.z@gmail.com> on
Mon, 22 Jun 2009 22:48:14 +0800.
It was downloaded from <http://code.google.com/p/pi-project/>
Upstream Author(s): Xiangfu Liu <xiangfu.z@gmail.com>
The Debian packaging is copyright 2009, xiangfu <xiangfu.z@gmail.com> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
You are free to distribute this software under the terms of
the GNU General Public License either version 3 of the License,
or (at your option) any later version.
On Debian systems, the complete text of the GNU General Public
License can be found in the file `/usr/share/common-licenses/GPL-3'.
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.

3
usbboot/debian/dirs Normal file
View File

@@ -0,0 +1,3 @@
usr/bin
usr/share/xburst-tools
usr/man/man1

1
usbboot/debian/docs Normal file
View File

@@ -0,0 +1 @@
README

105
usbboot/debian/rules Executable file
View File

@@ -0,0 +1,105 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
else
CROSS= --build $(DEB_BUILD_GNU_TYPE)
endif
config.status: configure
dh_testdir
# Add here commands to configure the package.
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs"
build: build-stamp
build-stamp: config.status
dh_testdir
# Add here commands to compile the package.
$(MAKE)
#docbook-to-man debian/xburst-tools.sgml > xburst-tools.1
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Add here commands to clean up after the build process.
[ ! -f Makefile ] || $(MAKE) distclean
rm -f config.sub config.guess
dh_clean
install: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
# Add here commands to install the package into debian/xburst-tools.
$(MAKE) DESTDIR=$(CURDIR)/debian/xburst-tools install
# Build architecture-independent files here.
binary-indep: install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
dh_installdocs
dh_installexamples
# dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

8
usbboot/src/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
.deps
cmd.o
command_line.o
inflash
inflash_version.h
ingenic_cfg.o
ingenic_usb.o
main.o

28
usbboot/src/Makefile.am Normal file
View File

@@ -0,0 +1,28 @@
AM_CFLAGS = -pedantic -Wall -W -O1 -g3 -std=gnu99 -lusb -lconfuse
BUILD_BRANCH := $(shell git branch | grep ^\* | cut -d' ' -f2)
BUILD_HEAD := $(shell git show --pretty=oneline | head -n1 | cut -d' ' -f1 | cut -b1-16)
BUILD_VERSION := ${BUILD_BRANCH}_${BUILD_HEAD}
xburst_tools_version.h:
echo -e '#ifndef XBURST_TOOLS_VERSION' \
'\n#define XBURST_TOOLS_VERSION "20090630-1"' \
'\n#endif' > xburst_tools_version.h
BUILT_SOURCES = xburst_tools_version.h
bin_PROGRAMS = usbboot
usbboot_SOURCES = cmd.c command_line.c ingenic_cfg.c \
ingenic_usb.c main.c
prefix = /usr
datadir = /usr/share/xburst_tools
data_DATA = ../xburst_stage1/xburst_stage1.bin \
../xburst_stage2/xburst_stage2.bin \
usbboot.cfg
EXTRA_DIST = $(datadir)
../xburst_stage1/xburst_stage1.bin:
$(MAKE) -C ../xburst_stage1
../xburst_stage2/xburst_stage2.bin:
$(MAKE) -C ../xburst_stage2

931
usbboot/src/cmd.c Normal file
View File

@@ -0,0 +1,931 @@
/*
* Authors: Marek Lindner <lindner_marek@yahoo.de>
* Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include "cmd.h"
#include "ingenic_cfg.h"
#include "ingenic_usb.h"
#include "usb_boot_defines.h"
extern int com_argc;
extern char com_argv[MAX_ARGC][MAX_COMMAND_LENGTH];
struct ingenic_dev ingenic_dev;
struct hand hand;
struct sdram_in sdram_in;
struct nand_in nand_in;
static struct nand_out nand_out;
unsigned int total_size;
unsigned char code_buf[4 * 512 * 1024];
unsigned char check_buf[4 * 512 * 1024];
unsigned char cs[16];
unsigned char ret[8];
static const char IMAGE_TYPE[][30] = {
"with oob and ecc",
"with oob and without ecc",
"without oob",
};
static int load_file(struct ingenic_dev *ingenic_dev, const char *file_path)
{
struct stat fstat;
int fd, status, res = -1;
status = stat(file_path, &fstat);
if (status < 0) {
fprintf(stderr, "Error - can't get file size from '%s': %s\n",
file_path, strerror(errno));
goto out;
}
ingenic_dev->file_len = fstat.st_size;
ingenic_dev->file_buff = code_buf;
fd = open(file_path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Error - can't open file '%s': %s\n",
file_path, strerror(errno));
goto out;
}
status = read(fd, ingenic_dev->file_buff, ingenic_dev->file_len);
if (status < ingenic_dev->file_len) {
fprintf(stderr, "Error - can't read file '%s': %s\n",
file_path, strerror(errno));
goto close;
}
/* write args to code */
memcpy(ingenic_dev->file_buff + 8, &hand.fw_args,
sizeof(struct fw_args));
res = 1;
close:
close(fd);
out:
return res;
}
/* after upload stage2. must init device */
void init_cfg()
{
if (usb_get_ingenic_cpu(&ingenic_dev) < 3) {
printf(" XBurst CPU not booted yet, boot it first!\n");
return;
}
ingenic_dev.file_buff = &hand;
ingenic_dev.file_len = sizeof(hand);
if (usb_send_data_to_ingenic(&ingenic_dev) != 1)
goto xout;
if (usb_ingenic_configration(&ingenic_dev, DS_hand) != 1)
goto xout;
if (usb_read_data_from_ingenic(&ingenic_dev, ret, 8) != 1)
goto xout;
printf(" Configuring XBurst CPU succeeded.\n");
return;
xout:
printf("Configuring XBurst CPU failed.\n");
}
int boot(char *stage1_path, char *stage2_path){
int status;
status = usb_get_ingenic_cpu(&ingenic_dev);
switch (status) {
case 1: /* Jz4740v1 */
status = 0;
hand.fw_args.cpu_id = 0x4740;
break;
case 2: /* Jz4750v1 */
status = 0;
hand.fw_args.cpu_id = 0x4750;
break;
case 3: /* Boot4740 */
status = 1;
hand.fw_args.cpu_id = 0x4740;
break;
case 4: /* Boot4750 */
status = 1;
hand.fw_args.cpu_id = 0x4750;
break;
default:
return 1;
}
if (status) {
printf(" Already booted.\n");
return 1;
} else {
printf(" CPU not yet booted, now booting...\n");
/* now we upload the boot stage1 */
printf(" Loading stage1 from '%s'\n", stage1_path);
if (load_file(&ingenic_dev, stage1_path) < 1)
return -1;
if (usb_ingenic_upload(&ingenic_dev, 1) < 1)
return -1;
/* now we upload the boot stage2 */
usleep(100);
printf(" Loading stage2 from '%s'\n", stage2_path);
if (load_file(&ingenic_dev, stage2_path) < 1)
return -1;
if (usb_ingenic_upload(&ingenic_dev, 2) < 1)
return -1;
printf(" Booted successfully!\n");
}
usleep(100);
init_cfg();
return 1;
}
/* nand function */
int error_check(unsigned char *org,unsigned char * obj,unsigned int size)
{
unsigned int i;
printf(" Comparing %d bytes - ", size);
for (i = 0; i < size; i++) {
if (org[i] != obj[i]) {
unsigned int s = (i < 8) ? i : i - 8; // start_dump
printf("FAIL at off %d, wrote 0x%x, read 0x%x\n", i, org[i], obj[i]);
printf(" off %d write: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", s,
org[s], org[s+1], org[s+2], org[s+3], org[s+4], org[s+5], org[s+6], org[s+7],
org[s+8], org[s+9], org[s+10], org[s+11], org[s+12], org[s+13], org[s+14], org[s+15]);
printf(" off %d read: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", s,
obj[s], obj[s+1], obj[s+2], obj[s+3], obj[s+4], obj[s+5], obj[s+6], obj[s+7],
obj[s+8], obj[s+9], obj[s+10], obj[s+11], obj[s+12], obj[s+13], obj[s+14], obj[s+15]);
return 0;
}
}
printf("SUCCESS\n");
return 1;
}
int nand_markbad(struct nand_in *nand_in)
{
if (usb_get_ingenic_cpu(&ingenic_dev) < 3) {
printf(" Device unboot! Boot it first!\n");
return -1;
}
printf(" mark bad block : %d\n",nand_in->start);
usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start);
usb_ingenic_nand_ops(&ingenic_dev, NAND_MARK_BAD);
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
printf(" Mark bad block at %d\n",((ret[3] << 24) |
(ret[2] << 16) |
(ret[1] << 8) |
(ret[0] << 0)) / hand.nand_ppb);
return 0;
}
int nand_program_check(struct nand_in *nand_in,
struct nand_out *nand_out,
unsigned int *start_page)
{
unsigned int i, page_num, cur_page = -1;
unsigned short temp;
printf(" Writing NAND page %d len %d...\n", nand_in->start, nand_in->length);
if (nand_in->length > (unsigned int)MAX_TRANSFER_SIZE) {
printf(" Buffer size too long!\n");
return -1;
}
#ifdef CONFIG_NAND_OUT
unsigned char status_buf[32];
nand_out->status = status_buf;
for (i = 0; i < nand_in->max_chip; i++)
(nand_out->status)[i] = 0; /* set all status to fail */
#endif
if (usb_get_ingenic_cpu(&ingenic_dev) < 3) {
printf(" Device unboot! Boot it first!\n");
return -1;
}
ingenic_dev.file_buff = nand_in->buf;
ingenic_dev.file_len = nand_in->length;
usb_send_data_to_ingenic(&ingenic_dev);
for (i = 0; i < nand_in->max_chip; i++) {
if ((nand_in->cs_map)[i]==0)
continue;
if (nand_in->option == NO_OOB) {
page_num = nand_in->length / hand.nand_ps;
if ((nand_in->length % hand.nand_ps) !=0)
page_num++;
} else {
page_num = nand_in->length /
(hand.nand_ps + hand.nand_os);
if ((nand_in->length% (hand.nand_ps + hand.nand_os)) !=0)
page_num++;
}
temp = ((nand_in->option << 12) & 0xf000) +
((i<<4) & 0xff0) + NAND_PROGRAM;
usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start);
usb_send_data_length_to_ingenic(&ingenic_dev, page_num);
usb_ingenic_nand_ops(&ingenic_dev, temp);
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
printf(" Finish! (len %d start_page %d page_num %d)", nand_in->length, nand_in->start, page_num);
usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start);
/* Read back to check! */
usb_send_data_length_to_ingenic(&ingenic_dev, page_num);
switch (nand_in->option) {
case OOB_ECC:
temp = ((OOB_ECC << 12) & 0xf000) +
((i << 4) & 0xff0) + NAND_READ;
usb_ingenic_nand_ops(&ingenic_dev, temp);
printf("Checking %d bytes...", nand_in->length);
usb_read_data_from_ingenic(&ingenic_dev, check_buf,
page_num * (hand.nand_ps + hand.nand_os));
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
break;
case OOB_NO_ECC: /* do not support data verify */
temp = ((OOB_NO_ECC << 12) & 0xf000) +
((i << 4) & 0xff0) + NAND_READ;
usb_ingenic_nand_ops(&ingenic_dev, temp);
printf("Checking %d bytes...", nand_in->length);
usb_read_data_from_ingenic(&ingenic_dev, check_buf,
page_num * (hand.nand_ps + hand.nand_os));
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
break;
case NO_OOB:
temp = ((NO_OOB << 12) & 0xf000) +
((i << 4) & 0xff0) + NAND_READ;
usb_ingenic_nand_ops(&ingenic_dev, temp);
printf("Checking %d bytes...", nand_in->length);
usb_read_data_from_ingenic(&ingenic_dev, check_buf,
page_num * hand.nand_ps);
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
break;
default:
;
}
cur_page = (ret[3] << 24) | (ret[2] << 16) | (ret[1] << 8) |
(ret[0] << 0);
if (nand_in->start < 1 &&
hand.nand_ps == 4096 &&
hand.fw_args.cpu_id == 0x4740) {
/* (nand_out->status)[i] = 1; */
printf(" no check! End at %d ",cur_page);
continue;
}
if (nand_in->check(nand_in->buf, check_buf, nand_in->length)) {
/* (nand_out->status)[i] = 1; */
printf(" pass! End at %d ",cur_page);
} else {
/* (nand_out->status)[i] = 0; */
printf(" fail! End at %d ",cur_page);
struct nand_in bad;
// tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page?
// tbd: why do we only mark a block as bad if the last page in the block was written?
bad.start = (cur_page - 1) / hand.nand_ppb;
if (cur_page % hand.nand_ppb == 0)
nand_markbad(&bad);
}
}
*start_page = cur_page;
return 0;
}
int nand_erase(struct nand_in *nand_in)
{
unsigned int start_blk, blk_num, end_block;
int i;
start_blk = nand_in->start;
blk_num = nand_in->length;
if (start_blk > (unsigned int)NAND_MAX_BLK_NUM) {
printf(" Start block number overflow!\n");
return -1;
}
if (blk_num > (unsigned int)NAND_MAX_BLK_NUM) {
printf(" Length block number overflow!\n");
return -1;
}
if (usb_get_ingenic_cpu(&ingenic_dev) < 3) {
printf(" Device unboot! Boot it first!\n");
return -1;
}
for (i = 0; i < nand_in->max_chip; i++) {
if ((nand_in->cs_map)[i]==0)
continue;
printf(" Erasing No.%d device No.%d flash (start_blk %u blk_num %u)......\n",
nand_in->dev, i, start_blk, blk_num);
usb_send_data_address_to_ingenic(&ingenic_dev, start_blk);
usb_send_data_length_to_ingenic(&ingenic_dev, blk_num);
unsigned short temp = ((i << 4) & 0xff0) + NAND_ERASE;
usb_ingenic_nand_ops(&ingenic_dev, temp);
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
printf(" Finish!");
}
end_block = ((ret[3] << 24) |
(ret[2] << 16) |
(ret[1] << 8) |
(ret[0] << 0)) / hand.nand_ppb;
printf(" Return: %02x %02x %02x %02x %02x %02x %02x %02x (position %d)\n", ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7], end_block);
if (!hand.nand_force_erase) {
/* not force erase, show bad block infomation */
printf(" There are marked bad blocks: %d\n",
end_block - start_blk - blk_num );
} else {
/* force erase, no bad block infomation can show */
printf(" Force erase, no bad block infomation!\n" );
}
return 1;
}
int nand_program_file(struct nand_in *nand_in,
struct nand_out *nand_out,
char *fname)
{
int flen, m, j, k;
unsigned int start_page = 0, page_num, code_len, offset, transfer_size;
int fd, status;
struct stat fstat;
struct nand_in n_in;
struct nand_out n_out;
#ifdef CONFIG_NAND_OUT
unsigned char status_buf[32];
nand_out->status = status_buf;
for (i=0; i<nand_in->max_chip; i++)
(nand_out->status)[i] = 0; /* set all status to fail */
#endif
status = stat(fname, &fstat);
if (status < 0) {
fprintf(stderr, "Error - can't get file size from '%s': %s\n",
fname, strerror(errno));
return -1;
}
flen = fstat.st_size;
fd = open(fname, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Error - can't open file '%s': %s\n",
fname, strerror(errno));
return -1;
}
printf(" Programing No.%d device, flen %d, start page %d...\n",nand_in->dev, flen, nand_in->start);
n_in.start = nand_in->start / hand.nand_ppb;
if (nand_in->option == NO_OOB) {
if (flen % (hand.nand_ppb * hand.nand_ps) == 0)
n_in.length = flen / (hand.nand_ps * hand.nand_ppb);
else
n_in.length = flen / (hand.nand_ps * hand.nand_ppb) + 1;
} else {
if (flen % (hand.nand_ppb * (hand.nand_ps + hand.nand_os)) == 0)
n_in.length = flen /
((hand.nand_ps + hand.nand_os) * hand.nand_ppb);
else
n_in.length = flen /
((hand.nand_ps + hand.nand_os) * hand.nand_ppb)
+ 1;
}
/* printf(" length %d flen %d\n", n_in.length, flen); */
n_in.cs_map = nand_in->cs_map;
n_in.dev = nand_in->dev;
n_in.max_chip = nand_in->max_chip;
if (nand_erase(&n_in) != 1)
return -1;
if (nand_in->option == NO_OOB)
transfer_size = (hand.nand_ppb * hand.nand_ps);
else
transfer_size = (hand.nand_ppb * (hand.nand_ps + hand.nand_os));
m = flen / transfer_size;
j = flen % transfer_size;
printf(" Size to send %d, transfer_size %d\n", flen, transfer_size);
printf(" Image type : %s\n", IMAGE_TYPE[nand_in->option]);
printf(" It will cause %d times buffer transfer.\n", j == 0 ? m : m + 1);
#ifdef CONFIG_NAND_OUT
for (i = 0; i < nand_in->max_chip; i++)
(nand_out->status)[i] = 1; /* set all status to success! */
#endif
offset = 0;
for (k = 0; k < m; k++) {
if (nand_in->option == NO_OOB)
page_num = transfer_size / hand.nand_ps;
else
page_num = transfer_size / (hand.nand_ps + hand.nand_os);
code_len = transfer_size;
status = read(fd, code_buf, code_len);
if (status < code_len) {
fprintf(stderr, "Error - can't read file '%s': %s\n",
fname, strerror(errno));
return -1;
}
nand_in->length = code_len; /* code length,not page number! */
nand_in->buf = code_buf;
if (nand_program_check(nand_in, &n_out, &start_page) == -1)
return -1;
if (start_page - nand_in->start > hand.nand_ppb)
printf(" Skip a old bad block !\n");
nand_in->start = start_page;
#ifdef CONFIG_NAND_OUT
for (i = 0; i < nand_in->max_chip; i++) {
(nand_out->status)[i] = (nand_out->status)[i] *
(n_out.status)[i];
}
#endif
offset += code_len ;
}
if (j) {
code_len = j;
if (j % hand.nand_ps)
j += hand.nand_ps - (j % hand.nand_ps);
memset(code_buf, 0, j); /* set all to null */
status = read(fd, code_buf, code_len);
if (status < code_len) {
fprintf(stderr, "Error - can't read file '%s': %s\n",
fname, strerror(errno));
return -1;
}
nand_in->length = j;
nand_in->buf = code_buf;
if (nand_program_check(nand_in, &n_out, &start_page) == -1)
return -1;
if (start_page - nand_in->start > hand.nand_ppb)
printf(" Skip a old bad block !");
#ifdef CONFIG_NAND_OUT
for (i=0; i < nand_in->max_chip; i++) {
(nand_out->status)[i] = (nand_out->status)[i] *
(n_out.status)[i];
}
#endif
}
close(fd);
return 1;
}
int nand_program_file_planes(struct nand_in *nand_in,
struct nand_out *nand_out,
char *fname)
{
printf(" not implement yet !\n");
return -1;
}
int init_nand_in(void)
{
nand_in.buf = code_buf;
nand_in.check = error_check;
nand_in.dev = 0;
nand_in.cs_map = cs;
memset(nand_in.cs_map, 0, MAX_DEV_NUM);
nand_in.max_chip = 16;
return 0;
}
int nand_prog(void)
{
char *image_file;
char *help = " Usage: nprog (1) (2) (3) (4) (5)\n"
" (1)\tstart page number\n"
" (2)\timage file name\n"
" (3)\tdevice index number\n"
" (4)\tflash index number\n"
" (5) image type must be:\n"
" \t-n:\tno oob\n"
" \t-o:\twith oob no ecc\n"
" \t-e:\twith oob and ecc\n";
if (com_argc != 6) {
printf(" not enough argument.\n");
printf("%s", help);
return 0;
}
init_nand_in();
nand_in.start = atoi(com_argv[1]);
image_file = com_argv[2];
nand_in.dev = atoi(com_argv[3]);
(nand_in.cs_map)[atoi(com_argv[4])] = 1;
if (!strcmp(com_argv[5], "-e"))
nand_in.option = OOB_ECC;
else if (!strcmp(com_argv[5], "-o"))
nand_in.option = OOB_NO_ECC;
else if (!strcmp(com_argv[5], "-n"))
nand_in.option = NO_OOB;
else
printf("%s", help);
if (hand.nand_plane > 1)
nand_program_file_planes(&nand_in, &nand_out, image_file);
else
nand_program_file(&nand_in, &nand_out, image_file);
#ifdef CONFIG_NAND_OUT
printf(" Flash check result:\n");
int i;
for (i = 0; i < 16; i++)
printf(" %d", (nand_out.status)[i]);
#endif
return 1;
}
int nand_query(void)
{
int i;
unsigned char csn;
if (com_argc < 3) {
printf(" Usage: nquery (1) (2)\n"
" (1):device index number\n"
" (2):flash index number\n");
return -1;
}
init_nand_in();
nand_in.dev = atoi(com_argv[1]);
(nand_in.cs_map)[atoi(com_argv[2])] = 1;
for (i = 0; i < nand_in.max_chip; i++) {
if ((nand_in.cs_map)[i] != 0)
break;
}
if (i >= nand_in.max_chip)
return -1;
if (usb_get_ingenic_cpu(&ingenic_dev) < 3) {
printf(" Device unboot! Boot it first!\n");
return -1;
}
csn = i;
printf(" ID of No.%d device No.%d flash: \n", nand_in.dev, csn);
unsigned short ops = ((csn << 4) & 0xff0) + NAND_QUERY;
usb_ingenic_nand_ops(&ingenic_dev, ops);
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
printf(" Vendor ID :0x%x \n",(unsigned char)ret[0]);
printf(" Product ID :0x%x \n",(unsigned char)ret[1]);
printf(" Chip ID :0x%x \n",(unsigned char)ret[2]);
printf(" Page ID :0x%x \n",(unsigned char)ret[3]);
printf(" Plane ID :0x%x \n",(unsigned char)ret[4]);
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
printf(" Operation status: Success!\n");
return 1;
}
int nand_read(int mode)
{
unsigned int i,j;
unsigned int start_addr, length, page_num;
unsigned char csn;
unsigned short temp = 0;
unsigned ram_addr = 0;
if (com_argc < 5) {
printf(" Usage: nread (1) (2) (3) (4)\n"
" 1:start page number\n"
" 2:length in byte\n"
" 3:device index number\n"
" 4:flash index number\n"
" 5:start SDRAM address\n");
return -1;
}
init_nand_in();
if (atoi(com_argv[4]) >= MAX_DEV_NUM) {
printf(" Flash index number overflow!\n");
return -1;
}
(nand_in.cs_map)[atoi(com_argv[4])] = 1;
nand_in.start = atoi(com_argv[1]);
nand_in.length= atoi(com_argv[2]);
nand_in.dev = atoi(com_argv[3]);
if (com_argc = 6) {
ram_addr = strtoul(com_argv[5], NULL, 0);
printf("==%s==", com_argv[5]);
}
start_addr = nand_in.start;
length = nand_in.length;
if (start_addr > NAND_MAX_PAGE_NUM || length > NAND_MAX_PAGE_NUM ) {
printf(" Page number overflow!\n");
return -1;
}
if (usb_get_ingenic_cpu(&ingenic_dev) < 3) {
printf(" Device unboot! Boot it first!\n");
return -1;
}
for (i = 0; i < nand_in.max_chip; i++)
if ((nand_in.cs_map)[i] != 0)
break;
if (i >= nand_in.max_chip) return 1;
csn = i;
printf(" Reading from No.%d device No.%d flash....\n",nand_in.dev,csn);
page_num = length / hand.nand_ps +1;
switch(mode) {
case NAND_READ:
temp = ((NO_OOB<<12) & 0xf000) + ((csn<<4) & 0xff0) + NAND_READ;
break;
case NAND_READ_OOB:
temp = ((csn<<4) & 0xff0) + NAND_READ_OOB;
break;
case NAND_READ_RAW:
temp = ((NO_OOB<<12) & 0xf000) + ((csn<<4) & 0xff0) +
NAND_READ_RAW;
break;
case NAND_READ_TO_RAM:
temp = ((NO_OOB<<12) & 0xf000) + ((csn<<4) & 0xff0) +
NAND_READ_TO_RAM;
printf(" Reading nand to RAM: 0x%x\n", ram_addr);
usb_ingenic_start(&ingenic_dev, VR_PROGRAM_START1, ram_addr);
break;
default:
printf(" unknow mode!\n");
return -1;
}
usb_send_data_address_to_ingenic(&ingenic_dev, start_addr);
usb_send_data_length_to_ingenic(&ingenic_dev, page_num);
usb_ingenic_nand_ops(&ingenic_dev, temp);
usb_read_data_from_ingenic(&ingenic_dev, nand_in.buf, page_num * hand.nand_ps);
for (j = 0; j < length; j++) {
if (j % 16 == 0)
printf("\n 0x%08x : ",j);
printf("%02x ",(nand_in.buf)[j]);
}
printf("\n");
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
printf(" Operation end position : %d \n",
(ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0));
return 1;
}
int debug_memory(int obj, unsigned int start, unsigned int size)
{
unsigned int buffer[8],tmp;
tmp = usb_get_ingenic_cpu(&ingenic_dev);
if (tmp > 2) {
printf(" This command only run under UNBOOT state!\n");
return -1;
}
switch (tmp) {
case 1:
tmp = 0;
hand.fw_args.cpu_id = 0x4740;
break;
case 2:
tmp = 0;
hand.fw_args.cpu_id = 0x4750;
break;
}
hand.fw_args.debug_ops = 1;/* tell device it's memory debug */
hand.fw_args.start = start;
if (size == 0)
hand.fw_args.size = total_size;
else
hand.fw_args.size = size;
printf(" Now test memory from 0x%x to 0x%x: \n",
start, start + hand.fw_args.size);
if (load_file(&ingenic_dev, STAGE1_FILE_PATH) < 1)
return -1;
if (usb_ingenic_upload(&ingenic_dev, 1) < 1)
return -1;
usleep(100);
usb_read_data_from_ingenic(&ingenic_dev, buffer, 8);
if (buffer[0] != 0)
printf(" Test memory fail! Last error address is 0x%x !\n",
buffer[0]);
else
printf(" Test memory pass!\n");
return 1;
}
int debug_gpio(int obj, unsigned char ops, unsigned char pin)
{
unsigned int tmp;
tmp = usb_get_ingenic_cpu(&ingenic_dev);
if (tmp > 2) {
printf(" This command only run under UNBOOT state!\n");
return -1;
}
switch (tmp) {
case 1:
tmp = 0;
hand.fw_args.cpu_id = 0x4740;
if (pin > 124) {
printf(" Jz4740 has 124 GPIO pin in all!\n");
return -1;
}
break;
case 2:
tmp = 0;
hand.fw_args.cpu_id = 0x4750;
if (pin > 178) {
printf(" Jz4750 has 178 GPIO pin in all!\n");
return -1;
}
break;
}
hand.fw_args.debug_ops = ops;/* tell device it's memory debug */
hand.fw_args.pin_num = pin;
if (ops == 2)
printf(" GPIO %d set!\n",pin);
else
printf(" GPIO %d clear!\n",pin);
if (load_file(&ingenic_dev, STAGE1_FILE_PATH) < 1)
return -1;
if (usb_ingenic_upload(&ingenic_dev, 1) < 1)
return -1;
return 0;
}
int debug_go(void)
{
unsigned int addr,obj;
if (com_argc<3) {
printf(" Usage: go (1) (2) \n"
" 1:start SDRAM address\n"
" 2:device index number\n");
return 0;
}
addr = strtoul(com_argv[1], NULL, 0);
obj = atoi(com_argv[2]);
printf(" Executing No.%d device at address 0x%x\n", obj, addr);
if (usb_ingenic_start(&ingenic_dev, VR_PROGRAM_START2, addr) < 1)
return -1;
return 1;
}
int sdram_load(struct sdram_in *sdram_in)
{
if (usb_get_ingenic_cpu(&ingenic_dev) < 3) {
printf(" Device unboot! Boot it first!\n");
return -1;
}
if (sdram_in->length > (unsigned int) MAX_LOAD_SIZE) {
printf(" Image length too long!\n");
return -1;
}
ingenic_dev.file_buff = sdram_in->buf;
ingenic_dev.file_len = sdram_in->length;
usb_send_data_to_ingenic(&ingenic_dev);
usb_send_data_address_to_ingenic(&ingenic_dev, sdram_in->start);
usb_send_data_length_to_ingenic(&ingenic_dev, sdram_in->length);
usb_ingenic_sdram_ops(&ingenic_dev, sdram_in);
usb_read_data_from_ingenic(&ingenic_dev, ret, 8);
printf(" Load last address at 0x%x\n",
((ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0)));
return 1;
}
int sdram_load_file(struct sdram_in *sdram_in, char *file_path)
{
struct stat fstat;
unsigned int flen,m,j,offset,k;
int fd, status, res = -1;
status = stat(file_path, &fstat);
if (status < 0) {
fprintf(stderr, "Error - can't get file size from '%s': %s\n",
file_path, strerror(errno));
goto out;
}
flen = fstat.st_size;
fd = open(file_path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Error - can't open file '%s': %s\n",
file_path, strerror(errno));
goto out;
}
m = flen / MAX_LOAD_SIZE;
j = flen % MAX_LOAD_SIZE;
offset = 0;
printf(" Total size to send in byte is :%d\n", flen);
printf(" Loading data to SDRAM :\n");
for (k = 0; k < m; k++) {
status = read(fd, sdram_in->buf, MAX_LOAD_SIZE);
if (status < MAX_LOAD_SIZE) {
fprintf(stderr, "Error - can't read file '%s': %s\n",
file_path, strerror(errno));
goto close;
}
sdram_in->length = MAX_LOAD_SIZE;
if (sdram_load(sdram_in) < 1)
goto close;
sdram_in->start += MAX_LOAD_SIZE;
if ( k % 60 == 0)
printf(" 0x%x \n", sdram_in->start);
}
if (j) {
if (j % 4 !=0)
j += 4 - (j % 4);
status = read(fd, sdram_in->buf, j);
if (status < j) {
fprintf(stderr, "Error - can't read file '%s': %s\n",
file_path, strerror(errno));
goto close;
}
sdram_in->length = j;
if (sdram_load(sdram_in) < 1)
goto close;
}
res = 1;
close:
close(fd);
out:
return res;
}

28
usbboot/src/cmd.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* Authors: Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#ifndef __CMD_H__
#define __CMD_H__
#include "usb_boot_defines.h"
#define COMMAND_NUM 31
#define MAX_ARGC 10
#define MAX_COMMAND_LENGTH 100
int boot(char *stage1_path, char *stage2_path);
int init_nand_in();
int nand_prog(void);
int nand_query(void);
int nand_erase(struct nand_in *nand_in);
int debug_memory(int obj, unsigned int start, unsigned int size);
int debug_gpio(int obj, unsigned char ops, unsigned char pin);
int debug_go(void);
#endif /* __CMD_H__ */

317
usbboot/src/command_line.c Normal file
View File

@@ -0,0 +1,317 @@
/*
* Authors: Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "usb_boot_defines.h"
#include "ingenic_usb.h"
#include "cmd.h"
#include "xburst_tools_version.h"
extern struct nand_in nand_in;
extern struct sdram_in sdram_in;
extern unsigned char code_buf[4 * 512 * 1024];
int com_argc;
char com_argv[MAX_ARGC][MAX_COMMAND_LENGTH];
static const char COMMAND[][COMMAND_NUM]=
{
"",
"query",
"querya",
"erase",
"read",
"prog",
"nquery",
"nerase",
"nread",
"nreadraw",
"nreadoob", /* index 10 */
"nprog",
"help",
"version",
"go",
"fconfig",
"exit",
"readnand",
"gpios",
"gpioc",
"boot", /* index 20 */
"list",
"select",
"unselect",
"chip",
"unchip",
"nmark",
"nmake",
"load",
"memtest",
"run"
};
static int handle_help(void)
{
printf(" command support in current version:\n"
/* " query" */
/* " querya" */
/* " erase" */
/* " read" */
/* " prog" */
" nquery query NAND flash info\n"
" nerase erase NAND flash\n"
" nread read NAND flash data with checking bad block and ECC\n"
" nreadraw read NAND flash data without checking bad block and ECC\n"
" nreadoo read NAND flash oob without checking bad block and ECC\n" /* index 10 */
" nprog program NAND flash with data and ECC\n"
" help print this help\n"
" version show current USB Boot software version\n"
" go execute program in SDRAM\n"
" fconfig set USB Boot config file(not implement)\n"
" exit quit from telnet session\n"
" readnand read data from nand flash and store to SDRAM\n"
" gpios set one GPIO to high level\n"
" gpioc set one GPIO to low level\n"
" boot boot device and make it in stage2\n" /* index 20 */
" list show current device number can connect(not implement)\n"
/* " select" */
/* " unselect" */
/* " chip" */
/* " unchip" */
" nmark mark a bad block in NAND flash\n"
" nmake read all data from nand flash and store to file(not implement)\n"
" load load file data to SDRAM\n"
" memtest do SDRAM test\n"
" run run command script in file(implement by -c args)\n"
" sdprog program SD card(not implement)\n"
" sdread read data from SD card(not implement)\n");
return 1;
}
static int handle_version(void)
{
printf(" USB Boot Software current version: %s\n", XBURST_TOOLS_VERSION);
return 1;
}
/* need transfer two para :blk_num ,start_blk */
int handle_nerase(void)
{
if (com_argc < 5) {
printf(" Usage: nerase (1) (2) (3) (4)\n"
" 1:start block number\n"
" 2:block length\n"
" 3:device index number\n"
" 4:flash chip index number\n");
return -1;
}
init_nand_in();
nand_in.start = atoi(com_argv[1]);
nand_in.length = atoi(com_argv[2]);
nand_in.dev = atoi(com_argv[3]);
if (atoi(com_argv[4]) >= MAX_DEV_NUM) {
printf(" Flash index number overflow!\n");
return -1;
}
(nand_in.cs_map)[atoi(com_argv[4])] = 1;
if (nand_erase(&nand_in) < 1)
return -1;
return 1;
}
int handle_nmark(void)
{
if (com_argc < 4) {
printf(" Usage: nerase (1) (2) (3)\n"
" 1:bad block number\n"
" 2:device index number\n"
" 3:flash chip index number\n");
return -1;
}
init_nand_in();
nand_in.start = atoi(com_argv[1]);
nand_in.dev = atoi(com_argv[2]);
if (atoi(com_argv[3])>=MAX_DEV_NUM) {
printf(" Flash index number overflow!\n");
return -1;
}
(nand_in.cs_map)[atoi(com_argv[3])] = 1;
nand_markbad(&nand_in);
return 1;
}
int handle_memtest(void)
{
unsigned int start, size;
if (com_argc != 2 && com_argc != 4)
{
printf(" Usage: memtest (1) [2] [3]\n"
" 1:device index number\n"
" 2:SDRAM start address\n"
" 3:test size\n");
return -1;
}
if (com_argc == 4) {
start = strtoul(com_argv[2], NULL, 0);
size = strtoul(com_argv[3], NULL, 0);
} else {
start = 0;
size = 0;
}
debug_memory(atoi(com_argv[1]), start, size);
return 1;
}
int handle_gpio(int mode)
{
if (com_argc < 3) {
printf(" Usage:"
" gpios (1) (2)\n"
" 1:GPIO pin number\n"
" 2:device index number\n");
return -1;
}
debug_gpio(atoi(com_argv[2]), mode, atoi(com_argv[1]));
return 1;
}
int handle_load(void)
{
if (com_argc<4) {
printf(" Usage:"
" load (1) (2) (3) \n"
" 1:SDRAM start address\n"
" 2:image file name\n"
" 3:device index number\n");
return -1;
}
sdram_in.start=strtoul(com_argv[1], NULL, 0);
printf(" start:::::: 0x%x\n", sdram_in.start);
sdram_in.dev = atoi(com_argv[3]);
sdram_in.buf = code_buf;
sdram_load_file(&sdram_in, com_argv[2]);
return 1;
}
int command_interpret(char * com_buf)
{
char *buf = com_buf;
int k, L, i = 0, j = 0;
L = (int)strlen(buf);
buf[L]=' ';
if (buf[0] == '\n')
return 0;
for (k = 0; k <= L; k++) {
if (*buf == ' ' || *buf == '\n') {
while ( *(++buf) == ' ' );
com_argv[i][j] = '\0';
i++;
if (i > MAX_ARGC)
return COMMAND_NUM + 1;
j = 0;
continue;
} else {
com_argv[i][j] = *buf;
j++;
if (j > MAX_COMMAND_LENGTH)
return COMMAND_NUM + 1;
}
buf++;
}
com_argc = i;
for (i = 1; i <= COMMAND_NUM; i++)
if (!strcmp(COMMAND[i], com_argv[0]))
return i;
return COMMAND_NUM + 1;
}
int command_handle(char *buf)
{
int cmd = command_interpret(buf); /* get the command index */
switch (cmd) {
case 0:
break;
case 6:
nand_query();
break;
case 7:
handle_nerase();
break;
case 8: /* nread */
nand_read(NAND_READ);
break;
case 9: /* nreadraw */
nand_read(NAND_READ_RAW);
break;
case 10: /* nreadoob */
nand_read(NAND_READ_OOB);
break;
case 11:
nand_prog();
break;
case 12:
handle_help();
break;
case 13:
handle_version();
break;
case 14:
debug_go();
break;
case 16: /* exit */
printf(" exiting usbboot software\n");
return -1; /* return -1 to break the main.c while
* then run usb_ingenic_cleanup*/
/*case 17:
nand_read(NAND_READ_TO_RAM); */
break;
case 18:
handle_gpio(2);
break;
case 19:
handle_gpio(3);
break;
case 20:
boot(STAGE1_FILE_PATH, STAGE2_FILE_PATH);
break;
case 26:
handle_nmark();
break;
case 28:
handle_load();
break;
case 29:
handle_memtest();
break;
default:
printf(" command not support or input error!\n");
break;
}
return 1;
}

View File

@@ -0,0 +1,16 @@
/*
* Authors: Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#ifndef __COMMAND_LINE_H__
#define __COMMAND_LINE_H__
int command_input(char *buf);
int command_handle(char *buf);
#endif /* __COMMAND_LINE_H__ */

204
usbboot/src/ingenic_cfg.c Normal file
View File

@@ -0,0 +1,204 @@
/*
* Authors: Marek Lindner <lindner_marek@yahoo.de>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#include <errno.h>
#include <confuse.h>
#include <unistd.h>
#include <string.h>
#include "ingenic_cfg.h"
#include "usb_boot_defines.h"
extern unsigned int total_size;
int hand_init_def(struct hand *hand)
{
/* nand flash info */
/* hand.nand_start=0; */ /* important !!!! */
hand->pt = JZ4740; /* cpu type */
hand->nand_bw = 8;
hand->nand_rc = 3;
hand->nand_ps = 2048;
hand->nand_os = 64;
hand->nand_ppb = 64;
hand->nand_eccpos = 6;
hand->nand_bbpage = 0;
hand->nand_bbpos = 0;
hand->nand_force_erase = 0;
/* hand.nand_ids=0; */ /* vendor_id & device_id */
hand->fw_args.cpu_id = 0x4740;
hand->fw_args.ext_clk = 12;
hand->fw_args.cpu_speed = 225 / hand->fw_args.ext_clk;
hand->fw_args.phm_div = 3;
hand->fw_args.use_uart = 0;
hand->fw_args.boudrate = 57600;
hand->fw_args.bus_width = 0;
hand->fw_args.bank_num = 1;
hand->fw_args.row_addr = 13;
hand->fw_args.col_addr = 9;
hand->fw_args.is_mobile = 0;
hand->fw_args.is_busshare = 1;
return 1;
}
int check_dump_cfg(struct hand *hand)
{
printf("Now checking whether all configure args valid:");
/* check PLL */
if (hand->fw_args.ext_clk > 27 || hand->fw_args.ext_clk < 12) {
printf(" EXTCLK setting invalid!\n");
return 0;
}
if (hand->fw_args.phm_div > 32 || hand->fw_args.ext_clk < 2) {
printf(" PHMDIV setting invalid!\n");
return 0;
}
if ((hand->fw_args.cpu_speed * hand->fw_args.ext_clk ) % 12 != 0) {
printf(" CPUSPEED setting invalid!\n");
return 0;
}
/* check SDRAM */
if (hand->fw_args.bus_width > 1 ) {
printf(" SDRAMWIDTH setting invalid!\n");
return 0;
}
if (hand->fw_args.bank_num > 1 ) {
printf(" BANKNUM setting invalid!\n");
return 0;
}
if (hand->fw_args.row_addr > 13 && hand->fw_args.row_addr < 11 ) {
printf(" ROWADDR setting invalid!\n");
return 0;
}
if (hand->fw_args.col_addr > 13 && hand->fw_args.col_addr < 11 ) {
printf(" COLADDR setting invalid!\n");
return 0;
}
/* check NAND */
if ( hand->nand_ps < 2048 && hand->nand_os > 16 ) {
printf(" PAGESIZE or OOBSIZE setting invalid!\n");
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
hand->nand_ps, hand->nand_os);
return 0;
}
if ( hand->nand_ps < 2048 && hand->nand_ppb > 32 ) {
printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
return 0;
}
if ( hand->nand_ps > 512 && hand->nand_os <= 16 ) {
printf(" PAGESIZE or OOBSIZE setting invalid!\n");
printf(" PAGESIZE is %d,\t OOBSIZE is %d\n",
hand->nand_ps, hand->nand_os);
return 0;
}
if ( hand->nand_ps > 512 && hand->nand_ppb < 64 ) {
printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n");
return 0;
}
printf(" YES\n");
printf("Current device information:\n");
printf("CPU type is Ingenic XBurst Jz%x\n",hand->fw_args.cpu_id);
printf("Crystal work at %dMHz, the CCLK up to %dMHz and PMH_CLK up to %dMHz\n",
hand->fw_args.ext_clk,
(unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk,
((unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk) / hand->fw_args.phm_div);
printf("SDRAM Total size is %d MB, work in %d bank and %d bit mode\n",
total_size / 0x100000, 2 * (hand->fw_args.bank_num + 1),
16 * (2 - hand->fw_args.bus_width));
printf("Nand page size %d, "
"ECC offset in OOB %d, "
"bad block offset in OOB %d, "
"bad block page %d, "
"use %d plane mode\n",
hand->nand_ps,
hand->nand_eccpos,
hand->nand_bbpos,
hand->nand_bbpage,
hand->nand_plane);
return 1;
}
int parse_configure(struct hand *hand, char * file_path)
{
if (access(file_path, F_OK)) {
fprintf(stderr, "Error - can't read configure file %s.\n",
file_path);
return -1;
}
hand_init_def(hand);
cfg_opt_t opts[] = {
CFG_INT("BOUDRATE", 57600, CFGF_NONE),
CFG_SIMPLE_INT("EXTCLK", &hand->fw_args.ext_clk),
CFG_SIMPLE_INT("CPUSPEED", &hand->fw_args.cpu_speed),
CFG_SIMPLE_INT("PHMDIV", &hand->fw_args.phm_div),
CFG_SIMPLE_INT("USEUART", &hand->fw_args.use_uart),
CFG_SIMPLE_INT("BUSWIDTH", &hand->fw_args.bus_width),
CFG_SIMPLE_INT("BANKS", &hand->fw_args.bank_num),
CFG_SIMPLE_INT("ROWADDR", &hand->fw_args.row_addr),
CFG_SIMPLE_INT("COLADDR", &hand->fw_args.col_addr),
CFG_SIMPLE_INT("ISMOBILE", &hand->fw_args.is_mobile),
CFG_SIMPLE_INT("ISBUSSHARE", &hand->fw_args.is_busshare),
CFG_SIMPLE_INT("DEBUGOPS", &hand->fw_args.debug_ops),
CFG_SIMPLE_INT("PINNUM", &hand->fw_args.pin_num),
CFG_SIMPLE_INT("START", &hand->fw_args.start),
CFG_SIMPLE_INT("SIZE", &hand->fw_args.size),
CFG_SIMPLE_INT("NAND_BUSWIDTH", &hand->nand_bw),
CFG_SIMPLE_INT("NAND_ROWCYCLES", &hand->nand_rc),
CFG_SIMPLE_INT("NAND_PAGESIZE", &hand->nand_ps),
CFG_SIMPLE_INT("NAND_PAGEPERBLOCK", &hand->nand_ppb),
CFG_SIMPLE_INT("NAND_FORCEERASE", &hand->nand_force_erase),
CFG_SIMPLE_INT("NAND_OOBSIZE", &hand->nand_os),
CFG_SIMPLE_INT("NAND_ECCPOS", &hand->nand_eccpos),
CFG_SIMPLE_INT("NAND_BADBLOCKPOS", &hand->nand_bbpos),
CFG_SIMPLE_INT("NAND_BADBLOCKPAGE", &hand->nand_bbpage),
CFG_SIMPLE_INT("NAND_PLANENUM", &hand->nand_plane),
CFG_SIMPLE_INT("NAND_BCHBIT", &hand->nand_bchbit),
CFG_SIMPLE_INT("NAND_WPPIN", &hand->nand_wppin),
CFG_SIMPLE_INT("NAND_BLOCKPERCHIP", &hand->nand_bpc),
CFG_END()
};
cfg_t *cfg;
cfg = cfg_init(opts, 0);
if (cfg_parse(cfg, file_path) == CFG_PARSE_ERROR)
return -1;
hand->fw_args.boudrate = cfg_getint(cfg, "BOUDRATE");
cfg_free(cfg);
hand->fw_args.cpu_id = 0x4740;
if (hand->fw_args.bus_width == 32)
hand->fw_args.bus_width = 0 ;
else
hand->fw_args.bus_width = 1 ;
hand->fw_args.bank_num = hand->fw_args.bank_num / 4;
hand->fw_args.cpu_speed = hand->fw_args.cpu_speed / hand->fw_args.ext_clk;
total_size = (unsigned int)
(2 << (hand->fw_args.row_addr + hand->fw_args.col_addr - 1)) * 2
* (hand->fw_args.bank_num + 1) * 2
* (2 - hand->fw_args.bus_width);
if (check_dump_cfg(hand) < 1)
return -1;
return 1;
}

21
usbboot/src/ingenic_cfg.h Normal file
View File

@@ -0,0 +1,21 @@
/*
* Authors: Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#ifndef __INGENIC_CFG_H__
#define __INGENIC_CFG_H__
#include "usb_boot_defines.h"
#define CONFIG_FILE_PATH "/usr/share/xburst_tools/xburst_tools.cfg"
int hand_init_def(struct hand *hand);
int check_dump_cfg(struct hand *hand);
int parse_configure(struct hand *hand, char * file_path);
#endif /*__INGENIC_CFG_H__ */

393
usbboot/src/ingenic_usb.c Normal file
View File

@@ -0,0 +1,393 @@
/*
* Authors: Marek Lindner <lindner_marek@yahoo.de>
* Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#include <usb.h>
#include <stdio.h>
#include <string.h>
#include "usb_boot_defines.h"
#include "ingenic_usb.h"
extern unsigned int total_size;
static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
{
struct usb_bus *usb_busses, *usb_bus;
struct usb_device *usb_dev;
int count = 0;
usb_busses = usb_get_busses();
for (usb_bus = usb_busses; usb_bus != NULL; usb_bus = usb_bus->next) {
for (usb_dev = usb_bus->devices; usb_dev != NULL;
usb_dev = usb_dev->next) {
if ((usb_dev->descriptor.idVendor == VENDOR_ID) &&
(usb_dev->descriptor.idProduct == PRODUCT_ID)) {
ingenic_dev->usb_dev = usb_dev;
count++;
}
}
}
return count;
}
static int get_ingenic_interface(struct ingenic_dev *ingenic_dev)
{
struct usb_config_descriptor *usb_config_desc;
struct usb_interface_descriptor *usb_if_desc;
struct usb_interface *usb_if;
int config_index, if_index, alt_index;
for (config_index = 0;
config_index < ingenic_dev->usb_dev->descriptor.bNumConfigurations;
config_index++) {
usb_config_desc = &ingenic_dev->usb_dev->config[config_index];
if (!usb_config_desc)
return 0;
for (if_index = 0; if_index < usb_config_desc->bNumInterfaces;
if_index++) {
usb_if = &usb_config_desc->interface[if_index];
if (!usb_if)
return 0;
for (alt_index = 0; alt_index < usb_if->num_altsetting;
alt_index++) {
usb_if_desc = &usb_if->altsetting[alt_index];
if (!usb_if_desc)
return 0;
if ((usb_if_desc->bInterfaceClass == 0xff) &&
(usb_if_desc->bInterfaceSubClass == 0)) {
ingenic_dev->interface =
usb_if_desc->bInterfaceNumber;
return 1;
}
}
}
}
return 0;
}
int usb_ingenic_init(struct ingenic_dev *ingenic_dev)
{
int num_ingenic, status = -1;
memset(ingenic_dev, 0, sizeof(struct ingenic_dev));
usb_init();
/* usb_set_debug(255); */
usb_find_busses();
usb_find_devices();
num_ingenic = get_ingenic_device(ingenic_dev);
if (num_ingenic == 0) {
fprintf(stderr, "Error - no XBurst device found\n");
goto out;
}
if (num_ingenic > 1) {
fprintf(stderr, "Error - too many XBurst devices found: %i\n",
num_ingenic);
goto out;
}
ingenic_dev->usb_handle = usb_open(ingenic_dev->usb_dev);
if (!ingenic_dev->usb_handle) {
fprintf(stderr, "Error - can't open XBurst device: %s\n",
usb_strerror());
goto out;
}
if (get_ingenic_interface(ingenic_dev) < 1) {
fprintf(stderr, "Error - can't find XBurst interface\n");
goto out;
}
if (usb_claim_interface(ingenic_dev->usb_handle, ingenic_dev->interface)
< 0) {
fprintf(stderr, "Error - can't claim XBurst interface: %s\n",
usb_strerror());
goto out;
}
status = 1;
out:
return status;
}
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev)
{
int status;
memset(&ingenic_dev->cpu_info_buff, 0,
ARRAY_SIZE(ingenic_dev->cpu_info_buff));
sleep(1);
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
/* bRequest */ VR_GET_CPU_INFO,
/* wValue */ 0,
/* wIndex */ 0,
/* Data */ ingenic_dev->cpu_info_buff,
/* wLength */ 8,
USB_TIMEOUT);
if (status != sizeof(ingenic_dev->cpu_info_buff) - 1 ) {
fprintf(stderr, "Error - "
"can't retrieve XBurst CPU information: %i\n", status);
return status;
}
ingenic_dev->cpu_info_buff[8] = '\0';
/* printf(" CPU data: %s\n", ingenic_dev->cpu_info_buff); */
if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4740V1")) return 1;
if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4750V1")) return 2;
if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4740")) return 3;
if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4750")) return 4;
return 0;
}
int usb_ingenic_flush_cache(struct ingenic_dev *ingenic_dev)
{
int status;
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_FLUSH_CACHES,
/* wValue */ 0,
/* wIndex */ 0,
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - can't flush cache: %i\n", status);
return status;
}
return 1;
}
int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, int len)
{
int status;
/* tell the device the length of the file to be uploaded */
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_SET_DATA_LENGTH,
/* wValue */ STAGE_ADDR_MSB(len),
/* wIndex */ STAGE_ADDR_LSB(len),
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - "
"can't set data length on Ingenic device: %i\n", status);
return -1;
}
return 1;
}
int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev,
unsigned int stage_addr)
{
int status;
/* tell the device the RAM address to store the file */
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_SET_DATA_ADDRESS,
/* wValue */ STAGE_ADDR_MSB(stage_addr),
/* wIndex */ STAGE_ADDR_LSB(stage_addr),
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - "
"can't set the address on Ingenic device: %i\n", status);
return -1;
}
return 1;
}
int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev)
{
int status;
status = usb_bulk_write(ingenic_dev->usb_handle,
/* endpoint */ INGENIC_OUT_ENDPOINT,
/* bulk data */ ingenic_dev->file_buff,
/* bulk data length */ ingenic_dev->file_len,
USB_TIMEOUT);
if (status < ingenic_dev->file_len) {
fprintf(stderr, "Error - "
"can't send bulk data to Ingenic CPU: %i\n", status);
return -1;
}
return 1;
}
int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev,
unsigned char *buff, unsigned int len)
{
int status;
status = usb_bulk_read(ingenic_dev->usb_handle,
/* endpoint */ INGENIC_IN_ENDPOINT,
/* bulk data */ buff,
/* bulk data length */ len,
USB_TIMEOUT);
if (status < len) {
fprintf(stderr, "Error - "
"can't read bulk data from Ingenic device:%i\n", status);
return -1;
}
return 1;
}
int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr)
{
int status;
/* tell the device to start the uploaded device */
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ rqst,
/* wValue */ STAGE_ADDR_MSB(stage_addr),
/* wIndex */ STAGE_ADDR_LSB(stage_addr),
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - can't start the uploaded binary "
"on the Ingenic device: %i\n", status);
return status;
}
return 1;
}
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage)
{
int status;
unsigned int stage2_addr;
stage2_addr = total_size + 0x80000000;
stage2_addr -= CODE_SIZE;
int stage_addr = (stage == 1 ? 0x80002000 : stage2_addr);
int rqst = VR_PROGRAM_START1;
usb_send_data_address_to_ingenic(ingenic_dev, stage_addr);
printf(" Download stage %d program and execute at 0x%08x\n",
stage, (stage_addr));
usb_send_data_to_ingenic(ingenic_dev);
if (stage == 2) {
if (usb_get_ingenic_cpu(ingenic_dev) < 1)
return -1;
usb_ingenic_flush_cache(ingenic_dev);
rqst = VR_PROGRAM_START2;
}
if (usb_ingenic_start(ingenic_dev, rqst, stage_addr) < 1)
return -1;
if (usb_get_ingenic_cpu(ingenic_dev) < 1)
return -1;
return 1;
}
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev)
{
if ((ingenic_dev->usb_handle) && (ingenic_dev->interface))
usb_release_interface(ingenic_dev->usb_handle,
ingenic_dev->interface);
if (ingenic_dev->usb_handle)
usb_close(ingenic_dev->usb_handle);
}
int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops)
{
int status;
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_NAND_OPS,
/* wValue */ ops & 0xffff,
/* wIndex */ 0,
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - "
"can't set Ingenic device nand ops: %i\n", status);
return -1;
}
return 1;
}
int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops)
{
int status;
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_CONFIGRATION,
/* wValue */ ops,
/* wIndex */ 0,
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - "
"can't init Ingenic configration: %i\n", status);
return -1;
}
return 1;
}
int usb_ingenic_sdram_ops(struct ingenic_dev *ingenic_dev, int ops)
{
int status;
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_SDRAM_OPS,
/* wValue */ ops,
/* wIndex */ 0,
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - "
"Device can't load file to sdram: %i\n", status);
return -1;
}
return 1;
}

67
usbboot/src/ingenic_usb.h Normal file
View File

@@ -0,0 +1,67 @@
/*
* Authors: Xiangfu Liu <xiangfu.z@gmail.com>
* Marek Lindner <lindner_marek@yahoo.de>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#ifndef __INGENIC_USB_H__
#define __INGENIC_USB_H__
#include <stdint.h>
#define INGENIC_OUT_ENDPOINT 0x01
#define INGENIC_IN_ENDPOINT 0x81
#define VR_GET_CPU_INFO 0x00
#define VR_SET_DATA_ADDRESS 0x01
#define VR_SET_DATA_LENGTH 0x02
#define VR_FLUSH_CACHES 0x03
#define VR_PROGRAM_START1 0x04
#define VR_PROGRAM_START2 0x05
#define VR_NOR_OPS 0x06
#define VR_NAND_OPS 0x07
#define VR_SDRAM_OPS 0x08
#define VR_CONFIGRATION 0x09
#define VR_GET_NUM 0x0a
#define STAGE_ADDR_MSB(addr) ((addr) >> 16)
#define STAGE_ADDR_LSB(addr) ((addr) & 0xffff)
#define USB_PACKET_SIZE 512
#define USB_TIMEOUT 5000
#define VENDOR_ID 0x601a
#define PRODUCT_ID 0x4740
#define STAGE1_FILE_PATH "/usr/share/xburst_tools/xburst_stage1.bin"
#define STAGE2_FILE_PATH "/usr/share/xburst_tools/xburst_stage2.bin"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
struct ingenic_dev {
struct usb_device *usb_dev;
struct usb_dev_handle *usb_handle;
uint8_t interface;
char cpu_info_buff[9];
char *file_buff;
unsigned int file_len;
};
int usb_ingenic_init(struct ingenic_dev *ingenic_dev);
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev);
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage);
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev);
int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev,
unsigned int stage_addr);
int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev);
int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev,
int len);
int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops);
int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev,unsigned char *buff, unsigned int len);
#endif /* __INGENIC_USB_H__ */

121
usbboot/src/main.c Normal file
View File

@@ -0,0 +1,121 @@
/*
* Authors: Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <string.h>
#include "xburst_tools_version.h"
#include "command_line.h"
#include "ingenic_usb.h"
#include "ingenic_cfg.h"
extern struct ingenic_dev ingenic_dev;
extern struct hand hand;
static void help(void)
{
printf("Usage: usbboot [options] ...(must run as root)\n"
" -h --help\t\t\tPrint this help message\n"
" -v --version\t\t\tPrint the version number\n"
" -c --command\t\t\tDirect run the commands, split by ';'\n"
" <run without options to enter commands via usbboot prompt>\n\n"
"Report bugs to <xiangfu.z@gmail.com>.\n"
);
}
static void print_version(void)
{
printf("usbboot version: %s\n", XBURST_TOOLS_VERSION);
}
static struct option opts[] = {
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'v' },
{ "command", 1, 0, 'c' },
{ 0, 0, 0, 0 }
};
int main(int argc, char **argv)
{
int command = 0;
char *cptr;
char com_buf[256] = {0};
char *cmdpt;
printf("usbboot - Ingenic XBurst USB Boot Utility\n"
"(c) 2009 Ingenic Semiconductor Inc., Qi Hardware Inc., Xiangfu Liu, Marek Lindner\n"
"This program is Free Software and comes with ABSOLUTELY NO WARRANTY.\n\n");
while(1) {
int c, option_index = 0;
c = getopt_long(argc, argv, "hvc:", opts,
&option_index);
if (c == -1)
break;
switch (c) {
case 'h':
help();
exit(EXIT_SUCCESS);
case 'v':
print_version();
exit(EXIT_SUCCESS);
case 'c':
command = 1;
cmdpt = optarg;
break;
default:
help();
exit(2);
}
}
if ((getuid()) || (getgid())) {
fprintf(stderr, "Error - you must be root to run '%s'\n", argv[0]);
return EXIT_FAILURE;
}
if (usb_ingenic_init(&ingenic_dev) < 1)
return EXIT_FAILURE;
if (parse_configure(&hand, CONFIG_FILE_PATH) < 1)
return EXIT_FAILURE;
if (command) { /* direct run command */
char *delim=";";
char *p;
p = strtok(cmdpt, delim);
strcpy(com_buf, p);
printf(" Execute command: %s \n",com_buf);
command_handle(com_buf);
while((p = strtok(NULL,delim))) {
strcpy(com_buf, p);
printf(" Execute command: %s \n",com_buf);
command_handle(com_buf);
}
goto out;
}
while (1) {
printf("usbboot :> ");
cptr = fgets(com_buf, 256, stdin);
if (cptr == NULL)
continue;
if (command_handle(com_buf) == -1 )
break;
}
out:
usb_ingenic_cleanup(&ingenic_dev);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,152 @@
/*
* Authors: Marek Lindner <lindner_marek@yahoo.de>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#ifndef __USB_BOOT_DEFINES_H__
#define __USB_BOOT_DEFINES_H__
#define SDRAM_SIZE ( 16 * 1024 * 1024 )
#define CODE_SIZE ( 4 * 1024 * 1024 )
/* #define START_ADDR ( 0x80000000 + SDRAM_SIZE - CODE_SIZE ) */
#define NAND_MAX_BLK_NUM 10000000 /*((Hand.nand_pn / Hand.nand_ppb) + 1)*/
#define NAND_MAX_PAGE_NUM 1073740824 /*Hand.nand_pn */
#define NAND_SECTION_NUM 23
#define MAX_TRANSFER_SIZE 0x100000
#define MAX_LOAD_SIZE 0x3000
#define NAND_MAX_BYTE_NUM (hand.nand_pn * hand.nand_ps)
#define MAX_DEV_NUM 16
enum CPUTYPE {
JZ4740,
JZ4750,
};
enum USB_Boot_State {
DISCONNECT,
CONNECT,
BOOT,
UNBOOT
};
enum OPTION {
OOB_ECC,
OOB_NO_ECC,
NO_OOB,
};
enum NOR_OPS_TYPE {
NOR_INIT = 0,
NOR_QUERY,
NOR_WRITE,
NOR_ERASE_CHIP,
NOR_ERASE_SECTOR
};
enum NOR_FLASH_TYPE
{
NOR_AM29 = 0,
NOR_SST28,
NOR_SST39x16,
NOR_SST39x8
};
enum NAND_OPS_TYPE {
NAND_QUERY = 0,
NAND_INIT,
NAND_MARK_BAD,
NAND_READ_OOB,
NAND_READ_RAW,
NAND_ERASE,
NAND_READ,
NAND_PROGRAM,
NAND_READ_TO_RAM
};
enum SDRAM_OPS_TYPE {
SDRAM_LOAD,
};
enum DATA_STRUCTURE_OB {
DS_flash_info ,
DS_hand
};
struct fw_args {
/* CPU ID */
unsigned int cpu_id;
/* PLL args */
unsigned char ext_clk;
unsigned char cpu_speed;
unsigned char phm_div;
unsigned char use_uart;
unsigned int boudrate;
/* SDRAM args */
unsigned char bus_width;
unsigned char bank_num;
unsigned char row_addr;
unsigned char col_addr;
unsigned char is_mobile;
unsigned char is_busshare;
/* debug args */
unsigned char debug_ops;
unsigned char pin_num;
unsigned int start;
unsigned int size;
} __attribute__((packed));
struct hand {
/* nand flash info */
int pt; /* cpu type */
unsigned int nand_bw; /* bus width */
unsigned int nand_rc; /* row cycle */
unsigned int nand_ps; /* page size */
unsigned int nand_ppb; /* page number per block */
unsigned int nand_force_erase;
unsigned int nand_pn; /* page number in total */
unsigned int nand_os; /* oob size */
unsigned int nand_eccpos;
unsigned int nand_bbpage;
unsigned int nand_bbpos;
unsigned int nand_plane;
unsigned int nand_bchbit;
unsigned int nand_wppin;
unsigned int nand_bpc; /* block number per chip */
struct fw_args fw_args;
} __attribute__((packed));
struct nand_in {
unsigned char dev;
unsigned char max_chip;
unsigned char *buf;
unsigned char *cs_map;
unsigned int start;
unsigned int length;
unsigned int option;
int (* check) (unsigned char *,unsigned char *,unsigned int);
};
struct nand_out {
unsigned char *status;
};
struct sdram_in {
unsigned char dev;
unsigned char *buf;
unsigned int start;
unsigned int length;
unsigned int option;
};
#endif /* __USB_BOOT_DEFINES_H__ */

52
usbboot/src/usbboot.cfg Normal file
View File

@@ -0,0 +1,52 @@
#
# usbboot configuration file
#
# Utility to respond to the Ingenic XBurst USB boot protocol, provide
# initial boot stages and ability to access NAND on device.
#
# Authors: Ingenic Semiconductor, Inc.
# Xiangfu Liu <xiangfu.z@gmail.com>
# Marek Lindner <lindner_marek@yahoo.de>
# Wolfgang Spraul <wolfgang@qi-hardware.com>
#
# 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
# 3 of the License, or (at your option) any later version.
#
# [PLL]
EXTCLK = 12 #Define the external crystal in MHz
CPUSPEED = 252 #Define the PLL output frequency
PHMDIV = 3 #Define the frequency divider ratio of PLL=CCLK:PCLK=HCLK=MCLK
BOUDRATE = 57600 #Define the uart boudrate
USEUART = 0 #Use which uart, 0/1 for jz4740,0/1/2/3 for jz4750
# [SDRAM]
BUSWIDTH = 16 #The bus width of the SDRAM in bits (16|32)
BANKS = 4 #The bank number (2|4)
ROWADDR = 13 #Row address width in bits (11-13)
COLADDR = 9 #Column address width in bits (8-12)
ISMOBILE = 0 #Define whether SDRAM is mobile SDRAM, this only valid for Jz4750 ,1:yes 0:no
ISBUSSHARE = 1 #Define whether SDRAM bus share with NAND 1:shared 0:unshared
DEBUGOPS = 0
# [NAND]
NAND_BUSWIDTH = 8 #The width of the NAND flash chip in bits (8|16|32)
NAND_ROWCYCLES = 3 #The row address cycles (2|3)
NAND_PAGESIZE = 2048 #The page size of the NAND chip in bytes(512|2048|4096)
NAND_PAGEPERBLOCK = 128 #The page number per block
NAND_FORCEERASE = 1 #The force to erase flag (0|1)
NAND_OOBSIZE = 64 #oob size in byte
NAND_ECCPOS = 6 #Specify the ECC offset inside the oob data (0-[oobsize-1])
NAND_BADBLOCKPOS = 0 #Specify the badblock flag offset inside the oob (0-[oobsize-1])
NAND_BADBLOCKPAGE = 127 #Specify the page number of badblock flag inside a block(0-[PAGEPERBLOCK-1])
NAND_PLANENUM = 1 #The planes number of target nand flash
NAND_BCHBIT = 4 #Specify the hardware BCH algorithm for 4750 (4|8)
NAND_WPPIN = 0 #Specify the write protect pin number
NAND_BLOCKPERCHIP = 0 #Specify the block number per chip,0 means ignore
#The program will calculate the total SDRAM size by : size = 2^(ROWADDR + COLADDR) * BANKNUM * (SDRAMWIDTH / 4)
#The CPUSPEED has restriction as: ( CPUSPEED % EXTCLK == 0 ) && ( CPUSPEED % 12 == 0 )
#For jz4750, the program just init BANK0(DSC0).
#Beware all variables must be set correct!

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/*
* device board
*
* (C) Copyright 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#ifndef _CONFIGS_H
#define _CONFIGS_H
/* Here are these common definitions */
/* Once your system configration change, just modify the file */
#define CONFIG_NR_DRAM_BANKS 1 /* SDRAM BANK Number: 1, 2*/
#define SDRAM_CASL 3 /* CAS latency: 2 or 3 */
/* SDRAM Timings, unit: ns */
#define SDRAM_TRAS 45 /* RAS# Active Time */
#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
#define SDRAM_TPC 20 /* RAS# Precharge Time */
#define SDRAM_TRWL 7 /* Write Latency Time */
#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
extern volatile u32 CPU_ID;
extern volatile u8 SDRAM_BW16;
extern volatile u8 SDRAM_BANK4;
extern volatile u8 SDRAM_ROW;
extern volatile u8 SDRAM_COL;
extern volatile u8 CONFIG_MOBILE_SDRAM;
extern volatile u32 CFG_CPU_SPEED;
extern volatile u8 PHM_DIV;
extern volatile u32 CFG_EXTAL;
extern volatile u32 CONFIG_BAUDRATE;
extern volatile u32 UART_BASE;
extern volatile u8 CONFIG_MOBILE_SDRAM;
extern volatile u8 IS_SHARE;
extern void gpio_init_4740(void);
extern void sdram_init_4740(void);
extern void serial_init_4740(void);
extern void pll_init_4740(void);
extern void gpio_init_4750(void);
extern void sdram_init_4750(void);
extern void serial_init_4750(void);
extern void pll_init_4750(void);
extern void serial_puts(const char *s);
#endif

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#ifndef __ERROR_H__
#define __ERROR_H__
/*
* All of the return codes
*/
#define ERR_OK 0
#define ERR_TIMOUT 1
#define ERR_NOT_ERASED 2
#define ERR_PROTECTED 4
#define ERR_INVAL 8
#define ERR_OPS_NOTSUPPORT 9
#define ERR_ALIGN 16
#define ERR_UNKNOWN_FLASH_VENDOR 32
#define ERR_UNKNOWN_FLASH_TYPE 64
#define ERR_PROG_ERROR 128
#define ERR_ERASE_ERROR 256
#define ERR_WRITE_VERIFY 512
#define ERR_NOT_SUPPORT 1024 /* operation not supported */
#endif /* __ERROR_H__ */

File diff suppressed because it is too large Load Diff

5318
usbboot/xburst_include/jz4750.h Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,820 @@
/**************************************************************************
* *
* PROJECT : MIPS port for uC/OS-II *
* *
* MODULE : MIPS.h *
* *
* AUTHOR : Michael Anburaj *
* URL : http://geocities.com/michaelanburaj/ *
* EMAIL: michaelanburaj@hotmail.com *
* *
* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board *
* *
* TOOL-CHAIN : SDE & Cygnus *
* *
* DESCRIPTION : *
* MIPS processor definitions. *
* The basic CPU definitions are found in the file archdefs.h, which *
* is included by mips.h. *
* *
* mips.h implements aliases for some of the definitions in archdefs.h *
* and adds various definitions. *
* *
**************************************************************************/
#ifndef __MIPS_H__
#define __MIPS_H__
#include "archdefs.h"
/* ********************************************************************* */
/* Module configuration */
/* ********************************************************************* */
/* Interface macro & data definition */
#ifndef MSK
#define MSK(n) ((1 << (n)) - 1)
#endif
/* CPU registers */
#define SYS_CPUREG_ZERO 0
#define SYS_CPUREG_AT 1
#define SYS_CPUREG_V0 2
#define SYS_CPUREG_V1 3
#define SYS_CPUREG_A0 4
#define SYS_CPUREG_A1 5
#define SYS_CPUREG_A2 6
#define SYS_CPUREG_A3 7
#define SYS_CPUREG_T0 8
#define SYS_CPUREG_T1 9
#define SYS_CPUREG_T2 10
#define SYS_CPUREG_T3 11
#define SYS_CPUREG_T4 12
#define SYS_CPUREG_T5 13
#define SYS_CPUREG_T6 14
#define SYS_CPUREG_T7 15
#define SYS_CPUREG_S0 16
#define SYS_CPUREG_S1 17
#define SYS_CPUREG_S2 18
#define SYS_CPUREG_S3 19
#define SYS_CPUREG_S4 20
#define SYS_CPUREG_S5 21
#define SYS_CPUREG_S6 22
#define SYS_CPUREG_S7 23
#define SYS_CPUREG_T8 24
#define SYS_CPUREG_T9 25
#define SYS_CPUREG_K0 26
#define SYS_CPUREG_K1 27
#define SYS_CPUREG_GP 28
#define SYS_CPUREG_SP 29
#define SYS_CPUREG_S8 30
#define SYS_CPUREG_FP SYS_CPUREG_S8
#define SYS_CPUREG_RA 31
/* CPU register fp ($30) has an alias s8 */
#define s8 fp
/* Aliases for System Control Coprocessor (CP0) registers */
#define C0_INDEX C0_Index
#define C0_RANDOM C0_Random
#define C0_ENTRYLO0 C0_EntryLo0
#define C0_ENTRYLO1 C0_EntryLo1
#define C0_CONTEXT C0_Context
#define C0_PAGEMASK C0_PageMask
#define C0_WIRED C0_Wired
#define C0_BADVADDR C0_BadVAddr
#define C0_COUNT C0_Count
#define C0_ENTRYHI C0_EntryHi
#define C0_COMPARE C0_Compare
#define C0_STATUS C0_Status
#define C0_CAUSE C0_Cause
#ifdef C0_PRID /* ArchDefs has an obsolete def. of C0_PRID */
#undef C0_PRID
#endif
#define C0_PRID C0_PRId
#define C0_CONFIG C0_Config
#define C0_CONFIG1 C0_Config1
#define C0_LLADDR C0_LLAddr
#define C0_WATCHLO C0_WatchLo
#define C0_WATCHHI C0_WatchHi
#define C0_DEBUG C0_Debug
#define C0_PERFCNT C0_PerfCnt
#define C0_ERRCTL C0_ErrCtl
#define C0_CACHEERR C0_CacheErr
#define C0_TAGLO C0_TagLo
#define C0_DATALO C0_DataLo
#define C0_TAGHI C0_TagHi
#define C0_DATAHI C0_DataHi
#define C0_ERROREPC C0_ErrorEPC
#if 0
#define C0_DESAVE C0_DESAVE
#define C0_EPC C0_EPC
#define C0_DEPC C0_DEPC
#endif
/* System Control Coprocessor (CP0) registers select fields */
#define C0_INDEX_SEL 0 /* TLB Index */
#define C0_RANDOM_SEL 0 /* TLB Random */
#define C0_TLBLO0_SEL 0 /* TLB EntryLo0 */
#define C0_TLBLO1_SEL 0 /* TLB EntryLo1 */
#define C0_CONTEXT_SEL 0 /* Context */
#define C0_PAGEMASK_SEL 0 /* TLB PageMask */
#define C0_WIRED_SEL 0 /* TLB Wired */
#define C0_BADVADDR_SEL 0 /* Bad Virtual Address */
#define C0_COUNT_SEL 0 /* Count */
#define C0_ENTRYHI_SEL 0 /* TLB EntryHi */
#define C0_COMPARE_SEL 0 /* Compare */
#define C0_STATUS_SEL 0 /* Processor Status */
#define C0_CAUSE_SEL 0 /* Exception Cause */
#define C0_EPC_SEL 0 /* Exception PC */
#define C0_PRID_SEL 0 /* Processor Revision Indentifier */
#define C0_CONFIG_SEL 0 /* Config */
#define C0_CONFIG1_SEL 1 /* Config1 */
#define C0_LLADDR_SEL 0 /* LLAddr */
#define C0_WATCHLO_SEL 0 /* WatchpointLo */
#define C0_WATCHHI_SEL 0 /* WatchpointHi */
#define C0_DEBUG_SEL 0 /* EJTAG Debug Register */
#define C0_DEPC_SEL 0 /* Program counter at last EJTAG debug exception */
#define C0_PERFCNT_SEL 0 /* Performance counter interface */
#define C0_ERRCTL_SEL 0 /* ERRCTL */
#define C0_CACHEERR_SEL 0 /* CacheErr */
#define C0_TAGLO_SEL 0 /* TagLo */
#define C0_DATALO_SEL 1 /* DataLo */
#define C0_DTAGLO_SEL 2 /* DTagLo */
#define C0_TAGHI_SEL 0 /* TagHi */
#define C0_DATAHI_SEL 1 /* DataHi */
#define C0_DTAGHI_SEL 2 /* DTagHi */
#define C0_ERROREPC_SEL 0 /* ErrorEPC */
#define C0_DESAVE_SEL 0 /* EJTAG dbg exc. save register */
/* C0_CONFIG register encoding */
#define C0_CONFIG_M_SHF S_ConfigMore
#define C0_CONFIG_M_MSK M_ConfigMore
#define C0_CONFIG_M_BIT C0_CONFIG_M_MSK
#define C0_CONFIG_BE_SHF S_ConfigBE
#define C0_CONFIG_BE_MSK M_ConfigBE
#define C0_CONFIG_BE_BIT C0_CONFIG_BE_MSK
#define C0_CONFIG_AT_SHF S_ConfigAT
#define C0_CONFIG_AT_MSK M_ConfigAT
#define C0_CONFIG_AT_MIPS32 K_ConfigAT_MIPS32
#define C0_CONFIG_AT_MIPS64_32ADDR K_ConfigAT_MIPS64S
#define C0_CONFIG_AT_MIPS64 K_ConfigAT_MIPS64
#define C0_CONFIG_AR_SHF S_ConfigAR
#define C0_CONFIG_AR_MSK M_ConfigAR
#define C0_CONFIG_MT_SHF S_ConfigMT
#define C0_CONFIG_MT_MSK M_ConfigMT
#define C0_CONFIG_MT_NONE K_ConfigMT_NoMMU
#define C0_CONFIG_MT_TLB K_ConfigMT_TLBMMU
#define C0_CONFIG_MT_BAT K_ConfigMT_BATMMU
#define C0_CONFIG_MT_NON_STD K_ConfigMT_FMMMU
#define C0_CONFIG_K0_SHF S_ConfigK0
#define C0_CONFIG_K0_MSK M_ConfigK0
#define C0_CONFIG_K0_WTHRU_NOALLOC K_CacheAttrCWTnWA
#define C0_CONFIG_K0_WTHRU_ALLOC K_CacheAttrCWTWA
#define C0_CONFIG_K0_UNCACHED K_CacheAttrU
#define C0_CONFIG_K0_NONCOHERENT K_CacheAttrCN
#define C0_CONFIG_K0_COHERENTXCL K_CacheAttrCCE
#define C0_CONFIG_K0_COHERENTXCLW K_CacheAttrCCS
#define C0_CONFIG_K0_COHERENTUPD K_CacheAttrCCU
#define C0_CONFIG_K0_UNCACHED_ACCEL K_CacheAttrUA
/* WC field.
*
* This feature is present specifically to support configuration
* testing of the core in a lead vehicle, and is not supported
* in any other environment. Attempting to use this feature
* outside of the scope of a lead vehicle is a violation of the
* MIPS Architecture, and may cause unpredictable operation of
* the processor.
*/
#define C0_CONFIG_WC_SHF 19
#define C0_CONFIG_WC_MSK (MSK(1) << C0_CONFIG_WC_SHF)
#define C0_CONFIG_WC_BIT C0_CONFIG_WC_MSK
/* C0_CONFIG1 register encoding */
#define C0_CONFIG1_MMUSIZE_SHF S_Config1MMUSize
#define C0_CONFIG1_MMUSIZE_MSK M_Config1MMUSize
#define C0_CONFIG1_IS_SHF S_Config1IS
#define C0_CONFIG1_IS_MSK M_Config1IS
#define C0_CONFIG1_IL_SHF S_Config1IL
#define C0_CONFIG1_IL_MSK M_Config1IL
#define C0_CONFIG1_IA_SHF S_Config1IA
#define C0_CONFIG1_IA_MSK M_Config1IA
#define C0_CONFIG1_DS_SHF S_Config1DS
#define C0_CONFIG1_DS_MSK M_Config1DS
#define C0_CONFIG1_DL_SHF S_Config1DL
#define C0_CONFIG1_DL_MSK M_Config1DL
#define C0_CONFIG1_DA_SHF S_Config1DA
#define C0_CONFIG1_DA_MSK M_Config1DA
#define C0_CONFIG1_WR_SHF S_Config1WR
#define C0_CONFIG1_WR_MSK M_Config1WR
#define C0_CONFIG1_WR_BIT C0_CONFIG1_WR_MSK
#define C0_CONFIG1_CA_SHF S_Config1CA
#define C0_CONFIG1_CA_MSK M_Config1CA
#define C0_CONFIG1_CA_BIT C0_CONFIG1_CA_MSK
#define C0_CONFIG1_EP_SHF S_Config1EP
#define C0_CONFIG1_EP_MSK M_Config1EP
#define C0_CONFIG1_EP_BIT C0_CONFIG1_EP_MSK
#define C0_CONFIG1_FP_SHF S_Config1FP
#define C0_CONFIG1_FP_MSK M_Config1FP
#define C0_CONFIG1_FP_BIT C0_CONFIG1_FP_MSK
/* C0_STATUS register encoding */
#define C0_STATUS_CU3_SHF S_StatusCU3
#define C0_STATUS_CU3_MSK M_StatusCU3
#define C0_STATUS_CU3_BIT C0_STATUS_CU3_MSK
#define C0_STATUS_CU2_SHF S_StatusCU2
#define C0_STATUS_CU2_MSK M_StatusCU2
#define C0_STATUS_CU2_BIT C0_STATUS_CU2_MSK
#define C0_STATUS_CU1_SHF S_StatusCU1
#define C0_STATUS_CU1_MSK M_StatusCU1
#define C0_STATUS_CU1_BIT C0_STATUS_CU1_MSK
#define C0_STATUS_CU0_SHF S_StatusCU1
#define C0_STATUS_CU0_MSK M_StatusCU1
#define C0_STATUS_CU0_BIT C0_STATUS_CU0_MSK
#define C0_STATUS_RP_SHF S_StatusRP
#define C0_STATUS_RP_MSK M_StatusRP
#define C0_STATUS_RP_BIT C0_STATUS_RP_MSK
#define C0_STATUS_FR_SHF S_StatusFR
#define C0_STATUS_FR_MSK M_StatusFR
#define C0_STATUS_FR_BIT C0_STATUS_FR_MSK
#define C0_STATUS_RE_SHF S_StatusRE
#define C0_STATUS_RE_MSK M_StatusRE
#define C0_STATUS_RE_BIT C0_STATUS_RE_MSK
#define C0_STATUS_BEV_SHF S_StatusBEV
#define C0_STATUS_BEV_MSK M_StatusBEV
#define C0_STATUS_BEV_BIT C0_STATUS_BEV_MSK
#define C0_STATUS_TS_SHF S_StatusTS
#define C0_STATUS_TS_MSK M_StatusTS
#define C0_STATUS_TS_BIT C0_STATUS_TS_MSK
#define C0_STATUS_SR_SHF S_StatusSR
#define C0_STATUS_SR_MSK M_StatusSR
#define C0_STATUS_SR_BIT C0_STATUS_SR_MSK
#define C0_STATUS_NMI_SHF S_StatusNMI
#define C0_STATUS_NMI_MSK M_StatusNMI
#define C0_STATUS_NMI_BIT C0_STATUS_NMI_MSK
#define C0_STATUS_IM_SHF S_StatusIM
#define C0_STATUS_IM_MSK M_StatusIM
/* Note that the the definitions below indicate the interrupt number
* rather than the mask.
* (0..1 for SW interrupts and 2...7 for HW interrupts)
*/
#define C0_STATUS_IM_SW0 (S_StatusIM0 - S_StatusIM)
#define C0_STATUS_IM_SW1 (S_StatusIM1 - S_StatusIM)
#define C0_STATUS_IM_HW0 (S_StatusIM2 - S_StatusIM)
#define C0_STATUS_IM_HW1 (S_StatusIM3 - S_StatusIM)
#define C0_STATUS_IM_HW2 (S_StatusIM4 - S_StatusIM)
#define C0_STATUS_IM_HW3 (S_StatusIM5 - S_StatusIM)
#define C0_STATUS_IM_HW4 (S_StatusIM6 - S_StatusIM)
#define C0_STATUS_IM_HW5 (S_StatusIM7 - S_StatusIM)
/* Max interrupt code */
#define C0_STATUS_IM_MAX C0_STATUS_IM_HW5
#define C0_STATUS_KSU_SHF S_StatusKSU
#define C0_STATUS_KSU_MSK M_StatusKSU
#define C0_STATUS_UM_SHF S_StatusUM
#define C0_STATUS_UM_MSK M_StatusUM
#define C0_STATUS_UM_BIT C0_STATUS_UM_MSK
#define C0_STATUS_ERL_SHF S_StatusERL
#define C0_STATUS_ERL_MSK M_StatusERL
#define C0_STATUS_ERL_BIT C0_STATUS_ERL_MSK
#define C0_STATUS_EXL_SHF S_StatusEXL
#define C0_STATUS_EXL_MSK M_StatusEXL
#define C0_STATUS_EXL_BIT C0_STATUS_EXL_MSK
#define C0_STATUS_IE_SHF S_StatusIE
#define C0_STATUS_IE_MSK M_StatusIE
#define C0_STATUS_IE_BIT C0_STATUS_IE_MSK
/* C0_PRID register encoding */
#define C0_PRID_OPT_SHF S_PRIdCoOpt
#define C0_PRID_OPT_MSK M_PRIdCoOpt
#define C0_PRID_COMP_SHF S_PRIdCoID
#define C0_PRID_COMP_MSK M_PRIdCoID
#define C0_PRID_COMP_MIPS K_PRIdCoID_MIPS
#define C0_PRID_COMP_NOT_MIPS32_64 0
#define C0_PRID_PRID_SHF S_PRIdImp
#define C0_PRID_PRID_MSK M_PRIdImp
/* Jade */
#define C0_PRID_PRID_4Kc K_PRIdImp_Jade
#define C0_PRID_PRID_4Kmp K_PRIdImp_JadeLite /* 4Km/4Kp */
/* Emerald */
#define C0_PRID_PRID_4KEc K_PRIdImp_4KEc
#define C0_PRID_PRID_4KEmp K_PRIdImp_4KEmp
/* Coral */
#define C0_PRID_PRID_4KSc K_PRIdImp_4KSc
/* Opal */
#define C0_PRID_PRID_5K K_PRIdImp_Opal
/* Ruby */
#define C0_PRID_PRID_20Kc K_PRIdImp_Ruby
/* Other CPUs */
#define C0_PRID_PRID_R4000 K_PRIdImp_R4000
#define C0_PRID_PRID_RM52XX K_PRIdImp_R5200
#define C0_PRID_PRID_RM70XX 0x27
#define C0_PRID_REV_SHF S_PRIdRev
#define C0_PRID_REV_MSK M_PRIdRev
#define MIPS_4Kc ( (C0_PRID_COMP_MIPS << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_4Kc << \
C0_PRID_PRID_SHF) \
)
#define MIPS_4Kmp ( (C0_PRID_COMP_MIPS << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_4Kmp << \
C0_PRID_PRID_SHF) \
)
#define MIPS_4KEc ( (C0_PRID_COMP_MIPS << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_4KEc << \
C0_PRID_PRID_SHF) \
)
#define MIPS_4KEmp ( (C0_PRID_COMP_MIPS << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_4KEmp << \
C0_PRID_PRID_SHF) \
)
#define MIPS_4KSc ( (C0_PRID_COMP_MIPS << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_4KSc << \
C0_PRID_PRID_SHF) \
)
#define MIPS_5K ( (C0_PRID_COMP_MIPS << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_5K << \
C0_PRID_PRID_SHF) \
)
#define MIPS_20Kc ( (C0_PRID_COMP_MIPS << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_20Kc << \
C0_PRID_PRID_SHF) \
)
#define QED_RM52XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_RM52XX << \
C0_PRID_PRID_SHF) \
)
#define QED_RM70XX ( (C0_PRID_COMP_NOT_MIPS32_64 << \
C0_PRID_COMP_SHF) | \
(C0_PRID_PRID_RM70XX << \
C0_PRID_PRID_SHF) \
)
/* C0_ENTRYHI register encoding */
#define C0_ENTRYHI_VPN2_SHF S_EntryHiVPN2
#define C0_ENTRYHI_VPN2_MSK M_EntryHiVPN2
#define C0_ENTRYHI_ASID_SHF S_EntryHiASID
#define C0_ENTRYHI_ASID_MSK M_EntryHiASID
/* C0_CAUSE register encoding */
#define C0_CAUSE_BD_SHF S_CauseBD
#define C0_CAUSE_BD_MSK M_CauseBD
#define C0_CAUSE_BD_BIT C0_CAUSE_BD_MSK
#define C0_CAUSE_CE_SHF S_CauseCE
#define C0_CAUSE_CE_MSK M_CauseCE
#define C0_CAUSE_IV_SHF S_CauseIV
#define C0_CAUSE_IV_MSK M_CauseIV
#define C0_CAUSE_IV_BIT C0_CAUSE_IV_MSK
#define C0_CAUSE_WP_SHF S_CauseWP
#define C0_CAUSE_WP_MSK M_CauseWP
#define C0_CAUSE_WP_BIT C0_CAUSE_WP_MSK
#define C0_CAUSE_IP_SHF S_CauseIP
#define C0_CAUSE_IP_MSK M_CauseIP
#define C0_CAUSE_CODE_SHF S_CauseExcCode
#define C0_CAUSE_CODE_MSK M_CauseExcCode
#define C0_CAUSE_CODE_INT EX_INT
#define C0_CAUSE_CODE_MOD EX_MOD
#define C0_CAUSE_CODE_TLBL EX_TLBL
#define C0_CAUSE_CODE_TLBS EX_TLBS
#define C0_CAUSE_CODE_ADEL EX_ADEL
#define C0_CAUSE_CODE_ADES EX_ADES
#define C0_CAUSE_CODE_IBE EX_IBE
#define C0_CAUSE_CODE_DBE EX_DBE
#define C0_CAUSE_CODE_SYS EX_SYS
#define C0_CAUSE_CODE_BP EX_BP
#define C0_CAUSE_CODE_RI EX_RI
#define C0_CAUSE_CODE_CPU EX_CPU
#define C0_CAUSE_CODE_OV EX_OV
#define C0_CAUSE_CODE_TR EV_TR
#define C0_CAUSE_CODE_FPE EX_FPE
#define C0_CAUSE_CODE_WATCH EX_WATCH
#define C0_CAUSE_CODE_MCHECK EX_MCHECK
/* Max cause code */
#define C0_CAUSE_CODE_MAX EX_MCHECK
/* C0_PAGEMASK register encoding */
#define C0_PAGEMASK_MASK_SHF S_PageMaskMask
#define C0_PAGEMASK_MASK_MSK M_PageMaskMask
#define C0_PAGEMASK_MASK_4K K_PageMask4K
#define C0_PAGEMASK_MASK_16K K_PageMask16K
#define C0_PAGEMASK_MASK_64K K_PageMask64K
#define C0_PAGEMASK_MASK_256K K_PageMask256K
#define C0_PAGEMASK_MASK_1M K_PageMask1M
#define C0_PAGEMASK_MASK_4M K_PageMask4M
#define C0_PAGEMASK_MASK_16M K_PageMask16M
/* C0_ENTRYLO0 register encoding (equiv. to C0_ENTRYLO1) */
#define C0_ENTRYLO0_PFN_SHF S_EntryLoPFN
#define C0_ENTRYLO0_PFN_MSK M_EntryLoPFN
#define C0_ENTRYLO0_C_SHF S_EntryLoC
#define C0_ENTRYLO0_C_MSK M_EntryLoC
#define C0_ENTRYLO0_D_SHF S_EntryLoD
#define C0_ENTRYLO0_D_MSK M_EntryLoD
#define C0_ENTRYLO0_V_SHF S_EntryLoV
#define C0_ENTRYLO0_V_MSK M_EntryLoV
#define C0_ENTRYLO0_G_SHF S_EntryLoG
#define C0_ENTRYLO0_G_MSK M_EntryLoG
/* FPU (CP1) FIR register encoding */
#define C1_FIR_3D_SHF S_FIRConfig3D
#define C1_FIR_3D_MSK M_FIRConfig3D
#define C1_FIR_PS_SHF S_FIRConfigPS
#define C1_FIR_PS_MSK M_FIRConfigPS
#define C1_FIR_D_SHF S_FIRConfigD
#define C1_FIR_D_MSK M_FIRConfigD
#define C1_FIR_S_SHF S_FIRConfigS
#define C1_FIR_S_MSK M_FIRConfigS
#define C1_FIR_PRID_SHF S_FIRImp
#define C1_FIR_PRID_MSK M_FIRImp
#define C1_FIR_REV_SHF S_FIRRev
#define C1_FIR_REV_MSK M_FIRRev
/* FPU (CP1) FCSR control/status register */
#define C1_FCSR_FCC_SHF S_FCSRFCC7_1
#define C1_FCSR_FCC_MSK M_FCSRFCC7_1
#define C1_FCSR_FS_SHF S_FCSRFS
#define C1_FCSR_FS_MSK M_FCSRFS
#define C1_FCSR_FS_BIT C1_FCSR_FS_MSK
#define C1_FCSR_CC_SHF S_FCSRCC
#define C1_FCSR_CC_MSK M_FCSRCC
#define C1_FCSR_IMPL_SHF S_FCSRImpl
#define C1_FCSR_IMPL_MSK M_FCSRImpl
#define C1_FCSR_EXC_SHF S_FCSRExc
#define C1_FCSR_EXC_MSK M_FCSRExc
#define C1_FCSR_ENA_SHF S_FCSREna
#define C1_FCSR_ENA_MSK M_FCSREna
#define C1_FCSR_FLG_SHF S_FCSRFlg
#define C1_FCSR_FLG_MSK M_FCSRFlg
#define C1_FCSR_RM_SHF S_FCSRRM
#define C1_FCSR_RM_MSK M_FCSRRM
#define C1_FCSR_RM_RN K_FCSRRM_RN
#define C1_FCSR_RM_RZ K_FCSRRM_RZ
#define C1_FCSR_RM_RP K_FCSRRM_RP
#define C1_FCSR_RM_RM K_FCSRRM_RM
/* cache operations */
#define CACHE_OP( code, type ) ( ((code) << 2) | (type) )
#define ICACHE_INDEX_INVALIDATE CACHE_OP(0x0, 0)
#define ICACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 0)
#define ICACHE_INDEX_STORE_TAG CACHE_OP(0x2, 0)
#define DCACHE_INDEX_WRITEBACK_INVALIDATE CACHE_OP(0x0, 1)
#define DCACHE_INDEX_LOAD_TAG CACHE_OP(0x1, 1)
#define DCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 1)
#define SCACHE_INDEX_STORE_TAG CACHE_OP(0x2, 3)
#define ICACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 0)
#define ICACHE_ADDR_FILL CACHE_OP(0x5, 0)
#define ICACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 0)
#define DCACHE_ADDR_HIT_INVALIDATE CACHE_OP(0x4, 1)
#define DCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 1)
#define DCACHE_ADDR_HIT_WRITEBACK CACHE_OP(0x6, 1)
#define DCACHE_ADDR_FETCH_LOCK CACHE_OP(0x7, 1)
#define SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE CACHE_OP(0x5, 3)
/* Workaround for bug in early revisions of MIPS 4K family of
* processors. Only relevant in early engineering samples of test
* chips (RTL revision <= 3.0).
*
* The bug is described in :
*
* MIPS32 4K(tm) Processor Core Family RTL Errata Sheet
* MIPS Document No: MD00003
*
* The bug is identified as : C16
*/
#ifndef SET_MIPS0
#define SET_MIPS0()
#define SET_PUSH()
#define SET_POP()
#endif
#define ICACHE_INVALIDATE_WORKAROUND(reg) \
SET_PUSH(); \
SET_MIPS0(); \
la reg, 999f; \
SET_POP(); \
cache ICACHE_ADDR_FILL, 0(reg); \
sync; \
nop; nop; nop; nop; \
999:
/* EMPTY_PIPELINE is used for the below cache invalidation operations.
* When $I is invalidated, there will still be operations in the
* pipeline. We make sure these are 'nop' operations.
*/
#define EMPTY_PIPELINE nop; nop; nop; nop
#define ICACHE_INDEX_INVALIDATE_OP(index,scratch) \
ICACHE_INVALIDATE_WORKAROUND(scratch); \
cache ICACHE_INDEX_INVALIDATE, 0(index); \
EMPTY_PIPELINE
#define ICACHE_ADDR_INVALIDATE_OP(addr,scratch) \
ICACHE_INVALIDATE_WORKAROUND(scratch); \
cache ICACHE_ADDR_HIT_INVALIDATE, 0(addr); \
EMPTY_PIPELINE
/* The sync used in the below macro is there in case we are installing
* a new instruction (flush $D, sync, invalidate $I sequence).
*/
#define SCACHE_ADDR_HIT_WB_INVALIDATE_OP(reg) \
cache SCACHE_ADDR_HIT_WRITEBACK_INVALIDATE, 0(reg); \
sync; \
EMPTY_PIPELINE
/* Config1 cache field decoding */
#define CACHE_CALC_SPW(s) ( 64 << (s) )
#define CACHE_CALC_LS(l) ( (l) ? 2 << (l) : 0 )
#define CACHE_CALC_BPW(l,s) ( CACHE_CALC_LS(l) * CACHE_CALC_SPW(s) )
#define CACHE_CALC_ASSOC(a) ( (a) + 1 )
/**** Move from/to Coprocessor operations ****/
/* We use ssnop instead of nop operations in order to handle
* superscalar CPUs.
* The "sll zero,zero,1" notation is compiler backwards compatible.
*/
#define SSNOP sll zero,zero,1
#define NOPS SSNOP; SSNOP; SSNOP; SSNOP
#define MFLO(dst) \
mflo dst;\
NOPS
/* Workaround for bug in early revisions of MIPS 4K family of
* processors.
*
* This concerns the nop instruction before mtc0 in the
* MTC0 macro below.
*
* The bug is described in :
*
* MIPS32 4K(tm) Processor Core Family RTL Errata Sheet
* MIPS Document No: MD00003
*
* The bug is identified as : C27
*/
#define MTC0(src, dst) \
nop; \
mtc0 src,dst;\
NOPS
#define DMTC0(src, dst) \
nop; \
dmtc0 src,dst;\
NOPS
#define MFC0(dst, src) \
mfc0 dst,src;\
NOPS
#define DMFC0(dst, src) \
dmfc0 dst,src;\
NOPS
#define MFC0_SEL_OPCODE(dst, src, sel)\
.##word (0x40000000 | ((dst)<<16) | ((src)<<11) | (sel));\
NOPS
#define MTC0_SEL_OPCODE(dst, src, sel)\
.##word (0x40800000 | ((dst)<<16) | ((src)<<11) | (sel));\
NOPS
#define LDC1(dst, src, offs)\
.##word (0xd4000000 | ((src)<<21) | ((dst)<<16) | (offs))
#define SDC1(src, dst, offs)\
.##word (0xf4000000 | ((dst)<<21) | ((src)<<16) | (offs))
/* Instruction opcode fields */
#define OPC_SPECIAL 0x0
#define OPC_REGIM 0x1
#define OPC_J 0x2
#define OPC_JAL 0x3
#define OPC_BEQ 0x4
#define OPC_BNE 0x5
#define OPC_BLEZ 0x6
#define OPC_BGTZ 0x7
#define OPC_COP1 0x11
#define OPC_JALX 0x1D
#define OPC_BEQL 0x14
#define OPC_BNEL 0x15
#define OPC_BLEZL 0x16
#define OPC_BGTZL 0x17
/* Instruction function fields */
#define FUNC_JR 0x8
#define FUNC_JALR 0x9
/* Instruction rt fields */
#define RT_BLTZ 0x0
#define RT_BGEZ 0x1
#define RT_BLTZL 0x2
#define RT_BGEZL 0x3
#define RT_BLTZAL 0x10
#define RT_BGEZAL 0x11
#define RT_BLTZALL 0x12
#define RT_BGEZALL 0x13
/* Instruction rs fields */
#define RS_BC1 0x08
/* Access macros for instruction fields */
#define MIPS_OPCODE( instr) ((instr) >> 26)
#define MIPS_FUNCTION(instr) ((instr) & MSK(6))
#define MIPS_RT(instr) (((instr) >> 16) & MSK(5))
#define MIPS_RS(instr) (((instr) >> 21) & MSK(5))
#define MIPS_OFFSET(instr) ((instr) & 0xFFFF)
#define MIPS_TARGET(instr) ((instr) & MSK(26))
/* Instructions */
#define OPCODE_DERET 0x4200001f
#define OPCODE_BREAK 0x0005000d
#define OPCODE_NOP 0
#define OPCODE_JUMP(addr) ( (OPC_J << 26) | (((addr) >> 2) & 0x3FFFFFF) )
#define DERET .##word OPCODE_DERET
/* MIPS16e opcodes and instruction field access macros */
#define MIPS16E_OPCODE(inst) (((inst) >> 11) & 0x1f)
#define MIPS16E_I8_FUNCTION(inst) (((inst) >> 8) & 0x7)
#define MIPS16E_X(inst) (((inst) >> 26) & 0x1)
#define MIPS16E_RR_FUNCTION(inst) (((inst) >> 0) & 0x1f)
#define MIPS16E_RY(inst) (((inst) >> 5) & 0x3)
#define MIPS16E_OPC_EXTEND 0x1e
#define MIPS16E_OPC_JAL_X 0x03
#define MIPS16E_OPC_B 0x02
#define MIPS16E_OPC_BEQZ 0x04
#define MIPS16E_OPC_BNEZ 0x05
#define MIPS16E_OPC_I8 0x0c
#define MIPS16E_I8_FUNC_BTEQZ 0x00
#define MIPS16E_I8_FUNC_BTNEZ 0x01
#define MIPS16E_X_JALX 0x01
#define MIPS16E_OPC_RR 0x1d
#define MIPS16E_RR_FUNC_JALRC 0x00
#define MIPS16E_RR_RY_JRRX 0x00
#define MIPS16E_RR_RY_JRRA 0x01
#define MIPS16E_RR_RY_JALR 0x02
#define MIPS16E_RR_RY_JRCRX 0x04
#define MIPS16E_RR_RY_JRCRA 0x05
#define MIPS16E_RR_RY_JALRC 0x06
#define MIPS16E_OPCODE_BREAK 0xE805
#define MIPS16E_OPCODE_NOP 0x6500
/* MIPS reset vector */
#define MIPS_RESET_VECTOR 0x1fc00000
/* Clock periods per count register increment */
#define MIPS4K_COUNT_CLK_PER_CYCLE 2
#define MIPS5K_COUNT_CLK_PER_CYCLE 2
#define MIPS20Kc_COUNT_CLK_PER_CYCLE 1
/**** MIPS 4K/5K families specific fields of CONFIG register ****/
#define C0_CONFIG_MIPS4K5K_K23_SHF S_ConfigK23
#define C0_CONFIG_MIPS4K5K_K23_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_K23_SHF)
#define C0_CONFIG_MIPS4K5K_KU_SHF S_ConfigKU
#define C0_CONFIG_MIPS4K5K_KU_MSK (MSK(3) << C0_CONFIG_MIPS4K5K_KU_SHF)
/**** MIPS 20Kc specific fields of CONFIG register ****/
#define C0_CONFIG_MIPS20KC_EC_SHF 28
#define C0_CONFIG_MIPS20KC_EC_MSK (MSK(3) << C0_CONFIG_MIPS20KC_EC_SHF)
#define C0_CONFIG_MIPS20KC_DD_SHF 27
#define C0_CONFIG_MIPS20KC_DD_MSK (MSK(1) << C0_CONFIG_MIPS20KC_DD_SHF)
#define C0_CONFIG_MIPS20KC_DD_BIT C0_CONFIG_MIPS20KC_DD_MSK
#define C0_CONFIG_MIPS20KC_LP_SHF 26
#define C0_CONFIG_MIPS20KC_LP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_LP_SHF)
#define C0_CONFIG_MIPS20KC_LP_BIT C0_CONFIG_MIPS20KC_LP_MSK
#define C0_CONFIG_MIPS20KC_SP_SHF 25
#define C0_CONFIG_MIPS20KC_SP_MSK (MSK(1) << C0_CONFIG_MIPS20KC_SP_SHF)
#define C0_CONFIG_MIPS20KC_SP_BIT C0_CONFIG_MIPS20KC_SP_MSK
#define C0_CONFIG_MIPS20KC_TI_SHF 24
#define C0_CONFIG_MIPS20KC_TI_MSK (MSK(1) << C0_CONFIG_MIPS20KC_TI_SHF)
#define C0_CONFIG_MIPS20KC_TI_BIT C0_CONFIG_MIPS20KC_TI_MSK
/* ********************************************************************* */
/* Interface function definition */
/* ********************************************************************* */
#endif /* #ifndef __MIPS_H__ */

View File

@@ -0,0 +1,985 @@
/*
* 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 (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle
* Copyright (C) 2000 Silicon Graphics, Inc.
* Modified for further R[236]000 support by Paul M. Antoine, 1996.
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
* Copyright (C) 2003 Maciej W. Rozycki
*/
#ifndef _ASM_MIPSREGS_H
#define _ASM_MIPSREGS_H
#include <linux/config.h>
#include <linux/linkage.h>
/*
* The following macros are especially useful for __asm__
* inline assembler.
*/
#ifndef __STR
#define __STR(x) #x
#endif
#ifndef STR
#define STR(x) __STR(x)
#endif
/*
* Configure language
*/
#ifdef __ASSEMBLY__
#define _ULCAST_
#else
#define _ULCAST_ (unsigned long)
#endif
/*
* Coprocessor 0 register names
*/
#define CP0_INDEX $0
#define CP0_RANDOM $1
#define CP0_ENTRYLO0 $2
#define CP0_ENTRYLO1 $3
#define CP0_CONF $3
#define CP0_CONTEXT $4
#define CP0_PAGEMASK $5
#define CP0_WIRED $6
#define CP0_INFO $7
#define CP0_BADVADDR $8
#define CP0_COUNT $9
#define CP0_ENTRYHI $10
#define CP0_COMPARE $11
#define CP0_STATUS $12
#define CP0_CAUSE $13
#define CP0_EPC $14
#define CP0_PRID $15
#define CP0_CONFIG $16
#define CP0_LLADDR $17
#define CP0_WATCHLO $18
#define CP0_WATCHHI $19
#define CP0_XCONTEXT $20
#define CP0_FRAMEMASK $21
#define CP0_DIAGNOSTIC $22
#define CP0_DEBUG $23
#define CP0_DEPC $24
#define CP0_PERFORMANCE $25
#define CP0_ECC $26
#define CP0_CACHEERR $27
#define CP0_TAGLO $28
#define CP0_TAGHI $29
#define CP0_ERROREPC $30
#define CP0_DESAVE $31
/*
* R4640/R4650 cp0 register names. These registers are listed
* here only for completeness; without MMU these CPUs are not useable
* by Linux. A future ELKS port might take make Linux run on them
* though ...
*/
#define CP0_IBASE $0
#define CP0_IBOUND $1
#define CP0_DBASE $2
#define CP0_DBOUND $3
#define CP0_CALG $17
#define CP0_IWATCH $18
#define CP0_DWATCH $19
/*
* Coprocessor 0 Set 1 register names
*/
#define CP0_S1_DERRADDR0 $26
#define CP0_S1_DERRADDR1 $27
#define CP0_S1_INTCONTROL $20
/*
* TX39 Series
*/
#define CP0_TX39_CACHE $7
/*
* Coprocessor 1 (FPU) register names
*/
#define CP1_REVISION $0
#define CP1_STATUS $31
/*
* FPU Status Register Values
*/
/*
* Status Register Values
*/
#define FPU_CSR_FLUSH 0x01000000 /* flush denormalised results to 0 */
#define FPU_CSR_COND 0x00800000 /* $fcc0 */
#define FPU_CSR_COND0 0x00800000 /* $fcc0 */
#define FPU_CSR_COND1 0x02000000 /* $fcc1 */
#define FPU_CSR_COND2 0x04000000 /* $fcc2 */
#define FPU_CSR_COND3 0x08000000 /* $fcc3 */
#define FPU_CSR_COND4 0x10000000 /* $fcc4 */
#define FPU_CSR_COND5 0x20000000 /* $fcc5 */
#define FPU_CSR_COND6 0x40000000 /* $fcc6 */
#define FPU_CSR_COND7 0x80000000 /* $fcc7 */
/*
* X the exception cause indicator
* E the exception enable
* S the sticky/flag bit
*/
#define FPU_CSR_ALL_X 0x0003f000
#define FPU_CSR_UNI_X 0x00020000
#define FPU_CSR_INV_X 0x00010000
#define FPU_CSR_DIV_X 0x00008000
#define FPU_CSR_OVF_X 0x00004000
#define FPU_CSR_UDF_X 0x00002000
#define FPU_CSR_INE_X 0x00001000
#define FPU_CSR_ALL_E 0x00000f80
#define FPU_CSR_INV_E 0x00000800
#define FPU_CSR_DIV_E 0x00000400
#define FPU_CSR_OVF_E 0x00000200
#define FPU_CSR_UDF_E 0x00000100
#define FPU_CSR_INE_E 0x00000080
#define FPU_CSR_ALL_S 0x0000007c
#define FPU_CSR_INV_S 0x00000040
#define FPU_CSR_DIV_S 0x00000020
#define FPU_CSR_OVF_S 0x00000010
#define FPU_CSR_UDF_S 0x00000008
#define FPU_CSR_INE_S 0x00000004
/* rounding mode */
#define FPU_CSR_RN 0x0 /* nearest */
#define FPU_CSR_RZ 0x1 /* towards zero */
#define FPU_CSR_RU 0x2 /* towards +Infinity */
#define FPU_CSR_RD 0x3 /* towards -Infinity */
/*
* Values for PageMask register
*/
#ifdef CONFIG_CPU_VR41XX
/* Why doesn't stupidity hurt ... */
#define PM_1K 0x00000000
#define PM_4K 0x00001800
#define PM_16K 0x00007800
#define PM_64K 0x0001f800
#define PM_256K 0x0007f800
#else
#define PM_4K 0x00000000
#define PM_16K 0x00006000
#define PM_64K 0x0001e000
#define PM_256K 0x0007e000
#define PM_1M 0x001fe000
#define PM_4M 0x007fe000
#define PM_16M 0x01ffe000
#define PM_64M 0x07ffe000
#define PM_256M 0x1fffe000
#endif
/*
* Values used for computation of new tlb entries
*/
#define PL_4K 12
#define PL_16K 14
#define PL_64K 16
#define PL_256K 18
#define PL_1M 20
#define PL_4M 22
#define PL_16M 24
#define PL_64M 26
#define PL_256M 28
/*
* R4x00 interrupt enable / cause bits
*/
#define IE_SW0 (_ULCAST_(1) << 8)
#define IE_SW1 (_ULCAST_(1) << 9)
#define IE_IRQ0 (_ULCAST_(1) << 10)
#define IE_IRQ1 (_ULCAST_(1) << 11)
#define IE_IRQ2 (_ULCAST_(1) << 12)
#define IE_IRQ3 (_ULCAST_(1) << 13)
#define IE_IRQ4 (_ULCAST_(1) << 14)
#define IE_IRQ5 (_ULCAST_(1) << 15)
/*
* R4x00 interrupt cause bits
*/
#define C_SW0 (_ULCAST_(1) << 8)
#define C_SW1 (_ULCAST_(1) << 9)
#define C_IRQ0 (_ULCAST_(1) << 10)
#define C_IRQ1 (_ULCAST_(1) << 11)
#define C_IRQ2 (_ULCAST_(1) << 12)
#define C_IRQ3 (_ULCAST_(1) << 13)
#define C_IRQ4 (_ULCAST_(1) << 14)
#define C_IRQ5 (_ULCAST_(1) << 15)
/*
* Bitfields in the R4xx0 cp0 status register
*/
#define ST0_IE 0x00000001
#define ST0_EXL 0x00000002
#define ST0_ERL 0x00000004
#define ST0_KSU 0x00000018
# define KSU_USER 0x00000010
# define KSU_SUPERVISOR 0x00000008
# define KSU_KERNEL 0x00000000
#define ST0_UX 0x00000020
#define ST0_SX 0x00000040
#define ST0_KX 0x00000080
#define ST0_DE 0x00010000
#define ST0_CE 0x00020000
/*
* Bitfields in the R[23]000 cp0 status register.
*/
#define ST0_IEC 0x00000001
#define ST0_KUC 0x00000002
#define ST0_IEP 0x00000004
#define ST0_KUP 0x00000008
#define ST0_IEO 0x00000010
#define ST0_KUO 0x00000020
/* bits 6 & 7 are reserved on R[23]000 */
#define ST0_ISC 0x00010000
#define ST0_SWC 0x00020000
#define ST0_CM 0x00080000
/*
* Bits specific to the R4640/R4650
*/
#define ST0_UM (_ULCAST_(1) << 4)
#define ST0_IL (_ULCAST_(1) << 23)
#define ST0_DL (_ULCAST_(1) << 24)
/*
* Bitfields in the TX39 family CP0 Configuration Register 3
*/
#define TX39_CONF_ICS_SHIFT 19
#define TX39_CONF_ICS_MASK 0x00380000
#define TX39_CONF_ICS_1KB 0x00000000
#define TX39_CONF_ICS_2KB 0x00080000
#define TX39_CONF_ICS_4KB 0x00100000
#define TX39_CONF_ICS_8KB 0x00180000
#define TX39_CONF_ICS_16KB 0x00200000
#define TX39_CONF_DCS_SHIFT 16
#define TX39_CONF_DCS_MASK 0x00070000
#define TX39_CONF_DCS_1KB 0x00000000
#define TX39_CONF_DCS_2KB 0x00010000
#define TX39_CONF_DCS_4KB 0x00020000
#define TX39_CONF_DCS_8KB 0x00030000
#define TX39_CONF_DCS_16KB 0x00040000
#define TX39_CONF_CWFON 0x00004000
#define TX39_CONF_WBON 0x00002000
#define TX39_CONF_RF_SHIFT 10
#define TX39_CONF_RF_MASK 0x00000c00
#define TX39_CONF_DOZE 0x00000200
#define TX39_CONF_HALT 0x00000100
#define TX39_CONF_LOCK 0x00000080
#define TX39_CONF_ICE 0x00000020
#define TX39_CONF_DCE 0x00000010
#define TX39_CONF_IRSIZE_SHIFT 2
#define TX39_CONF_IRSIZE_MASK 0x0000000c
#define TX39_CONF_DRSIZE_SHIFT 0
#define TX39_CONF_DRSIZE_MASK 0x00000003
/*
* Status register bits available in all MIPS CPUs.
*/
#define ST0_IM 0x0000ff00
#define STATUSB_IP0 8
#define STATUSF_IP0 (_ULCAST_(1) << 8)
#define STATUSB_IP1 9
#define STATUSF_IP1 (_ULCAST_(1) << 9)
#define STATUSB_IP2 10
#define STATUSF_IP2 (_ULCAST_(1) << 10)
#define STATUSB_IP3 11
#define STATUSF_IP3 (_ULCAST_(1) << 11)
#define STATUSB_IP4 12
#define STATUSF_IP4 (_ULCAST_(1) << 12)
#define STATUSB_IP5 13
#define STATUSF_IP5 (_ULCAST_(1) << 13)
#define STATUSB_IP6 14
#define STATUSF_IP6 (_ULCAST_(1) << 14)
#define STATUSB_IP7 15
#define STATUSF_IP7 (_ULCAST_(1) << 15)
#define STATUSB_IP8 0
#define STATUSF_IP8 (_ULCAST_(1) << 0)
#define STATUSB_IP9 1
#define STATUSF_IP9 (_ULCAST_(1) << 1)
#define STATUSB_IP10 2
#define STATUSF_IP10 (_ULCAST_(1) << 2)
#define STATUSB_IP11 3
#define STATUSF_IP11 (_ULCAST_(1) << 3)
#define STATUSB_IP12 4
#define STATUSF_IP12 (_ULCAST_(1) << 4)
#define STATUSB_IP13 5
#define STATUSF_IP13 (_ULCAST_(1) << 5)
#define STATUSB_IP14 6
#define STATUSF_IP14 (_ULCAST_(1) << 6)
#define STATUSB_IP15 7
#define STATUSF_IP15 (_ULCAST_(1) << 7)
#define ST0_CH 0x00040000
#define ST0_SR 0x00100000
#define ST0_TS 0x00200000
#define ST0_BEV 0x00400000
#define ST0_RE 0x02000000
#define ST0_FR 0x04000000
#define ST0_CU 0xf0000000
#define ST0_CU0 0x10000000
#define ST0_CU1 0x20000000
#define ST0_CU2 0x40000000
#define ST0_CU3 0x80000000
#define ST0_XX 0x80000000 /* MIPS IV naming */
/*
* Bitfields and bit numbers in the coprocessor 0 cause register.
*
* Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
*/
#define CAUSEB_EXCCODE 2
#define CAUSEF_EXCCODE (_ULCAST_(31) << 2)
#define CAUSEB_IP 8
#define CAUSEF_IP (_ULCAST_(255) << 8)
#define CAUSEB_IP0 8
#define CAUSEF_IP0 (_ULCAST_(1) << 8)
#define CAUSEB_IP1 9
#define CAUSEF_IP1 (_ULCAST_(1) << 9)
#define CAUSEB_IP2 10
#define CAUSEF_IP2 (_ULCAST_(1) << 10)
#define CAUSEB_IP3 11
#define CAUSEF_IP3 (_ULCAST_(1) << 11)
#define CAUSEB_IP4 12
#define CAUSEF_IP4 (_ULCAST_(1) << 12)
#define CAUSEB_IP5 13
#define CAUSEF_IP5 (_ULCAST_(1) << 13)
#define CAUSEB_IP6 14
#define CAUSEF_IP6 (_ULCAST_(1) << 14)
#define CAUSEB_IP7 15
#define CAUSEF_IP7 (_ULCAST_(1) << 15)
#define CAUSEB_IV 23
#define CAUSEF_IV (_ULCAST_(1) << 23)
#define CAUSEB_CE 28
#define CAUSEF_CE (_ULCAST_(3) << 28)
#define CAUSEB_BD 31
#define CAUSEF_BD (_ULCAST_(1) << 31)
/*
* Bits in the coprocessor 0 config register.
*/
/* Generic bits. */
#define CONF_CM_CACHABLE_NO_WA 0
#define CONF_CM_CACHABLE_WA 1
#define CONF_CM_UNCACHED 2
#define CONF_CM_CACHABLE_NONCOHERENT 3
#define CONF_CM_CACHABLE_CE 4
#define CONF_CM_CACHABLE_COW 5
#define CONF_CM_CACHABLE_CUW 6
#define CONF_CM_CACHABLE_ACCELERATED 7
#define CONF_CM_CMASK 7
#define CONF_BE (_ULCAST_(1) << 15)
/* Bits common to various processors. */
#define CONF_CU (_ULCAST_(1) << 3)
#define CONF_DB (_ULCAST_(1) << 4)
#define CONF_IB (_ULCAST_(1) << 5)
#define CONF_DC (_ULCAST_(7) << 6)
#define CONF_IC (_ULCAST_(7) << 9)
#define CONF_EB (_ULCAST_(1) << 13)
#define CONF_EM (_ULCAST_(1) << 14)
#define CONF_SM (_ULCAST_(1) << 16)
#define CONF_SC (_ULCAST_(1) << 17)
#define CONF_EW (_ULCAST_(3) << 18)
#define CONF_EP (_ULCAST_(15)<< 24)
#define CONF_EC (_ULCAST_(7) << 28)
#define CONF_CM (_ULCAST_(1) << 31)
/* Bits specific to the R4xx0. */
#define R4K_CONF_SW (_ULCAST_(1) << 20)
#define R4K_CONF_SS (_ULCAST_(1) << 21)
#define R4K_CONF_SB (_ULCAST_(3) << 22)
/* Bits specific to the R5000. */
#define R5K_CONF_SE (_ULCAST_(1) << 12)
#define R5K_CONF_SS (_ULCAST_(3) << 20)
/* Bits specific to the R10000. */
#define R10K_CONF_DN (_ULCAST_(3) << 3)
#define R10K_CONF_CT (_ULCAST_(1) << 5)
#define R10K_CONF_PE (_ULCAST_(1) << 6)
#define R10K_CONF_PM (_ULCAST_(3) << 7)
#define R10K_CONF_EC (_ULCAST_(15)<< 9)
#define R10K_CONF_SB (_ULCAST_(1) << 13)
#define R10K_CONF_SK (_ULCAST_(1) << 14)
#define R10K_CONF_SS (_ULCAST_(7) << 16)
#define R10K_CONF_SC (_ULCAST_(7) << 19)
#define R10K_CONF_DC (_ULCAST_(7) << 26)
#define R10K_CONF_IC (_ULCAST_(7) << 29)
/* Bits specific to the VR41xx. */
#define VR41_CONF_CS (_ULCAST_(1) << 12)
#define VR41_CONF_M16 (_ULCAST_(1) << 20)
#define VR41_CONF_AD (_ULCAST_(1) << 23)
/* Bits specific to the R30xx. */
#define R30XX_CONF_FDM (_ULCAST_(1) << 19)
#define R30XX_CONF_REV (_ULCAST_(1) << 22)
#define R30XX_CONF_AC (_ULCAST_(1) << 23)
#define R30XX_CONF_RF (_ULCAST_(1) << 24)
#define R30XX_CONF_HALT (_ULCAST_(1) << 25)
#define R30XX_CONF_FPINT (_ULCAST_(7) << 26)
#define R30XX_CONF_DBR (_ULCAST_(1) << 29)
#define R30XX_CONF_SB (_ULCAST_(1) << 30)
#define R30XX_CONF_LOCK (_ULCAST_(1) << 31)
/* Bits specific to the TX49. */
#define TX49_CONF_DC (_ULCAST_(1) << 16)
#define TX49_CONF_IC (_ULCAST_(1) << 17) /* conflict with CONF_SC */
#define TX49_CONF_HALT (_ULCAST_(1) << 18)
#define TX49_CONF_CWFON (_ULCAST_(1) << 27)
/* Bits specific to the MIPS32/64 PRA. */
#define MIPS_CONF_MT (_ULCAST_(7) << 7)
#define MIPS_CONF_AR (_ULCAST_(7) << 10)
#define MIPS_CONF_AT (_ULCAST_(3) << 13)
#define MIPS_CONF_M (_ULCAST_(1) << 31)
/*
* R10000 performance counter definitions.
*
* FIXME: The R10000 performance counter opens a nice way to implement CPU
* time accounting with a precission of one cycle. I don't have
* R10000 silicon but just a manual, so ...
*/
/*
* Events counted by counter #0
*/
#define CE0_CYCLES 0
#define CE0_INSN_ISSUED 1
#define CE0_LPSC_ISSUED 2
#define CE0_S_ISSUED 3
#define CE0_SC_ISSUED 4
#define CE0_SC_FAILED 5
#define CE0_BRANCH_DECODED 6
#define CE0_QW_WB_SECONDARY 7
#define CE0_CORRECTED_ECC_ERRORS 8
#define CE0_ICACHE_MISSES 9
#define CE0_SCACHE_I_MISSES 10
#define CE0_SCACHE_I_WAY_MISSPREDICTED 11
#define CE0_EXT_INTERVENTIONS_REQ 12
#define CE0_EXT_INVALIDATE_REQ 13
#define CE0_VIRTUAL_COHERENCY_COND 14
#define CE0_INSN_GRADUATED 15
/*
* Events counted by counter #1
*/
#define CE1_CYCLES 0
#define CE1_INSN_GRADUATED 1
#define CE1_LPSC_GRADUATED 2
#define CE1_S_GRADUATED 3
#define CE1_SC_GRADUATED 4
#define CE1_FP_INSN_GRADUATED 5
#define CE1_QW_WB_PRIMARY 6
#define CE1_TLB_REFILL 7
#define CE1_BRANCH_MISSPREDICTED 8
#define CE1_DCACHE_MISS 9
#define CE1_SCACHE_D_MISSES 10
#define CE1_SCACHE_D_WAY_MISSPREDICTED 11
#define CE1_EXT_INTERVENTION_HITS 12
#define CE1_EXT_INVALIDATE_REQ 13
#define CE1_SP_HINT_TO_CEXCL_SC_BLOCKS 14
#define CE1_SP_HINT_TO_SHARED_SC_BLOCKS 15
/*
* These flags define in which priviledge mode the counters count events
*/
#define CEB_USER 8 /* Count events in user mode, EXL = ERL = 0 */
#define CEB_SUPERVISOR 4 /* Count events in supvervisor mode EXL = ERL = 0 */
#define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */
#define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */
#ifndef __ASSEMBLY__
#define CAUSE_EXCCODE(x) ((CAUSEF_EXCCODE & (x->cp0_cause)) >> CAUSEB_EXCCODE)
#define CAUSE_EPC(x) (x->cp0_epc + (((x->cp0_cause & CAUSEF_BD) >> CAUSEB_BD) << 2))
/*
* Functions to access the r10k performance counter and control registers
*/
#define read_r10k_perf_cntr(counter) \
({ unsigned int __res; \
__asm__ __volatile__( \
"mfpc\t%0, "STR(counter) \
: "=r" (__res)); \
__res;})
#define write_r10k_perf_cntr(counter,val) \
__asm__ __volatile__( \
"mtpc\t%0, "STR(counter) \
: : "r" (val));
#define read_r10k_perf_cntl(counter) \
({ unsigned int __res; \
__asm__ __volatile__( \
"mfps\t%0, "STR(counter) \
: "=r" (__res)); \
__res;})
#define write_r10k_perf_cntl(counter,val) \
__asm__ __volatile__( \
"mtps\t%0, "STR(counter) \
: : "r" (val));
/*
* Macros to access the system control coprocessor
*/
#define __read_32bit_c0_register(source, sel) \
({ int __res; \
if (sel == 0) \
__asm__ __volatile__( \
"mfc0\t%0, " #source "\n\t" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mfc0\t%0, " #source ", " #sel "\n\t" \
".set\tmips0\n\t" \
: "=r" (__res)); \
__res; \
})
#define __read_64bit_c0_register(source, sel) \
({ unsigned long __res; \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips3\n\t" \
"dmfc0\t%0, " #source "\n\t" \
".set\tmips0" \
: "=r" (__res)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmfc0\t%0, " #source ", " #sel "\n\t" \
".set\tmips0" \
: "=r" (__res)); \
__res; \
})
#define __write_32bit_c0_register(register, sel, value) \
do { \
if (sel == 0) \
__asm__ __volatile__( \
"mtc0\t%z0, " #register "\n\t" \
: : "Jr" (value)); \
else \
__asm__ __volatile__( \
".set\tmips32\n\t" \
"mtc0\t%z0, " #register ", " #sel "\n\t" \
".set\tmips0" \
: : "Jr" (value)); \
} while (0)
#define __write_64bit_c0_register(register, sel, value) \
do { \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips3\n\t" \
"dmtc0\t%z0, " #register "\n\t" \
".set\tmips0" \
: : "Jr" (value)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmtc0\t%z0, " #register ", " #sel "\n\t" \
".set\tmips0" \
: : "Jr" (value)); \
} while (0)
#define __read_ulong_c0_register(reg, sel) \
((sizeof(unsigned long) == 4) ? \
__read_32bit_c0_register(reg, sel) : \
__read_64bit_c0_register(reg, sel))
#define __write_ulong_c0_register(reg, sel, val) \
do { \
if (sizeof(unsigned long) == 4) \
__write_32bit_c0_register(reg, sel, val); \
else \
__write_64bit_c0_register(reg, sel, val); \
} while (0)
/*
* These versions are only needed for systems with more than 38 bits of
* physical address space running the 32-bit kernel. That's none atm :-)
*/
#define __read_64bit_c0_split(source, sel) \
({ \
unsigned long long val; \
unsigned long flags; \
\
local_irq_save(flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmfc0\t%M0, " #source "\n\t" \
"dsll\t%L0, %M0, 32\n\t" \
"dsrl\t%M0, %M0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
".set\tmips0" \
: "=r" (val)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dmfc0\t%M0, " #source ", " #sel "\n\t" \
"dsll\t%L0, %M0, 32\n\t" \
"dsrl\t%M0, %M0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
".set\tmips0" \
: "=r" (val)); \
local_irq_restore(flags); \
\
val; \
})
#define __write_64bit_c0_split(source, sel, val) \
do { \
unsigned long flags; \
\
local_irq_save(flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dsll\t%L0, %L0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
"dsll\t%M0, %M0, 32\n\t" \
"or\t%L0, %L0, %M0\n\t" \
"dmtc0\t%L0, " #source "\n\t" \
".set\tmips0" \
: : "r" (val)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
"dsll\t%L0, %L0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
"dsll\t%M0, %M0, 32\n\t" \
"or\t%L0, %L0, %M0\n\t" \
"dmtc0\t%L0, " #source ", " #sel "\n\t" \
".set\tmips0" \
: : "r" (val)); \
local_irq_restore(flags); \
} while (0)
#define read_c0_index() __read_32bit_c0_register($0, 0)
#define write_c0_index(val) __write_32bit_c0_register($0, 0, val)
#define read_c0_entrylo0() __read_ulong_c0_register($2, 0)
#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val)
#define read_c0_entrylo1() __read_ulong_c0_register($3, 0)
#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val)
#define read_c0_conf() __read_32bit_c0_register($3, 0)
#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val)
#define read_c0_context() __read_ulong_c0_register($4, 0)
#define write_c0_context(val) __write_ulong_c0_register($4, 0, val)
#define read_c0_pagemask() __read_32bit_c0_register($5, 0)
#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val)
#define read_c0_wired() __read_32bit_c0_register($6, 0)
#define write_c0_wired(val) __write_32bit_c0_register($6, 0, val)
#define read_c0_info() __read_32bit_c0_register($7, 0)
#define read_c0_cache() __read_32bit_c0_register($7, 0) /* TX39xx */
#define write_c0_cache(val) __write_32bit_c0_register($7, 0, val)
#define read_c0_count() __read_32bit_c0_register($9, 0)
#define write_c0_count(val) __write_32bit_c0_register($9, 0, val)
#define read_c0_entryhi() __read_ulong_c0_register($10, 0)
#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val)
#define read_c0_compare() __read_32bit_c0_register($11, 0)
#define write_c0_compare(val) __write_32bit_c0_register($11, 0, val)
#define read_c0_status() __read_32bit_c0_register($12, 0)
#define write_c0_status(val) __write_32bit_c0_register($12, 0, val)
#define read_c0_cause() __read_32bit_c0_register($13, 0)
#define write_c0_cause(val) __write_32bit_c0_register($13, 0, val)
#define read_c0_prid() __read_32bit_c0_register($15, 0)
#define read_c0_config() __read_32bit_c0_register($16, 0)
#define read_c0_config1() __read_32bit_c0_register($16, 1)
#define read_c0_config2() __read_32bit_c0_register($16, 2)
#define read_c0_config3() __read_32bit_c0_register($16, 3)
#define write_c0_config(val) __write_32bit_c0_register($16, 0, val)
#define write_c0_config1(val) __write_32bit_c0_register($16, 1, val)
#define write_c0_config2(val) __write_32bit_c0_register($16, 2, val)
#define write_c0_config3(val) __write_32bit_c0_register($16, 3, val)
/*
* The WatchLo register. There may be upto 8 of them.
*/
#define read_c0_watchlo0() __read_ulong_c0_register($18, 0)
#define read_c0_watchlo1() __read_ulong_c0_register($18, 1)
#define read_c0_watchlo2() __read_ulong_c0_register($18, 2)
#define read_c0_watchlo3() __read_ulong_c0_register($18, 3)
#define read_c0_watchlo4() __read_ulong_c0_register($18, 4)
#define read_c0_watchlo5() __read_ulong_c0_register($18, 5)
#define read_c0_watchlo6() __read_ulong_c0_register($18, 6)
#define read_c0_watchlo7() __read_ulong_c0_register($18, 7)
#define write_c0_watchlo0(val) __write_ulong_c0_register($18, 0, val)
#define write_c0_watchlo1(val) __write_ulong_c0_register($18, 1, val)
#define write_c0_watchlo2(val) __write_ulong_c0_register($18, 2, val)
#define write_c0_watchlo3(val) __write_ulong_c0_register($18, 3, val)
#define write_c0_watchlo4(val) __write_ulong_c0_register($18, 4, val)
#define write_c0_watchlo5(val) __write_ulong_c0_register($18, 5, val)
#define write_c0_watchlo6(val) __write_ulong_c0_register($18, 6, val)
#define write_c0_watchlo7(val) __write_ulong_c0_register($18, 7, val)
/*
* The WatchHi register. There may be upto 8 of them.
*/
#define read_c0_watchhi0() __read_32bit_c0_register($19, 0)
#define read_c0_watchhi1() __read_32bit_c0_register($19, 1)
#define read_c0_watchhi2() __read_32bit_c0_register($19, 2)
#define read_c0_watchhi3() __read_32bit_c0_register($19, 3)
#define read_c0_watchhi4() __read_32bit_c0_register($19, 4)
#define read_c0_watchhi5() __read_32bit_c0_register($19, 5)
#define read_c0_watchhi6() __read_32bit_c0_register($19, 6)
#define read_c0_watchhi7() __read_32bit_c0_register($19, 7)
#define write_c0_watchhi0(val) __write_32bit_c0_register($19, 0, val)
#define write_c0_watchhi1(val) __write_32bit_c0_register($19, 1, val)
#define write_c0_watchhi2(val) __write_32bit_c0_register($19, 2, val)
#define write_c0_watchhi3(val) __write_32bit_c0_register($19, 3, val)
#define write_c0_watchhi4(val) __write_32bit_c0_register($19, 4, val)
#define write_c0_watchhi5(val) __write_32bit_c0_register($19, 5, val)
#define write_c0_watchhi6(val) __write_32bit_c0_register($19, 6, val)
#define write_c0_watchhi7(val) __write_32bit_c0_register($19, 7, val)
#define read_c0_xcontext() __read_ulong_c0_register($20, 0)
#define write_c0_xcontext(val) __write_ulong_c0_register($20, 0, val)
#define read_c0_intcontrol() __read_32bit_c0_register($20, 1)
#define write_c0_intcontrol(val) __write_32bit_c0_register($20, 1, val)
#define read_c0_framemask() __read_32bit_c0_register($21, 0)
#define write_c0_framemask(val) __write_32bit_c0_register($21, 0, val)
#define read_c0_debug() __read_32bit_c0_register($23, 0)
#define write_c0_debug(val) __write_32bit_c0_register($23, 0, val)
#define read_c0_depc() __read_ulong_c0_register($24, 0)
#define write_c0_depc(val) __write_ulong_c0_register($24, 0, val)
#define read_c0_ecc() __read_32bit_c0_register($26, 0)
#define write_c0_ecc(val) __write_32bit_c0_register($26, 0, val)
#define read_c0_derraddr0() __read_ulong_c0_register($26, 1)
#define write_c0_derraddr0(val) __write_ulong_c0_register($26, 1, val)
#define read_c0_cacheerr() __read_32bit_c0_register($27, 0)
#define read_c0_derraddr1() __read_ulong_c0_register($27, 1)
#define write_c0_derraddr1(val) __write_ulong_c0_register($27, 1, val)
#define read_c0_taglo() __read_32bit_c0_register($28, 0)
#define write_c0_taglo(val) __write_32bit_c0_register($28, 0, val)
#define read_c0_taghi() __read_32bit_c0_register($29, 0)
#define write_c0_taghi(val) __write_32bit_c0_register($29, 0, val)
#define read_c0_errorepc() __read_ulong_c0_register($30, 0)
#define write_c0_errorepc(val) __write_ulong_c0_register($30, 0, val)
#define read_c0_epc() __read_ulong_c0_register($14, 0)
#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val)
#if 1
/*
* Macros to access the system control coprocessor
*/
#define read_32bit_cp0_register(source) \
({ int __res; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set\treorder\n\t" \
"mfc0\t%0,"STR(source)"\n\t" \
".set\tpop" \
: "=r" (__res)); \
__res;})
#define read_32bit_cp0_set1_register(source) \
({ int __res; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set\treorder\n\t" \
"cfc0\t%0,"STR(source)"\n\t" \
".set\tpop" \
: "=r" (__res)); \
__res;})
/*
* For now use this only with interrupts disabled!
*/
#define read_64bit_cp0_register(source) \
({ int __res; \
__asm__ __volatile__( \
".set\tmips3\n\t" \
"dmfc0\t%0,"STR(source)"\n\t" \
".set\tmips0" \
: "=r" (__res)); \
__res;})
#define write_32bit_cp0_register(register,value) \
__asm__ __volatile__( \
"mtc0\t%0,"STR(register)"\n\t" \
"nop" \
: : "r" (value));
#define write_32bit_cp0_set1_register(register,value) \
__asm__ __volatile__( \
"ctc0\t%0,"STR(register)"\n\t" \
"nop" \
: : "r" (value));
#define write_64bit_cp0_register(register,value) \
__asm__ __volatile__( \
".set\tmips3\n\t" \
"dmtc0\t%0,"STR(register)"\n\t" \
".set\tmips0" \
: : "r" (value))
/*
* This should be changed when we get a compiler that support the MIPS32 ISA.
*/
#define read_mips32_cp0_config1() \
({ int __res; \
__asm__ __volatile__( \
".set\tnoreorder\n\t" \
".set\tnoat\n\t" \
"#.set\tmips64\n\t" \
"#mfc0\t$1, $16, 1\n\t" \
"#.set\tmips0\n\t" \
".word\t0x40018001\n\t" \
"move\t%0,$1\n\t" \
".set\tat\n\t" \
".set\treorder" \
:"=r" (__res)); \
__res;})
#endif
/*
* Macros to access the floating point coprocessor control registers
*/
#define read_32bit_cp1_register(source) \
({ int __res; \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set\treorder\n\t" \
"cfc1\t%0,"STR(source)"\n\t" \
".set\tpop" \
: "=r" (__res)); \
__res;})
/* TLB operations. */
static inline void tlb_probe(void)
{
__asm__ __volatile__(
".set noreorder\n\t"
"tlbp\n\t"
".set reorder");
}
static inline void tlb_read(void)
{
__asm__ __volatile__(
".set noreorder\n\t"
"tlbr\n\t"
".set reorder");
}
static inline void tlb_write_indexed(void)
{
__asm__ __volatile__(
".set noreorder\n\t"
"tlbwi\n\t"
".set reorder");
}
static inline void tlb_write_random(void)
{
__asm__ __volatile__(
".set noreorder\n\t"
"tlbwr\n\t"
".set reorder");
}
/*
* Manipulate bits in a c0 register.
*/
#define __BUILD_SET_C0(name,register) \
static inline unsigned int \
set_c0_##name(unsigned int set) \
{ \
unsigned int res; \
\
res = read_c0_##name(); \
res |= set; \
write_c0_##name(res); \
\
return res; \
} \
\
static inline unsigned int \
clear_c0_##name(unsigned int clear) \
{ \
unsigned int res; \
\
res = read_c0_##name(); \
res &= ~clear; \
write_c0_##name(res); \
\
return res; \
} \
\
static inline unsigned int \
change_c0_##name(unsigned int change, unsigned int new) \
{ \
unsigned int res; \
\
res = read_c0_##name(); \
res &= ~change; \
res |= (new & change); \
write_c0_##name(res); \
\
return res; \
}
__BUILD_SET_C0(status,CP0_STATUS)
__BUILD_SET_C0(cause,CP0_CAUSE)
__BUILD_SET_C0(config,CP0_CONFIG)
#define set_cp0_status(x) set_c0_status(x)
#define set_cp0_cause(x) set_c0_cause(x)
#define set_cp0_config(x) set_c0_config(x)
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_MIPSREGS_H */

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#ifndef __NANDLIB_H__
#define __NANDLIB_H__
#include "xburst_types.h"
#ifndef NULL
#define NULL 0
#endif
/* Jz4740 nandflash interface */
unsigned int nand_query_4740(u8 *);
int nand_init_4740(int bus_width, int row_cycle, int page_size, int page_per_block,
int,int,int,int);
int nand_fini_4740(void);
u32 nand_program_4740(void *context, int spage, int pages, int option);
//int nand_program_oob_4740(void *context, int spage, int pages, void (*notify)(int));
u32 nand_erase_4740(int blk_num, int sblk, int force);
u32 nand_read_4740(void *buf, u32 startpage, u32 pagenum,int option);
u32 nand_read_oob_4740(void *buf, u32 startpage, u32 pagenum);
u32 nand_read_raw_4740(void *buf, u32 startpage, u32 pagenum,int);
u32 nand_mark_bad_4740(int bad);
void nand_enable_4740(u32 csn);
void nand_disable_4740(u32 csn);
/* Jz4750 nandflash interface */
unsigned int nand_query_4750(u8 *);
//int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
// int,int,int,int);
int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force);
int nand_fini_4750(void);
u32 nand_program_4750(void *context, int spage, int pages, int option);
//int nand_program_oob_4740(void *context, int spage, int pages, void (*notify)(int));
u32 nand_erase_4750(int blk_num, int sblk, int force);
u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum,int option);
u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum);
u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum,int);
u32 nand_mark_bad_4750(int bad);
void nand_enable_4750(u32 csn);
void nand_disable_4750(u32 csn);
#endif

View File

@@ -0,0 +1,442 @@
/**************************************************************************
* *
* PROJECT : MIPS port for uC/OS-II *
* *
* MODULE : SYSDEFS.h *
* *
* AUTHOR : Michael Anburaj *
* URL : http://geocities.com/michaelanburaj/ *
* EMAIL: michaelanburaj@hotmail.com *
* *
* PROCESSOR : MIPS 4Kc (32 bit RISC) - ATLAS board *
* *
* TOOL-CHAIN : SDE & Cygnus *
* *
* DESCRIPTION : *
* System definitions header file. *
* *
**************************************************************************/
#ifndef __SYSDEFS_H__
#define __SYSDEFS_H__
/* ********************************************************************* */
/* Module configuration */
/* ********************************************************************* */
/* Interface macro & data definition */
#ifdef _ASSEMBLER_
/******** ASSEMBLER SPECIFIC DEFINITIONS ********/
#ifdef __ghs__
#define ALIGN(x) .##align (1 << (x))
#else
#define ALIGN(x) .##align (x)
#endif
#ifdef __ghs__
#define SET_MIPS3()
#define SET_MIPS0()
#define SET_PUSH()
#define SET_POP()
#else
#define SET_MIPS3() .##set mips3
#define SET_MIPS0() .##set mips0
#define SET_PUSH() .##set push
#define SET_POP() .##set pop
#endif
/* Different assemblers have different requirements for how to
* indicate that the next section is bss :
*
* Some use : .bss
* Others use : .section bss
*
* We select which to use based on _BSS_OLD_, which may be defined
* in makefile.
*/
#ifdef _BSS_OLD_
#define BSS .##section bss
#else
#define BSS .##bss
#endif
#define LEAF(name)\
.##text;\
.##globl name;\
.##ent name;\
name:
#define SLEAF(name)\
.##text;\
.##ent name;\
name:
#ifdef __ghs__
#define END(name)\
.##end name
#else
#define END(name)\
.##size name,.-name;\
.##end name
#endif
#define EXTERN(name)
#else
#define U64 unsigned long long
#define U32 unsigned int
#define U16 unsigned short
#define U8 unsigned char
#define S64 signed long long
#define S32 int
#define S16 short int
#define S8 signed char
#define bool U8
#ifndef _SIZE_T_
#define _SIZE_T_
#ifdef __ghs__
typedef unsigned int size_t;
#else
typedef unsigned long size_t;
#endif
#endif
/* Sets the result on bPort */
#define BIT_SET(bPort,bBitMask) (bPort |= bBitMask)
#define BIT_CLR(bPort,bBitMask) (bPort &= ~bBitMask)
/* Returns the result */
#define GET_BIT_SET(bPort,bBitMask) (bPort | bBitMask)
#define GET_BIT_CLR(bPort,bBitMask) (bPort & ~bBitMask)
/* Returns 0 if the condition is False & a non-zero value if it is True */
#define TEST_BIT_SET(bPort,bBitMask) (bPort & bBitMask)
#define TEST_BIT_CLR(bPort,bBitMask) ((~bPort) & bBitMask)
/* Split union definitions */
typedef union tunSU16
{
U16 hwHW;
struct tst2U8
{
U8 bB0;
U8 bB1;
}st2U8;
}tunSU16;
typedef union tunSU32
{
U32 wW;
struct tst2U16
{
U16 hwHW0;
U16 hwHW1;
}st2U16;
struct tst4U8
{
U8 bB0;
U8 bB1;
U8 bB2;
U8 bB3;
}st4U8;
}tunSU32;
#endif /* #ifdef _ASSEMBLER_ */
/******** DEFINITIONS FOR BOTH ASSEMBLER AND C ********/
#define NO_ERR 0x00000000 /* operation completed successfully */
#define ERR 0xffffffff /* operation completed not successfully */
#define False 0
#define True !False
#define NULL ((void *)0)
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MAXUINT(w) (\
((w) == sizeof(U8)) ? 0xFFU :\
((w) == sizeof(U16)) ? 0xFFFFU :\
((w) == sizeof(U32)) ? 0xFFFFFFFFU : 0\
)
#define MAXINT(w) (\
((w) == sizeof(S8)) ? 0x7F :\
((w) == sizeof(S16)) ? 0x7FFF :\
((w) == sizeof(S32)) ? 0x7FFFFFFF : 0\
)
#define MSK(n) ((1 << (n)) - 1)
#define KUSEG_MSK 0x80000000
#define KSEG_MSK 0xE0000000
#define KUSEGBASE 0x00000000
#define KSEG0BASE 0x80000000
#define KSEG1BASE 0xA0000000
#define KSSEGBASE 0xC0000000
#define KSEG3BASE 0xE0000000
/* Below macros perform the following functions :
*
* KSEG0 : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG0.
* KSEG1 : Converts KSEG0/1 or physical addr (below 0.5GB) to KSEG1.
* PHYS : Converts KSEG0/1 or physical addr (below 0.5GB) to physical address.
* KSSEG : Not relevant for converting, but used for determining range.
* KSEG3 : Not relevant for converting, but used for determining range.
* KUSEG : Not relevant for converting, but used for determining range.
* KSEG0A : Same as KSEG0 but operates on register rather than constant.
* KSEG1A : Same as KSEG1 but operates on register rather than constant.
* PHYSA : Same as PHYS but operates on register rather than constant.
* CACHED : Alias for KSEG0 macro .
* (Note that KSEG0 cache attribute is determined by K0
* field of Config register, but this is typically cached).
* UNCACHED : Alias for KSEG1 macro .
*/
#ifdef _ASSEMBLER_
#define KSEG0(addr) (((addr) & ~KSEG_MSK) | KSEG0BASE)
#define KSEG1(addr) (((addr) & ~KSEG_MSK) | KSEG1BASE)
#define KSSEG(addr) (((addr) & ~KSEG_MSK) | KSSEGBASE)
#define KSEG3(addr) (((addr) & ~KSEG_MSK) | KSEG3BASE)
#define KUSEG(addr) (((addr) & ~KUSEG_MSK) | KUSEGBASE)
#define PHYS(addr) ( (addr) & ~KSEG_MSK)
#define KSEG0A(reg) and reg, ~KSEG_MSK; or reg, KSEG0BASE
#define KSEG1A(reg) and reg, ~KSEG_MSK; or reg, KSEG1BASE
#define PHYSA(reg) and reg, ~KSEG_MSK
#else
#define KSEG0(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG0BASE)
#define KSEG1(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG1BASE)
#define KSSEG(addr) (((U32)(addr) & ~KSEG_MSK) | KSSEGBASE)
#define KSEG3(addr) (((U32)(addr) & ~KSEG_MSK) | KSEG3BASE)
#define KUSEG(addr) (((U32)(addr) & ~KUSEG_MSK) | KUSEGBASE)
#define PHYS(addr) ((U32)(addr) & ~KSEG_MSK)
#endif
#define CACHED(addr) KSEG0(addr)
#define UNCACHED(addr) KSEG1(addr)
#ifdef _ASSEMBLER_
/* Macroes to access variables at constant addresses
* Compensates for signed 16 bit displacement
* Typical use: li a0, HIKSEG1(ATLAS_ASCIIWORD)
* sw v1, LO_OFFS(ATLAS_ASCIIWORD)(a0)
*/
#define HIKSEG0(addr) ((KSEG0(addr) + 0x8000) & 0xffff0000)
#define HIKSEG1(addr) ((KSEG1(addr) + 0x8000) & 0xffff0000)
#define HI_PART(addr) (((addr) + 0x8000) & 0xffff0000)
#define LO_OFFS(addr) ((addr) & 0xffff)
#endif
/* Most/Least significant 32 bit from 64 bit double word */
#define HI32(data64) ((U32)(data64 >> 32))
#define LO32(data64) ((U32)(data64 & 0xFFFFFFFF))
#define REG8( addr ) (*(volatile U8 *) (addr))
#define REG16( addr ) (*(volatile U16 *)(addr))
#define REG32( addr ) (*(volatile U32 *)(addr))
#define REG64( addr ) (*(volatile U64 *)(addr))
/* Register field mapping */
#define REGFIELD(reg, rfld) (((reg) & rfld##_MSK) >> rfld##_SHF)
/* absolute register address, access */
#define REGA(addr) REG32(addr)
/* physical register address, access: base address + offsett */
#define REGP(base,phys) REG32( (U32)(base) + (phys) )
/* relative register address, access: base address + offsett */
#define REG(base,offs) REG32( (U32)(base) + offs##_##OFS )
/* relative register address, access: base address + offsett */
#define REG_8(base,offs) REG8( (U32)(base) + offs##_##OFS )
/* relative register address, access: base address + offsett */
#define REG_16(base,offs) REG16( (U32)(base) + offs##_##OFS )
/* relative register address, access: base address + offsett */
#define REG_64(base,offs) REG64( (U32)(base) + offs##_##OFS )
/**************************************
* Macroes not used by YAMON any more
* (kept for backwards compatibility)
*/
/* register read field */
#define REGARD(addr,fld) ((REGA(addr) & addr##_##fld##_##MSK) \
>> addr##_##fld##_##SHF)
/* register write numeric field value */
#define REGAWRI(addr,fld,intval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
| ((intval) << addr##_##fld##_##SHF))
/* register write enumerated field value */
#define REGAWRE(addr,fld,enumval) ((REGA(addr) & ~(addr##_##fld##_##MSK))\
| ((addr##_##fld##_##enumval) << addr##_##fld##_##SHF))
/* Examples:
*
* exccode = REGARD(CPU_CAUSE,EXC);
*
* REGA(SDR_CONTROL) = REGAWRI(OSG_CONTROL,TMO,17)
* | REGAWRE(OSG_CONTROL,DTYPE,PC1);
*/
/* register read field */
#define REGRD(base,offs,fld) ((REG(base,offs) & offs##_##fld##_##MSK) \
>> offs##_##fld##_##SHF)
/* register write numeric field value */
#define REGWRI(base,offs,fld,intval)((REG(base,offs)& ~(offs##_##fld##_##MSK))\
| (((intval) << offs##_##fld##_##SHF) & offs##_##fld##_##MSK))
/* register write enumerated field value */
#define REGWRE(base,offs,fld,enumval)((REG(base,offs) & ~(offs##_##fld##_##MSK))\
| ((offs##_##fld##_##enumval) << offs##_##fld##_##SHF))
/* physical register read field */
#define REGPRD(base,phys,fld) ((REGP(base,phys) & phys##_##fld##_##MSK) \
>> phys##_##fld##_##SHF)
/* physical register write numeric field value */
#define REGPWRI(base,phys,fld,intval)((REGP(base,phys)& ~(phys##_##fld##_##MSK))\
| ((intval) << phys##_##fld##_##SHF))
/* physical register write enumerated field value */
#define REGPWRE(base,phys,fld,enumval)((REGP(base,phys) & ~(phys##_##fld##_##MSK))\
| ((phys##_##fld##_##enumval) << phys##_##fld##_##SHF))
/*
* End of macroes not used by YAMON any more
*********************************************/
/* Endian related macros */
#define SWAP_BYTEADDR32( addr ) ( (addr) ^ 0x3 )
#define SWAP_U16ADDR32( addr ) ( (addr) ^ 0x2 )
/* Set byte address to little endian format */
#ifdef EL
#define SWAP_BYTEADDR_EL(addr) addr
#else
#define SWAP_BYTEADDR_EL(addr) SWAP_BYTEADDR32( addr )
#endif
/* Set byte address to big endian format */
#ifdef EB
#define SWAP_BYTEADDR_EB(addr) addr
#else
#define SWAP_BYTEADDR_EB(addr) SWAP_BYTEADDR32( addr )
#endif
/* Set U16 address to little endian format */
#ifdef EL
#define SWAP_U16ADDR_EL(addr) addr
#else
#define SWAP_U16ADDR_EL(addr) SWAP_U16ADDR32( addr )
#endif
/* Set U16 address to big endian format */
#ifdef EB
#define SWAP_U16ADDR_EB(addr) addr
#else
#define SWAP_U16ADDR_EB(addr) SWAP_U16ADDR32( addr )
#endif
#ifdef EL
#define REGW32LE(addr, data) REG32(addr) = (data)
#define REGR32LE(addr, data) (data) = REG32(addr)
#else
#define REGW32LE(addr, data) REG32(addr) = SWAPEND32(data)
#define REGR32LE(addr, data) (data) = REG32(addr), (data) = SWAPEND32(data)
#endif
/* Set of 'LE'-macros, convert by BE: */
#ifdef EL
#define CPU_TO_LE32( value ) (value)
#define LE32_TO_CPU( value ) (value)
#define CPU_TO_LE16( value ) (value)
#define LE16_TO_CPU( value ) (value)
#else
#define CPU_TO_LE32( value ) ( ( ((U32)value) << 24) | \
((0x0000FF00UL & ((U32)value)) << 8) | \
((0x00FF0000UL & ((U32)value)) >> 8) | \
( ((U32)value) >> 24) )
#define LE32_TO_CPU( value ) CPU_TO_LE32( value )
#define CPU_TO_LE16( value ) ( ((U16)(((U16)value) << 8)) | \
((U16)(((U16)value) >> 8)) )
#define LE16_TO_CPU( value ) CPU_TO_LE16( value )
#endif
/* Set of 'BE'-macros, convert by LE: */
#ifdef EB
#define CPU_TO_BE32( value ) (value)
#define BE32_TO_CPU( value ) (value)
#define CPU_TO_BE16( value ) (value)
#define BE16_TO_CPU( value ) (value)
#else
#define CPU_TO_BE32( value ) ( ( ((U32)value) << 24) | \
((0x0000FF00UL & ((U32)value)) << 8) | \
((0x00FF0000UL & ((U32)value)) >> 8) | \
( ((U32)value) >> 24) )
#define BE32_TO_CPU( value ) CPU_TO_BE32( value )
#define CPU_TO_BE16( value ) ( ((U16)(((U16)value) << 8)) | \
((U16)(((U16)value) >> 8)) )
#define BE16_TO_CPU( value ) CPU_TO_BE16( value )
#endif
/* Control characters */
#define CTRL_A ('A'-0x40)
#define CTRL_B ('B'-0x40)
#define CTRL_C ('C'-0x40)
#define CTRL_D ('D'-0x40)
#define CTRL_E ('E'-0x40)
#define CTRL_F ('F'-0x40)
#define CTRL_H ('H'-0x40)
#define CTRL_K ('K'-0x40)
#define CTRL_N ('N'-0x40)
#define CTRL_P ('P'-0x40)
#define CTRL_U ('U'-0x40)
#define BACKSPACE 0x08
#define DEL 0x7F
#define TAB 0x09
#define CR 0x0D /* Enter Key */
#define LF 0x0A
#define ESC 0x1B
#define SP 0x20
#define CSI 0x9B
/* DEF2STR(x) converts #define symbol to string */
#define DEF2STR1(x) #x
#define DEF2STR(x) DEF2STR1(x)
/* ********************************************************************* */
/* Interface function definition */
/* ********************************************************************* */
#endif /*__SYSDEFS_H__*/

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#ifndef __UDC_H__
#define __UDC_H__
#include "usb.h"
#define MAX_EP0_SIZE 64
#define MAX_EP1_SIZE 512
#define USB_HS 0
#define USB_FS 1
#define USB_LS 2
//definitions of EP0
#define USB_EP0_IDLE 0
#define USB_EP0_RX 1
#define USB_EP0_TX 2
/* Define maximum packet size for endpoint 0 */
#define M_EP0_MAXP 64
/* Endpoint 0 status structure */
static __inline__ void usb_setb(u32 port, u8 val)
{
volatile u8 *ioport = (volatile u8 *)(port);
*ioport = (*ioport) | val;
}
static __inline__ void usb_clearb(u32 port, u8 val)
{
volatile u8 *ioport = (volatile u8 *)(port);
*ioport = (*ioport) & ~val;
}
static __inline__ void usb_setw(u32 port, u16 val)
{
volatile u16 *ioport = (volatile u16 *)(port);
*ioport = (*ioport) | val;
}
static __inline__ void usb_clearw(u32 port, u16 val)
{
volatile u16 *ioport = (volatile u16 *)(port);
*ioport = (*ioport) & ~val;
}
#endif //__UDC_H__

View File

@@ -0,0 +1,225 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#ifndef __USB_H
#define __USB_H
#ifndef u8
#define u8 unsigned char
#endif
#ifndef u16
#define u16 unsigned short
#endif
#ifndef u32
#define u32 unsigned int
#endif
#ifndef s8
#define s8 char
#endif
#ifndef s16
#define s16 short
#endif
#ifndef s32
#define s32 int
#endif
extern int usbdebug;
enum USB_ENDPOINT_TYPE
{
ENDPOINT_TYPE_CONTROL,
/* Typically used to configure a device when attached to the host.
* It may also be used for other device specific purposes, including
* control of other pipes on the device.
*/
ENDPOINT_TYPE_ISOCHRONOUS,
/* Typically used for applications which need guaranteed speed.
* Isochronous transfer is fast but with possible data loss. A typical
* use is audio data which requires a constant data rate.
*/
ENDPOINT_TYPE_BULK,
/* Typically used by devices that generate or consume data in relatively
* large and bursty quantities. Bulk transfer has wide dynamic latitude
* in transmission constraints. It can use all remaining available bandwidth,
* but with no guarantees on bandwidth or latency. Since the USB bus is
* normally not very busy, there is typically 90% or more of the bandwidth
* available for USB transfers.
*/
ENDPOINT_TYPE_INTERRUPT
/* Typically used by devices that need guaranteed quick responses
* (bounded latency).
*/
};
enum USB_STANDARD_REQUEST_CODE {
GET_STATUS,
CLEAR_FEATURE,
SET_FEATURE = 3,
SET_ADDRESS = 5,
GET_DESCRIPTOR,
SET_DESCRIPTOR,
GET_CONFIGURATION,
SET_CONFIGURATION,
GET_INTERFACE,
SET_INTERFACE,
SYNCH_FRAME
};
enum USB_DESCRIPTOR_TYPE {
DEVICE_DESCRIPTOR = 1,
CONFIGURATION_DESCRIPTOR,
STRING_DESCRIPTOR,
INTERFACE_DESCRIPTOR,
ENDPOINT_DESCRIPTOR,
DEVICE_QUALIFIER_DESCRIPTOR,
OTHER_SPEED_CONFIGURATION_DESCRIPTOR,
INTERFACE_POWER1_DESCRIPTOR
};
enum USB_FEATURE_SELECTOR {
ENDPOINT_HALT,
DEVICE_REMOTE_WAKEUP,
TEST_MODE
};
enum USB_CLASS_CODE {
CLASS_DEVICE,
CLASS_AUDIO,
CLASS_COMM_AND_CDC_CONTROL,
CLASS_HID,
CLASS_PHYSICAL = 0x05,
CLASS_STILL_IMAGING,
CLASS_PRINTER,
CLASS_MASS_STORAGE,
CLASS_HUB,
CLASS_CDC_DATA,
CLASS_SMART_CARD,
CLASS_CONTENT_SECURITY = 0x0d,
CLASS_VIDEO,
CLASS_DIAGNOSTIC_DEVICE = 0xdc,
CLASS_WIRELESS_CONTROLLER = 0xe0,
CLASS_MISCELLANEOUS = 0xef,
CLASS_APP_SPECIFIC = 0xfe,
CLASS_VENDOR_SPECIFIC = 0xff
};
typedef struct {
u8 bmRequestType;
u8 bRequest;
u16 wValue;
u16 wIndex;
u16 wLength;
} __attribute__ ((packed)) USB_DeviceRequest;
typedef struct {
u8 bLength;
u8 bDescriptorType;
u16 bcdUSB;
u8 bDeviceClass;
u8 bDeviceSubClass;
u8 bDeviceProtocol;
u8 bMaxPacketSize0;
u16 idVendor;
u16 idProduct;
u16 bcdDevice;
u8 iManufacturer;
u8 iProduct;
u8 iSerialNumber;
u8 bNumConfigurations;
} __attribute__ ((packed)) USB_DeviceDescriptor;
typedef struct {
u8 bLength;
u8 bDescriptorType;
u16 bcdUSB;
u8 bDeviceClass;
u8 bDeviceSubClass;
u8 bDeviceProtocol;
u8 bMaxPacketSize0;
u8 bNumConfigurations;
u8 bReserved;
} __attribute__ ((packed)) USB_DeviceQualifierDescriptor;
typedef struct {
u8 bLength;
u8 bDescriptorType;
u16 wTotalLength;
u8 bNumInterfaces;
u8 bConfigurationValue;
u8 iConfiguration;
u8 bmAttributes;
u8 MaxPower;
} __attribute__ ((packed)) USB_ConfigDescriptor;
typedef struct {
u8 bLength;
u8 bDescriptorType;
u16 wTotalLength;
u8 bNumInterfaces;
u8 bConfigurationValue;
u8 iConfiguration;
u8 bmAttributes;
u8 bMaxPower;
} __attribute__ ((packed)) USB_OtherSpeedConfigDescriptor;
typedef struct {
u8 bLength;
u8 bDescriptorType;
u8 bInterfaceNumber;
u8 bAlternateSetting;
u8 bNumEndpoints;
u8 bInterfaceClass;
u8 bInterfaceSubClass;
u8 bInterfaceProtocol;
u8 iInterface;
} __attribute__ ((packed)) USB_InterfaceDescriptor;
typedef struct {
u8 bLegth;
u8 bDescriptorType;
u8 bEndpointAddress;
u8 bmAttributes;
u16 wMaxPacketSize;
u8 bInterval;
} __attribute__ ((packed)) USB_EndPointDescriptor;
typedef struct {
u8 bLength;
u8 bDescriptorType;
u16 SomeDesriptor[1];
} __attribute__ ((packed)) USB_StringDescriptor;
#endif // !defined(__USB_H)

View File

@@ -0,0 +1,49 @@
/*
* "Ingenic flash tool" - flash the Ingenic CPU via USB
*
* Copyright (C) 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#ifndef __USB_BOOT_H__
#define __USB_BOOT_H__
#define BULK_OUT_BUF_SIZE 0x21000
#define BULK_IN_BUF_SIZE 0x21000
enum UDC_STATE
{
IDLE,
BULK_IN,
BULK_OUT
};
enum USB_JZ4740_REQUEST /* add for USB_BOOT */
{
VR_GET_CUP_INFO = 0,
VR_SET_DATA_ADDERSS,
VR_SET_DATA_LENGTH,
VR_FLUSH_CACHES,
VR_PROGRAM_START1,
VR_PROGRAM_START2,
VR_NOR_OPS,
VR_NAND_OPS,
VR_SDRAM_OPS,
VR_CONFIGRATION
};
#endif /* __USB_BOOT_H__ */

View File

@@ -0,0 +1,18 @@
/*
* Authors: Xiangfu Liu <xiangfu.z@gmail.com>
*
* 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
* 3 of the License, or (at your option) any later version.
*/
#ifndef __XBURST_TYPES_H__
#define __XBURST_TYPES_H__
typedef unsigned int size_t;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#endif /* __XBURST_TYPES_H__ */

11
usbboot/xburst_stage1/.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
System.map
board_4740.o
board_4750.o
common.o
debug.o
head.o
main.o
xburst_stage1.bin
xburst_stage1.dump
xburst_stage1.elf
xburst_stage1.map

View File

@@ -0,0 +1,40 @@
#
# Authors: Xiangfu Liu <xiangfu.z@gmail.com>
#
# 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
# 3 of the License, or (at your option) any later version.
#
INFLASH_SRC_PATH = ../src
XBURST_INCLUDE_PATH = ../xburst_include
ifeq ($(CROSS_COMPILE),)
$(error CROSS_COMPILE variable not set, should point to .../mipsel-openwrt-linux-)
endif
CFLAGS := -O2 -fno-unit-at-a-time -fno-zero-initialized-in-bss -mips32 -fno-pic \
-mno-abicalls -I$(INFLASH_SRC_PATH) -I$(XBURST_INCLUDE_PATH)
LDFLAGS := -nostdlib -EL -T target.ld
OBJS = head.o main.o common.o board_4740.o board_4750.o debug.o
all: xburst_stage1.bin
xburst_stage1.bin: xburst_stage1.elf
$(CROSS_COMPILE)objcopy -O binary $< $@
$(CROSS_COMPILE)objdump -D $< > xburst_stage1.dump
$(CROSS_COMPILE)objdump -h $< > xburst_stage1.map
$(CROSS_COMPILE)nm -n $< > System.map
xburst_stage1.elf: $(OBJS)
$(CROSS_COMPILE)ld $(LDFLAGS) $(OBJS) -o $@
.c.o:
$(CROSS_COMPILE)gcc $(CFLAGS) -c $< -o $@
.S.o:
$(CROSS_COMPILE)gcc $(CFLAGS) -c $< -o $@
clean:
rm -f xburst_stage1.bin xburst_stage1.elf xburst_stage1.dump xburst_stage1.map
rm -f $(OBJS)
rm -f System.map

View File

@@ -0,0 +1,224 @@
/*
* device board
*
* (C) Copyright 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4740.h"
#include "configs.h"
void gpio_init_4740(void)
{
/*
* Initialize SDRAM pins
*/
#if 0
/* PORT A: D0 ~ D31 */
REG_GPIO_PXFUNS(0) = 0xffffffff;
REG_GPIO_PXSELC(0) = 0xffffffff;
/* PORT B: A0 ~ A16, DCS#, RAS#, CAS#, CKE#, RDWE#, CKO#, WE0# */
REG_GPIO_PXFUNS(1) = 0x81f9ffff;
REG_GPIO_PXSELC(1) = 0x81f9ffff;
/* PORT C: WE1#, WE2#, WE3# */
REG_GPIO_PXFUNS(2) = 0x07000000;
REG_GPIO_PXSELC(2) = 0x07000000;
/*
* Initialize Static Memory Pins
*/
/* CS4# */
REG_GPIO_PXFUNS(1) = 0x10000000;
REG_GPIO_PXSELC(1) = 0x10000000;
/*
* Initialize UART0 pins
*/
/* PORT D: TXD/RXD */
REG_GPIO_PXFUNS(3) = 0x06000000;
REG_GPIO_PXSELS(3) = 0x06000000;
#endif
__gpio_as_nand();
/*
* Initialize SDRAM pins
*/
__gpio_as_sdram_32bit();
/*
* Initialize UART0 pins
*/
__gpio_as_uart0();
__gpio_as_uart1();
}
void pll_init_4740(void)
{
register unsigned int cfcr, plcr1;
int n2FR[33] = {
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
9
};
/* int div[5] = {1, 4, 4, 4, 4}; */ /* divisors of I:S:P:L:M */
int nf, pllout2;
cfcr = CPM_CPCCR_CLKOEN |
(n2FR[1] << CPM_CPCCR_CDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_HDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_PDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_MDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_LDIV_BIT);
pllout2 = (cfcr & CPM_CPCCR_PCS) ? CFG_CPU_SPEED : (CFG_CPU_SPEED / 2);
/* Init UHC clock */
REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
nf = CFG_CPU_SPEED * 2 / CFG_EXTAL;
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
(0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
(0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
CPM_CPPCR_PLLEN; /* enable PLL */
/* init PLL */
REG_CPM_CPCCR = cfcr;
REG_CPM_CPPCR = plcr1;
}
void sdram_init_4740(void)
{
register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
unsigned int cas_latency_sdmr[2] = {
EMC_SDMR_CAS_2,
EMC_SDMR_CAS_3,
};
unsigned int cas_latency_dmcr[2] = {
1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */
2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
};
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
cpu_clk = CFG_CPU_SPEED;
mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
REG_EMC_BCR = 0; /* Disable bus release */
REG_EMC_RTCSR = 0; /* Disable clock for counting */
/* Fault DMCR value for mode register setting*/
#define SDRAM_ROW0 11
#define SDRAM_COL0 8
#define SDRAM_BANK40 0
dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
EMC_DMCR_EPIN |
cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
/* Basic DMCR value */
dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
(SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
EMC_DMCR_EPIN |
cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
/* SDRAM timimg */
ns = 1000000000 / mem_clk;
tmp = SDRAM_TRAS/ns;
if (tmp < 4) tmp = 4;
if (tmp > 11) tmp = 11;
dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
tmp = SDRAM_RCD/ns;
if (tmp > 3) tmp = 3;
dmcr |= (tmp << EMC_DMCR_RCD_BIT);
tmp = SDRAM_TPC/ns;
if (tmp > 7) tmp = 7;
dmcr |= (tmp << EMC_DMCR_TPC_BIT);
tmp = SDRAM_TRWL/ns;
if (tmp > 3) tmp = 3;
dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
if (tmp > 14) tmp = 14;
dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
/* SDRAM mode value */
sdmode = EMC_SDMR_BT_SEQ |
EMC_SDMR_OM_NORMAL |
EMC_SDMR_BL_4 |
cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
REG_EMC_DMCR = dmcr;
REG8(EMC_SDMR0|sdmode) = 0;
/* Wait for precharge, > 200us */
tmp = (cpu_clk / 1000000) * 1000;
while (tmp--);
/* Stage 2. Enable auto-refresh */
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
tmp = SDRAM_TREF/ns;
tmp = tmp/64 + 1;
if (tmp > 0xff) tmp = 0xff;
REG_EMC_RTCOR = tmp;
REG_EMC_RTCNT = 0;
REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
/* Wait for number of auto-refresh cycles */
tmp = (cpu_clk / 1000000) * 1000;
while (tmp--);
/* Stage 3. Mode Register Set */
REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
REG8(EMC_SDMR0|sdmode) = 0;
/* Set back to basic DMCR value */
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
/* everything is ok now */
}
void serial_setbrg_4740(void)
{
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
volatile u8 *uart_dlhr = (volatile u8 *)(UART_BASE + OFF_DLHR);
volatile u8 *uart_dllr = (volatile u8 *)(UART_BASE + OFF_DLLR);
u32 baud_div, tmp;
baud_div = CFG_EXTAL / 16 / CONFIG_BAUDRATE;
tmp = *uart_lcr;
tmp |= UART_LCR_DLAB;
*uart_lcr = tmp;
*uart_dlhr = (baud_div >> 8) & 0xff;
*uart_dllr = baud_div & 0xff;
tmp &= ~UART_LCR_DLAB;
*uart_lcr = tmp;
}

View File

@@ -0,0 +1,227 @@
/*
* Board init routines.
*
* (C) Copyright 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4750.h"
#include "configs.h"
void gpio_init_4750(void)
{
__gpio_as_sdram_32bit();
__gpio_as_uart1();
__gpio_as_uart0();
__gpio_as_uart2();
__gpio_as_uart3();
__gpio_as_nand_8bit();
}
void ccpll_init_4750(void)
{
register unsigned int cfcr, plcr1;
int n2FR[33] = {
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
9
};
// int div[5] = {1, 4, 4, 4, 4}; /* divisors of I:S:P:L:M */
int nf, pllout2;
cfcr = ~CPM_CPCCR_ECS &
(n2FR[1] << CPM_CPCCR_CDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_HDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_PDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_MDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_LDIV_BIT);
pllout2 = (cfcr & CPM_CPCCR_PCS) ? CFG_CPU_SPEED : (CFG_CPU_SPEED / 2);
nf = CFG_CPU_SPEED * 2 / CFG_EXTAL;
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
(0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
(0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
CPM_CPPCR_PLLEN; /* enable PLL */
/* init PLL */
REG_CPM_CPCCR = cfcr;
REG_CPM_CPPCR = plcr1;
}
int nf, pllout2;
void pll_init_4750(void)
{
register unsigned int cfcr, plcr1,tmp;
int n2FR[33] = {
0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
9
};
int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */
cfcr = CPM_CPCCR_PCS |
(n2FR[1] << CPM_CPCCR_CDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_HDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_PDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_MDIV_BIT) |
(n2FR[PHM_DIV] << CPM_CPCCR_LDIV_BIT);
if (CFG_EXTAL > 16000000)
cfcr |= CPM_CPCCR_ECS;
pllout2 = (cfcr & CPM_CPCCR_PCS) ? CFG_CPU_SPEED : (CFG_CPU_SPEED / 2);
/* Init USB Host clock, pllout2 must be n*48MHz */
// REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
nf = CFG_CPU_SPEED * 2 / CFG_EXTAL;
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
(0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
(0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
(0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
CPM_CPPCR_PLLEN; /* enable PLL */
cfcr |= CPM_CPCCR_UCS; /* set PLL as UDC PHY*/
tmp = pllout2 / 1000000 / 12 - 1;
cfcr |= (tmp << CPM_CPCCR_UDIV_BIT); /* set UDC DIV*/
/* init PLL */
REG_CPM_CPCCR = cfcr;
REG_CPM_CPPCR = plcr1;
}
void sdram_init_4750(void)
{
register unsigned int dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
register unsigned int sdemode; /*SDRAM Extended Mode*/
unsigned int cas_latency_sdmr[2] = {
EMC_SDMR_CAS_2,
EMC_SDMR_CAS_3,
};
unsigned int cas_latency_dmcr[2] = {
1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */
2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
};
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
cpu_clk = CFG_CPU_SPEED;
mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
/* set REG_EMC_DMAR0 for supporting 128MB sdram on DCS0 */
REG_EMC_DMAR0 = EMC_DMAR0_BASE | EMC_DMAR_MASK_128_128;
REG_EMC_BCR = 0; /* Disable bus release */
REG_EMC_RTCSR = 0; /* Disable clock for counting */
/* Basic DMCR value */
dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
(SDRAM_BANK4<<EMC_DMCR_BA_BIT) |
(SDRAM_BW16<<EMC_DMCR_BW_BIT) |
EMC_DMCR_EPIN |
cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
/* SDRAM timimg */
ns = 1000000000 / mem_clk;
tmp = SDRAM_TRAS/ns;
if (tmp < 4) tmp = 4;
if (tmp > 11) tmp = 11;
dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
tmp = SDRAM_RCD/ns;
if (tmp > 3) tmp = 3;
dmcr |= (tmp << EMC_DMCR_RCD_BIT);
tmp = SDRAM_TPC/ns;
if (tmp > 7) tmp = 7;
dmcr |= (tmp << EMC_DMCR_TPC_BIT);
tmp = SDRAM_TRWL/ns;
if (tmp > 3) tmp = 3;
dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
if (tmp > 14) tmp = 14;
dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
/* SDRAM mode value */
sdmode = EMC_SDMR_BT_SEQ |
EMC_SDMR_OM_NORMAL |
EMC_SDMR_BL_4 |
cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
REG_EMC_DMCR = dmcr;
REG8(EMC_SDMR0|sdmode) = 0;
if (CONFIG_MOBILE_SDRAM == 1)
/* Mobile SDRAM Extended Mode Register */
sdemode = EMC_SDMR_SET_BA1 | EMC_SDMR_DS_FULL | EMC_SDMR_PRSR_ALL;
/* Wait for precharge, > 200us */
tmp = (cpu_clk / 1000000) * 1000;
while (tmp--);
/* Stage 2. Enable auto-refresh */
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
tmp = SDRAM_TREF/ns;
tmp = tmp/64 + 1;
if (tmp > 0xff) tmp = 0xff;
REG_EMC_RTCOR = tmp;
REG_EMC_RTCNT = 0;
REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
/* Wait for number of auto-refresh cycles */
tmp = (cpu_clk / 1000000) * 1000;
while (tmp--);
/* Stage 3. Mode Register Set */
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET | EMC_DMCR_MBSEL_B0;
REG8(EMC_SDMR0|sdmode) = 0;
if (CONFIG_MOBILE_SDRAM == 1)
REG8(EMC_SDMR0|sdemode) = 0; /* Set Mobile SDRAM Extended Mode Register */
/* Set back to basic DMCR value */
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
/* everything is ok now */
}
void serial_setbrg_4750(void)
{
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
volatile u8 *uart_dlhr = (volatile u8 *)(UART_BASE + OFF_DLHR);
volatile u8 *uart_dllr = (volatile u8 *)(UART_BASE + OFF_DLLR);
u32 baud_div, tmp;
baud_div = (REG_CPM_CPCCR & CPM_CPCCR_ECS) ?
(CFG_EXTAL / 32 / CONFIG_BAUDRATE) : (CFG_EXTAL / 16 / CONFIG_BAUDRATE);
tmp = *uart_lcr;
tmp |= UART_LCR_DLAB;
*uart_lcr = tmp;
*uart_dlhr = (baud_div >> 8) & 0xff;
*uart_dllr = baud_div & 0xff;
tmp &= ~UART_LCR_DLAB;
*uart_lcr = tmp;
}

View File

@@ -0,0 +1,110 @@
/*
* device board
*
* (C) Copyright 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4740.h"
#include "configs.h"
void serial_putc (const char c)
{
volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
volatile u8 *uart_tdr = (volatile u8 *)(UART_BASE + OFF_TDR);
if (c == '\n') serial_putc ('\r');
/* Wait for fifo to shift out some bytes */
while ( !((*uart_lsr & (UART_LSR_TDRQ | UART_LSR_TEMT)) == 0x60) );
*uart_tdr = (u8)c;
}
void serial_puts (const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
int serial_getc (void)
{
volatile u8 *uart_rdr = (volatile u8 *)(UART_BASE + OFF_RDR);
while (!serial_tstc());
return *uart_rdr;
}
int serial_tstc (void)
{
volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
if (*uart_lsr & UART_LSR_DR) {
/* Data in rfifo */
return (1);
}
return 0;
}
void serial_init(void)
{
volatile u8 *uart_fcr = (volatile u8 *)(UART_BASE + OFF_FCR);
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
volatile u8 *uart_ier = (volatile u8 *)(UART_BASE + OFF_IER);
volatile u8 *uart_sircr = (volatile u8 *)(UART_BASE + OFF_SIRCR);
/* Disable port interrupts while changing hardware */
*uart_ier = 0;
/* Disable UART unit function */
*uart_fcr = ~UART_FCR_UUE;
/* Set both receiver and transmitter in UART mode (not SIR) */
*uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
/* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
*uart_lcr = UART_LCR_WLEN_8 | UART_LCR_STOP_1;
/* Set baud rate */
if ( CPU_ID == 0x4740 )
serial_setbrg_4740();
else
serial_setbrg_4750();
/* Enable UART unit, enable and clear FIFO */
*uart_fcr = UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS;
}
void serial_put_hex(unsigned int d)
{
unsigned char c[12];
char i;
for(i = 0; i < 8;i++)
{
c[i] = (d >> ((7 - i) * 4)) & 0xf;
if(c[i] < 10)
c[i] += 0x30;
else
c[i] += (0x41 - 10);
}
c[8] = '\n';
c[9] = 0;
serial_puts(c);
}

View File

@@ -0,0 +1,102 @@
/*
* device board
*
* (C) Copyright 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4750.h"
#include "configs.h"
#include "usb_boot_defines.h"
extern struct fw_args *fw_args;
unsigned int check_sdram(unsigned int saddr, unsigned int size)
{
unsigned int addr,err = 0;
serial_puts("\nCheck SDRAM ... \n");
saddr += 0xa0000000;
size += saddr;
serial_put_hex(saddr);
serial_put_hex(size);
saddr &= 0xfffffffc; /* must word align */
for (addr = saddr; addr < size; addr += 4)
{
*(volatile unsigned int *)addr = addr;
if (*(volatile unsigned int *)addr != addr)
{
serial_put_hex(addr);
err = addr;
}
}
if (err)
serial_puts("Check SDRAM fail!\n");
else
serial_puts("Check SDRAM pass!\n");
return err;
}
void gpio_test(unsigned char ops, unsigned char pin)
{
__gpio_as_output(pin);
if (ops)
{
serial_puts("\nGPIO set ");
serial_put_hex(pin);
__gpio_set_pin(pin);
}
else
{
serial_puts("\nGPIO clear ");
serial_put_hex(pin);
__gpio_clear_pin(pin);
}
/* __gpio_as_input(pin); */
}
void do_debug()
{
switch (fw_args->debug_ops) {
case 1: /* sdram check */
switch (CPU_ID) {
case 0x4740:
gpio_init_4740();
serial_init();
sdram_init_4740();
break;
case 0x4750:
gpio_init_4750();
serial_init();
sdram_init_4750();
break;
default:
;
}
REG8(USB_REG_INDEX) = 1;
REG32(USB_FIFO_EP1) = check_sdram(fw_args->start, fw_args->size);
REG32(USB_FIFO_EP1) = 0x0;
REG8(USB_REG_INCSR) |= USB_INCSR_INPKTRDY;
break;
case 2: /* set gpio */
gpio_test(1, fw_args->pin_num);
break;
case 3: /* clear gpio */
gpio_test(0, fw_args->pin_num);
break;
}
}

View File

@@ -0,0 +1,53 @@
/*
* head.S
*
* Entry point of the firmware.
* The firmware code are executed in the ICache.
*
* (C) Copyright 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
.text
.extern c_main
.globl _start
.set noreorder
_start:
b real_start
nop
.word 0x0 /* address: 0x80002008 */
.word 0x0
.word 0x0
.word 0x0
.word 0x0
.word 0x0
.word 0x0
.word 0x0
/* reserve 8 words for args
* this is must big then sizeof(sturct fw_args)
*/
real_start:
/*
* setup stack, jump to C code
*/
la $29, 0x80004000 /* sp */
j c_main
nop
.set reorder

View File

@@ -0,0 +1,124 @@
/*
* Main routine of the firmware.
*
* Copyright (C) 2009
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4740.h"
#include "configs.h"
#include "usb_boot_defines.h"
struct fw_args *fw_args;
volatile u32 CPU_ID;
volatile u32 UART_BASE;
volatile u32 CONFIG_BAUDRATE;
volatile u8 SDRAM_BW16;
volatile u8 SDRAM_BANK4;
volatile u8 SDRAM_ROW;
volatile u8 SDRAM_COL;
volatile u8 CONFIG_MOBILE_SDRAM;
volatile u32 CFG_CPU_SPEED;
volatile u32 CFG_EXTAL;
volatile u8 PHM_DIV;
volatile u8 IS_SHARE;
extern int pllout2;
#if 0
void test_load_args(void)
{
CPU_ID = 0x4740 ;
CFG_EXTAL = 12000000 ;
CFG_CPU_SPEED = 252000000 ;
PHM_DIV = 3;
fw_args->use_uart = 0;
UART_BASE = UART0_BASE + fw_args->use_uart * 0x1000;
CONFIG_BAUDRATE = 57600;
SDRAM_BW16 = 16;
SDRAM_BANK4 = 4;
SDRAM_ROW = 13;
SDRAM_COL = 9;
CONFIG_MOBILE_SDRAM = 0;
IS_SHARE = 1;
fw_args->debug_ops = -1;
}
#endif
void load_args(void)
{
fw_args = (struct fw_args *)0x80002008; /* get the fw args from memory */
CPU_ID = fw_args->cpu_id ;
CFG_EXTAL = (u32)fw_args->ext_clk * 1000000;
CFG_CPU_SPEED = (u32)fw_args->cpu_speed * CFG_EXTAL ;
if (CFG_EXTAL == 19000000) {
CFG_EXTAL = 19200000;
CFG_CPU_SPEED = 192000000;
}
PHM_DIV = fw_args->phm_div;
if (fw_args->use_uart > 3)
fw_args->use_uart = 0;
UART_BASE = UART0_BASE + fw_args->use_uart * 0x1000;
CONFIG_BAUDRATE = fw_args->boudrate;
SDRAM_BW16 = fw_args->bus_width == 0 ? 32 : 16;
SDRAM_BANK4 = fw_args->bank_num * 4;
SDRAM_ROW = fw_args->row_addr;
SDRAM_COL = fw_args->col_addr;
CONFIG_MOBILE_SDRAM = fw_args->is_mobile;
IS_SHARE = fw_args->is_busshare;
}
void c_main(void)
{
load_args();
if (fw_args->debug_ops > 0) {
do_debug();
return ;
}
switch (CPU_ID) {
case 0x4740:
gpio_init_4740();
pll_init_4740();
serial_init();
sdram_init_4740();
break;
case 0x4750:
gpio_init_4750();
pll_init_4750();
serial_init();
sdram_init_4750();
break;
default:
return;
}
#if 1
serial_puts("Setup xburst CPU args as:\n");
serial_put_hex(CPU_ID);
serial_put_hex(CFG_EXTAL);
serial_put_hex(CFG_CPU_SPEED);
serial_put_hex(PHM_DIV);
serial_put_hex(fw_args->use_uart);
serial_put_hex(CONFIG_BAUDRATE);
serial_put_hex(SDRAM_BW16);
serial_put_hex(SDRAM_BANK4);
serial_put_hex(SDRAM_ROW);
serial_put_hex(SDRAM_COL);
serial_put_hex(pllout2);
serial_put_hex(REG_CPM_CPCCR);
#endif
serial_puts("xburst stage1 run finish !\n");
}

View File

@@ -0,0 +1,31 @@
OUTPUT_ARCH(mips)
ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x80002000 , LENGTH = 0x100000
}
SECTIONS
{
. = ALIGN(4);
.text : { *(.text*) } > ram
. = ALIGN(4);
.rodata : { *(.rodata*) } > ram
. = ALIGN(4);
.sdata : { *(.sdata*) } > ram
. = ALIGN(4);
.data : { *(.data*) *(.scommon*) *(.reginfo*) } > ram
_gp = ABSOLUTE(.); /* Base of small data */
.got : { *(.got*) } > ram
. = ALIGN(4);
.sbss : { *(.sbss*) } > ram
.bss : { *(.bss*) } > ram
. = ALIGN (4);
}

21
usbboot/xburst_stage2/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
boothandler.lst
boothandler.o
cache.lst
cache.o
head.lst
head.o
main.lst
main.o
nandflash_4740.lst
nandflash_4740.o
nandflash_4750.lst
nandflash_4750.o
serial.lst
serial.o
udc.lst
udc.o
xburst_stage2.bin
xburst_stage2.dump
xburst_stage2.elf
xburst_stage2.map
xburst_stage2.sym

View File

@@ -0,0 +1,57 @@
#
# Authors: Lucifer at Ingenic Semiconductor Inc.
# Xiangfu Liu <xiangfu.z@gmail.com>
#
# 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.
#
INFLASH_SRC_PATH = ../src
XBURST_INCLUDE_PATH = ../xburst_include
ifeq ($(CROSS_COMPILE),)
$(error CROSS_COMPILE variable not set, should point to .../mipsel-openwrt-linux-)
endif
CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar rcsv
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
NM = $(CROSS_COMPILE)nm
OBJDUMP = $(CROSS_COMPILE)objdump
DEBUG_CFLAGS = -g -Wa,-a=$(basename $@).lst
# Wolfgang saw data corruptions in stage2 when dealing with ECC data on random writes
# to NAND. Disabling the unit-at-a-time optimization reproducibly fixed the bug.
# The compiler may be optimizing in a way that conflicts with how the hardware ECC
# registers work. Since other register accesses might be affected too it seems the best
# is to disable this optimization right now.
CFLAGS = -mips32 -O2 -fno-exceptions -fno-unit-at-a-time -fno-zero-initialized-in-bss \
-ffunction-sections -fomit-frame-pointer -msoft-float -G 0 $(DEBUG_CFLAGS) \
-I$(XBURST_INCLUDE_PATH) -I$(INFLASH_SRC_PATH)
LDFLAGS = -nostdlib -T target.ld $(CFLAGS)
LIBS = -lstdc++ -lc -lm -lgcc
OBJS = main.o udc.o cache.o serial.o boothandler.o nandflash_4740.o nandflash_4750.o
all: xburst_stage2.elf
$(OBJCOPY) -O binary xburst_stage2.elf xburst_stage2.bin
$(OBJDUMP) -D xburst_stage2.elf > xburst_stage2.dump
$(NM) xburst_stage2.elf | sort > xburst_stage2.sym
$(OBJDUMP) -h xburst_stage2.elf > xburst_stage2.map
xburst_stage2.elf: head.o $(OBJS)
$(CC) $(LDFLAGS) $^ -o $@
.c.o:
$(CC) $(CFLAGS) -o $@ -c $<
.cpp.o:
$(CC) $(CFLAGS) -fno-rtti -fvtable-gc -o $@ -c $<
.S.o:
$(CC) $(CFLAGS) -o $@ -c $<
clean:
rm -f $(addprefix xburst_stage2., bin dump elf map sym)
rm -f head.o $(OBJS) $(OBJS:.o=.lst)

View File

@@ -0,0 +1,370 @@
/*
* USB_BOOT Handle routines
*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4740.h"
#include "usb.h"
#include "error.h"
#include "usb_boot.h"
#include "usb_boot_defines.h"
#include "nandflash.h"
#include "udc.h"
#define dprintf(x) serial_puts(x)
unsigned int (*nand_query)(u8 *);
int (*nand_init)(int bus_width, int row_cycle, int page_size, int page_per_block,
int,int,int,int);
int (*nand_fini)(void);
u32 (*nand_program)(void *context, int spage, int pages,int option);
u32 (*nand_erase)(int blk_num, int sblk, int force);
u32 (*nand_read)(void *buf, u32 startpage, u32 pagenum,int option);
u32 (*nand_read_oob)(void *buf, u32 startpage, u32 pagenum);
u32 (*nand_read_raw)(void *buf, u32 startpage, u32 pagenum,int);
u32 (*nand_mark_bad) (int bad);
void (*nand_enable) (unsigned int csn);
void (*nand_disable) (unsigned int csn);
struct hand Hand,*Hand_p;
extern u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
extern u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
extern u16 handshake_PKT[4];
extern udc_state;
extern void *memset(void *s, int c, size_t count);
extern void *memcpy(void *dest, const void *src, size_t count);
u32 ret_dat;
u32 start_addr; //program operation start address or sector
u32 ops_length; //number of operation unit ,in byte or sector
u32 ram_addr;
void config_flash_info()
{
}
void dump_data(unsigned int *p, int size)
{
int i;
for(i = 0; i < size; i ++)
serial_put_hex(*p++);
}
void config_hand()
{
struct hand *hand_p;
hand_p=(struct hand *)Bulk_out_buf;
memcpy(&Hand, (unsigned char *)Bulk_out_buf, sizeof(struct hand));
#if 0
Hand.nand_bw=hand_p->nand_bw;
Hand.nand_rc=hand_p->nand_rc;
Hand.nand_ps=hand_p->nand_ps;
Hand.nand_ppb=hand_p->nand_ppb;
Hand.nand_force_erase=hand_p->nand_force_erase;
Hand.nand_pn=hand_p->nand_pn;
Hand.nand_os=hand_p->nand_os;
Hand.nand_eccpos=hand_p->nand_eccpos;
Hand.nand_bbpos=hand_p->nand_bbpos;
Hand.nand_bbpage=hand_p->nand_bbpage;
// memcpy( &Hand.fw_args, (unsigned char *)(start_addr + 0x8), 32 );
// serial_putc(Hand.nand_eccpos + 48);
// serial_putc(Hand.nand_bbpos + 48);
// serial_putc(Hand.nand_bbpage + 48);
/* dprintf("\n Hand : bw %d rc %d ps %d ppb %d erase %d pn %d os %d", */
/* Hand.nand_bw,Hand.nand_rc,Hand.nand_ps,Hand.nand_ppb,Hand.nand_force_erase,Hand.nand_pn,Hand.nand_os); */
serial_put_hex(Hand.fw_args.cpu_id);
serial_put_hex(Hand.fw_args.ext_clk);
#endif
}
int GET_CUP_INFO_Handle()
{
char temp1[8]="Boot4740",temp2[8]="Boot4750";
dprintf("\n GET_CPU_INFO!");
if ( Hand.fw_args.cpu_id == 0x4740 )
HW_SendPKT(0,temp1,8);
else
HW_SendPKT(0,temp2,8);
udc_state = IDLE;
return ERR_OK;
}
int SET_DATA_ADDERSS_Handle(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
start_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
dprintf("\n SET ADDRESS:");
serial_put_hex(start_addr);
return ERR_OK;
}
int SET_DATA_LENGTH_Handle(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
ops_length=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
dprintf("\n DATA_LENGTH :");
serial_put_hex(ops_length);
return ERR_OK;
}
int FLUSH_CACHES_Handle()
{
return ERR_OK;
}
int PROGRAM_START1_Handle(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
ram_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
//dprintf("\n RAM ADDRESS :%x", ram_addr);
return ERR_OK;
}
int PROGRAM_START2_Handle(u8 *buf)
{
void (*f)(void);
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
f=(void *) ((((u32)dreq->wValue)<<16)+(u32)dreq->wIndex);
__dcache_writeback_all();
//stop udc connet before execute program!
jz_writeb(USB_REG_POWER,0x0); //High speed
//dprintf("\n Execute program at %x",(u32)f);
f();
return ERR_OK;
}
int NOR_OPS_Handle(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
return ERR_OK;
}
int NAND_OPS_Handle(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
u32 temp;
int option;
u8 CSn;
CSn = (dreq->wValue>>4) & 0xff;
option = (dreq->wValue>>12) & 0xff;
nand_enable(CSn);
switch ((dreq->wValue)&0xf)
{
case NAND_QUERY:
dprintf("\n Request : NAND_QUERY!");
nand_query((u8 *)Bulk_in_buf);
HW_SendPKT(1, Bulk_in_buf, 8);
handshake_PKT[3]=(u16)ERR_OK;
udc_state = BULK_IN;
break;
case NAND_INIT:
dprintf("\n Request : NAND_INIT!");
break;
case NAND_MARK_BAD:
dprintf("\n Request : NAND_MARK_BAD!");
ret_dat = nand_mark_bad(start_addr);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
udc_state = IDLE;
break;
case NAND_READ_OOB:
dprintf("\n Request : NAND_READ_OOB!");
memset(Bulk_in_buf,0,ops_length*Hand.nand_ps);
ret_dat = nand_read_oob(Bulk_in_buf,start_addr,ops_length);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
udc_state = BULK_IN;
break;
case NAND_READ_RAW:
dprintf("\n Request : NAND_READ_RAW!");
switch (option)
{
case OOB_ECC:
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
udc_state = BULK_IN;
break;
default:
nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
udc_state = BULK_IN;
break;
}
break;
case NAND_ERASE:
dprintf("\n Request : NAND_ERASE!");
ret_dat = nand_erase(ops_length,start_addr,
Hand.nand_force_erase);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
udc_state = IDLE;
dprintf("\n Request : NAND_ERASE_FINISH!");
break;
case NAND_READ:
dprintf("\n Request : NAND_READ!");
// dprintf("\n Option : %x",option);
switch (option)
{
case OOB_ECC:
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_ECC);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os ));
udc_state = BULK_IN;
break;
case OOB_NO_ECC:
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_NO_ECC);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
udc_state = BULK_IN;
break;
case NO_OOB:
ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,NO_OOB);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
udc_state = BULK_IN;
break;
}
dprintf("\n Request : NAND_READ_FUNISH!");
break;
case NAND_PROGRAM:
dprintf("\n Request : NAND_PROGRAM!");
// dprintf("\n Option : %x",option);
ret_dat = nand_program((void *)Bulk_out_buf,
start_addr,ops_length,option);
dprintf("\n NAND_PROGRAM finish!");
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
udc_state = IDLE;
break;
case NAND_READ_TO_RAM:
dprintf("\n Request : NAND_READNAND!");
nand_read((u8 *)ram_addr,start_addr,ops_length,NO_OOB);
__dcache_writeback_all();
handshake_PKT[3]=(u16)ERR_OK;
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
udc_state = IDLE;
break;
default:
nand_disable(CSn);
return ERR_OPS_NOTSUPPORT;
}
return ERR_OK;
}
int SDRAM_OPS_Handle(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
u32 temp,i;
u8 *obj;
switch ((dreq->wValue)&0xf)
{
case SDRAM_LOAD:
// dprintf("\n Request : SDRAM_LOAD!");
ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_out_buf,ops_length);
handshake_PKT[0] = (u16) ret_dat;
handshake_PKT[1] = (u16) (ret_dat>>16);
HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
udc_state = IDLE;
break;
}
return ERR_OK;
}
void Borad_Init()
{
dprintf("\n Borad_init! ");
serial_put_hex(Hand.fw_args.cpu_id);
switch (Hand.fw_args.cpu_id)
{
case 0x4740:
//Init nand flash
nand_init_4740(Hand.nand_bw,Hand.nand_rc,Hand.nand_ps,Hand.nand_ppb,
Hand.nand_bbpage,Hand.nand_bbpos,Hand.nand_force_erase,Hand.nand_eccpos);
nand_program=nand_program_4740;
nand_erase =nand_erase_4740;
nand_read =nand_read_4740;
nand_read_oob=nand_read_oob_4740;
nand_read_raw=nand_read_raw_4740;
nand_query = nand_query_4740;
nand_enable = nand_enable_4740;
nand_disable= nand_disable_4740;
nand_mark_bad = nand_mark_bad_4740;
break;
case 0x4750:
//Init nand flash
nand_init_4750(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
Hand.nand_ppb, Hand.nand_bchbit, Hand.nand_eccpos,
Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase);
nand_program=nand_program_4750;
nand_erase =nand_erase_4750;
nand_read =nand_read_4750;
nand_read_oob=nand_read_oob_4750;
nand_read_raw=nand_read_raw_4750;
nand_query = nand_query_4750;
nand_enable = nand_enable_4750;
nand_disable= nand_disable_4750;
nand_mark_bad = nand_mark_bad_4750;
break;
default:
serial_puts("Not support CPU ID!");
}
}
int CONFIGRATION_Handle(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
switch ((dreq->wValue)&0xf)
{
case DS_flash_info:
dprintf("\n configration :DS_flash_info_t!");
config_flash_info();
break;
case DS_hand:
dprintf("\n configration :DS_hand_t!");
config_hand();
break;
default:;
}
Borad_Init();
return ERR_OK;
}

View File

@@ -0,0 +1,149 @@
/*
* Handle operation of Jz CPU's cache
*
* Copyright (C) 2006 Ingenic Semiconductor Inc.
* Author: Seeger Chin <seeger.chin@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#define u32 unsigned int
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
#define Index_Load_Tag_I 0x04
#define Index_Load_Tag_D 0x05
#define Index_Store_Tag_I 0x08
#define Index_Store_Tag_D 0x09
#define Hit_Invalidate_I 0x10
#define Hit_Invalidate_D 0x11
#define Hit_Writeback_Inv_D 0x15
#define Hit_Writeback_I 0x18
#define Hit_Writeback_D 0x19
#define CACHE_SIZE 16*1024
#define CACHE_LINE_SIZE 32
#define KSEG0 0x80000000
#define K0_TO_K1() \
do { \
unsigned long __k0_addr; \
\
__asm__ __volatile__( \
"la %0, 1f\n\t" \
"or %0, %0, %1\n\t" \
"jr %0\n\t" \
"nop\n\t" \
"1: nop\n" \
: "=&r"(__k0_addr) \
: "r" (0x20000000) ); \
} while(0)
#define K1_TO_K0() \
do { \
unsigned long __k0_addr; \
__asm__ __volatile__( \
"nop;nop;nop;nop;nop;nop;nop\n\t" \
"la %0, 1f\n\t" \
"jr %0\n\t" \
"nop\n\t" \
"1: nop\n" \
: "=&r" (__k0_addr)); \
} while (0)
#define INVALIDATE_BTB() \
do { \
unsigned long tmp; \
__asm__ __volatile__( \
".set mips32\n\t" \
"mfc0 %0, $16, 7\n\t" \
"nop\n\t" \
"ori %0, 2\n\t" \
"mtc0 %0, $16, 7\n\t" \
"nop\n\t" \
".set mips2\n\t" \
: "=&r" (tmp)); \
} while (0)
#define SYNC_WB() __asm__ __volatile__ ("sync")
#define cache_op(op,addr) \
__asm__ __volatile__( \
" .set noreorder \n" \
" .set mips32\n\t \n" \
" cache %0, %1 \n" \
" .set mips0 \n" \
" .set reorder" \
: \
: "i" (op), "m" (*(unsigned char *)(addr)))
void __flush_dcache_line(unsigned long addr)
{
cache_op(Hit_Writeback_Inv_D, addr);
SYNC_WB();
}
void __icache_invalidate_all(void)
{
u32 i;
K0_TO_K1();
asm volatile (".set noreorder\n"
".set mips32\n\t"
"mtc0\t$0,$28\n\t"
"mtc0\t$0,$29\n"
".set mips0\n"
".set reorder\n");
for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
cache_op(Index_Store_Tag_I, i);
K1_TO_K0();
INVALIDATE_BTB();
}
void __dcache_invalidate_all(void)
{
u32 i;
asm volatile (".set noreorder\n"
".set mips32\n\t"
"mtc0\t$0,$28\n\t"
"mtc0\t$0,$29\n"
".set mips0\n"
".set reorder\n");
for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
cache_op(Index_Store_Tag_D, i);
}
void __dcache_writeback_all(void)
{
u32 i;
for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
cache_op(Index_Writeback_Inv_D, i);
SYNC_WB();
}
void dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
unsigned long end, a;
if (size >= CACHE_SIZE) {
__dcache_writeback_all();
}
else {
unsigned long dc_lsize = CACHE_LINE_SIZE;
a = addr & ~(dc_lsize - 1);
end = (addr + size - 1) & ~(dc_lsize - 1);
while (1) {
__flush_dcache_line(a); /* Hit_Writeback_Inv_D */
if (a == end)
break;
a += dc_lsize;
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* head.S
*
* Entry point of the firmware.
* The firmware code are executed in the ICache.
* Do not edit!
* Copyright (C) 2006 Ingenic Semiconductor Inc.
*
*/
.text
.extern c_main
.globl _start
.set noreorder
_start:
b real_start
nop
.word 0x0 // its address == start address + 8
.word 0x0
.word 0x0
.word 0x0
.word 0x0
.word 0x0
.word 0x0
.word 0x0
real_start:
//----------------------------------------------------
// setup stack, jump to C code
//----------------------------------------------------
add $29, $20, 0x3ffff0 // sp locate at start address offset 0x2ffff0
add $25, $20, 0x40 // t9 = usb_main()
j $25
nop
.set reorder

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "usb_boot_defines.h"
extern void usb_main();
unsigned int start_addr,got_start,got_end;
extern unsigned int UART_BASE;
struct fw_args *fw_args;
void c_main(void)
{
volatile unsigned int addr,offset;
/* get absolute start address */
__asm__ __volatile__(
"move %0, $20\n\t"
: "=r"(start_addr)
:
);
/* get related GOT address */
__asm__ __volatile__(
"la $4, _GLOBAL_OFFSET_TABLE_\n\t"
"move %0, $4\n\t"
"la $5, _got_end\n\t"
"move %1, $5\n\t"
: "=r"(got_start),"=r"(got_end)
:
);
/* calculate offset and correct GOT*/
offset = start_addr - 0x80000000;
got_start += offset;
got_end += offset;
for ( addr = got_start + 8; addr < got_end; addr += 4 )
{
*((volatile unsigned int *)(addr)) += offset; //add offset to correct all GOT
}
fw_args = (struct fw_args *)(start_addr + 0x8); //get the fw args from memory
if ( fw_args->use_uart > 3 ) fw_args->use_uart = 0;
UART_BASE = 0xB0030000 + fw_args->use_uart * 0x1000;
serial_puts("Start address is :");
serial_put_hex(start_addr);
serial_puts("Address offset is:");
serial_put_hex(offset);
serial_puts("GOT correct to :");
serial_put_hex(got_start);
usb_main();
}

View File

@@ -0,0 +1,829 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "nandflash.h"
#include "jz4740.h"
#include "usb_boot.h"
#include "usb_boot_defines.h"
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
#define __nand_ecc_rs_encoding() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
#define __nand_ecc_rs_decoding() (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
#define __nand_ready() ((REG_GPIO_PXPIN(2) & 0x40000000) ? 1 : 0)
#define __nand_ecc() (REG_EMC_NFECC & 0x00ffffff)
#define __nand_cmd(n) (REG8(cmdport) = (n))
#define __nand_addr(n) (REG8(addrport) = (n))
#define __nand_data8() REG8(dataport)
#define __nand_data16() REG16(dataport)
#define CMD_READA 0x00
#define CMD_READB 0x01
#define CMD_READC 0x50
#define CMD_ERASE_SETUP 0x60
#define CMD_ERASE 0xD0
#define CMD_READ_STATUS 0x70
#define CMD_CONFIRM 0x30
#define CMD_SEQIN 0x80
#define CMD_PGPROG 0x10
#define CMD_READID 0x90
#define OOB_BAD_OFF 0x00
#define OOB_ECC_OFF 0x04
#define OP_ERASE 0
#define OP_WRITE 1
#define OP_READ 2
#define ECC_BLOCK 512
#define ECC_POS 6
#define PAR_SIZE 9
#define ECC_SIZE 36
static volatile unsigned char *gpio_base = (volatile unsigned char *)0xb0010000;
static volatile unsigned char *emc_base = (volatile unsigned char *)0xb3010000;
static volatile unsigned char *addrport = (volatile unsigned char *)0xb8010000;
static volatile unsigned char *dataport = (volatile unsigned char *)0xb8000000;
static volatile unsigned char *cmdport = (volatile unsigned char *)0xb8008000;
static int bus = 8, row = 2, pagesize = 2048, oobsize = 64, ppb = 128;
static int bad_block_pos,bad_block_page,force_erase,ecc_pos,wp_pin;
extern struct hand Hand;
//static u8 data_buf[2048] = {0};
static u8 oob_buf[256] = {0};
extern u16 handshake_PKT[4];
#define dprintf(x) serial_puts(x)
static unsigned int EMC_CSN[4]=
{
0xb8000000,
0xb4000000,
0xa8000000,
0xa4000000
};
static inline void __nand_sync(void)
{
unsigned int timeout = 100000;
while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
while (!(REG_GPIO_PXPIN(2) & 0x40000000));
}
static void select_chip(int block)
{
int t;
if (!Hand.nand_bpc) return;
t = (block / Hand.nand_bpc) % 4;
addrport = (volatile unsigned char *)(EMC_CSN[t] + 0x10000);
dataport = (volatile unsigned char *)EMC_CSN[t];
cmdport = (volatile unsigned char *)(EMC_CSN[t] + 0x8000);
}
static int read_oob(void *buf, u32 size, u32 pg);
static int nand_data_write8(char *buf, int count);
static int nand_data_write16(char *buf, int count);
static int nand_data_read8(char *buf, int count);
static int nand_data_read16(char *buf, int count);
static int (*write_proc)(char *, int) = NULL;
static int (*read_proc)(char *, int) = NULL;
static nand_init_gpio(void)
{
//modify this fun to a specifical borad
//this fun init those gpio use by all flash chip
//select the gpio function related to flash chip
__gpio_as_nand();
}
inline void nand_enable_4740(unsigned int csn)
{
//modify this fun to a specifical borad
//this fun to enable the chip select pin csn
//the choosn chip can work after this fun
//dprintf("\n Enable chip select :%d",csn);
__nand_enable();
}
inline void nand_disable_4740(unsigned int csn)
{
//modify this fun to a specifical borad
//this fun to enable the chip select pin csn
//the choosn chip can not work after this fun
//dprintf("\n Disable chip select :%d",csn);
__nand_disable();
}
unsigned int nand_query_4740(u8 *id)
{
__nand_sync();
__nand_cmd(CMD_READID);
__nand_addr(0);
id[0] = __nand_data8(); //VID
id[1] = __nand_data8(); //PID
id[2] = __nand_data8(); //CHIP ID
id[3] = __nand_data8(); //PAGE ID
id[4] = __nand_data8(); //PLANE ID
return 0;
}
int nand_init_4740(int bus_width, int row_cycle, int page_size, int page_per_block,
int bbpage,int bbpos,int force,int ep)
{
bus = bus_width;
row = row_cycle;
pagesize = page_size;
oobsize = pagesize / 32;
ppb = page_per_block;
bad_block_pos = bbpos;
bad_block_page = bbpage;
force_erase = force;
ecc_pos = ep;
wp_pin = Hand.nand_wppin;
// nand_enable(0);
/* Initialize NAND Flash Pins */
if (wp_pin)
{
__gpio_as_output(wp_pin);
__gpio_disable_pull(wp_pin);
}
nand_init_gpio();
select_chip(0);
REG_EMC_SMCR1 = 0x0fff7700; //slow speed
// REG_EMC_SMCR1 = 0x04444400; //normal speed
// REG_EMC_SMCR1 = 0x0d221200; //fast speed
if (bus == 8) {
write_proc = nand_data_write8;
read_proc = nand_data_read8;
} else {
write_proc = nand_data_write16;
read_proc = nand_data_read16;
}
return 0;
}
int nand_fini_4740(void)
{
__nand_disable();
return 0;
}
/*
* Read oob <pagenum> pages from <startpage> page.
* Don't skip bad block.
* Don't use HW ECC.
*/
u32 nand_read_oob_4740(void *buf, u32 startpage, u32 pagenum)
{
u32 cnt, cur_page;
u8 *tmpbuf;
tmpbuf = (u8 *)buf;
cur_page = startpage;
cnt = 0;
while (cnt < pagenum) {
read_oob((void *)tmpbuf, oobsize, cur_page);
tmpbuf += oobsize;
cur_page++;
cnt++;
}
return cur_page;
}
static int nand_check_block(u32 block)
{
u32 pg,i;
if ( bad_block_page >= ppb ) //do absolute bad block detect!
{
pg = block * ppb + 0;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
return 1;
}
pg = block * ppb + 1;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
return 1;
}
pg = block * ppb + ppb - 2 ;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
return 1;
}
pg = block * ppb + ppb - 1 ;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
return 1;
}
}
else
{
pg = block * ppb + bad_block_page;
read_oob(oob_buf, oobsize, pg);
if (oob_buf[bad_block_pos] != 0xff)
{
serial_puts("Skip a bad block\n");
return 1;
}
}
return 0;
}
/*
* Read data <pagenum> pages from <startpage> page.
* Don't skip bad block.
* Don't use HW ECC.
*/
u32 nand_read_raw_4740(void *buf, u32 startpage, u32 pagenum, int option)
{
u32 cnt, j;
u32 cur_page, rowaddr;
u8 *tmpbuf;
tmpbuf = (u8 *)buf;
cur_page = startpage;
cnt = 0;
while (cnt < pagenum) {
select_chip(cnt / ppb);
if ((cur_page % ppb) == 0) {
if (nand_check_block(cur_page / ppb)) {
cur_page += ppb; // Bad block, set to next block
continue;
}
}
__nand_cmd(CMD_READA);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
__nand_sync();
read_proc(tmpbuf, pagesize);
tmpbuf += pagesize;
if (option != NO_OOB)
{
read_oob(tmpbuf, oobsize, cur_page);
tmpbuf += oobsize;
}
cur_page++;
cnt++;
}
return cur_page;
}
u32 nand_erase_4740(int blk_num, int sblk, int force)
{
int i, j;
u32 cur, rowaddr;
if (wp_pin)
__gpio_set_pin(wp_pin);
cur = sblk * ppb;
for (i = 0; i < blk_num; ) {
rowaddr = cur;
select_chip(cur / ppb);
if ( !force )
{
if (nand_check_block(cur/ppb))
{
cur += ppb;
blk_num += Hand.nand_plane;
continue;
}
}
__nand_cmd(CMD_ERASE_SETUP);
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
__nand_cmd(CMD_ERASE);
__nand_sync();
__nand_cmd(CMD_READ_STATUS);
if (__nand_data8() & 0x01)
{
serial_puts("Erase fail at ");
serial_put_hex(cur / ppb);
nand_mark_bad_4740(cur/ppb);
cur += ppb;
blk_num += Hand.nand_plane;
continue;
}
cur += ppb;
i++;
}
if (wp_pin)
__gpio_clear_pin(wp_pin);
return cur;
}
static int read_oob(void *buf, u32 size, u32 pg)
{
u32 i, coladdr, rowaddr;
select_chip(pg / ppb);
if (pagesize == 512)
coladdr = 0;
else
coladdr = pagesize;
if (pagesize == 512)
/* Send READOOB command */
__nand_cmd(CMD_READC);
else
/* Send READ0 command */
__nand_cmd(CMD_READA);
/* Send column address */
__nand_addr(coladdr & 0xff);
if (pagesize != 512)
__nand_addr(coladdr >> 8);
/* Send page address */
rowaddr = pg;
for (i = 0; i < row; i++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
/* Send READSTART command for 2048 ps NAND */
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
/* Wait for device ready */
__nand_sync();
/* Read oob data */
read_proc(buf, size);
if (pagesize == 512)
__nand_sync();
return 0;
}
void rs_correct(unsigned char *buf, int idx, int mask)
{
int i, j;
unsigned short d, d1, dm;
i = (idx * 9) >> 3;
j = (idx * 9) & 0x7;
i = (j == 0) ? (i - 1) : i;
j = (j == 0) ? 7 : (j - 1);
d = (buf[i] << 8) | buf[i - 1];
d1 = (d >> j) & 0x1ff;
d1 ^= mask;
dm = ~(0x1ff << j);
d = (d & dm) | (d1 << j);
buf[i - 1] = d & 0xff;
buf[i] = (d >> 8) & 0xff;
}
/*
* Read data <pagenum> pages from <startpage> page.
* Skip bad block if detected.
* HW ECC is used.
*/
u32 nand_read_4740(void *buf, u32 startpage, u32 pagenum, int option)
{
u32 j, k;
u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
u8 *tmpbuf,flag = 0;
ecccnt = pagesize / ECC_BLOCK;
cur_page = startpage;
cnt = 0;
tmpbuf = buf;
handshake_PKT[3] = 0;
while (cnt < pagenum) {
select_chip(cnt / ppb);
/* If this is the first page of the block, check for bad. */
if ((cur_page % ppb) == 0) {
cur_blk = cur_page / ppb;
if (nand_check_block(cur_blk)) {
cur_page += ppb; // Bad block, set to next block
continue;
}
}
/* read oob first */
read_oob(oob_buf, oobsize, cur_page);
__nand_cmd(CMD_READA);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
__nand_sync();
for (j = 0; j < ecccnt; j++) {
volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
u32 stat;
flag = 0;
REG_EMC_NFINTS = 0x0;
__nand_ecc_rs_decoding();
read_proc(tmpbuf, ECC_BLOCK);
for (k = 0; k < PAR_SIZE; k++) {
*paraddr++ = oob_buf[ecc_pos + j*PAR_SIZE + k];
if (oob_buf[ecc_pos + j*PAR_SIZE + k] != 0xff)
flag = 1;
}
REG_EMC_NFECR |= EMC_NFECR_PRDY;
__nand_ecc_decode_sync();
__nand_ecc_disable();
/* Check decoding */
stat = REG_EMC_NFINTS;
if (stat & EMC_NFINTS_ERR) {
if (stat & EMC_NFINTS_UNCOR) {
if (flag)
{
serial_puts("\nUncorrectable error occurred\n");
serial_put_hex(cur_page);
handshake_PKT[3] = 1;
}
}
else {
handshake_PKT[3] = 0;
u32 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
switch (errcnt) {
case 4:
rs_correct(tmpbuf, (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
case 3:
rs_correct(tmpbuf, (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
case 2:
rs_correct(tmpbuf, (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
case 1:
rs_correct(tmpbuf, (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT, (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT);
break;
default:
break;
}
}
}
/* increment pointer */
tmpbuf += ECC_BLOCK;
}
switch (option)
{
case OOB_ECC:
for (j = 0; j < oobsize; j++)
tmpbuf[j] = oob_buf[j];
tmpbuf += oobsize;
break;
case OOB_NO_ECC:
for (j = 0; j < ecccnt * PAR_SIZE; j++)
oob_buf[ecc_pos + j] = 0xff;
for (j = 0; j < oobsize; j++)
tmpbuf[j] = oob_buf[j];
tmpbuf += oobsize;
break;
case NO_OOB:
break;
}
cur_page++;
cnt++;
}
return cur_page;
}
u32 nand_program_4740(void *context, int spage, int pages, int option)
{
u32 i, j, cur, rowaddr;
u8 *tmpbuf;
u32 ecccnt,oobsize_sav,ecccnt_sav,eccpos_sav;
u8 ecc_buf[256];
if (wp_pin)
__gpio_set_pin(wp_pin);
restart:
tmpbuf = (u8 *)context;
ecccnt_sav = ecccnt = pagesize / ECC_BLOCK;
oobsize_sav = oobsize;
eccpos_sav = ecc_pos;
i = 0;
cur = spage;
while (i < pages) {
select_chip(cur / ppb);
#if 1
if ((pagesize == 4096) && (cur < 8)) {
ecccnt = 4;
oobsize = 64;
ecc_pos = 6;
} else {
ecccnt = ecccnt_sav;
oobsize = oobsize_sav;
ecc_pos = eccpos_sav;
}
/* Skip 16KB after nand_spl if pagesize=4096 */
if ((pagesize == 4096) && (cur == 8))
tmpbuf += 16 * 1024;
#endif
if ((cur % ppb) == 0) {
if (nand_check_block(cur / ppb)) {
cur += ppb; // Bad block, set to next block
continue;
}
}
if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
{
for ( j = 0 ; j < pagesize + oobsize; j ++)
{
if (tmpbuf[j] != 0xff)
break;
}
if ( j == oobsize + pagesize )
{
tmpbuf += ( pagesize + oobsize ) ;
i ++;
cur ++;
continue;
}
}
if (pagesize == 512)
__nand_cmd(CMD_READA);
__nand_cmd(CMD_SEQIN);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
switch (option)
{
case OOB_ECC:
write_proc(tmpbuf, pagesize); //write data
tmpbuf += pagesize;
write_proc((u8 *)tmpbuf, oobsize); //write oob
tmpbuf += oobsize;
break;
case OOB_NO_ECC:
for (j = 0; j < ecccnt; j++) {
volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
int k;
REG_EMC_NFINTS = 0x0;
__nand_ecc_rs_encoding();
write_proc(tmpbuf, ECC_BLOCK);
__nand_ecc_encode_sync();
__nand_ecc_disable();
/* Read PAR values */
for (k = 0; k < PAR_SIZE; k++) {
ecc_buf[j*PAR_SIZE+k] = *paraddr++;
}
tmpbuf += ECC_BLOCK;
}
for (j = 0; j < oobsize; j++) {
oob_buf[j] = tmpbuf[j];
}
for (j = 0; j < ecccnt*PAR_SIZE; j++)
oob_buf[ecc_pos + j] = ecc_buf[j];
write_proc((u8 *)oob_buf, oobsize);
tmpbuf += oobsize;
break;
case NO_OOB: //bin image
/* write out data */
for (j = 0; j < ecccnt; j++) {
volatile u8 *paraddr = (volatile u8 *)EMC_NFPAR0;
int k;
REG_EMC_NFINTS = 0x0;
__nand_ecc_rs_encoding();
write_proc(tmpbuf, ECC_BLOCK);
__nand_ecc_encode_sync();
__nand_ecc_disable();
/* Read PAR values */
for (k = 0; k < PAR_SIZE; k++) {
ecc_buf[j*PAR_SIZE+k] = *paraddr++;
}
tmpbuf += ECC_BLOCK;
}
for (j = 0; j < oobsize; j++) {
oob_buf[j] = 0xff;
}
oob_buf[2] = 0;
oob_buf[3] = 0;
oob_buf[4] = 0;
for (j = 0; j < ecccnt*PAR_SIZE; j++) {
oob_buf[ecc_pos + j] = ecc_buf[j];
}
write_proc((u8 *)oob_buf, oobsize);
break;
}
/* send program confirm command */
__nand_cmd(CMD_PGPROG);
__nand_sync();
__nand_cmd(CMD_READ_STATUS);
if (__nand_data8() & 0x01) /* page program error */
{
serial_puts("Skip a write fail block\n");
nand_erase_4740( 1, cur/ppb, 1); //force erase before
nand_mark_bad_4740(cur/ppb);
spage += ppb;
goto restart;
}
i ++;
cur ++;
}
if (wp_pin)
__gpio_clear_pin(wp_pin);
ecccnt = ecccnt_sav;
oobsize = oobsize_sav;
ecc_pos = eccpos_sav;
return cur;
}
static u32 nand_mark_bad_page(u32 page)
{
u8 badbuf[4096 + 128];
u32 i;
if (wp_pin)
__gpio_set_pin(wp_pin);
//all set to 0x00
for (i = 0; i < pagesize + oobsize; i++)
badbuf[i] = 0x00;
__nand_cmd(CMD_READA);
__nand_cmd(CMD_SEQIN);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
for (i = 0; i < row; i++) {
__nand_addr(page & 0xff);
page >>= 8;
}
write_proc((char *)badbuf, pagesize + oobsize);
__nand_cmd(CMD_PGPROG);
__nand_sync();
if (wp_pin)
__gpio_clear_pin(wp_pin);
return page;
}
u32 nand_mark_bad_4740(int block)
{
u32 rowaddr;
// nand_erase_4740( 1, block, 1); //force erase before
if ( bad_block_page >= ppb ) //absolute bad block mark!
{ //mark four page!
rowaddr = block * ppb + 0;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + 1;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + ppb - 2;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + ppb - 1;
nand_mark_bad_page(rowaddr);
}
else //mark one page only
{
rowaddr = block * ppb + bad_block_page;
nand_mark_bad_page(rowaddr);
}
return rowaddr;
}
static int nand_data_write8(char *buf, int count)
{
int i;
u8 *p = (u8 *)buf;
for (i=0;i<count;i++)
__nand_data8() = *p++;
return 0;
}
static int nand_data_write16(char *buf, int count)
{
int i;
u16 *p = (u16 *)buf;
for (i=0;i<count/2;i++)
__nand_data16() = *p++;
return 0;
}
static int nand_data_read8(char *buf, int count)
{
int i;
u8 *p = (u8 *)buf;
for (i=0;i<count;i++)
*p++ = __nand_data8();
return 0;
}
static int nand_data_read16(char *buf, int count)
{
int i;
u16 *p = (u16 *)buf;
for (i=0;i<count/2;i++)
*p++ = __nand_data16();
return 0;
}

View File

@@ -0,0 +1,844 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4750.h"
#include "nandflash.h"
#include "usb_boot.h"
#include "usb_boot_defines.h"
#define dprintf(n...)
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
#define __nand_ready() ((REG_GPIO_PXPIN(2) & 0x08000000) ? 1 : 0)
#define __nand_cmd(n) (REG8(cmdport) = (n))
#define __nand_addr(n) (REG8(addrport) = (n))
#define __nand_data8() REG8(dataport)
#define __nand_data16() REG16(dataport)
#define CMD_READA 0x00
#define CMD_READB 0x01
#define CMD_READC 0x50
#define CMD_ERASE_SETUP 0x60
#define CMD_ERASE 0xD0
#define CMD_READ_STATUS 0x70
#define CMD_CONFIRM 0x30
#define CMD_SEQIN 0x80
#define CMD_PGPROG 0x10
#define CMD_READID 0x90
#define ECC_BLOCK 512
static volatile unsigned char *gpio_base = (volatile unsigned char *)0xb0010000;
static volatile unsigned char *emc_base = (volatile unsigned char *)0xb3010000;
static volatile unsigned char *addrport = (volatile unsigned char *)0xb8010000;
static volatile unsigned char *dataport = (volatile unsigned char *)0xb8000000;
static volatile unsigned char *cmdport = (volatile unsigned char *)0xb8008000;
static int bus = 8, row = 2, pagesize = 512, oobsize = 16, ppb = 32;
static int eccpos = 3, bchbit = 8, par_size = 13, forceerase = 1, wp_pin;
static int oobfs = 0; /* 1:store file system information in oob, 0:don't store */
static int oobecc = 0; /* Whether the oob data of the binary contains ECC data? */
static int bad_block_page = 127; /* Specify the page number of badblock flag inside a block */
static u32 bad_block_pos = 0; /* Specify the badblock flag offset inside the oob */
static u8 oob_buf[256] = {0};
extern struct hand Hand;
extern u16 handshake_PKT[4];
static inline void __nand_sync(void)
{
unsigned int timeout = 10000;
while ((REG_GPIO_PXPIN(2) & 0x08000000) && timeout--);
while (!(REG_GPIO_PXPIN(2) & 0x08000000));
}
static int read_oob(void *buf, u32 size, u32 pg);
static int nand_data_write8(char *buf, int count);
static int nand_data_write16(char *buf, int count);
static int nand_data_read8(char *buf, int count);
static int nand_data_read16(char *buf, int count);
static int (*write_proc)(char *, int) = NULL;
static int (*read_proc)(char *, int) = NULL;
inline void nand_enable_4750(unsigned int csn)
{
//modify this fun to a specifical borad
//this fun to enable the chip select pin csn
//the choosn chip can work after this fun
//dprintf("\n Enable chip select :%d",csn);
__nand_enable();
}
inline void nand_disable_4750(unsigned int csn)
{
//modify this fun to a specifical borad
//this fun to enable the chip select pin csn
//the choosn chip can not work after this fun
//dprintf("\n Disable chip select :%d",csn);
__nand_disable();
}
unsigned int nand_query_4750(u8 *id)
{
__nand_sync();
__nand_cmd(CMD_READID);
__nand_addr(0);
id[0] = __nand_data8(); //VID
id[1] = __nand_data8(); //PID
id[2] = __nand_data8(); //CHIP ID
id[3] = __nand_data8(); //PAGE ID
id[4] = __nand_data8(); //PLANE ID
return 0;
}
int nand_init_4750(int bus_width, int row_cycle, int page_size, int page_per_block,
int bch_bit, int ecc_pos, int bad_pos, int bad_page, int force)
{
bus = bus_width;
row = row_cycle;
pagesize = page_size;
oobsize = pagesize / 32;
ppb = page_per_block;
bchbit = bch_bit;
forceerase = force;
eccpos = ecc_pos;
bad_block_pos = bad_pos;
bad_block_page = bad_page;
wp_pin = Hand.nand_wppin;
if (bchbit == 8)
par_size = 13;
else
par_size = 7;
#if 0
gpio_base = (u8 *)gbase;
emc_base = (u8 *)ebase;
addrport = (u8 *)aport;
dataport = (u8 *)dport;
cmdport = (u8 *)cport;
#endif
/* Initialize NAND Flash Pins */
if (bus == 8) {
__gpio_as_nand_8bit();
}
if (wp_pin)
{
__gpio_as_output(wp_pin);
__gpio_disable_pull(wp_pin);
}
__nand_enable();
// REG_EMC_SMCR1 = 0x0fff7700; //slow speed
REG_EMC_SMCR1 = 0x04444400; //normal speed
// REG_EMC_SMCR1 = 0x0d221200; //fast speed
/* If ECCPOS isn't configured in config file, the initial value is 0 */
if (eccpos == 0) {
eccpos = 3;
}
if (bus == 8) {
write_proc = nand_data_write8;
read_proc = nand_data_read8;
} else {
write_proc = nand_data_write16;
read_proc = nand_data_read16;
}
return 0;
}
int nand_fini_4750(void)
{
__nand_disable();
return 0;
}
/*
* Read oob <pagenum> pages from <startpage> page.
* Don't skip bad block.
* Don't use HW ECC.
*/
u32 nand_read_oob_4750(void *buf, u32 startpage, u32 pagenum)
{
u32 cnt, cur_page;
u8 *tmpbuf;
tmpbuf = (u8 *)buf;
cur_page = startpage;
cnt = 0;
while (cnt < pagenum) {
read_oob((void *)tmpbuf, oobsize, cur_page);
tmpbuf += oobsize;
cur_page++;
cnt++;
}
return cur_page;
}
static int nand_check_block(u32 block)
{
u32 pg,i;
if ( bad_block_page >= ppb ) //do absolute bad block detect!
{
pg = block * ppb + 0;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
pg = block * ppb + 1;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
pg = block * ppb + ppb - 2 ;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
pg = block * ppb + ppb - 1 ;
read_oob(oob_buf, oobsize, pg);
if ( oob_buf[0] != 0xff || oob_buf[1] != 0xff )
{
serial_puts("Absolute skip a bad block\n");
serial_put_hex(block);
return 1;
}
}
else
{
pg = block * ppb + bad_block_page;
read_oob(oob_buf, oobsize, pg);
if (oob_buf[bad_block_pos] != 0xff)
{
serial_puts("Skip a bad block at");
serial_put_hex(block);
return 1;
}
}
return 0;
}
/*
* Read data <pagenum> pages from <startpage> page.
* Don't skip bad block.
* Don't use HW ECC.
*/
u32 nand_read_raw_4750(void *buf, u32 startpage, u32 pagenum, int option)
{
u32 cnt, j;
u32 cur_page, rowaddr;
u8 *tmpbuf;
tmpbuf = (u8 *)buf;
cur_page = startpage;
cnt = 0;
while (cnt < pagenum) {
if ((cur_page % ppb) == 0) {
if (nand_check_block(cur_page / ppb)) {
cur_page += ppb; // Bad block, set to next block
continue;
}
}
__nand_cmd(CMD_READA);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
__nand_sync();
read_proc(tmpbuf, pagesize);
tmpbuf += pagesize;
if (option != NO_OOB)
{
read_oob(tmpbuf, oobsize, cur_page);
tmpbuf += oobsize;
}
cur_page++;
cnt++;
}
return cur_page;
}
u32 nand_erase_4750(int blk_num, int sblk, int force)
{
int i, j;
u32 cur, rowaddr;
if (wp_pin)
__gpio_set_pin(wp_pin);
cur = sblk * ppb;
for (i = 0; i < blk_num; i++) {
rowaddr = cur;
if (!force) /* if set, erase anything */
if (nand_check_block(cur/ppb))
{
cur += ppb;
blk_num += Hand.nand_plane;
continue;
}
__nand_cmd(CMD_ERASE_SETUP);
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
__nand_cmd(CMD_ERASE);
__nand_sync();
__nand_cmd(CMD_READ_STATUS);
if (__nand_data8() & 0x01)
{
serial_puts("Erase fail at ");
serial_put_hex(cur / ppb);
nand_mark_bad_4750(cur / ppb);
cur += ppb;
blk_num += Hand.nand_plane;
continue;
}
cur += ppb;
}
if (wp_pin)
__gpio_clear_pin(wp_pin);
return cur;
}
static int read_oob(void *buf, u32 size, u32 pg)
{
u32 i, coladdr, rowaddr;
if (pagesize == 512)
coladdr = 0;
else
coladdr = pagesize;
if (pagesize == 512)
/* Send READOOB command */
__nand_cmd(CMD_READC);
else
/* Send READ0 command */
__nand_cmd(CMD_READA);
/* Send column address */
__nand_addr(coladdr & 0xff);
if (pagesize != 512)
__nand_addr(coladdr >> 8);
/* Send page address */
rowaddr = pg;
for (i = 0; i < row; i++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
/* Send READSTART command for 2048 or 4096 ps NAND */
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
/* Wait for device ready */
__nand_sync();
/* Read oob data */
read_proc(buf, size);
if (pagesize == 512)
__nand_sync();
return 0;
}
static void bch_correct(unsigned char *dat, int idx)
{
int i, bit; // the 'bit' of i byte is error
i = (idx - 1) >> 3;
bit = (idx - 1) & 0x7;
dat[i] ^= (1 << bit);
}
/*
* Read data <pagenum> pages from <startpage> page.
* Skip bad block if detected.
* HW ECC is used.
*/
u32 nand_read_4750(void *buf, u32 startpage, u32 pagenum, int option)
{
u32 j, k;
u32 cur_page, cur_blk, cnt, rowaddr, ecccnt;
u8 *tmpbuf, *p, flag = 0;
u32 oob_per_eccsize;
ecccnt = pagesize / ECC_BLOCK;
oob_per_eccsize = eccpos / ecccnt;
cur_page = startpage;
cnt = 0;
tmpbuf = buf;
while (cnt < pagenum) {
/* If this is the first page of the block, check for bad. */
if ((cur_page % ppb) == 0) {
cur_blk = cur_page / ppb;
if (nand_check_block(cur_blk)) {
cur_page += ppb; // Bad block, set to next block
continue;
}
}
__nand_cmd(CMD_READA);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
if (pagesize != 512)
__nand_cmd(CMD_CONFIRM);
__nand_sync();
/* Read data */
read_proc((char *)tmpbuf, pagesize);
/* read oob first */
read_proc((char *)oob_buf, oobsize);
for (j = 0; j < ecccnt; j++) {
u32 stat;
flag = 0;
REG_BCH_INTS = 0xffffffff;
if (cur_page >= 16384 / pagesize)
{
if (bchbit == 8)
{
__ecc_decoding_8bit();
par_size = 13;
}
else
{
__ecc_decoding_4bit();
par_size = 7;
}
}
else
{
__ecc_decoding_8bit();
par_size = 13;
}
if (option != NO_OOB)
__ecc_cnt_dec(ECC_BLOCK + oob_per_eccsize + par_size);
else
__ecc_cnt_dec(ECC_BLOCK + par_size);
for (k = 0; k < ECC_BLOCK; k++) {
REG_BCH_DR = tmpbuf[k];
}
if (option != NO_OOB) {
for (k = 0; k < oob_per_eccsize; k++) {
REG_BCH_DR = oob_buf[oob_per_eccsize * j + k];
}
}
for (k = 0; k < par_size; k++) {
REG_BCH_DR = oob_buf[eccpos + j*par_size + k];
if (oob_buf[eccpos + j*par_size + k] != 0xff)
flag = 1;
}
/* Wait for completion */
__ecc_decode_sync();
__ecc_disable();
/* Check decoding */
stat = REG_BCH_INTS;
if (stat & BCH_INTS_ERR) {
if (stat & BCH_INTS_UNCOR) {
if (flag)
{
dprintf("Uncorrectable ECC error occurred\n");
handshake_PKT[3] = 1;
}
}
else {
handshake_PKT[3] = 0;
unsigned int errcnt = (stat & BCH_INTS_ERRC_MASK) >> BCH_INTS_ERRC_BIT;
switch (errcnt) {
case 8:
dprintf("correct 8th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 7:
dprintf("correct 7th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR3 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
case 6:
dprintf("correct 6th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 5:
dprintf("correct 5th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR2 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
case 4:
dprintf("correct 4th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 3:
dprintf("correct 3th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR1 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
case 2:
dprintf("correct 2th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_ODD_MASK) >> BCH_ERR_INDEX_ODD_BIT);
case 1:
dprintf("correct 1th error\n");
bch_correct(tmpbuf, (REG_BCH_ERR0 & BCH_ERR_INDEX_EVEN_MASK) >> BCH_ERR_INDEX_EVEN_BIT);
break;
default:
dprintf("no error\n");
break;
}
}
}
/* increment pointer */
tmpbuf += ECC_BLOCK;
}
switch (option)
{
case OOB_ECC:
for (j = 0; j < oobsize; j++)
tmpbuf[j] = oob_buf[j];
tmpbuf += oobsize;
break;
case OOB_NO_ECC:
for (j = 0; j < par_size * ecccnt; j++)
oob_buf[eccpos + j] = 0xff;
for (j = 0; j < oobsize; j++)
tmpbuf[j] = oob_buf[j];
tmpbuf += oobsize;
break;
case NO_OOB:
break;
}
cur_page++;
cnt++;
}
return cur_page;
}
u32 nand_program_4750(void *context, int spage, int pages, int option)
{
u32 i, j, cur_page, cur_blk, rowaddr;
u8 *tmpbuf;
u32 ecccnt;
u8 ecc_buf[256];
u32 oob_per_eccsize;
int eccpos_sav = eccpos, bchbit_sav = bchbit, par_size_sav = par_size;
int spl_size = 16 * 1024 / pagesize;
if (wp_pin)
__gpio_set_pin(wp_pin);
restart:
tmpbuf = (u8 *)context;
ecccnt = pagesize / ECC_BLOCK;
oob_per_eccsize = eccpos / ecccnt;
i = 0;
cur_page = spage;
while (i < pages) {
if (cur_page < spl_size) {
bchbit = 8;
eccpos = 3;
par_size = 13;
} else if (cur_page >= spl_size) {
bchbit = bchbit_sav;
eccpos = eccpos_sav;
par_size = par_size_sav;
}
if ((cur_page % ppb) == 0) { /* First page of block, test BAD. */
if (nand_check_block(cur_page / ppb)) {
cur_page += ppb; /* Bad block, set to next block */
continue;
}
}
if ( option != NO_OOB ) //if NO_OOB do not perform vaild check!
{
for ( j = 0 ; j < pagesize + oobsize; j ++)
{
if (tmpbuf[j] != 0xff)
break;
}
if ( j == oobsize + pagesize )
{
tmpbuf += ( pagesize + oobsize ) ;
i ++;
cur_page ++;
continue;
}
}
if (pagesize == 512)
__nand_cmd(CMD_READA);
__nand_cmd(CMD_SEQIN);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
rowaddr = cur_page;
for (j = 0; j < row; j++) {
__nand_addr(rowaddr & 0xff);
rowaddr >>= 8;
}
/* write out data */
for (j = 0; j < ecccnt; j++) {
volatile u8 *paraddr;
int k;
paraddr = (volatile u8 *)BCH_PAR0;
REG_BCH_INTS = 0xffffffff;
if (bchbit == 8)
__ecc_encoding_8bit();
else
__ecc_encoding_4bit();
/* Set BCHCNT.DEC_COUNT to data block size in bytes */
if (option != NO_OOB)
__ecc_cnt_enc(ECC_BLOCK + oob_per_eccsize);
else
__ecc_cnt_enc(ECC_BLOCK);
/* Write data in data area to BCH */
for (k = 0; k < ECC_BLOCK; k++) {
REG_BCH_DR = tmpbuf[ECC_BLOCK * j + k];
}
/* Write file system information in oob area to BCH */
if (option != NO_OOB)
{
for (k = 0; k < oob_per_eccsize; k++) {
REG_BCH_DR = tmpbuf[pagesize + oob_per_eccsize * j + k];
}
}
__ecc_encode_sync();
__ecc_disable();
/* Read PAR values */
for (k = 0; k < par_size; k++) {
ecc_buf[j * par_size + k] = *paraddr++;
}
write_proc((char *)&tmpbuf[ECC_BLOCK * j], ECC_BLOCK);
}
switch (option)
{
case OOB_ECC:
case OOB_NO_ECC:
for (j = 0; j < eccpos; j++) {
oob_buf[j] = tmpbuf[pagesize + j];
}
for (j = 0; j < ecccnt * par_size; j++) {
oob_buf[eccpos + j] = ecc_buf[j];
}
tmpbuf += pagesize + oobsize;
break;
case NO_OOB: //bin image
for (j = 0; j < ecccnt * par_size; j++) {
oob_buf[eccpos + j] = ecc_buf[j];
}
tmpbuf += pagesize;
break;
}
/* write out oob buffer */
write_proc((u8 *)oob_buf, oobsize);
/* send program confirm command */
__nand_cmd(CMD_PGPROG);
__nand_sync();
__nand_cmd(CMD_READ_STATUS);
if (__nand_data8() & 0x01) /* page program error */
{
serial_puts("Skip a write fail block\n");
nand_erase_4750( 1, cur_page/ppb, 1); //force erase before
nand_mark_bad_4750(cur_page/ppb);
spage += ppb;
goto restart;
}
i++;
cur_page++;
}
if (wp_pin)
__gpio_clear_pin(wp_pin);
bchbit = bchbit_sav;
eccpos = eccpos_sav;
par_size = par_size_sav;
return cur_page;
}
static u32 nand_mark_bad_page(u32 page)
{
u8 badbuf[4096 + 128];
u32 i;
if (wp_pin)
__gpio_set_pin(wp_pin);
for (i = 0; i < pagesize + oobsize; i++)
badbuf[i] = 0x00;
//all set to 0x00
__nand_cmd(CMD_READA);
__nand_cmd(CMD_SEQIN);
__nand_addr(0);
if (pagesize != 512)
__nand_addr(0);
for (i = 0; i < row; i++) {
__nand_addr(page & 0xff);
page >>= 8;
}
write_proc((char *)badbuf, pagesize + oobsize);
__nand_cmd(CMD_PGPROG);
__nand_sync();
if (wp_pin)
__gpio_clear_pin(wp_pin);
return page;
}
u32 nand_mark_bad_4750(int block)
{
u32 rowaddr;
if ( bad_block_page >= ppb ) //absolute bad block mark!
{ //mark four page!
rowaddr = block * ppb + 0;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + 1;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + ppb - 2;
nand_mark_bad_page(rowaddr);
rowaddr = block * ppb + ppb - 1;
nand_mark_bad_page(rowaddr);
}
else //mark one page only
{
rowaddr = block * ppb + bad_block_page;
nand_mark_bad_page(rowaddr);
}
return rowaddr;
}
static int nand_data_write8(char *buf, int count)
{
int i;
u8 *p = (u8 *)buf;
for (i=0;i<count;i++)
__nand_data8() = *p++;
return 0;
}
static int nand_data_write16(char *buf, int count)
{
int i;
u16 *p = (u16 *)buf;
for (i=0;i<count/2;i++)
__nand_data16() = *p++;
return 0;
}
static int nand_data_read8(char *buf, int count)
{
int i;
u8 *p = (u8 *)buf;
for (i=0;i<count;i++)
*p++ = __nand_data8();
return 0;
}
static int nand_data_read16(char *buf, int count)
{
int i;
u16 *p = (u16 *)buf;
for (i=0;i<count/2;i++)
*p++ = __nand_data16();
return 0;
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "jz4750.h"
volatile u32 UART_BASE;
#define CONFIG_BAUDRATE 57600
#define CFG_EXTAL 12000000 /* EXTAL freq must=12 MHz !! */
void serial_setbrg (void)
{
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
volatile u8 *uart_dlhr = (volatile u8 *)(UART_BASE + OFF_DLHR);
volatile u8 *uart_dllr = (volatile u8 *)(UART_BASE + OFF_DLLR);
u32 baud_div, tmp;
baud_div = CFG_EXTAL / 16 / CONFIG_BAUDRATE;
tmp = *uart_lcr;
tmp |= UART_LCR_DLAB;
*uart_lcr = tmp;
*uart_dlhr = (baud_div >> 8) & 0xff;
*uart_dllr = baud_div & 0xff;
tmp &= ~UART_LCR_DLAB;
*uart_lcr = tmp;
}
void serial_putc (const char c)
{
volatile u8 *uart_lsr = (volatile u8 *)(UART_BASE + OFF_LSR);
volatile u8 *uart_tdr = (volatile u8 *)(UART_BASE + OFF_TDR);
if (c == '\n') serial_putc ('\r');
/* Wait for fifo to shift out some bytes */
while ( !((*uart_lsr & (UART_LSR_TDRQ | UART_LSR_TEMT)) == 0x60) );
*uart_tdr = (u8)c;
}
void serial_puts (const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
void serial_init(void)
{
volatile u8 *uart_fcr = (volatile u8 *)(UART_BASE + OFF_FCR);
volatile u8 *uart_lcr = (volatile u8 *)(UART_BASE + OFF_LCR);
volatile u8 *uart_ier = (volatile u8 *)(UART_BASE + OFF_IER);
volatile u8 *uart_sircr = (volatile u8 *)(UART_BASE + OFF_SIRCR);
/* Disable port interrupts while changing hardware */
*uart_ier = 0;
/* Disable UART unit function */
*uart_fcr = ~UART_FCR_UUE;
/* Set both receiver and transmitter in UART mode (not SIR) */
*uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
/* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
*uart_lcr = UART_LCR_WLEN_8 | UART_LCR_STOP_1;
/* Set baud rate */
serial_setbrg();
/* Enable UART unit, enable and clear FIFO */
*uart_fcr = UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS;
}
void serial_put_hex(unsigned int d)
{
unsigned char c[12];
char i;
for(i = 0; i < 8;i++)
{
c[i] = (d >> ((7 - i) * 4)) & 0xf;
if(c[i] < 10)
c[i] += 0x30;
else
c[i] += (0x41 - 10);
}
c[8] = '\n';
c[9] = 0;
serial_puts(c);
}

View File

@@ -0,0 +1,32 @@
OUTPUT_ARCH(mips)
ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x80000000 , LENGTH = 3M
}
SECTIONS
{
. = ALIGN(4);
.text : { *(.text*) } > ram
. = ALIGN(4);
.rodata : { *(.rodata*) } > ram
. = ALIGN(4);
.sdata : { *(.sdata*) } > ram
. = ALIGN(4);
.data : { *(.data*) *(.scommon*) *(.reginfo*) } > ram
_gp = ALIGN(16);
.got : { *(.got*) } > ram
_got_end = ABSOLUTE(.);
. = ALIGN(4);
.sbss : { *(.sbss*) } > ram
.bss : { *(.bss*) } > ram
. = ALIGN (4);
}

654
usbboot/xburst_stage2/udc.c Normal file
View File

@@ -0,0 +1,654 @@
/*
* Copyright (C) 2009 PI
* Author: Xiangfu Liu <xiangfu.z@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include <jz4740.h>
#include "usb.h"
#include "udc.h"
#include "usb_boot.h"
#define dprintf(x...)
#define TXFIFOEP0 USB_FIFO_EP0
u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
u32 Bulk_in_size,Bulk_in_finish,Bulk_out_size;
u16 handshake_PKT[4]={0,0,0,0};
u8 udc_state;
static u32 rx_buf[32];
static u32 tx_buf[32];
static u32 tx_size, rx_size, finished,fifo;
static u8 ep0state,USB_Version;
static u32 fifoaddr[] =
{
TXFIFOEP0, TXFIFOEP0+4 ,TXFIFOEP0+8
};
static u32 fifosize[] = {
MAX_EP0_SIZE, MAX_EP1_SIZE
};
void *memset(void *s, int c, size_t count)
{
char *xs = s;
while (count--)
*xs++ = c;
return s;
}
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
static void udcReadFifo(u8 *ptr, int size)
{
u32 *d = (u32 *)ptr;
int s;
s = (size + 3) >> 2;
while (s--)
*d++ = REG32(fifo);
}
static void udcWriteFifo(u8 *ptr, int size)
{
u32 *d = (u32 *)ptr;
u8 *c;
int s, q;
if (size > 0) {
s = size >> 2;
while (s--)
REG32(fifo) = *d++;
q = size & 3;
if (q) {
c = (u8 *)d;
while (q--)
REG8(fifo) = *c++;
}
}
}
void HW_SendPKT(int ep, const u8 *buf, int size)
{
// dprintf("EP%d send pkt :%d\n", ep, size);
fifo = fifoaddr[ep];
if (ep!=0)
{
Bulk_in_size = size;
Bulk_in_finish = 0;
jz_writeb(USB_REG_INDEX, ep);
if (Bulk_in_size - Bulk_in_finish <= fifosize[ep])
{
udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
Bulk_in_size - Bulk_in_finish);
usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
Bulk_in_finish = Bulk_in_size;
} else
{
udcWriteFifo((u8 *)((u32)buf+Bulk_in_finish),
fifosize[ep]);
usb_setb(USB_REG_INCSR, USB_INCSR_INPKTRDY);
Bulk_in_finish += fifosize[ep];
}
}
else //EP0
{
tx_size = size;
finished = 0;
memcpy((void *)tx_buf, buf, size);
ep0state = USB_EP0_TX;
}
}
void HW_GetPKT(int ep, const u8 *buf, int size)
{
// dprintf("EP%d read pkt :%d\n", ep, size);
memcpy((void *)buf, (u8 *)rx_buf, size);
fifo = fifoaddr[ep];
if (rx_size > size)
rx_size -= size;
else {
size = rx_size;
rx_size = 0;
}
memcpy((u8 *)rx_buf, (u8 *)((u32)rx_buf+size), rx_size);
}
static USB_DeviceDescriptor devDesc =
{
sizeof(USB_DeviceDescriptor),
DEVICE_DESCRIPTOR, //1
0x0200, //Version 2.0
0xff, //Vendor spec class
0xff,
0xff,
64, /* Ep0 FIFO size */
0x601a, //vendor ID
0x4740, //Product ID
0xffff,
0x00,
0x00,
0x00,
0x01
};
#define CONFIG_DESCRIPTOR_LEN (sizeof(USB_ConfigDescriptor) + \
sizeof(USB_InterfaceDescriptor) + \
sizeof(USB_EndPointDescriptor) * 2)
static struct {
USB_ConfigDescriptor configuration_descriptor;
USB_InterfaceDescriptor interface_descritor;
USB_EndPointDescriptor endpoint_descriptor[2];
} __attribute__ ((packed)) confDesc = {
{
sizeof(USB_ConfigDescriptor),
CONFIGURATION_DESCRIPTOR,
CONFIG_DESCRIPTOR_LEN,
0x01,
0x01,
0x00,
0xc0, // Self Powered, no remote wakeup
0x64 // Maximum power consumption 2000 mA
},
{
sizeof(USB_InterfaceDescriptor),
INTERFACE_DESCRIPTOR,
0x00,
0x00,
0x02, /* ep number */
0xff,
0xff,
0xff,
0x00
},
{
{
sizeof(USB_EndPointDescriptor),
ENDPOINT_DESCRIPTOR,
(1 << 7) | 1,// endpoint 2 is IN endpoint
2, /* bulk */
512,
16
},
{
sizeof(USB_EndPointDescriptor),
ENDPOINT_DESCRIPTOR,
(0 << 7) | 1,// endpoint 5 is OUT endpoint
2, /* bulk */
512, /* OUT EP FIFO size */
16
}
}
};
void sendDevDescString(int size)
{
u16 str_ret[13] = {
0x031a,//0x1a=26 byte
0x0041,
0x0030,
0x0030,
0x0041,
0x0030,
0x0030,
0x0041,
0x0030,
0x0030,
0x0041,
0x0030,
0x0030
};
// dprintf("sendDevDescString size = %d\r\n",size);
if(size >= 26)
size = 26;
str_ret[0] = (0x0300 | size);
HW_SendPKT(0, (u8 *)str_ret,size);
}
void sendDevDesc(int size)
{
switch (size) {
case 18:
HW_SendPKT(0, (u8 *)&devDesc, sizeof(devDesc));
break;
default:
HW_SendPKT(0, (u8 *)&devDesc, 8);
break;
}
}
void sendConfDesc(int size)
{
switch (size) {
case 9:
HW_SendPKT(0, (u8 *)&confDesc, 9);
break;
case 8:
HW_SendPKT(0, (u8 *)&confDesc, 8);
break;
default:
HW_SendPKT(0, (u8 *)&confDesc, sizeof(confDesc));
break;
}
}
void EP0_init(u32 out, u32 out_size, u32 in, u32 in_size)
{
confDesc.endpoint_descriptor[0].bEndpointAddress = (1<<7) | in;
confDesc.endpoint_descriptor[0].wMaxPacketSize = in_size;
confDesc.endpoint_descriptor[1].bEndpointAddress = (0<<7) | out;
confDesc.endpoint_descriptor[1].wMaxPacketSize = out_size;
}
static void udc_reset(void)
{
u8 byte;
//data init
ep0state = USB_EP0_IDLE;
Bulk_in_size = 0;
Bulk_in_finish = 0;
Bulk_out_size = 0;
udc_state = IDLE;
tx_size = 0;
rx_size = 0;
finished = 0;
/* Enable the USB PHY */
// REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
/* Disable interrupts */
byte=jz_readb(USB_REG_POWER);
// dprintf("\nREG_POWER: %02x",byte);
jz_writew(USB_REG_INTRINE, 0);
jz_writew(USB_REG_INTROUTE, 0);
jz_writeb(USB_REG_INTRUSBE, 0);
jz_writeb(USB_REG_FADDR,0);
jz_writeb(USB_REG_POWER,0x60); //High speed
jz_writeb(USB_REG_INDEX,0);
jz_writeb(USB_REG_CSR0,0xc0);
jz_writeb(USB_REG_INDEX,1);
jz_writew(USB_REG_INMAXP,512);
jz_writew(USB_REG_INCSR,0x2048);
jz_writeb(USB_REG_INDEX,1);
jz_writew(USB_REG_OUTMAXP,512);
jz_writew(USB_REG_OUTCSR,0x0090);
jz_writew(USB_REG_INTRINE,0x3); //enable intr
jz_writew(USB_REG_INTROUTE,0x2);
jz_writeb(USB_REG_INTRUSBE,0x4);
byte=jz_readb(USB_REG_POWER);
// dprintf("\nREG_POWER: %02x",byte);
if ((byte&0x10)==0)
{
jz_writeb(USB_REG_INDEX,1);
jz_writew(USB_REG_INMAXP,64);
jz_writew(USB_REG_INCSR,0x2048);
jz_writeb(USB_REG_INDEX,1);
jz_writew(USB_REG_OUTMAXP,64);
jz_writew(USB_REG_OUTCSR,0x0090);
USB_Version=USB_FS;
fifosize[1]=64;
EP0_init(1,64,1,64);
}
else
{
jz_writeb(USB_REG_INDEX,1);
jz_writew(USB_REG_INMAXP,512);
jz_writew(USB_REG_INCSR,0x2048);
jz_writeb(USB_REG_INDEX,1);
jz_writew(USB_REG_OUTMAXP,512);
jz_writew(USB_REG_OUTCSR,0x0090);
USB_Version=USB_HS;
fifosize[1]=512;
EP0_init(1,512,1,512);
}
}
void usbHandleStandDevReq(u8 *buf)
{
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
switch (dreq->bRequest) {
case GET_DESCRIPTOR:
if (dreq->bmRequestType == 0x80) /* Dev2Host */
switch(dreq->wValue >> 8)
{
case DEVICE_DESCRIPTOR:
dprintf("get device\n");
sendDevDesc(dreq->wLength);
break;
case CONFIGURATION_DESCRIPTOR:
dprintf("get config\n");
sendConfDesc(dreq->wLength);
break;
case STRING_DESCRIPTOR:
if (dreq->wLength == 0x02)
HW_SendPKT(0, "\x04\x03", 2);
else
sendDevDescString(dreq->wLength);
//HW_SendPKT(0, "\x04\x03\x09\x04", 2);
break;
}
dprintf("\nSet ep0state=TX!");
ep0state=USB_EP0_TX;
break;
case SET_ADDRESS:
dprintf("\nSET_ADDRESS!");
jz_writeb(USB_REG_FADDR,dreq->wValue);
break;
case GET_STATUS:
switch (dreq->bmRequestType) {
case 80: /* device */
HW_SendPKT(0, "\x01\x00", 2);
break;
case 81: /* interface */
case 82: /* ep */
HW_SendPKT(0, "\x00\x00", 2);
break;
}
ep0state=USB_EP0_TX;
break;
case CLEAR_FEATURE:
case SET_CONFIGURATION:
case SET_INTERFACE:
case SET_FEATURE:
break;
}
}
void usbHandleVendorReq(u8 *buf)
{
int ret_state;
USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
switch (dreq->bRequest) {
case VR_GET_CUP_INFO:
ret_state=GET_CUP_INFO_Handle();
break;
case VR_SET_DATA_ADDERSS:
ret_state=SET_DATA_ADDERSS_Handle(buf);
break;
case VR_SET_DATA_LENGTH:
ret_state=SET_DATA_LENGTH_Handle(buf);
break;
case VR_FLUSH_CACHES:
ret_state=FLUSH_CACHES_Handle();
break;
case VR_PROGRAM_START1:
ret_state=PROGRAM_START1_Handle(buf);
break;
case VR_PROGRAM_START2:
ret_state=PROGRAM_START2_Handle(buf);
break;
case VR_NOR_OPS:
ret_state=NOR_OPS_Handle(buf);
Bulk_out_size = 0;
//Bulk_in_size = 0;
break;
case VR_NAND_OPS:
NAND_OPS_Handle(buf);
Bulk_out_size = 0;
//Bulk_in_size = 0;
//handshake_PKT[3]=(u16)ret_state;
//HW_SendPKT(0,handshake_PKT,sizeof(handshake_PKT));
break;
case VR_CONFIGRATION:
ret_state=CONFIGRATION_Handle(buf);
handshake_PKT[3]=(u16)ret_state;
HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT));
Bulk_out_size = 0;
//Bulk_in_size = 0;
break;
case VR_SDRAM_OPS:
SDRAM_OPS_Handle(buf);
Bulk_out_size = 0;
break;
}
// serial_puts("get here! \n");
}
void Handshake_PKT()
{
if (udc_state!=IDLE)
{
HW_SendPKT(1,(u8 *)handshake_PKT,sizeof(handshake_PKT));
udc_state = IDLE;
dprintf("\n Send handshake PKT!");
}
}
void usbHandleDevReq(u8 *buf)
{
// dprintf("dev req:%d\n", (buf[0] & (3 << 5)) >> 5);
switch ((buf[0] & (3 << 5)) >> 5) {
case 0: /* Standard request */
usbHandleStandDevReq(buf);
break;
case 1: /* Class request */
break;
case 2: /* Vendor request */
usbHandleVendorReq(buf);
break;
}
}
void EP0_Handler ()
{
u8 byCSR0;
/* Read CSR0 */
jz_writeb(USB_REG_INDEX, 0);
byCSR0 = jz_readb(USB_REG_CSR0);
/* Check for SentStall
if sendtall is set ,clear the sendstall bit*/
if (byCSR0 & USB_CSR0_SENTSTALL)
{
jz_writeb(USB_REG_CSR0, (byCSR0 & ~USB_CSR0_SENDSTALL));
ep0state = USB_EP0_IDLE;
dprintf("\nSentstall!");
return;
}
/* Check for SetupEnd */
if (byCSR0 & USB_CSR0_SETUPEND)
{
jz_writeb(USB_REG_CSR0, (byCSR0 | USB_CSR0_SVDSETUPEND));
ep0state = USB_EP0_IDLE;
dprintf("\nSetupend!");
return;
}
/* Call relevant routines for endpoint 0 state */
if (ep0state == USB_EP0_IDLE)
{
if (byCSR0 & USB_CSR0_OUTPKTRDY) //There are datas in fifo
{
USB_DeviceRequest *dreq;
fifo=fifoaddr[0];
udcReadFifo((u8 *)rx_buf, sizeof(USB_DeviceRequest));
usb_setb(USB_REG_CSR0, 0x48);//clear OUTRD bit
dreq = (USB_DeviceRequest *)rx_buf;
#if 0
dprintf("\nbmRequestType:%02x\nbRequest:%02x\n"
"wValue:%04x\nwIndex:%04x\n"
"wLength:%04x\n",
dreq->bmRequestType,
dreq->bRequest,
dreq->wValue,
dreq->wIndex,
dreq->wLength);
#endif
usbHandleDevReq((u8 *)rx_buf);
} else
{
dprintf("0:R DATA\n");
}
rx_size = 0;
}
if (ep0state == USB_EP0_TX)
{
fifo=fifoaddr[0];
if (tx_size - finished <= 64)
{
udcWriteFifo((u8 *)((u32)tx_buf+finished),
tx_size - finished);
finished = tx_size;
usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
usb_setb(USB_REG_CSR0, USB_CSR0_DATAEND); //Set dataend!
ep0state=USB_EP0_IDLE;
} else
{
udcWriteFifo((u8 *)((u32)tx_buf+finished), 64);
usb_setb(USB_REG_CSR0, USB_CSR0_INPKTRDY);
finished += 64;
}
}
return;
}
void EPIN_Handler(u8 EP)
{
jz_writeb(USB_REG_INDEX, EP);
fifo = fifoaddr[EP];
if (Bulk_in_size-Bulk_in_finish==0)
{
Handshake_PKT();
return;
}
if (Bulk_in_size - Bulk_in_finish <= fifosize[EP])
{
udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
Bulk_in_size - Bulk_in_finish);
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
Bulk_in_finish = Bulk_in_size;
} else
{
udcWriteFifo((u8 *)((u32)Bulk_in_buf+Bulk_in_finish),
fifosize[EP]);
usb_setw(USB_REG_INCSR, USB_INCSR_INPKTRDY);
Bulk_in_finish += fifosize[EP];
}
}
void EPOUT_Handler(u8 EP)
{
u32 size;
jz_writeb(USB_REG_INDEX, EP);
size = jz_readw(USB_REG_OUTCOUNT);
fifo = fifoaddr[EP];
udcReadFifo((u8 *)((u32)Bulk_out_buf+Bulk_out_size), size);
usb_clearb(USB_REG_OUTCSR,USB_OUTCSR_OUTPKTRDY);
Bulk_out_size += size;
dprintf("\nEPOUT_handle return!");
}
void udc4740Proc ()
{
volatile u8 IntrUSB;
volatile u16 IntrIn;
volatile u16 IntrOut;
/* Read interrupt registers */
// while(1)
// {
IntrUSB = jz_readb(USB_REG_INTRUSB);
IntrIn = jz_readw(USB_REG_INTRIN);
IntrOut = jz_readw(USB_REG_INTROUT);
if ( IntrUSB == 0 && IntrIn == 0 && IntrOut == 0)
return;
if (IntrIn & 2)
{
dprintf("\nUDC EP1 IN operation!");
EPIN_Handler(1);
}
if (IntrOut & 2)
{
dprintf("\nUDC EP1 OUT operation!");
EPOUT_Handler(1);
}
if (IntrUSB & USB_INTR_RESET)
{
dprintf("\nUDC reset intrupt!");
udc_reset();
}
/* Check for endpoint 0 interrupt */
if (IntrIn & USB_INTR_EP0)
{
dprintf("\nUDC EP0 operations!");
EP0_Handler();
}
if (USB_Version == USB_FS)
IntrIn = jz_readw(USB_REG_INTRIN);
// }
return;
}
//unsigned int g_stack[2049];
void usb_main()
{
u8 byte;
__dcache_writeback_all();
__icache_invalidate_all();
ep0state = USB_EP0_IDLE;
Bulk_in_size = 0;
Bulk_in_finish = 0;
Bulk_out_size = 0;
udc_state = IDLE;
tx_size = 0;
rx_size = 0;
finished = 0;
byte=jz_readb(USB_REG_POWER);
if ((byte&0x10)==0)
{
USB_Version=USB_FS;
fifosize[1]=64;
EP0_init(1,64,1,64);
}
else
{
USB_Version=USB_HS;
fifosize[1]=512;
EP0_init(1,512,1,512);
}
serial_puts("\n Init UDC");
USB_Version=USB_HS;
while (1) {
udc4740Proc();
}
}