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:
11
usbboot/.gitignore
vendored
Normal file
11
usbboot/.gitignore
vendored
Normal 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
674
usbboot/COPYING
Normal 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
4
usbboot/ChangeLog
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
* xburst-tools ChangeLog
|
||||
|
||||
25Jun2009 [WS] some cleanup in directory structure and build system
|
||||
2
usbboot/Makefile.am
Normal file
2
usbboot/Makefile.am
Normal file
@@ -0,0 +1,2 @@
|
||||
SUBDIRS = src
|
||||
EXTRA_DIST = autogen.sh
|
||||
41
usbboot/README
Normal file
41
usbboot/README
Normal 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
3
usbboot/autogen.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
export AUTOMAKE="automake --foreign --add-missing --copy"
|
||||
autoreconf
|
||||
41
usbboot/configure.ac
Normal file
41
usbboot/configure.ac
Normal 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
5
usbboot/debian/changelog
Normal 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
1
usbboot/debian/compat
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
16
usbboot/debian/control
Normal file
16
usbboot/debian/control
Normal 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
19
usbboot/debian/copyright
Normal 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
3
usbboot/debian/dirs
Normal file
@@ -0,0 +1,3 @@
|
||||
usr/bin
|
||||
usr/share/xburst-tools
|
||||
usr/man/man1
|
||||
1
usbboot/debian/docs
Normal file
1
usbboot/debian/docs
Normal file
@@ -0,0 +1 @@
|
||||
README
|
||||
105
usbboot/debian/rules
Executable file
105
usbboot/debian/rules
Executable 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
8
usbboot/src/.gitignore
vendored
Normal 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
28
usbboot/src/Makefile.am
Normal 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
931
usbboot/src/cmd.c
Normal 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
28
usbboot/src/cmd.h
Normal 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
317
usbboot/src/command_line.c
Normal 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;
|
||||
}
|
||||
16
usbboot/src/command_line.h
Normal file
16
usbboot/src/command_line.h
Normal 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
204
usbboot/src/ingenic_cfg.c
Normal 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
21
usbboot/src/ingenic_cfg.h
Normal 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
393
usbboot/src/ingenic_usb.c
Normal 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
67
usbboot/src/ingenic_usb.h
Normal 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
121
usbboot/src/main.c
Normal 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;
|
||||
}
|
||||
152
usbboot/src/usb_boot_defines.h
Normal file
152
usbboot/src/usb_boot_defines.h
Normal 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
52
usbboot/src/usbboot.cfg
Normal 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!
|
||||
2356
usbboot/xburst_include/archdefs.h
Normal file
2356
usbboot/xburst_include/archdefs.h
Normal file
File diff suppressed because it is too large
Load Diff
62
usbboot/xburst_include/configs.h
Normal file
62
usbboot/xburst_include/configs.h
Normal 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
|
||||
39
usbboot/xburst_include/error.h
Normal file
39
usbboot/xburst_include/error.h
Normal 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__ */
|
||||
4864
usbboot/xburst_include/jz4740.h
Normal file
4864
usbboot/xburst_include/jz4740.h
Normal file
File diff suppressed because it is too large
Load Diff
5318
usbboot/xburst_include/jz4750.h
Executable file
5318
usbboot/xburst_include/jz4750.h
Executable file
File diff suppressed because it is too large
Load Diff
820
usbboot/xburst_include/mips.h
Normal file
820
usbboot/xburst_include/mips.h
Normal 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__ */
|
||||
985
usbboot/xburst_include/mipsregs.h
Normal file
985
usbboot/xburst_include/mipsregs.h
Normal 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 */
|
||||
63
usbboot/xburst_include/nandflash.h
Normal file
63
usbboot/xburst_include/nandflash.h
Normal 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
|
||||
442
usbboot/xburst_include/sysdefs.h
Normal file
442
usbboot/xburst_include/sysdefs.h
Normal 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__*/
|
||||
64
usbboot/xburst_include/udc.h
Normal file
64
usbboot/xburst_include/udc.h
Normal 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__
|
||||
225
usbboot/xburst_include/usb.h
Normal file
225
usbboot/xburst_include/usb.h
Normal 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)
|
||||
|
||||
49
usbboot/xburst_include/usb_boot.h
Normal file
49
usbboot/xburst_include/usb_boot.h
Normal 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__ */
|
||||
18
usbboot/xburst_include/xburst_types.h
Normal file
18
usbboot/xburst_include/xburst_types.h
Normal 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
11
usbboot/xburst_stage1/.gitignore
vendored
Normal 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
|
||||
40
usbboot/xburst_stage1/Makefile
Normal file
40
usbboot/xburst_stage1/Makefile
Normal 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
|
||||
224
usbboot/xburst_stage1/board_4740.c
Normal file
224
usbboot/xburst_stage1/board_4740.c
Normal 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;
|
||||
}
|
||||
227
usbboot/xburst_stage1/board_4750.c
Executable file
227
usbboot/xburst_stage1/board_4750.c
Executable 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;
|
||||
}
|
||||
|
||||
110
usbboot/xburst_stage1/common.c
Normal file
110
usbboot/xburst_stage1/common.c
Normal 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);
|
||||
|
||||
}
|
||||
102
usbboot/xburst_stage1/debug.c
Normal file
102
usbboot/xburst_stage1/debug.c
Normal 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;
|
||||
}
|
||||
}
|
||||
53
usbboot/xburst_stage1/head.S
Normal file
53
usbboot/xburst_stage1/head.S
Normal 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
|
||||
124
usbboot/xburst_stage1/main.c
Normal file
124
usbboot/xburst_stage1/main.c
Normal 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");
|
||||
}
|
||||
31
usbboot/xburst_stage1/target.ld
Normal file
31
usbboot/xburst_stage1/target.ld
Normal 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
21
usbboot/xburst_stage2/.gitignore
vendored
Normal 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
|
||||
57
usbboot/xburst_stage2/Makefile
Normal file
57
usbboot/xburst_stage2/Makefile
Normal 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)
|
||||
370
usbboot/xburst_stage2/boothandler.c
Normal file
370
usbboot/xburst_stage2/boothandler.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
149
usbboot/xburst_stage2/cache.c
Normal file
149
usbboot/xburst_stage2/cache.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
usbboot/xburst_stage2/head.S
Normal file
37
usbboot/xburst_stage2/head.S
Normal 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
|
||||
68
usbboot/xburst_stage2/main.c
Normal file
68
usbboot/xburst_stage2/main.c
Normal 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();
|
||||
}
|
||||
829
usbboot/xburst_stage2/nandflash_4740.c
Normal file
829
usbboot/xburst_stage2/nandflash_4740.c
Normal 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;
|
||||
}
|
||||
|
||||
844
usbboot/xburst_stage2/nandflash_4750.c
Normal file
844
usbboot/xburst_stage2/nandflash_4750.c
Normal 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;
|
||||
}
|
||||
106
usbboot/xburst_stage2/serial.c
Normal file
106
usbboot/xburst_stage2/serial.c
Normal 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);
|
||||
|
||||
}
|
||||
32
usbboot/xburst_stage2/target.ld
Normal file
32
usbboot/xburst_stage2/target.ld
Normal 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
654
usbboot/xburst_stage2/udc.c
Normal 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user