initial commit for zc706_cx9261a_demo
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
*.xsa filter=lfs diff=lfs merge=lfs -text
|
||||
*.csv filter=lfs diff=lfs merge=lfs -text
|
||||
*.bit filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.dcp filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "scripts"]
|
||||
path = scripts
|
||||
url = https://git.gatsby.icu/gatsby/embedded-autobuild.git
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright © 2007 Free Software Foundation, Inc. <https://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.
|
||||
|
||||
embedded-autobuild
|
||||
Copyright (C) 2024 gatsby
|
||||
|
||||
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 <https://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:
|
||||
|
||||
embedded-autobuild Copyright (C) 2024 gatsby
|
||||
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 <https://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 <https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,166 @@
|
||||
# embedded-autobuild
|
||||
|
||||
`embedded-autobuild` 是一个实用脚本库,旨在简化从源码构建目标 IDE 工程的流程。该脚本库通过 `JSON` 文件管理工程配置,并使用 IDE 的命令行接口快速实现项目的重建与管理,减少手动配置的繁琐步骤。
|
||||
|
||||
## 特性
|
||||
|
||||
- 使用 JSON 文件保存硬件设计、应用程序配置、BSP 设置等项目配置。
|
||||
- 支持多个 IDE 工具链,便于多平台开发或切换开发环境。
|
||||
- 支持自动化构建,确保在多次迭代开发中保持一致性。
|
||||
|
||||
## 支持的开发工具
|
||||
|
||||
本项目目前支持以下 Xilinx 工具链版本:
|
||||
|
||||
- **Xilinx SDK** 版本:`2017.1` ~ `2019.2`
|
||||
- **Xilinx Vitis** 版本:`2019.2` ~ `2023.1`
|
||||
- **Xilinx Vitis Classic** 版本:`2023.2` 及以上
|
||||
|
||||
## 工程配置
|
||||
|
||||
在使用脚本前,请参考以下文档配置对应平台:
|
||||
|
||||
- [Xilinx 平台配置指南](./platform/xilinx/HOWTO.md)
|
||||
|
||||
## 项目结构
|
||||
|
||||
- `platform/` - 包含各平台构建工具脚本
|
||||
- `generic_variables.mk` - 使用 `make` 工具构建时的基本变量声明
|
||||
- `generic.mk` - 提供若干实用构建目标
|
||||
- `template.mk` - 基于 `make` 的构建模板
|
||||
- `template.bat` - 基于 Windows 批处理文件的构建模板
|
||||
|
||||
## 快速开始
|
||||
|
||||
1. **将项目添加为 `submodule`**
|
||||
|
||||
在目标项目的根目录下运行以下命令,将 `embedded-autobuild` 项目作为 `scripts` 文件夹的子模块:
|
||||
|
||||
```shell
|
||||
git submodule add https://git.gatsby.icu/gatsby/embedded-autobuild.git scripts
|
||||
```
|
||||
|
||||
2. **初始化并更新子模块**
|
||||
|
||||
如果已经有子模块配置,请使用以下命令初始化并更新子模块:
|
||||
|
||||
```shell
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
若需更新子模块,使用以下命令:
|
||||
|
||||
```shell
|
||||
git submodule update --remote
|
||||
```
|
||||
|
||||
3. **添加配置文件**
|
||||
|
||||
将对应平台的配置模板文件拷贝到工程根目录:
|
||||
|
||||
```shell
|
||||
cp ./scripts/platform/<your_platform>/template.json ./config.json
|
||||
```
|
||||
|
||||
**请参照对应平台[配置说明](#工程配置),根据实际需要修改配置文件**。
|
||||
|
||||
4. **添加构建脚本**
|
||||
|
||||
1. 如果使用 `make` 进行工程构建,可以基于 [`template.mk`](./template.mk) 编写自己的 Makefile:
|
||||
|
||||
```shell
|
||||
cp ./scripts/template.mk Makefile
|
||||
```
|
||||
|
||||
其内容如下,只需指定 `PLATFORM` 和 `CONFIG_FILE` 即可。默认在当前工作路径的 `build` 文件夹下构建工程:
|
||||
|
||||
```makefile
|
||||
include scripts/generic_variables.mk
|
||||
|
||||
PLATFORM := <your_platform> # eg. xilinx
|
||||
CONFIG_FILE := <config_file> #eg. $(PROJECT)/config.json
|
||||
|
||||
include scripts/generic.mk
|
||||
```
|
||||
|
||||
你还可以根据需求追加更多自定义构建目标。默认的构建目标如下:
|
||||
|
||||
- `all`: 构建并编译配置文件中所有的工程
|
||||
- `project`: 仅构建工程
|
||||
- `build`: 编译所有已配置工程
|
||||
- `sdkopen`: 打开对应开发工具
|
||||
- `clean`: 清除当前编译结果
|
||||
- `reset`: 删除所有已构建工程
|
||||
|
||||
2. 对于 Windows 系统,还支持通过批处理文件或 PowerShell 脚本实现自动化构建。可基于 [`template.bat`](./template.bat) 编写自己的批处理脚本:
|
||||
|
||||
```shell
|
||||
cp ./scripts/template.bat make.bat
|
||||
```
|
||||
|
||||
该模板内容如下,需指定以下参数:
|
||||
|
||||
- `platform`: 使用的平台
|
||||
- `pltform_ver`: 平台工具版本
|
||||
- `work_dir`: 工作目录(即构建工程存储的目录)
|
||||
- `config`: 配置文件
|
||||
- `tools_dir`: 平台工具脚本目录
|
||||
|
||||
```bat
|
||||
@echo off
|
||||
set "platform=xilinx"
|
||||
set "pltform_ver=2019.1"
|
||||
set "work_dir=%~dp0build"
|
||||
set "config=%~dp0config.json"
|
||||
set "tools_dir=%~dp0scripts\platform\%platform%"
|
||||
|
||||
REM Set up environment
|
||||
call "%tools_dir%\setenv.bat" "%pltform_ver%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to initialize environment.
|
||||
pause >nul
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Build project
|
||||
call "%tools_dir%\build.bat" "%config%" "%work_dir%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to build project.
|
||||
pause >nul
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Launch SDK
|
||||
call "%tools_dir%\launch.bat" "%pltform_ver%" "%work_dir%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to launch SDK.
|
||||
pause >nul
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
```
|
||||
|
||||
其中 `%~dp0` 表示当前 `.bat` 文件所在目录。上述模板配置假设配置文件和相关工具脚本与 `.bat` 在同一目录,并在该目录下的 `build` 文件夹中创建工程。该脚本实现了自动创建工程并完成相关配置最后加载对应 IDE 的功能。
|
||||
|
||||
## 常见问题
|
||||
|
||||
1. 在 Xilinx Vitis 中打开构建的工程后,点击符号时可能无法跳转,并且在 IDE 左下角会显示如下错误信息:
|
||||
|
||||
```plaintext
|
||||
Could not find symbol 'XXXX' in index
|
||||
```
|
||||
|
||||
这是因为源文件在导入时被直接链接或复制到了工程目录中,未触发 C++ Indexer 更新索引。此外,新版本的 Vitis 没有直接的命令或 UI 选项来重建或更新索引。最简单的解决方法是随意打开一个源文件,在任意行末输入一个空格并保存。IDE 会自动删除该空格,不会对源文件造成任何更改,但此操作可触发索引的自动更新。
|
||||
|
||||
## 待办事项
|
||||
|
||||
- [x] 支持 Xilinx SDK 的 XSCT 接口
|
||||
- [x] 支持 Xilinx Vitis 的 XSCT 接口
|
||||
- [ ] 增加对 Xilinx Vitis Python API 的支持
|
||||
- [ ] 完善 Xilinx 工具下 FSBL 补丁的功能
|
||||
- [ ] 支持 IAR 工具链
|
||||
|
||||
## 贡献指南
|
||||
|
||||
如果您对该项目有任何改进意见或功能需求,欢迎提交 issue 或 pull request,commit 格式请参考 [Angular convention](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional).
|
||||
@@ -0,0 +1,110 @@
|
||||
ifeq ($(VERBOSE),y)
|
||||
else
|
||||
HIDE = > /dev/zero
|
||||
.SILENT:
|
||||
endif
|
||||
|
||||
TIMESTAMP = $(shell date +"%T")
|
||||
copy_files = cp $(1) $(2)
|
||||
copy_dir = cp -r $(1) $(2)
|
||||
remove_file = rm -rf $(1)
|
||||
remove_dir = rm -rf $(1)
|
||||
mk_dir = mkdir -p $(1)
|
||||
read_file = cat $(1) 2>/dev/null
|
||||
print_lines = echo $(1) | tr ' ' '\n'
|
||||
green = \\e[32m$(1)\\e[39m
|
||||
print = printf "$(call green,[$(TIMESTAMP)]) $(1)\n"
|
||||
make_dir_link = ln -sfr $(1) $(2)
|
||||
make_link = ln -sfr $(1) $(2)
|
||||
check_command = $(shell which $(1) > /dev/null 2>&1 && echo y || echo n)
|
||||
print_build_type = $(call print,Building for $(call green,$(1)))
|
||||
|
||||
ifeq ('y', '$(strip $(LINK_SRCS))')
|
||||
update_files = $(call make_link,$(1),$(2))
|
||||
update_dir = $(call make_dir_link,$(1),$(2))
|
||||
ACTION = Linking
|
||||
else
|
||||
update_files = $(call copy_files,$(1),$(dir $(2)))
|
||||
update_dir = $(call copy_dir,$(1),$(2))
|
||||
ACTION = Copying
|
||||
endif
|
||||
|
||||
ifndef PROJECT
|
||||
$(error "PROJECT variable needs to be set")
|
||||
endif
|
||||
ifndef PLATFORM
|
||||
$(error "PLATFORM variable needs to be set")
|
||||
endif
|
||||
ifndef BUILD_DIR
|
||||
$(error "BUILD_DIR variable needs to be set")
|
||||
endif
|
||||
ifndef CONFIG_FILE
|
||||
$(error "CONFIG_FILE variable needs to be set")
|
||||
endif
|
||||
ifndef SCRIPT_DIR
|
||||
CURRENT_FILE := $(lastword $(MAKEFILE_LIST))
|
||||
CURRENT_DIR := $(patsubst %/,%,$(dir $(CURRENT_FILE)))
|
||||
SCRIPT_DIR := $(CURRENT_DIR)
|
||||
endif
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# COMMON INITIALIZATION
|
||||
#------------------------------------------------------------------------------
|
||||
PLATFORM_TOOLS = $(SCRIPT_DIR)/platform/$(PLATFORM)
|
||||
BUILD_LOCK = $(BUILD_DIR)/.project.lock
|
||||
|
||||
ifeq ('xilinx', '$(PLATFORM)')
|
||||
include $(PLATFORM_TOOLS)/xilinx.mk
|
||||
endif
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Generic Goals
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
PHONY += all
|
||||
ifneq ($(wildcard $(BUILD_LOCK)),)
|
||||
all:
|
||||
$(call print_build_type,$(PLATFORM))
|
||||
$(MAKE) --no-print-directory build
|
||||
$(call print,Done ($(notdir $(BUILD_DIR))))
|
||||
else
|
||||
all:
|
||||
$(call print_build_type,$(PLATFORM))
|
||||
$(MAKE) --no-print-directory project
|
||||
$(MAKE) --no-print-directory build
|
||||
$(call print,Done ($(notdir $(BUILD_DIR))))
|
||||
endif
|
||||
|
||||
project: $(PLATFORM)_project
|
||||
@echo "$(TIMESTAMP): Build lock." > $(BUILD_LOCK)
|
||||
|
||||
standalone:
|
||||
$(MAKE) --no-print-directory project LINK_SRCS=n
|
||||
|
||||
# Build project using generic compiler
|
||||
build: $(PLATFORM)_sdkbuild
|
||||
|
||||
# Open the project using the corresponding SDK
|
||||
sdkopen: $(PLATFORM)_sdkopen
|
||||
|
||||
# Remove build artefacts
|
||||
PHONY += clean
|
||||
ifneq ($(wildcard $(BUILD_LOCK)),)
|
||||
clean:
|
||||
$(call print,Cleaning sdk build uploaded to board)
|
||||
$(MAKE) --no-print-directory $(PLATFORM)_sdkclean
|
||||
else
|
||||
clean:
|
||||
$(call print,No project found, cleaning dummy files)
|
||||
$(MAKE) --no-print-directory reset
|
||||
endif
|
||||
|
||||
# Remove the whole build directory
|
||||
PHONY += reset
|
||||
reset: $(PLATFORM)_reset
|
||||
$(call print,[Delete] $(BUILD_DIR))
|
||||
$(call remove_dir,$(BUILD_DIR))
|
||||
|
||||
.PHONY: $(PHONY)
|
||||
@@ -0,0 +1,9 @@
|
||||
#Variables needed by makefile
|
||||
PROJECT ?= $(realpath .)
|
||||
BUILD_DIR ?= $(PROJECT)/build
|
||||
CONFIG_FILE ?= $(PROJECT)/config.json
|
||||
SCRIPT_DIR ?= $(PROJECT)/scripts
|
||||
|
||||
# By default link sources into the build directory of the project.
|
||||
# This way all needed files will be in one place and they can be tracked on git
|
||||
LINK_SRCS ?= y
|
||||
@@ -0,0 +1,239 @@
|
||||
# Xilinx 平台配置指南 (HOWTO)
|
||||
|
||||
## 目录结构说明
|
||||
|
||||
- **build.bat**: 用于在 Windows 系统上运行的批处理脚本,负责自动化构建整个项目;
|
||||
|
||||
- **launch.bat**: 用于启动 Xilinx SDK 或 Vitis 的批处理脚本,适用于在 Windows 系统上打开开发环境,加载并查看生成的工程;
|
||||
|
||||
- **setenv.bat**: 运行环境配置脚本,用于在 Windows 系统中设置 Xilinx 开发工具的环境变量,通常在构建或启动项目前运行;
|
||||
|
||||
- **template.gitignore**: 针对 Xilinx 工具的 `.gitignore` 模板文件,用户可以将其内容复制到实际的 `.gitignore` 文件中;
|
||||
|
||||
- **template.json**: 项目的 JSON 配置模板文件,定义了工程的基本配置,具体配置参数请参考[配置文件说明](#配置文件说明);
|
||||
|
||||
- **util.tcl**: 包含一组通用工具命令的 TCL 脚本,用于辅助自动化构建过程。此文件在构建过程中被调用,用于与开发工具交互执行 Xilinx 工具相关的特定操作;
|
||||
|
||||
- **xilinx.mk**: 被 [`generic.mk`](../../generic.mk) 定义了 Xilinx 平台的特定的编译规则;
|
||||
|
||||
## 配置文件说明
|
||||
|
||||
配置文件用于定义 Xilinx 平台项目的构建参数、应用配置和库依赖关系等信息,以便于在 `embedded-autobuild` 项目中自动化生成工程。以下为最小化完整配置示例,包含了所有必填字段,可作为基础配置参考。
|
||||
|
||||
```json
|
||||
{
|
||||
"project_name": "demo",
|
||||
"version": "0.0.0",
|
||||
"hw_design": "demo_v0.0.0.hdf",
|
||||
"apps": {
|
||||
"demo_app": {
|
||||
"sources": ["source/"],
|
||||
"target_cpu": "ps7_cortexa9_0",
|
||||
"os": "standalone",
|
||||
"language": "C",
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如需添加更多配置请详细阅读后续 Xilinx 配置文件各部分的详细说明。
|
||||
|
||||
> **注**:以下针对字段的解释中 **加粗** 字段为必须参数,*斜体* 标注的字段为可选参数,可选参数不填写则使用对应 IDE 的默认配置。
|
||||
|
||||
### 基本字段
|
||||
|
||||
- **project_name**: 项目名称,例如 `"demo"`。
|
||||
- **version**: 项目版本,例如 `"0.0.0"`。
|
||||
- **hw_design**: 硬件设计文件(`.hdf` 或 `.xsa` 文件)路径(相对配置文件路径),例如 `"demo_v0.0.0.hdf"`。
|
||||
|
||||
### *fsbl_patch* (TODO)
|
||||
|
||||
用于配置 `FSBL` (First Stage Bootloader) 的补丁文件。可以包含多个补丁文件以满足自定义的硬件启动需求。
|
||||
|
||||
```json
|
||||
"fsbl_patch": {
|
||||
"<patch_target0>": "<patch_file0>",
|
||||
"<patch_target1>": "<patch_file1>"
|
||||
}
|
||||
```
|
||||
|
||||
其基本格式为 `<patch_target>: <patch_file>`,`<patch_target>` 是 FSBL 中需要被替换的文件,`<patch_file>` 为准备好的替换补丁文件。
|
||||
|
||||
### *bsps*
|
||||
|
||||
该字段用于定义 BSP 或者 Domain 的配置,支持多个 BSP/Domain 配置。
|
||||
|
||||
```json
|
||||
"bsps": {
|
||||
"<bsp_name>": {
|
||||
"os": "<os_type>",
|
||||
"target_cpu": "<cpu_id>",
|
||||
"libs": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
...
|
||||
}
|
||||
}
|
||||
...
|
||||
},
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
...
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
- **os**: 操作系统类型,支持的类型有 `standalone`,`freetos`,`linux`[^1];
|
||||
- **target_cpu**: 目标 CPU[^2],例如 "ps7_cortexa9_0" 表示 Zynq-7000 系列的 ARM Cortex-A9 核;
|
||||
-*libs*: 必要的库及其版本配置[^1],该配置项下可包含多个 `lib` 配置,默认不添加任何 `lib`;
|
||||
- **version**: `lib` 版本 [^1];
|
||||
- *config*: 其他具体 `lib` 设置[^1],不填写则使用 IDE 默认配置;
|
||||
-*config*: 其他具体 BSP/Domain 设置[^1],不填写则使用 IDE 默认配置;
|
||||
|
||||
以下配置添加了一个名为 "standalone" 的 BSP/Domain 工程,添加了 `xilffs` 和 `xilrsa` 两个 `lib,其中` `xilffs` 启用了长文件名(use_lfn)以及exFAT(enable_exfat)支持,并设置了标准输入输出为 `ps7_coresight_comp_0`,sleep 计数器使用 `ps7_globaltimer_0`.
|
||||
|
||||
```json
|
||||
"bsps": {
|
||||
"standalone": {
|
||||
"os": "standalone",
|
||||
"target_cpu": "ps7_cortexa9_0",
|
||||
"libs": {
|
||||
"xilffs": {
|
||||
"version": "4.1",
|
||||
"config": {
|
||||
"use_lfn": true,
|
||||
"enable_exfat": true
|
||||
}
|
||||
},
|
||||
"xilrsa": {
|
||||
"version": "1.5"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"stdin": "ps7_coresight_comp_0",
|
||||
"stdout": "ps7_coresight_comp_0",
|
||||
"sleep_timer": "ps7_globaltimer_0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### apps
|
||||
|
||||
该字段定义应用的具体构建配置,包括目标 CPU、操作系统、内存布局等,编译参数等。
|
||||
|
||||
```json
|
||||
"apps": {
|
||||
"<app_name>": {
|
||||
"sources": ["dir0", "dir1"],
|
||||
"target_cpu": "<cpu_id>",
|
||||
"os": "<os_type>",
|
||||
"language": "<language>",
|
||||
"bsp": "<bsp_name>",
|
||||
"bsp_lib": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bsp_config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
},
|
||||
"mem_layout" : {
|
||||
"heap_size": "<heap_size>",
|
||||
"stack_size": "<stack_size>"
|
||||
},
|
||||
"build_config": {
|
||||
"<config_name>": {
|
||||
"assembler-flags": "<assembler-flags>",
|
||||
"compiler-misc": "<compiler-misc>",
|
||||
"compiler-optimization": "<compiler-optimization>",
|
||||
"linker-misc": "<linker-misc>",
|
||||
"linker-script": "<linker-script>",
|
||||
"define-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"undef-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"include-path": ["<dir0>", "<dir1>"],
|
||||
"libraries": ["<lib0>", "<lib1>"],
|
||||
"library-search-path": ["<dir0>", "<dir1>"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **sources**: 源文件列表,应为相对当前配置文件的路径,可使用通配符。例如,`"src/*"` 会将配置文件所在目录下的 `src` 文件夹中的所有文件复制或链接到相应工程目录下的 `src` 文件夹中。
|
||||
- **target_cpu**: 目标 CPU ID[^2];
|
||||
- **os**: 操作系统类型[^1],必须与 BSP/Domain 匹配;
|
||||
- **language**: 编程语言,"C" 或 "C++";
|
||||
- *bsp*: 应用所使用的 BSP 名称,若未指定则会自动创建名为 `<os>_<cpu_id>` 的 BSP/Domain.
|
||||
- *bsp_lib*: 针对自动创建的 BSP/Domain 所使用库的配置,与 [bsps](#bsps) 中 `libs` 对应;
|
||||
- *bsp_config*: 针对自动创建的 BSP/Domain 配置与 [bsps](#bsps) 中 `config` 对应;
|
||||
- *mem_layout*: 应用内存布局,包括堆栈大小和堆大小等;
|
||||
-*heap_size*: 堆大小,必须写为十六进制,例如 "0x80000";
|
||||
-*stack_size*: 栈大小,必须写为十六进制,例如 "0x4000";
|
||||
- *build_config*: 编译目标配置,`release` 或 `debug`;
|
||||
- `assembler-flags`: 汇编器标志;
|
||||
- `compiler-misc`: 其他编译器选项;
|
||||
- `compiler-optimization`: 编译优化选项;
|
||||
- `linker-misc`: 链接器选项;
|
||||
- `linker-script`: 链接脚本路径;
|
||||
- `define-compiler-symbols`: 自定义的编译器宏定义符号列表;
|
||||
- `undef-compiler-symbols`: 要取消定义的符号列表;
|
||||
- `include-path`: 包含文件路径;
|
||||
- `libraries`: 需要链接的库;
|
||||
- `library-search-path`: 库搜索路径;
|
||||
|
||||
以下配置添加了一个名为 `demo_app` 的 Application 工程,该工程没有指定 BSP/Domain 但能够通过 `bsp_lib` 和 `bsp_config` 自动生成一个名为 `standalone_ps7_cortexa9_0` 的 BSP/Domain 工程。
|
||||
|
||||
```json
|
||||
"apps": {
|
||||
"demo_app": {
|
||||
"sources": ["source/"],
|
||||
"target_cpu": "ps7_cortexa9_0",
|
||||
"os": "standalone",
|
||||
"language": "C",
|
||||
"bsp_lib": {
|
||||
"xilffs": {
|
||||
"version": "5.2",
|
||||
"config": {
|
||||
"use_lfn": true,
|
||||
"enable_exfat": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"bsp_config": {
|
||||
"sleep_timer": "ps7_globaltimer_0",
|
||||
"stdin": "ps7_uart_1",
|
||||
"stdout": "ps7_uart_1"
|
||||
},
|
||||
"mem_layout" : {
|
||||
"heap_size": "0x80000",
|
||||
"stack_size": "0x4000"
|
||||
},
|
||||
"build_config": {
|
||||
"debug": {
|
||||
"define-compiler-symbols": ["XILINX_PLATFORM", "_DEBUG_LEVEL_=1"],
|
||||
"include-path": ["source/include"],
|
||||
},
|
||||
"release": {
|
||||
"define-compiler-symbols": ["XILINX_PLATFORM"],
|
||||
"include-path": ["source/include"],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
[^1]: 具体可配置项取决于对应 IDE 版本;
|
||||
|
||||
[^2]: 具体可选 CPU ID 取决于硬件型号;
|
||||
@@ -0,0 +1,44 @@
|
||||
@echo off
|
||||
REM Check if exactly two arguments are provided and not empty
|
||||
if "%~2"=="" (
|
||||
echo Usage: build.bat ^<config^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
if not "%~3"=="" (
|
||||
echo Usage: build.bat ^<config^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Check if the config file exists
|
||||
set "config=%1"
|
||||
if not exist "%config%" (
|
||||
echo Error: Config file "%config%" does not exist.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Check if the build directory already exists
|
||||
set "work_dir=%2"
|
||||
if exist "%work_dir%" (
|
||||
echo Error: The build folder already exists.
|
||||
echo "%work_dir%" folder needs to be deleted before the project can be recreated.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Create the build directory
|
||||
mkdir "%work_dir%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to create the build directory: "%work_dir%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Start xsct and wait for it to finish
|
||||
echo Invoking project build...
|
||||
@REM cmd /c "cd /d %~dp0 && xsct util.tcl create_project \"%config%\" \"%work_dir%\" || exit /b %errorlevel%"
|
||||
xsct %~dp0util.tcl create_project "%config%" "%work_dir%"
|
||||
if %errorlevel% NEQ 0 (
|
||||
echo Error: xsct execution failed with error code %ERRORLEVEL%.
|
||||
echo Please check your configurations.
|
||||
exit /b %ERRORLEVEL%
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
@@ -0,0 +1,53 @@
|
||||
@echo off
|
||||
REM Check if exactly two arguments are provided and not empty
|
||||
if "%~2"=="" (
|
||||
echo Usage: launch.bat ^<version^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
if not "%~3"=="" (
|
||||
echo Usage: launch.bat ^<version^> ^<work_dir^>
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Use regex to check if input version code is valid
|
||||
set "xilinx_version=%1"
|
||||
set "version_pattern=20[12][01234789][.][12]"
|
||||
echo %xilinx_version% | findstr /r /c:"%version_pattern%" >nul
|
||||
if %errorlevel% NEQ 0 (
|
||||
echo Error: %xilinx_version% is not a valid version coede ^(e.g., 2019.1^)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Check if the build directory already exists
|
||||
set "work_dir=%2"
|
||||
if not exist "%work_dir%" (
|
||||
echo Error: no `%work_dir%' folder
|
||||
echo try to create project before launching SDK
|
||||
pause >nul
|
||||
)
|
||||
|
||||
REM Convert it to a integer
|
||||
for /f "tokens=1,2 delims=." %%a in ("%xilinx_version%") do (
|
||||
set major=%%a
|
||||
set minor=%%b
|
||||
)
|
||||
set /a version_number=%major%%minor%
|
||||
set /a lowest_vits_version=20192
|
||||
set /a new_vits_version=20232
|
||||
|
||||
REM Determine which tool to launch based on the Xilinx version
|
||||
if %version_number% lss %lowest_vits_version% (
|
||||
REM Version is less than 2019.2, use xsdk
|
||||
echo Launching Xilinx SDK...
|
||||
xsdk -workspace "%work_dir%"
|
||||
) else if %version_number% lss %new_vits_version% (
|
||||
REM Version is between 2019.2 and 2023.1, use vitis
|
||||
echo Launching Xilinx Vitis...
|
||||
vitis -workspace "%work_dir%"
|
||||
) else (
|
||||
REM Version is 2023.2 or higher, use vitis -classic
|
||||
echo Launching Xilinx Vitis Classic...
|
||||
vitis -classic -workspace "%work_dir%"
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
@@ -0,0 +1,59 @@
|
||||
@echo off
|
||||
REM Check if exactly two arguments are provided and not empty
|
||||
if "%~1"=="" (
|
||||
echo Usage: setenv_xilinx.bat ^<version^>
|
||||
exit /b 1
|
||||
)
|
||||
if not "%~2"=="" (
|
||||
echo Usage: setenv_xilinx.bat ^<version^>
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Use regex to check if input version code is valid
|
||||
set "xilinx_version=%1"
|
||||
set "version_pattern=20[12][01234789][.][12]"
|
||||
echo %xilinx_version% | findstr /r /c:"%version_pattern%" >nul
|
||||
if %errorlevel% NEQ 0 (
|
||||
echo Error: %xilinx_version% is not a valid version code ^(e.g., 2019.1^)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Prompt user for Xilinx installation path, default to C:\Xilinx if not provided
|
||||
set "default_path=C:\Xilinx"
|
||||
set /p "xilinx_path=Enter Xilinx installation path (press Enter for default: %default_path%): "
|
||||
if "%xilinx_path%"=="" (
|
||||
set "xilinx_path=%default_path%"
|
||||
)
|
||||
|
||||
REM Convert version to integer
|
||||
for /f "tokens=1,2 delims=." %%a in ("%xilinx_version%") do (
|
||||
set major=%%a
|
||||
set minor=%%b
|
||||
)
|
||||
set /a version_number=%major%%minor%
|
||||
set /a lowest_vitis_version=20192
|
||||
|
||||
REM Determine the correct settings.bat path based on the Xilinx version and user path
|
||||
if %version_number% lss %lowest_vitis_version% (
|
||||
echo Setting up environment for Xilinx SDK.
|
||||
set settings_bat=%xilinx_path%\SDK\%xilinx_version%\settings64.bat
|
||||
) else (
|
||||
echo Setting up environment for Xilinx Vitis.
|
||||
set settings_bat=%xilinx_path%\Vitis\%xilinx_version%\settings64.bat
|
||||
)
|
||||
|
||||
REM Check if the settings.bat file exists
|
||||
if not exist "%settings_bat%" (
|
||||
echo Error: Could not find settings file at %settings_bat%.
|
||||
echo Please check your Xilinx tools installation.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Call the settings.bat file to set up the environment
|
||||
call "%settings_bat%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to source "%settings_bat%".
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
@@ -0,0 +1,32 @@
|
||||
# Buid folder
|
||||
build/
|
||||
|
||||
# Xilinx tools generated files
|
||||
.metadata/
|
||||
.settings/
|
||||
.wsdata/
|
||||
.Xil/
|
||||
logs/
|
||||
Packages/
|
||||
*.log*
|
||||
|
||||
# System generated files
|
||||
# -- macOS
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
._*
|
||||
|
||||
# -- Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# -- Linux
|
||||
*~
|
||||
|
||||
# IDEs and editors' files
|
||||
*.idea
|
||||
*.vscode
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"project_name": "<project_name>",
|
||||
"version": "<project_version>",
|
||||
"hw_design": "<hw_design>",
|
||||
"fsbl_patch": {
|
||||
"<patch_target0>": "<patch_file0>",
|
||||
"<patch_target1>": "<patch_file1>"
|
||||
},
|
||||
"bsps": {
|
||||
"<bsp_name>": {
|
||||
"os": "<os_type>",
|
||||
"target_cpu": "<cpu_id>",
|
||||
"lib": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"apps": {
|
||||
"<app_name>": {
|
||||
"sources": ["dir0", "dir1"],
|
||||
"target_cpu": "<cpu_id>",
|
||||
"os": "<os_type>",
|
||||
"language": "<language>",
|
||||
"bsp": "<bsp_name>",
|
||||
"bsp_lib": {
|
||||
"<lib_name>": {
|
||||
"version": "<lib_version>",
|
||||
"config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bsp_config": {
|
||||
"<parameter0>": "<value0>",
|
||||
"<parameter1>": "<value1>"
|
||||
},
|
||||
"mem_layout" : {
|
||||
"heap_size": "<heap_size>",
|
||||
"stack_size": "<stack_size>"
|
||||
},
|
||||
"build_config": {
|
||||
"<config_name>": {
|
||||
"assembler-flags": "<assembler-flags>",
|
||||
"compiler-misc": "<compiler-misc>",
|
||||
"compiler-optimization": "<compiler-optimization>",
|
||||
"linker-misc": "<linker-misc>",
|
||||
"linker-script": "<linker-script>",
|
||||
"define-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"undef-compiler-symbols": ["<symbol0>", "<symbol1>"],
|
||||
"include-path": ["<dir0>", "<dir1>"],
|
||||
"libraries": ["<lib0>", "<lib1>"],
|
||||
"library-search-path": ["<dir0>", "<dir1>"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
package require json
|
||||
|
||||
# Helper procedure for formatted messages
|
||||
proc _info {message} {
|
||||
puts [format "INFO: %s" $message]
|
||||
}
|
||||
proc _warn {message} {
|
||||
puts [format "WARN: %s" $message]
|
||||
}
|
||||
proc _error {message details} {
|
||||
error [format "ERROR: %s. Details: %s" $message $details]
|
||||
}
|
||||
|
||||
# Helper procedure to create hardware platform
|
||||
proc _prepare_platform {hw_file platform_name is_vitis} {
|
||||
if {![file exists $hw_file]} {
|
||||
_error "Hardware design file does not exist" $hw_file
|
||||
}
|
||||
_info "Creating hardware platform: $platform_name"
|
||||
if {$is_vitis} {
|
||||
platform create -name $platform_name -hw $hw_file
|
||||
_info "Platform '$platform_name' created successfully for Vitis."
|
||||
} else {
|
||||
sdk createhw -name $platform_name -hwspec $hw_file
|
||||
_info "Hardware platform '$platform_name' created successfully for Xilinx SDK."
|
||||
}
|
||||
}
|
||||
|
||||
# Helper procedure for BSP configuration
|
||||
proc _configure_bsp {bsp_name bsp_config platform_name is_vitis} {
|
||||
set cpu [dict get $bsp_config target_cpu]
|
||||
set os [dict get $bsp_config os]
|
||||
|
||||
# Create Domain/BSP
|
||||
_info "Creating BSP: $bsp_name for CPU: $cpu and OS: $os"
|
||||
if {$is_vitis} {
|
||||
platform active $platform_name
|
||||
domain create -name $bsp_name -os $os -proc $cpu
|
||||
domain active $bsp_name
|
||||
_info "BSP '$bsp_name' created for Vitis."
|
||||
} else {
|
||||
sdk createbsp -name $bsp_name -hwproject $platform_name -proc $cpu -os $os
|
||||
_info "BSP '$bsp_name' created for Xilinx SDK."
|
||||
}
|
||||
|
||||
# Apply BSP library configurations if they exist
|
||||
if {[dict exists $bsp_config libs]} {
|
||||
_info "Configuring BSP libraries..."
|
||||
dict for {lib_name lib_info} [dict get $bsp_config libs] {
|
||||
if {$is_vitis} {
|
||||
bsp setlib -name $lib_name -ver [dict get $lib_info version]
|
||||
} else {
|
||||
setlib -bsp $bsp_name -lib $lib_name -ver [dict get $lib_info version]
|
||||
}
|
||||
_info "Applied library '$lib_name' version '[dict get $lib_info version]' for BSP '$bsp_name'."
|
||||
if {[dict exists $lib_info config]} {
|
||||
dict for {param value} [dict get $lib_info config] {
|
||||
if {$is_vitis} {
|
||||
bsp config $param $value
|
||||
} else {
|
||||
configbsp -bsp $bsp_name $param $value
|
||||
}
|
||||
_info "Configured library '$lib_name': $param = $value"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Apply BSP configurations if they exist
|
||||
if {[dict exists $bsp_config config]} {
|
||||
_info "Configuring BSP options..."
|
||||
dict for {param value} [dict get $bsp_config config] {
|
||||
if {$is_vitis} {
|
||||
bsp config $param $value
|
||||
} else {
|
||||
configbsp -bsp $bsp_name $param $value
|
||||
}
|
||||
_info "Applied BSP configuration: $param = $value for $bsp_name"
|
||||
}
|
||||
}
|
||||
|
||||
if {$is_vitis} {
|
||||
bsp regenerate
|
||||
} else {
|
||||
regenbsp -bsp $bsp_name
|
||||
projects -build -type bsp -name $bsp_name
|
||||
}
|
||||
_info "BSP '$bsp_name' successfully configured and regenerated."
|
||||
return $bsp_name
|
||||
}
|
||||
|
||||
# Helper procedure to handle source files: link or copy based on LINK_SRCS
|
||||
proc _handle_sources {app_name sources} {
|
||||
# Check environment variable LINK_SRCS
|
||||
set link_srcs "y"
|
||||
if {[info exists ::env(LINK_SRCS)]} {
|
||||
set link_srcs $::env(LINK_SRCS)
|
||||
}
|
||||
|
||||
foreach source_file $sources {
|
||||
# Expand wildcards
|
||||
set expanded_sources [glob -nocomplain -directory $::root $source_file]
|
||||
if {[llength $expanded_sources] == 0} {
|
||||
_error "Source file not found" "No file or directory matches $source_file"
|
||||
}
|
||||
# Hanle each expanded source
|
||||
foreach eval_source $expanded_sources {
|
||||
set relative_source [string range $eval_source [expr [string length $::root] + 1] end]
|
||||
set target_path [file join $::ws $app_name $relative_source]
|
||||
|
||||
# Ensure the target directory exists
|
||||
set target_dir [file dirname $target_path]
|
||||
if {![file exists $target_dir]} {
|
||||
file mkdir $target_dir
|
||||
_info "Created directory: $target_dir"
|
||||
}
|
||||
|
||||
# Delete existing symbolic link or file if it exists
|
||||
if {[file exists $target_path]} {
|
||||
file delete -force $target_path
|
||||
_warn "Deleted existing link or file: $target_path"
|
||||
}
|
||||
|
||||
# Handle source based on the value of LINK_SRCS
|
||||
switch $link_srcs {
|
||||
"y" {
|
||||
# Create symbolic link
|
||||
file link -symbolic $target_path $eval_source
|
||||
_info "Created symbolic link: $target_path -> $eval_source"
|
||||
}
|
||||
"n" {
|
||||
# Copy the source file
|
||||
file copy $eval_source $target_path
|
||||
_info "Copied source file: $eval_source to $target_path"
|
||||
}
|
||||
default {
|
||||
_error "Unknown value for LINK_SRCS: ${link_srcs}."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc _update_app_mem_layout {app_name mem_layout} {
|
||||
|
||||
# Update heap and stack sizes in linker script if specified
|
||||
set lscript_path "$::ws/$app_name/src/lscript.ld"
|
||||
if {[file exists $lscript_path]} {
|
||||
set file_content {}
|
||||
set file_id [open $lscript_path r]
|
||||
while {[gets $file_id line] >= 0} {
|
||||
if {[regexp {^_HEAP_SIZE =} $line] && [dict exists $mem_layout heap_size]} {
|
||||
set heap_size [dict get $mem_layout heap_size]
|
||||
if {$heap_size ne ""} {
|
||||
set line "_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : $heap_size;"
|
||||
_info "Updating _HEAP_SIZE in linker script to $heap_size"
|
||||
} else {
|
||||
_warn "Empty `heap_size` config, _HEAP_SIZE not updated."
|
||||
}
|
||||
} elseif {[regexp {^_STACK_SIZE =} $line] && [dict exists $mem_layout stack_size]} {
|
||||
set stack_size [dict get $mem_layout stack_size]
|
||||
if {$stack_size ne ""} {
|
||||
set line "_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : $stack_size;"
|
||||
_info "Updating _STACK_SIZE in linker script to $stack_size"
|
||||
} else {
|
||||
_warn "Empty `stack_size` config, _STACK_SIZE not updated."
|
||||
}
|
||||
}
|
||||
lappend file_content $line
|
||||
}
|
||||
close $file_id
|
||||
|
||||
set file_id [open $lscript_path w]
|
||||
puts $file_id [join $file_content \n]
|
||||
close $file_id
|
||||
} else {
|
||||
_warn "Linker script $lscript_path not found for application: $app_name"
|
||||
}
|
||||
}
|
||||
|
||||
proc _update_app_build_config {app_name build_type build_config is_vitis} {
|
||||
set build_types {"debug" "release"}
|
||||
if {[lsearch $build_types $build_type] == -1} {
|
||||
_error "Invalid config type: $build_type" "available types: $build_types"
|
||||
}
|
||||
|
||||
set cmd [list]
|
||||
if {$is_vitis} {
|
||||
lappend cmd app config -name
|
||||
} else {
|
||||
lappend cmd sdk configapp -app
|
||||
}
|
||||
|
||||
_info "Setting build configuration for '$app_name' as $build_type."
|
||||
eval $cmd $app_name -set build-config $build_type
|
||||
|
||||
dict for {param value} $build_config {
|
||||
switch -exact -- $param {
|
||||
"include-path" -
|
||||
"library-search-path" {
|
||||
foreach path $value {
|
||||
set path_str [format "\"\${workspace_loc:/%s/%s}\"" $app_name $path]
|
||||
eval $cmd $app_name $param [list $path_str]
|
||||
_info "Append $param: $path for $app_name."
|
||||
}
|
||||
}
|
||||
"define-compiler-symbols" -
|
||||
"undef-compiler-symbols" -
|
||||
"libraries" {
|
||||
foreach item $value {
|
||||
eval $cmd $app_name $param $item
|
||||
_info "Append parameter $param: $item for $app_name."
|
||||
}
|
||||
}
|
||||
"assembler-flags" -
|
||||
"compiler-misc" -
|
||||
"compiler-optimization" -
|
||||
"linker-misc" -
|
||||
"linker-script" {
|
||||
if {$value ne ""} {
|
||||
eval $cmd $app_name -set $param $value
|
||||
_info "Set $param: $value for $app_name."
|
||||
}
|
||||
}
|
||||
default {
|
||||
_error "Unsupported app build-config option" $param
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Helper procedure for application configuration
|
||||
proc _create_app {app_name app_config platform_name is_vitis} {
|
||||
set cpu [dict get $app_config target_cpu]
|
||||
set os [dict get $app_config os]
|
||||
set lang [dict get $app_config language]
|
||||
set sources [dict get $app_config sources]
|
||||
set bsp_name "${os}_${cpu}"
|
||||
|
||||
# Configure BSP/Domain for application
|
||||
if {[dict exists $app_config bsp] && [dict get $app_config bsp] ne ""} {
|
||||
set bsp_name [dict get $app_config bsp]
|
||||
} else {
|
||||
set bsp_config [dict create]
|
||||
set bsp_config [dict set bsp_config target_cpu $cpu]
|
||||
set bsp_config [dict set bsp_config os $os]
|
||||
if {[dict exists $app_config bsp_lib]} {
|
||||
set bsp_lib [dict get $app_config bsp_lib]
|
||||
set bsp_config [dict merge $bsp_config [dict create libs $bsp_lib]]
|
||||
}
|
||||
if {[dict exists $app_config bsp_config]} {
|
||||
set bsp_cfg [dict get $app_config bsp_config]
|
||||
set bsp_config [dict merge $bsp_config [dict create config $bsp_cfg]]
|
||||
}
|
||||
_configure_bsp $bsp_name $bsp_config $platform_name $is_vitis
|
||||
}
|
||||
|
||||
# Create application
|
||||
_info "Creating application: $app_name"
|
||||
if {$is_vitis} {
|
||||
app create -name $app_name \
|
||||
-platform $platform_name \
|
||||
-domain $bsp_name \
|
||||
-proc $cpu \
|
||||
-os $os \
|
||||
-lang $lang \
|
||||
-sysproj $::project_name \
|
||||
-template "Empty Application($lang)"
|
||||
_info "Application '$app_name' created for Vitis."
|
||||
} else {
|
||||
sdk createapp -name $app_name \
|
||||
-hwproject $platform_name \
|
||||
-bsp $bsp_name \
|
||||
-proc $cpu \
|
||||
-os $os \
|
||||
-lang $lang \
|
||||
-app "Empty Application"
|
||||
_info "Application '$app_name' created for Xilinx SDK."
|
||||
}
|
||||
|
||||
# Handle source files if present
|
||||
if {[llength $sources] > 0} {
|
||||
_info "Handling sources for application: $app_name"
|
||||
_handle_sources $app_name $sources
|
||||
} else {
|
||||
_warn "No source files specified for application: $app_name"
|
||||
}
|
||||
|
||||
# Configure application if additional configs exist
|
||||
_info "Configuring application: $app_name"
|
||||
if {[dict exists $app_config build_config]} {
|
||||
dict for {build_type build_config} [dict get $app_config build_config] {
|
||||
_update_app_build_config $app_name $build_type $build_config $is_vitis
|
||||
}
|
||||
}
|
||||
|
||||
# Update memory layout in linker script if specified
|
||||
_info "Updating memory layout for application: $app_name"
|
||||
if {[dict exists $app_config mem_layout]} {
|
||||
set mem_layout [dict get $app_config mem_layout]
|
||||
_update_app_mem_layout $app_name $mem_layout
|
||||
}
|
||||
}
|
||||
|
||||
# Apply FSBL patches if specified
|
||||
# TODO:
|
||||
proc _apply_fsbl_patches {patches} {
|
||||
_info "Applying FSBL patches."
|
||||
dict for {target_file patch_file} $patches {
|
||||
set target_path "$::ws/fsbl/src/$target_file"
|
||||
set patch_path "$::root/$patch_file"
|
||||
|
||||
file copy -force $patch_path $target_path
|
||||
if {[file exists $patch_path]} {
|
||||
_info "Patched $target_file with $patch_file"
|
||||
} else {
|
||||
_warn "FSBL patch file $patch_path not found, new file $patch_file "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Main procedures
|
||||
proc create_project {} {
|
||||
cd $::ws
|
||||
setws $::ws
|
||||
_info "Workspace set to $::ws."
|
||||
|
||||
set is_vitis [expr {[string first ".hdf" $::hw_file] == -1}]
|
||||
set platform_name "${::project_name}_platform"
|
||||
|
||||
# Prepare hardware platform
|
||||
_prepare_platform $::hw_file $platform_name $is_vitis
|
||||
|
||||
# Process each bsp
|
||||
if {[dict exists $::config bsps]} {
|
||||
dict for {bsp_name bsp_config} [dict get $::config bsps] {
|
||||
_configure_bsp $bsp_name $bsp_config $platform_name $is_vitis
|
||||
}
|
||||
}
|
||||
|
||||
# Process each application
|
||||
dict for {app_name app_config} [dict get $::config apps] {
|
||||
_create_app $app_name $app_config $platform_name $is_vitis
|
||||
}
|
||||
}
|
||||
|
||||
proc build_project {} {
|
||||
setws $::ws
|
||||
set is_vitis [expr {[string first ".hdf" $::hw_file] == -1}]
|
||||
if {$is_vitis} {
|
||||
# paltform file can be deleted by clean operation ahead
|
||||
platform active ${::project_name}_platform
|
||||
platform generate
|
||||
}
|
||||
|
||||
# Determine build type from environment
|
||||
set build_type "debug"
|
||||
if {[info exists ::env(RELEASE)] && $::env(RELEASE) == "y"} {
|
||||
set build_type "release"
|
||||
}
|
||||
_info "Build type: $build_type"
|
||||
|
||||
dict for {app_name app_config} [dict get $::config apps] {
|
||||
_info "Building application: $app_name"
|
||||
if {$is_vitis} {
|
||||
app config -name $app_name -set build-config $build_type
|
||||
app build -name $app_name
|
||||
_info "Application '$app_name' built for Vitis."
|
||||
} else {
|
||||
sdk configapp -app $app_name -set build-config $build_type
|
||||
projects -build -type app -name $app_name
|
||||
_info "Application '$app_name' built for Xilinx SDK."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc clean_project {} {
|
||||
setws $::ws
|
||||
_info "Cleaning project in workspace: $::ws."
|
||||
|
||||
set is_vitis [expr {[string first ".hdf" $::hw_file] == -1}]
|
||||
|
||||
dict for {app_name app_config} [dict get $::config apps] {
|
||||
_info "Cleaning application: $app_name"
|
||||
if {$is_vitis} {
|
||||
app clean -name $app_name
|
||||
} else {
|
||||
projects -clean -type app -name $app_name
|
||||
}
|
||||
_info "Application '$app_name' cleaned."
|
||||
}
|
||||
}
|
||||
|
||||
# Main execution
|
||||
set function [lindex $argv 0]
|
||||
set config_file [lindex $argv 1]
|
||||
set ws [file normalize [lindex $argv 2]]
|
||||
_info "Working at $ws"
|
||||
|
||||
# Load and parse configuration
|
||||
set config_file_id [open $config_file r]
|
||||
set config_data [read $config_file_id]
|
||||
close $config_file_id
|
||||
set root [file dirname [file normalize $config_file]]
|
||||
set config [json::json2dict $config_data]
|
||||
set project_name [dict get $config project_name]
|
||||
set hw_file [file normalize [file join [file dirname $config_file] [dict get $config hw_design]]]
|
||||
|
||||
_info "Starting process: $function"
|
||||
_info "Project name: $project_name"
|
||||
_info "Hardware design file: $hw_file"
|
||||
|
||||
# Execute requested function
|
||||
$function
|
||||
_info "Process $function completed."
|
||||
@@ -0,0 +1,42 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# ENVIRONMENT VARIABLES
|
||||
#------------------------------------------------------------------------------
|
||||
define tcl_util
|
||||
xsct -nodisp $(PLATFORM_TOOLS)/util.tcl \
|
||||
$(1) \
|
||||
$(CONFIG_FILE) $(BUILD_DIR)
|
||||
endef
|
||||
|
||||
xilinx_sdkopen:
|
||||
$(call print,Launching IDE...)
|
||||
@if [ "$(call check_command,vitis)" = "y" ]; then \
|
||||
if [ "$(XILINX_VITIS_CLASSIC)" = "y" ]; then \
|
||||
vitis -classic -workspace=$(BUILD_DIR); \
|
||||
else \
|
||||
vitis -workspace=$(BUILD_DIR); \
|
||||
fi; \
|
||||
elif [ "$(call check_command,xsdk)" = "y" ]; then \
|
||||
xsdk -workspace=$(BUILD_DIR); \
|
||||
else \
|
||||
echo "No IDE found!" && exit 1; \
|
||||
fi
|
||||
|
||||
PHONY += xilinx_sdkbuild
|
||||
xilinx_sdkbuild:
|
||||
$(call print,[Build] SDK projects in $(BUILD_DIR))
|
||||
$(call tcl_util, build) $(HIDE)
|
||||
|
||||
PHONY += xilinx_sdkclean
|
||||
xilinx_sdkclean:
|
||||
$(call print,[Delete] SDK artefacts from $(BUILD_DIR))
|
||||
$(call tcl_util, clean_project) $(HIDE)
|
||||
|
||||
xilinx_project:
|
||||
$(call mk_dir,$(BUILD_DIR))
|
||||
$(call print,Creating and configuring the IDE project)
|
||||
$(call tcl_util, create_project) $(HIDE)
|
||||
|
||||
xilinx_reset: xilinx_clean_all
|
||||
|
||||
xilinx_clean_all:
|
||||
$(call remove_dir,.Xil) $(HIDE)
|
||||
@@ -0,0 +1,32 @@
|
||||
@echo off
|
||||
set "platform=xilinx"
|
||||
set "pltform_ver=2019.1"
|
||||
set "work_dir=%~dp0build"
|
||||
set "config=%~dp0config.json"
|
||||
set "tools_dir=%~dp0scripts\platform\%platform%"
|
||||
|
||||
REM Set up enviroment
|
||||
call "%tools_dir%\setenv_xilinx.bat" "%pltform_ver%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to installize enviroment.
|
||||
pause >nul
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Build project
|
||||
call "%tools_dir%\build.bat" "%config%" "%work_dir%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to build project.
|
||||
pause >nul
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Lauch SDK
|
||||
call "%tools_dir%\launch.bat" "%pltform_ver%" "%work_dir%"
|
||||
if "%ERRORLEVEL%" neq "0" (
|
||||
echo Error: Failed to launch SDK.
|
||||
pause >nul
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
@@ -0,0 +1,6 @@
|
||||
include scripts/generic_variables.mk
|
||||
|
||||
PLATFORM := <your_platform>
|
||||
CONFIG_FILE := $(PROJECT)/config.json
|
||||
|
||||
include scripts/generic.mk
|
||||
@@ -0,0 +1,119 @@
|
||||
################################################################################
|
||||
############################### Project Specific ###############################
|
||||
################################################################################
|
||||
# everything
|
||||
*
|
||||
|
||||
# git related
|
||||
!/.gitignore
|
||||
!/.gitattributes
|
||||
|
||||
# project documents
|
||||
!/*.md
|
||||
!/*.txt
|
||||
|
||||
################################################################################
|
||||
############################### Vivado Specific ################################
|
||||
################################################################################
|
||||
|
||||
# xpr: needed for recreating design
|
||||
!/*.xpr
|
||||
|
||||
# source: include everything
|
||||
!/*.srcs/
|
||||
!/*.srcs/**/*
|
||||
|
||||
# runs: exclude everything but design run results
|
||||
!/*.runs/
|
||||
!/*.runs/impl_*/
|
||||
!/*.runs/impl_*/*.bit
|
||||
!/*.runs/impl_*/*.ltx
|
||||
|
||||
# xsa (Xilinx support archive): include for ps
|
||||
!/*.xsa
|
||||
|
||||
################################################################################
|
||||
################################ Vitis Specific ################################
|
||||
################################################################################
|
||||
|
||||
# include sdk directory and everything in it
|
||||
!/vitis*/
|
||||
!/vitis*/**
|
||||
/vitis*/**.log
|
||||
/vitis*/.analytics
|
||||
|
||||
# exclude some obscure hidden SDK folders
|
||||
/vitis*/.metadata/
|
||||
/vitis*/.sdk/
|
||||
/vitis*/RemoteSystemsTempFiles/
|
||||
/vitis*/webtalk/
|
||||
|
||||
# hw_platform: exclude the entire hw_platform folder, as everything can be
|
||||
# generated from the .hdf file. Make sure to include the bitstream in the .hdf
|
||||
# file when exporting from Vivado!
|
||||
/vitis*/*_hw_platform_*/
|
||||
|
||||
# BSP: only keep `.cproject`, `.project`, `.sdkproject`, `.system.mss` and
|
||||
# Makefile, ps lib files are regenerated automatically
|
||||
/vitis*/*_bsp/*
|
||||
!/vitis*/*_bsp/*.cproject
|
||||
!/vitis*/*_bsp/*.project
|
||||
!/vitis*/*_bsp/*.sdkproject
|
||||
!/vitis*/*_bsp/system.mss
|
||||
!/vitis*/*_bsp/Makefile
|
||||
|
||||
# Application: ignored file patterns, exclude Debug & Release folders
|
||||
/vitis*/**/*.o
|
||||
/vitis*/**/*.d
|
||||
/vitis*/**/*.a
|
||||
/vitis*/*/Debug/
|
||||
/vitis*/*/Release/
|
||||
|
||||
################################################################################
|
||||
############################ Vivado & Vitis Common #############################
|
||||
################################################################################
|
||||
|
||||
# file patterns that should always be ignored (journal files, log files, dump
|
||||
# files that are created upon Vivado/SDK errors)
|
||||
*.jou
|
||||
*.log
|
||||
*.backup.jou
|
||||
*.backup.log
|
||||
*.upgrade_log
|
||||
*.dmp
|
||||
*.debug
|
||||
vivado_pid*
|
||||
|
||||
# vivado workspace files
|
||||
xsim.dir/
|
||||
xvlog.pb
|
||||
|
||||
# Xilinx tools generated files
|
||||
.metadata/
|
||||
.settings/
|
||||
.wsdata/
|
||||
.Xil/
|
||||
logs/
|
||||
Packages/
|
||||
*.log*
|
||||
|
||||
# System generated files
|
||||
# -- macOS
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
._*
|
||||
|
||||
# -- Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# -- Linux
|
||||
*~
|
||||
|
||||
# IDEs and editors' files
|
||||
*.idea
|
||||
*.vscode
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
Binary file not shown.
@@ -0,0 +1,32 @@
|
||||
# Buid folder
|
||||
build/
|
||||
|
||||
# Xilinx tools generated files
|
||||
.metadata/
|
||||
.settings/
|
||||
.wsdata/
|
||||
.Xil/
|
||||
logs/
|
||||
Packages/
|
||||
*.log*
|
||||
|
||||
# System generated files
|
||||
# -- macOS
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
._*
|
||||
|
||||
# -- Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# -- Linux
|
||||
*~
|
||||
|
||||
# IDEs and editors' files
|
||||
*.idea
|
||||
*.vscode
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
@@ -0,0 +1,8 @@
|
||||
include ../../scripts/generic_variables.mk
|
||||
|
||||
PLATFORM := xilinx
|
||||
CONFIG_FILE := $(PROJECT)/config.json
|
||||
XILINX_VITIS_CLASSIC = y
|
||||
SCRIPT_DIR = ../../scripts
|
||||
|
||||
include ../../scripts/generic.mk
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"project_name": "zc706_cx9261a",
|
||||
"version": "0.0.1",
|
||||
"hw_design": "../system_top.xsa",
|
||||
"hw_version": "zc706_cx9261a_demo-HW-0.0.1",
|
||||
"apps": {
|
||||
"sjl_dj_app_df": {
|
||||
"sources": ["source/"],
|
||||
"target_cpu": "ps7_cortexa9_0",
|
||||
"os": "standalone",
|
||||
"language": "C",
|
||||
"mem_layout" : {
|
||||
"heap_size": "0x80000",
|
||||
"stack_size": "0x4000"
|
||||
},
|
||||
"build_config": {
|
||||
"debug": {
|
||||
"include-path": ["source/include"],
|
||||
"libraries": ["cx9261a_c_dbg", "stdc++", "m"],
|
||||
"library-search-path": ["lib"]
|
||||
},
|
||||
"release": {
|
||||
"include-path": ["source/include"],
|
||||
"libraries": ["cx9261a_c", "stdc++", "m"],
|
||||
"library-search-path": ["lib"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Description: Global configurations.
|
||||
*
|
||||
* Date: 2021-04-28 13:19
|
||||
* Last Editors: Fan Hao
|
||||
* Last Edit Time: [2022-05-23 20:32]
|
||||
*
|
||||
* Revisions: Rev 0.0
|
||||
* History:
|
||||
* [2021-04-28]: Initial edition.
|
||||
*
|
||||
* Copyright(c) 2024 Beijing Institute of Technology.
|
||||
* Lab of Communication and Networking
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __APP_CONFIG_H_
|
||||
#define __APP_CONFIG_H_
|
||||
|
||||
#define XILINX_PLATFORM
|
||||
|
||||
#include "xparameters.h"
|
||||
|
||||
/******** Software Version ********/
|
||||
#define _APP_VER 0x00010008
|
||||
|
||||
#define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24)
|
||||
#define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16)
|
||||
#define _APP_VER_PATCH (_APP_VER & 0x0000FFFF)
|
||||
|
||||
/*********** Debug Info Level ************/
|
||||
// #define _DEBUG_LEVEL 1
|
||||
// 3 - print all debug info
|
||||
// 2 - print warnings and errors
|
||||
// 1 - print only errors
|
||||
// other - print nothing
|
||||
|
||||
#define DATALINK_ENABLE_AUTORECONNECT
|
||||
#define DATALINK_ENABLE_AUTOTIMESYNC
|
||||
// #define DATALINK_ENABLE_BERTEST
|
||||
|
||||
/************ Hardware Configs ************/
|
||||
#ifdef __aarch64__ // Zynq MPSoC (Zynq UltraScale+)
|
||||
#define CPU_CLK_HZ XPAR_CPU_CORTEXA53_0_CPU_CLK_FREQ_HZ
|
||||
#define FCLK_CLK0_HZ 100000000
|
||||
#define APP_TIMER_CLK_HZ FCLK_CLK0_HZ
|
||||
#else // Zynq-7000
|
||||
#define CPU_CLK_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ
|
||||
#define APP_TIMER_CLK_HZ (CPU_CLK_HZ / 2)
|
||||
#define FCLK_CLK0_HZ 100000000
|
||||
#endif
|
||||
/********* Zynq Platform Configs **********/
|
||||
// APP Timer (for logging)
|
||||
#ifdef __aarch64__ // Zynq MPSoC (Zynq UltraScale+)
|
||||
#define APPTIMER_DEVICE_ID XPAR_AXI_TIMER_DEVICE_ID
|
||||
#define APPTIMER_INTR_ID XPAR_FABRIC_AXI_TIMER_INTERRUPT_INTR
|
||||
#else
|
||||
#define APPTIMER_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID
|
||||
#define APPTIMER_INTR_ID XPAR_SCUTIMER_INTR
|
||||
#endif
|
||||
// Physical Layer Configs
|
||||
#define PHY_DEVICE_ID (0x01 | 0x00)
|
||||
#define PHY_BASEADDR XPAR_PHYC_BASEADDR
|
||||
#define PHY_BEAM_FORMING_ENABLE
|
||||
// -- Antenna Bram Configs
|
||||
#define PHY_ANTCONFIG_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_BRAM_CTRL_DEVICE_ID
|
||||
#define PHY_ANTINFO_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_BEAM_BRAM_CTRL_DEVICE_ID
|
||||
// -- Buffers
|
||||
#define PHY_TXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DEVICE_ID
|
||||
#define PHY_RXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DEVICE_ID
|
||||
// -- Xadc
|
||||
#define PHY_HW_SYSMON_DEVICE_ID XPAR_SYSTEM_MANAGEMENT_DEVICE_ID
|
||||
// -- Interrupt id
|
||||
#define PHY_INTR_ID XPAR_FABRIC_PHY_IRQ_INTR
|
||||
#define PERIODIC_5MS_INTR_ID XPAR_FABRIC_PHY_5MS_DELAY_2MS_INTR
|
||||
|
||||
// Time Controller Configs
|
||||
#define TIME_CONTROLLER_BASEADDR XPAR_TMC_BASEADDR
|
||||
|
||||
// System Bus Configs
|
||||
#define SYSBUS_BASE_ADDR XPAR_SYSTEMBUS_BASEADDR
|
||||
#define SYSBUS_TX_INTR_ID XPAR_FABRIC_SYSTEMBUS_TX_DONE_INTR
|
||||
#define SYSBUS_RX_INTR_ID XPAR_FABRIC_SYSTEMBUS_RX_DONE_INTR
|
||||
|
||||
// INTC configis
|
||||
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
|
||||
|
||||
/********* Hardware Configurations **********/
|
||||
|
||||
// Clock Management Configuration
|
||||
//#define HMC7044
|
||||
//#define AD9528
|
||||
//#define LMK04828
|
||||
//#define LMX2594_ADC
|
||||
//#define LMX2594_DAC
|
||||
|
||||
// RF Transceiver Configuration
|
||||
//#define AD9361_REG
|
||||
//#define AD9361_API
|
||||
//#define RFSOC
|
||||
#define CX9261A
|
||||
|
||||
// ADC Configuration
|
||||
//#define AD9653
|
||||
//#define AD9694
|
||||
|
||||
// RFSoC Configuration
|
||||
#ifdef RFSOC
|
||||
#define RFDC_DEVICE_ID XPAR_XRFDC_0_DEVICE_ID
|
||||
#endif
|
||||
|
||||
// AD9361 Configuration
|
||||
#define SPI_INTERFACE_SPI_ENGINE
|
||||
#define HAVE_SPLIT_GAIN_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/
|
||||
#define HAVE_TDD_SYNTH_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/
|
||||
#define AD9361_DEVICE 1 /* set it 1 if AD9361 device is used, 0 otherwise */
|
||||
#define AD9364_DEVICE 0 /* set it 1 if AD9364 device is used, 0 otherwise */
|
||||
#define AD9363A_DEVICE 0 /* set it 1 if AD9363A device is used, 0 otherwise */
|
||||
#define HAVE_VERBOSE_MESSAGES /* Recommended during development prints errors and warnings */
|
||||
// #define HAVE_DEBUG_MESSAGES /* For Debug purposes only */
|
||||
// -- AD9361 SPI Engine Configuration
|
||||
#define AD9361_SPI_DEVICE_ID 0
|
||||
#define AD9361_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define AD9361_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define AD9361_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define AD9361_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define AD9361_SPI_ENGINE_CS_DELAY 3
|
||||
#define AD9361_1_SPI_CS 0x01
|
||||
#define AD9361_2_SPI_CS 0x02
|
||||
#define AD9361_TIMEOUT_TH 2000
|
||||
// -- AD9361 GPIO Configurations
|
||||
#define AD9361_GPIO_DEVICE_ID 0
|
||||
#define AD9361_GPIO_OFFSET 54
|
||||
#define AD9361_GPIO_INPUT 0
|
||||
#define AD9361_GPIO_OUTPUT 1
|
||||
#define AD9361_GPIO_DISABLE 0
|
||||
#define AD9361_GPIO_ENABLE 1
|
||||
// -- AD9361-1
|
||||
#define AD9361_1_TXNRX (AD9361_GPIO_OFFSET + 6)
|
||||
#define AD9361_1_ENABLE (AD9361_GPIO_OFFSET + 7)
|
||||
#define AD9361_1_EN_AGC (AD9361_GPIO_OFFSET + 8)
|
||||
#define AD9361_1_RESET_B (AD9361_GPIO_OFFSET + 9)
|
||||
#define AD9361_1_CTRL_OUT0 (AD9361_GPIO_OFFSET + 10)
|
||||
#define AD9361_1_CTRL_OUT1 (AD9361_GPIO_OFFSET + 11)
|
||||
#define AD9361_1_CTRL_OUT2 (AD9361_GPIO_OFFSET + 12)
|
||||
#define AD9361_1_CTRL_OUT3 (AD9361_GPIO_OFFSET + 13)
|
||||
#define AD9361_1_CTRL_OUT4 (AD9361_GPIO_OFFSET + 14)
|
||||
#define AD9361_1_CTRL_OUT5 (AD9361_GPIO_OFFSET + 15)
|
||||
#define AD9361_1_CTRL_OUT6 (AD9361_GPIO_OFFSET + 16)
|
||||
#define AD9361_1_CTRL_OUT7 (AD9361_GPIO_OFFSET + 17)
|
||||
#define AD9361_1_CTRL_IN0 (AD9361_GPIO_OFFSET + 18)
|
||||
#define AD9361_1_CTRL_IN1 (AD9361_GPIO_OFFSET + 19)
|
||||
#define AD9361_1_CTRL_IN2 (AD9361_GPIO_OFFSET + 20)
|
||||
#define AD9361_1_CTRL_IN3 (AD9361_GPIO_OFFSET + 21)
|
||||
// AD9361-2
|
||||
#define AD9361_2_TXNRX (AD9361_GPIO_OFFSET + 22)
|
||||
#define AD9361_2_ENABLE (AD9361_GPIO_OFFSET + 23)
|
||||
#define AD9361_2_EN_AGC (AD9361_GPIO_OFFSET + 24)
|
||||
#define AD9361_2_RESET_B (AD9361_GPIO_OFFSET + 25)
|
||||
#define AD9361_2_CTRL_OUT0 (AD9361_GPIO_OFFSET + 26)
|
||||
#define AD9361_2_CTRL_OUT1 (AD9361_GPIO_OFFSET + 27)
|
||||
#define AD9361_2_CTRL_OUT2 (AD9361_GPIO_OFFSET + 28)
|
||||
#define AD9361_2_CTRL_OUT3 (AD9361_GPIO_OFFSET + 29)
|
||||
#define AD9361_2_CTRL_OUT4 (AD9361_GPIO_OFFSET + 30)
|
||||
#define AD9361_2_CTRL_OUT5 (AD9361_GPIO_OFFSET + 31)
|
||||
#define AD9361_2_CTRL_OUT6 (AD9361_GPIO_OFFSET + 32)
|
||||
#define AD9361_2_CTRL_OUT7 (AD9361_GPIO_OFFSET + 33)
|
||||
#define AD9361_2_CTRL_IN0 (AD9361_GPIO_OFFSET + 34)
|
||||
#define AD9361_2_CTRL_IN1 (AD9361_GPIO_OFFSET + 35)
|
||||
#define AD9361_2_CTRL_IN2 (AD9361_GPIO_OFFSET + 36)
|
||||
#define AD9361_2_CTRL_IN3 (AD9361_GPIO_OFFSET + 37)
|
||||
// AD9361-Status Code
|
||||
#define AD9361_SYNC (AD9361_GPIO_OFFSET + 38)
|
||||
#define AD9361_RX_FIFO_RST (AD9361_GPIO_OFFSET + 39)
|
||||
#define AD9361_1_CAL_START (AD9361_GPIO_OFFSET + 40)
|
||||
#define AD9361_2_CAL_START (AD9361_GPIO_OFFSET + 41)
|
||||
#define AD9361_RECAL (AD9361_GPIO_OFFSET + 42)
|
||||
#define AD9361_TX_SWITCH (AD9361_GPIO_OFFSET + 43)
|
||||
#define AD9361_1_CAL_DONE (AD9361_GPIO_OFFSET + 44)
|
||||
#define AD9361_2_CAL_DONE (AD9361_GPIO_OFFSET + 45)
|
||||
#define AD9361_CAL_RESULT (AD9361_GPIO_OFFSET + 46)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TX_FREQ_125,
|
||||
TX_FREQ_126,
|
||||
TX_FREQ_4125
|
||||
} ad9361TxFreq;
|
||||
|
||||
// CX9261A Configurations
|
||||
#define CX9261A_GPIO_DEVICE_ID 0
|
||||
#define CX9261A_GPIO_OFFSET 54
|
||||
#define CX9261A_NRST (CX9261A_GPIO_OFFSET+0)
|
||||
#define CX9261A_TXNRX_TRX1 (CX9261A_GPIO_OFFSET+1)
|
||||
#define CX9261A_TXNRX_TRX2 (CX9261A_GPIO_OFFSET+2)
|
||||
#define CX9261A_TXNRX_RXFB (CX9261A_GPIO_OFFSET+3)
|
||||
#define CX9261A_ENABLE_TRX1 (CX9261A_GPIO_OFFSET+4)
|
||||
#define CX9261A_ENABLE_TRX2 (CX9261A_GPIO_OFFSET+5)
|
||||
#define CX9261A_ENABLE_RXFB (CX9261A_GPIO_OFFSET+6)
|
||||
#define CX9261A_PL_RST (CX9261A_GPIO_OFFSET+7)
|
||||
#define CX9261A_TR_SEL (CX9261A_GPIO_OFFSET+8)
|
||||
#define CX9261A_TDD_FDD_SEL (CX9261A_GPIO_OFFSET+9)
|
||||
#define CX9261A_R1T1_R2T2_SEL (CX9261A_GPIO_OFFSET+10)
|
||||
#define CX9261A_SP_DP_SEL (CX9261A_GPIO_OFFSET+11)
|
||||
#define CX9261A_MCLK_DELAY_CTRL0 (CX9261A_GPIO_OFFSET+12)
|
||||
#define CX9261A_MCLK_DELAY_CTRL1 (CX9261A_GPIO_OFFSET+13)
|
||||
#define CX9261A_MCLK_DELAY_CTRL2 (CX9261A_GPIO_OFFSET+14)
|
||||
#define CX9261A_HOP_FLAG (CX9261A_GPIO_OFFSET+15)
|
||||
// -- CX9261A SPI Engine Configuration
|
||||
#define CX9261A_SPI_DEVICE_ID 0
|
||||
#define CX9261A_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define CX9261A_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define CX9261A_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define CX9261A_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define CX9261A_SPI_ENGINE_CS_DELAY 3
|
||||
#define CX9261A_SPI_CS 0x00
|
||||
|
||||
// HMC7044 Configurations
|
||||
#define HMC7044_GPIO_DEVICE_ID 0
|
||||
#define HMC7044_GPIO_OFFSET 54
|
||||
#define HMC7044_RESET (HMC7044_GPIO_OFFSET + 0)
|
||||
#define HMC7044_SYNC (HMC7044_GPIO_OFFSET + 1)
|
||||
#define HMC7044_GPIO_0 (HMC7044_GPIO_OFFSET + 2)
|
||||
#define HMC7044_GPIO_1 (HMC7044_GPIO_OFFSET + 3)
|
||||
#define HMC7044_GPIO_2 (HMC7044_GPIO_OFFSET + 4)
|
||||
#define HMC7044_GPIO_3 (HMC7044_GPIO_OFFSET + 5)
|
||||
// -- HMC7044 SPI Engine Configuration
|
||||
#define HMC7044_SPI_DEVICE_ID 0
|
||||
#define HMC7044_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define HMC7044_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define HMC7044_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define HMC7044_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define HMC7044_SPI_ENGINE_CS_DELAY 3
|
||||
#define HMC7044_SPI_CS 0x00
|
||||
|
||||
// AD9528 Configurations
|
||||
#define AD9528_GPIO_DEVICE_ID 0
|
||||
#define AD9528_GPIO_OFFSET 54
|
||||
#define AD9528_RESETB (AD9528_GPIO_OFFSET+0)
|
||||
#define AD9528_SYSREF_REQ (AD9528_GPIO_OFFSET+1)
|
||||
#define AD9528_STATUS_0 (AD9528_GPIO_OFFSET+2)
|
||||
#define AD9528_STATUS_1 (AD9528_GPIO_OFFSET+3)
|
||||
// -- AD9528 SPI Engine Configuration
|
||||
#define AD9528_SPI_DEVICE_ID 0
|
||||
#define AD9528_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define AD9528_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define AD9528_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define AD9528_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define AD9528_SPI_ENGINE_CS_DELAY 3
|
||||
#define AD9528_SPI_CS 0x00
|
||||
|
||||
// LMK04828 Configurations
|
||||
#define LMK04828_GPIO_DEVICE_ID 0
|
||||
#define LMK04828_GPIO_OFFSET 54
|
||||
// -- LMK04828 SPI Engine Configuration
|
||||
#define LMK04828_SPI_DEVICE_ID 0
|
||||
#define LMK04828_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define LMK04828_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define LMK04828_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define LMK04828_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define LMK04828_SPI_ENGINE_CS_DELAY 3
|
||||
#define LMK04828_SPI_CS 0x00
|
||||
|
||||
// LMX2594_ADC Configurations
|
||||
#define LMX2594_ADC_GPIO_DEVICE_ID 0
|
||||
#define LMX2594_ADC_GPIO_OFFSET 54
|
||||
// -- LMX2594_ADC SPI Engine Configuration
|
||||
#define LMX2594_ADC_SPI_DEVICE_ID 0
|
||||
#define LMX2594_ADC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define LMX2594_ADC_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define LMX2594_ADC_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define LMX2594_ADC_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define LMX2594_ADC_SPI_ENGINE_CS_DELAY 3
|
||||
#define LMX2594_ADC_SPI_CS 0x01
|
||||
|
||||
// LMX2594_DAC Configurations
|
||||
#define LMX2594_DAC_GPIO_DEVICE_ID 0
|
||||
#define LMX2594_DAC_GPIO_OFFSET 54
|
||||
// -- LMX2594_DAC SPI Engine Configuration
|
||||
#define LMX2594_DAC_SPI_DEVICE_ID 0
|
||||
#define LMX2594_DAC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define LMX2594_DAC_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define LMX2594_DAC_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define LMX2594_DAC_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define LMX2594_DAC_SPI_ENGINE_CS_DELAY 3
|
||||
#define LMX2594_DAC_SPI_CS 0x02
|
||||
|
||||
// AD9653 Configurations
|
||||
#define AD9653_GPIO_DEVICE_ID 0
|
||||
#define AD9653_GPIO_OFFSET 54
|
||||
#define AD9653_POWR_DOWN (AD9653_GPIO_OFFSET+0)
|
||||
// -- AD9653 SPI Engine Configuration
|
||||
#define AD9653_SPI_DEVICE_ID 0
|
||||
#define AD9653_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define AD9653_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define AD9653_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define AD9653_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define AD9653_SPI_ENGINE_CS_DELAY 3
|
||||
#define AD9653_SPI_CS 0x03
|
||||
|
||||
// AD9694 Configurations
|
||||
#define AD9694_GPIO_DEVICE_ID 0
|
||||
#define AD9694_GPIO_OFFSET 54
|
||||
// -- AD9694 SPI Engine Configuration
|
||||
#define AD9694_SPI_DEVICE_ID 0
|
||||
#define AD9694_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
|
||||
#define AD9694_SPI_ENGINE_MAX_SPEED 5000000
|
||||
#define AD9694_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
|
||||
#define AD9694_SPI_ENGINE_DATA_WIDTH 8
|
||||
#define AD9694_SPI_ENGINE_CS_DELAY 3
|
||||
#define AD9694_SPI_CS 0x03
|
||||
|
||||
// Configuration Check
|
||||
#if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE)
|
||||
#define PHY_BEAM_FORMING_ENABLE
|
||||
#warning To impliment beam scan must enable beam forming...
|
||||
#endif
|
||||
|
||||
#if defined(DATALINK_ENABLE_BERTEST)
|
||||
#if !defined(DATALINK_ENABLE_AUTOTIMESYNC)
|
||||
#warning To enbale bit error rate test, auto time-sync should be enabled...
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif //__APP_CONFIG_H_
|
||||
@@ -0,0 +1,340 @@
|
||||
#include "dev_profile.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/rf-transceiver/ad9361/ad9361_api.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
|
||||
struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = AD9361_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = AD9361_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
struct xil_gpio_init_param xil_gpio_param = {
|
||||
.type = GPIO_PS,
|
||||
.device_id = AD9361_GPIO_DEVICE_ID
|
||||
};
|
||||
|
||||
AD9361_InitParam ad9361_default_init_param = {
|
||||
/* Device selection */
|
||||
ID_AD9361, // dev_sel
|
||||
/* Reference Clock */
|
||||
48000000UL, //reference_clk_rate
|
||||
/* Base Configuration */
|
||||
1, //two_rx_two_tx_mode_enable *** adi,2rx-2tx-mode-enable
|
||||
1, //one_rx_one_tx_mode_use_rx_num *** adi,1rx-1tx-mode-use-rx-num
|
||||
1, //one_rx_one_tx_mode_use_tx_num *** adi,1rx-1tx-mode-use-tx-num
|
||||
1, //frequency_division_duplex_mode_enable *** adi,frequency-division-duplex-mode-enable
|
||||
0, //frequency_division_duplex_independent_mode_enable *** adi,frequency-division-duplex-independent-mode-enable
|
||||
0, //tdd_use_dual_synth_mode_enable *** adi,tdd-use-dual-synth-mode-enable
|
||||
0, //tdd_skip_vco_cal_enable *** adi,tdd-skip-vco-cal-enable
|
||||
0, //tx_fastlock_delay_ns *** adi,tx-fastlock-delay-ns
|
||||
0, //rx_fastlock_delay_ns *** adi,rx-fastlock-delay-ns
|
||||
0, //rx_fastlock_pincontrol_enable *** adi,rx-fastlock-pincontrol-enable
|
||||
0, //tx_fastlock_pincontrol_enable *** adi,tx-fastlock-pincontrol-enable
|
||||
0, //external_rx_lo_enable *** adi,external-rx-lo-enable
|
||||
0, //external_tx_lo_enable *** adi,external-tx-lo-enable
|
||||
5, //dc_offset_tracking_update_event_mask *** adi,dc-offset-tracking-update-event-mask
|
||||
6, //dc_offset_attenuation_high_range *** adi,dc-offset-attenuation-high-range
|
||||
5, //dc_offset_attenuation_low_range *** adi,dc-offset-attenuation-low-range
|
||||
0x28, //dc_offset_count_high_range *** adi,dc-offset-count-high-range
|
||||
0x32, //dc_offset_count_low_range *** adi,dc-offset-count-low-range
|
||||
0, //split_gain_table_mode_enable *** adi,split-gain-table-mode-enable
|
||||
MAX_SYNTH_FREF, //trx_synthesizer_target_fref_overwrite_hz *** adi,trx-synthesizer-target-fref-overwrite-hz
|
||||
0, // qec_tracking_slow_mode_enable *** adi,qec-tracking-slow-mode-enable
|
||||
/* ENSM Control */
|
||||
0, //ensm_enable_pin_pulse_mode_enable *** adi,ensm-enable-pin-pulse-mode-enable
|
||||
0, //ensm_enable_txnrx_control_enable *** adi,ensm-enable-txnrx-control-enable
|
||||
/* LO Control */
|
||||
4125000000UL, //rx_synthesizer_frequency_hz *** adi,rx-synthesizer-frequency-hz
|
||||
4126000000UL, //tx_synthesizer_frequency_hz *** adi,tx-synthesizer-frequency-hz
|
||||
1, //tx_lo_powerdown_managed_enable *** adi,tx-lo-powerdown-managed-enable
|
||||
/* Rate & BW Control */
|
||||
{768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// rx_path_clock_frequencies[6] *** adi,rx-path-clock-frequencies
|
||||
{768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// tx_path_clock_frequencies[6] *** adi,tx-path-clock-frequencies
|
||||
18000000,//rf_rx_bandwidth_hz *** adi,rf-rx-bandwidth-hz
|
||||
18000000,//rf_tx_bandwidth_hz *** adi,rf-tx-bandwidth-hz
|
||||
/* RF Port Control */
|
||||
0, //rx_rf_port_input_select *** adi,rx-rf-port-input-select
|
||||
0, //tx_rf_port_input_select *** adi,tx-rf-port-input-select
|
||||
/* TX Attenuation Control */
|
||||
10000, //tx_attenuation_mdB *** adi,tx-attenuation-mdB
|
||||
0, //update_tx_gain_in_alert_enable *** adi,update-tx-gain-in-alert-enable
|
||||
/* Reference Clock Control */
|
||||
0, //xo_disable_use_ext_refclk_enable *** adi,xo-disable-use-ext-refclk-enable
|
||||
{8, 5920}, //dcxo_coarse_and_fine_tune[2] *** adi,dcxo-coarse-and-fine-tune
|
||||
CLKOUT_DISABLE, //clk_output_mode_select *** adi,clk-output-mode-select
|
||||
/* Gain Control */
|
||||
2, //gc_rx1_mode *** adi,gc-rx1-mode
|
||||
2, //gc_rx2_mode *** adi,gc-rx2-mode
|
||||
58, //gc_adc_large_overload_thresh *** adi,gc-adc-large-overload-thresh
|
||||
4, //gc_adc_ovr_sample_size *** adi,gc-adc-ovr-sample-size
|
||||
47, //gc_adc_small_overload_thresh *** adi,gc-adc-small-overload-thresh
|
||||
8192, //gc_dec_pow_measurement_duration *** adi,gc-dec-pow-measurement-duration
|
||||
0, //gc_dig_gain_enable *** adi,gc-dig-gain-enable
|
||||
800, //gc_lmt_overload_high_thresh *** adi,gc-lmt-overload-high-thresh
|
||||
704, //gc_lmt_overload_low_thresh *** adi,gc-lmt-overload-low-thresh
|
||||
24, //gc_low_power_thresh *** adi,gc-low-power-thresh
|
||||
15, //gc_max_dig_gain *** adi,gc-max-dig-gain
|
||||
0, //gc_use_rx_fir_out_for_dec_pwr_meas_enable *** adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable
|
||||
/* Gain MGC Control */
|
||||
2, //mgc_dec_gain_step *** adi,mgc-dec-gain-step
|
||||
2, //mgc_inc_gain_step *** adi,mgc-inc-gain-step
|
||||
0, //mgc_rx1_ctrl_inp_enable *** adi,mgc-rx1-ctrl-inp-enable
|
||||
0, //mgc_rx2_ctrl_inp_enable *** adi,mgc-rx2-ctrl-inp-enable
|
||||
0, //mgc_split_table_ctrl_inp_gain_mode *** adi,mgc-split-table-ctrl-inp-gain-mode
|
||||
/* Gain AGC Control */
|
||||
10, //agc_adc_large_overload_exceed_counter *** adi,agc-adc-large-overload-exceed-counter
|
||||
2, //agc_adc_large_overload_inc_steps *** adi,agc-adc-large-overload-inc-steps
|
||||
0, //agc_adc_lmt_small_overload_prevent_gain_inc_enable *** adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable
|
||||
10, //agc_adc_small_overload_exceed_counter *** adi,agc-adc-small-overload-exceed-counter
|
||||
4, //agc_dig_gain_step_size *** adi,agc-dig-gain-step-size
|
||||
3, //agc_dig_saturation_exceed_counter *** adi,agc-dig-saturation-exceed-counter
|
||||
1000, // agc_gain_update_interval_us *** adi,agc-gain-update-interval-us
|
||||
0, //agc_immed_gain_change_if_large_adc_overload_enable *** adi,agc-immed-gain-change-if-large-adc-overload-enable
|
||||
0, //agc_immed_gain_change_if_large_lmt_overload_enable *** adi,agc-immed-gain-change-if-large-lmt-overload-enable
|
||||
10, //agc_inner_thresh_high *** adi,agc-inner-thresh-high
|
||||
1, //agc_inner_thresh_high_dec_steps *** adi,agc-inner-thresh-high-dec-steps
|
||||
12, //agc_inner_thresh_low *** adi,agc-inner-thresh-low
|
||||
1, //agc_inner_thresh_low_inc_steps *** adi,agc-inner-thresh-low-inc-steps
|
||||
10, //agc_lmt_overload_large_exceed_counter *** adi,agc-lmt-overload-large-exceed-counter
|
||||
2, //agc_lmt_overload_large_inc_steps *** adi,agc-lmt-overload-large-inc-steps
|
||||
10, //agc_lmt_overload_small_exceed_counter *** adi,agc-lmt-overload-small-exceed-counter
|
||||
5, //agc_outer_thresh_high *** adi,agc-outer-thresh-high
|
||||
2, //agc_outer_thresh_high_dec_steps *** adi,agc-outer-thresh-high-dec-steps
|
||||
18, //agc_outer_thresh_low *** adi,agc-outer-thresh-low
|
||||
2, //agc_outer_thresh_low_inc_steps *** adi,agc-outer-thresh-low-inc-steps
|
||||
1, //agc_attack_delay_extra_margin_us; *** adi,agc-attack-delay-extra-margin-us
|
||||
0, //agc_sync_for_gain_counter_enable *** adi,agc-sync-for-gain-counter-enable
|
||||
/* Fast AGC */
|
||||
64, //fagc_dec_pow_measuremnt_duration *** adi,fagc-dec-pow-measurement-duration
|
||||
260, //fagc_state_wait_time_ns *** adi,fagc-state-wait-time-ns
|
||||
/* Fast AGC - Low Power */
|
||||
0, //fagc_allow_agc_gain_increase *** adi,fagc-allow-agc-gain-increase-enable
|
||||
5, //fagc_lp_thresh_increment_time *** adi,fagc-lp-thresh-increment-time
|
||||
1, //fagc_lp_thresh_increment_steps *** adi,fagc-lp-thresh-increment-steps
|
||||
/* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */
|
||||
1, //fagc_lock_level_lmt_gain_increase_en *** adi,fagc-lock-level-lmt-gain-increase-enable
|
||||
5, //fagc_lock_level_gain_increase_upper_limit *** adi,fagc-lock-level-gain-increase-upper-limit
|
||||
/* Fast AGC - Peak Detectors and Final Settling */
|
||||
1, //fagc_lpf_final_settling_steps *** adi,fagc-lpf-final-settling-steps
|
||||
1, //fagc_lmt_final_settling_steps *** adi,fagc-lmt-final-settling-steps
|
||||
3, //fagc_final_overrange_count *** adi,fagc-final-overrange-count
|
||||
/* Fast AGC - Final Power Test */
|
||||
0, //fagc_gain_increase_after_gain_lock_en *** adi,fagc-gain-increase-after-gain-lock-enable
|
||||
/* Fast AGC - Unlocking the Gain */
|
||||
0, //fagc_gain_index_type_after_exit_rx_mode *** adi,fagc-gain-index-type-after-exit-rx-mode
|
||||
1, //fagc_use_last_lock_level_for_set_gain_en *** adi,fagc-use-last-lock-level-for-set-gain-enable
|
||||
1, //fagc_rst_gla_stronger_sig_thresh_exceeded_en *** adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable
|
||||
5, //fagc_optimized_gain_offset *** adi,fagc-optimized-gain-offset
|
||||
10, //fagc_rst_gla_stronger_sig_thresh_above_ll *** adi,fagc-rst-gla-stronger-sig-thresh-above-ll
|
||||
1, //fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en *** adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable
|
||||
1, //fagc_rst_gla_engergy_lost_goto_optim_gain_en *** adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable
|
||||
10, //fagc_rst_gla_engergy_lost_sig_thresh_below_ll *** adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll
|
||||
8, //fagc_energy_lost_stronger_sig_gain_lock_exit_cnt *** adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt
|
||||
1, //fagc_rst_gla_large_adc_overload_en *** adi,fagc-rst-gla-large-adc-overload-enable
|
||||
1, //fagc_rst_gla_large_lmt_overload_en *** adi,fagc-rst-gla-large-lmt-overload-enable
|
||||
0, //fagc_rst_gla_en_agc_pulled_high_en *** adi,fagc-rst-gla-en-agc-pulled-high-enable
|
||||
0, //fagc_rst_gla_if_en_agc_pulled_high_mode *** adi,fagc-rst-gla-if-en-agc-pulled-high-mode
|
||||
64, //fagc_power_measurement_duration_in_state5 *** adi,fagc-power-measurement-duration-in-state5
|
||||
2, //fagc_large_overload_inc_steps *** adi,fagc-adc-large-overload-inc-steps
|
||||
/* RSSI Control */
|
||||
1, //rssi_delay *** adi,rssi-delay
|
||||
1000, //rssi_duration *** adi,rssi-duration
|
||||
3, //rssi_restart_mode *** adi,rssi-restart-mode
|
||||
0, //rssi_unit_is_rx_samples_enable *** adi,rssi-unit-is-rx-samples-enable
|
||||
1, //rssi_wait *** adi,rssi-wait
|
||||
/* Aux ADC Control */
|
||||
256, //aux_adc_decimation *** adi,aux-adc-decimation
|
||||
48000000UL, //aux_adc_rate *** adi,aux-adc-rate
|
||||
/* AuxDAC Control */
|
||||
1, //aux_dac_manual_mode_enable *** adi,aux-dac-manual-mode-enable
|
||||
0, //aux_dac1_default_value_mV *** adi,aux-dac1-default-value-mV
|
||||
0, //aux_dac1_active_in_rx_enable *** adi,aux-dac1-active-in-rx-enable
|
||||
0, //aux_dac1_active_in_tx_enable *** adi,aux-dac1-active-in-tx-enable
|
||||
0, //aux_dac1_active_in_alert_enable *** adi,aux-dac1-active-in-alert-enable
|
||||
0, //aux_dac1_rx_delay_us *** adi,aux-dac1-rx-delay-us
|
||||
0, //aux_dac1_tx_delay_us *** adi,aux-dac1-tx-delay-us
|
||||
0, //aux_dac2_default_value_mV *** adi,aux-dac2-default-value-mV
|
||||
0, //aux_dac2_active_in_rx_enable *** adi,aux-dac2-active-in-rx-enable
|
||||
0, //aux_dac2_active_in_tx_enable *** adi,aux-dac2-active-in-tx-enable
|
||||
0, //aux_dac2_active_in_alert_enable *** adi,aux-dac2-active-in-alert-enable
|
||||
0, //aux_dac2_rx_delay_us *** adi,aux-dac2-rx-delay-us
|
||||
0, //aux_dac2_tx_delay_us *** adi,aux-dac2-tx-delay-us
|
||||
/* Temperature Sensor Control */
|
||||
256, //temp_sense_decimation *** adi,temp-sense-decimation
|
||||
1000, //temp_sense_measurement_interval_ms *** adi,temp-sense-measurement-interval-ms
|
||||
0xCE, //temp_sense_offset_signed *** adi,temp-sense-offset-signed
|
||||
1, //temp_sense_periodic_measurement_enable *** adi,temp-sense-periodic-measurement-enable
|
||||
/* Control Out Setup */
|
||||
0xFF, //ctrl_outs_enable_mask *** adi,ctrl-outs-enable-mask
|
||||
0, //ctrl_outs_index *** adi,ctrl-outs-index
|
||||
/* External LNA Control */
|
||||
0, //elna_settling_delay_ns *** adi,elna-settling-delay-ns
|
||||
0, //elna_gain_mdB *** adi,elna-gain-mdB
|
||||
0, //elna_bypass_loss_mdB *** adi,elna-bypass-loss-mdB
|
||||
0, //elna_rx1_gpo0_control_enable *** adi,elna-rx1-gpo0-control-enable
|
||||
0, //elna_rx2_gpo1_control_enable *** adi,elna-rx2-gpo1-control-enable
|
||||
0, //elna_gaintable_all_index_enable *** adi,elna-gaintable-all-index-enable
|
||||
/* Digital Interface Control */
|
||||
0, //digital_interface_tune_skip_mode *** adi,digital-interface-tune-skip-mode
|
||||
0, //digital_interface_tune_fir_disable *** adi,digital-interface-tune-fir-disable
|
||||
1, //pp_tx_swap_enable *** adi,pp-tx-swap-enable
|
||||
1, //pp_rx_swap_enable *** adi,pp-rx-swap-enable
|
||||
0, //tx_channel_swap_enable *** adi,tx-channel-swap-enable
|
||||
0, //rx_channel_swap_enable *** adi,rx-channel-swap-enable
|
||||
1, //rx_frame_pulse_mode_enable *** adi,rx-frame-pulse-mode-enable
|
||||
0, //two_t_two_r_timing_enable *** adi,2t2r-timing-enable
|
||||
0, //invert_data_bus_enable *** adi,invert-data-bus-enable
|
||||
0, //invert_data_clk_enable *** adi,invert-data-clk-enable
|
||||
0, //fdd_alt_word_order_enable *** adi,fdd-alt-word-order-enable
|
||||
0, //invert_rx_frame_enable *** adi,invert-rx-frame-enable
|
||||
0, //fdd_rx_rate_2tx_enable *** adi,fdd-rx-rate-2tx-enable
|
||||
0, //swap_ports_enable *** adi,swap-ports-enable
|
||||
0, //single_data_rate_enable *** adi,single-data-rate-enable
|
||||
1, //lvds_mode_enable *** adi,lvds-mode-enable
|
||||
0, //half_duplex_mode_enable *** adi,half-duplex-mode-enable
|
||||
0, //single_port_mode_enable *** adi,single-port-mode-enable
|
||||
0, //full_port_enable *** adi,full-port-enable
|
||||
0, //full_duplex_swap_bits_enable *** adi,full-duplex-swap-bits-enable
|
||||
0, //delay_rx_data *** adi,delay-rx-data
|
||||
0, //rx_data_clock_delay *** adi,rx-data-clock-delay
|
||||
4, //rx_data_delay *** adi,rx-data-delay
|
||||
7, //tx_fb_clock_delay *** adi,tx-fb-clock-delay
|
||||
0, //tx_data_delay *** adi,tx-data-delay
|
||||
150, //lvds_bias_mV *** adi,lvds-bias-mV
|
||||
1, //lvds_rx_onchip_termination_enable *** adi,lvds-rx-onchip-termination-enable
|
||||
0, //rx1rx2_phase_inversion_en *** adi,rx1-rx2-phase-inversion-enable
|
||||
0xFF, //lvds_invert1_control *** adi,lvds-invert1-control
|
||||
0x0F, //lvds_invert2_control *** adi,lvds-invert2-control
|
||||
/* GPO Control */
|
||||
0, //gpo_manual_mode_enable *** adi,gpo-manual-mode-enable
|
||||
0, //gpo_manual_mode_enable_mask *** adi,gpo-manual-mode-enable-mask
|
||||
0, //gpo0_inactive_state_high_enable *** adi,gpo0-inactive-state-high-enable
|
||||
0, //gpo1_inactive_state_high_enable *** adi,gpo1-inactive-state-high-enable
|
||||
0, //gpo2_inactive_state_high_enable *** adi,gpo2-inactive-state-high-enable
|
||||
0, //gpo3_inactive_state_high_enable *** adi,gpo3-inactive-state-high-enable
|
||||
0, //gpo0_slave_rx_enable *** adi,gpo0-slave-rx-enable
|
||||
0, //gpo0_slave_tx_enable *** adi,gpo0-slave-tx-enable
|
||||
0, //gpo1_slave_rx_enable *** adi,gpo1-slave-rx-enable
|
||||
0, //gpo1_slave_tx_enable *** adi,gpo1-slave-tx-enable
|
||||
0, //gpo2_slave_rx_enable *** adi,gpo2-slave-rx-enable
|
||||
0, //gpo2_slave_tx_enable *** adi,gpo2-slave-tx-enable
|
||||
0, //gpo3_slave_rx_enable *** adi,gpo3-slave-rx-enable
|
||||
0, //gpo3_slave_tx_enable *** adi,gpo3-slave-tx-enable
|
||||
0, //gpo0_rx_delay_us *** adi,gpo0-rx-delay-us
|
||||
0, //gpo0_tx_delay_us *** adi,gpo0-tx-delay-us
|
||||
0, //gpo1_rx_delay_us *** adi,gpo1-rx-delay-us
|
||||
0, //gpo1_tx_delay_us *** adi,gpo1-tx-delay-us
|
||||
0, //gpo2_rx_delay_us *** adi,gpo2-rx-delay-us
|
||||
0, //gpo2_tx_delay_us *** adi,gpo2-tx-delay-us
|
||||
0, //gpo3_rx_delay_us *** adi,gpo3-rx-delay-us
|
||||
0, //gpo3_tx_delay_us *** adi,gpo3-tx-delay-us
|
||||
/* Tx Monitor Control */
|
||||
37000, //low_high_gain_threshold_mdB *** adi,txmon-low-high-thresh
|
||||
0, //low_gain_dB *** adi,txmon-low-gain
|
||||
24, //high_gain_dB *** adi,txmon-high-gain
|
||||
0, //tx_mon_track_en *** adi,txmon-dc-tracking-enable
|
||||
0, //one_shot_mode_en *** adi,txmon-one-shot-mode-enable
|
||||
511, //tx_mon_delay *** adi,txmon-delay
|
||||
8192, //tx_mon_duration *** adi,txmon-duration
|
||||
2, //tx1_mon_front_end_gain *** adi,txmon-1-front-end-gain
|
||||
2, //tx2_mon_front_end_gain *** adi,txmon-2-front-end-gain
|
||||
48, //tx1_mon_lo_cm *** adi,txmon-1-lo-cm
|
||||
48, //tx2_mon_lo_cm *** adi,txmon-2-lo-cm
|
||||
/* GPIO definitions */
|
||||
/* Reset_b */
|
||||
{
|
||||
.number = AD9361_1_RESET_B,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
}, //gpio_resetb *** reset-gpios
|
||||
/* MCS Sync */
|
||||
{
|
||||
.number = -1,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
}, //gpio_sync *** sync-gpios
|
||||
/* Cal-SW1 */
|
||||
{
|
||||
.number = -1,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
}, //gpio_cal_sw1 *** cal-sw1-gpios
|
||||
/* Cal-SW2 */
|
||||
{
|
||||
.number = -1,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
}, //gpio_cal_sw2 *** cal-sw2-gpios
|
||||
|
||||
{
|
||||
.device_id = AD9361_SPI_DEVICE_ID,
|
||||
.mode = SPI_MODE_1,
|
||||
.chip_select = AD9361_1_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
},
|
||||
|
||||
/* External LO clocks */
|
||||
NULL, //(*ad9361_rfpll_ext_recalc_rate)()
|
||||
NULL, //(*ad9361_rfpll_ext_round_rate)()
|
||||
NULL, //(*ad9361_rfpll_ext_set_rate)()
|
||||
};
|
||||
|
||||
AD9361_RXFIRConfig rx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs
|
||||
3, // rx
|
||||
0, // rx_gain
|
||||
1, // rx_dec
|
||||
{
|
||||
-4, -6, -37, 35, 186, 86, -284, -315,
|
||||
107, 219, -4, 271, 558, -307, -1182, -356,
|
||||
658, 157, 207, 1648, 790, -2525, -2553, 748,
|
||||
865, -476, 3737, 6560, -3583, -14731, -5278, 14819,
|
||||
14819, -5278, -14731, -3583, 6560, 3737, -476, 865,
|
||||
748, -2553, -2525, 790, 1648, 207, 157, 658,
|
||||
-356, -1182, -307, 558, 271, -4, 219, 107,
|
||||
-315, -284, 86, 186, 35, -37, -6, -4,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // rx_coef[128]
|
||||
64, // rx_coef_size
|
||||
{0, 0, 0, 0, 0, 0}, //rx_path_clks[6]
|
||||
0 // rx_bandwidth
|
||||
};
|
||||
|
||||
AD9361_TXFIRConfig tx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs
|
||||
3, // tx
|
||||
-6, // tx_gain
|
||||
1, // tx_int
|
||||
{
|
||||
-4, -6, -37, 35, 186, 86, -284, -315,
|
||||
107, 219, -4, 271, 558, -307, -1182, -356,
|
||||
658, 157, 207, 1648, 790, -2525, -2553, 748,
|
||||
865, -476, 3737, 6560, -3583, -14731, -5278, 14819,
|
||||
14819, -5278, -14731, -3583, 6560, 3737, -476, 865,
|
||||
748, -2553, -2525, 790, 1648, 207, 157, 658,
|
||||
-356, -1182, -307, 558, 271, -4, 219, 107,
|
||||
-315, -284, 86, 186, 35, -37, -6, -4,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, // tx_coef[128]
|
||||
64, // tx_coef_size
|
||||
{0, 0, 0, 0, 0, 0}, // tx_path_clks[6]
|
||||
0 // tx_bandwidth
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
#include "dev_profile.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/frequency/ad9528/ad9528.h"
|
||||
|
||||
static struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = AD9528_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = AD9528_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = AD9528_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = AD9528_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
static struct xil_gpio_init_param xil_gpio_param = {
|
||||
.type = GPIO_PS,
|
||||
.device_id = AD9528_GPIO_DEVICE_ID
|
||||
};
|
||||
|
||||
static struct spi_init_param ad9528_spi_init = {
|
||||
.device_id = AD9528_SPI_DEVICE_ID,
|
||||
.max_speed_hz = AD9528_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_0,
|
||||
.chip_select = AD9528_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param ad9528_gpio_resetb_init = {
|
||||
.number = AD9528_RESETB,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param ad9528_gpio_sysref_req_init = {
|
||||
.number = AD9528_SYSREF_REQ,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static ad9528pll1Settings_t clockPll1Settings = {
|
||||
.refA_Frequency_Hz = 50000000,
|
||||
.refA_Divider = 1,
|
||||
.refA_bufferCtrl = SINGLE_ENDED,
|
||||
.refB_Frequency_Hz = 0,
|
||||
.refB_Divider = 1,
|
||||
.refB_bufferCtrl = DISABLED,
|
||||
.vcxo_Frequency_Hz = 50000000,
|
||||
.vcxoBufferCtrl = SINGLE_ENDED,
|
||||
.nDivider = 1
|
||||
};
|
||||
|
||||
static ad9528pll2Settings_t clockPll2Settings = {
|
||||
.rfDivider = 4,
|
||||
.n2Divider = 20,
|
||||
.totalNdiv = 80
|
||||
};
|
||||
|
||||
/*******************************************************************
|
||||
* Output Distribution Settings
|
||||
* 9369CE02A uses the following clock outputs
|
||||
* OUT 1: FPGA REFCLK
|
||||
* OUT 3: FPGA SYSREF
|
||||
* OUT 12: DUT SYSREF
|
||||
* OUT 13: DUT REFCLK
|
||||
*******************************************************************
|
||||
*/
|
||||
static ad9528outputSettings_t clockOutputSettings = {
|
||||
.outPowerDown = 0xE001,
|
||||
.outSource = {
|
||||
AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV,
|
||||
AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV,
|
||||
AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV
|
||||
},
|
||||
.outBufferCtrl = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0
|
||||
},
|
||||
.outAnalogDelay = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0
|
||||
},
|
||||
.outDigitalDelay = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0
|
||||
},
|
||||
.outChannelDiv = {
|
||||
5,25,25,5,5,
|
||||
5,5,5,5,5,
|
||||
5,5,10,5
|
||||
},
|
||||
.outFrequency_Hz = {
|
||||
200e6, 40e6, 40e6, 200e6, 200e6,
|
||||
200e6, 200e6, 200e6, 200e6, 200e6,
|
||||
200e6, 200e6, 100e6, 200e6
|
||||
}
|
||||
};
|
||||
|
||||
static ad9528sysrefSettings_t clockSysrefSettings = {
|
||||
.sysrefRequestMethod = PIN,
|
||||
.sysrefSource = INTERNAL,
|
||||
.sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH,
|
||||
.sysrefPinBufferMode = DISABLED,
|
||||
.sysrefPatternMode = CONTINUOUS,
|
||||
.sysrefNshotMode = FOUR_PULSES,
|
||||
.sysrefDivide = 256
|
||||
};
|
||||
|
||||
static ad9528spiSettings_t clockSpiSettings = {
|
||||
.chipSelectIndex = AD9528_SPI_CS, //chip select Index, not used
|
||||
.writeBitPolarity = 0, //Write bit polarity
|
||||
.longInstructionWord = 1, //16bit instruction word
|
||||
.MSBFirst = 1, //MSB first
|
||||
.CPHA = 0, //Clock phase
|
||||
.CPOL = 0, //Clock polarity
|
||||
.enSpiStreaming = 0, //uint8_t enSpiStreaming;
|
||||
.autoIncAddrUp = 1, //uint8_t autoIncAddrUp;
|
||||
.fourWireMode = 1 //uint8_t fourWireMode;
|
||||
};
|
||||
|
||||
ad9528Init_t ad9528_default_init_param = {
|
||||
/* SPI */
|
||||
.spi_init = &ad9528_spi_init,
|
||||
.gpio_init_resetb = &ad9528_gpio_resetb_init,
|
||||
.gpio_init_sysref_req = &ad9528_gpio_sysref_req_init,
|
||||
.spiSettings = &clockSpiSettings,
|
||||
.pll1Settings = &clockPll1Settings,
|
||||
.pll2Settings = &clockPll2Settings,
|
||||
.outputSettings = &clockOutputSettings,
|
||||
.sysrefSettings = &clockSysrefSettings
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "dev_profile.h"
|
||||
#include "spi.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/adc/ad9653/ad9653.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
|
||||
static struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = AD9653_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = AD9653_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = AD9653_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = AD9653_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
static struct xil_gpio_init_param xil_gpio_param = {
|
||||
.type = GPIO_PS,
|
||||
.device_id = AD9653_GPIO_DEVICE_ID
|
||||
};
|
||||
|
||||
static struct spi_init_param ad9653_spi_init = {
|
||||
.device_id = AD9653_SPI_DEVICE_ID,
|
||||
.max_speed_hz = AD9653_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_4,
|
||||
.chip_select = AD9653_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param ad9653_gpio_resetb_init = {
|
||||
.number = AD9653_POWR_DOWN,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
struct ad9653_init_param ad9653_default_init_param = {
|
||||
/* SPI */
|
||||
.spi_init = &ad9653_spi_init,
|
||||
.gpio_pdwn = &ad9653_gpio_resetb_init
|
||||
};
|
||||
|
||||
const uint32_t ad9653_default_config_len = 36;
|
||||
const struct ad9653_config ad9653_default_config[] = {
|
||||
// configuration
|
||||
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "dev_profile.h"
|
||||
#include "spi.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/adc/ad9694/ad9694.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
|
||||
static struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = AD9694_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = AD9694_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = AD9694_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = AD9694_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
//static struct xil_gpio_init_param xil_gpio_param = {
|
||||
// .type = GPIO_PS,
|
||||
// .device_id = AD9694_GPIO_DEVICE_ID
|
||||
//};
|
||||
|
||||
static struct spi_init_param ad9694_spi_init = {
|
||||
.device_id = AD9694_SPI_DEVICE_ID,
|
||||
.max_speed_hz = AD9694_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_4,
|
||||
.chip_select = AD9694_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
struct ad9694_init_param ad9694_default_init_param = {
|
||||
/* SPI */
|
||||
.spi_init = &ad9694_spi_init
|
||||
};
|
||||
|
||||
const uint32_t ad9694_default_config_len = 36;
|
||||
const struct ad9694_config ad9694_default_config[] = {
|
||||
// reset
|
||||
{0x0000, 0x81},
|
||||
{0x1228, 0x4F}, // JESD204B start-up circuit reset
|
||||
{0x1228, 0x0F}, // JESD204B start-up normal operation
|
||||
{0x1222, 0x04}, // PLL calibration
|
||||
{0x1222, 0x00}, // PLL normal operation
|
||||
{0x1262, 0x08}, // PLL loss of lock control - Clear loss of lock
|
||||
{0x1262, 0x00}, // PLL loss of lock control - Normal operation
|
||||
|
||||
// system clock
|
||||
{0x0108, 0x00}, // Clock divider = 1 -> device clock = 368.64MHz
|
||||
{0x0201, 0x00}, // Chip decimation ration = 1 -> full sample rate
|
||||
|
||||
// channel configuration
|
||||
{0x0009, 0x03}, // ADC Pair AB & CD receive all spi command
|
||||
{0x0571, 0x15}, // JESD204B map JTX Link Control 1
|
||||
{0x056E, 0x00}, // JESD204B map PLL control, lane rate 6.75~13.5Gbps, actual = 7.3728Gbps
|
||||
{0x0570, 0x49}, // JESD204B map JTX quick config: L=2 M=2 F=2
|
||||
{0x058B, 0x01}, // JESD204B map JTX SCR L config: scrambler disabled, L=2
|
||||
{0x0590, 0x2F}, // JESD204B map JTX Subclass & NP config: subclass 1, N' = 16
|
||||
{0x058D, 0x1F}, // JESD204B map JTX K config: K = 32
|
||||
{0x058F, 0x2D}, // JESD204B map JTX N config: CS = 0, N = 14
|
||||
{0x0571, 0x14}, // JESD204B map JTX Link Control 1
|
||||
{0x05B0, 0x00}, // SERDOUTx0, SERDOUTx1 power on
|
||||
{0x0120, 0x0A}, // SYSREF COntrol: continuous mode, captured on falling edge
|
||||
|
||||
// fast detect control
|
||||
{0x0040, 0x00}, // FD_B/FD_D, FD_A/FD_C function as Fast Detect B/D, A/C output
|
||||
{0x0245, 0x01}, // Fine fast detect enabled
|
||||
{0x0247, 0xFE}, // Channel map fast detect upper threshold LSB
|
||||
{0x0248, 0x1F}, // Channel map fast detect upper threshold MSB, -> 8190
|
||||
{0x0249, 0xA4}, // Channel map fast detect lower threshold LSB
|
||||
{0x024A, 0x1F}, // Channel map fast detect lower threshold MSB, -> 8100
|
||||
{0x024B, 0x80}, // Channel map fast detect dwell time LSB
|
||||
{0x024C, 0x00} // Channel map fast detect dwell time MSB, -> 128
|
||||
};
|
||||
@@ -0,0 +1,228 @@
|
||||
#include "dev_profile.h"
|
||||
#include "spi.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/rf-transceiver/cx9261a/cx9261a.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
|
||||
static struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = CX9261A_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = CX9261A_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = CX9261A_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = CX9261A_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
static struct xil_gpio_init_param xil_gpio_param = {
|
||||
.type = GPIO_PS,
|
||||
.device_id = CX9261A_GPIO_DEVICE_ID
|
||||
};
|
||||
|
||||
static struct spi_init_param cx9261a_spi_init = {
|
||||
.device_id = CX9261A_SPI_DEVICE_ID,
|
||||
.max_speed_hz = CX9261A_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_1,
|
||||
.chip_select = CX9261A_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_nrst_init = {
|
||||
.number = CX9261A_NRST,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_txnrx_trx1_init = {
|
||||
.number = CX9261A_TXNRX_TRX1,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_txnrx_trx2_init = {
|
||||
.number = CX9261A_TXNRX_TRX2,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_txnrx_rxfb_init = {
|
||||
.number = CX9261A_TXNRX_RXFB,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_enable_trx1_init = {
|
||||
.number = CX9261A_ENABLE_TRX1,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_enable_trx2_init = {
|
||||
.number = CX9261A_ENABLE_TRX2,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_enable_rxfb_init = {
|
||||
.number = CX9261A_ENABLE_RXFB,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_pl_rst_init = {
|
||||
.number = CX9261A_PL_RST,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_tr_sel_init = {
|
||||
.number = CX9261A_TR_SEL,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_tdd_fdd_sel_init = {
|
||||
.number = CX9261A_TDD_FDD_SEL,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_r1t1_r2t2_sel_init = {
|
||||
.number = CX9261A_R1T1_R2T2_SEL,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_sp_dp_sel_init = {
|
||||
.number = CX9261A_SP_DP_SEL,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_mclk_delay_ctrl0_init = {
|
||||
.number = CX9261A_MCLK_DELAY_CTRL0,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_mclk_delay_ctrl1_init = {
|
||||
.number = CX9261A_MCLK_DELAY_CTRL1,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_mclk_delay_ctrl2_init = {
|
||||
.number = CX9261A_MCLK_DELAY_CTRL2,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
static struct gpio_init_param cx9261a_gpio_hop_flag_init = {
|
||||
.number = CX9261A_HOP_FLAG,
|
||||
.platform_ops = &xil_gpio_ops,
|
||||
.extra = &xil_gpio_param
|
||||
};
|
||||
|
||||
struct cx9261a_init_param cx9261a_default_init_param = {
|
||||
/* SPI */
|
||||
.spi_init = &cx9261a_spi_init,
|
||||
.gpio_nrst = &cx9261a_gpio_nrst_init,
|
||||
.gpio_txnrx_trx1 = &cx9261a_gpio_txnrx_trx1_init,
|
||||
.gpio_txnrx_trx2 = &cx9261a_gpio_txnrx_trx2_init,
|
||||
.gpio_txnrx_rxfb = &cx9261a_gpio_txnrx_rxfb_init,
|
||||
.gpio_enable_trx1 = &cx9261a_gpio_enable_trx1_init,
|
||||
.gpio_enable_trx2 = &cx9261a_gpio_enable_trx2_init,
|
||||
.gpio_enable_rxfb = &cx9261a_gpio_enable_rxfb_init,
|
||||
.gpio_pl_rst = &cx9261a_gpio_pl_rst_init,
|
||||
.gpio_tr_sel = &cx9261a_gpio_tr_sel_init,
|
||||
.gpio_tdd_fdd_sel = &cx9261a_gpio_tdd_fdd_sel_init,
|
||||
.gpio_r1t1_r2t2_sel = &cx9261a_gpio_r1t1_r2t2_sel_init,
|
||||
.gpio_sp_dp_sel = &cx9261a_gpio_sp_dp_sel_init,
|
||||
.gpio_mclk_delay_ctrl0 = &cx9261a_gpio_mclk_delay_ctrl0_init,
|
||||
.gpio_mclk_delay_ctrl1 = &cx9261a_gpio_mclk_delay_ctrl1_init,
|
||||
.gpio_mclk_delay_ctrl2 = &cx9261a_gpio_mclk_delay_ctrl2_init,
|
||||
.gpio_hop_flag = &cx9261a_gpio_hop_flag_init
|
||||
};
|
||||
|
||||
CX9261A_CX9261AConfiguration cx9261a_configuration = {
|
||||
// 电源管理 (与评估软件电源管理自定义电源里面勾选项相对应,先左再右,从上往下)
|
||||
.powerManagement =
|
||||
{
|
||||
// 接收模式电源管理
|
||||
.rxPower = {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
|
||||
// 发射模式电源管理
|
||||
.txPower = {1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1},
|
||||
// FDD模式电源管理
|
||||
.fddPower = {1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
|
||||
0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
||||
.powerMode = CX9261A_PWM_Duplex,
|
||||
},
|
||||
// 接口模式
|
||||
.interface = {.workMode = CX9261A_WKM_FDD,
|
||||
.trMode = CX9261A_TRM_R1T1,
|
||||
.portMode = CX9261A_PORTM_Single,
|
||||
.ioMode = CX9261A_IOM_CMOS},
|
||||
// 时钟相关
|
||||
.clock = {.ref = 100,
|
||||
.adc = 64,
|
||||
.refDiv = 1,
|
||||
.bbUseIntDiv = false,
|
||||
.refDoubler = false},
|
||||
// 本振相关
|
||||
// 本振来源
|
||||
.pllSource = {.rxUseExt = false,
|
||||
.txUseExt = false,
|
||||
.rx1Source = CX9261A_LOSRC_Pll1,
|
||||
.rx2Source = CX9261A_LOSRC_Pll2,
|
||||
.rx3Source = CX9261A_LOSRC_Off,
|
||||
.tx1Source = CX9261A_LOSRC_Pll1,
|
||||
.tx2Source = CX9261A_LOSRC_Pll2},
|
||||
// 本振频率 注意:使用的所有PLL,频率必须设为正数
|
||||
.pllFreq = {.pll1Freq = 121.88,
|
||||
.pll2Freq = 5000,
|
||||
.pll3Freq = 800,
|
||||
.pll4Freq = 900,
|
||||
.pll5Freq = 1000},
|
||||
// Rx通道 注意:tia推荐配置为6 Mixer为三个通道共用同一个寄存器
|
||||
.rx1Config = {.bandwidth = 32, .tia = 6, .mixer = 31},
|
||||
.rx2Config = {.bandwidth = 32, .tia = 6, .mixer = 31},
|
||||
.rx3Config = {.bandwidth = 32, .tia = 6, .mixer = 31},
|
||||
// Tx通道
|
||||
.tx1Config = {.bandwidth = 20, .mixer = 63},
|
||||
.tx2Config = {.bandwidth = 20, .mixer = 63},
|
||||
// 接收滤波器
|
||||
.rxFilters = {.fir = 0, .hbf1 = 0, .hbf2 = 0, .hbf3 = 0, .cic = 0},
|
||||
// 发射滤波器
|
||||
.txFilters = {.fir = 0, .hbf1 = 2, .hbf2 = 2, .hbf3 = 0, .cic = 0},
|
||||
// Rx NCO
|
||||
.rxNco = {.rxUseBist = false,
|
||||
.rxNCOBypass = true,
|
||||
.rxNCOUpward = true,
|
||||
.rxNCOMaster = true,
|
||||
.rxNCOFreq = 0},
|
||||
// Tx NCO
|
||||
.txNco = {.txUseBist = false, .txNCOFreq = 0},
|
||||
// AGC 注意:mode = 0表示关闭AGC,此时其他的参数可以不配置
|
||||
// 校准
|
||||
.calib = {.calibDC = true,
|
||||
.dcCalibMethod = CX9261A_DCCALM_Tracking,
|
||||
.dcTrackingLength = 16384,
|
||||
.dcHighPassFactor = 8191,
|
||||
.rx1CalibPll = CX9261A_LOSRC_Pll1 | CX9261A_LOSRC_Pll2,
|
||||
.rx2CalibPll = CX9261A_LOSRC_Pll1 | CX9261A_LOSRC_Pll2,
|
||||
.rx3CalibPll = CX9261A_LOSRC_Pll5,
|
||||
.tx1CalibPll = 0,
|
||||
.tx2CalibPll = 0,
|
||||
.rxMethod = CX9261A_CALM_Tracking,
|
||||
.txMethod = CX9261A_CALM_Bisec,
|
||||
.f0 = 4,
|
||||
// .rxMultiPoints = {2200, 2400, 2600, 2800, 3000, 3200, 3400,
|
||||
// 3600, 3800, 4000, 4200, 4400, 4600, 4800,
|
||||
// 5000, 5200, 5400, 5600, 5800, 6000}
|
||||
},
|
||||
.agc = {.mode = 0},
|
||||
.tempComp = CX9261A_TEMPCP_Band
|
||||
};
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef _DEV_PROFILE_H_
|
||||
#define _DEV_PROFILE_H_
|
||||
|
||||
#include "irq.h"
|
||||
#include "error.h"
|
||||
#include "../drivers/frequency/hmc7044/hmc7044.h"
|
||||
#include "../drivers/frequency/ad9528/ad9528.h"
|
||||
#include "../drivers/frequency/lmk04828/lmk04828.h"
|
||||
#include "../drivers/frequency/lmx2594/lmx2594.h"
|
||||
#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h"
|
||||
#include "../drivers/rf-transceiver/ad9361/ad9361_api.h"
|
||||
#include "../drivers/rf-transceiver/cx9261a/cx9261a.h"
|
||||
#include "../drivers/rf-transceiver/cx9261a/cx9261adriver_c.h"
|
||||
#include "../drivers/adc/ad9694/ad9694.h"
|
||||
#include "../drivers/adc/ad9653/ad9653.h"
|
||||
#include "../config/app_config.h"
|
||||
|
||||
// device parameters
|
||||
extern struct irq_init_param intc_init_param;
|
||||
extern struct timer_init_param apptimer_init_param;
|
||||
|
||||
// HMC7044
|
||||
extern struct hmc7044_init_param hmc7044_default_init_param;
|
||||
|
||||
// AD9528
|
||||
extern ad9528Init_t ad9528_default_init_param;
|
||||
|
||||
// LMK04828
|
||||
extern struct lmk04828_init_param lmk04828_default_init_param;
|
||||
extern const struct lmk04828_config lmk04828_default_config[];
|
||||
extern const uint32_t lmk04828_default_config_len;
|
||||
|
||||
// LMX2594
|
||||
extern struct lmx2594_init_param lmx2594_adc_init_param;
|
||||
extern struct lmx2594_init_param lmx2594_dac_init_param;
|
||||
extern const struct lmx2594_config lmx2594_default_config[];
|
||||
extern const uint32_t lmx2594_default_config_len;
|
||||
|
||||
// AD9361
|
||||
extern AD9361_InitParam ad9361_default_init_param;
|
||||
extern AD9361_RXFIRConfig rx_fir_config;
|
||||
extern AD9361_TXFIRConfig tx_fir_config;
|
||||
extern struct ad9361_reg_init_param ad9361_1_reg_default_init_param;
|
||||
extern struct ad9361_reg_init_param ad9361_2_reg_default_init_param;
|
||||
uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev);
|
||||
|
||||
// CX9261A
|
||||
extern struct cx9261a_init_param cx9261a_default_init_param;
|
||||
extern CX9261A_CX9261AConfiguration cx9261a_configuration;
|
||||
|
||||
// AD9653
|
||||
extern struct ad9653_init_param ad9653_default_init_param;
|
||||
extern const struct ad9653_config ad9653_default_config[];
|
||||
extern const uint32_t ad9653_default_config_len;
|
||||
|
||||
// AD9694
|
||||
extern struct ad9694_init_param ad9694_default_init_param;
|
||||
extern const struct ad9694_config ad9694_default_config[];
|
||||
extern const uint32_t ad9694_default_config_len;
|
||||
|
||||
|
||||
#endif /* SRC_DEV_PROFILE_H_ */
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "dev_profile.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/frequency/hmc7044/hmc7044.h"
|
||||
|
||||
|
||||
static struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = HMC7044_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = HMC7044_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = HMC7044_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = HMC7044_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
//static struct xil_gpio_init_param xil_gpio_param = {
|
||||
// .type = GPIO_PS,
|
||||
// .device_id = AD9361_GPIO_DEVICE_ID
|
||||
//};
|
||||
|
||||
// hmc7044 spi settings
|
||||
static struct spi_init_param hmc7044_spi_init_param = {
|
||||
.device_id = HMC7044_SPI_DEVICE_ID,
|
||||
.max_speed_hz = HMC7044_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_4,
|
||||
.chip_select = HMC7044_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
// hmc7044 channel specifications
|
||||
struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
|
||||
/* AD9361_XTAL */
|
||||
{
|
||||
.disable = 0,
|
||||
.num = 3,
|
||||
.divider = 100,
|
||||
.coarse_delay = 0,
|
||||
.fine_delay = 0,
|
||||
.high_performance_mode_dis = true,
|
||||
.start_up_mode_dynamic_enable = false,
|
||||
.dynamic_driver_enable = false,
|
||||
.output_control0_rb4_enable = true,
|
||||
.force_mute_enable = false,
|
||||
.driver_mode = CML,
|
||||
.driver_impedance = INTERNAL_100OHM_PER_PIN,
|
||||
.out_mux_mode = CHANNEL_DIV
|
||||
},
|
||||
/* FPGA_DAC_LOGIC_CLK */
|
||||
{
|
||||
.disable = 0,
|
||||
.num = 4,
|
||||
.divider = 10,
|
||||
.coarse_delay = 0,
|
||||
.fine_delay = 0,
|
||||
.high_performance_mode_dis = true,
|
||||
.start_up_mode_dynamic_enable = false,
|
||||
.dynamic_driver_enable = false,
|
||||
.output_control0_rb4_enable = true,
|
||||
.force_mute_enable = false,
|
||||
.driver_mode = CML,
|
||||
.driver_impedance = INTERNAL_100OHM_PER_PIN,
|
||||
.out_mux_mode = CHANNEL_DIV
|
||||
},
|
||||
/* B_AD9361_XTAL */
|
||||
{
|
||||
.disable = 0,
|
||||
.num = 12,
|
||||
.divider = 100,
|
||||
.coarse_delay = 0,
|
||||
.fine_delay = 0,
|
||||
.high_performance_mode_dis = false,
|
||||
.start_up_mode_dynamic_enable = false,
|
||||
.dynamic_driver_enable = false,
|
||||
.output_control0_rb4_enable = true,
|
||||
.force_mute_enable = false,
|
||||
.driver_mode = CML,
|
||||
.driver_impedance = INTERNAL_100OHM_PER_PIN,
|
||||
.out_mux_mode = CHANNEL_DIV
|
||||
},
|
||||
/* AD9361_RX_EXT_LO */
|
||||
{
|
||||
.disable = 0,
|
||||
.num = 13,
|
||||
.divider = 10,
|
||||
.coarse_delay = 0,
|
||||
.fine_delay = 0,
|
||||
.high_performance_mode_dis = false,
|
||||
.start_up_mode_dynamic_enable = false,
|
||||
.dynamic_driver_enable = false,
|
||||
.output_control0_rb4_enable = true,
|
||||
.force_mute_enable = false,
|
||||
.driver_mode = CML,
|
||||
.driver_impedance = INTERNAL_100OHM_PER_PIN,
|
||||
.out_mux_mode = CHANNEL_DIV
|
||||
},
|
||||
};
|
||||
|
||||
// hmc7044 default configurations
|
||||
struct hmc7044_init_param hmc7044_default_init_param = {
|
||||
.spi_init = &hmc7044_spi_init_param,
|
||||
.clkin_freq = {0, 100000000, 0, 0},
|
||||
.vcxo_freq = 100000000,
|
||||
.pll2_freq = 2500000000,
|
||||
.pll1_loop_bw = 200,
|
||||
.sysref_timer_div = 1536,
|
||||
.in_buf_mode = {
|
||||
BUFFER_DISABLE,
|
||||
ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE,
|
||||
BUFFER_DISABLE,
|
||||
BUFFER_DISABLE,
|
||||
ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE
|
||||
},
|
||||
.gpi_ctrl = {
|
||||
GPI_DISABLE,
|
||||
GPI_DISABLE,
|
||||
CHIP_SLEEP_MODE,
|
||||
PULSE_GEN_REQUSET
|
||||
},
|
||||
.gpo_ctrl = {
|
||||
PLL1_LOCK_DETECT | GPO_CMOS_MODE,
|
||||
PLL2_LOCK_DETECT | GPO_CMOS_MODE,
|
||||
GPO_DISABLE,
|
||||
GPO_DISABLE
|
||||
},
|
||||
.num_channels = 4,
|
||||
.pll1_ref_prio_ctrl = 0xE4,
|
||||
.sync_pin_mode = SYNC_MULTICHIP,
|
||||
.high_performance_mode_clock_dist_en = false,
|
||||
.pulse_gen_mode = PULSE_ONE,
|
||||
.channels = hmc7044_chan_spec
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "dev_profile.h"
|
||||
#include "irq.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/platform/xilinx_irq.h"
|
||||
|
||||
struct xil_irq_init_param xil_intc_init_param = {
|
||||
.type = IRQ_PS
|
||||
};
|
||||
|
||||
struct irq_init_param intc_init_param = {
|
||||
.irq_ctrl_id = INTC_DEVICE_ID,
|
||||
.platform_ops = &xil_irq_ops,
|
||||
.extra = &xil_intc_init_param
|
||||
};
|
||||
@@ -0,0 +1,182 @@
|
||||
#include "dev_profile.h"
|
||||
#include "spi.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/frequency/lmk04828/lmk04828.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
|
||||
static struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = LMK04828_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = LMK04828_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = LMK04828_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = LMK04828_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
//static struct xil_gpio_init_param xil_gpio_param = {
|
||||
// .type = GPIO_PS,
|
||||
// .device_id = LMK04828_GPIO_DEVICE_ID
|
||||
//};
|
||||
|
||||
static struct spi_init_param lmk04828_spi_init = {
|
||||
.device_id = LMK04828_SPI_DEVICE_ID,
|
||||
.max_speed_hz = LMK04828_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_0,
|
||||
.chip_select = LMK04828_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
struct lmk04828_init_param lmk04828_default_init_param = {
|
||||
/* SPI */
|
||||
.spi_init = &lmk04828_spi_init
|
||||
};
|
||||
|
||||
const uint32_t lmk04828_default_config_len = 137;
|
||||
const struct lmk04828_config lmk04828_default_config[] = {
|
||||
// 192MHz
|
||||
{0x0000, 0x90}, // [7] reset; [4] 3-wire mode disabled
|
||||
{0x0000, 0x10}, // [7] normal operation; [4] 3-wire mode disabled
|
||||
{0x0002, 0x00}, // [0] normal operation
|
||||
{0x0003, 0x06}, // [7-0] product device type, read only, default: 6
|
||||
{0x0004, 0xD0}, // [7-0] msb of product identifier, read only, default: 208
|
||||
{0x0005, 0x5B}, // [7-0] lsb of product identifier, read only, default: 91
|
||||
{0x0006, 0x00}, // [7-0] ic version identifier, read only, default: 32
|
||||
{0x000C, 0x51}, // [7-0] msb of vendor identifier, read only, default: 81
|
||||
{0x000D, 0x04}, // [7-0] lsb of vendor identifier, read only, default: 4
|
||||
// device clock 0
|
||||
{0x0100, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider
|
||||
{0x0101, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count
|
||||
{0x0102, 0x55},
|
||||
{0x0103, 0x01}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux
|
||||
{0x0104, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value
|
||||
{0x0105, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb
|
||||
{0x0106, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable
|
||||
{0x0107, 0x11}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format
|
||||
// device clock 2
|
||||
{0x0108, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider
|
||||
{0x0109, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count
|
||||
{0x010A, 0x55},
|
||||
{0x010B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux
|
||||
{0x010C, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value
|
||||
{0x010D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb
|
||||
{0x010E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable
|
||||
{0x010F, 0x10}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format
|
||||
// device clock 4
|
||||
{0x0110, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider
|
||||
{0x0111, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count
|
||||
{0x0112, 0x55},
|
||||
{0x0113, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux
|
||||
{0x0114, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value
|
||||
{0x0115, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb
|
||||
{0x0116, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable
|
||||
{0x0117, 0x11}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format
|
||||
// device clock 6
|
||||
{0x0118, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider
|
||||
{0x0119, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count
|
||||
{0x011A, 0x55},
|
||||
{0x011B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux
|
||||
{0x011C, 0x02}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value
|
||||
{0x011D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb
|
||||
{0x011E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable
|
||||
{0x011F, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format
|
||||
// device clock 8
|
||||
{0x0120, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider
|
||||
{0x0121, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count
|
||||
{0x0122, 0x55},
|
||||
{0x0123, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux
|
||||
{0x0124, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value
|
||||
{0x0125, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb
|
||||
{0x0126, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable
|
||||
{0x0127, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format
|
||||
// device clock 10
|
||||
{0x0128, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider
|
||||
{0x0129, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count
|
||||
{0x012A, 0x55},
|
||||
{0x012B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux
|
||||
{0x012C, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value
|
||||
{0x012D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb
|
||||
{0x012E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable
|
||||
{0x012F, 0x51}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format
|
||||
// device clock 12
|
||||
{0x0130, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider
|
||||
{0x0131, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count
|
||||
{0x0132, 0x55},
|
||||
{0x0133, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux
|
||||
{0x0134, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value
|
||||
{0x0135, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb
|
||||
{0x0136, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable
|
||||
{0x0137, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format
|
||||
// clock distribution source
|
||||
{0x0138, 0x20}, // [6-5] VCO mux; [4] OSCout mux; [3:0] OSCout format
|
||||
{0x0139, 0x03}, // [2] SYSREF output mux; [1-0] SYSREF source
|
||||
{0x013A, 0x0C}, // [4-0] SYSREF divider [12:8]
|
||||
{0x013B, 0x00}, // [7-0] SYSREF divider [7:0]
|
||||
{0x013C, 0x00}, // [4-0] SYSREF DDLY [12:8]
|
||||
{0x013D, 0x08}, // [7-0] SYSREF DDLY [7:0]
|
||||
{0x013E, 0x03}, // [1-0] SYSREF pulse count
|
||||
{0x013F, 0x00}, // [4] pll2 mux; [3] pll1 mux; [2-1] feedback mux; [0] feedback mux enable
|
||||
{0x0140, 0x0B}, // power-down control: [7] pll1; [6] vco_ldo; [5] vco; [4] OSCin; [3] individual SYSREF; [2] SYSREF; [1] SYSREF DDLY; [0] SYSREF pluse generator
|
||||
{0x0141, 0x00}, // dynamic DDLY control
|
||||
{0x0142, 0x00}, // dynamic DDLY step control
|
||||
{0x0143, 0x10},
|
||||
{0x0144, 0xFF},
|
||||
{0x0145, 0x7F},
|
||||
{0x0146, 0x12},
|
||||
{0x0147, 0x1A},
|
||||
{0x0148, 0x03},
|
||||
{0x0149, 0x05},
|
||||
{0x014A, 0x1B},
|
||||
{0x014B, 0x16},
|
||||
{0x014C, 0x00},
|
||||
{0x014D, 0x00},
|
||||
{0x014E, 0xC0},
|
||||
{0x014F, 0x7F},
|
||||
{0x0150, 0x03},
|
||||
{0x0151, 0x02},
|
||||
{0x0152, 0x00},
|
||||
{0x0153, 0x00},
|
||||
{0x0154, 0x78},
|
||||
{0x0155, 0x00},
|
||||
{0x0156, 0x7D},
|
||||
{0x0157, 0x00},
|
||||
{0x0158, 0x96},
|
||||
{0x0159, 0x06},
|
||||
{0x015A, 0x00},
|
||||
{0x015B, 0xD4},
|
||||
{0x015C, 0x20},
|
||||
{0x015D, 0x00},
|
||||
{0x015E, 0x00},
|
||||
{0x015F, 0x3B},
|
||||
{0x0160, 0x00},
|
||||
{0x0161, 0x02},
|
||||
{0x0162, 0x44},
|
||||
{0x0163, 0x00},
|
||||
{0x0164, 0x00},
|
||||
{0x0165, 0x0C},
|
||||
{0x0171, 0xAA},
|
||||
{0x0172, 0x02},
|
||||
{0x017C, 0x15},
|
||||
{0x017D, 0x33},
|
||||
{0x0166, 0x00},
|
||||
{0x0167, 0x00},
|
||||
{0x0168, 0x19},
|
||||
{0x0169, 0x59},
|
||||
{0x016A, 0x20},
|
||||
{0x016B, 0x00},
|
||||
{0x016C, 0x00},
|
||||
{0x016D, 0x00},
|
||||
{0x016E, 0x1B},
|
||||
{0x0173, 0x00},
|
||||
{0x0182, 0x00},
|
||||
{0x0183, 0x00},
|
||||
{0x0184, 0x00},
|
||||
{0x0185, 0x00},
|
||||
{0x0188, 0x00},
|
||||
{0x0189, 0x00},
|
||||
{0x018A, 0x00},
|
||||
{0x018B, 0x00},
|
||||
{0x1FFD, 0x00},
|
||||
{0x1FFE, 0x00},
|
||||
{0x1FFF, 0x53}
|
||||
};
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "dev_profile.h"
|
||||
#include "spi.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/frequency/lmx2594/lmx2594.h"
|
||||
#include "../drivers/axi_core/spi_engine/spi_engine.h"
|
||||
#include "../drivers/platform/xilinx_gpio.h"
|
||||
|
||||
static struct spi_engine_init_param spi_engine_param = {
|
||||
.ref_clk_hz = AD9653_SPI_ENGINE_REF_CLK,
|
||||
.type = SPI_ENGINE,
|
||||
.spi_engine_baseaddr = AD9653_SPI_ENGINE_BASEADDR,
|
||||
.cs_delay = AD9653_SPI_ENGINE_CS_DELAY,
|
||||
.data_width = AD9653_SPI_ENGINE_DATA_WIDTH
|
||||
};
|
||||
|
||||
//static struct xil_gpio_init_param xil_gpio_param = {
|
||||
// .type = GPIO_PS,
|
||||
// .device_id = AD9653_GPIO_DEVICE_ID
|
||||
//};
|
||||
|
||||
static struct spi_init_param lmx2594_adc_spi_init = {
|
||||
.device_id = LMX2594_ADC_SPI_DEVICE_ID,
|
||||
.max_speed_hz = LMX2594_ADC_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_0,
|
||||
.chip_select = LMX2594_ADC_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
static struct spi_init_param lmx2594_dac_spi_init = {
|
||||
.device_id = LMX2594_DAC_SPI_DEVICE_ID,
|
||||
.max_speed_hz = LMX2594_DAC_SPI_ENGINE_MAX_SPEED,
|
||||
.mode = SPI_MODE_0,
|
||||
.chip_select = LMX2594_DAC_SPI_CS,
|
||||
.platform_ops = &spi_eng_platform_ops,
|
||||
.extra = &spi_engine_param
|
||||
};
|
||||
|
||||
struct lmx2594_init_param lmx2594_adc_init_param = {
|
||||
/* SPI */
|
||||
.spi_init = &lmx2594_adc_spi_init
|
||||
};
|
||||
|
||||
struct lmx2594_init_param lmx2594_dac_init_param = {
|
||||
/* SPI */
|
||||
.spi_init = &lmx2594_dac_spi_init
|
||||
};
|
||||
|
||||
const uint32_t lmx2594_default_config_len = 110;
|
||||
const struct lmx2594_config lmx2594_default_config[] = {
|
||||
// 0 ~ 78: General configuration
|
||||
// 79 ~ 106: Ramping configuration
|
||||
// 107 ~ 112: Readback registers
|
||||
|
||||
// Recommended Initial Power-Up Sequence
|
||||
// For the most reliable programming, TI recommends this procedure::
|
||||
// 1. Apply power to device.
|
||||
// 2. Program RESET = 1 to reset registers.
|
||||
// 3. Program RESET = 0 to remove reset.
|
||||
// 4. Program registers as shown in the register map in REVERSE order from highest to lowest.
|
||||
// 5. Wait 10 ms.
|
||||
// 6. Program register R0 one additional time with FCAL_EN = 1 to ensure that the VCO calibration runs from a stable state.
|
||||
|
||||
// Reset
|
||||
{ 0, 0x0002},
|
||||
|
||||
// Remove Reset
|
||||
{ 0, 0x0000},
|
||||
|
||||
// Reverse order programming
|
||||
{106, 0x0000},
|
||||
{105, 0x0021},
|
||||
{104, 0x0000},
|
||||
{103, 0xD555},
|
||||
{102, 0x3F97},
|
||||
{101, 0x0011},
|
||||
{100, 0x0000},
|
||||
{ 99, 0x2AAB},
|
||||
{ 98, 0x01A0},
|
||||
{ 97, 0x0888},
|
||||
{ 96, 0x0000},
|
||||
{ 95, 0x0000}, // fixed
|
||||
{ 94, 0x0000}, // fixed
|
||||
{ 93, 0x0000}, // fixed
|
||||
{ 92, 0x0000}, // fixed
|
||||
{ 91, 0x0000}, // fixed
|
||||
{ 90, 0x0000}, // fixed
|
||||
{ 89, 0x0000}, // fixed
|
||||
{ 88, 0x0000}, // fixed
|
||||
{ 87, 0x0000}, // fixed
|
||||
{ 86, 0x5879},
|
||||
{ 85, 0xEC58},
|
||||
{ 84, 0x0001},
|
||||
{ 83, 0x54C9},
|
||||
{ 82, 0x2961},
|
||||
{ 81, 0x0000},
|
||||
{ 80, 0x4000},
|
||||
{ 79, 0x001F},
|
||||
{ 78, 0x0003}, // [8:1] VCO_CAPCTRL_STRT
|
||||
{ 77, 0x0000}, // fixed
|
||||
{ 76, 0x000C}, // fixed
|
||||
{ 75, 0x0800}, // [10:6] CHDIV
|
||||
{ 74, 0x0000}, // [11:6] JESD_DAC4_CTRL; [5:0] JESD_DAC3_CTRL
|
||||
{ 73, 0x003F}, // [11:6] JESD_DAC2_CTRL; [5:0] JESD_DAC1_CTRL
|
||||
{ 72, 0x0001}, // [10:0] SYSREF_DIV
|
||||
{ 71, 0x0081}, // [7:5] SYSREF_DIV_PRE; [4] SYSREF_PULSE; [3] SYSREF_EN; [2] SYSREF_REPEAT
|
||||
{ 70, 0xC350}, // [15:0] MASH_RST_COUNT
|
||||
{ 69, 0x0000}, // [15:0] MASH_RST_COUNT
|
||||
{ 68, 0x03E8}, // fixed
|
||||
{ 67, 0x0000}, // fixed
|
||||
{ 66, 0x01F4}, // fixed
|
||||
{ 65, 0x0000}, // fixed
|
||||
{ 64, 0x1388}, // fixed
|
||||
{ 63, 0x0000}, // fixed
|
||||
{ 62, 0x0322}, // fixed
|
||||
{ 61, 0x00A8}, // fixed
|
||||
{ 60, 0x0000}, // [15:0] LD_DLY
|
||||
{ 59, 0x0001}, // [0] LD_TYPE
|
||||
{ 58, 0x9001}, // [15] INPIN_IGNORE; [14] INPIN_HYST; [13:12] INPIN_LVL; [11:9] INPIN_FMT
|
||||
{ 57, 0x0020}, // fixed
|
||||
{ 56, 0x0000}, // fixed
|
||||
{ 55, 0x0000}, // fixed
|
||||
{ 54, 0x0000}, // fixed
|
||||
{ 53, 0x0000}, // fixed
|
||||
{ 52, 0x0820}, // fixed
|
||||
{ 51, 0x0080}, // fixed
|
||||
{ 50, 0x0000}, // fixed
|
||||
{ 49, 0x4180}, // fixed
|
||||
{ 48, 0x0300}, // fixed
|
||||
{ 47, 0x0300}, // fixed
|
||||
{ 46, 0x07FC}, // [1:0] OUTB_MUX
|
||||
{ 45, 0xC0DF}, // [12:11] OUTA_MUX; [10:9] OUT_ISET; [5:0] OUTB_PWR
|
||||
{ 44, 0x1AA3}, // [13:8] OUTA_PWR; [7] OUTB_PD; [6] OUTA_PD; [5] MASH_RESET_N; [2:0] MASH_ORDER
|
||||
{ 43, 0x0000}, // [15:0] PLL_NUM
|
||||
{ 42, 0x0000}, // [15:0] PLL_NUM
|
||||
{ 41, 0x0000}, // [15:0] MASH_SEE
|
||||
{ 40, 0x0000}, // [15:0] MASH_SEE
|
||||
{ 39, 0x03E8}, // [15:0] PLL_DEN
|
||||
{ 38, 0x0000}, // [15:0] PLL_DEN
|
||||
{ 37, 0x0304}, // [37] MASH_SEED_EN; [13:8] PFD_DLY_SEL
|
||||
{ 36, 0x0028}, // [15:0] PLL_N
|
||||
{ 35, 0x0004}, // fixed
|
||||
{ 34, 0x0000}, // [2:0] PLL_N
|
||||
{ 33, 0x1E21}, // fixed
|
||||
{ 32, 0x0393}, // fixed
|
||||
{ 31, 0x43EC}, // [14] SEG1_EN
|
||||
{ 30, 0x318C}, // fixed
|
||||
{ 29, 0x318C}, // fixed
|
||||
{ 28, 0x0488}, // fixed
|
||||
{ 27, 0x0002}, // fixed
|
||||
{ 26, 0x0DB0}, // fixed
|
||||
{ 25, 0x0C2B}, // fixed
|
||||
{ 24, 0x071A}, // fixed
|
||||
{ 23, 0x007C}, // fixed
|
||||
{ 22, 0x0001}, // fixed
|
||||
{ 21, 0x0401}, // fixed
|
||||
{ 20, 0xE048}, // [13:11] VCO_SEL. [10] VCO_SEL_FORCE
|
||||
{ 19, 0x27B7}, // [7:0] VCO_CAPCTRL
|
||||
{ 18, 0x0064}, // fixed
|
||||
{ 17, 0x012C}, // [8:0] VCO_DACISET_STRT
|
||||
{ 16, 0x0080}, // [8:0] VCO_DACISET
|
||||
{ 15, 0x064F}, // fixed
|
||||
{ 14, 0x1E70}, // [6:4] CPG
|
||||
{ 13, 0x4000}, // fixed
|
||||
{ 12, 0x5001}, // [11:0] PLL_R_PR
|
||||
{ 11, 0x0018}, // [11:4] PLL_R
|
||||
{ 10, 0x10D8}, // [11:7] MULT
|
||||
{ 9, 0x0604}, // [12] OSC_2X
|
||||
{ 8, 0x2000}, // [14] VCO_DACISET_FORCE; [11] VCO_CAPCTRL_FORCE
|
||||
{ 7, 0x40B2}, // [14] OUT_FORCE
|
||||
{ 6, 0xC802}, // fixed
|
||||
{ 5, 0x00C8}, // fixed
|
||||
{ 4, 0x0C43}, // [15:8] ACAL_CMP_DLY
|
||||
{ 3, 0x0642}, // fixed
|
||||
{ 2, 0x0500}, // fixed
|
||||
{ 1, 0x0809}, // [2:0] CAL_CLK_DIV
|
||||
{ 0, 0x2598}, // [15] RAMP_EN; [14] VCO_PHASE_SYNC; [9] OUT_MUTE; [8:7] FCAL_HPFD_ADJ; [6:5] FCAL_LPFD_ADJ; [3] FCAL_EN; [2] MUXOUT_LD_SEL; [1] RESET; [0] POWERDOWN
|
||||
|
||||
// one more time
|
||||
{ 0, 0x2598}
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "dev_profile.h"
|
||||
#include "timer.h"
|
||||
#include "../config/app_config.h"
|
||||
#include "../drivers/platform/xilinx_timer.h"
|
||||
|
||||
struct xil_timer_init_param xil_apptimer_init_param = {
|
||||
.active_tmr = 0,
|
||||
#ifdef __aarch64__
|
||||
.type = TIMER_PL
|
||||
#else
|
||||
.type = TIMER_PS
|
||||
#endif
|
||||
};
|
||||
|
||||
struct timer_init_param apptimer_init_param = {
|
||||
.id = APPTIMER_DEVICE_ID,
|
||||
.freq_hz = APP_TIMER_CLK_HZ,
|
||||
.ticks_count = (APP_TIMER_CLK_HZ/10), //update log every 100ms
|
||||
.platform_ops = &xil_timer_ops,
|
||||
.extra = &xil_apptimer_init_param
|
||||
};
|
||||
@@ -0,0 +1,129 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9653.c
|
||||
* @brief Implementation of AD9653 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include "ad9653.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "../../../include/error.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9653_read
|
||||
*******************************************************************************/
|
||||
int32_t ad9653_read(struct ad9653_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data)
|
||||
{
|
||||
uint8_t tx_buf[2];
|
||||
uint8_t rx_buf[1];
|
||||
int32_t ret;
|
||||
|
||||
tx_buf[0] = 0x80 | (reg_addr >> 8);
|
||||
tx_buf[1] = reg_addr & 0xFF;
|
||||
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
tx_buf, rx_buf, 2, 1);
|
||||
|
||||
*reg_data = rx_buf[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9653_write
|
||||
*******************************************************************************/
|
||||
int32_t ad9653_write(struct ad9653_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
|
||||
int32_t ret;
|
||||
|
||||
buf[0] = reg_addr >> 8;
|
||||
buf[1] = reg_addr & 0xFF;
|
||||
buf[2] = reg_data;
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
buf, NULL, 3, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9653_init
|
||||
*******************************************************************************/
|
||||
int32_t ad9653_init(struct ad9653_dev **device,
|
||||
const struct ad9653_init_param *init_param)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
struct ad9653_dev *dev;
|
||||
|
||||
dev = (struct ad9653_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Free the resources allocated by ad9653_setup().
|
||||
*
|
||||
* @param dev - The device structure.
|
||||
*
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*******************************************************************************/
|
||||
int32_t ad9653_remove(struct ad9653_dev *dev)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = spi_remove(dev->spi_desc);
|
||||
|
||||
free(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9653.h
|
||||
* @brief Header file of AD9653 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef AD9653_H_
|
||||
#define AD9653_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
#define AD9694_REG_GLOBAL_MAP_SPI_CONF_A 0x0000
|
||||
#define AD9694_REG_GLOBAL_MAP_SPI_CONF_B 0x0001
|
||||
#define AD9694_REG_CH_MAP_CHIP_CONF 0x0002
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_TYPE 0x0003
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_ID_LSB 0x0004
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_GRADE 0x0006
|
||||
#define AD9694_REG_PAIR_MAP_DEV_INDEX 0x0008
|
||||
#define AD9694_REG_GLOBAL_MAP_PAIR_INDEX 0x0009
|
||||
#define AD9694_REG_PAIR_MAP_SCRATCH_PAD 0x000A
|
||||
#define AD9694_REG_PAIR_MAP_SPI_REVISION 0x000B
|
||||
#define AD9694_REG_PAIR_MAP_VENDOR_ID_LSB 0x000C
|
||||
#define AD9694_REG_PAIR_MAP_VENDOR_ID_MSB 0x000D
|
||||
#define AD9694_REG_CH_MAP_CHIP_PD_PIN 0x003F
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_PIN_CTRL_1 0x0040
|
||||
#define AD9694_REG_PAIR_MAP_CLK_DIV_CTRL 0x0108
|
||||
#define AD9694_REG_CH_MAP_CLK_DIV_PHASE 0x0109
|
||||
#define AD9694_REG_PAIR_MAP_CLK_DIV_SYSREF_CTRL 0x010A
|
||||
#define AD9694_REG_PAIR_MAP_CLK_DELAY_CTRL 0x0110
|
||||
#define AD9694_REG_CH_MAP_CLK_SUPER_FINE_DELAY 0x0111
|
||||
#define AD9694_REG_CH_MAP_CLK_FINE_DELAY 0x0112
|
||||
#define AD9694_REG_CLK_DETN_CTRL 0x011A
|
||||
#define AD9694_REG_PAIR_MAP_CLK_STAT 0x011B
|
||||
#define AD9694_REG_CLK_DCS_CTRL_1 0x011C
|
||||
#define AD9694_REG_CLK_DCS_CTRL_2 0x011E
|
||||
#define AD9694_REG_CLK_DCS_CTRL_3 0x011F
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_1 0x0120
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_2 0x0121
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_4 0x0123
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_STAT_1 0x0128
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_STAT_2 0x0129
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_STAT_3 0x012A
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_SYNC 0x01FF
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_MODE 0x0200
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_DEC_RATIO 0x0201
|
||||
#define AD9694_REG_CH_MAP_CUSTOM_OFFSET 0x0228
|
||||
#define AD9694_REG_CH_MAP_FD_CTRL 0x0245
|
||||
#define AD9694_REG_CH_MAP_FD_UT_LSB 0x0247
|
||||
#define AD9694_REG_CH_MAP_FD_UT_MSB 0x0248
|
||||
#define AD9694_REG_CH_MAP_FD_LT_LSB 0x0249
|
||||
#define AD9694_REG_CH_MAP_FD_LT_MSB 0x024A
|
||||
#define AD9694_REG_CH_MAP_FD_DWELL_TIME_LSB 0x024B
|
||||
#define AD9694_REG_CH_MAP_FD_DWELL_TIME_MSB 0x024C
|
||||
#define AD9694_REG_PAIR_MAP_SIG_MON_SYNC_CTRL 0x026F
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_CTRL 0x0270
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_0 0x0271
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_1 0x0272
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_2 0x0273
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_CTRL 0x0274
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_0 0x0275
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_1 0x0276
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_2 0x0277
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_FRAME_CNT 0x0278
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_SERIAL_FRAMER_CTRL 0x0279
|
||||
#define AD9694_REG_SPORT_OVER_JESD204B_INPUT_SEL 0x027A
|
||||
#define AD9694_REG_PAIR_MAP_DDC_SYNC_CTRL 0x0300
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_CTRL 0x0310
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_INPUT_SEL 0x0311
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_0 0x0314
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_1 0x0315
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_2 0x0316
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_3 0x0317
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_4 0x0318
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_5 0x031A
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_0 0x031D
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_1 0x031E
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_2 0x031F
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_3 0x0320
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_4 0x0321
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_5 0x0322
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_TEST_ENABLE 0x0327
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_CTRL 0x0330
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_INPUT_SEL 0x0331
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_0 0x0334
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_1 0x0335
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_2 0x0336
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_3 0x0337
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_4 0x0338
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_5 0x033A
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_0 0x033D
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_1 0x033E
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_2 0x033F
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_3 0x0340
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_4 0x0341
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_5 0x0342
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_TEST_ENABLE 0x0347
|
||||
#define AD9694_REG_CH_MAP_TEST_MODE_CTRL 0x0550
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_LSB 0x0551
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_MSB 0x0552
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_LSB 0x0553
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_MSB 0x0554
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_LSB 0x0555
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_MSB 0x0556
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_LSB 0x0557
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_MSB 0x0558
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_0 0x0559
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_1 0x055A
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_SAMPLE_MODE 0x0561
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_CH_SEL 0x0564
|
||||
#define AD9694_REG_JESD204B_MAP_PLL_CTRL 0x056E
|
||||
#define AD9694_REG_JESD204B_MAP_PLL_STAT 0x056F
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_QUICK_CONF 0x0570
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_1 0x0571
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_2 0x0572
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_3 0x0573
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_4 0x0574
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LMFC_OFFSET 0x0578
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_DID_CONF 0x0580
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_BID_CONF 0x0581
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LID_0_CONF 0x0583
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LID_1_CONF 0x0585
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_SCR_L_CONF 0x058B
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_F_CONF 0x058C
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_K_CONF 0x058D
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_M_CONF 0x058E
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_CS_N_CONF 0x058F
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_SUBCLASS_CONF 0x0590
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_S_CONF 0x0591
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_HD_CF_CONF 0x0592
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_0_CONF 0x05A0
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_1_CONF 0x05A1
|
||||
#define AD9694_REG_SERDOUTX0_SERDOUTX1_LANE_PD 0x05B0
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_1 0x05B2
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_2 0x05B3
|
||||
#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_0 0x05C0
|
||||
#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_1 0x05C1
|
||||
#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_0 0x05C4
|
||||
#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_1 0x05C6
|
||||
#define AD9694_REG_LARGE_DITHER_CTRL 0x0922
|
||||
#define AD9694_REG_PLL_CAL 0x1222
|
||||
#define AD9694_REG_JESD204B_STARTUP_CIRCUIT_RST 0x1228
|
||||
#define AD9694_REG_PLL_LOSS_OF_LOCK_CTRL 0x1262
|
||||
#define AD9694_REG_DC_OFFSET_CAL_CTRL 0x0701
|
||||
#define AD9694_REG_DC_OFFSET_CAL_CTRL_2 0x073B
|
||||
#define AD9694_REG_PAIR_MAP_VREF_CTRL 0x18A6
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL_1 0x18E0
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL_2 0x18E1
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL_3 0x18E2
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL 0x18E3
|
||||
#define AD9694_REG_TEMP_DIODE_EXPORT 0x18E6
|
||||
#define AD9694_REG_CH_MAP_ANALOG_INPUT_CTRL 0x1908
|
||||
#define AD9694_REG_CH_MAP_INPUT_FULLSCALE_RANGE 0x1910
|
||||
#define AD9694_REG_CH_MAP_BUF_CTRL_1 0x1A4C
|
||||
#define AD9694_REG_CH_MAP_BUF_CTRL_2 0x1A4D
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
struct ad9653_dev {
|
||||
/* SPI */
|
||||
struct spi_desc *spi_desc;
|
||||
struct gpio_desc *gpio_desc_pdwn;
|
||||
};
|
||||
|
||||
struct ad9653_init_param {
|
||||
/* SPI */
|
||||
struct spi_init_param *spi_init;
|
||||
struct gpio_init_param *gpio_pdwn;
|
||||
};
|
||||
|
||||
struct ad9653_config {
|
||||
uint16_t addr;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int32_t ad9653_read(struct ad9653_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data);
|
||||
|
||||
int32_t ad9653_write(struct ad9653_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data);
|
||||
|
||||
int32_t ad9653_init(struct ad9653_dev **device,
|
||||
const struct ad9653_init_param *init_param);
|
||||
|
||||
int32_t ad9653_remove(struct ad9653_dev *dev);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9694.c
|
||||
* @brief Implementation of AD9680 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "ad9694.h"
|
||||
#include "../../../include/error.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9694_read
|
||||
*******************************************************************************/
|
||||
int32_t ad9694_read(struct ad9694_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data)
|
||||
{
|
||||
uint8_t tx_buf[2];
|
||||
uint8_t rx_buf[1];
|
||||
int32_t ret;
|
||||
|
||||
tx_buf[0] = 0x80 | (reg_addr >> 8);
|
||||
tx_buf[1] = reg_addr & 0xFF;
|
||||
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
tx_buf, rx_buf, 2, 1);
|
||||
|
||||
*reg_data = rx_buf[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9694_write
|
||||
*******************************************************************************/
|
||||
int32_t ad9694_write(struct ad9694_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
|
||||
int32_t ret;
|
||||
|
||||
buf[0] = reg_addr >> 8;
|
||||
buf[1] = reg_addr & 0xFF;
|
||||
buf[2] = reg_data;
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
buf, NULL, 3, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9694_init
|
||||
*******************************************************************************/
|
||||
int32_t ad9694_init(struct ad9694_dev **device,
|
||||
const struct ad9694_init_param *init_param)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
struct ad9694_dev *dev;
|
||||
|
||||
dev = (struct ad9694_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Free the resources allocated by ad9694_setup().
|
||||
*
|
||||
* @param dev - The device structure.
|
||||
*
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*******************************************************************************/
|
||||
int32_t ad9694_remove(struct ad9694_dev *dev)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = spi_remove(dev->spi_desc);
|
||||
|
||||
free(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9694.h
|
||||
* @brief Header file of AD9694 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef AD9694_H_
|
||||
#define AD9694_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
#define AD9694_REG_GLOBAL_MAP_SPI_CONF_A 0x0000
|
||||
#define AD9694_REG_GLOBAL_MAP_SPI_CONF_B 0x0001
|
||||
#define AD9694_REG_CH_MAP_CHIP_CONF 0x0002
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_TYPE 0x0003
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_ID_LSB 0x0004
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_GRADE 0x0006
|
||||
#define AD9694_REG_PAIR_MAP_DEV_INDEX 0x0008
|
||||
#define AD9694_REG_GLOBAL_MAP_PAIR_INDEX 0x0009
|
||||
#define AD9694_REG_PAIR_MAP_SCRATCH_PAD 0x000A
|
||||
#define AD9694_REG_PAIR_MAP_SPI_REVISION 0x000B
|
||||
#define AD9694_REG_PAIR_MAP_VENDOR_ID_LSB 0x000C
|
||||
#define AD9694_REG_PAIR_MAP_VENDOR_ID_MSB 0x000D
|
||||
#define AD9694_REG_CH_MAP_CHIP_PD_PIN 0x003F
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_PIN_CTRL_1 0x0040
|
||||
#define AD9694_REG_PAIR_MAP_CLK_DIV_CTRL 0x0108
|
||||
#define AD9694_REG_CH_MAP_CLK_DIV_PHASE 0x0109
|
||||
#define AD9694_REG_PAIR_MAP_CLK_DIV_SYSREF_CTRL 0x010A
|
||||
#define AD9694_REG_PAIR_MAP_CLK_DELAY_CTRL 0x0110
|
||||
#define AD9694_REG_CH_MAP_CLK_SUPER_FINE_DELAY 0x0111
|
||||
#define AD9694_REG_CH_MAP_CLK_FINE_DELAY 0x0112
|
||||
#define AD9694_REG_CLK_DETN_CTRL 0x011A
|
||||
#define AD9694_REG_PAIR_MAP_CLK_STAT 0x011B
|
||||
#define AD9694_REG_CLK_DCS_CTRL_1 0x011C
|
||||
#define AD9694_REG_CLK_DCS_CTRL_2 0x011E
|
||||
#define AD9694_REG_CLK_DCS_CTRL_3 0x011F
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_1 0x0120
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_2 0x0121
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_4 0x0123
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_STAT_1 0x0128
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_STAT_2 0x0129
|
||||
#define AD9694_REG_PAIR_MAP_SYSREF_STAT_3 0x012A
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_SYNC 0x01FF
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_MODE 0x0200
|
||||
#define AD9694_REG_PAIR_MAP_CHIP_DEC_RATIO 0x0201
|
||||
#define AD9694_REG_CH_MAP_CUSTOM_OFFSET 0x0228
|
||||
#define AD9694_REG_CH_MAP_FD_CTRL 0x0245
|
||||
#define AD9694_REG_CH_MAP_FD_UT_LSB 0x0247
|
||||
#define AD9694_REG_CH_MAP_FD_UT_MSB 0x0248
|
||||
#define AD9694_REG_CH_MAP_FD_LT_LSB 0x0249
|
||||
#define AD9694_REG_CH_MAP_FD_LT_MSB 0x024A
|
||||
#define AD9694_REG_CH_MAP_FD_DWELL_TIME_LSB 0x024B
|
||||
#define AD9694_REG_CH_MAP_FD_DWELL_TIME_MSB 0x024C
|
||||
#define AD9694_REG_PAIR_MAP_SIG_MON_SYNC_CTRL 0x026F
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_CTRL 0x0270
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_0 0x0271
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_1 0x0272
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_2 0x0273
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_CTRL 0x0274
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_0 0x0275
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_1 0x0276
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_2 0x0277
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_STAT_FRAME_CNT 0x0278
|
||||
#define AD9694_REG_CH_MAP_SIG_MON_SERIAL_FRAMER_CTRL 0x0279
|
||||
#define AD9694_REG_SPORT_OVER_JESD204B_INPUT_SEL 0x027A
|
||||
#define AD9694_REG_PAIR_MAP_DDC_SYNC_CTRL 0x0300
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_CTRL 0x0310
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_INPUT_SEL 0x0311
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_0 0x0314
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_1 0x0315
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_2 0x0316
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_3 0x0317
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_4 0x0318
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_5 0x031A
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_0 0x031D
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_1 0x031E
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_2 0x031F
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_3 0x0320
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_4 0x0321
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_5 0x0322
|
||||
#define AD9694_REG_PAIR_MAP_DDC_0_TEST_ENABLE 0x0327
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_CTRL 0x0330
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_INPUT_SEL 0x0331
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_0 0x0334
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_1 0x0335
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_2 0x0336
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_3 0x0337
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_4 0x0338
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_5 0x033A
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_0 0x033D
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_1 0x033E
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_2 0x033F
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_3 0x0340
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_4 0x0341
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_5 0x0342
|
||||
#define AD9694_REG_PAIR_MAP_DDC_1_TEST_ENABLE 0x0347
|
||||
#define AD9694_REG_CH_MAP_TEST_MODE_CTRL 0x0550
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_LSB 0x0551
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_MSB 0x0552
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_LSB 0x0553
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_MSB 0x0554
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_LSB 0x0555
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_MSB 0x0556
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_LSB 0x0557
|
||||
#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_MSB 0x0558
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_0 0x0559
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_1 0x055A
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_SAMPLE_MODE 0x0561
|
||||
#define AD9694_REG_PAIR_MAP_OUTPUT_CH_SEL 0x0564
|
||||
#define AD9694_REG_JESD204B_MAP_PLL_CTRL 0x056E
|
||||
#define AD9694_REG_JESD204B_MAP_PLL_STAT 0x056F
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_QUICK_CONF 0x0570
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_1 0x0571
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_2 0x0572
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_3 0x0573
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_4 0x0574
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LMFC_OFFSET 0x0578
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_DID_CONF 0x0580
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_BID_CONF 0x0581
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LID_0_CONF 0x0583
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LID_1_CONF 0x0585
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_SCR_L_CONF 0x058B
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_F_CONF 0x058C
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_K_CONF 0x058D
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_M_CONF 0x058E
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_CS_N_CONF 0x058F
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_SUBCLASS_CONF 0x0590
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_S_CONF 0x0591
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_HD_CF_CONF 0x0592
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_0_CONF 0x05A0
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_1_CONF 0x05A1
|
||||
#define AD9694_REG_SERDOUTX0_SERDOUTX1_LANE_PD 0x05B0
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_1 0x05B2
|
||||
#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_2 0x05B3
|
||||
#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_0 0x05C0
|
||||
#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_1 0x05C1
|
||||
#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_0 0x05C4
|
||||
#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_1 0x05C6
|
||||
#define AD9694_REG_LARGE_DITHER_CTRL 0x0922
|
||||
#define AD9694_REG_PLL_CAL 0x1222
|
||||
#define AD9694_REG_JESD204B_STARTUP_CIRCUIT_RST 0x1228
|
||||
#define AD9694_REG_PLL_LOSS_OF_LOCK_CTRL 0x1262
|
||||
#define AD9694_REG_DC_OFFSET_CAL_CTRL 0x0701
|
||||
#define AD9694_REG_DC_OFFSET_CAL_CTRL_2 0x073B
|
||||
#define AD9694_REG_PAIR_MAP_VREF_CTRL 0x18A6
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL_1 0x18E0
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL_2 0x18E1
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL_3 0x18E2
|
||||
#define AD9694_REG_EXT_VCM_BUF_CTRL 0x18E3
|
||||
#define AD9694_REG_TEMP_DIODE_EXPORT 0x18E6
|
||||
#define AD9694_REG_CH_MAP_ANALOG_INPUT_CTRL 0x1908
|
||||
#define AD9694_REG_CH_MAP_INPUT_FULLSCALE_RANGE 0x1910
|
||||
#define AD9694_REG_CH_MAP_BUF_CTRL_1 0x1A4C
|
||||
#define AD9694_REG_CH_MAP_BUF_CTRL_2 0x1A4D
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
struct ad9694_dev {
|
||||
/* SPI */
|
||||
struct spi_desc *spi_desc;
|
||||
};
|
||||
|
||||
struct ad9694_init_param {
|
||||
/* SPI */
|
||||
struct spi_init_param *spi_init;
|
||||
};
|
||||
|
||||
struct ad9694_config {
|
||||
uint16_t addr;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int32_t ad9694_read(struct ad9694_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data);
|
||||
|
||||
int32_t ad9694_write(struct ad9694_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data);
|
||||
|
||||
int32_t ad9694_init(struct ad9694_dev **device,
|
||||
const struct ad9694_init_param *init_param);
|
||||
|
||||
int32_t ad9694_remove(struct ad9694_dev *dev);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,241 @@
|
||||
/***************************************************************************//**
|
||||
* @file gpio.c
|
||||
* @brief Implementation of the GPIO Interface
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "gpio.h"
|
||||
#include <stdlib.h>
|
||||
#include "error.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Obtain the GPIO decriptor.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param param - GPIO Initialization parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_get(struct gpio_desc **desc,
|
||||
const struct gpio_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->gpio_ops_get)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->gpio_ops_get(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of an optional GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param param - GPIO Initialization parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_get_optional(struct gpio_desc **desc,
|
||||
const struct gpio_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || (param->number == -1)) {
|
||||
*desc = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->gpio_ops_get_optional)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->gpio_ops_get_optional(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @brief Free the resources allocated by gpio_get().
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_remove(struct gpio_desc *desc)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_remove(desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the input direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_direction_input(struct gpio_desc *desc)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_direction_input)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_direction_input(desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the output direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: GPIO_HIGH
|
||||
* GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_direction_output(struct gpio_desc *desc,
|
||||
uint8_t value)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_direction_output)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->
|
||||
gpio_ops_direction_output(desc, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param direction - The direction.
|
||||
* Example: GPIO_OUT
|
||||
* GPIO_IN
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_get_direction(struct gpio_desc *desc,
|
||||
uint8_t *direction)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_get_direction)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->
|
||||
gpio_ops_get_direction(desc, direction);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the value of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: GPIO_HIGH
|
||||
* GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_set_value(struct gpio_desc *desc,
|
||||
uint8_t value)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_set_value)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_set_value(desc, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: GPIO_HIGH
|
||||
* GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t gpio_get_value(struct gpio_desc *desc,
|
||||
uint8_t *value)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_set_value)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_get_value(desc, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/***************************************************************************//**
|
||||
* @file i2c.c
|
||||
* @brief Implementation of the I2C Interface
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "i2c.h"
|
||||
#include <stdlib.h>
|
||||
#include "error.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the I2C communication peripheral.
|
||||
* @param desc - The I2C descriptor.
|
||||
* @param param - The structure that contains the I2C parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t i2c_init(struct i2c_desc **desc,
|
||||
const struct i2c_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->i2c_ops_init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->i2c_ops_init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by i2c_init().
|
||||
* @param desc - The I2C descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t i2c_remove(struct i2c_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i2c_ops_remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->i2c_ops_remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C Write data to slave device.
|
||||
* @param desc - The I2C descriptor.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @param bytes_number - Number of bytes to write.
|
||||
* @param stop_bit - Stop conditional control.
|
||||
* Example: 0 - A stop condition will not be generated.
|
||||
* 1 - A stop condition will be generated.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t i2c_write(struct i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i2c_ops_write)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->i2c_ops_write(desc, data, bytes_number,
|
||||
stop_bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C Read data from slave device.
|
||||
* @param desc - The i2c descriptor.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @param bytes_number - Number of bytes to read.
|
||||
* @param stop_bit - Stop conditional control.
|
||||
* Example: 0 - A stop condition will not be generated.
|
||||
* 1 - A stop condition will be generated.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t i2c_read(struct i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i2c_ops_read)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->i2c_ops_read(desc, data, bytes_number,
|
||||
stop_bit);
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/***************************************************************************//**
|
||||
* @file irq.c
|
||||
* @brief Implementation of the IRQ Interface
|
||||
* @author Andrei Porumb ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include "irq.h"
|
||||
#include "error.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the IRQ interrupts.
|
||||
* @param desc - The IRQ descriptor.
|
||||
* @param param - The structure that contains the IRQ parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t irq_ctrl_init(struct irq_ctrl_desc **desc,
|
||||
const struct irq_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by irq_ctrl_init().
|
||||
* @param desc - The SPI descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a callback to handle the irq events.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param callback - Callback descriptor - platform specific type.
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
int32_t irq_register_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct callback_desc *callback)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->register_callback)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->register_callback(desc, irq_id, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregisters a generic IRQ handling function.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param callback - Callback descriptor - platform specific type.
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
int32_t irq_unregister_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct callback_desc *callback)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->unregister_callback)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->unregister_callback(desc, irq_id, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable global interrupts.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t irq_global_enable(struct irq_ctrl_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->global_enable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->global_enable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable global interrupts.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t irq_global_disable(struct irq_ctrl_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->global_disable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->global_disable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set interrupt trigger level.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param trig - New trigger level for the interrupt.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
enum irq_trig_level trig)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if(!desc->platform_ops->trigger_level_set)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->trigger_level_set(desc, irq_id, trig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable specific interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->enable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->enable(desc, irq_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable specific interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->disable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->disable(desc, irq_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the priority for an interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param priority_level - The priority level of the interrupt.
|
||||
* @return 0 in case of success, negative errno error codes.
|
||||
*/
|
||||
int32_t irq_set_priority(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
uint32_t priority_level)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->set_priority)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->set_priority(desc, irq_id, priority_level);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/***************************************************************************//**
|
||||
* @file spi.c
|
||||
* @brief Implementation of the SPI Interface
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "spi.h"
|
||||
#include <stdlib.h>
|
||||
#include "error.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI communication peripheral.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param param - The structure that contains the SPI parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t spi_init(struct spi_desc **desc,
|
||||
const struct spi_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
(*desc)->parent = param->parent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by spi_init().
|
||||
* @param desc - The SPI descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t spi_remove(struct spi_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write and read data to/from SPI.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @param bytes_number - Number of bytes to write/read.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t spi_write_and_read(struct spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->write_and_read)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->write_and_read(desc, data, bytes_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write and read data to/from SPI in 3 wire mode.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param write_data - The buffer with the transmitted data.
|
||||
* @param read_data - The buffer with the received data.
|
||||
* @param write_bytes_number - Number of bytes to write.
|
||||
* @param read_bytes_number - Number of bytes to read.
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
int32_t spi_write_and_read_3wire(struct spi_desc *desc,
|
||||
uint8_t *write_data,
|
||||
uint8_t *read_data,
|
||||
uint16_t write_bytes_number,
|
||||
uint16_t read_bytes_number)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->write_and_read_3wire)
|
||||
return -ENOSYS;
|
||||
return desc->platform_ops->write_and_read_3wire(desc, write_data, read_data,
|
||||
write_bytes_number, read_bytes_number);
|
||||
}
|
||||
/**
|
||||
* @brief Iterate over head list and send all spi messages
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param msgs - Array of messages.
|
||||
* @param len - Number of messages in the array.
|
||||
* @return 0 in case of success, negativ error code otherwise.
|
||||
*/
|
||||
int32_t spi_transfer(struct spi_desc *desc,
|
||||
struct spi_msg *msgs,
|
||||
uint32_t len)
|
||||
{
|
||||
int32_t ret;
|
||||
uint32_t i;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->platform_ops->transfer)
|
||||
return desc->platform_ops->transfer(desc, msgs, len);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (msgs[i].rx_buff != msgs[i].tx_buff || !msgs[i].tx_buff)
|
||||
return -EINVAL;
|
||||
ret = spi_write_and_read(desc, msgs[i].rx_buff,
|
||||
msgs[i].bytes_number);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/***************************************************************************//**
|
||||
* @file timer.c
|
||||
* @brief Implementation of the timer Interface
|
||||
* @author RBolboac ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include "error.h"
|
||||
#include "timer.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @brief Initialize hardware timer and the handler structure associated with
|
||||
* it.
|
||||
* @param [out] desc - Pointer to the reference of the device handler.
|
||||
* @param [in] param - Initialization structure.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t timer_init(struct timer_desc **desc,
|
||||
struct timer_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the memory allocated by timer_init().
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t timer_remove(struct timer_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start a timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t timer_start(struct timer_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->start)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->start(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop a timer from counting.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t timer_stop(struct timer_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->stop)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->stop(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of the counter register for the timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [out] counter - Pointer to the counter value.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t timer_counter_get(struct timer_desc *desc,
|
||||
uint32_t *counter)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !counter)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->counter_get)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->counter_get(desc, counter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the timer counter register value.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] new_val - The new value of the counter register.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t timer_counter_set(struct timer_desc *desc, uint32_t new_val)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->counter_set)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->counter_set(desc, new_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the timer clock frequency.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [out] freq_hz - The value in Hz of the timer clock.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t timer_count_clk_get(struct timer_desc *desc,
|
||||
uint32_t *freq_hz)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !freq_hz)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->count_clk_get)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->count_clk_get(desc, freq_hz);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the timer clock frequency.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] freq_hz - The value in Hz of the new timer clock.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t timer_count_clk_set(struct timer_desc *desc,
|
||||
uint32_t freq_hz)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->count_clk_set)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->count_clk_set(desc, freq_hz);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the elapsed time in nsec for the timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] elapsed_time - The elapsed time in nsec.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t timer_get_elapsed_time_nsec(struct timer_desc *desc,
|
||||
uint64_t *elapsed_time)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->get_elapsed_time_nsec)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->get_elapsed_time_nsec(desc, elapsed_time);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/***************************************************************************//**
|
||||
* @file trng.c
|
||||
* @brief Implementation of the TRNG Interface
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <inttypes.h>
|
||||
#include "trng.h"
|
||||
#include <stdlib.h>
|
||||
#include "error.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Initialize the TRNG.
|
||||
* @param desc - The TRNG descriptor.
|
||||
* @param param - The structure that contains the TRNG parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int trng_init(struct trng_desc **desc,
|
||||
const struct trng_init_param *param)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by trng_init().
|
||||
* @param desc - The TRNG descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int trng_remove(struct trng_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill buffer with rng data.
|
||||
* @param desc - The TRNG descriptor.
|
||||
* @param buff - Buffer to be filled
|
||||
* @param len - Size of the buffer
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int trng_fill_buffer(struct trng_desc *desc, uint8_t *buff,
|
||||
uint32_t len)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->fill_buffer)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->fill_buffer(desc, buff, len);
|
||||
}
|
||||
+547
@@ -0,0 +1,547 @@
|
||||
/*******************************************************************************
|
||||
* @file axi_dmac.c
|
||||
* @brief Driver for the Analog Devices AXI-DMAC core.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2018(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "axi_io.h"
|
||||
#include "error.h"
|
||||
#include "delay.h"
|
||||
#include "axi_dmac.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief ISR for dev to mem DMA transfer. It computes the next transfer params,
|
||||
* if any, and sets the transfer structure fields accordingly.
|
||||
*
|
||||
* @param instance - the instance that triggered the ISR.
|
||||
*
|
||||
* @return None.
|
||||
*******************************************************************************/
|
||||
void axi_dmac_dev_to_mem_isr(void *instance)
|
||||
{
|
||||
struct axi_dmac *dmac = (struct axi_dmac *)instance;
|
||||
uint32_t burst_size;
|
||||
uint32_t reg_val;
|
||||
|
||||
/* Get interrupt sources and clear interrupts. */
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val);
|
||||
|
||||
if (reg_val & AXI_DMAC_IRQ_SOT) {
|
||||
if (dmac->remaining_size) {
|
||||
/* See if remaining size is bigger than max transfer size and
|
||||
* set burst size. */
|
||||
if (dmac->remaining_size > dmac->max_length) {
|
||||
burst_size = dmac->max_length;
|
||||
} else {
|
||||
burst_size = dmac->remaining_size - 1;
|
||||
}
|
||||
|
||||
/* The current transfer was started; set up the new one. */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0);
|
||||
|
||||
/* Compute size of the next transfer. */
|
||||
dmac->remaining_size = dmac->remaining_size - (burst_size + 1);
|
||||
/* Address must advance with +1 since the DMAC writes X_LENGTH+1. */
|
||||
dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1);
|
||||
|
||||
/* Trigger the next transfer. */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT);
|
||||
}
|
||||
}
|
||||
if (reg_val & AXI_DMAC_IRQ_EOT) {
|
||||
if (!dmac->remaining_size) {
|
||||
dmac->transfer.transfer_done = true;
|
||||
dmac->next_dest_addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief ISR for mem DMA to dev transfer. It computes the next transfer params,
|
||||
* if any, and sets the transfer structure fields accordingly.
|
||||
*
|
||||
* @param instance - the instance that triggered the ISR.
|
||||
*
|
||||
* @return None.
|
||||
*******************************************************************************/
|
||||
void axi_dmac_mem_to_dev_isr(void *instance)
|
||||
{
|
||||
struct axi_dmac *dmac = (struct axi_dmac *)instance;
|
||||
uint32_t burst_size;
|
||||
uint32_t reg_val;
|
||||
|
||||
/* Get interrupt sources and clear interrupts. */
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val);
|
||||
|
||||
if (reg_val & AXI_DMAC_IRQ_SOT) {
|
||||
if ((dmac->transfer.cyclic == CYCLIC) &&
|
||||
(dmac->next_src_addr >= (dmac->init_addr + dmac->transfer.size - 1))) {
|
||||
dmac->remaining_size = dmac->transfer.size;
|
||||
dmac->next_src_addr = dmac->init_addr;
|
||||
}
|
||||
|
||||
if (dmac->remaining_size) {
|
||||
/** See if remaining size is bigger than max transfer size and
|
||||
* set burst size. */
|
||||
if (dmac->remaining_size > dmac->max_length) {
|
||||
burst_size = dmac->max_length;
|
||||
} else {
|
||||
burst_size = dmac->remaining_size - 1;
|
||||
}
|
||||
|
||||
/* The current transfer was started; set up the new one. */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0);
|
||||
|
||||
/* Compute parameters for the next transfer. */
|
||||
dmac->remaining_size = dmac->remaining_size - (burst_size + 1);
|
||||
/* Address must advance with +1 since the DMAC writes X_LENGTH+1. */
|
||||
dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1);
|
||||
|
||||
/* Trigger the current transfer */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT);
|
||||
}
|
||||
}
|
||||
if (reg_val & AXI_DMAC_IRQ_EOT) {
|
||||
if ((!dmac->remaining_size) && (dmac->transfer.cyclic != CYCLIC)) {
|
||||
dmac->transfer.transfer_done = true;
|
||||
dmac->next_src_addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief ISR for mem DMA to mem DMA transfer. It computes the next transfer
|
||||
* params, if any, and sets the transfer structure fields accordingly.
|
||||
*
|
||||
* @param instance - the instance that triggered the ISR.
|
||||
*
|
||||
* @return None.
|
||||
*******************************************************************************/
|
||||
void axi_dmac_mem_to_mem_isr(void *instance)
|
||||
{
|
||||
struct axi_dmac *dmac = (struct axi_dmac *)instance;
|
||||
uint32_t burst_size;
|
||||
uint32_t reg_val;
|
||||
|
||||
/* Get interrupt sources and clear interrupts. */
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val);
|
||||
|
||||
if (reg_val & AXI_DMAC_IRQ_SOT) {
|
||||
if (dmac->remaining_size) {
|
||||
/** See if remaining size is bigger than max transfer size and
|
||||
* set burst size. */
|
||||
if (dmac->remaining_size > dmac->max_length) {
|
||||
burst_size = dmac->max_length;
|
||||
} else {
|
||||
burst_size = dmac->remaining_size - 1;
|
||||
}
|
||||
|
||||
/* The current transfer was started; set up the new one. */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0);
|
||||
|
||||
/* Compute parameters for the next transfer. */
|
||||
dmac->remaining_size = dmac->remaining_size - (burst_size + 1);
|
||||
/* Address must advance with +1 since the DMAC writes X_LENGTH+1. */
|
||||
dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1);
|
||||
dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1);
|
||||
|
||||
/* If transfer finished advance src address so that transfer_done can be set*/
|
||||
if (!dmac->remaining_size) {
|
||||
dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1);
|
||||
}
|
||||
|
||||
/* Trigger the current transfer */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT);
|
||||
}
|
||||
}
|
||||
if (reg_val & AXI_DMAC_IRQ_EOT) {
|
||||
if (!dmac->remaining_size) {
|
||||
if(dmac->next_src_addr > (dmac->init_addr + dmac->transfer.size)) {
|
||||
dmac->transfer.transfer_done = true;
|
||||
dmac->next_src_addr = 0;
|
||||
dmac->next_dest_addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Wrapper for AXI IO through UIO/devmem read function.
|
||||
*
|
||||
* @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address.
|
||||
* @param reg_addr - Address to read from.
|
||||
* @param reg_data - Location where read data will be stored.
|
||||
*
|
||||
* @return 0 - success.
|
||||
*******************************************************************************/
|
||||
int32_t axi_dmac_read(struct axi_dmac *dmac,
|
||||
uint32_t reg_addr,
|
||||
uint32_t *reg_data)
|
||||
{
|
||||
axi_io_read(dmac->base, reg_addr, reg_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Wrapper for AXI IO through UIO/devmem wrrite function.
|
||||
*
|
||||
* @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address.
|
||||
* @param reg_addr - Address to write to.
|
||||
* @param reg_data - Data to be written.
|
||||
*
|
||||
* @return 0 - success.
|
||||
*******************************************************************************/
|
||||
int32_t axi_dmac_write(struct axi_dmac *dmac,
|
||||
uint32_t reg_addr,
|
||||
uint32_t reg_data)
|
||||
{
|
||||
axi_io_write(dmac->base, reg_addr, reg_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Get transfer status (value of dmac->transfer.transfer_done flag).
|
||||
*
|
||||
* @note This function should not be used if DMA IRQ is not used.
|
||||
*
|
||||
* @param dmac - DMAC istance.
|
||||
* @param rdy - Transfer status (0 - not ready, 1 - ready).
|
||||
*
|
||||
* @return 0 - success.
|
||||
*******************************************************************************/
|
||||
int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy)
|
||||
{
|
||||
*rdy = dmac->transfer.transfer_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Get DMAC capabilities.
|
||||
*
|
||||
* @param dmac - DMAC istance.
|
||||
*
|
||||
* @return 0 for success, -1 in case of failure.
|
||||
*******************************************************************************/
|
||||
static int32_t axi_dmac_detect_caps(struct axi_dmac *dmac)
|
||||
{
|
||||
uint32_t reg_val, initial_reg_val = 0;
|
||||
uint32_t src_mem_mapped = 0;
|
||||
uint32_t dest_mem_mapped = 0;
|
||||
|
||||
dmac->max_length = -1;
|
||||
dmac->direction = INVALID_DIR;
|
||||
|
||||
/* Check if HW cyclic possible */
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, &initial_reg_val);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, DMA_CYCLIC);
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val);
|
||||
if (reg_val == DMA_CYCLIC)
|
||||
dmac->hw_cyclic = true;
|
||||
/* Restore initial value for AXI_DMAC_REG_FLAGS register */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, initial_reg_val);
|
||||
|
||||
/* Get maximum burst size and set value. */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, dmac->max_length);
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH, &dmac->max_length);
|
||||
|
||||
/* Get transfer direction and set value. */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, 0xffffffff);
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_DEST_ADDRESS, &dest_mem_mapped);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, 0xffffffff);
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_SRC_ADDRESS, &src_mem_mapped);
|
||||
|
||||
if (dest_mem_mapped && !src_mem_mapped) {
|
||||
dmac->direction = DMA_DEV_TO_MEM;
|
||||
} else if (!dest_mem_mapped && src_mem_mapped) {
|
||||
dmac->direction = DMA_MEM_TO_DEV;
|
||||
} else if (dest_mem_mapped && src_mem_mapped) {
|
||||
dmac->direction = DMA_MEM_TO_MEM;
|
||||
} else {
|
||||
printf("Destination and source memory-mapped interfaces not supported.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Get transfer status (value of dmac->transfer.transfer_done flag).
|
||||
*
|
||||
* @param dmac_core - DMAC istance.
|
||||
* @param init - Structure containing initializing data.
|
||||
*
|
||||
* @return 0 for success, -1 in case of failure.
|
||||
*******************************************************************************/
|
||||
int32_t axi_dmac_init(struct axi_dmac **dmac_core,
|
||||
const struct axi_dmac_init *init)
|
||||
{
|
||||
struct axi_dmac *dmac;
|
||||
|
||||
dmac = (struct axi_dmac *)calloc(1, sizeof(*dmac));
|
||||
if (!dmac)
|
||||
return -1;
|
||||
|
||||
dmac->name = init->name;
|
||||
dmac->base = init->base;
|
||||
dmac->irq_option = init->irq_option;
|
||||
|
||||
*dmac_core = dmac;
|
||||
|
||||
int32_t status = axi_dmac_detect_caps(*dmac_core);
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Remove the DMAC instance.
|
||||
*
|
||||
* @param dmac - DMAC istance.
|
||||
*
|
||||
* @return 0 for success, -1 in case of failure.
|
||||
*******************************************************************************/
|
||||
int32_t axi_dmac_remove(struct axi_dmac *dmac)
|
||||
{
|
||||
if (!dmac)
|
||||
return -1;
|
||||
|
||||
free(dmac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Start a DMA transfer.
|
||||
*
|
||||
* @param dmac - DMAC istance.
|
||||
* @param dma_transfer - Structure containing transfer details.
|
||||
*
|
||||
* @return 0 for success, -1 in case of failure.
|
||||
*******************************************************************************/
|
||||
int32_t axi_dmac_transfer_start(struct axi_dmac *dmac,
|
||||
struct axi_dma_transfer *dma_transfer)
|
||||
{
|
||||
uint32_t reg_val, burst_size;
|
||||
|
||||
if (dma_transfer->size == 0)
|
||||
return 0; /* Nothing to do. */
|
||||
|
||||
/* Set current transfer parameters. */
|
||||
dmac->transfer.size = dma_transfer->size;
|
||||
dmac->transfer.cyclic = dma_transfer->cyclic;
|
||||
dmac->transfer.dest_addr = dma_transfer->dest_addr;
|
||||
dmac->transfer.src_addr = dma_transfer->src_addr;
|
||||
|
||||
dmac->remaining_size = dma_transfer->size;
|
||||
dmac->next_dest_addr = dma_transfer->dest_addr;
|
||||
dmac->next_src_addr = dma_transfer->src_addr;
|
||||
|
||||
/* If HW cyclic transfer selected and not available, show error */
|
||||
/* HW cyclic transfer available only for MEM to DEV transfers. */
|
||||
if ((!dmac->hw_cyclic) && (dma_transfer->cyclic == CYCLIC)) {
|
||||
printf("Transfer mode not supported!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Cyclic transfers not possible for DEV_TO_MEM and MEM_TO_MEM transmissions. */
|
||||
if ((dmac->direction == DMA_DEV_TO_MEM)
|
||||
|| (dmac->direction == DMA_MEM_TO_MEM)) {
|
||||
if (dma_transfer->cyclic == CYCLIC) {
|
||||
printf("Transfer mode not supported!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cyclic transfers set to HW or SW depending on size for MEM to DEV. */
|
||||
if ((dmac->direction == DMA_MEM_TO_DEV) && (dmac->transfer.cyclic == CYCLIC)) {
|
||||
if ((dmac->remaining_size - 1) <= dmac->max_length) {
|
||||
if (dmac->hw_cyclic) {
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val);
|
||||
reg_val = reg_val | DMA_CYCLIC;
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val);
|
||||
}
|
||||
} else {
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val);
|
||||
reg_val = reg_val & ~DMA_CYCLIC;
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable DMA if not already enabled. */
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_CTRL, ®_val);
|
||||
if (!(reg_val & AXI_DMAC_CTRL_ENABLE)) {
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0x0);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x0);
|
||||
}
|
||||
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, ®_val);
|
||||
/* If we don't have a start of transfer then start compute
|
||||
* values and trigger next transfer. */
|
||||
if (!(reg_val & AXI_DMAC_QUEUE_FULL)) {
|
||||
switch (dmac->direction) {
|
||||
case DMA_DEV_TO_MEM:
|
||||
dmac->init_addr = dmac->next_dest_addr;
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0);
|
||||
break;
|
||||
case DMA_MEM_TO_DEV:
|
||||
dmac->init_addr = dmac->next_src_addr;
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0);
|
||||
break;
|
||||
case DMA_MEM_TO_MEM:
|
||||
dmac->init_addr = dmac->next_src_addr;
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0);
|
||||
break;
|
||||
default:
|
||||
return -1; /* Other directions are not supported yet. */
|
||||
}
|
||||
|
||||
/* Compute the burst size. */
|
||||
if (dmac->remaining_size > dmac->max_length) {
|
||||
burst_size = dmac->max_length;
|
||||
} else {
|
||||
burst_size = dmac->remaining_size - 1;
|
||||
}
|
||||
|
||||
/* Compute next address (src or dest, or both, depending on type of transfer). */
|
||||
switch (dmac->direction) {
|
||||
case DMA_DEV_TO_MEM:
|
||||
dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1);
|
||||
break;
|
||||
case DMA_MEM_TO_DEV:
|
||||
dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1);
|
||||
break;
|
||||
case DMA_MEM_TO_MEM:
|
||||
dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1);
|
||||
dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compute remaining size. */
|
||||
dmac->remaining_size = dmac->remaining_size - (burst_size + 1);
|
||||
|
||||
/* Specify the length of the transfer and trigger transfer. */
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0);
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Wait for DMA transfer to be completed.
|
||||
*
|
||||
* @param dmac - DMAC istance.
|
||||
* @param timeout_ms - Number of ms to wait for completion of transfer.
|
||||
*
|
||||
* @return 0 for success, -1 in case trasnfer not completed in specified time.
|
||||
*******************************************************************************/
|
||||
int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac,
|
||||
uint32_t timeout_ms)
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
uint32_t reg_val = 0;
|
||||
|
||||
if (dmac->irq_option == IRQ_ENABLED) {
|
||||
while (!dmac->transfer.transfer_done) {
|
||||
timeout++;
|
||||
mdelay(1);
|
||||
if (timeout == timeout_ms) {
|
||||
printf("Error transferring data using DMA.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else if (dmac->irq_option == IRQ_DISABLED) {
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val);
|
||||
while (reg_val != (AXI_DMAC_IRQ_SOT | AXI_DMAC_IRQ_EOT)) {
|
||||
timeout++;
|
||||
mdelay(1);
|
||||
if (timeout == timeout_ms) {
|
||||
printf("Error transferring data using DMA.\n");
|
||||
return -1;
|
||||
}
|
||||
axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @brief Stop a DMA transfer.
|
||||
*
|
||||
* @param dmac - DMAC istance.
|
||||
*
|
||||
* @return None
|
||||
*******************************************************************************/
|
||||
void axi_dmac_transfer_stop(struct axi_dmac *dmac)
|
||||
{
|
||||
axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_DISABLE);
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/***************************************************************************//**
|
||||
* @file axi_dmac.h
|
||||
* @brief Driver for the Analog Devices AXI-DMAC core.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2018(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef AXI_DMAC_H_
|
||||
#define AXI_DMAC_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "util.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
#define AXI_DMAC_REG_IRQ_MASK 0x80
|
||||
#define AXI_DMAC_REG_IRQ_PENDING 0x84
|
||||
#define AXI_DMAC_IRQ_SOT BIT(0)
|
||||
#define AXI_DMAC_IRQ_EOT BIT(1)
|
||||
|
||||
#define AXI_DMAC_REG_INTF_DESC 0x010
|
||||
#define AXI_DMAC_DMA_TYPE_DEST GENMASK(5,4)
|
||||
#define AXI_DMAC_DMA_TYPE_SRC GENMASK(13,12)
|
||||
//Define macro for src and dest
|
||||
|
||||
#define AXI_DMAC_REG_CTRL 0x400
|
||||
#define AXI_DMAC_CTRL_ENABLE BIT(0)
|
||||
#define AXI_DMAC_CTRL_DISABLE 0u
|
||||
#define AXI_DMAC_CTRL_PAUSE BIT(1)
|
||||
|
||||
#define AXI_DMAC_REG_TRANSFER_ID 0x404
|
||||
#define AXI_DMAC_REG_TRANSFER_SUBMIT 0x408
|
||||
#define AXI_DMAC_TRANSFER_SUBMIT BIT(0)
|
||||
#define AXI_DMAC_QUEUE_FULL BIT(0)
|
||||
#define AXI_DMAC_REG_FLAGS 0x40c
|
||||
#define AXI_DMAC_REG_DEST_ADDRESS 0x410
|
||||
#define AXI_DMAC_REG_SRC_ADDRESS 0x414
|
||||
#define AXI_DMAC_REG_X_LENGTH 0x418
|
||||
#define AXI_DMAC_REG_Y_LENGTH 0x41c
|
||||
#define AXI_DMAC_REG_DEST_STRIDE 0x420
|
||||
#define AXI_DMAC_REG_SRC_STRIDE 0x424
|
||||
#define AXI_DMAC_REG_TRANSFER_DONE 0x428
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
enum use_irq {
|
||||
IRQ_DISABLED = 0,
|
||||
IRQ_ENABLED = 1
|
||||
};
|
||||
|
||||
enum dma_direction {
|
||||
INVALID_DIR = 0,
|
||||
DMA_DEV_TO_MEM = 1,
|
||||
DMA_MEM_TO_DEV = 2,
|
||||
DMA_MEM_TO_MEM = 3
|
||||
};
|
||||
|
||||
enum dma_flags {
|
||||
DMA_CYCLIC = 1,
|
||||
DMA_LAST = 2,
|
||||
DMA_PARTIAL_REPORTING_EN = 4
|
||||
};
|
||||
|
||||
// Could be transformed to a bool
|
||||
enum cyclic_transfer {
|
||||
NO = 0,
|
||||
CYCLIC = 1
|
||||
};
|
||||
|
||||
struct axi_dma_transfer {
|
||||
uint32_t size;
|
||||
volatile bool transfer_done;
|
||||
enum cyclic_transfer cyclic;
|
||||
uint32_t src_addr;
|
||||
uint32_t dest_addr;
|
||||
};
|
||||
|
||||
struct axi_dmac {
|
||||
const char *name;
|
||||
uint32_t base;
|
||||
enum use_irq irq_option;
|
||||
enum dma_direction direction;
|
||||
bool hw_cyclic;
|
||||
uint32_t max_length;
|
||||
volatile struct axi_dma_transfer transfer;
|
||||
//Current sub-transfer properties
|
||||
uint32_t init_addr;
|
||||
uint32_t remaining_size;
|
||||
uint32_t next_src_addr;
|
||||
uint32_t next_dest_addr;
|
||||
};
|
||||
|
||||
struct axi_dmac_init {
|
||||
const char *name;
|
||||
uint32_t base;
|
||||
enum use_irq irq_option;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
void axi_dmac_dev_to_mem_isr(void *instance);
|
||||
void axi_dmac_mem_to_dev_isr(void *instance);
|
||||
void axi_dmac_mem_to_mem_isr(void *instance);
|
||||
void axi_dmac_write_isr(void *instance);
|
||||
int32_t axi_dmac_read(struct axi_dmac *dmac, uint32_t reg_addr,
|
||||
uint32_t *reg_data);
|
||||
int32_t axi_dmac_write(struct axi_dmac *dmac, uint32_t reg_addr,
|
||||
uint32_t reg_data);
|
||||
int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy);
|
||||
int32_t axi_dmac_init(struct axi_dmac **adc_core,
|
||||
const struct axi_dmac_init *init);
|
||||
int32_t axi_dmac_remove(struct axi_dmac *dmac);
|
||||
int32_t axi_dmac_transfer_start(struct axi_dmac *dmac,
|
||||
struct axi_dma_transfer *dma_transfer);
|
||||
int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac,
|
||||
uint32_t timeout_ms);
|
||||
void axi_dmac_transfer_stop(struct axi_dmac *dmac);
|
||||
|
||||
#endif
|
||||
+996
@@ -0,0 +1,996 @@
|
||||
/*******************************************************************************
|
||||
* @file spi_engine.c
|
||||
* @brief Core implementation of the SPI Engine Driver.
|
||||
* @author Sergiu Cuciurean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* In debug mode the printf function used in displaying the messages is causing
|
||||
significant delays */
|
||||
//#define DEBUG_LEVEL 2
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sleep.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "axi_io.h"
|
||||
#include "error.h"
|
||||
#include "spi_engine.h"
|
||||
|
||||
/**
|
||||
* @brief Spi engine platform specific SPI platform ops structure
|
||||
*/
|
||||
const struct spi_platform_ops spi_eng_platform_ops = {
|
||||
.init = &spi_engine_init,
|
||||
.write_and_read = &spi_engine_write_and_read,
|
||||
.write_and_read_3wire = &spi_engine_write_and_read_3wire,
|
||||
.remove = &spi_engine_remove
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Static variables *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Static variable used to sync transfers
|
||||
*
|
||||
*/
|
||||
static uint8_t _sync_id = 0x01;
|
||||
|
||||
/******************************************************************************/
|
||||
/************************** Functions Implementation **************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Write SPI Engine's axi registers
|
||||
*
|
||||
* @param desc Decriptor containing SPI Engine's parameters
|
||||
* @param reg_addr The address of the SPI Engine's axi register where the data
|
||||
* will be written
|
||||
* @param reg_data Data that will be written
|
||||
* @return int32_t This function allways returns SUCCESS
|
||||
*/
|
||||
int32_t spi_engine_write(struct spi_engine_desc *desc,
|
||||
uint32_t reg_addr,
|
||||
uint32_t reg_data)
|
||||
{
|
||||
axi_io_write(desc->spi_engine_baseaddr, reg_addr, reg_data);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read SPI Engine's axi registers
|
||||
*
|
||||
* @param desc Decriptor containing SPI Engine's parameters
|
||||
* @param reg_addr The address of the SPI Engine's axi register from where the
|
||||
* data where the data will be read
|
||||
* @param reg_data Pointer where the read that will be stored
|
||||
* @return int32_t This function allways returns SUCCESS
|
||||
*/
|
||||
int32_t spi_engine_read(struct spi_engine_desc *desc,
|
||||
uint32_t reg_addr,
|
||||
uint32_t *reg_data)
|
||||
{
|
||||
axi_io_read(desc->spi_engine_baseaddr, reg_addr, reg_data);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set width of the transferred word over SPI
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param data_width The desired data width
|
||||
* The supported values are:
|
||||
* - 8
|
||||
* - 16
|
||||
* - 24
|
||||
* - 32
|
||||
*/
|
||||
int32_t spi_engine_set_transfer_width(struct spi_desc *desc,
|
||||
uint8_t data_width)
|
||||
{
|
||||
struct spi_engine_desc *desc_extra;
|
||||
|
||||
desc_extra = desc->extra;
|
||||
|
||||
if (data_width > desc_extra->max_data_width)
|
||||
desc_extra->data_width = desc_extra->max_data_width;
|
||||
else
|
||||
desc_extra->data_width = data_width;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set SPI engine clock frequency
|
||||
*
|
||||
* @param desc Decriptor containing SPI Engine's parameters
|
||||
* @param speed_hz SPI engine transfer speed
|
||||
*/
|
||||
void spi_engine_set_speed(struct spi_desc *desc,
|
||||
uint32_t speed_hz)
|
||||
{
|
||||
struct spi_engine_desc *desc_extra;
|
||||
|
||||
desc_extra = desc->extra;
|
||||
|
||||
desc_extra->clk_div = desc_extra->ref_clk_hz /
|
||||
(2 * speed_hz) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the number of words transferred in a single transaction
|
||||
*
|
||||
* @param desc Decriptor containing SPI Engine's parameters
|
||||
* @param bytes_number The number of bytes to be converted
|
||||
* @return uint8_t A number of words in which bytes_number can be grouped
|
||||
*/
|
||||
static uint8_t spi_get_words_number(struct spi_engine_desc *desc,
|
||||
uint8_t bytes_number)
|
||||
{
|
||||
uint8_t xfer_word_len;
|
||||
uint8_t words_number;
|
||||
|
||||
xfer_word_len = desc->data_width / 8;
|
||||
words_number = bytes_number / xfer_word_len;
|
||||
|
||||
if ((bytes_number % xfer_word_len) != 0)
|
||||
words_number++;
|
||||
|
||||
return words_number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the word length in bytes
|
||||
*
|
||||
* @param desc Decriptor containing SPI Engine's parameters
|
||||
* @return uint8_t Number of bytes that fit in one word
|
||||
*/
|
||||
static uint8_t spi_get_word_length(struct spi_engine_desc *desc)
|
||||
{
|
||||
uint8_t word_length;
|
||||
|
||||
word_length = desc->data_width / 8;
|
||||
|
||||
return word_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute the prescaler used to set the sleep period.
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param sleep_time_ns The amount of time where the transfer hangs
|
||||
* @param sleep_div Clock prescaler
|
||||
* @return int32_t This function allways returns SUCCESS
|
||||
*/
|
||||
static int32_t spi_get_sleep_div(struct spi_desc *desc,
|
||||
uint32_t sleep_time_ns,
|
||||
uint32_t *sleep_div)
|
||||
{
|
||||
struct spi_engine_desc *eng_desc;
|
||||
|
||||
eng_desc = desc->extra;
|
||||
|
||||
/*
|
||||
* Engine Wiki:
|
||||
*
|
||||
* The frequency of the SCLK signal is derived from the
|
||||
* module clock frequency using the following formula:
|
||||
* f_sclk = f_clk / ((div + 1) * 2)
|
||||
*/
|
||||
|
||||
*sleep_div = (desc->max_speed_hz / 1000000 * sleep_time_ns / 1000) /
|
||||
((eng_desc->clk_div + 1) * 2) - 1;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new commands queue used in a spi transfer
|
||||
*
|
||||
* @param fifo Command buffer, usually used in fifo mode
|
||||
* @param cmd Command with which the buffer will be initiated
|
||||
* @return int32_t Failure if the memory allocation failed
|
||||
*/
|
||||
static int32_t spi_engine_queue_new_cmd(struct spi_engine_cmd_queue **fifo,
|
||||
uint32_t cmd)
|
||||
{
|
||||
struct spi_engine_cmd_queue *local_fifo;
|
||||
|
||||
local_fifo = (spi_engine_cmd_queue*)malloc(sizeof(*local_fifo));
|
||||
|
||||
if(!local_fifo)
|
||||
return FAILURE;
|
||||
|
||||
local_fifo->cmd = cmd;
|
||||
local_fifo->next = NULL;
|
||||
*fifo = local_fifo;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a command at the end of an existing queue
|
||||
*
|
||||
* @param fifo Command buffer, usually used in fifo mode
|
||||
* @param cmd Command to be added
|
||||
*/
|
||||
static void spi_engine_queue_add_cmd(struct spi_engine_cmd_queue **fifo,
|
||||
uint32_t cmd)
|
||||
{
|
||||
struct spi_engine_cmd_queue *to_add = NULL;
|
||||
struct spi_engine_cmd_queue *local_fifo;
|
||||
|
||||
local_fifo = *fifo;
|
||||
while (local_fifo->next != NULL) {
|
||||
// Get the last element
|
||||
local_fifo = local_fifo->next;
|
||||
}
|
||||
|
||||
// Create a new element
|
||||
spi_engine_queue_new_cmd(&to_add, cmd);
|
||||
// Add as the next element
|
||||
local_fifo->next = to_add;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a command at the beginning of an existing queue
|
||||
*
|
||||
* @param fifo Command buffer, usually used in fifo mode
|
||||
* @param cmd Command to be added
|
||||
*/
|
||||
static void spi_engine_queue_append_cmd(struct spi_engine_cmd_queue **fifo,
|
||||
uint32_t cmd)
|
||||
{
|
||||
struct spi_engine_cmd_queue *to_add = NULL;
|
||||
|
||||
// Create a new element
|
||||
spi_engine_queue_new_cmd(&to_add, cmd);
|
||||
// Interchange the addresses
|
||||
to_add->next = *fifo;
|
||||
*fifo = to_add;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the command from the beginning of the queue
|
||||
*
|
||||
* @param fifo Command buffer, usually used in fifo mode
|
||||
* @param cmd Value of the command that was extracted
|
||||
* @return int32_t Return FAILURE if the queue is empty
|
||||
*/
|
||||
static int32_t spi_engine_queue_get_cmd(struct spi_engine_cmd_queue **fifo,
|
||||
uint32_t *cmd)
|
||||
{
|
||||
struct spi_engine_cmd_queue *local_fifo;
|
||||
|
||||
if (!*fifo)
|
||||
return FAILURE;
|
||||
|
||||
local_fifo = *fifo;
|
||||
*cmd = local_fifo->cmd;
|
||||
if ((*fifo)->next) {
|
||||
*fifo = local_fifo->next;
|
||||
free(local_fifo);
|
||||
} else {
|
||||
free(*fifo);
|
||||
*fifo = NULL;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the memory allocated by a queue
|
||||
*
|
||||
* @param fifo The queue that needs it's memory freed
|
||||
* @return int32_t This function always returns SUCCESS
|
||||
*/
|
||||
static int32_t spi_engine_queue_free(struct spi_engine_cmd_queue **fifo)
|
||||
{
|
||||
if(*fifo && (*fifo)->next)
|
||||
spi_engine_queue_free(&(*fifo)->next);
|
||||
if((*fifo) != NULL) {
|
||||
free(*fifo);
|
||||
*fifo = NULL;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the SPI engine's command fifo
|
||||
*
|
||||
* @param desc Decriptor containing SPI Engine's parameters
|
||||
* @param cmd The command that will be written
|
||||
* @return int32_t Returns FAILURE if the the axi transfer failed
|
||||
*/
|
||||
static int32_t spi_engine_write_cmd_reg(struct spi_engine_desc *desc,
|
||||
uint32_t cmd)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
/* Check if offload is enabled */
|
||||
if(desc->offload_config & (OFFLOAD_TX_EN | OFFLOAD_RX_EN)) {
|
||||
ret = spi_engine_write(desc,
|
||||
SPI_ENGINE_REG_OFFLOAD_CMD_MEM(0),
|
||||
cmd);
|
||||
|
||||
} else {
|
||||
ret = spi_engine_write(desc,
|
||||
SPI_ENGINE_REG_CMD_FIFO,
|
||||
cmd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a transfer command to the SPI engine's command fifo
|
||||
*
|
||||
* @param desc Decriptor containing SPI Engine's parameters
|
||||
* @param read_write Read/Write operation flag
|
||||
* @param bytes_number Number of bytes to transfer
|
||||
* @return int32_t This function always returns SUCCESS
|
||||
*/
|
||||
static int32_t spi_engine_transfer(struct spi_engine_desc *desc,
|
||||
uint8_t read_write,
|
||||
uint8_t bytes_number)
|
||||
{
|
||||
uint8_t words_number;
|
||||
|
||||
words_number = spi_get_words_number(desc, bytes_number);
|
||||
|
||||
desc->offload_tx_len += words_number;
|
||||
|
||||
/*
|
||||
* Engine Wiki:
|
||||
*
|
||||
* https://wiki.analog.com/resources/fpga/peripherals/spi_engine
|
||||
*
|
||||
* The words number is zero based
|
||||
*/
|
||||
|
||||
spi_engine_write_cmd_reg(desc,
|
||||
SPI_ENGINE_CMD_TRANSFER(read_write,
|
||||
words_number - 1));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Change the state of the chip select port
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param assert Chip select state.
|
||||
* The supported values are :
|
||||
* -true (HIGH)
|
||||
* -false (LOW)
|
||||
*/
|
||||
static void spi_engine_set_cs(struct spi_desc *desc,
|
||||
bool assert)
|
||||
{
|
||||
uint8_t mask;
|
||||
struct spi_engine_desc *eng_desc;
|
||||
|
||||
eng_desc = desc->extra;
|
||||
|
||||
mask = 0xFF;
|
||||
/* Switch the state only of the selected chip select */
|
||||
if (!assert)
|
||||
mask ^= BIT(desc->chip_select);
|
||||
|
||||
spi_engine_write_cmd_reg(eng_desc,
|
||||
SPI_ENGINE_CMD_ASSERT(eng_desc->cs_delay,
|
||||
mask));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a delay between the engine commands
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param sleep_time_ns Number of nanoseconds to sleep between commands
|
||||
*/
|
||||
static void spi_gen_sleep_ns(struct spi_desc *desc,
|
||||
uint32_t sleep_time_ns)
|
||||
{
|
||||
uint32_t sleep_div;
|
||||
struct spi_engine_desc *eng_desc;
|
||||
|
||||
eng_desc = desc->extra;
|
||||
|
||||
spi_get_sleep_div(desc, sleep_time_ns, &sleep_div);
|
||||
|
||||
spi_engine_write_cmd_reg(eng_desc, SPI_ENGINE_CMD_SLEEP(sleep_div));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Spi engine command interpreter
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param cmd Command to send to the engine
|
||||
* @return int32_t - SUCCESS if the command is transferred
|
||||
* - FAILURE if the command format is invalid
|
||||
*/
|
||||
static int32_t spi_engine_write_cmd(struct spi_desc *desc,
|
||||
uint32_t cmd)
|
||||
{
|
||||
uint8_t engine_command;
|
||||
uint8_t parameter;
|
||||
uint8_t modifier;
|
||||
struct spi_engine_desc *desc_extra;
|
||||
|
||||
desc_extra = desc->extra;
|
||||
|
||||
engine_command = (cmd >> 12) & 0x0F;
|
||||
modifier = (cmd >> 8) & 0x0F;
|
||||
parameter = cmd & 0xFF;
|
||||
|
||||
switch(engine_command) {
|
||||
case SPI_ENGINE_INST_TRANSFER:
|
||||
spi_engine_transfer(desc_extra, modifier, parameter);
|
||||
break;
|
||||
|
||||
case SPI_ENGINE_INST_ASSERT:
|
||||
if(parameter == 0xFF) {
|
||||
/* Set the CS HIGH */
|
||||
spi_engine_set_cs(desc, true);
|
||||
} else if(parameter == 0x00) {
|
||||
/* Set the CS LOW */
|
||||
spi_engine_set_cs(desc, false);
|
||||
}
|
||||
break;
|
||||
|
||||
/* The SYNC and SLEEP commands got the same value but different
|
||||
modifier */
|
||||
case SPI_ENGINE_INST_SYNC_SLEEP:
|
||||
/* SYNC instruction */
|
||||
if(modifier == 0x00) {
|
||||
spi_engine_write_cmd_reg(desc_extra, cmd);
|
||||
} else if(modifier == 0x01) {
|
||||
spi_gen_sleep_ns(desc, parameter);
|
||||
}
|
||||
break;
|
||||
case SPI_ENGINE_INST_CONFIG:
|
||||
spi_engine_write_cmd_reg(desc_extra, cmd);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare the command queue before sending it to the engine
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param msg Structure used to store the transfer messages
|
||||
* @return int32_t This function always returns SUCCESS
|
||||
*/
|
||||
static int32_t spi_engine_compile_message(struct spi_desc *desc,
|
||||
struct spi_engine_msg *msg)
|
||||
{
|
||||
struct spi_engine_desc *desc_extra;
|
||||
|
||||
desc_extra = desc->extra;
|
||||
|
||||
/* Configure the prescaler */
|
||||
spi_engine_queue_append_cmd(&msg->cmds,
|
||||
SPI_ENGINE_CMD_CONFIG(
|
||||
SPI_ENGINE_CMD_REG_CLK_DIV,
|
||||
desc_extra->clk_div));
|
||||
|
||||
/* Set the data transfer length */
|
||||
spi_engine_queue_append_cmd(&msg->cmds,
|
||||
SPI_ENGINE_CMD_CONFIG(
|
||||
SPI_ENGINE_CMD_DATA_TRANSFER_LEN,
|
||||
desc_extra->data_width));
|
||||
/*
|
||||
* Configure the spi mode :
|
||||
* - 3 wire
|
||||
* - CPOL
|
||||
* - CPHA
|
||||
*/
|
||||
spi_engine_queue_append_cmd(&msg->cmds,
|
||||
SPI_ENGINE_CMD_CONFIG(
|
||||
SPI_ENGINE_CMD_REG_CONFIG,
|
||||
desc->mode));
|
||||
|
||||
/* Add a sync command to signal that the transfer has finished */
|
||||
spi_engine_queue_add_cmd(&msg->cmds, SPI_ENGINE_CMD_SYNC(_sync_id));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initiate a spi transfer (Blocking)
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param msg Structure used to store the transfer messages
|
||||
* @return int32_t - SUCCESS if the transfer finished
|
||||
* - FAILURE if the memory allocation failed
|
||||
*/
|
||||
static int32_t spi_engine_transfer_message(struct spi_desc *desc,
|
||||
struct spi_engine_msg *msg)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t data;
|
||||
uint32_t sync_id;
|
||||
bool offload_en;
|
||||
struct spi_engine_desc *desc_extra;
|
||||
|
||||
desc_extra = desc->extra;
|
||||
|
||||
spi_engine_compile_message(desc, msg);
|
||||
|
||||
offload_en = (desc_extra->offload_config & OFFLOAD_TX_EN) |
|
||||
(desc_extra->offload_config & OFFLOAD_RX_EN);
|
||||
|
||||
/* Write the command fifo buffer */
|
||||
while(msg->cmds != NULL) {
|
||||
spi_engine_queue_get_cmd(&msg->cmds, &data);
|
||||
spi_engine_write_cmd(desc, data);
|
||||
}
|
||||
|
||||
/* Write a number of tx_length WORDS on the SDO line */
|
||||
if(offload_en) {
|
||||
for(i = 0; i < desc_extra->offload_tx_len; i++)
|
||||
spi_engine_write(desc_extra,
|
||||
SPI_ENGINE_REG_OFFLOAD_SDO_MEM(0),
|
||||
msg->tx_buf[i]);
|
||||
|
||||
} else {
|
||||
if(msg->tx_buf != NULL){
|
||||
for(i = 0; i < msg->tx_length; i++)
|
||||
spi_engine_write(desc_extra,
|
||||
SPI_ENGINE_REG_SDO_DATA_FIFO,
|
||||
msg->tx_buf[i]);
|
||||
}
|
||||
do {
|
||||
spi_engine_read(desc_extra,
|
||||
SPI_ENGINE_REG_SYNC_ID,
|
||||
&sync_id);
|
||||
}
|
||||
/* Wait for the end sync signal */
|
||||
while(sync_id != _sync_id);
|
||||
_sync_id++;
|
||||
|
||||
/* Read a number of rx_length WORDS from the SDI line and store
|
||||
them */
|
||||
for(i = 0; i < msg->rx_length; i++) {
|
||||
spi_engine_read(desc_extra,
|
||||
SPI_ENGINE_REG_SDI_DATA_FIFO,
|
||||
&data);
|
||||
/* Store the rx data if rx buffer valid, flush sdi_fifo if
|
||||
rx buffer is invalid.*/
|
||||
if(msg->rx_buf != NULL){
|
||||
msg->rx_buf[i] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the spi engine
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param param Structure containing the spi init parameters
|
||||
* @return int32_t - SUCCESS if the transfer finished
|
||||
* - FAILURE if the memory allocation failed
|
||||
*/
|
||||
int32_t spi_engine_init(struct spi_desc **desc,
|
||||
const struct spi_init_param *param)
|
||||
{
|
||||
uint32_t data_width;
|
||||
uint32_t spi_engine_version;
|
||||
struct spi_engine_desc *eng_desc;
|
||||
struct spi_engine_init_param *spi_engine_init;
|
||||
|
||||
if (!param) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
*desc = malloc(sizeof(**desc));
|
||||
if(! *desc) {
|
||||
free(*desc);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
eng_desc = (struct spi_engine_desc*)malloc(sizeof(*eng_desc));
|
||||
|
||||
if (!eng_desc)
|
||||
return FAILURE;
|
||||
|
||||
spi_engine_init = param->extra;
|
||||
|
||||
(*desc)->max_speed_hz = param->max_speed_hz;
|
||||
(*desc)->chip_select = param->chip_select;
|
||||
(*desc)->mode = param->mode;
|
||||
(*desc)->extra = eng_desc;
|
||||
|
||||
eng_desc->offload_config = OFFLOAD_DISABLED;
|
||||
eng_desc->spi_engine_baseaddr = spi_engine_init->spi_engine_baseaddr;
|
||||
eng_desc->type = spi_engine_init->type;
|
||||
eng_desc->cs_delay = spi_engine_init->cs_delay;
|
||||
eng_desc->ref_clk_hz = spi_engine_init->ref_clk_hz;
|
||||
eng_desc->clk_div = eng_desc->ref_clk_hz /
|
||||
(2 * param->max_speed_hz) - 1;
|
||||
|
||||
/* Perform a reset */
|
||||
spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x01);
|
||||
usleep(1000);
|
||||
spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x00);
|
||||
|
||||
/* Get current data width */
|
||||
spi_engine_read(eng_desc, SPI_ENGINE_REG_DATA_WIDTH, &data_width);
|
||||
eng_desc->max_data_width = data_width;
|
||||
|
||||
spi_engine_set_transfer_width(*desc, spi_engine_init->data_width);
|
||||
|
||||
/* Get spi engine version */
|
||||
spi_engine_read(eng_desc, SPI_ENGINE_REG_VERSION, &spi_engine_version);
|
||||
|
||||
printf("Spi engine v%"PRIu32".%"PRIu32".%"PRIu32" successfully initialized.\n",
|
||||
(spi_engine_version >> 16),
|
||||
((spi_engine_version >> 8) & 0xFF),
|
||||
(spi_engine_version & 0xFF));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write/read on the spi interface in 4-wire mode (full-duplex)
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param data Pointer to data buffer
|
||||
* @param bytes_number Number of bytes to transfer
|
||||
* @return int32_t - SUCCESS if the transfer finished
|
||||
* - FAILURE if the memory allocation or transfer failed
|
||||
*/
|
||||
int32_t spi_engine_write_and_read(struct spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number)
|
||||
{
|
||||
uint8_t word_len;
|
||||
uint8_t words_number;
|
||||
int32_t ret;
|
||||
struct spi_engine_msg msg;
|
||||
struct spi_engine_desc *desc_extra;
|
||||
|
||||
desc_extra = desc->extra;
|
||||
|
||||
/* If we want to access SPI interface and SPI engine offload module was
|
||||
* activated, we need to disable it
|
||||
* This is set in spi_engine_offload_init() */
|
||||
desc_extra->offload_config = OFFLOAD_DISABLED;
|
||||
/* This is set in spi_engine_offload_transfer() */
|
||||
spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0);
|
||||
|
||||
words_number = spi_get_words_number(desc_extra, bytes_number);
|
||||
|
||||
msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds));
|
||||
if (!msg.cmds)
|
||||
return FAILURE;
|
||||
|
||||
msg.tx_buf =(uint32_t*)calloc(words_number, sizeof(msg.tx_buf[0]));
|
||||
msg.rx_buf =(uint32_t*)calloc(words_number, sizeof(msg.rx_buf[0]));
|
||||
msg.tx_length = words_number;
|
||||
msg.rx_length = words_number;
|
||||
|
||||
/* Get the length of transferred word */
|
||||
word_len = spi_get_word_length(desc_extra);
|
||||
|
||||
/* Make sure the CS is HIGH before starting a transaction */
|
||||
msg.cmds->next = NULL;
|
||||
msg.cmds->cmd = CS_HIGH;
|
||||
// Assert select.
|
||||
spi_engine_queue_add_cmd(&msg.cmds, CS_LOW);
|
||||
// add read/write command
|
||||
spi_engine_queue_add_cmd(&msg.cmds, WRITE_READ(bytes_number));
|
||||
// Disable select.
|
||||
spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH);
|
||||
|
||||
/* Pack the bytes into engine WORDS */
|
||||
for (int i = 0; i < bytes_number; i++)
|
||||
msg.tx_buf[i / word_len] |= data[i] << (desc_extra->data_width-
|
||||
(i % word_len + 1) * 8);
|
||||
|
||||
ret = spi_engine_transfer_message(desc, &msg);
|
||||
|
||||
for (int i = 0; i < bytes_number; i++)
|
||||
data[i] = msg.rx_buf[(i) / word_len] >>
|
||||
(desc_extra->data_width -
|
||||
((i) % word_len + 1) * 8);
|
||||
|
||||
spi_engine_queue_free(&msg.cmds);
|
||||
free(msg.tx_buf);
|
||||
free(msg.rx_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write and read on the spi interface in 3-wire mode (half-duplex)
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param data Pointer to data buffer
|
||||
* @param bytes_number Number of bytes to transfer
|
||||
* @return int32_t - SUCCESS if the transfer finished
|
||||
* - FAILURE if the memory allocation or transfer failed
|
||||
*/
|
||||
int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc,
|
||||
uint8_t *write_data,
|
||||
uint8_t *read_data,
|
||||
uint16_t write_bytes_number,
|
||||
uint16_t read_bytes_number)
|
||||
{
|
||||
uint8_t word_len;
|
||||
uint8_t wr_words_number;
|
||||
uint8_t rd_words_number;
|
||||
int32_t ret;
|
||||
struct spi_engine_msg msg;
|
||||
struct spi_engine_desc *desc_extra;
|
||||
|
||||
desc_extra = desc->extra;
|
||||
|
||||
/* If we want to access SPI interface and SPI engine offload module was
|
||||
* activated, we need to disable it
|
||||
* This is set in spi_engine_offload_init() */
|
||||
desc_extra->offload_config = OFFLOAD_DISABLED;
|
||||
/* This is set in spi_engine_offload_transfer() */
|
||||
spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0);
|
||||
|
||||
wr_words_number = spi_get_words_number(desc_extra, write_bytes_number);
|
||||
rd_words_number = spi_get_words_number(desc_extra, read_bytes_number);
|
||||
|
||||
msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds));
|
||||
if (!msg.cmds)
|
||||
return FAILURE;
|
||||
|
||||
msg.tx_buf =(wr_words_number>0)?(uint32_t*)calloc(wr_words_number, sizeof(msg.tx_buf[0])):NULL;
|
||||
msg.rx_buf =(rd_words_number>0)?(uint32_t*)calloc(rd_words_number, sizeof(msg.rx_buf[0])):NULL;
|
||||
msg.tx_length = wr_words_number;
|
||||
msg.rx_length = rd_words_number;
|
||||
|
||||
/* Get the length of transferred word */
|
||||
word_len = spi_get_word_length(desc_extra);
|
||||
|
||||
/* Make sure the CS is HIGH before starting a transaction */
|
||||
msg.cmds->next = NULL;
|
||||
msg.cmds->cmd = CS_HIGH;
|
||||
|
||||
// Assert select.
|
||||
spi_engine_queue_add_cmd(&msg.cmds, CS_LOW);
|
||||
|
||||
// add read/write command
|
||||
if(write_bytes_number > 0)
|
||||
spi_engine_queue_add_cmd(&msg.cmds, WRITE(write_bytes_number));
|
||||
if(read_bytes_number > 0)
|
||||
spi_engine_queue_add_cmd(&msg.cmds, READ(read_bytes_number));
|
||||
|
||||
// Disable select.
|
||||
spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH);
|
||||
|
||||
/* Pack the bytes into engine WORDS */
|
||||
for (int i = 0; i < write_bytes_number; i++)
|
||||
msg.tx_buf[i / word_len] |= write_data[i] << (desc_extra->data_width-
|
||||
(i % word_len + 1) * 8);
|
||||
|
||||
ret = spi_engine_transfer_message(desc, &msg);
|
||||
|
||||
for (int i = 0; i < read_bytes_number; i++)
|
||||
read_data[i] = msg.rx_buf[(i) / word_len] >>
|
||||
(desc_extra->data_width -
|
||||
((i) % word_len + 1) * 8);
|
||||
|
||||
spi_engine_queue_free(&msg.cmds);
|
||||
free(msg.tx_buf);
|
||||
free(msg.rx_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI engine's offload module
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param param Structure containing the offload init parameters
|
||||
* @return int32_t This function always returns SUCCESS
|
||||
*/
|
||||
int32_t spi_engine_offload_init(struct spi_desc *desc,
|
||||
const struct spi_engine_offload_init_param *param)
|
||||
{
|
||||
struct spi_engine_desc *eng_desc;
|
||||
struct axi_dmac_init dmac_init;
|
||||
|
||||
eng_desc = desc->extra;
|
||||
|
||||
eng_desc->offload_config = param->offload_config;
|
||||
|
||||
if(!(param->dma_flags)) {
|
||||
eng_desc->cyclic = CYCLIC;
|
||||
} else {
|
||||
if((*(param->dma_flags)) & DMA_CYCLIC)
|
||||
eng_desc->cyclic = CYCLIC;
|
||||
else
|
||||
eng_desc->cyclic = NO;
|
||||
}
|
||||
|
||||
|
||||
if(param->offload_config & OFFLOAD_TX_EN) {
|
||||
dmac_init.name = "DAC DMAC";
|
||||
dmac_init.base = param->tx_dma_baseaddr;
|
||||
axi_dmac_init(&eng_desc->offload_tx_dma, &dmac_init);
|
||||
if(!eng_desc->offload_tx_dma)
|
||||
return FAILURE;
|
||||
}
|
||||
if(param->offload_config & OFFLOAD_RX_EN) {
|
||||
dmac_init.name = "ADC DMAC";
|
||||
dmac_init.base = param->rx_dma_baseaddr;
|
||||
axi_dmac_init(&eng_desc->offload_rx_dma, &dmac_init);
|
||||
if(!eng_desc->offload_rx_dma)
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initiate a SPI transfer in offload mode
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @param msg Offload message that get's to be transferred
|
||||
* @param no_samples Number of time the messages will be transferred
|
||||
* @return int32_t This function always returns SUCCESS
|
||||
*/
|
||||
int32_t spi_engine_offload_transfer(struct spi_desc *desc,
|
||||
struct spi_engine_offload_message msg,
|
||||
uint32_t no_samples)
|
||||
{
|
||||
struct spi_engine_msg transfer;
|
||||
struct spi_engine_desc *eng_desc;
|
||||
uint32_t i;
|
||||
uint8_t word_length;
|
||||
|
||||
eng_desc = desc->extra;
|
||||
|
||||
/* Check if offload is disabled */
|
||||
if(!((eng_desc->offload_config & OFFLOAD_TX_EN) |
|
||||
(eng_desc->offload_config & OFFLOAD_RX_EN)))
|
||||
return FAILURE;
|
||||
|
||||
spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 1);
|
||||
spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 0);
|
||||
|
||||
eng_desc->offload_tx_len = 0;
|
||||
eng_desc->offload_rx_len = 0;
|
||||
|
||||
transfer.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*transfer.cmds));
|
||||
|
||||
if (!transfer.cmds)
|
||||
return -1;
|
||||
|
||||
transfer.tx_buf = msg.commands_data;
|
||||
|
||||
/* Load the commands into the message */
|
||||
transfer.cmds->next = NULL;
|
||||
transfer.cmds->cmd = msg.commands[0];
|
||||
i = 1;
|
||||
while(i < msg.no_commands) {
|
||||
spi_engine_queue_add_cmd(&transfer.cmds, msg.commands[i++]);
|
||||
|
||||
}
|
||||
|
||||
spi_engine_transfer_message(desc, &transfer);
|
||||
|
||||
/* Start transfer */
|
||||
spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0x0001);
|
||||
|
||||
word_length = spi_get_word_length(eng_desc);
|
||||
if(eng_desc->offload_config & OFFLOAD_TX_EN) {
|
||||
struct axi_dma_transfer tx_transfer = {
|
||||
// Number of bytes to write/read
|
||||
.size = word_length * eng_desc->offload_tx_len * no_samples,
|
||||
// Transfer done flag
|
||||
.transfer_done = 0,
|
||||
// Signal transfer mode
|
||||
.cyclic = eng_desc->cyclic,
|
||||
// Address of data source
|
||||
.src_addr = (uintptr_t)msg.tx_addr,
|
||||
// Address of data destination
|
||||
.dest_addr = 0
|
||||
};
|
||||
axi_dmac_transfer_start(eng_desc->offload_tx_dma, &tx_transfer);
|
||||
}
|
||||
|
||||
if(eng_desc->offload_config & OFFLOAD_RX_EN) {
|
||||
struct axi_dma_transfer rx_transfer = {
|
||||
// Number of bytes to write/read
|
||||
.size = word_length * eng_desc->offload_tx_len * no_samples,
|
||||
// Transfer done flag
|
||||
.transfer_done = 0,
|
||||
// Signal transfer mode
|
||||
.cyclic = NO,
|
||||
// Address of data source
|
||||
.src_addr = 0,
|
||||
// Address of data destination
|
||||
.dest_addr = (uintptr_t)msg.rx_addr
|
||||
};
|
||||
axi_dmac_transfer_start(eng_desc->offload_rx_dma, &rx_transfer);
|
||||
axi_dmac_transfer_wait_completion(eng_desc->offload_rx_dma, 500);
|
||||
}
|
||||
|
||||
usleep(1000);
|
||||
|
||||
spi_engine_queue_free(&transfer.cmds);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by spi_init().
|
||||
*
|
||||
* @param desc Decriptor containing SPI interface parameters
|
||||
* @return int32_t This function allways returns SUCCESS
|
||||
*/
|
||||
int32_t spi_engine_remove(struct spi_desc *desc)
|
||||
{
|
||||
struct spi_engine_desc *eng_desc;
|
||||
|
||||
eng_desc = desc->extra;
|
||||
|
||||
if(eng_desc->offload_config & OFFLOAD_TX_EN)
|
||||
axi_dmac_remove(eng_desc->offload_tx_dma);
|
||||
if(eng_desc->offload_config & OFFLOAD_RX_EN)
|
||||
axi_dmac_remove(eng_desc->offload_rx_dma);
|
||||
free(desc->extra);
|
||||
free(desc);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
/*******************************************************************************
|
||||
* @file spi_engine.h
|
||||
* @brief Header file of SPI Engine core features.
|
||||
* @author Sergiu Cuciurean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SPI_ENGINE_H
|
||||
#define SPI_ENGINE_H
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "spi_engine_private.h"
|
||||
#include "../axi_dmac/axi_dmac.h"
|
||||
#include "../../platform/xilinx_spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define OFFLOAD_DISABLED 0x00
|
||||
#define OFFLOAD_TX_EN BIT(0)
|
||||
#define OFFLOAD_RX_EN BIT(1)
|
||||
#define OFFLOAD_TX_RX_EN OFFLOAD_TX_EN | OFFLOAD_RX_EN
|
||||
|
||||
#define SPI_ENGINE_MSG_QUEUE_END 0xFFFFFFFF
|
||||
|
||||
/* Spi engine commands */
|
||||
#define WRITE(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\
|
||||
(SPI_ENGINE_INSTRUCTION_TRANSFER_W << 8) | no_bytes)
|
||||
|
||||
#define READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\
|
||||
(SPI_ENGINE_INSTRUCTION_TRANSFER_R << 8) | no_bytes)
|
||||
|
||||
#define WRITE_READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\
|
||||
(SPI_ENGINE_INSTRUCTION_TRANSFER_RW << 8) | no_bytes)
|
||||
|
||||
#define SLEEP(time) SPI_ENGINE_CMD_SLEEP(time & 0xF)
|
||||
|
||||
/* The delay and chip select parmeters are passed over the engine descriptor
|
||||
and will be used inside the function call */
|
||||
#define CS_HIGH SPI_ENGINE_CMD_ASSERT(0x01, 0xFF)
|
||||
#define CS_LOW SPI_ENGINE_CMD_ASSERT(0x01, 0x00)
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @struct spi_engine_init_param
|
||||
* @brief Structure containing the init parameters needed by the SPI engine
|
||||
*/
|
||||
struct spi_engine_init_param {
|
||||
/** SPI engine reference clock */
|
||||
uint32_t ref_clk_hz;
|
||||
/** Type of implementation */
|
||||
enum xil_spi_type type;
|
||||
/** Base address where the HDL core is situated */
|
||||
uint32_t spi_engine_baseaddr;
|
||||
/** Delay between the CS toggle and the start of SCLK */
|
||||
uint32_t cs_delay;
|
||||
/** Data with of one SPI transfer ( in bits ) */
|
||||
uint8_t data_width;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct spi_engine_desc
|
||||
* @brief Structure representing an SPI engine device
|
||||
*/
|
||||
struct spi_engine_desc {
|
||||
/** SPI engine reference clock */
|
||||
uint32_t ref_clk_hz;
|
||||
/** Type of implementation */
|
||||
enum xil_spi_type type;
|
||||
/** Pointer to a DMAC used in transmission */
|
||||
struct axi_dmac *offload_tx_dma;
|
||||
/** Pointer to a DMAC used in reception */
|
||||
struct axi_dmac *offload_rx_dma;
|
||||
/** Transfer mode for Tx DMAC */
|
||||
enum cyclic_transfer cyclic;
|
||||
/** Offload's module transfer direction : TX, RX or both */
|
||||
uint8_t offload_config;
|
||||
/** Number of words that the module has to send */
|
||||
uint8_t offload_tx_len;
|
||||
/** Number of words that the module has to receive */
|
||||
uint8_t offload_rx_len;
|
||||
/** Base address where the HDL core is situated */
|
||||
uint32_t spi_engine_baseaddr;
|
||||
/** Base address where the RX DMAC core is situated */
|
||||
uint32_t rx_dma_baseaddr;
|
||||
/** Base address where the TX DMAC core is situated */
|
||||
uint32_t tx_dma_baseaddr;
|
||||
/** Delay between the CS toggle and the start of SCLK */
|
||||
uint8_t cs_delay;
|
||||
/** Clock divider used in transmission delays */
|
||||
uint32_t clk_div;
|
||||
/** Data with of one SPI transfer ( in bits ) */
|
||||
uint8_t data_width;
|
||||
/** The maximum data width supported by the engine */
|
||||
uint8_t max_data_width;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct spi_engine_offload_init_param
|
||||
* @brief Structure containing the init parameters needed by the offload module
|
||||
*/
|
||||
struct spi_engine_offload_init_param {
|
||||
/** Base address where the RX DMAC core is situated */
|
||||
uint32_t rx_dma_baseaddr;
|
||||
/** Base address where the TX DMAC core is situated */
|
||||
uint32_t tx_dma_baseaddr;
|
||||
/** DMAC flags - if not initialized, the default value is DMA_CYCLIC */
|
||||
uint32_t *dma_flags;
|
||||
/** Offload's module transfer direction : TX, RX or both */
|
||||
uint8_t offload_config;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct spi_engine_offload_message
|
||||
* @brief Structure representing an offload message
|
||||
*/
|
||||
struct spi_engine_offload_message {
|
||||
/** Pointer to the SPI engine commands buffer that will be sent.
|
||||
* The available commands can be found at:
|
||||
* https://wiki.analog.com/resources/fpga/peripherals/spi_engine/
|
||||
*/
|
||||
uint32_t *commands;
|
||||
/** Length of the SPI engine commands buffer */
|
||||
uint32_t no_commands;
|
||||
/** Pointer of the data that will be sent over spi */
|
||||
uint32_t *commands_data;
|
||||
/** The address where the data that will be transmitted is situated */
|
||||
uint32_t tx_addr;
|
||||
/** The address where the data that will be received is situated */
|
||||
uint32_t rx_addr;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Spi engine platform specific SPI platform ops structure
|
||||
*/
|
||||
extern const struct spi_platform_ops xil_spi_ops;
|
||||
|
||||
/* Write SPI Engine's axi registers */
|
||||
int32_t spi_engine_write(struct spi_engine_desc *desc,
|
||||
uint32_t reg_addr,
|
||||
uint32_t reg_data);
|
||||
|
||||
/* Read SPI Engine's axi registers */
|
||||
int32_t spi_engine_read(struct spi_engine_desc *desc,
|
||||
uint32_t reg_addr,
|
||||
uint32_t *reg_data);
|
||||
/* Initialize the SPI engine device */
|
||||
int32_t spi_engine_init(struct spi_desc **desc,
|
||||
const struct spi_init_param *param);
|
||||
|
||||
/* Write and read data over SPI using the SPI engine */
|
||||
int32_t spi_engine_write_and_read(struct spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number);
|
||||
|
||||
/* Write and read data over SPI using the SPI engine in 3-wire mode */
|
||||
int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc,
|
||||
uint8_t *write_data,
|
||||
uint8_t *read_data,
|
||||
uint16_t write_bytes_number,
|
||||
uint16_t read_bytes_number);
|
||||
/* Free the resources used by the SPI engine device */
|
||||
int32_t spi_engine_remove(struct spi_desc *desc);
|
||||
|
||||
/* Initialize the SPI engine offload module */
|
||||
int32_t spi_engine_offload_init(struct spi_desc *desc,
|
||||
const struct spi_engine_offload_init_param *param);
|
||||
|
||||
/* Write and read data over SPI using the offload module */
|
||||
int32_t spi_engine_offload_transfer(struct spi_desc *desc,
|
||||
struct spi_engine_offload_message msg,
|
||||
uint32_t no_samples);
|
||||
|
||||
/* Set SPI transfer width */
|
||||
int32_t spi_engine_set_transfer_width(struct spi_desc *desc,
|
||||
uint8_t data_wdith);
|
||||
|
||||
/* Set SPI transfer speed */
|
||||
void spi_engine_set_speed(struct spi_desc *desc,
|
||||
uint32_t speed_hz);
|
||||
|
||||
#endif // SPI_ENGINE_H
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
/*******************************************************************************
|
||||
* @file spi_engine_private.h
|
||||
* @brief Private definitions of the SPI Engine
|
||||
* @author Sergiu Cuciurean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SPI_ENGINE_PRIVATE_H
|
||||
#define SPI_ENGINE_PRIVATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "spi.h"
|
||||
#include "util.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Spi Engine registers *****************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define SPI_ENGINE_REG_VERSION 0x00
|
||||
#define SPI_ENGINE_REG_DATA_WIDTH 0x0C
|
||||
#define SPI_ENGINE_REG_RESET 0x40
|
||||
#define SPI_ENGINE_REG_INT_ENABLE 0x80
|
||||
#define SPI_ENGINE_REG_INT_PENDING 0x84
|
||||
#define SPI_ENGINE_REG_INT_SOURCE 0x88
|
||||
#define SPI_ENGINE_REG_SYNC_ID 0xC0
|
||||
#define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xD0
|
||||
#define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xD4
|
||||
#define SPI_ENGINE_REG_SDI_FIFO_LEVEL 0xD8
|
||||
#define SPI_ENGINE_REG_CMD_FIFO 0xE0
|
||||
#define SPI_ENGINE_REG_SDO_DATA_FIFO 0xE4
|
||||
#define SPI_ENGINE_REG_SDI_DATA_FIFO 0xE8
|
||||
#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xEC
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Spi Engine register parameters **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define SPI_ENGINE_INST_TRANSFER 0x00
|
||||
#define SPI_ENGINE_INST_ASSERT 0x01
|
||||
#define SPI_ENGINE_INST_CONFIG 0x02
|
||||
#define SPI_ENGINE_INST_SYNC_SLEEP 0x03
|
||||
#define SPI_ENGINE_INST_MISC 0x03
|
||||
#define SPI_ENGINE_CMD_REG_CLK_DIV 0x00
|
||||
#define SPI_ENGINE_CMD_REG_CONFIG 0x01
|
||||
#define SPI_ENGINE_CMD_DATA_TRANSFER_LEN 0x02
|
||||
#define SPI_ENGINE_MISC_SYNC 0x00
|
||||
#define SPI_ENGINE_MISC_SLEEP 0x01
|
||||
#define SPI_ENGINE_SYNC_TRANSFER_BEGIN BIT(1)
|
||||
#define SPI_ENGINE_SYNC_TRANSFER_END BIT(2)
|
||||
#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0)
|
||||
#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1)
|
||||
#define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2)
|
||||
#define SPI_ENGINE_INT_SYNC BIT(3)
|
||||
#define SPI_ENGINE_OFFLOAD_CTRL_ENABLE BIT(0)
|
||||
#define SPI_ENGINE_OFFLOAD_STATUS_ENABLED BIT(0)
|
||||
#define SPI_ENGINE_CONFIG_CPHA BIT(0)
|
||||
#define SPI_ENGINE_CONFIG_CPOL BIT(1)
|
||||
#define SPI_ENGINE_CONFIG_3WIRE BIT(2)
|
||||
#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff)
|
||||
#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff)
|
||||
#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff)
|
||||
|
||||
/******************************************************************************/
|
||||
/**************************** Spi Engine commands *****************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define SPI_ENGINE_INSTRUCTION_TRANSFER_W 0x01
|
||||
#define SPI_ENGINE_INSTRUCTION_TRANSFER_R 0x02
|
||||
#define SPI_ENGINE_INSTRUCTION_TRANSFER_RW 0x03
|
||||
|
||||
#define SPI_ENGINE_REG_OFFLOAD_CTRL(x) (0x100 + (0x20 * x))
|
||||
#define SPI_ENGINE_REG_OFFLOAD_STATUS(x) (0x104 + (0x20 * x))
|
||||
#define SPI_ENGINE_REG_OFFLOAD_RESET(x) (0x108 + (0x20 * x))
|
||||
#define SPI_ENGINE_REG_OFFLOAD_CMD_MEM(x) (0x110 + (0x20 * x))
|
||||
#define SPI_ENGINE_REG_OFFLOAD_SDO_MEM(x) (0x114 + (0x20 * x))
|
||||
|
||||
#define SPI_ENGINE_CMD(inst, arg1, arg2) \
|
||||
(((inst & 0x03) << 12) | \
|
||||
((arg1 & 0x03) << 8) | arg2 )
|
||||
|
||||
#define SPI_ENGINE_CMD_TRANSFER(readwrite, n) \
|
||||
SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, \
|
||||
(readwrite), (n))
|
||||
|
||||
#define SPI_ENGINE_CMD_ASSERT(delay, cs) \
|
||||
SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, \
|
||||
(delay), (cs))
|
||||
|
||||
#define SPI_ENGINE_CMD_CONFIG(reg, val) \
|
||||
SPI_ENGINE_CMD(SPI_ENGINE_INST_CONFIG, \
|
||||
(reg), (val))
|
||||
|
||||
#define SPI_ENGINE_CMD_SLEEP(delay) \
|
||||
SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \
|
||||
SPI_ENGINE_MISC_SLEEP, \
|
||||
(delay))
|
||||
|
||||
#define SPI_ENGINE_CMD_SYNC(id) \
|
||||
SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \
|
||||
SPI_ENGINE_MISC_SYNC, \
|
||||
(id))
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct spi_engine_cmd_queue {
|
||||
uint32_t cmd;
|
||||
struct spi_engine_cmd_queue *next;
|
||||
} spi_engine_cmd_queue;
|
||||
|
||||
typedef struct spi_engine_msg {
|
||||
uint32_t *tx_buf;
|
||||
uint32_t *rx_buf;
|
||||
uint32_t tx_length;
|
||||
uint32_t rx_length;
|
||||
struct spi_engine_cmd_queue *cmds;
|
||||
} spi_engine_msg;
|
||||
|
||||
#endif // SPI_ENGINE_PRIVATE_H
|
||||
@@ -0,0 +1,783 @@
|
||||
/**
|
||||
* \file ad9528.c
|
||||
* \brief Contains source code for configuring and initializing AD9528 clock device
|
||||
*/
|
||||
|
||||
/**
|
||||
* \page Disclaimer Legal Disclaimer
|
||||
* Copyright 2015-2017 Analog Devices Inc.
|
||||
* Released under the AD9371 API license.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "ad9528.h"
|
||||
#include "../../../include/error.h"
|
||||
|
||||
static uint32_t _desired_time_to_elapse_ms = 0;
|
||||
|
||||
/**
|
||||
* \brief Write data to a register
|
||||
*/
|
||||
int32_t AD9528_spiWriteByte(ad9528Device_t *device, uint16_t addr,
|
||||
uint8_t data)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
int32_t status;
|
||||
|
||||
buf[0] = (addr >> 8) & 0x7F;
|
||||
buf[1] = addr & 0xFF;
|
||||
buf[2] = data;
|
||||
status = spi_write_and_read_3wire(device->spi_desc,
|
||||
buf, NULL, 3, 0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read data from a register
|
||||
*/
|
||||
int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr,
|
||||
uint8_t *readdata)
|
||||
{
|
||||
uint8_t tx_buf[2];
|
||||
uint8_t rx_buf[1];
|
||||
int32_t status;
|
||||
|
||||
tx_buf[0] = 0x80 | addr >> 8;
|
||||
tx_buf[1] = addr & 0xFF;
|
||||
|
||||
status = spi_write_and_read_3wire(device->spi_desc,
|
||||
tx_buf, rx_buf, 2, 1);
|
||||
|
||||
*readdata = rx_buf[0];
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Modify a field of bits from a register
|
||||
*/
|
||||
int32_t AD9528_spiWriteField(ad9528Device_t *device,
|
||||
uint16_t addr, uint8_t fieldVal, uint8_t mask, uint8_t startBit)
|
||||
{
|
||||
int32_t errVal;
|
||||
uint8_t readVal;
|
||||
|
||||
errVal = AD9528_spiReadByte(device, addr, &readVal);
|
||||
if (errVal < 0)
|
||||
return errVal;
|
||||
|
||||
readVal = (readVal & ~mask) | ((fieldVal << startBit) & mask);
|
||||
|
||||
return AD9528_spiWriteByte(device, addr, readVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the desired timeout value
|
||||
*/
|
||||
int32_t AD9528_setTimeout_ms(uint32_t timeOut_ms)
|
||||
{
|
||||
_desired_time_to_elapse_ms = timeOut_ms;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Verify if the desired time has elapsed
|
||||
*/
|
||||
int32_t AD9528_hasTimeoutExpired()
|
||||
{
|
||||
udelay(1000);
|
||||
|
||||
_desired_time_to_elapse_ms--;
|
||||
if (_desired_time_to_elapse_ms > 0)
|
||||
return SUCCESS;
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Performs a hard reset on the AD9528 DUT
|
||||
*
|
||||
* <B>Dependencies</B>
|
||||
* - device->spiSettings->chipSelectIndex
|
||||
*
|
||||
* \param device is structure pointer to the AD9528 data structure containing settings
|
||||
* \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail
|
||||
*/
|
||||
int32_t AD9528_resetDevice(ad9528Device_t *device)
|
||||
{
|
||||
gpio_direction_output(device->gpio_resetb, 0);
|
||||
mdelay(100);
|
||||
gpio_direction_output(device->gpio_resetb, 1);
|
||||
mdelay(100);
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x81);
|
||||
mdelay(100);
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x00);
|
||||
mdelay(100);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets the AD9528 device SPI settings (3wire/4wire, MSBFirst, etc).
|
||||
*
|
||||
* This function will use the settings in the device->spiSettings structure
|
||||
* to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst,
|
||||
* and 3wire/4wire mode. The AD9528 device always uses SPI MODE 0 (CPHA=0, CPOL=0).
|
||||
* This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and
|
||||
* longInstructionWord =1 to use a 16bit instruction word.
|
||||
*
|
||||
* <B>Dependencies</B>
|
||||
* - writes device->spiSettings->CPHA = 0
|
||||
* - writes device->spiSettings->CPOL = 0
|
||||
* - writes device->spiSettings->longInstructionWord = 1
|
||||
*
|
||||
* - device->spiSettings->MSBFirst
|
||||
* - device->spiSettings->enSpiStreaming
|
||||
* - device->spiSettings->autoIncAddrUp
|
||||
* - device->spiSettings->fourWireMode
|
||||
*
|
||||
* \param device is structure pointer to the AD9528 data structure containing settings
|
||||
*
|
||||
* \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail
|
||||
*/
|
||||
int32_t AD9528_setSpiSettings(ad9528Device_t *device)
|
||||
{
|
||||
uint8_t spiReg = 0;
|
||||
|
||||
device->spiSettings->CPHA = 0;
|
||||
device->spiSettings->CPOL = 0;
|
||||
device->spiSettings->longInstructionWord = 1;
|
||||
|
||||
if (device->spiSettings->MSBFirst == 0) {
|
||||
spiReg |= 0x42; /* SPI bit is 1=LSB first */
|
||||
}
|
||||
|
||||
if (device->spiSettings->autoIncAddrUp > 0) {
|
||||
spiReg |= 0x24;
|
||||
}
|
||||
|
||||
if (device->spiSettings->fourWireMode > 0) {
|
||||
spiReg |= 0x18;
|
||||
}
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, spiReg);
|
||||
|
||||
if (device->spiSettings->enSpiStreaming > 0) {
|
||||
/* Allow SPI streaming mode: SPI message ends when chip select deasserts */
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00);
|
||||
} else {
|
||||
/* Force single instruction mode */
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x80);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Helper function for ADI transceiver eval boards to init the AD9528 data structure
|
||||
*
|
||||
* This function inits the AD9528 device data structure with defaults that
|
||||
* are known to work with the ADI AD9369 and AD9371 evaluation boards. NOTE: This function will
|
||||
* modify the contents of the AD9528 device data structure.
|
||||
*
|
||||
* <B>Dependencies</B>
|
||||
* - spi->chipSelectIndex
|
||||
* - spi
|
||||
*
|
||||
* \param device Pointer to the AD9528 device data structure to initialize
|
||||
* \param vcxoFrequency_Hz The VCXO frequency that is connected to the AD9528
|
||||
* \param refAFrequency_Hz The reference clock frequency being input into the AD9528 REFCLK A input
|
||||
* \param outputDeviceClock_Hz Desired output clock frequency to the FPGA and transceiver device
|
||||
*
|
||||
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
|
||||
*/
|
||||
int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device,
|
||||
uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz,
|
||||
uint32_t outputDeviceClock_Hz)
|
||||
{
|
||||
// uint16_t chDiv;
|
||||
// uint8_t i = 0;
|
||||
//
|
||||
// uint32_t pll1PfdFreq_Hz = 0;
|
||||
// uint8_t pll1Ndiv = 0;
|
||||
// uint8_t validPll1DivSetting = 0;
|
||||
// uint8_t refAdiv = 1;
|
||||
//
|
||||
//
|
||||
// uint8_t pll2RfDiv = 3; /* Valid values 3,4,5 */
|
||||
// uint16_t pll2Ndiv = 1; /* Valid values 1-256 */
|
||||
// uint32_t pll2InputFreq_Hz = 0;
|
||||
// uint64_t pll2VcoFreq_Hz = 0;
|
||||
// uint16_t pll2NdivStart = 0;
|
||||
// uint8_t validPll2DivSetting = 0;
|
||||
// uint64_t chDivU64 = 0;
|
||||
//
|
||||
// static const uint64_t PLL2_MIN_VCO_FREQ_HZ = 3450000000ULL;
|
||||
// static const uint64_t PLL2_MAX_VCO_FREQ_HZ = 4025000000ULL;
|
||||
|
||||
// struct spi_init_param spi_param;
|
||||
// int32_t status;
|
||||
//
|
||||
// status = gpio_get(&device->gpio_resetb, CLK_RESETB);
|
||||
// status |= gpio_get(&device->gpio_sysref_req, ADRV_SYSREF_REQ);
|
||||
//
|
||||
// spi_param.id = 0;
|
||||
// spi_param.mode = SPI_MODE_0;
|
||||
// spi_param.chip_select = CLK_CS;
|
||||
// status |= spi_init(&device->spi_desc, &spi_param);
|
||||
//
|
||||
// if (status != SUCCESS)
|
||||
// return FAILURE;
|
||||
|
||||
/*******************************************************************
|
||||
* PLL1 Settings
|
||||
*******************************************************************
|
||||
*/
|
||||
|
||||
/* find valid PLL1 Ndiv and REFA div */
|
||||
// for (pll1Ndiv = 1; pll1Ndiv < 20; pll1Ndiv++) {
|
||||
// pll1PfdFreq_Hz = vcxoFrequency_Hz / pll1Ndiv;
|
||||
//
|
||||
// if ((pll1PfdFreq_Hz <= 110000000) && (pll1PfdFreq_Hz >= 1000000) &&
|
||||
// (pll1PfdFreq_Hz <= refAFrequency_Hz) &&
|
||||
// (refAFrequency_Hz % pll1PfdFreq_Hz == 0)
|
||||
// ) {
|
||||
// validPll1DivSetting = 1;
|
||||
// refAdiv = refAFrequency_Hz / pll1PfdFreq_Hz ;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (validPll1DivSetting == 0) {
|
||||
// return FAILURE;
|
||||
// }
|
||||
|
||||
// device->pll1Settings->nDivider =
|
||||
// pll1Ndiv; //This init function always runs PLL1 at 30.72MHz Pfd rate
|
||||
// device->pll1Settings->refA_bufferCtrl =
|
||||
// DIFFERENTIAL; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
|
||||
// device->pll1Settings->refA_Divider = refAdiv;
|
||||
// device->pll1Settings->refA_Frequency_Hz = refAFrequency_Hz;
|
||||
// device->pll1Settings->refB_bufferCtrl =
|
||||
// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
|
||||
// device->pll1Settings->refB_Divider = 1;
|
||||
// device->pll1Settings->refB_Frequency_Hz = 0;
|
||||
// device->pll1Settings->vcxoBufferCtrl =
|
||||
// NEG_SINGLE_ENDED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
|
||||
// device->pll1Settings->vcxo_Frequency_Hz = vcxoFrequency_Hz;
|
||||
|
||||
/*******************************************************************
|
||||
* PLL2 Settings
|
||||
*******************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************
|
||||
* Output Distribution Settings
|
||||
* 9369CE02A uses the following clock outputs
|
||||
* OUT 1: FPGA REFCLK
|
||||
* OUT 3: FPGA SYSREF
|
||||
* OUT 12: DUT SYSREF
|
||||
* OUT 13: DUT REFCLK
|
||||
*******************************************************************
|
||||
*/
|
||||
|
||||
/* PLL 2 input clock can be several different things. Currently hard coded by this init funciton to use
|
||||
* PLL 1 output (VCXO Frequency) with no scaling
|
||||
*/
|
||||
// pll2InputFreq_Hz = device->pll1Settings->vcxo_Frequency_Hz;
|
||||
// validPll2DivSetting = 0;
|
||||
|
||||
/* Sweep PLL2 Divider settings to find something that has a valid integer divide (3,4,5)*/
|
||||
// for (pll2RfDiv = 3; pll2RfDiv <= 5; pll2RfDiv++) {
|
||||
//
|
||||
// pll2NdivStart = (PLL2_MIN_VCO_FREQ_HZ / pll2RfDiv / pll2InputFreq_Hz);
|
||||
// /* find valid PLL2 Ndiv (1-256) */
|
||||
// for (pll2Ndiv = pll2NdivStart; pll2Ndiv <= 256; pll2Ndiv++) {
|
||||
// pll2VcoFreq_Hz = (pll2InputFreq_Hz * pll2RfDiv * pll2Ndiv);
|
||||
//
|
||||
// if (pll2VcoFreq_Hz < PLL2_MIN_VCO_FREQ_HZ) {
|
||||
// /* Continue to next PLL2 N div */
|
||||
// continue;
|
||||
// } else if (pll2VcoFreq_Hz > PLL2_MAX_VCO_FREQ_HZ) {
|
||||
// /* Break to next PLL2 RF div */
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if (((pll2VcoFreq_Hz / pll2RfDiv) % outputDeviceClock_Hz) == 0) {
|
||||
//
|
||||
// device->pll2Settings->rfDivider = pll2RfDiv;
|
||||
// device->pll2Settings->n2Divider = pll2Ndiv;
|
||||
// device->pll2Settings->totalNdiv = pll2RfDiv * pll2Ndiv;
|
||||
// chDivU64 = ((pll2VcoFreq_Hz / pll2RfDiv) / outputDeviceClock_Hz);
|
||||
//
|
||||
// if ((chDivU64 < 1) || (chDivU64 > 256)) {
|
||||
// return FAILURE;
|
||||
// } else {
|
||||
// chDiv = (uint16_t)(chDivU64);
|
||||
// }
|
||||
//
|
||||
// validPll2DivSetting = 1;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (validPll2DivSetting == 1) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (validPll2DivSetting == 0) {
|
||||
// return FAILURE;
|
||||
// }
|
||||
//
|
||||
// device->outputSettings->outPowerDown = (uint16_t)(
|
||||
// ~0x318A); //enable outputs 13,12,8,7,3 and 1
|
||||
//
|
||||
// for (i=0; i<14; i++) {
|
||||
// device->outputSettings->outSource[i] =
|
||||
// CHANNEL_DIV; //CHANNEL_DIV , PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT
|
||||
// device->outputSettings->outBufferCtrl[i] = LVDS; //LVDS, LVDS_BOOST, HSTL
|
||||
// device->outputSettings->outChannelDiv[i] = chDiv;
|
||||
// device->outputSettings->outFrequency_Hz[i] = outputDeviceClock_Hz;
|
||||
// device->outputSettings->outAnalogDelay[i] = 0;
|
||||
// device->outputSettings->outDigitalDelay[i] = 0;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// device->outputSettings->outSource[3] = SYSREF;
|
||||
// device->outputSettings->outSource[7] = SYSREF;
|
||||
// device->outputSettings->outSource[12] = SYSREF;
|
||||
//
|
||||
//
|
||||
// device->sysrefSettings->sysrefDivide =
|
||||
// 512; //SYSREF frequency = VCXO / 2 / sysrefDivde
|
||||
// device->sysrefSettings->sysrefNshotMode =
|
||||
// ONE_PULSE; //ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5
|
||||
// device->sysrefSettings->sysrefPatternMode =
|
||||
// CONTINUOUS; //NSHOT=0, CONTINUOUS=1, PRBS=2, STOP=3
|
||||
// device->sysrefSettings->sysrefPinBufferMode =
|
||||
// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
|
||||
// device->sysrefSettings->sysrefPinEdgeMode =
|
||||
// LEVEL_ACTIVE_HIGH; //LEVEL_ACTIVE_HIGH=0, LEVEL_ACTIVE_LOW=1, RISING_EDGE=2, FALLING_EDGE=3
|
||||
// device->sysrefSettings->sysrefRequestMethod = PIN; //SPI=0,PIN=1
|
||||
// device->sysrefSettings->sysrefSource =
|
||||
// INTERNAL; //EXTERNAL=0, EXT_RESAMPLED=1, INTERNAL=2
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
ad9528Device_t *dev;
|
||||
|
||||
dev = (ad9528Device_t *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_device->spi_init);
|
||||
ret |= gpio_get(&dev->gpio_resetb, init_device->gpio_init_resetb);
|
||||
ret |= gpio_get(&dev->gpio_sysref_req, init_device->gpio_init_sysref_req);
|
||||
|
||||
gpio_direction_output(dev->gpio_resetb, 0);
|
||||
gpio_direction_output(dev->gpio_sysref_req, 0);
|
||||
|
||||
AD9528_resetDevice(dev);
|
||||
|
||||
dev->spiSettings = init_device->spiSettings;
|
||||
dev->pll1Settings = init_device->pll1Settings;
|
||||
dev->pll2Settings = init_device->pll2Settings;
|
||||
dev->outputSettings = init_device->outputSettings;
|
||||
dev->sysrefSettings = init_device->sysrefSettings;
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initializes the AD9528 by writing all SPI registers
|
||||
*
|
||||
* Initializes the AD9528 for use with the AD9369 transceiver. Designed to work with
|
||||
* a reference clock of 122.88MHz. Reference clock is expected to be 30.72MHz.
|
||||
* The output clocks from the AD9528 can run at 122.88M, 153.6M, 184.32M, 245.76M, or 307.2M.
|
||||
* Typical setup: REFA frequency = 30.72, VCXO = 122.88MHz
|
||||
* SYNC(SYSREF) pulses output at rate of 120kHz
|
||||
*
|
||||
* <B>Dependencies</B>
|
||||
* - All parameters in device structure
|
||||
*
|
||||
* \param device is structure pointer to AD9528 clock device structure
|
||||
*
|
||||
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
|
||||
*/
|
||||
int32_t AD9528_config(ad9528Device_t
|
||||
*device) //writes all registers to desired values, leaves clock outputs off, SYSREF output disabled.
|
||||
{
|
||||
uint8_t pll2_Adiv=0;
|
||||
uint8_t pll2_Bdiv=0;
|
||||
uint8_t reg108=0;
|
||||
uint8_t reg109=0x4;
|
||||
uint8_t i = 0;
|
||||
uint8_t j = 0;
|
||||
uint8_t reg508;
|
||||
int32_t retval = SUCCESS;
|
||||
|
||||
retval = AD9528_setSpiSettings(device);
|
||||
if (retval != SUCCESS) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Configure PLL1
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_LSB,
|
||||
device->pll1Settings->refA_Divider & 0xFF); //REF A div[7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_MSB,
|
||||
(device->pll1Settings->refA_Divider >> 8) & 0x03); //REF A div[9:8]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_LSB,
|
||||
device->pll1Settings->refB_Divider & 0xFF); //REF B div[7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_MSB,
|
||||
(device->pll1Settings->refB_Divider >> 8) & 0x03); //REF B div[9:8]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_LSB,
|
||||
device->pll1Settings->nDivider & 0xFF); //PLL1 N div[7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_MSB,
|
||||
(device->pll1Settings->nDivider >> 8) & 0x03); //PLL1 N div[9:8]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CHARGEPUMP,
|
||||
0x0A); //PLL1 Charge Pump control 1
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CP_CTRL2,
|
||||
0x03); //PLL1 Charge Pump control 2
|
||||
|
||||
switch (device->pll1Settings->refA_bufferCtrl) {
|
||||
case DISABLED:
|
||||
reg108 &= ~0x28;
|
||||
reg109 &= ~0x01;
|
||||
break; //clear all REFA enable bits
|
||||
case SINGLE_ENDED:
|
||||
reg108 |= 0x08;
|
||||
reg109 &= ~0x01;
|
||||
break; //Set REFA receiver enable, clear REFA SE negative input enable
|
||||
case NEG_SINGLE_ENDED:
|
||||
reg108 |= 0x08;
|
||||
reg108 &= ~0x10;
|
||||
reg109 |= 0x01;
|
||||
break; //Disable REFA diff receiver, enable REFA receiver and use negative REFA input
|
||||
case DIFFERENTIAL:
|
||||
reg108 |= 0x28;
|
||||
reg109 &= ~0x01;
|
||||
break;
|
||||
default:
|
||||
reg108 |= 0x08;
|
||||
reg109 &= ~0x01;
|
||||
break; //default to single ended case
|
||||
}
|
||||
switch (device->pll1Settings->refB_bufferCtrl) {
|
||||
case DISABLED:
|
||||
reg108 &= ~0x50;
|
||||
reg109 &= ~0x02;
|
||||
break; //clear all REFB enable bits
|
||||
case SINGLE_ENDED:
|
||||
reg108 |= 0x10;
|
||||
reg109 &= ~0x02;
|
||||
break; //Set REFB receiver enable, clear REFB SE negative input enable
|
||||
case NEG_SINGLE_ENDED:
|
||||
reg108 |= 0x10;
|
||||
reg108 &= ~0x40;
|
||||
reg109 |= 0x02;
|
||||
break; //Disable REFB diff receiver, enable REFB receiver and use negative REFB input
|
||||
case DIFFERENTIAL:
|
||||
reg108 |= 0x50;
|
||||
reg109 &= ~0x02;
|
||||
break;
|
||||
default:
|
||||
reg108 |= 0x10;
|
||||
reg109 &= ~0x02;
|
||||
break; //default to single ended case
|
||||
}
|
||||
switch (device->pll1Settings->vcxoBufferCtrl) {
|
||||
case DISABLED:
|
||||
reg108 &= ~0x03;
|
||||
reg108 |= 0x04;
|
||||
break; //power down VCXO input
|
||||
case SINGLE_ENDED:
|
||||
reg108 &= ~0x07;
|
||||
break; //Clear VCXO receiver power down, defaults to Single ended mode
|
||||
case NEG_SINGLE_ENDED:
|
||||
reg108 &= ~0x07;
|
||||
reg108 |= 0x02;
|
||||
break; //Clear VCXO power down, enable Negative single ended mode[1]
|
||||
case DIFFERENTIAL:
|
||||
reg108 &= ~0x07;
|
||||
reg108 |= 0x01;
|
||||
break; //Clear VCXO power down, enable differential input buffer[0]
|
||||
default:
|
||||
reg108 &= ~0x07;
|
||||
break; //default to positive single ended case
|
||||
}
|
||||
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS1,
|
||||
reg108); //Input receiver settings (single ended or differential clock inputs)
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS2,
|
||||
reg109); //Input receiver settings
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS3,
|
||||
0x0A); //Reference selection mode
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_FASTLOCK,
|
||||
0x00); //Disable Fast lock
|
||||
|
||||
/**********************************************************************
|
||||
* Configure PLL2
|
||||
**********************************************************************
|
||||
*/
|
||||
pll2_Bdiv = device->pll2Settings->totalNdiv / 4;
|
||||
pll2_Adiv = device->pll2Settings->totalNdiv % 4;
|
||||
|
||||
if (pll2_Adiv > 3) { //A div valid range (0 to 3)
|
||||
return FAILURE;
|
||||
}
|
||||
if (pll2_Bdiv < 3 || pll2_Bdiv > 63) {
|
||||
return FAILURE;
|
||||
}
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CHARGEPUMP,
|
||||
0xE6); //PLL2 Charge Pump[7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_N_DIV,
|
||||
((pll2_Adiv & 0x3) << 6) | (pll2_Bdiv & 0x3F)); //PLL2 A and B divider
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CTRL, 0x03); //PLL2 control
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_CTRL, 0x01); //Manual VCO CAL
|
||||
|
||||
if (device->pll2Settings->rfDivider < 3
|
||||
|| device->pll2Settings->rfDivider > 5) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_DIV,
|
||||
device->pll2Settings->rfDivider); //VCO divider
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL1,
|
||||
0x3A); //PLL2 Loop filter [7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL2,
|
||||
0x00); //PLL2 Loop filter [8]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_RDIV, 0x01); //R divider
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_CHDIV,
|
||||
(device->pll2Settings->totalNdiv / device->pll2Settings->rfDivider)
|
||||
-1 ); //Replica channel divider: Ndivider = rfDivider * R divider
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_DIV_PHASE,
|
||||
0x00); //Replica Channel Divider phase
|
||||
|
||||
/**********************************************************************
|
||||
* Configure Output Distribution
|
||||
**********************************************************************
|
||||
*/
|
||||
for (i=0; i<14; i=i+1) {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL1 + j,
|
||||
((device->outputSettings->outSource[i] & 0x7) << 5) |
|
||||
(device->outputSettings->outAnalogDelay[i] & 0x1F));
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL2 + j,
|
||||
((device->outputSettings->outBufferCtrl[i] & 0x3) << 6) |
|
||||
(device->outputSettings->outDigitalDelay[i] & 0x3F));
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CHDIV + j,
|
||||
device->outputSettings->outChannelDiv[i]-1);
|
||||
j = j+3;
|
||||
}
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_OUTPUT_SYNC, 0x00); //Sync outputs
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC1, 0x00); //Mask SYNC[7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC2, 0x00); //Mask SYNC[13:8]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL1,
|
||||
0x00); //Bypass SYSREF resample [6:0], bit0:Enable VCXO to feed output distrubution
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL2,
|
||||
0x00); //Bypass SYSREF resample [13:7]
|
||||
|
||||
/**********************************************************************
|
||||
* Configure SYSREF operation
|
||||
**********************************************************************
|
||||
*/
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_LSB,
|
||||
device->sysrefSettings->sysrefDivide & 0xFF); //SYSREF divider [7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_MSB,
|
||||
(device->sysrefSettings->sysrefDivide >> 8) & 0xFF); //SYSREF divider [7:0]
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL3,
|
||||
((device->sysrefSettings->sysrefRequestMethod & 0x1) << 7) |
|
||||
((device->sysrefSettings->sysrefPinEdgeMode & 0x3) << 5) );
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4,
|
||||
((device->sysrefSettings->sysrefSource & 0x03) << 6) |
|
||||
((device->sysrefSettings->sysrefPatternMode & 0x3) << 4 ) |
|
||||
((device->sysrefSettings->sysrefNshotMode & 0x7) << 1) );
|
||||
|
||||
if(device->sysrefSettings->sysrefPinBufferMode == DISABLED) {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
|
||||
0x04); //power down input buffer for external SYSREF
|
||||
} else if(device->sysrefSettings->sysrefPinBufferMode == SINGLE_ENDED) {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
|
||||
0x00); //enable positive singled ended input
|
||||
} else if(device->sysrefSettings->sysrefPinBufferMode == NEG_SINGLE_ENDED) {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
|
||||
0x02); //enable negative singled ended input
|
||||
} else if(device->sysrefSettings->sysrefPinBufferMode == DIFFERENTIAL) {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
|
||||
0x01); //enable differential input buffer
|
||||
} else {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5,
|
||||
0x04); //power down input buffer for external SYSREF
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Power down control
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
if (device->pll1Settings->bypassPll1 > 0) {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL,
|
||||
0x14);// power up PLL2 and output distribution, power down PLL1
|
||||
} else {
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL,
|
||||
0x10);// power up PLL1, PLL2 and output distribution
|
||||
}
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN1,
|
||||
device->outputSettings->outPowerDown & 0xFF); //power down out[7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN2,
|
||||
((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES1,
|
||||
0xFF); //LDO enable per output channel [7:0]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES2,
|
||||
0xFF); //LDO enable per output channel [15:8]
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_STATUS0_CTRL,
|
||||
0x07); //STATUS 0 outputs REFA present
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_STATUS1_CTRL,
|
||||
0x01); //STATUS 1 outputs PLL1 and PLL2 locked
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_STATUS_OE,
|
||||
0x0C);// Make Status0 and Status1 outputs after reset.
|
||||
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE,
|
||||
0x01); //IO update to make all these settings valid in the 9528
|
||||
|
||||
AD9528_setTimeout_ms(1000);
|
||||
|
||||
do {
|
||||
AD9528_spiReadByte(device, AD9528_ADDR_STATUS_READBACK0, ®508);
|
||||
if(AD9528_hasTimeoutExpired() > 0) {
|
||||
return FAILURE;
|
||||
}
|
||||
} while((reg508 & 0x26) != 0x26);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/// Send a SPI message to request a SYSREF pulse or continuous SYSREF from the AD9528.
|
||||
/*******************************************************************************//**
|
||||
* Requests a SYSREF from the AD9528. It will use whatever settings for SYSREF
|
||||
* that are current configured in the AD9528. This could be a single pulse,
|
||||
* multiple pulses, or continuous pulses.
|
||||
* <B>Dependencies</B>
|
||||
* - device->spiSettings
|
||||
* - device->sysrefSettings->sysrefPatternMode
|
||||
*
|
||||
* \param device is structure pointer to AD9528 clock device structure
|
||||
* \param enableSYSREF If NSHOT SYSREF mode, this parameter is ignored. If PRBS/CONTINUOUS SYSREF mode, 1= enable SYSREF, 0= disable SYSREF.
|
||||
*
|
||||
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
|
||||
***********************************************************************************/
|
||||
int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF)
|
||||
{
|
||||
uint8_t _enableSYSREF=0;
|
||||
|
||||
if (device->sysrefSettings->sysrefPatternMode == NSHOT || enableSYSREF > 0) {
|
||||
_enableSYSREF = 1;
|
||||
} else {
|
||||
_enableSYSREF = 0;
|
||||
}
|
||||
|
||||
AD9528_spiWriteField(device, AD9528_ADDR_SYSREF_CTRL4, _enableSYSREF, 0x01,
|
||||
0x00); //Set SPI SYSREF request bit
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE,
|
||||
0x01); //IO update to make all these settings valid in the 9528
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/// Allow changing the 9528 SYSREF frequency and pattern mode(CONTINUOUS, PRBS vs NSHOT mode)
|
||||
/*******************************************************************************//**
|
||||
* NOTE: this function will update the device structure with the parameter values passed
|
||||
* into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode,
|
||||
* and device->sysrefSettings->sysrefDivide values will be updated in the device structure.
|
||||
*
|
||||
* <B>Dependencies</B>
|
||||
* - device->spiSettings
|
||||
*
|
||||
* \param device is structure pointer to AD9528 clock device structure
|
||||
* \param divideFromPll1Out Sets the SYSREF pulse frequency. SYSREF frequency = PLL1_VCXO frequency/divideFromPll1Out
|
||||
* \param sysrefPatternMode Valid settings: NSHOT, CONTINUOUS, PRBS, STOP
|
||||
* \param nShotPulses Valid settings: ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5
|
||||
*
|
||||
* \return Returns enum ADI_ERR, 0=pass, >0 = fail
|
||||
***********************************************************************************/
|
||||
int32_t AD9528_setupSYSREF(ad9528Device_t *device,
|
||||
uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode,
|
||||
sysrefNshotMode_t nShotPulses)
|
||||
{
|
||||
uint8_t reg403=0;
|
||||
|
||||
device->sysrefSettings->sysrefPatternMode = sysrefPatternMode;
|
||||
device->sysrefSettings->sysrefNshotMode = nShotPulses;
|
||||
device->sysrefSettings->sysrefDivide = divideFromPll1Out >>
|
||||
1; //SYSREF frequency is (PLL1)VCXO frequency / 2 / device->sysrefSettings->sysrefDivide
|
||||
|
||||
AD9528_spiReadByte(device, AD9528_ADDR_SYSREF_CTRL4, ®403);
|
||||
|
||||
reg403 = reg403 & ~0x01; //clear bit 0 to stop a continuous sysref if it is on.
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, reg403);
|
||||
|
||||
reg403 = reg403 & ~0x3E; //clear bits for pattern mode and Nshot mode bitfields
|
||||
reg403 = reg403 | ((sysrefPatternMode & 0x3) << 4) | ((nShotPulses & 0x7) << 1);
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4,
|
||||
reg403); //update internal sysref pattern mode and Nshot mode (number of pulses)
|
||||
|
||||
//SYSREF request bit x403[0] is left 0. The next call to AD9528_requestSysref will start the SYSREF
|
||||
AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE,
|
||||
0x01); //IO update to make all these settings valid in the 9528
|
||||
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int32_t AD9528_sysrefReq(ad9528Device_t *device,
|
||||
ad9528SysrefReqMode_t mode)
|
||||
{
|
||||
if (mode == SYSREF_CONT_ON)
|
||||
gpio_direction_output(device->gpio_sysref_req, 1);
|
||||
else if (mode == SYSREF_CONT_OFF)
|
||||
gpio_direction_output(device->gpio_sysref_req, 0);
|
||||
else if (mode == SYSREF_PULSE) {
|
||||
gpio_direction_output(device->gpio_sysref_req, 1);
|
||||
mdelay(1);
|
||||
gpio_direction_output(device->gpio_sysref_req, 0);
|
||||
} else
|
||||
return FAILURE;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Free the allocated resources
|
||||
*/
|
||||
int32_t AD9528_remove(ad9528Device_t *device)
|
||||
{
|
||||
int32_t status;
|
||||
|
||||
status = gpio_remove(device->gpio_resetb);
|
||||
status |= gpio_remove(device->gpio_sysref_req);
|
||||
status |= spi_remove(device->spi_desc);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* \file ad9528.h
|
||||
* \brief Contains function declarations and ad9528Device_t structure typedef for ad9528.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* \page Disclaimer Legal Disclaimer
|
||||
* Copyright 2015-2017 Analog Devices Inc.
|
||||
* Released under the AD9371 API license.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AD9528_H_
|
||||
#define _AD9528_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* AD9528 SPI Address defines */
|
||||
#define AD9528_ADDR_ADI_SPI_CONFIG_A 0x000
|
||||
#define AD9528_ADDR_ADI_SPI_CONFIG_B 0x001
|
||||
#define AD9528_ADDR_IO_UPDATE 0x00F
|
||||
|
||||
#define AD9528_ADDR_REF_A_DIVIDER_LSB 0x100
|
||||
#define AD9528_ADDR_REF_A_DIVIDER_MSB 0x101
|
||||
#define AD9528_ADDR_REF_B_DIVIDER_LSB 0x102
|
||||
#define AD9528_ADDR_REF_B_DIVIDER_MSB 0x103
|
||||
#define AD9528_ADDR_PLL1_N_DIV_LSB 0x104
|
||||
#define AD9528_ADDR_PLL1_N_DIV_MSB 0x105
|
||||
#define AD9528_ADDR_PLL1_CHARGEPUMP 0x106
|
||||
#define AD9528_ADDR_PLL1_CP_CTRL2 0x107
|
||||
#define AD9528_ADDR_INPUT_RECEIVERS1 0x108
|
||||
#define AD9528_ADDR_INPUT_RECEIVERS2 0x109
|
||||
#define AD9528_ADDR_INPUT_RECEIVERS3 0x10A
|
||||
#define AD9528_ADDR_PLL1_FASTLOCK 0x10B
|
||||
|
||||
#define AD9528_ADDR_PLL2_CHARGEPUMP 0x200
|
||||
#define AD9528_ADDR_PLL2_N_DIV 0x201
|
||||
#define AD9528_ADDR_PLL2_CTRL 0x202
|
||||
#define AD9528_ADDR_PLL2_VCO_CTRL 0x203
|
||||
#define AD9528_ADDR_PLL2_VCO_DIV 0x204
|
||||
#define AD9528_ADDR_PLL2_LF_CTRL1 0x205
|
||||
#define AD9528_ADDR_PLL2_LF_CTRL2 0x206
|
||||
#define AD9528_ADDR_PLL2_RDIV 0x207
|
||||
#define AD9528_ADDR_PLL2_REPLICA_CHDIV 0x208
|
||||
#define AD9528_ADDR_PLL2_REPLICA_DIV_PHASE 0x209
|
||||
|
||||
#define AD9528_ADDR_CH_OUT0_CTRL1 0x300
|
||||
#define AD9528_ADDR_CH_OUT0_CTRL2 0x301
|
||||
#define AD9528_ADDR_CH_OUT0_CHDIV 0x302
|
||||
#define AD9528_ADDR_OUTPUT_SYNC 0x32A
|
||||
#define AD9528_ADDR_MASK_SYNC1 0x32B
|
||||
#define AD9528_ADDR_MASK_SYNC2 0x32C
|
||||
#define AD9528_ADDR_EN_OUTPUT_PATH_SEL1 0x32D
|
||||
#define AD9528_ADDR_EN_OUTPUT_PATH_SEL2 0x32E
|
||||
|
||||
#define AD9528_ADDR_SYSERF_DIV_LSB 0x400
|
||||
#define AD9528_ADDR_SYSERF_DIV_MSB 0x401
|
||||
#define AD9528_ADDR_SYSREF_CTRL3 0x402
|
||||
#define AD9528_ADDR_SYSREF_CTRL4 0x403
|
||||
#define AD9528_ADDR_SYSREF_CTRL5 0x404
|
||||
|
||||
#define AD9528_ADDR_POWERDOWN_CTRL 0x500
|
||||
#define AD9528_ADDR_CH_POWERDOWN1 0x501
|
||||
#define AD9528_ADDR_CH_POWERDOWN2 0x502
|
||||
#define AD9528_ADDR_LDO_ENABLES1 0x503
|
||||
#define AD9528_ADDR_LDO_ENABLES2 0x504
|
||||
#define AD9528_ADDR_STATUS0_CTRL 0x505
|
||||
#define AD9528_ADDR_STATUS1_CTRL 0x506
|
||||
#define AD9528_ADDR_STATUS_OE 0x507
|
||||
#define AD9528_ADDR_STATUS_READBACK0 0x508
|
||||
#define AD9528_ADDR_STATUS_READBACK1 0x509
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
///Enum to select what source outputs from each AD9528 output channel
|
||||
typedef enum {
|
||||
AD9528_CHANNEL_DIV = 0, PLL1_OUTPUT = 1, //VCXO frequency
|
||||
SYSREF = 2,
|
||||
INV_PLL1_OUTPUT = 5 //VCXO inverted
|
||||
} ad9528outSourceSel_t;
|
||||
|
||||
///Enum to select what output buffer standard is used for the clock outputs
|
||||
typedef enum {
|
||||
AD9528_LVDS = 0, AD9528_LVDS_BOOST = 1, AD9528_HSTL = 2
|
||||
} ad9528outBufferControl_t;
|
||||
|
||||
///Enum to select the clock input buffer mode.
|
||||
typedef enum {
|
||||
DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
|
||||
} ad9528RefBuffer_t;
|
||||
|
||||
/// Structure to hold AD9528 PLL1 settings
|
||||
typedef struct {
|
||||
uint32_t refA_Frequency_Hz;
|
||||
uint16_t refA_Divider;
|
||||
ad9528RefBuffer_t refA_bufferCtrl;
|
||||
|
||||
uint32_t refB_Frequency_Hz;
|
||||
uint16_t refB_Divider;
|
||||
ad9528RefBuffer_t refB_bufferCtrl;
|
||||
|
||||
uint32_t vcxo_Frequency_Hz;
|
||||
ad9528RefBuffer_t vcxoBufferCtrl;
|
||||
|
||||
uint16_t nDivider;
|
||||
uint8_t bypassPll1;
|
||||
} ad9528pll1Settings_t;
|
||||
|
||||
/// Structure to hold AD9528 PLL2 settings
|
||||
typedef struct {
|
||||
uint8_t rfDivider; //VCO divider: Valid range (3,4,5)
|
||||
uint8_t n2Divider; //PLL2 N2 Divider
|
||||
uint8_t totalNdiv; //NDiv = 4*Bdiv + Adiv //Bdiv valid range (3 to 63), Adiv valid range (0-3)
|
||||
} ad9528pll2Settings_t;
|
||||
|
||||
/// Structure to hold AD9528 Output Clock settings
|
||||
typedef struct {
|
||||
uint16_t outPowerDown; //bit per output, if 1 power down that output.
|
||||
ad9528outSourceSel_t
|
||||
outSource[14]; //CHANNEL_DIV, PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT
|
||||
ad9528outBufferControl_t outBufferCtrl[14]; //LVDS, LVDS_BOOST, HSTL
|
||||
uint8_t outAnalogDelay[14]; //5 bits
|
||||
uint8_t outDigitalDelay[14]; //6 bits, 1/2 clock resolution @ channel div input frequency
|
||||
uint8_t outChannelDiv[14]; //8 bit channel divider
|
||||
uint32_t outFrequency_Hz[14]; //output clock frequency per clock output
|
||||
} ad9528outputSettings_t;
|
||||
|
||||
///Enum to select the SYSREF output source
|
||||
typedef enum {
|
||||
EXTERNAL = 0, EXT_RESAMPLED = 1, INTERNAL = 2
|
||||
} sysrefSourceSelection_t;
|
||||
|
||||
///Enum to choose the SYSREF pattern mode.
|
||||
typedef enum {
|
||||
NSHOT = 0, CONTINUOUS = 1, PRBS = 2, STOP = 3
|
||||
} sysrefPatternMode_t;
|
||||
|
||||
///Enum to select the SYSREF input pin mode.
|
||||
typedef enum {
|
||||
LEVEL_ACTIVE_HIGH = 0, LEVEL_ACTIVE_LOW = 1, RISING_EDGE = 2, FALLING_EDGE = 3
|
||||
} sysrefPinEdgeMode_t;
|
||||
|
||||
///Enum to select the SYSREF output # of pulses for NSHOT mode.
|
||||
typedef enum {
|
||||
ONE_PULSE = 0, TWO_PULSES = 2, FOUR_PULSES = 3, SIX_PULSES = 4, EIGHT_PULSES = 5
|
||||
} sysrefNshotMode_t;
|
||||
|
||||
//Enum to select how a SYSREF is requested.
|
||||
typedef enum {
|
||||
SPI = 0, PIN = 1
|
||||
} sysrefRequestMethod_t;
|
||||
|
||||
/// Structure to hold AD9528 SYSREF output settings
|
||||
typedef struct {
|
||||
sysrefRequestMethod_t sysrefRequestMethod;
|
||||
sysrefSourceSelection_t sysrefSource;
|
||||
sysrefPinEdgeMode_t sysrefPinEdgeMode;
|
||||
ad9528RefBuffer_t sysrefPinBufferMode;
|
||||
sysrefPatternMode_t sysrefPatternMode;
|
||||
sysrefNshotMode_t sysrefNshotMode;
|
||||
uint16_t sysrefDivide;
|
||||
|
||||
} ad9528sysrefSettings_t;
|
||||
|
||||
/// Structure to hold AD9528 SPI settings
|
||||
typedef struct {
|
||||
uint8_t chipSelectIndex; ///< valid 1~8
|
||||
uint8_t writeBitPolarity; ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation
|
||||
uint8_t longInstructionWord; ///< 1 = 16bit instruction word, 0 = 8bit instruction word
|
||||
uint8_t MSBFirst; ///< 1 = MSBFirst, 0 = LSBFirst
|
||||
uint8_t CPHA; ///< clock phase, sets which clock edge the data updates (valid 0 or 1)
|
||||
uint8_t CPOL; ///< clock polarity 0 = clock starts low, 1 = clock starts high
|
||||
uint8_t enSpiStreaming; ///< Not implemented. SW feature to improve SPI throughput.
|
||||
uint8_t autoIncAddrUp; ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1
|
||||
uint8_t fourWireMode; ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode.
|
||||
uint32_t spiClkFreq_Hz; ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */
|
||||
} ad9528spiSettings_t;
|
||||
|
||||
/// Structure to hold AD9528 settings
|
||||
typedef struct {
|
||||
struct gpio_desc *gpio_resetb;
|
||||
struct gpio_desc *gpio_sysref_req;
|
||||
struct spi_desc *spi_desc;
|
||||
ad9528spiSettings_t *spiSettings;
|
||||
ad9528pll1Settings_t *pll1Settings;
|
||||
ad9528pll2Settings_t *pll2Settings;
|
||||
ad9528outputSettings_t *outputSettings;
|
||||
ad9528sysrefSettings_t *sysrefSettings;
|
||||
} ad9528Device_t;
|
||||
|
||||
typedef struct {
|
||||
struct gpio_init_param *gpio_init_resetb;
|
||||
struct gpio_init_param *gpio_init_sysref_req;
|
||||
struct spi_init_param *spi_init;
|
||||
ad9528spiSettings_t *spiSettings;
|
||||
ad9528pll1Settings_t *pll1Settings;
|
||||
ad9528pll2Settings_t *pll2Settings;
|
||||
ad9528outputSettings_t *outputSettings;
|
||||
ad9528sysrefSettings_t *sysrefSettings;
|
||||
} ad9528Init_t;
|
||||
|
||||
typedef enum {
|
||||
SYSREF_CONT_ON,
|
||||
SYSREF_CONT_OFF,
|
||||
SYSREF_PULSE,
|
||||
} ad9528SysrefReqMode_t;
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
//Helper function to setup the 9528 device data structure specifically for the ADI transceiver evaluation cards
|
||||
int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device,
|
||||
uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz,
|
||||
uint32_t outputDeviceClock_Hz);
|
||||
int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr,
|
||||
uint8_t *readdata);
|
||||
|
||||
//AD9528 API functions
|
||||
int32_t AD9528_hasTimeoutExpired();
|
||||
int32_t AD9528_resetDevice(ad9528Device_t *device);
|
||||
int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device);
|
||||
int32_t AD9528_config(ad9528Device_t
|
||||
*device); //writes all registers to desired values, leaves clock outputs off.
|
||||
int32_t AD9528_setupSYSREF(ad9528Device_t *device,
|
||||
uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode,
|
||||
sysrefNshotMode_t nShotPulses);
|
||||
int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF);
|
||||
int32_t AD9528_sysrefReq(ad9528Device_t *device,
|
||||
ad9528SysrefReqMode_t mode);
|
||||
int32_t AD9528_remove(ad9528Device_t *device);
|
||||
|
||||
#endif
|
||||
+927
@@ -0,0 +1,927 @@
|
||||
/***************************************************************************//**
|
||||
* @file hmc7044.c
|
||||
* @brief Implementation of HMC7044, HMC7043 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2018-2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "hmc7044.h"
|
||||
#include "../../../include/error.h"
|
||||
#include "../../../include/util.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
#define HMC7044_WRITE (0 << 15)
|
||||
#define HMC7044_READ (1 << 15)
|
||||
#define HMC7044_CNT(x) (((x) - 1) << 13)
|
||||
#define HMC7044_ADDR(x) ((x) & 0xFFF)
|
||||
|
||||
/* Global Control */
|
||||
#define HMC7044_REG_SOFT_RESET 0x0000
|
||||
#define HMC7044_SOFT_RESET BIT(0)
|
||||
|
||||
#define HMC7044_REG_REQ_MODE_0 0x0001
|
||||
#define HMC7044_RESEED_REQ BIT(7)
|
||||
#define HMC7044_HIGH_PERF_DISTRIB_PATH BIT(6)
|
||||
#define HMC7044_HIGH_PERF_PLL_VCO BIT(5)
|
||||
#define HMC7044_FORCE_HOLDOVER BIT(4)
|
||||
#define HMC7044_MUTE_OUT_DIV BIT(3)
|
||||
#define HMC7044_PULSE_GEN_REQ BIT(2)
|
||||
#define HMC7044_RESTART_DIV_FSM BIT(1)
|
||||
#define HMC7044_SLEEP_MODE BIT(0)
|
||||
|
||||
#define HMC7044_REG_REQ_MODE_1 0x0002
|
||||
#define HMC7044_PLL2_AUTOTUNE_TRIG BIT(2)
|
||||
#define HMC7044_SLIP_REQ BIT(1)
|
||||
|
||||
#define HMC7044_REG_EN_CTRL_0 0x0003
|
||||
#define HMC7044_RF_RESEEDER_EN BIT(5)
|
||||
#define HMC7044_VCO_SEL(x) (((x) & 0x3) << 3)
|
||||
#define HMC7044_VCO_EXT 0
|
||||
#define HMC7044_VCO_HIGH 1
|
||||
#define HMC7044_VCO_LOW 2
|
||||
#define HMC7044_SYSREF_TIMER_EN BIT(2)
|
||||
#define HMC7044_PLL2_EN BIT(1)
|
||||
#define HMC7044_PLL1_EN BIT(0)
|
||||
|
||||
#define HMC7044_REG_EN_CTRL_1 0x0004
|
||||
#define HMC7044_SEVEN_PAIRS(x) ((x) & 0x7f)
|
||||
|
||||
#define HMC7044_REG_GLOB_MODE 0x0005
|
||||
#define HMC7044_REF_PATH_EN(x) ((x) & 0xf)
|
||||
#define HMC7044_RFSYNC_EN BIT(4)
|
||||
#define HMC7044_VCOIN_MODE_EN BIT(5)
|
||||
#define HMC7044_SYNC_PIN_MODE(x) (((x) & 0x3) << 6)
|
||||
|
||||
/* PLL1 */
|
||||
#define HMC7044_REG_CLKIN0_BUF_CTRL 0x000A
|
||||
#define HMC7044_REG_CLKIN1_BUF_CTRL 0x000B
|
||||
#define HMC7044_REG_CLKIN2_BUF_CTRL 0x000C
|
||||
#define HMC7044_REG_CLKIN3_BUF_CTRL 0x000D
|
||||
#define HMC7044_REG_OSCIN_BUF_CTRL 0x000E
|
||||
|
||||
#define HMC7044_REG_PLL1_REF_PRIO_CTRL 0x0014
|
||||
|
||||
#define HMC7044_HIGH_Z_EN BIT(4)
|
||||
#define HMC7044_LVPECL_EN BIT(3)
|
||||
#define HMC7044_AC_COUPLING_EN BIT(2)
|
||||
#define HMC7044_100_OHM_EN BIT(1)
|
||||
#define HMC7044_BUF_EN BIT(0)
|
||||
|
||||
#define HMC7044_REG_CLKIN_PRESCALER(x) (0x001C + (x))
|
||||
#define HMC7044_REG_OSCIN_PRESCALER 0x0020
|
||||
|
||||
#define HMC7044_REG_PLL1_R_LSB 0x0021
|
||||
#define HMC7044_R1_LSB(x) ((x) & 0xff)
|
||||
|
||||
#define HMC7044_REG_PLL1_R_MSB 0x0022
|
||||
#define HMC7044_R1_MSB(x) (((x) & 0xff00) >> 8)
|
||||
|
||||
#define HMC7044_REG_PLL1_N_LSB 0x0026
|
||||
#define HMC7044_N1_LSB(x) ((x) & 0xff)
|
||||
|
||||
#define HMC7044_REG_PLL1_N_MSB 0x0027
|
||||
#define HMC7044_N1_MSB(x) (((x) & 0xff00) >> 8)
|
||||
|
||||
#define HMC7044_REG_PLL1_LOCK_DETECT 0x0028
|
||||
#define HMC7044_LOCK_DETECT_SLIP BIT(5)
|
||||
#define HMC7044_LOCK_DETECT_TIMER(x) ((x) & 0x1f)
|
||||
|
||||
/* PLL2 */
|
||||
#define HMC7044_REG_PLL2_FREQ_DOUBLER 0x0032
|
||||
#define HMC7044_PLL2_FREQ_DOUBLER_DIS BIT(0)
|
||||
|
||||
#define HMC7044_REG_PLL2_R_LSB 0x0033
|
||||
#define HMC7044_R2_LSB(x) ((x) & 0xff)
|
||||
|
||||
#define HMC7044_REG_PLL2_R_MSB 0x0034
|
||||
#define HMC7044_R2_MSB(x) (((x) & 0xf00) >> 8)
|
||||
|
||||
#define HMC7044_REG_PLL2_N_LSB 0x0035
|
||||
#define HMC7044_N2_LSB(x) ((x) & 0xff)
|
||||
|
||||
#define HMC7044_REG_PLL2_N_MSB 0x0036
|
||||
#define HMC7044_N2_MSB(x) (((x) & 0xff00) >> 8)
|
||||
|
||||
#define HMC7044_REG_OSCOUT_PATH 0x0039
|
||||
#define HMC7044_REG_OSCOUT_DRIVER_0 0x003A
|
||||
#define HMC7044_REG_OSCOUT_DRIVER_1 0x003B
|
||||
|
||||
/* GPIO/SDATA Control */
|
||||
#define HMC7044_REG_GPI_CTRL(x) (0x0046 + (x))
|
||||
#define HMC7044_REG_GPI_SEL(x) ((x) & 0xf)
|
||||
|
||||
#define HMC7044_REG_GPO_CTRL(x) (0x0050 + (x))
|
||||
#define HMC7044_GPO_SEL(x) (((x) & 0x3f) << 2)
|
||||
#define HMC7044_GPO_MODE BIT(1)
|
||||
#define HMC7044_GPO_EN BIT(0)
|
||||
|
||||
/* SYSREF/SYNC Control */
|
||||
#define HMC7044_REG_PULSE_GEN 0x005A
|
||||
#define HMC7044_PULSE_GEN_MODE(x) ((x) & 0x7)
|
||||
|
||||
#define HMC7044_REG_SYNC 0x005B
|
||||
#define HMC7044_SYNC_RETIME BIT(2)
|
||||
#define HMC7044_SYNC_THROUGH_PLL2 BIT(1)
|
||||
#define HMC7044_SYNC_POLARITY BIT(0)
|
||||
|
||||
#define HMC7044_REG_SYSREF_TIMER_LSB 0x005C
|
||||
#define HMC7044_SYSREF_TIMER_LSB(x) ((x) & 0xff)
|
||||
|
||||
#define HMC7044_REG_SYSREF_TIMER_MSB 0x005D
|
||||
#define HMC7044_SYSREF_TIMER_MSB(x) (((x) & 0xf00) >> 8)
|
||||
|
||||
#define HMC7044_CLK_INPUT_CTRL 0x0064
|
||||
#define HMC7044_LOW_FREQ_INPUT_MODE BIT(0)
|
||||
#define HMC7044_DIV_2_INPUT_MODE BIT(1)
|
||||
|
||||
/* Status and Alarm readback */
|
||||
#define HMC7044_REG_ALARM_READBACK 0x007D
|
||||
#define HMC7044_REG_PLL1_STATUS 0x0082
|
||||
|
||||
#define HMC7044_PLL1_FSM_STATE(x) ((x) & 0x7)
|
||||
#define HMC7044_PLL1_ACTIVE_CLKIN(x) (((x) >> 3) & 0x3)
|
||||
|
||||
#define HMC7044_PLL2_LOCK_DETECT(x) ((x) & 0x1)
|
||||
#define HMC7044_SYSREF_SYNC_STAT(x) ((x) & 0x2)
|
||||
#define HMC7044_CLK_OUT_PH_STATUS(x) ((x) & 0x4)
|
||||
#define HMC7044_PLL1_PLL2_LOCK_STAT(x) ((x) & 0x8)
|
||||
#define HMC7044_SYNC_REQ_STATUS(x) ((x) & 0x10)
|
||||
|
||||
/* Other Controls */
|
||||
#define HMC7044_REG_CLK_OUT_DRV_LOW_PW 0x009F
|
||||
#define HMC7044_REG_CLK_OUT_DRV_HIGH_PW 0x00A0
|
||||
#define HMC7044_REG_PLL1_DELAY 0x00A5
|
||||
#define HMC7044_REG_PLL1_HOLDOVER 0x00A8
|
||||
#define HMC7044_REG_VTUNE_PRESET 0x00B0
|
||||
|
||||
/* Clock Distribution */
|
||||
#define HMC7044_REG_CH_OUT_CRTL_0(ch) (0x00C8 + 0xA * (ch))
|
||||
#define HMC7044_HI_PERF_MODE BIT(7)
|
||||
#define HMC7044_SYNC_EN BIT(6)
|
||||
#define HMC7044_CH_EN BIT(0)
|
||||
#define HMC7044_START_UP_MODE_DYN_EN (BIT(3) | BIT(2))
|
||||
|
||||
#define HMC7044_REG_CH_OUT_CRTL_1(ch) (0x00C9 + 0xA * (ch))
|
||||
#define HMC7044_DIV_LSB(x) ((x) & 0xFF)
|
||||
|
||||
#define HMC7044_REG_CH_OUT_CRTL_2(ch) (0x00CA + 0xA * (ch))
|
||||
#define HMC7044_DIV_MSB(x) (((x) >> 8) & 0xFF)
|
||||
|
||||
#define HMC7044_REG_CH_OUT_CRTL_3(ch) (0x00CB + 0xA * (ch))
|
||||
#define HMC7044_REG_CH_OUT_CRTL_4(ch) (0x00CC + 0xA * (ch))
|
||||
#define HMC7044_REG_CH_OUT_CRTL_5(ch) (0x00CD + 0xA * (ch))
|
||||
#define HMC7044_REG_CH_OUT_CRTL_6(ch) (0x00CE + 0xA * (ch))
|
||||
#define HMC7044_REG_CH_OUT_CRTL_7(ch) (0x00CF + 0xA * (ch))
|
||||
|
||||
#define HMC7044_REG_CH_OUT_CRTL_8(ch) (0x00D0 + 0xA * (ch))
|
||||
#define HMC7044_DRIVER_MODE(x) (((x) & 0x3) << 3)
|
||||
#define HMC7044_DRIVER_Z_MODE(x) (((x) & 0x3) << 0)
|
||||
#define HMC7044_DYN_DRIVER_EN BIT(5)
|
||||
#define HMC7044_FORCE_MUTE_EN BIT(7)
|
||||
|
||||
#define HMC7044_NUM_CHAN 14
|
||||
|
||||
#define HMC7044_LOW_VCO_MIN 2150000
|
||||
#define HMC7044_LOW_VCO_MAX 2880000
|
||||
#define HMC7044_HIGH_VCO_MIN 2650000
|
||||
#define HMC7044_HIGH_VCO_MAX 3200000
|
||||
|
||||
#define HMC7044_RECOMM_LCM_MIN 30000
|
||||
#define HMC7044_RECOMM_LCM_MAX 70000
|
||||
#define HMC7044_RECOMM_FPD1 10000
|
||||
|
||||
#define HMC7044_R1_MAX 65535
|
||||
#define HMC7044_N1_MAX 65535
|
||||
|
||||
#define HMC7044_R2_MIN 1
|
||||
#define HMC7044_R2_MAX 4095
|
||||
#define HMC7044_N2_MIN 8
|
||||
#define HMC7044_N2_MAX 65535
|
||||
|
||||
#define HMC7044_OUT_DIV_MIN 1
|
||||
#define HMC7044_OUT_DIV_MAX 4094
|
||||
|
||||
/******************************************************************************/
|
||||
/************************** Functions Implementation **************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* SPI register write to device.
|
||||
* @param dev - The device structure.
|
||||
* @param reg - The register address.
|
||||
* @param val - The register data.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t hmc7044_write(struct hmc7044_dev *dev,
|
||||
uint16_t reg,
|
||||
uint8_t val)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
uint16_t cmd;
|
||||
|
||||
cmd = HMC7044_WRITE | HMC7044_CNT(1) | HMC7044_ADDR(reg);
|
||||
buf[0] = cmd >> 8;
|
||||
buf[1] = cmd & 0xFF;
|
||||
buf[2] = val;
|
||||
return spi_write_and_read_3wire(dev->spi_desc, buf, NULL,
|
||||
ARRAY_SIZE(buf), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* SPI register read from device.
|
||||
* @param dev - The device structure.
|
||||
* @param reg - The register address.
|
||||
* @param val - The register data.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
|
||||
int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val)
|
||||
{
|
||||
uint8_t wr_buf[2];
|
||||
uint8_t rd_data[1];
|
||||
uint16_t cmd;
|
||||
int ret;
|
||||
|
||||
cmd = HMC7044_READ | HMC7044_CNT(1) | HMC7044_ADDR(reg);
|
||||
wr_buf[0] = cmd >> 8;
|
||||
wr_buf[1] = cmd & 0xFF;
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc, wr_buf, rd_data,
|
||||
ARRAY_SIZE(wr_buf), ARRAY_SIZE(rd_data));
|
||||
if (ret != SUCCESS)
|
||||
return ret;
|
||||
|
||||
*val = rd_data[0];
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the output channel divider.
|
||||
* @param rate - The desired rate.
|
||||
* @param parent_rate - The parent rate.
|
||||
* @return The output divider.
|
||||
*/
|
||||
uint32_t hmc7044_calc_out_div(uint32_t rate,
|
||||
uint32_t parent_rate)
|
||||
{
|
||||
uint32_t div;
|
||||
|
||||
div = DIV_ROUND_CLOSEST(parent_rate, rate);
|
||||
|
||||
/* Supported odd divide ratios are 1, 3, and 5 */
|
||||
if ((div != 1) && (div != 3) && (div != 5) && (div % 2))
|
||||
div = DIV_ROUND_CLOSEST(parent_rate, rate * 2) * 2;
|
||||
|
||||
div = clamp_t(unsigned int,
|
||||
div,
|
||||
HMC7044_OUT_DIV_MIN,
|
||||
HMC7044_OUT_DIV_MAX);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate rate corresponding to a channel.
|
||||
* @param dev - The device structure.
|
||||
* @param chan_num - Channel number.
|
||||
* @param rate - Channel rate.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num,
|
||||
uint64_t *rate)
|
||||
{
|
||||
int i;
|
||||
struct hmc7044_chan_spec *chan = NULL;
|
||||
|
||||
/* Find the reqested channel number */
|
||||
for (i = 0; i < dev->num_channels; i++) {
|
||||
if (dev->channels[i].num == chan_num) {
|
||||
chan = &dev->channels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chan == NULL )
|
||||
return FAILURE;
|
||||
|
||||
*rate = dev->pll2_freq / chan->divider;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate closest possible rate
|
||||
* @param dev - The device structure
|
||||
* @param rate - The desired rate.
|
||||
* @param rounded_rate - The closest possible rate of desired rate.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate,
|
||||
uint64_t *rounded_rate)
|
||||
{
|
||||
uint32_t div = hmc7044_calc_out_div(rate, dev->pll2_freq);
|
||||
|
||||
*rounded_rate = DIV_ROUND_CLOSEST(dev->pll2_freq, div);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel rate.
|
||||
* @param dev - The device structure.
|
||||
* @param chan_num - Channel number.
|
||||
* @param rate - Channel rate.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num,
|
||||
uint64_t rate)
|
||||
{
|
||||
uint32_t div;
|
||||
int32_t ret;
|
||||
int i;
|
||||
struct hmc7044_chan_spec *chan = NULL;
|
||||
|
||||
/* Find the reqested channel number */
|
||||
for (i = 0; i < dev->num_channels; i++) {
|
||||
if (dev->channels[i].num == chan_num) {
|
||||
chan = &dev->channels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chan == NULL )
|
||||
return FAILURE;
|
||||
|
||||
div = hmc7044_calc_out_div(rate, dev->pll2_freq);
|
||||
chan->divider = div;
|
||||
|
||||
ret = hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num),
|
||||
HMC7044_DIV_LSB(div));
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
|
||||
return hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num),
|
||||
HMC7044_DIV_MSB(div));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the device.
|
||||
* @param dev - The device structure.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int32_t hmc7044_setup(struct hmc7044_dev *dev)
|
||||
{
|
||||
struct hmc7044_chan_spec *chan;
|
||||
bool high_vco_en;
|
||||
bool pll2_freq_doubler_en;
|
||||
uint32_t vcxo_freq, pll2_freq;
|
||||
uint32_t clkin_freq[4];
|
||||
uint32_t lcm_freq;
|
||||
uint32_t in_prescaler[5];
|
||||
uint32_t pll1_lock_detect;
|
||||
uint32_t n1, r1;
|
||||
uint32_t pfd1_freq;
|
||||
uint32_t vco_limit;
|
||||
uint32_t n2[2], r2[2];
|
||||
uint32_t i, ref_en = 0;
|
||||
|
||||
vcxo_freq = dev->vcxo_freq / 1000;
|
||||
pll2_freq = dev->pll2_freq / 1000;
|
||||
|
||||
lcm_freq = vcxo_freq;
|
||||
for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) {
|
||||
if (dev->clkin_freq_ccf[i])
|
||||
clkin_freq[i] = dev->clkin_freq_ccf[i] / 1000;
|
||||
else
|
||||
clkin_freq[i] = dev->clkin_freq[i] / 1000;
|
||||
|
||||
if (clkin_freq[i]) {
|
||||
lcm_freq = greatest_common_divisor(clkin_freq[i], lcm_freq);
|
||||
ref_en |= BIT(i);
|
||||
}
|
||||
}
|
||||
|
||||
while (lcm_freq > HMC7044_RECOMM_LCM_MAX)
|
||||
lcm_freq /= 2;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) {
|
||||
if (clkin_freq[i])
|
||||
in_prescaler[i] = clkin_freq[i] / lcm_freq;
|
||||
else
|
||||
in_prescaler[i] = 1;
|
||||
}
|
||||
in_prescaler[4] = vcxo_freq / lcm_freq;
|
||||
|
||||
pll1_lock_detect = log_base_2((lcm_freq * 4000) / dev->pll1_loop_bw);
|
||||
|
||||
/* fVCXO / N1 = fLCM / R1 */
|
||||
rational_best_approximation(vcxo_freq, lcm_freq,
|
||||
HMC7044_N1_MAX, HMC7044_R1_MAX,
|
||||
&n1, &r1);
|
||||
|
||||
pfd1_freq = vcxo_freq / n1;
|
||||
while ((pfd1_freq > HMC7044_RECOMM_FPD1) &&
|
||||
(n1 <= HMC7044_N1_MAX / 2) &&
|
||||
(r1 <= HMC7044_R1_MAX / 2)) {
|
||||
pfd1_freq /= 2;
|
||||
n1 *= 2;
|
||||
r1 *= 2;
|
||||
}
|
||||
|
||||
dev->pll1_pfd = pfd1_freq;
|
||||
|
||||
if (pll2_freq < HMC7044_LOW_VCO_MIN ||
|
||||
pll2_freq > HMC7044_HIGH_VCO_MAX)
|
||||
return FAILURE;
|
||||
|
||||
vco_limit = (HMC7044_LOW_VCO_MAX + HMC7044_HIGH_VCO_MIN) / 2;
|
||||
if (pll2_freq >= vco_limit)
|
||||
high_vco_en = true;
|
||||
else
|
||||
high_vco_en = false;
|
||||
|
||||
/* fVCO / N2 = fVCXO * doubler / R2 */
|
||||
pll2_freq_doubler_en = true;
|
||||
rational_best_approximation(pll2_freq, vcxo_freq * 2,
|
||||
HMC7044_N2_MAX, HMC7044_R2_MAX,
|
||||
&n2[0], &r2[0]);
|
||||
|
||||
if (pll2_freq != vcxo_freq * n2[0] / r2[0]) {
|
||||
rational_best_approximation(pll2_freq, vcxo_freq,
|
||||
HMC7044_N2_MAX, HMC7044_R2_MAX,
|
||||
&n2[1], &r2[1]);
|
||||
|
||||
if (abs((int)pll2_freq - (int)(vcxo_freq * 2 * n2[0] / r2[0])) >
|
||||
abs((int)pll2_freq - (int)(vcxo_freq * n2[1] / r2[1]))) {
|
||||
n2[0] = n2[1];
|
||||
r2[0] = r2[1];
|
||||
pll2_freq_doubler_en = false;
|
||||
}
|
||||
}
|
||||
|
||||
while ((n2[0] < HMC7044_N2_MIN) && (r2[0] <= HMC7044_R2_MAX / 2)) {
|
||||
n2[0] *= 2;
|
||||
r2[0] *= 2;
|
||||
}
|
||||
if (n2[0] < HMC7044_N2_MIN)
|
||||
return -FAILURE;
|
||||
|
||||
/* Resets all registers to default values */
|
||||
hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET);
|
||||
mdelay(10);
|
||||
hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0);
|
||||
mdelay(10);
|
||||
|
||||
/* Disable all channels */
|
||||
for (i = 0; i < HMC7044_NUM_CHAN; i++)
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0);
|
||||
|
||||
/* Load the configuration updates (provided by Analog Devices) */
|
||||
hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d);
|
||||
hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf);
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_DELAY, 0x06);
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_HOLDOVER, 0x06);
|
||||
hmc7044_write(dev, HMC7044_REG_VTUNE_PRESET, 0x04);
|
||||
|
||||
uint8_t rd_back;
|
||||
hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, &rd_back);
|
||||
hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, &rd_back);
|
||||
hmc7044_read(dev, HMC7044_REG_PLL1_DELAY, &rd_back);
|
||||
hmc7044_read(dev, HMC7044_REG_PLL1_HOLDOVER, &rd_back);
|
||||
hmc7044_read(dev, HMC7044_REG_VTUNE_PRESET, &rd_back);
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_GLOB_MODE,
|
||||
HMC7044_SYNC_PIN_MODE(dev->sync_pin_mode) |
|
||||
(dev->clkin0_rfsync_en ? HMC7044_RFSYNC_EN : 0) |
|
||||
(dev->clkin1_vcoin_en ? HMC7044_VCOIN_MODE_EN : 0) |
|
||||
HMC7044_REF_PATH_EN(ref_en));
|
||||
|
||||
/* Program PLL2 */
|
||||
|
||||
/* Select the VCO range */
|
||||
hmc7044_write(dev, HMC7044_REG_EN_CTRL_0,
|
||||
(dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) |
|
||||
HMC7044_VCO_SEL(high_vco_en ?
|
||||
HMC7044_VCO_HIGH :
|
||||
HMC7044_VCO_LOW) |
|
||||
HMC7044_SYSREF_TIMER_EN | HMC7044_PLL2_EN |
|
||||
HMC7044_PLL1_EN);
|
||||
|
||||
/* Program the dividers */
|
||||
hmc7044_write(dev, HMC7044_REG_PLL2_R_LSB,
|
||||
HMC7044_R2_LSB(r2[0]));
|
||||
hmc7044_write(dev, HMC7044_REG_PLL2_R_MSB,
|
||||
HMC7044_R2_MSB(r2[0]));
|
||||
hmc7044_write(dev, HMC7044_REG_PLL2_N_LSB,
|
||||
HMC7044_N2_LSB(n2[0]));
|
||||
hmc7044_write(dev, HMC7044_REG_PLL2_N_MSB,
|
||||
HMC7044_N2_MSB(n2[0]));
|
||||
|
||||
/* Program the reference doubler */
|
||||
hmc7044_write(dev, HMC7044_REG_PLL2_FREQ_DOUBLER,
|
||||
pll2_freq_doubler_en ? 0 : HMC7044_PLL2_FREQ_DOUBLER_DIS);
|
||||
|
||||
/* Program PLL1 */
|
||||
|
||||
/* Set the lock detect timer threshold */
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_LOCK_DETECT,
|
||||
HMC7044_LOCK_DETECT_TIMER(pll1_lock_detect));
|
||||
|
||||
/* Set the LCM */
|
||||
for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) {
|
||||
hmc7044_write(dev, HMC7044_REG_CLKIN_PRESCALER(i),
|
||||
in_prescaler[i]);
|
||||
}
|
||||
hmc7044_write(dev, HMC7044_REG_OSCIN_PRESCALER,
|
||||
in_prescaler[4]);
|
||||
|
||||
/* Program the dividers */
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_R_LSB,
|
||||
HMC7044_R2_LSB(r1));
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_R_MSB,
|
||||
HMC7044_R2_MSB(r1));
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_N_LSB,
|
||||
HMC7044_N2_LSB(n1));
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_N_MSB,
|
||||
HMC7044_N2_MSB(n1));
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_PLL1_REF_PRIO_CTRL,
|
||||
dev->pll1_ref_prio_ctrl);
|
||||
|
||||
/* Program the SYSREF timer */
|
||||
|
||||
/* Set the divide ratio */
|
||||
hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB,
|
||||
HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div));
|
||||
hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB,
|
||||
HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div));
|
||||
|
||||
/* Set the pulse generator mode configuration */
|
||||
hmc7044_write(dev, HMC7044_REG_PULSE_GEN,
|
||||
HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode));
|
||||
|
||||
/* Enable the input buffers */
|
||||
hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL,
|
||||
dev->in_buf_mode[0]);
|
||||
hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL,
|
||||
dev->in_buf_mode[1]);
|
||||
hmc7044_write(dev, HMC7044_REG_CLKIN2_BUF_CTRL,
|
||||
dev->in_buf_mode[2]);
|
||||
hmc7044_write(dev, HMC7044_REG_CLKIN3_BUF_CTRL,
|
||||
dev->in_buf_mode[3]);
|
||||
hmc7044_write(dev, HMC7044_REG_OSCIN_BUF_CTRL,
|
||||
dev->in_buf_mode[4]);
|
||||
|
||||
/* Set GPIOs */
|
||||
for (i = 0; i < ARRAY_SIZE(dev->gpi_ctrl); i++) {
|
||||
hmc7044_write(dev, HMC7044_REG_GPI_CTRL(i),
|
||||
dev->gpi_ctrl[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->gpo_ctrl); i++) {
|
||||
hmc7044_write(dev, HMC7044_REG_GPO_CTRL(i),
|
||||
dev->gpo_ctrl[i]);
|
||||
}
|
||||
|
||||
mdelay(10);
|
||||
|
||||
/* Program the output channels */
|
||||
for (i = 0; i < dev->num_channels; i++) {
|
||||
chan = &dev->channels[i];
|
||||
if (chan->num >= HMC7044_NUM_CHAN || chan->disable)
|
||||
continue;
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num),
|
||||
HMC7044_DIV_LSB(chan->divider));
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num),
|
||||
HMC7044_DIV_MSB(chan->divider));
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num),
|
||||
HMC7044_DRIVER_MODE(chan->driver_mode) |
|
||||
HMC7044_DRIVER_Z_MODE(chan->driver_impedance) |
|
||||
(chan->dynamic_driver_enable ?
|
||||
HMC7044_DYN_DRIVER_EN : 0) |
|
||||
(chan->force_mute_enable ?
|
||||
HMC7044_FORCE_MUTE_EN : 0));
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num),
|
||||
chan->fine_delay & 0x1F);
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num),
|
||||
chan->coarse_delay & 0x1F);
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num),
|
||||
chan->out_mux_mode & 0x3);
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num),
|
||||
(chan->start_up_mode_dynamic_enable ?
|
||||
HMC7044_START_UP_MODE_DYN_EN : 0) |
|
||||
(chan->output_control0_rb4_enable ? BIT(4) : 0) |
|
||||
(chan->high_performance_mode_dis ?
|
||||
0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN |
|
||||
HMC7044_CH_EN);
|
||||
}
|
||||
mdelay(10);
|
||||
|
||||
/* Do a restart to reset the system and initiate calibration */
|
||||
hmc7044_write(dev, HMC7044_REG_REQ_MODE_0,
|
||||
HMC7044_RESTART_DIV_FSM);
|
||||
mdelay(1);
|
||||
hmc7044_write(dev, HMC7044_REG_REQ_MODE_0,
|
||||
(dev->high_performance_mode_clock_dist_en ?
|
||||
HMC7044_HIGH_PERF_DISTRIB_PATH : 0));
|
||||
mdelay(1);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the device.
|
||||
* @param dev - The device structure.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
static int32_t hmc7043_setup(struct hmc7044_dev *dev)
|
||||
{
|
||||
struct hmc7044_chan_spec *chan;
|
||||
uint32_t i;
|
||||
|
||||
if (dev->clkin_freq_ccf[0])
|
||||
dev->pll2_freq = dev->clkin_freq_ccf[0];
|
||||
else
|
||||
dev->pll2_freq = dev->clkin_freq[0];
|
||||
|
||||
if (!dev->pll2_freq) {
|
||||
printf("%s: Failed to get valid parent rate\n", __func__);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Resets all registers to default values */
|
||||
hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET);
|
||||
mdelay(10);
|
||||
hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0);
|
||||
mdelay(10);
|
||||
|
||||
/* Load the configuration updates (provided by Analog Devices) */
|
||||
hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d);
|
||||
hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf);
|
||||
|
||||
/* Disable all channels */
|
||||
for (i = 0; i < HMC7044_NUM_CHAN; i++)
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0);
|
||||
|
||||
if (dev->pll2_freq < 1000000000U)
|
||||
hmc7044_write(dev, HMC7044_CLK_INPUT_CTRL,
|
||||
HMC7044_LOW_FREQ_INPUT_MODE);
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_EN_CTRL_0,
|
||||
(dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) |
|
||||
HMC7044_SYSREF_TIMER_EN);
|
||||
|
||||
/* Program the SYSREF timer */
|
||||
|
||||
/* Set the divide ratio */
|
||||
hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB,
|
||||
HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div));
|
||||
hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB,
|
||||
HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div));
|
||||
|
||||
/* Set the pulse generator mode configuration */
|
||||
hmc7044_write(dev, HMC7044_REG_PULSE_GEN,
|
||||
HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode));
|
||||
|
||||
/* Enable the input buffers */
|
||||
hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL,
|
||||
dev->in_buf_mode[0]);
|
||||
hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL,
|
||||
dev->in_buf_mode[1]);
|
||||
|
||||
/* Set GPIOs */
|
||||
hmc7044_write(dev, HMC7044_REG_GPI_CTRL(0),
|
||||
dev->gpi_ctrl[0]);
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_GPO_CTRL(0),
|
||||
dev->gpo_ctrl[0]);
|
||||
|
||||
/* Program the output channels */
|
||||
for (i = 0; i < dev->num_channels; i++) {
|
||||
chan = &dev->channels[i];
|
||||
|
||||
if (chan->num >= HMC7044_NUM_CHAN || chan->disable)
|
||||
continue;
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num),
|
||||
HMC7044_DIV_LSB(chan->divider));
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num),
|
||||
HMC7044_DIV_MSB(chan->divider));
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num),
|
||||
HMC7044_DRIVER_MODE(chan->driver_mode) |
|
||||
HMC7044_DRIVER_Z_MODE(chan->driver_impedance) |
|
||||
(chan->dynamic_driver_enable ?
|
||||
HMC7044_DYN_DRIVER_EN : 0) |
|
||||
(chan->force_mute_enable ?
|
||||
HMC7044_FORCE_MUTE_EN : 0));
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num),
|
||||
chan->fine_delay & 0x1F);
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num),
|
||||
chan->coarse_delay & 0x1F);
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num),
|
||||
chan->out_mux_mode & 0x3);
|
||||
|
||||
hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num),
|
||||
(chan->start_up_mode_dynamic_enable ?
|
||||
HMC7044_START_UP_MODE_DYN_EN : 0) |
|
||||
(chan->output_control0_rb4_enable ? BIT(4) : 0) |
|
||||
(chan->high_performance_mode_dis ?
|
||||
0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN |
|
||||
HMC7044_CH_EN);
|
||||
}
|
||||
mdelay(10);
|
||||
|
||||
|
||||
/* Do a restart to reset the system and initiate calibration */
|
||||
hmc7044_write(dev, HMC7044_REG_REQ_MODE_0,
|
||||
HMC7044_RESTART_DIV_FSM);
|
||||
mdelay(1);
|
||||
hmc7044_write(dev, HMC7044_REG_REQ_MODE_0,
|
||||
(dev->high_performance_mode_clock_dist_en ?
|
||||
HMC7044_HIGH_PERF_DISTRIB_PATH : 0));
|
||||
mdelay(1);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief hmc7044_reg_init
|
||||
*******************************************************************************/
|
||||
int32_t hmc7044_reg_init(struct hmc7044_dev **device,
|
||||
const struct hmc7044_init_param *init_param)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
struct hmc7044_dev *dev;
|
||||
|
||||
dev = (struct hmc7044_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the device.
|
||||
* @param device - The device structure.
|
||||
* @param init_param - The structure that contains the device initial
|
||||
* parameters.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t hmc7044_init(struct hmc7044_dev **device,
|
||||
const struct hmc7044_init_param *init_param)
|
||||
{
|
||||
struct hmc7044_dev *dev;
|
||||
int32_t ret;
|
||||
unsigned int i;
|
||||
|
||||
dev = (struct hmc7044_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev->is_hmc7043 = init_param->is_hmc7043;
|
||||
|
||||
dev->clkin_freq[0] = init_param->clkin_freq[0];
|
||||
dev->clkin_freq[1] = init_param->clkin_freq[1];
|
||||
dev->clkin_freq[2] = init_param->clkin_freq[2];
|
||||
dev->clkin_freq[3] = init_param->clkin_freq[3];
|
||||
|
||||
dev->clkin_freq_ccf[0] = init_param->clkin_freq_ccf[0];
|
||||
dev->clkin_freq_ccf[1] = init_param->clkin_freq_ccf[1];
|
||||
dev->clkin_freq_ccf[2] = init_param->clkin_freq_ccf[2];
|
||||
dev->clkin_freq_ccf[3] = init_param->clkin_freq_ccf[3];
|
||||
|
||||
dev->vcxo_freq = init_param->vcxo_freq;
|
||||
dev->pll1_pfd = init_param->pll1_pfd;
|
||||
dev->pll2_freq = init_param->pll2_freq;
|
||||
dev->pll1_loop_bw = init_param->pll1_loop_bw;
|
||||
|
||||
dev->sysref_timer_div = init_param->sysref_timer_div;
|
||||
dev->pll1_ref_prio_ctrl = init_param->pll1_ref_prio_ctrl;
|
||||
dev->clkin0_rfsync_en = init_param->clkin0_rfsync_en;
|
||||
dev->clkin1_vcoin_en = init_param->clkin1_vcoin_en;
|
||||
dev->high_performance_mode_clock_dist_en =
|
||||
init_param->high_performance_mode_clock_dist_en;
|
||||
dev->rf_reseeder_en = !init_param->rf_reseeder_disable;
|
||||
dev->sync_pin_mode = init_param->sync_pin_mode;
|
||||
dev->pulse_gen_mode = init_param->pulse_gen_mode;
|
||||
|
||||
dev->in_buf_mode[0] = init_param->in_buf_mode[0];
|
||||
dev->in_buf_mode[1] = init_param->in_buf_mode[1];
|
||||
dev->in_buf_mode[2] = init_param->in_buf_mode[2];
|
||||
dev->in_buf_mode[3] = init_param->in_buf_mode[3];
|
||||
dev->in_buf_mode[4] = init_param->in_buf_mode[4];
|
||||
|
||||
dev->gpi_ctrl[0] = init_param->gpi_ctrl[0];
|
||||
dev->gpi_ctrl[1] = init_param->gpi_ctrl[1];
|
||||
dev->gpi_ctrl[2] = init_param->gpi_ctrl[2];
|
||||
dev->gpi_ctrl[3] = init_param->gpi_ctrl[3];
|
||||
|
||||
dev->gpo_ctrl[0] = init_param->gpo_ctrl[0];
|
||||
dev->gpo_ctrl[1] = init_param->gpo_ctrl[1];
|
||||
dev->gpo_ctrl[2] = init_param->gpo_ctrl[2];
|
||||
dev->gpo_ctrl[3] = init_param->gpo_ctrl[3];
|
||||
|
||||
dev->num_channels = init_param->num_channels;
|
||||
dev->channels = (struct hmc7044_chan_spec *)
|
||||
malloc(sizeof(*dev->channels) * dev->num_channels);
|
||||
|
||||
for (i = 0; i < dev->num_channels; i++) {
|
||||
dev->channels[i].num = init_param->channels[i].num;
|
||||
dev->channels[i].disable = init_param->channels[i].disable;
|
||||
dev->channels[i].divider = init_param->channels[i].divider;
|
||||
dev->channels[i].driver_mode =
|
||||
init_param->channels[i].driver_mode;
|
||||
dev->channels[i].high_performance_mode_dis =
|
||||
init_param->channels[i].high_performance_mode_dis;
|
||||
dev->channels[i].start_up_mode_dynamic_enable =
|
||||
init_param->channels[i].start_up_mode_dynamic_enable;
|
||||
dev->channels[i].dynamic_driver_enable =
|
||||
init_param->channels[i].dynamic_driver_enable;
|
||||
dev->channels[i].output_control0_rb4_enable =
|
||||
init_param->channels[i].output_control0_rb4_enable;
|
||||
dev->channels[i].force_mute_enable =
|
||||
init_param->channels[i].force_mute_enable;
|
||||
dev->channels[i].driver_impedance =
|
||||
init_param->channels[i].driver_impedance;
|
||||
dev->channels[i].coarse_delay =
|
||||
init_param->channels[i].coarse_delay;
|
||||
dev->channels[i].fine_delay =
|
||||
init_param->channels[i].fine_delay;
|
||||
dev->channels[i].out_mux_mode =
|
||||
init_param->channels[i].out_mux_mode;
|
||||
}
|
||||
|
||||
*device = dev;
|
||||
|
||||
if (!dev->is_hmc7043)
|
||||
return hmc7044_setup(dev);
|
||||
else
|
||||
return hmc7043_setup(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the device - release resources.
|
||||
* @param device - The device structure.
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t hmc7044_remove(struct hmc7044_dev *device)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = spi_remove(device->spi_desc);
|
||||
free(device->channels);
|
||||
free(device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
/***************************************************************************//**
|
||||
* @file hmc7044.h
|
||||
* @brief Header file of HMC7044, HMC7043 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2018-2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef HMC7044_H_
|
||||
#define HMC7044_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
// Enum to select SYNC pin configuration with respect to PLL2 (0x0005)
|
||||
typedef enum
|
||||
{
|
||||
SYNC_DISABLED = 0,
|
||||
SYNC_MULTICHIP = 1,
|
||||
SYNC_PULSE_GEN = 2,
|
||||
SYNC_ALARM = 3
|
||||
} hmc7044SyncPinModeSelect_t;
|
||||
|
||||
// Enum to select input buffer mode (0x000A, 0x000B, 0x000C, 0x000D, 0x000E)
|
||||
typedef enum
|
||||
{
|
||||
BUFFER_ENABLE = (1) << 0,
|
||||
BUFFER_DISABLE = (0) << 0,
|
||||
ENABLE_INTERNAL_TERM = (1) << 1,
|
||||
ENABLE_AC_COUPLE = (1) << 2,
|
||||
ENABLE_LVPECL = (1) << 3,
|
||||
ENABLE_HIGH_Z = (1) << 4
|
||||
} hmc7044InputBufferMode_t;
|
||||
|
||||
// Enum to select output driver mode (0x003A, 0x003B, 0x00D0, 0x00DA, 0x00E4,
|
||||
// 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A, 0x0134, 0x013E,
|
||||
// 0x0148, 0x0152)
|
||||
typedef enum
|
||||
{
|
||||
CML = 0,
|
||||
LVPECL = 1,
|
||||
LVDS = 2,
|
||||
CMOS = 3
|
||||
} hmc7044DriverMode_t;
|
||||
|
||||
// Enum to select the GPIx functionality. (0x0046, 0x0047, 0x0048, 0x0049)
|
||||
typedef enum
|
||||
{
|
||||
GPI_ENABLE = (1) << 0,
|
||||
GPI_DISABLE = (0) << 0,
|
||||
FORCE_PLL1_HOLDOVER = (0x01) << 1 | GPI_ENABLE,
|
||||
SELECT_PLL1_REF_BIT1 = (0x02) << 1 | GPI_ENABLE,
|
||||
SELECT_PLL1_REF_BIT2 = (0x03) << 1 | GPI_ENABLE,
|
||||
CHIP_SLEEP_MODE = (0x04) << 1 | GPI_ENABLE,
|
||||
MUTE_REQUSET = (0x05) << 1 | GPI_ENABLE,
|
||||
SELECT_INTERNAL_VCO_TYPE = (0x06) << 1 | GPI_ENABLE,
|
||||
SELECT_HI_PERF_MODE = (0x07) << 1 | GPI_ENABLE,
|
||||
PULSE_GEN_REQUSET = (0x08) << 1 | GPI_ENABLE,
|
||||
RESEED_REQUEST = (0x09) << 1 | GPI_ENABLE,
|
||||
RESTART_REQUSET = (0x0A) << 1 | GPI_ENABLE,
|
||||
FORCE_FANOUT_MODE = (0x0B) << 1 | GPI_ENABLE,
|
||||
SLIP_REQUEST = (0x0D) << 1 | GPI_ENABLE,
|
||||
} hmc7044GPIControl_t;
|
||||
|
||||
// Enum to select the GPOx functionality. (0x0050, 0x0051, 0x0052, 0x0053)
|
||||
typedef enum
|
||||
{
|
||||
GPO_ENABLE = (1) << 0,
|
||||
GPO_DISABLE = (0) << 0,
|
||||
GPO_CMOS_MODE = (1) << 1,
|
||||
GPO_OPEN_DRAIN_MODE = (0) << 1,
|
||||
ALARM_SIGNAL = (0x00) << 3 | GPO_ENABLE,
|
||||
SPI_SDATA = (0x01) << 3 | GPO_ENABLE,
|
||||
CLKIN3_SIGNAL_LOSS = (0x02) << 3 | GPO_ENABLE,
|
||||
CLKIN2_SIGNAL_LOSS = (0x03) << 3 | GPO_ENABLE,
|
||||
CLKIN1_SIGNAL_LOSS = (0x04) << 3 | GPO_ENABLE,
|
||||
CLKIN0_SIGNAL_LOSS = (0x05) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_ENABLE = (0x06) << 3 | GPO_ENABLE,
|
||||
PLL1_LOCK_DETECT = (0x07) << 3 | GPO_ENABLE,
|
||||
PLL1_ACQUIRING_LOCK = (0x08) << 3 | GPO_ENABLE,
|
||||
PLL1_NEAR_CLOCK_ACQ_STAT = (0x09) << 3 | GPO_ENABLE,
|
||||
PLL2_LOCK_DETECT = (0x0A) << 3 | GPO_ENABLE,
|
||||
PLL2_SYSREF_SYNC = (0x0B) << 3 | GPO_ENABLE,
|
||||
CLOCK_OUTPUT_PHASE_STAT = (0x0C) << 3 | GPO_ENABLE,
|
||||
PLL1_PLL2_LOCKED = (0x0D) << 3 | GPO_ENABLE,
|
||||
SYNC_REQUSRT_STAT = (0x0E) << 3 | GPO_ENABLE,
|
||||
PLL1_ACTIVE_CLKIN0 = (0x0F) << 3 | GPO_ENABLE,
|
||||
PLL1_ACTIVE_CLKIN1 = (0x10) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_IN_RANGE_STAT = (0x11) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_IN_STAT = (0x12) << 3 | GPO_ENABLE,
|
||||
PLL1_VCXO_STAT = (0x13) << 3 | GPO_ENABLE,
|
||||
PLL1_ACTIVE_CLKINx_STAT = (0x14) << 3 | GPO_ENABLE,
|
||||
PLL1_FSM_BIT0 = (0x15) << 3 | GPO_ENABLE,
|
||||
PLL1_FSM_BIT1 = (0x16) << 3 | GPO_ENABLE,
|
||||
PLL1_FSM_BIT2 = (0x17) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_EXIT_PHASE_BIT0 = (0x18) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_EXIT_PHASE_BIT1 = (0x19) << 3 | GPO_ENABLE,
|
||||
CHANNEL_OUTPUT_FSM_BUSY = (0x1A) << 3 | GPO_ENABLE,
|
||||
SYSREF_FSM_STAT_BIT0 = (0x1B) << 3 | GPO_ENABLE,
|
||||
SYSREF_FSM_STAT_BIT1 = (0x1C) << 3 | GPO_ENABLE,
|
||||
SYSREF_FSM_STAT_BIT2 = (0x1D) << 3 | GPO_ENABLE,
|
||||
SYSREF_FSM_STAT_BIT3 = (0x1E) << 3 | GPO_ENABLE,
|
||||
FORCE_LOGIC_1 = (0x1F) << 3 | GPO_ENABLE,
|
||||
FORCE_LOGIC_0 = (0x20) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_AVG_VALUE_BIT0 = (0x27) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_AVG_VALUE_BIT1 = (0x28) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_AVG_VALUE_BIT2 = (0x29) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_AVG_VALUE_BIT3 = (0x2A) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_CURR_VALUE_BIT0 = (0x2B) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_CURR_VALUE_BIT1 = (0x2C) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_CURR_VALUE_BIT2 = (0x2D) << 3 | GPO_ENABLE,
|
||||
PLL1_HOLDOVER_CURR_VALUE_BIT3 = (0x2E) << 3 | GPO_ENABLE
|
||||
} hmc7044GPOControl_t;
|
||||
|
||||
// Enum to select output channel (0x00CF, 0x00D9, 0x00E3, 0x00ED, 0x00F7,
|
||||
// 0x0101, 0x010B, 0x0115, 0x011F, 0x0129, 0x0133, 0x013D, 0x0147, 0x0151
|
||||
typedef enum
|
||||
{
|
||||
CHANNEL_DIV = 0,
|
||||
ANALOG_DELAY = 1,
|
||||
OTHER_CHANNEL = 2,
|
||||
VCO_CLOCK = 3
|
||||
} hmc7044OutputMuxSelect_t;
|
||||
|
||||
// Enum to select output driver impedance selection for CML mode (0x00D0,
|
||||
// 0x00DA, 0x00E4, 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A,
|
||||
// 0x0134, 0x013E, 0x0148, 0x0152)
|
||||
typedef enum
|
||||
{
|
||||
INTERNAL_RES_DISABLE = 0,
|
||||
INTERNAL_100OHM_PER_PIN = 1,
|
||||
// INTERNAL_RES_RESERVED = 2,
|
||||
INTERNAL_50OHM_PER_PIN = 3
|
||||
} hmc7044DriverImpedance_t;
|
||||
|
||||
// Enum to select pulse generator mode (0x005A)
|
||||
typedef enum
|
||||
{
|
||||
PULSE_LEVEL_SENSITIVE = 0,
|
||||
PULSE_ONE = 1,
|
||||
PULSE_TWO = 2,
|
||||
PULSE_FOUR = 3,
|
||||
PULSE_EIGHT = 4,
|
||||
PULSE_SIXTEEN = 5,
|
||||
// PULSE_SIXTEEN = 6,
|
||||
PULSE_CONTINOUS = 7
|
||||
} hmc7044SyncPulseGenControl_t;
|
||||
|
||||
struct hmc7044_chan_spec {
|
||||
unsigned int num;
|
||||
bool disable;
|
||||
bool high_performance_mode_dis;
|
||||
bool start_up_mode_dynamic_enable;
|
||||
bool dynamic_driver_enable;
|
||||
bool output_control0_rb4_enable;
|
||||
bool force_mute_enable;
|
||||
unsigned int divider;
|
||||
unsigned int coarse_delay;
|
||||
unsigned int fine_delay;
|
||||
hmc7044DriverMode_t driver_mode;
|
||||
hmc7044DriverImpedance_t driver_impedance;
|
||||
hmc7044OutputMuxSelect_t out_mux_mode;
|
||||
};
|
||||
|
||||
struct hmc7044_config {
|
||||
uint16_t addr;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
struct hmc7044_dev {
|
||||
struct spi_desc *spi_desc;
|
||||
bool is_hmc7043;
|
||||
uint32_t clkin_freq[4];
|
||||
uint32_t clkin_freq_ccf[4];
|
||||
uint32_t vcxo_freq;
|
||||
uint32_t pll1_pfd;
|
||||
uint32_t pll2_freq;
|
||||
uint32_t pll1_loop_bw;
|
||||
uint32_t sysref_timer_div;
|
||||
unsigned int pll1_ref_prio_ctrl;
|
||||
bool clkin0_rfsync_en;
|
||||
bool clkin1_vcoin_en;
|
||||
bool high_performance_mode_clock_dist_en;
|
||||
bool rf_reseeder_en;
|
||||
hmc7044SyncPinModeSelect_t sync_pin_mode;
|
||||
hmc7044SyncPulseGenControl_t pulse_gen_mode;
|
||||
uint32_t in_buf_mode[5];
|
||||
uint32_t gpi_ctrl[4];
|
||||
uint32_t gpo_ctrl[4];
|
||||
uint32_t num_channels;
|
||||
struct hmc7044_chan_spec *channels;
|
||||
};
|
||||
|
||||
struct hmc7044_init_param {
|
||||
struct spi_init_param *spi_init;
|
||||
bool is_hmc7043;
|
||||
uint32_t clkin_freq[4];
|
||||
uint32_t clkin_freq_ccf[4];
|
||||
uint32_t vcxo_freq;
|
||||
uint32_t pll1_pfd;
|
||||
uint32_t pll2_freq;
|
||||
uint32_t pll1_loop_bw;
|
||||
uint32_t sysref_timer_div;
|
||||
unsigned int pll1_ref_prio_ctrl;
|
||||
bool clkin0_rfsync_en;
|
||||
bool clkin1_vcoin_en;
|
||||
bool high_performance_mode_clock_dist_en;
|
||||
bool rf_reseeder_disable;
|
||||
hmc7044SyncPinModeSelect_t sync_pin_mode;
|
||||
hmc7044SyncPulseGenControl_t pulse_gen_mode;
|
||||
uint32_t in_buf_mode[5];
|
||||
uint32_t gpi_ctrl[4];
|
||||
uint32_t gpo_ctrl[4];
|
||||
uint32_t num_channels;
|
||||
struct hmc7044_chan_spec *channels;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
/* Initialize the device. */
|
||||
int32_t hmc7044_reg_init(struct hmc7044_dev **device,
|
||||
const struct hmc7044_init_param *init_param);
|
||||
int32_t hmc7044_init(struct hmc7044_dev **device,
|
||||
const struct hmc7044_init_param *init_param);
|
||||
/* Remove the device. */
|
||||
int32_t hmc7044_remove(struct hmc7044_dev *device);
|
||||
int32_t hmc7044_write(struct hmc7044_dev *dev,
|
||||
uint16_t reg, uint8_t val);
|
||||
int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val);
|
||||
int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num,
|
||||
uint64_t *rate);
|
||||
int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate,
|
||||
uint64_t *rounded_rate);
|
||||
int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num,
|
||||
uint64_t rate);
|
||||
|
||||
#endif // HMC7044_H_
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/***************************************************************************//**
|
||||
* @file lmk04828.c
|
||||
* @brief Implementation of AD9680 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "lmk04828.h"
|
||||
#include "../../../include/error.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief lmk04828_read
|
||||
*******************************************************************************/
|
||||
int32_t lmk04828_read(struct lmk04828_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data)
|
||||
{
|
||||
uint8_t tx_buf[2];
|
||||
uint8_t rx_buf[1];
|
||||
int32_t ret;
|
||||
|
||||
tx_buf[0] = 0x80 | (reg_addr >> 8);
|
||||
tx_buf[1] = reg_addr & 0xFF;
|
||||
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
tx_buf, rx_buf, 2, 1);
|
||||
|
||||
*reg_data = rx_buf[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief lmk04828_write
|
||||
*******************************************************************************/
|
||||
int32_t lmk04828_write(struct lmk04828_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
|
||||
int32_t ret;
|
||||
|
||||
buf[0] = reg_addr >> 8;
|
||||
buf[1] = reg_addr & 0xFF;
|
||||
buf[2] = reg_data;
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
buf, NULL, 3, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief lmk04828_init
|
||||
*******************************************************************************/
|
||||
int32_t lmk04828_init(struct lmk04828_dev **device,
|
||||
const struct lmk04828_init_param *init_param)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
struct lmk04828_dev *dev;
|
||||
|
||||
dev = (struct lmk04828_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Free the resources allocated by lmk04828_setup().
|
||||
*
|
||||
* @param dev - The device structure.
|
||||
*
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*******************************************************************************/
|
||||
int32_t lmk04828_remove(struct lmk04828_dev *dev)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = spi_remove(dev->spi_desc);
|
||||
|
||||
free(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/***************************************************************************//**
|
||||
* @file lmk04828.h
|
||||
* @brief Header file of lmk04828 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef LMK04828_H_
|
||||
#define LMK04828_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
struct lmk04828_dev {
|
||||
/* SPI */
|
||||
struct spi_desc *spi_desc;
|
||||
};
|
||||
|
||||
struct lmk04828_init_param {
|
||||
/* SPI */
|
||||
struct spi_init_param *spi_init;
|
||||
};
|
||||
|
||||
struct lmk04828_config {
|
||||
uint16_t addr;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int32_t lmk04828_read(struct lmk04828_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data);
|
||||
|
||||
int32_t lmk04828_write(struct lmk04828_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data);
|
||||
|
||||
int32_t lmk04828_init(struct lmk04828_dev **device,
|
||||
const struct lmk04828_init_param *init_param);
|
||||
|
||||
int32_t lmk04828_remove(struct lmk04828_dev *dev);
|
||||
|
||||
#endif
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/***************************************************************************//**
|
||||
* @file lmx2594.c
|
||||
* @brief Implementation of AD9680 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include "../lmx2594/lmx2594.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "../../../include/error.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief lmx2594_read
|
||||
*******************************************************************************/
|
||||
int32_t lmx2594_read(struct lmx2594_dev *dev,
|
||||
uint8_t reg_addr,
|
||||
uint16_t *reg_data)
|
||||
{
|
||||
uint8_t tx_buf[1];
|
||||
uint8_t rx_buf[2];
|
||||
int32_t ret;
|
||||
|
||||
tx_buf[0] = 0x80 | reg_addr;
|
||||
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
tx_buf, rx_buf, 1, 2);
|
||||
|
||||
*reg_data = rx_buf[1];
|
||||
*reg_data |= ((uint16_t)rx_buf[0]) << 8;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief lmx2594_write
|
||||
*******************************************************************************/
|
||||
int32_t lmx2594_write(struct lmx2594_dev *dev,
|
||||
uint8_t reg_addr,
|
||||
uint16_t reg_data)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
|
||||
int32_t ret;
|
||||
|
||||
buf[0] = reg_addr;
|
||||
buf[1] = reg_data >> 8;
|
||||
buf[2] = reg_data & 0xFF;
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
buf, NULL, 3, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief lmx2594_init
|
||||
*******************************************************************************/
|
||||
int32_t lmx2594_init(struct lmx2594_dev **device,
|
||||
const struct lmx2594_init_param *init_param)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
struct lmx2594_dev *dev;
|
||||
|
||||
dev = (struct lmx2594_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Free the resources allocated by lmx2594_setup().
|
||||
*
|
||||
* @param dev - The device structure.
|
||||
*
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*******************************************************************************/
|
||||
int32_t lmx2594_remove(struct lmx2594_dev *dev)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = spi_remove(dev->spi_desc);
|
||||
|
||||
free(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/***************************************************************************//**
|
||||
* @file lmx2594.h
|
||||
* @brief Header file of lmx2594 Driver.
|
||||
* @author DBogdan ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef LMX2594_H_
|
||||
#define LMX2594_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
struct lmx2594_dev {
|
||||
/* SPI */
|
||||
struct spi_desc *spi_desc;
|
||||
};
|
||||
|
||||
struct lmx2594_init_param {
|
||||
/* SPI */
|
||||
struct spi_init_param *spi_init;
|
||||
};
|
||||
|
||||
struct lmx2594_config {
|
||||
uint8_t addr;
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int32_t lmx2594_read(struct lmx2594_dev *dev,
|
||||
uint8_t reg_addr,
|
||||
uint16_t *reg_data);
|
||||
|
||||
int32_t lmx2594_write(struct lmx2594_dev *dev,
|
||||
uint8_t reg_addr,
|
||||
uint16_t reg_data);
|
||||
|
||||
int32_t lmx2594_init(struct lmx2594_dev **device,
|
||||
const struct lmx2594_init_param *init_param);
|
||||
|
||||
int32_t lmx2594_remove(struct lmx2594_dev *dev);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_axi_io.c
|
||||
* @brief Implementation of Xilinx AXI IO.
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <xil_io.h>
|
||||
#include "error.h"
|
||||
#include "axi_io.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief AXI IO Xilinx specific read function.
|
||||
* @param base - Base address
|
||||
* @param offset - Address offset
|
||||
* @param data - variable where returned data is stored
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data)
|
||||
{
|
||||
*data = Xil_In32(base + offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief AXI IO Xilinx specific write function.
|
||||
* @param base - Base address
|
||||
* @param offset - Address offset
|
||||
* @param data - data to be written.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data)
|
||||
{
|
||||
Xil_Out32(base + offset, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_delay.c
|
||||
* @brief Implementation of Xilinx Delay Functions.
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include "delay.h"
|
||||
#include <sleep.h>
|
||||
#ifdef _XPARAMETERS_PS_H_
|
||||
#include "util.h"
|
||||
#include "xtime_l.h"
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Generate microseconds delay.
|
||||
* @param usecs - Delay in microseconds.
|
||||
* @return None.
|
||||
*/
|
||||
void udelay(uint32_t usecs)
|
||||
{
|
||||
#ifdef _XPARAMETERS_PS_H_
|
||||
usleep(usecs);
|
||||
#else
|
||||
usleep_MB(usecs);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate miliseconds delay.
|
||||
* @param msecs - Delay in miliseconds.
|
||||
* @return None.
|
||||
*/
|
||||
void mdelay(uint32_t msecs)
|
||||
{
|
||||
#ifdef _XPARAMETERS_PS_H_
|
||||
usleep(msecs * 1000);
|
||||
#else
|
||||
usleep_MB(msecs * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current time.
|
||||
* @return Current time structure from system start (seconds, microseconds).
|
||||
*/
|
||||
struct time get_time(void)
|
||||
{
|
||||
struct time t = {0, 0};
|
||||
#ifdef _XPARAMETERS_PS_H_
|
||||
unsigned long long Xtime_Global;
|
||||
uint32_t rem;
|
||||
|
||||
XTime_GetTime(&Xtime_Global);
|
||||
t.s = div_u64_rem(Xtime_Global, COUNTS_PER_SECOND, &rem);
|
||||
t.us = div_u64((uint64_t)rem * 1000000, COUNTS_PER_SECOND);
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -0,0 +1,464 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_gpio.c
|
||||
* @brief Implementation of Xilinx GPIO Generic Driver.
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <xparameters.h>
|
||||
#ifdef XPAR_XGPIO_NUM_INSTANCES
|
||||
#include <xgpio.h>
|
||||
#endif
|
||||
#ifdef XPAR_XGPIOPS_NUM_INSTANCES
|
||||
#include <xgpiops.h>
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
#include "gpio.h"
|
||||
#include "xilinx_gpio.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Prepare the GPIO decriptor.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param param - The structure that contains the GPIO parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t _gpio_init(struct gpio_desc *desc,
|
||||
const struct gpio_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
struct xil_gpio_desc *xdesc;
|
||||
struct xil_gpio_init_param *xinit;
|
||||
|
||||
ret = -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
xinit = param->extra;
|
||||
|
||||
xdesc->type = xinit->type;
|
||||
desc->number = param->number;
|
||||
|
||||
switch (xinit->type) {
|
||||
case GPIO_PL:
|
||||
#ifdef XGPIO_H
|
||||
xdesc->instance = (XGpio *)malloc(sizeof(XGpio));
|
||||
if(!xdesc->instance)
|
||||
goto pl_error;
|
||||
|
||||
xdesc->config = XGpio_LookupConfig(xinit->device_id);
|
||||
if(xdesc->config == NULL)
|
||||
goto pl_error;
|
||||
|
||||
ret = XGpio_CfgInitialize(xdesc->instance,
|
||||
xdesc->config,
|
||||
((XGpio_Config*)xdesc->config)
|
||||
->BaseAddress);
|
||||
if(ret < 0)
|
||||
goto pl_error;
|
||||
|
||||
break;
|
||||
pl_error:
|
||||
free(xdesc->instance);
|
||||
#endif
|
||||
goto error;
|
||||
case GPIO_PS:
|
||||
#ifdef XGPIOPS_H
|
||||
xdesc->instance = (XGpioPs *)malloc(sizeof(XGpioPs));
|
||||
if(!xdesc->instance)
|
||||
goto ps_error;
|
||||
|
||||
xdesc->config = XGpioPs_LookupConfig(xinit->device_id);
|
||||
if(xdesc->config == NULL)
|
||||
goto ps_error;
|
||||
|
||||
ret = XGpioPs_CfgInitialize(xdesc->instance,
|
||||
xdesc->config,
|
||||
((XGpioPs_Config*)xdesc->config)->BaseAddr);
|
||||
if(ret < 0)
|
||||
goto ps_error;
|
||||
break;
|
||||
ps_error:
|
||||
free(xdesc->instance);
|
||||
#endif
|
||||
goto error;
|
||||
error:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Obtain the GPIO decriptor.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param param - GPIO initialization parameters
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_get(struct gpio_desc **desc,
|
||||
const struct gpio_init_param *param)
|
||||
{
|
||||
struct gpio_desc *descriptor;
|
||||
struct xil_gpio_desc *extra;
|
||||
int32_t ret;
|
||||
|
||||
descriptor = (struct gpio_desc *)malloc(sizeof(*descriptor));
|
||||
extra = (struct xil_gpio_desc*)malloc(sizeof(*extra));
|
||||
|
||||
if (!descriptor || !extra)
|
||||
return -1;
|
||||
|
||||
descriptor->extra = extra;
|
||||
ret = _gpio_init(descriptor, param);
|
||||
|
||||
if(ret != 0)
|
||||
goto error;
|
||||
|
||||
*desc = descriptor;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
free(extra);
|
||||
free(descriptor);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of an optional GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param param - GPIO Initialization parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_get_optional(struct gpio_desc **desc,
|
||||
const struct gpio_init_param *param)
|
||||
{
|
||||
if(param == NULL) {
|
||||
*desc = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return xil_gpio_get(desc, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by gpio_get().
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_remove(struct gpio_desc *desc)
|
||||
{
|
||||
if (desc != NULL) {
|
||||
free(((struct xil_gpio_desc *)(desc->extra))->instance);
|
||||
free(desc->extra);
|
||||
free(desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the input direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_direction_input(struct gpio_desc *desc)
|
||||
{
|
||||
struct xil_gpio_desc *extra;
|
||||
#ifdef XGPIO_H
|
||||
uint8_t pin = desc->number;
|
||||
uint32_t channel = 1;
|
||||
uint32_t config = 0;
|
||||
#endif
|
||||
extra = desc->extra;
|
||||
|
||||
switch (extra->type) {
|
||||
case GPIO_PL:
|
||||
#ifdef XGPIO_H
|
||||
/* We assume that pin 32 is the first pin from channel 2 */
|
||||
if (pin >= 32) {
|
||||
channel = 2;
|
||||
pin -= 32;
|
||||
}
|
||||
|
||||
config = XGpio_GetDataDirection((XGpio *)extra->instance,
|
||||
channel);
|
||||
config |= (1 << pin);
|
||||
XGpio_SetDataDirection((XGpio *)extra->instance,
|
||||
channel,
|
||||
config);
|
||||
#endif
|
||||
break;
|
||||
case GPIO_PS:
|
||||
#ifdef XGPIOPS_H
|
||||
XGpioPs_SetDirectionPin(extra->instance,
|
||||
desc->number,
|
||||
GPIO_IN);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the output direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: GPIO_HIGH
|
||||
* GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_direction_output(struct gpio_desc *desc,
|
||||
uint8_t value)
|
||||
{
|
||||
struct xil_gpio_desc *extra;
|
||||
#ifdef XGPIO_H
|
||||
uint8_t pin = desc->number;
|
||||
uint8_t channel;
|
||||
uint32_t reg_val;
|
||||
#endif
|
||||
extra = desc->extra;
|
||||
|
||||
switch (extra->type) {
|
||||
case GPIO_PL:
|
||||
#ifdef XGPIO_H
|
||||
if (pin >= 32) {
|
||||
channel = 2;
|
||||
pin -= 32;
|
||||
} else
|
||||
channel = 1;
|
||||
|
||||
reg_val = XGpio_GetDataDirection(extra->instance,
|
||||
channel);
|
||||
reg_val &= ~(1 << pin);
|
||||
XGpio_SetDataDirection(extra->instance,
|
||||
channel,
|
||||
reg_val);
|
||||
reg_val = XGpio_DiscreteRead(extra->instance,
|
||||
channel);
|
||||
if(value)
|
||||
reg_val |= (1 << pin);
|
||||
else
|
||||
reg_val &= ~(1 << pin);
|
||||
XGpio_DiscreteWrite(extra->instance,
|
||||
channel,
|
||||
reg_val);
|
||||
#endif
|
||||
break;
|
||||
case GPIO_PS:
|
||||
#ifdef XGPIOPS_H
|
||||
XGpioPs_SetDirectionPin(extra->instance,
|
||||
desc->number,
|
||||
GPIO_OUT);
|
||||
XGpioPs_SetOutputEnablePin(extra->instance,
|
||||
desc->number,
|
||||
GPIO_OUT);
|
||||
XGpioPs_WritePin(extra->instance,
|
||||
desc->number,
|
||||
value);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param direction - The direction.
|
||||
* Example: GPIO_OUT
|
||||
* GPIO_IN
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_get_direction(struct gpio_desc *desc,
|
||||
uint8_t *direction)
|
||||
{
|
||||
if (!desc)
|
||||
return -1;
|
||||
|
||||
struct xil_gpio_desc *extra;
|
||||
uint8_t pin = desc->number;
|
||||
|
||||
#ifdef XGPIO_H
|
||||
uint8_t channel;
|
||||
#endif
|
||||
extra = desc->extra;
|
||||
|
||||
switch (extra->type) {
|
||||
case GPIO_PL:
|
||||
#ifdef XGPIO_H
|
||||
if (pin >= 32) {
|
||||
channel = 2;
|
||||
pin -= 32;
|
||||
} else
|
||||
channel = 1;
|
||||
*direction = ((XGpio_GetDataDirection(extra->instance,
|
||||
channel) >> pin) & 0x1) ^ 0x1;
|
||||
#endif
|
||||
break;
|
||||
case GPIO_PS:
|
||||
#ifdef XGPIOPS_H
|
||||
*direction = XGpioPs_GetDirectionPin(extra->instance, pin);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the value of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: GPIO_HIGH
|
||||
* GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_set_value(struct gpio_desc *desc,
|
||||
uint8_t value)
|
||||
{
|
||||
struct xil_gpio_desc *extra;
|
||||
#ifdef XGPIO_H
|
||||
uint8_t pin = desc->number;
|
||||
uint8_t channel;
|
||||
uint32_t reg_val;
|
||||
#endif
|
||||
extra = desc->extra;
|
||||
|
||||
switch (extra->type) {
|
||||
case GPIO_PL:
|
||||
#ifdef XGPIO_H
|
||||
if (pin >= 32) {
|
||||
channel = 2;
|
||||
pin -= 32;
|
||||
} else
|
||||
channel = 1;
|
||||
|
||||
reg_val = XGpio_DiscreteRead(extra->instance, channel);
|
||||
if(value)
|
||||
reg_val |= (1 << pin);
|
||||
else
|
||||
reg_val &= ~(1 << pin);
|
||||
XGpio_DiscreteWrite(extra->instance, channel, reg_val);
|
||||
#endif
|
||||
break;
|
||||
case GPIO_PS:
|
||||
#ifdef XGPIOPS_H
|
||||
XGpioPs_WritePin(extra->instance, desc->number, value);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: GPIO_HIGH
|
||||
* GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_get_value(struct gpio_desc *desc,
|
||||
uint8_t *value)
|
||||
{
|
||||
if (!desc)
|
||||
return -1;
|
||||
|
||||
struct xil_gpio_desc *extra;
|
||||
uint8_t pin = desc->number;
|
||||
|
||||
#ifdef XGPIO_H
|
||||
uint8_t channel;
|
||||
#endif
|
||||
extra = desc->extra;
|
||||
|
||||
switch (extra->type) {
|
||||
case GPIO_PL:
|
||||
#ifdef XGPIO_H
|
||||
if (pin >= 32) {
|
||||
channel = 2;
|
||||
pin -= 32;
|
||||
} else
|
||||
channel = 1;
|
||||
*value = (XGpio_DiscreteRead(extra->instance, channel) >> pin) & 0x01;
|
||||
#endif
|
||||
break;
|
||||
case GPIO_PS:
|
||||
#ifdef XGPIOPS_H
|
||||
*value = XGpioPs_ReadPin(extra->instance, pin);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific GPIO platform ops structure
|
||||
*/
|
||||
const struct gpio_platform_ops xil_gpio_ops = {
|
||||
.gpio_ops_get = &xil_gpio_get,
|
||||
.gpio_ops_get_optional = &xil_gpio_get_optional,
|
||||
.gpio_ops_remove = &xil_gpio_remove,
|
||||
.gpio_ops_direction_input = &xil_gpio_direction_input,
|
||||
.gpio_ops_direction_output = &xil_gpio_direction_output,
|
||||
.gpio_ops_get_direction = &xil_gpio_get_direction,
|
||||
.gpio_ops_set_value = &xil_gpio_set_value,
|
||||
.gpio_ops_get_value = &xil_gpio_get_value,
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
/*******************************************************************************
|
||||
* @file xilinx/xilinx_gpio.h
|
||||
* @brief Header containing extra types used in the gpio driver
|
||||
* @author scuciurean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef XILINX_GPIO_H_
|
||||
#define XILINX_GPIO_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @enum xil_gpio_type
|
||||
* @brief Xilinx platform architecture sections
|
||||
*/
|
||||
enum xil_gpio_type {
|
||||
/** Programmable Logic */
|
||||
GPIO_PL,
|
||||
/** Processing System */
|
||||
GPIO_PS
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_gpio_init_param
|
||||
* @brief Structure holding the initialization parameters for Xilinx platform
|
||||
* specific GPIO parameters.
|
||||
*/
|
||||
struct xil_gpio_init_param {
|
||||
/** Xilinx architecture */
|
||||
enum xil_gpio_type type;
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_gpio_desc
|
||||
* @brief Xilinx platform specific GPIO descriptor
|
||||
*/
|
||||
struct xil_gpio_desc {
|
||||
/** Xilinx architecture */
|
||||
enum xil_gpio_type type;
|
||||
/** Xilinx GPIO configuration */
|
||||
void *config;
|
||||
/** Xilinx GPIO Instance */
|
||||
void *instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific gpio platform ops structure
|
||||
*/
|
||||
extern const struct gpio_platform_ops xil_gpio_ops;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,360 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_gpio_irq.c
|
||||
* @brief Implementation of Xilinx GPIO IRQ Generic Driver.
|
||||
* @author Porumb Andrei ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "xparameters.h"
|
||||
#include "error.h"
|
||||
#include "xilinx_gpio_irq.h"
|
||||
#include "util.h"
|
||||
#include "list.h"
|
||||
#include "irq.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Comparing function used by list.
|
||||
* @param desc_a - Compared item
|
||||
* @param desc_b - Reference item
|
||||
* @return - 0 if items match
|
||||
*/
|
||||
static int32_t call_cmp(struct xil_callback_desc *desc_a,
|
||||
struct xil_callback_desc *desc_b)
|
||||
{
|
||||
return desc_a->pin_nb - desc_b->pin_nb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called when GPIO IRQ occurs.
|
||||
* @param param - GPIO IRQ desc's extra field
|
||||
* @return - None.
|
||||
*/
|
||||
static void xil_gpio_irq_handler(struct xil_gpio_irq_desc *param)
|
||||
{
|
||||
int32_t status = 0;
|
||||
int32_t pin_nb;
|
||||
struct xil_callback_desc *callback_desc;
|
||||
|
||||
status = iterator_move_to_idx(param->it, 0);
|
||||
while(!status) {
|
||||
iterator_read(param->it, &callback_desc);
|
||||
status = iterator_move(param->it, 1);
|
||||
if(XGpioPs_IntrGetStatusPin(¶m->my_Gpio, callback_desc->pin_nb))
|
||||
callback_desc->triggered = true;
|
||||
}
|
||||
|
||||
status = iterator_move_to_idx(param->it, 0);
|
||||
while(!status) {
|
||||
iterator_read(param->it, &callback_desc);
|
||||
status = iterator_move(param->it, 1);
|
||||
if(callback_desc->triggered == true) {
|
||||
callback_desc->triggered = false;
|
||||
XGpioPs_IntrDisablePin(¶m->my_Gpio, callback_desc->pin_nb);
|
||||
XGpioPs_IntrClearPin(¶m->my_Gpio, callback_desc->pin_nb);
|
||||
callback_desc->callback.legacy_callback(callback_desc->callback.ctx, 0U, NULL);
|
||||
if(callback_desc->enabled)
|
||||
XGpioPs_IntrEnablePin(¶m->my_Gpio, callback_desc->pin_nb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable specific GPIO IRQ pin.
|
||||
* @param desc - The GPIO IRQ controller descriptor.
|
||||
* @param irq_id - Pin number.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
int32_t status;
|
||||
struct xil_gpio_irq_desc *extra;
|
||||
struct xil_callback_desc *callback_desc;
|
||||
|
||||
extra = desc->extra;
|
||||
|
||||
status = iterator_move_to_idx(extra->it, 0);
|
||||
while(!status) {
|
||||
iterator_read(extra->it, &callback_desc);
|
||||
status = iterator_move(extra->it, 1);
|
||||
if(callback_desc->pin_nb == irq_id) {
|
||||
callback_desc->enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XGpioPs_IntrDisablePin(&extra->my_Gpio, irq_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the GPIO IRQ controller.
|
||||
* @param desc - The GPIO IRQ controller descriptor.
|
||||
* @param param - The GPIO IRQ controller initial parameters.
|
||||
* irq_ctrl_id from irq_init_param is the interrupt id for the parent controller
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_irq_ctrl_init(struct irq_ctrl_desc **desc,
|
||||
const struct irq_init_param *param)
|
||||
{
|
||||
int32_t i;
|
||||
int32_t status;
|
||||
struct irq_ctrl_desc *ldesc;
|
||||
static XGpioPs_Config *GPIO_Config;
|
||||
struct xil_gpio_irq_desc *xil_desc;
|
||||
struct xil_gpio_irq_init_param *xil_ip;
|
||||
struct callback_desc callback;
|
||||
|
||||
xil_desc = (struct xil_gpio_irq_desc *)calloc(1, sizeof(*xil_desc));
|
||||
if(!xil_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
ldesc = (struct irq_ctrl_desc *)calloc(1, sizeof(*ldesc));
|
||||
if(!ldesc) {
|
||||
free(xil_desc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
xil_ip = param->extra;
|
||||
GPIO_Config = XGpioPs_LookupConfig(xil_ip->gpio_device_id);
|
||||
status = XGpioPs_CfgInitialize(&xil_desc->my_Gpio, GPIO_Config,
|
||||
GPIO_Config->BaseAddr);
|
||||
if(status)
|
||||
goto error_desc;
|
||||
|
||||
ldesc->extra = xil_desc;
|
||||
xil_desc->parent_desc = xil_ip->parent_desc;
|
||||
|
||||
status = list_init(&xil_desc->callback_list, LIST_DEFAULT,
|
||||
call_cmp);
|
||||
if(status)
|
||||
goto error_list;
|
||||
|
||||
status = iterator_init(&xil_desc->it, xil_desc->callback_list, 0);
|
||||
if(status) {
|
||||
iterator_remove(xil_desc->it);
|
||||
goto error_list;
|
||||
}
|
||||
|
||||
ldesc->irq_ctrl_id = param->irq_ctrl_id;
|
||||
status = irq_trigger_level_set(xil_desc->parent_desc, ldesc->irq_ctrl_id,
|
||||
IRQ_EDGE_RISING);
|
||||
if(status)
|
||||
goto error_op;
|
||||
|
||||
status = irq_enable(xil_desc->parent_desc, ldesc->irq_ctrl_id);
|
||||
if(status)
|
||||
goto error_op;
|
||||
|
||||
callback.legacy_callback = &xil_gpio_irq_handler;
|
||||
callback.ctx = ldesc->extra;
|
||||
status = irq_register_callback(xil_desc->parent_desc, ldesc->irq_ctrl_id,
|
||||
&callback);
|
||||
if(status)
|
||||
goto error_op;
|
||||
|
||||
*desc = ldesc;
|
||||
|
||||
return 0;
|
||||
|
||||
error_op:
|
||||
iterator_remove(xil_desc->it);
|
||||
error_list:
|
||||
list_remove(xil_desc->callback_list);
|
||||
error_desc:
|
||||
free(xil_desc);
|
||||
free(ldesc);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set GPIO interrupt trigger level.
|
||||
* @param desc - The GPIO IRQ controller descriptor.
|
||||
* @param irq_id - Pin number.
|
||||
* @param trig - New trigger level for the GPIO interrupt.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_irq_trigger_level_set(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
enum irq_trig_level trig)
|
||||
{
|
||||
static const int32_t trig_level[5] = {XGPIOPS_IRQ_TYPE_LEVEL_LOW,
|
||||
XGPIOPS_IRQ_TYPE_LEVEL_HIGH,
|
||||
XGPIOPS_IRQ_TYPE_EDGE_FALLING,
|
||||
XGPIOPS_IRQ_TYPE_EDGE_RISING,
|
||||
XGPIOPS_IRQ_TYPE_EDGE_BOTH
|
||||
};
|
||||
struct xil_gpio_irq_desc *extra;
|
||||
|
||||
extra = desc->extra;
|
||||
XGpioPs_SetIntrTypePin(&extra->my_Gpio, irq_id, trig_level[trig]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register pin specific GPIO interrupt.
|
||||
* @param desc - The GPIO IRQ controller descriptor.
|
||||
* @param irq_id - Pin number.
|
||||
* @param callback_desc - Callback.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_irq_register_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct callback_desc *callback_desc)
|
||||
{
|
||||
struct xil_callback_desc *dev_callback;
|
||||
struct xil_gpio_irq_desc *extra;
|
||||
|
||||
dev_callback = (struct xil_callback_desc *)calloc(1,
|
||||
sizeof(*dev_callback));
|
||||
if(!dev_callback)
|
||||
return -1;
|
||||
|
||||
dev_callback->pin_nb = irq_id;
|
||||
dev_callback->callback.legacy_callback = callback_desc->legacy_callback;
|
||||
dev_callback->callback.ctx = callback_desc->ctx;
|
||||
dev_callback->triggered = false;
|
||||
|
||||
extra = desc->extra;
|
||||
XGpioPs_SetDirectionPin(&extra->my_Gpio, irq_id, 0);
|
||||
list_add_last(extra->callback_list, dev_callback);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister pin specific GPIO interrupt.
|
||||
* @param desc - The GPIO IRQ controller descriptor.
|
||||
* @param irq_id - Pin number.
|
||||
* @param cb - Callback descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_irq_unregister_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id, struct callback_desc *cb)
|
||||
{
|
||||
int32_t status;
|
||||
struct xil_gpio_irq_desc *extra;
|
||||
struct xil_callback_desc *dev_callback;
|
||||
struct xil_callback_desc search_callback;
|
||||
|
||||
extra = desc->extra;
|
||||
search_callback.pin_nb = irq_id;
|
||||
status = list_get_find(extra->callback_list, &dev_callback,
|
||||
&search_callback);
|
||||
if(status)
|
||||
return -ENXIO;
|
||||
|
||||
free(dev_callback);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable specific GPIO IRQ pin.
|
||||
* @param desc - The GPIO IRQ controller descriptor.
|
||||
* @param irq_id - Pin number.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
int32_t status;
|
||||
struct xil_gpio_irq_desc *extra;
|
||||
struct xil_callback_desc *callback_desc;
|
||||
|
||||
extra = desc->extra;
|
||||
|
||||
status = iterator_move_to_idx(extra->it, 0);
|
||||
while(!status) {
|
||||
iterator_read(extra->it, &callback_desc);
|
||||
status = iterator_move(extra->it, 1);
|
||||
if(callback_desc->pin_nb == irq_id) {
|
||||
callback_desc->enabled = true;
|
||||
XGpioPs_IntrClearPin(&extra->my_Gpio, irq_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XGpioPs_IntrEnablePin(&extra->my_Gpio, irq_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove the GPIO IRQ controller.
|
||||
* @param desc - The GPIO IRQ controller descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_gpio_irq_ctrl_remove(struct irq_ctrl_desc *desc)
|
||||
{
|
||||
struct xil_gpio_irq_desc *extra;
|
||||
struct xil_callback_desc *callback_desc;
|
||||
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
extra = desc->extra;
|
||||
while (0 == list_get_first(extra->callback_list, &callback_desc))
|
||||
free(callback_desc);
|
||||
|
||||
iterator_remove(extra->it);
|
||||
list_remove(extra->callback_list);
|
||||
free(extra);
|
||||
free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific GPIO IRQ platform ops structure
|
||||
*/
|
||||
const struct irq_platform_ops xil_gpio_irq_ops = {
|
||||
.init = &xil_gpio_irq_ctrl_init,
|
||||
.enable = &xil_gpio_irq_enable,
|
||||
.disable = &xil_gpio_irq_disable,
|
||||
.trigger_level_set = &xil_gpio_irq_trigger_level_set,
|
||||
.register_callback = &xil_gpio_irq_register_callback,
|
||||
.unregister_callback = xil_gpio_irq_unregister_callback,
|
||||
.remove = &xil_gpio_irq_ctrl_remove
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx_gpio_irq.h
|
||||
* @brief Implementation of Xilinx GPIO IRQ Generic Driver.
|
||||
* @author Porumb Andrei ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef XILINX_GPIO_IRQ_H_
|
||||
#define XILINX_GPIO_IRQ_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include "stdbool.h"
|
||||
#include "list.h"
|
||||
#include "xgpiops.h"
|
||||
#include "irq.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @struct xil_callback_desc
|
||||
* @brief Structure holding callback parameters for each pin
|
||||
*/
|
||||
struct xil_callback_desc {
|
||||
int32_t pin_nb;
|
||||
struct callback_desc callback;
|
||||
bool triggered;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_gpio_irq_init_param
|
||||
* @brief Structure holding the initialization parameters for Xilinx platform
|
||||
* specific GPIO IRQ parameters.
|
||||
*/
|
||||
struct xil_gpio_irq_init_param {
|
||||
struct irq_ctrl_desc *parent_desc;
|
||||
int32_t gpio_device_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_gpio_irq_desc
|
||||
* @brief Xilinx platform specific GPIO IRQ descriptor
|
||||
*/
|
||||
struct xil_gpio_irq_desc {
|
||||
struct irq_ctrl_desc *parent_desc;
|
||||
XGpioPs my_Gpio;
|
||||
struct list_desc *callback_list;
|
||||
struct iterator *it;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Xilinx specific GPIO IRQ platform ops structure
|
||||
*/
|
||||
extern const struct irq_platform_ops xil_gpio_irq_ops;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,514 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_i2c.c
|
||||
* @brief Implementation of Xilinx I2C Generic Driver.
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <xparameters.h>
|
||||
#ifdef XPAR_XIIC_NUM_INSTANCES
|
||||
#include <xiic.h>
|
||||
#endif
|
||||
#ifdef XPAR_XIICPS_NUM_INSTANCES
|
||||
#include <xiicps.h>
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
#include "i2c.h"
|
||||
#include "xilinx_i2c.h"
|
||||
#include "list.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
static struct list_desc *pl_list = NULL;
|
||||
static struct iterator *pl_it = NULL;
|
||||
|
||||
#ifdef XIICPS_H
|
||||
static struct list_desc *ps_list = NULL;
|
||||
static struct iterator *ps_it = NULL;
|
||||
#endif /* XIICPS_H */
|
||||
|
||||
/**
|
||||
* @struct inst_table_item
|
||||
* @brief Table item for I2C cores already started.
|
||||
*/
|
||||
struct inst_table_item {
|
||||
/** Instance the BSP driver uses for this core. */
|
||||
void *instance;
|
||||
/** Core ID in BSP. */
|
||||
uint32_t device_id;
|
||||
/** Number of ADI driver instances running on this core. */
|
||||
uint32_t inst_no;
|
||||
};
|
||||
|
||||
#ifdef XPAR_XIICPS_NUM_INSTANCES
|
||||
/** Save the current state of the bitrate to not change it each time */
|
||||
static uint32_t ps_last_bitrate = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific I2C platform ops structure
|
||||
*/
|
||||
const struct i2c_platform_ops xil_i2c_ops = {
|
||||
.i2c_ops_init = &xil_i2c_init,
|
||||
.i2c_ops_write = &xil_i2c_write,
|
||||
.i2c_ops_read = &xil_i2c_read,
|
||||
.i2c_ops_remove = &xil_i2c_remove
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Compare two I2C cores by ID.
|
||||
* @param el1 - First I2C core to compare.
|
||||
* @param el2 - Second I2C core to compare.
|
||||
* @return \ref 0 if the two cores have the same ID,
|
||||
* \ref difference between the first and the second IDs otherwise.
|
||||
*/
|
||||
static int32_t xil_i2c_cmp(void *el1, void *el2)
|
||||
{
|
||||
struct inst_table_item *sel1 = el1, *sel2 = el2;
|
||||
|
||||
return (sel1->device_id - sel2->device_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure slave address and bitrate if needed
|
||||
* @param desc - Descriptor of the I2C device
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
static int32_t xil_i2c_set_transmission_config(struct i2c_desc *desc)
|
||||
{
|
||||
struct xil_i2c_desc *xil_i2c_desc = desc->extra;
|
||||
#ifdef XIICPS_H
|
||||
int32_t ret;
|
||||
#endif
|
||||
|
||||
switch (xil_i2c_desc->type) {
|
||||
case IIC_PL:
|
||||
#ifdef XIIC_H
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case IIC_PS:
|
||||
#ifdef XIICPS_H
|
||||
if (desc->max_speed_hz != ps_last_bitrate) {
|
||||
ret = XIicPs_SetSClk(xil_i2c_desc->instance, desc->max_speed_hz);
|
||||
if (ret != XST_SUCCESS)
|
||||
return -1;
|
||||
ps_last_bitrate = desc->max_speed_hz;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
default:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the I2C communication peripheral.
|
||||
* @param desc - The I2C descriptor.
|
||||
* @param param - The structure that contains the I2C parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_i2c_init(struct i2c_desc **desc,
|
||||
const struct i2c_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
struct i2c_desc *idesc;
|
||||
struct xil_i2c_desc *xdesc;
|
||||
struct xil_i2c_init_param *xinit;
|
||||
|
||||
idesc = (struct i2c_desc *)malloc(sizeof(*idesc));
|
||||
xdesc = (struct xil_i2c_desc *)malloc(sizeof(*xdesc));
|
||||
|
||||
if(!idesc || !xdesc)
|
||||
goto error;
|
||||
|
||||
idesc->max_speed_hz = param->max_speed_hz;
|
||||
idesc->slave_address = param->slave_address;
|
||||
xinit = param->extra;
|
||||
|
||||
idesc->extra = xdesc;
|
||||
xdesc->type = xinit->type;
|
||||
xdesc->device_id = xinit->device_id;
|
||||
switch (xinit->type) {
|
||||
case IIC_PL:
|
||||
#ifdef XIIC_H
|
||||
; /** Intentional empty statement */
|
||||
struct inst_table_item tab_check_pl;
|
||||
struct inst_table_item *temp_el_pl;
|
||||
|
||||
if (!pl_list)
|
||||
list_init(&pl_list, LIST_DEFAULT, xil_i2c_cmp);
|
||||
if (!pl_it)
|
||||
iterator_init(&pl_it, pl_list, true);
|
||||
|
||||
tab_check_pl.device_id = xdesc->device_id;
|
||||
|
||||
if (!IS_ERR_VALUE(list_read_find(pl_list, (void **)&temp_el_pl,
|
||||
&tab_check_pl))) {
|
||||
xdesc->instance = temp_el_pl->instance;
|
||||
temp_el_pl->inst_no++;
|
||||
break;
|
||||
}
|
||||
|
||||
xdesc->instance = (XIic *)malloc(sizeof(XIic));
|
||||
if(!xdesc->instance)
|
||||
goto pl_error;
|
||||
|
||||
xdesc->config = XIic_LookupConfig(xinit->device_id);
|
||||
if(xdesc->config == NULL)
|
||||
goto pl_error;
|
||||
|
||||
ret = XIic_CfgInitialize(xdesc->instance,
|
||||
xdesc->config,
|
||||
((XIic_Config*)xdesc->config)
|
||||
->BaseAddress);
|
||||
if(ret != 0)
|
||||
goto pl_error;
|
||||
|
||||
ret = XIic_Start(xdesc->instance);
|
||||
if(ret != 0)
|
||||
goto pl_error;
|
||||
|
||||
ret = XIic_SetAddress(xdesc->instance,
|
||||
XII_ADDR_TO_SEND_TYPE,
|
||||
param->slave_address);
|
||||
if(ret != 0)
|
||||
goto pl_error;
|
||||
|
||||
ret = XIic_SelfTest(xdesc->instance);
|
||||
if(ret < 0)
|
||||
goto pl_error;
|
||||
|
||||
ret = XIic_SetGpOutput(xdesc->instance, 1);
|
||||
if(ret < 0)
|
||||
goto pl_error;
|
||||
|
||||
temp_el_pl = (struct inst_table_item*)calloc(1, sizeof(*temp_el_pl));
|
||||
temp_el_pl->device_id = xinit->device_id;
|
||||
temp_el_pl->inst_no = 1;
|
||||
temp_el_pl->instance = xdesc->instance;
|
||||
pl_list->push(pl_list, temp_el_pl);
|
||||
|
||||
break;
|
||||
pl_error:
|
||||
free(xdesc->instance);
|
||||
#endif
|
||||
goto error;
|
||||
case IIC_PS:
|
||||
#ifdef XIICPS_H
|
||||
; /** Intentional empty statement */
|
||||
struct inst_table_item tab_check_ps;
|
||||
struct inst_table_item *temp_el_ps;
|
||||
|
||||
if (!pl_list)
|
||||
list_init(&ps_list, LIST_DEFAULT, xil_i2c_cmp);
|
||||
if (!pl_it)
|
||||
iterator_init(&ps_it, ps_list, true);
|
||||
|
||||
tab_check_ps.device_id = xdesc->device_id;
|
||||
|
||||
if (!IS_ERR_VALUE(list_read_find(ps_list,
|
||||
(void **)&temp_el_ps,
|
||||
&tab_check_ps))) {
|
||||
xdesc->instance = temp_el_ps->instance;
|
||||
temp_el_ps->inst_no++;
|
||||
break;
|
||||
}
|
||||
|
||||
xdesc->instance = (XIicPs *)malloc(sizeof(XIicPs));
|
||||
if(!xdesc->instance)
|
||||
goto ps_error;
|
||||
|
||||
xdesc->config = XIicPs_LookupConfig(xinit->device_id);
|
||||
if(xdesc->config == NULL)
|
||||
goto ps_error;
|
||||
|
||||
ret = XIicPs_CfgInitialize(xdesc->instance,
|
||||
xdesc->config,
|
||||
((XIicPs_Config*)xdesc->config)
|
||||
->BaseAddress);
|
||||
if(ret != 0)
|
||||
goto ps_error;
|
||||
|
||||
XIicPs_SetSClk(xdesc->instance, param->max_speed_hz);
|
||||
|
||||
temp_el_ps = (struct inst_table_item*)calloc(1, sizeof(*temp_el_ps));
|
||||
temp_el_ps->device_id = xinit->device_id;
|
||||
temp_el_ps->inst_no = 1;
|
||||
temp_el_ps->instance = xdesc->instance;
|
||||
ps_list->push(ps_list, temp_el_ps);
|
||||
|
||||
break;
|
||||
ps_error:
|
||||
free(xdesc->instance);
|
||||
#endif
|
||||
goto error;
|
||||
|
||||
default:
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
|
||||
*desc = idesc;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(idesc);
|
||||
free(xdesc);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by i2c_init().
|
||||
* @param desc - The I2C descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_i2c_remove(struct i2c_desc *desc)
|
||||
{
|
||||
struct xil_i2c_desc *xdesc;
|
||||
int32_t ret;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case IIC_PL:
|
||||
#ifdef XIIC_H
|
||||
; /** Intentional empty statement */
|
||||
struct inst_table_item tab_check_pl;
|
||||
struct inst_table_item *temp_el_pl;
|
||||
tab_check_pl.device_id = xdesc->device_id;
|
||||
ret = iterator_find(pl_it, &tab_check_pl);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
iterator_read(pl_it, (void **)&temp_el_pl);
|
||||
temp_el_pl->inst_no--;
|
||||
if (temp_el_pl->inst_no != 0)
|
||||
break;
|
||||
|
||||
ret = XIic_Stop(((XIic *)xdesc->instance));
|
||||
|
||||
if(ret != 0)
|
||||
goto error;
|
||||
|
||||
/** Remove list element */
|
||||
iterator_get(pl_it, (void **)&temp_el_pl);
|
||||
free(temp_el_pl);
|
||||
break;
|
||||
#endif
|
||||
goto error;
|
||||
case IIC_PS:
|
||||
#ifdef XIICPS_H
|
||||
; /** Intentional empty statement */
|
||||
struct inst_table_item tab_check_ps;
|
||||
struct inst_table_item *temp_el_ps;
|
||||
tab_check_ps.device_id = xdesc->device_id;
|
||||
ret = iterator_find(ps_it, &tab_check_ps);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
iterator_read(ps_it, (void **)&temp_el_ps);
|
||||
temp_el_ps->inst_no--;
|
||||
if (temp_el_ps->inst_no != 0)
|
||||
break;
|
||||
|
||||
/** Remove list element */
|
||||
iterator_get(ps_it, (void **)&temp_el_ps);
|
||||
free(temp_el_ps);
|
||||
break;
|
||||
#endif
|
||||
/* Intended fallthrough */
|
||||
error:
|
||||
default:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(desc->extra);
|
||||
free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data to a slave device.
|
||||
* @param desc - The I2C descriptor.
|
||||
* @param data - Buffer that stores the transmission data.
|
||||
* @param bytes_number - Number of bytes to write.
|
||||
* @param stop_bit - Stop condition control.
|
||||
* Example: 0 - A stop condition will not be generated;
|
||||
* 1 - A stop condition will be generated.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_i2c_write(struct i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit)
|
||||
{
|
||||
struct xil_i2c_desc *xdesc;
|
||||
int32_t ret;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case IIC_PL:
|
||||
#ifdef XIIC_H
|
||||
ret = xil_i2c_set_transmission_config(desc);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
XIic_Send(((XIic*)xdesc->instance)->BaseAddress,
|
||||
desc->slave_address,
|
||||
data,
|
||||
bytes_number,
|
||||
stop_bit ? XIIC_STOP : XIIC_REPEATED_START);
|
||||
break;
|
||||
#endif
|
||||
goto error;
|
||||
case IIC_PS:
|
||||
#ifdef XIICPS_H
|
||||
ret = xil_i2c_set_transmission_config(desc);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
ret = XIicPs_SetOptions(xdesc->instance,
|
||||
stop_bit ? 0 : XIICPS_REP_START_OPTION);
|
||||
if(ret != 0)
|
||||
goto error;
|
||||
|
||||
XIicPs_MasterSend(xdesc->instance,
|
||||
data,
|
||||
bytes_number,
|
||||
desc->slave_address);
|
||||
if(ret != 0)
|
||||
goto error;
|
||||
|
||||
break;
|
||||
#endif
|
||||
/* Intended fallthrough */
|
||||
error:
|
||||
default:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from a slave device.
|
||||
* @param desc - The I2C descriptor.
|
||||
* @param data - Buffer that will store the received data.
|
||||
* @param bytes_number - Number of bytes to read.
|
||||
* @param stop_bit - Stop condition control.
|
||||
* Example: 0 - A stop condition will not be generated;
|
||||
* 1 - A stop condition will be generated.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_i2c_read(struct i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit)
|
||||
{
|
||||
struct xil_i2c_desc *xdesc;
|
||||
int32_t ret;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case IIC_PL:
|
||||
#ifdef XIIC_H
|
||||
ret = xil_i2c_set_transmission_config(desc);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
ret = XIic_Recv(((XIic*)xdesc->instance)->BaseAddress,
|
||||
desc->slave_address,
|
||||
data,
|
||||
bytes_number,
|
||||
stop_bit ? XIIC_STOP : XIIC_REPEATED_START);
|
||||
if(ret != bytes_number)
|
||||
goto error;
|
||||
|
||||
break;
|
||||
#endif
|
||||
goto error;
|
||||
case IIC_PS:
|
||||
#ifdef XIICPS_H
|
||||
ret = xil_i2c_set_transmission_config(desc);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
ret = XIicPs_SetOptions(xdesc->instance,
|
||||
stop_bit ? 0 : XIICPS_REP_START_OPTION);
|
||||
if(ret != 0)
|
||||
goto error;
|
||||
|
||||
XIicPs_MasterRecv(xdesc->instance,
|
||||
data,
|
||||
bytes_number,
|
||||
desc->slave_address);
|
||||
if(ret != 0)
|
||||
goto error;
|
||||
|
||||
break;
|
||||
#endif
|
||||
/* Intended fallthrough */
|
||||
error:
|
||||
default:
|
||||
return -1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*******************************************************************************
|
||||
* @file xilinx/xilinx_i2c.h
|
||||
* @brief Header containing types used in the i2c driver.
|
||||
* @author scuciurean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef XILINX_I2C_H_
|
||||
#define XILINX_I2C_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @enum xil_i2c_type
|
||||
* @brief Xilinx platform architecture sections
|
||||
*/
|
||||
enum xil_i2c_type {
|
||||
/** Programmable Logic */
|
||||
IIC_PL,
|
||||
/** Processing System */
|
||||
IIC_PS
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_i2c_init
|
||||
* @brief Structure holding the initialization parameters for Xilinx platform
|
||||
* specific I2C parameters.
|
||||
*/
|
||||
struct xil_i2c_init_param {
|
||||
/** Xilinx architecture */
|
||||
enum xil_i2c_type type;
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_i2c_desc
|
||||
* @brief Xilinx platform specific I2C descriptor
|
||||
*/
|
||||
struct xil_i2c_desc {
|
||||
/** Xilinx architecture */
|
||||
enum xil_i2c_type type;
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** Xilinx I2C configuration */
|
||||
void *config;
|
||||
/** Xilinx I2C Instance */
|
||||
void *instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific i2c platform ops structure
|
||||
*/
|
||||
extern const struct i2c_platform_ops xil_i2c_ops;
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Initialize the I2C communication peripheral. */
|
||||
int32_t xil_i2c_init(struct i2c_desc **desc,
|
||||
const struct i2c_init_param *param);
|
||||
|
||||
/* Free the resources allocated by i2c_init(). */
|
||||
int32_t xil_i2c_remove(struct i2c_desc *desc);
|
||||
|
||||
/* I2C Write data */
|
||||
int32_t xil_i2c_write(struct i2c_desc *desc, uint8_t *data,
|
||||
uint8_t bytes_number, uint8_t stop_bit);
|
||||
|
||||
/* I2C Read data. */
|
||||
int32_t xil_i2c_read(struct i2c_desc *desc, uint8_t *data,
|
||||
uint8_t bytes_number, uint8_t stop_bit);
|
||||
|
||||
#endif // XILINX_I2C_H_
|
||||
@@ -0,0 +1,433 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_irq.c
|
||||
* @brief Implementation of Xilinx IRQ Generic Driver.
|
||||
* @author Cristian Pop ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <xparameters.h>
|
||||
#include <stdlib.h>
|
||||
#include "error.h"
|
||||
#include "irq.h"
|
||||
#include "xilinx_irq.h"
|
||||
#ifdef XPAR_XSCUGIC_NUM_INSTANCES
|
||||
#include <xscugic.h>
|
||||
#endif
|
||||
#ifdef XPAR_XINTC_NUM_INSTANCES
|
||||
#include <xintc.h>
|
||||
#endif
|
||||
#ifdef XPAR_XTMRCTR_NUM_INSTANCES
|
||||
#include <xtmrctr.h>
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Initialize the IRQ interrupts.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param param - The structure that contains the IRQ parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_ctrl_init(struct irq_ctrl_desc **desc,
|
||||
const struct irq_init_param *param)
|
||||
{
|
||||
int32_t status;
|
||||
struct irq_ctrl_desc *descriptor;
|
||||
struct xil_irq_desc *xil_dev;
|
||||
#ifdef XSCUGIC_H
|
||||
void *config;
|
||||
#endif
|
||||
|
||||
descriptor = (struct irq_ctrl_desc *)calloc(1, sizeof *descriptor);
|
||||
if(!descriptor)
|
||||
return -1;
|
||||
xil_dev = (struct xil_irq_desc *)calloc(1, sizeof *xil_dev);
|
||||
if(!xil_dev) {
|
||||
free(descriptor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Xil_ExceptionInit();
|
||||
|
||||
descriptor->irq_ctrl_id = param->irq_ctrl_id;
|
||||
descriptor->extra = xil_dev;
|
||||
xil_dev->type = ((struct xil_irq_init_param *)param->extra)->type;
|
||||
|
||||
switch(xil_dev->type) {
|
||||
case IRQ_PS:
|
||||
#ifdef XSCUGIC_H
|
||||
xil_dev->instance = calloc(1, sizeof(XScuGic));
|
||||
if(!xil_dev->instance)
|
||||
goto error;
|
||||
|
||||
config = XScuGic_LookupConfig(descriptor->irq_ctrl_id);
|
||||
if(!config)
|
||||
goto ps_error;
|
||||
|
||||
status = XScuGic_CfgInitialize(xil_dev->instance, config,
|
||||
((XScuGic_Config *)config)->CpuBaseAddress);
|
||||
if (status != 0)
|
||||
goto ps_error;
|
||||
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
|
||||
xil_dev->instance);
|
||||
|
||||
break;
|
||||
ps_error:
|
||||
free(xil_dev->instance);
|
||||
#endif
|
||||
goto error;
|
||||
case IRQ_PL:
|
||||
#ifdef XINTC_H
|
||||
xil_dev->instance = calloc(1, sizeof(XIntc));
|
||||
if(!xil_dev->instance)
|
||||
goto error;
|
||||
|
||||
status = XIntc_Initialize(xil_dev->instance, descriptor->irq_ctrl_id);
|
||||
if(status != 0)
|
||||
goto pl_error;
|
||||
|
||||
status = XIntc_Start(xil_dev->instance, XIN_REAL_MODE);
|
||||
if(status != 0)
|
||||
goto pl_error;
|
||||
|
||||
break;
|
||||
pl_error:
|
||||
free(xil_dev->instance);
|
||||
#endif
|
||||
goto error;
|
||||
default:
|
||||
goto error;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
*desc = descriptor;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(xil_dev);
|
||||
free(descriptor);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable global interrupts.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_global_enable(struct irq_ctrl_desc *desc)
|
||||
{
|
||||
/* Enable interrupts */
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable global interrupts.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_global_disable(struct irq_ctrl_desc *desc)
|
||||
{
|
||||
/* Disable interrupts */
|
||||
Xil_ExceptionDisable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable specific interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
struct xil_irq_desc *xil_dev = desc->extra;
|
||||
|
||||
switch(xil_dev->type) {
|
||||
case IRQ_PS:
|
||||
#ifdef XSCUGIC_H
|
||||
XScuGic_Enable(xil_dev->instance, irq_id);
|
||||
#endif
|
||||
break;
|
||||
case IRQ_PL:
|
||||
#ifdef XINTC_H
|
||||
XIntc_Enable(xil_dev->instance, irq_id);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable specific interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
struct xil_irq_desc *xil_dev = desc->extra;
|
||||
|
||||
switch(xil_dev->type) {
|
||||
case IRQ_PS:
|
||||
#ifdef XSCUGIC_H
|
||||
XScuGic_Disable(xil_dev->instance, irq_id);
|
||||
#endif
|
||||
break;
|
||||
case IRQ_PL:
|
||||
#ifdef XINTC_H
|
||||
XIntc_Disable(xil_dev->instance, irq_id);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a callback to handle the irq events.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param callback_desc - Callback descriptor
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_register_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct callback_desc *callback_desc)
|
||||
{
|
||||
struct xil_irq_desc *xil_dev = desc->extra;
|
||||
|
||||
switch(xil_dev->type) {
|
||||
case IRQ_PS:
|
||||
#ifdef XSCUGIC_H
|
||||
return XScuGic_Connect(xil_dev->instance, irq_id,
|
||||
(Xil_InterruptHandler) callback_desc->callback,
|
||||
callback_desc->ctx);
|
||||
#endif
|
||||
break;
|
||||
case IRQ_PL:
|
||||
#ifdef XINTC_H
|
||||
if (irq_id == XPAR_AXI_INTC_AXI_TIMER_INTERRUPT_INTR) {
|
||||
int32_t ret;
|
||||
|
||||
ret = XIntc_Connect(xil_dev->instance, irq_id,
|
||||
XTmrCtr_InterruptHandler, callback_desc->legacy_config);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return -1;
|
||||
XTmrCtr_SetHandler(callback_desc->legacy_config,
|
||||
(XTmrCtr_Handler)callback_desc->callback,
|
||||
callback_desc->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return XIntc_Connect(xil_dev->instance, irq_id,
|
||||
(XInterruptHandler) callback_desc->callback,
|
||||
callback_desc->ctx);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set interrupt trigger level.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param trig - New trigger level for the interrupt.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_trigger_level_set(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
enum irq_trig_level trig)
|
||||
{
|
||||
struct xil_irq_desc *xil_dev = desc->extra;
|
||||
|
||||
if(trig == IRQ_EDGE_BOTH)
|
||||
return -EINVAL;
|
||||
|
||||
switch(xil_dev->type) {
|
||||
case IRQ_PS:
|
||||
#ifdef XSCUGIC_H
|
||||
;
|
||||
uint8_t priority, trigger;
|
||||
|
||||
XScuGic_GetPriorityTriggerType(xil_dev->instance, irq_id, &priority,
|
||||
&trigger);
|
||||
trigger = trig;
|
||||
XScuGic_SetPriorityTriggerType(xil_dev->instance, irq_id, priority,
|
||||
trigger);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
break;
|
||||
case IRQ_PL:
|
||||
#ifdef XINTC_H
|
||||
/* Interrupt trigger determined in hardware. TODO: verify */
|
||||
return 0;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set interrupt trigger level.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param priority_level - New priority level for the interrupt.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_set_priority(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
uint32_t priority_level)
|
||||
{
|
||||
struct xil_irq_desc *xil_dev = desc->extra;
|
||||
|
||||
if(priority_level % 8 != 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch(xil_dev->type) {
|
||||
case IRQ_PS:
|
||||
#ifdef XSCUGIC_H
|
||||
;
|
||||
uint8_t priority, trigger;
|
||||
|
||||
XScuGic_GetPriorityTriggerType(xil_dev->instance, irq_id, &priority,
|
||||
&trigger);
|
||||
priority = priority_level;
|
||||
XScuGic_SetPriorityTriggerType(xil_dev->instance, irq_id, priority,
|
||||
trigger);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
break;
|
||||
case IRQ_PL:
|
||||
#ifdef XINTC_H
|
||||
/* Interrupt priority level determined in hardware. TODO: verify */
|
||||
return 0;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregisters a generic IRQ handling function.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param cb - Callback descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_unregister_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id, struct callback_desc *cb)
|
||||
{
|
||||
struct xil_irq_desc *xil_dev = desc->extra;
|
||||
|
||||
switch(xil_dev->type) {
|
||||
case IRQ_PS:
|
||||
#ifdef XSCUGIC_H
|
||||
XScuGic_Disconnect(xil_dev->instance, irq_id);
|
||||
#endif
|
||||
break;
|
||||
case IRQ_PL:
|
||||
#ifdef XINTC_H
|
||||
XIntc_Disconnect(xil_dev->instance, irq_id);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by irq_ctrl_init().
|
||||
* @param desc - The IRQ control descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_irq_ctrl_remove(struct irq_ctrl_desc *desc)
|
||||
{
|
||||
struct xil_irq_desc *xil_dev = desc->extra;
|
||||
free(xil_dev->instance);
|
||||
free(desc->extra);
|
||||
free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific IRQ platform ops structure
|
||||
*/
|
||||
const struct irq_platform_ops xil_irq_ops = {
|
||||
.init = &xil_irq_ctrl_init,
|
||||
.register_callback = &xil_irq_register_callback,
|
||||
.unregister_callback = &xil_irq_unregister_callback,
|
||||
.global_enable = &xil_irq_global_enable,
|
||||
.global_disable = &xil_irq_global_disable,
|
||||
.trigger_level_set = &xil_irq_trigger_level_set,
|
||||
.set_priority = &xil_irq_set_priority,
|
||||
.enable = &xil_irq_enable,
|
||||
.disable = &xil_irq_disable,
|
||||
.remove = &xil_irq_ctrl_remove
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
/*******************************************************************************
|
||||
* @file xilinx_irq.h
|
||||
* @brief Header containing types used in the irq driver.
|
||||
* @author Cristian Pop ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef XILINX_IRQ_H_
|
||||
#define XILINX_IRQ_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "irq.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @enum xil_irq_type
|
||||
* @brief Xilinx platform architecture sections
|
||||
*/
|
||||
enum xil_irq_type {
|
||||
/** Programmable Logic */
|
||||
IRQ_PL,
|
||||
/** Processing System */
|
||||
IRQ_PS
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_irq_init_param
|
||||
* @brief Structure holding the initialization parameters for Xilinx platform
|
||||
* specific IRQ parameters.
|
||||
*/
|
||||
struct xil_irq_init_param {
|
||||
/** Xilinx architecture */
|
||||
enum xil_irq_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_irq_desc
|
||||
* @brief Xilinx platform specific IRQ descriptor
|
||||
*/
|
||||
struct xil_irq_desc {
|
||||
/** Xilinx architecture */
|
||||
enum xil_irq_type type;
|
||||
/** Xilinx IRQ Instance */
|
||||
void *instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Xilinx specific IRQ platform ops structure
|
||||
*/
|
||||
extern const struct irq_platform_ops xil_irq_ops;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,462 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_spi.c
|
||||
* @brief Implementation of Xilinx SPI Generic Driver.
|
||||
* @author Antoniu Miclaus ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <xparameters.h>
|
||||
#ifdef XPAR_XSPI_NUM_INSTANCES
|
||||
#include <xspi.h>
|
||||
#endif
|
||||
#ifdef XPAR_XSPIPS_NUM_INSTANCES
|
||||
#include <xspips.h>
|
||||
#endif
|
||||
|
||||
#include "error.h"
|
||||
#include "spi.h"
|
||||
#include "xilinx_spi.h"
|
||||
|
||||
#if defined(PLATFORM_ZYNQ)
|
||||
#define SPI_CLK_FREQ_HZ(dev) (XPAR_PS7_SPI_ ## dev ## _SPI_CLK_FREQ_HZ)
|
||||
#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES
|
||||
#elif defined(PLATFORM_ZYNQMP)
|
||||
#define SPI_CLK_FREQ_HZ(dev) (XPAR_PSU_SPI_ ## dev ## _SPI_CLK_FREQ_HZ)
|
||||
#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES
|
||||
#else
|
||||
#define SPI_NUM_INSTANCES 0
|
||||
#endif
|
||||
|
||||
#warning SPI delays are not supported on the xilinx platform
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Initialize the hardware SPI peripherial
|
||||
*
|
||||
* @param xdesc Platform specific SPI descriptor
|
||||
* @param xinit Platform specific SPI init param
|
||||
* @return int32_t -1 if the device couldn't be found or configured
|
||||
*/
|
||||
static int32_t spi_init_pl(struct spi_desc *desc,
|
||||
const struct spi_init_param *param)
|
||||
{
|
||||
#ifdef XSPI_H
|
||||
int32_t ret;
|
||||
struct xil_spi_desc *xdesc;
|
||||
struct xil_spi_init_param *xinit;
|
||||
|
||||
xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc));
|
||||
if(!xdesc) {
|
||||
free(xdesc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
desc->extra = xdesc;
|
||||
xinit = param->extra;
|
||||
xdesc->type = xinit->type;
|
||||
xdesc->flags = xinit->flags;
|
||||
|
||||
xdesc->instance = (XSpi*)calloc(1, sizeof(XSpi));
|
||||
if(!xdesc->instance)
|
||||
goto pl_error;
|
||||
|
||||
xdesc->config = XSpi_LookupConfig(param->device_id);
|
||||
if(xdesc->config == NULL)
|
||||
goto pl_error;
|
||||
|
||||
ret = XSpi_CfgInitialize(xdesc->instance,
|
||||
xdesc->config,
|
||||
((XSpi_Config*)xdesc->config)
|
||||
->BaseAddress);
|
||||
if(ret != 0)
|
||||
goto pl_error;
|
||||
|
||||
ret = XSpi_Initialize(xdesc->instance, param->device_id);
|
||||
if (ret != 0)
|
||||
goto pl_error;
|
||||
|
||||
ret = XSpi_SetOptions(xdesc->instance,
|
||||
XSP_MASTER_OPTION |
|
||||
((desc->mode & SPI_CPOL) ?
|
||||
XSP_CLK_ACTIVE_LOW_OPTION : 0) |
|
||||
((desc->mode & SPI_CPHA) ?
|
||||
XSP_CLK_PHASE_1_OPTION : 0));
|
||||
if (ret != 0)
|
||||
goto pl_error;
|
||||
|
||||
ret = XSpi_Start(xdesc->instance);
|
||||
if (ret != 0)
|
||||
goto pl_error;
|
||||
|
||||
XSpi_IntrGlobalDisable((XSpi *)(xdesc->instance));
|
||||
|
||||
return 0;
|
||||
|
||||
pl_error:
|
||||
free(xdesc->instance);
|
||||
free(xdesc);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the hardware SPI peripherial
|
||||
*
|
||||
* @param xdesc Platform specific SPI descriptor
|
||||
* @param xinit Platform specific SPI init param
|
||||
* @return int32_t -1 if the device couldn't be found or configured
|
||||
*/
|
||||
static int32_t spi_init_ps(struct spi_desc *desc,
|
||||
const struct spi_init_param *param)
|
||||
{
|
||||
#ifdef XSPIPS_H
|
||||
int32_t ret;
|
||||
struct xil_spi_desc *xdesc;
|
||||
struct xil_spi_init_param *xinit;
|
||||
const uint32_t prescaler_default = XSPIPS_CLK_PRESCALE_64;
|
||||
const uint32_t prescaler_min = XSPIPS_CLK_PRESCALE_4;
|
||||
const uint32_t prescaler_max = XSPIPS_CLK_PRESCALE_256;
|
||||
uint32_t prescaler = 0u;
|
||||
uint32_t input_clock = 0u;
|
||||
|
||||
xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc));
|
||||
if(!xdesc) {
|
||||
free(xdesc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
desc->extra = xdesc;
|
||||
xinit = param->extra;
|
||||
xdesc->type = xinit->type;
|
||||
xdesc->flags = xinit->flags;
|
||||
|
||||
xdesc->instance = (XSpiPs*)malloc(sizeof(XSpiPs));
|
||||
if(!xdesc->instance)
|
||||
goto ps_error;
|
||||
|
||||
xdesc->config = XSpiPs_LookupConfig(param->device_id);
|
||||
if(xdesc->config == NULL)
|
||||
goto ps_error;
|
||||
|
||||
ret = XSpiPs_CfgInitialize(xdesc->instance,
|
||||
xdesc->config,
|
||||
((XSpiPs_Config*)xdesc->config)
|
||||
->BaseAddress);
|
||||
if(ret != 0)
|
||||
goto ps_error;
|
||||
|
||||
switch (param->device_id) {
|
||||
#if (SPI_NUM_INSTANCES >= 1)
|
||||
case 0:
|
||||
input_clock = SPI_CLK_FREQ_HZ(0);
|
||||
break;
|
||||
#endif
|
||||
#if (SPI_NUM_INSTANCES >= 2)
|
||||
case 1:
|
||||
input_clock = SPI_CLK_FREQ_HZ(1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
goto ps_error;
|
||||
};
|
||||
|
||||
if (desc->max_speed_hz != 0u) {
|
||||
uint32_t div = input_clock / desc->max_speed_hz;
|
||||
uint32_t rem = input_clock % desc->max_speed_hz;
|
||||
uint32_t po2 = !(div & (div - 1)) && !rem;
|
||||
|
||||
// find the power of two just higher than div and
|
||||
// store the exponent in prescaler
|
||||
while(div) {
|
||||
prescaler += 1;
|
||||
div >>= 1u;
|
||||
}
|
||||
|
||||
// this exponent - 1 is needed because of the way
|
||||
// xilinx stores it into registers
|
||||
if (prescaler)
|
||||
prescaler -= 1;
|
||||
|
||||
// this exponent - 1 is needed when initial div was
|
||||
// precisely a power of two
|
||||
if (prescaler && po2)
|
||||
prescaler -= 1;
|
||||
|
||||
if (prescaler < prescaler_min)
|
||||
prescaler = prescaler_min;
|
||||
|
||||
if (prescaler > prescaler_max)
|
||||
prescaler = prescaler_max;
|
||||
} else
|
||||
prescaler = prescaler_default;
|
||||
|
||||
ret = XSpiPs_SetClkPrescaler(xdesc->instance, prescaler);
|
||||
|
||||
if(ret != 0)
|
||||
goto ps_error;
|
||||
|
||||
return 0;
|
||||
|
||||
ps_error:
|
||||
free(xdesc->instance);
|
||||
free(xdesc);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI communication peripheral.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param param - The structure that contains the SPI parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_spi_init(struct spi_desc **desc,
|
||||
const struct spi_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
enum xil_spi_type *spi_type;
|
||||
|
||||
if (!param) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*desc = malloc(sizeof(**desc));
|
||||
if(! *desc) {
|
||||
free(*desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
spi_type = param->extra;
|
||||
|
||||
if(!spi_type)
|
||||
goto init_error;
|
||||
|
||||
(*desc)->max_speed_hz = param->max_speed_hz;
|
||||
(*desc)->mode = param->mode;
|
||||
(*desc)->bit_order = param->bit_order;
|
||||
(*desc)->chip_select = param->chip_select;
|
||||
|
||||
switch (*spi_type) {
|
||||
case SPI_PL:
|
||||
ret = spi_init_pl(*desc, param);
|
||||
break;
|
||||
case SPI_PS:
|
||||
ret = spi_init_ps(*desc, param);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto init_error;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
init_error:
|
||||
free(*desc);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by spi_init().
|
||||
* @param desc - The SPI descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_spi_remove(struct spi_desc *desc)
|
||||
{
|
||||
#ifdef XSPI_H
|
||||
int32_t ret;
|
||||
#endif
|
||||
struct xil_spi_desc *xdesc = NULL;
|
||||
enum xil_spi_type *spi_type;
|
||||
|
||||
spi_type = desc->extra;
|
||||
|
||||
if(!spi_type)
|
||||
return -1;
|
||||
|
||||
switch (*spi_type ) {
|
||||
case SPI_PL:
|
||||
#ifdef XSPI_H
|
||||
xdesc = desc->extra;
|
||||
|
||||
if(!xdesc)
|
||||
return -1;
|
||||
|
||||
ret = XSpi_Stop((XSpi *)(xdesc->instance));
|
||||
if(ret != 0)
|
||||
goto error;
|
||||
#endif
|
||||
break;
|
||||
case SPI_PS:
|
||||
#ifdef XSPIPS_H
|
||||
xdesc = desc->extra;
|
||||
|
||||
if(!xdesc)
|
||||
return -1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* Intended fallthrough */
|
||||
#ifdef XSPI_H
|
||||
error:
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(xdesc)
|
||||
free(xdesc->instance);
|
||||
free(desc->extra);
|
||||
free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write and read data to/from SPI.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @param bytes_number - Number of bytes to write/read.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t xil_spi_write_and_read(struct spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number)
|
||||
{
|
||||
int32_t ret;
|
||||
#ifdef XSPI_H
|
||||
uint32_t ctrl_reg;
|
||||
#endif
|
||||
struct xil_spi_desc *xdesc;
|
||||
enum xil_spi_type *spi_type;
|
||||
|
||||
ret = -1;
|
||||
|
||||
spi_type = desc->extra;
|
||||
|
||||
if(!spi_type)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (*spi_type) {
|
||||
case SPI_PL:
|
||||
#ifdef XSPI_H
|
||||
ret = XSpi_SetOptions(xdesc->instance,
|
||||
XSP_MASTER_OPTION |
|
||||
((desc->mode & SPI_CPOL) ?
|
||||
XSP_CLK_ACTIVE_LOW_OPTION : 0) |
|
||||
((desc->mode & SPI_CPHA) ?
|
||||
XSP_CLK_PHASE_1_OPTION : 0));
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
|
||||
ctrl_reg = XSpi_GetControlReg(((XSpi*)xdesc->instance));
|
||||
if (desc->bit_order == SPI_BIT_ORDER_LSB_FIRST)
|
||||
ctrl_reg |= XSP_CR_LSB_MSB_FIRST_MASK;
|
||||
else
|
||||
ctrl_reg &= ~ XSP_CR_LSB_MSB_FIRST_MASK;
|
||||
XSpi_SetControlReg(((XSpi*)xdesc->instance), ctrl_reg);
|
||||
|
||||
ret = XSpi_SetSlaveSelect(xdesc->instance,
|
||||
0x01 << desc->chip_select);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
|
||||
ret = XSpi_Transfer(xdesc->instance,
|
||||
data,
|
||||
data,
|
||||
bytes_number);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
#endif
|
||||
break;
|
||||
case SPI_PS:
|
||||
#ifdef XSPIPS_H
|
||||
ret = XSpiPs_SetOptions(xdesc->instance,
|
||||
XSPIPS_MASTER_OPTION |
|
||||
((xdesc->flags & SPI_CS_DECODE) ?
|
||||
XSPIPS_DECODE_SSELECT_OPTION : 0) |
|
||||
XSPIPS_FORCE_SSELECT_OPTION |
|
||||
((desc->mode & SPI_CPOL) ?
|
||||
XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) |
|
||||
((desc->mode & SPI_CPHA) ?
|
||||
XSPIPS_CLK_PHASE_1_OPTION : 0));
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
|
||||
ret = XSpiPs_SetSlaveSelect(xdesc->instance,
|
||||
desc->chip_select);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
ret = XSpiPs_PolledTransfer(xdesc->instance,
|
||||
data,
|
||||
data,
|
||||
bytes_number);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
ret = XSpiPs_SetSlaveSelect(xdesc->instance, SPI_DEASSERT_CURRENT_SS);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
#endif
|
||||
break;
|
||||
error:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific SPI platform ops structure
|
||||
*/
|
||||
const struct spi_platform_ops xil_spi_ops = {
|
||||
.init = &xil_spi_init,
|
||||
.write_and_read = &xil_spi_write_and_read,
|
||||
.remove = &xil_spi_remove
|
||||
};
|
||||
@@ -0,0 +1,115 @@
|
||||
/*******************************************************************************
|
||||
* @file xilinx/xilinx_spi.h
|
||||
* @brief Header containing extra types used in the spi driver.
|
||||
* @author scuciurean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef XILINX_SPI_H_
|
||||
#define XILINX_SPI_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define SPI_CS_DECODE 0x01
|
||||
#define SPI_DEASSERT_CURRENT_SS 0x0F
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @enum xil_spi_type
|
||||
* @brief Xilinx platform architecture sections
|
||||
*/
|
||||
enum xil_spi_type {
|
||||
/** Programmable Logic */
|
||||
SPI_PL,
|
||||
/** Processing System */
|
||||
SPI_PS,
|
||||
/** SPI Engine */
|
||||
SPI_ENGINE
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_spi_init_param
|
||||
* @brief Structure holding the initialization parameters for Xilinx platform
|
||||
* specific SPI parameters when using xil_spi_ops.
|
||||
*/
|
||||
struct xil_spi_init_param {
|
||||
/** Xilinx architecture */
|
||||
enum xil_spi_type type;
|
||||
/** SPI flags */
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_spi_desc
|
||||
* @brief Xilinx platform specific SPI descriptor
|
||||
*/
|
||||
struct xil_spi_desc {
|
||||
/** Xilinx architecture */
|
||||
enum xil_spi_type type;
|
||||
/** SPI flags */
|
||||
uint32_t flags;
|
||||
/** SPI configuration */
|
||||
void *config;
|
||||
/** SPI instance */
|
||||
void *instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief SPI engine platform ops structure
|
||||
*/
|
||||
extern const struct spi_platform_ops spi_eng_platform_ops;
|
||||
|
||||
/**
|
||||
* @brief Xilinx specific SPI platform ops structure
|
||||
*/
|
||||
extern const struct spi_platform_ops xil_spi_ops;
|
||||
|
||||
/**
|
||||
* @brief Xilinx SPI PS register functions. No extra param needed
|
||||
*/
|
||||
extern const struct spi_platform_ops xil_spi_pl_ops;
|
||||
|
||||
#endif // XILINX_SPI_H_
|
||||
@@ -0,0 +1,533 @@
|
||||
/*******************************************************************************
|
||||
* @file xilinx/xilinx_spi_pl.c
|
||||
* @brief Driver for spi pl device using registers
|
||||
* @author Mihail Chindris ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <xparameters.h>
|
||||
|
||||
#ifdef XPAR_XSPI_NUM_INSTANCES
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <xspi.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "spi.h"
|
||||
#include "error.h"
|
||||
#include "delay.h"
|
||||
#include "util.h"
|
||||
#include "alloc.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define XPS_TYPE_WRITE 0x1
|
||||
#define XPS_TYPE_READ 0x2
|
||||
#define XSP_DEFAULT_SR_VALUE 0x25
|
||||
#define XSP_DUMMY_DATA 0xFF
|
||||
|
||||
/*
|
||||
* Used to store current spi device configuration in order to not update it for
|
||||
* each spi transaction if not needed.
|
||||
*/
|
||||
static struct spi_desc g_spi_desc[XPAR_XSPI_NUM_INSTANCES];
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Xilinx PL spi specific data */
|
||||
struct xspi_desc {
|
||||
uint32_t base_addr;
|
||||
uint32_t disable_slaves_mask;
|
||||
uint32_t fifo_depth;
|
||||
uint8_t cs_asserted;
|
||||
};
|
||||
|
||||
/* Structure used to iterate over SPI messages */
|
||||
struct msg_iter {
|
||||
struct spi_msg *msgs;
|
||||
uint32_t len;
|
||||
uint32_t i;
|
||||
uint32_t buff_i;
|
||||
uint8_t is_wr;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Read device register */
|
||||
static inline uint32_t _read(struct xspi_desc *xdesc, uint32_t reg)
|
||||
{
|
||||
return Xil_In32(xdesc->base_addr + reg);
|
||||
}
|
||||
|
||||
/* Write device register */
|
||||
static inline void _write(struct xspi_desc *xdesc, uint32_t reg, uint32_t val)
|
||||
{
|
||||
Xil_Out32(xdesc->base_addr + reg, val);
|
||||
}
|
||||
|
||||
/* Update device register. Only bits set to 1 in mask will be modified */
|
||||
static inline void _wr_mask(struct xspi_desc *xdesc, uint32_t reg,
|
||||
uint32_t val, uint32_t mask)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = _read(xdesc, reg);
|
||||
tmp &= ~mask;
|
||||
tmp |= val & mask;
|
||||
_write(xdesc, reg, tmp);
|
||||
}
|
||||
|
||||
/* Update spi device configuration if needed */
|
||||
static void _update_mode(struct spi_desc *desc)
|
||||
{
|
||||
uint32_t val;
|
||||
uint32_t mask;
|
||||
|
||||
if (desc->mode == g_spi_desc[desc->device_id].mode &&
|
||||
desc->bit_order == g_spi_desc[desc->device_id].bit_order)
|
||||
return ;
|
||||
|
||||
/* Update mode */
|
||||
val = desc->mode | SPI_CPOL ? XSP_CR_CLK_POLARITY_MASK : 0;
|
||||
val |= desc->mode | SPI_CPHA ? XSP_CR_CLK_PHASE_MASK : 0;
|
||||
mask = XSP_CR_CLK_POLARITY_MASK | XSP_CR_CLK_PHASE_MASK;
|
||||
|
||||
val |= desc->bit_order == SPI_BIT_ORDER_LSB_FIRST ?
|
||||
XSP_CR_LSB_MSB_FIRST_MASK : 0;
|
||||
mask |= XSP_CR_LSB_MSB_FIRST_MASK;
|
||||
|
||||
_wr_mask(desc->extra, XSP_CR_OFFSET, val, mask);
|
||||
g_spi_desc[desc->device_id] = *desc;
|
||||
}
|
||||
|
||||
/* Configure SPI PL device */
|
||||
static int32_t _xil_spi_init_dev(struct xspi_desc *xdesc)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/* Software reset */
|
||||
_write(xdesc, XSP_SRR_OFFSET, XSP_SRR_RESET_MASK);
|
||||
mdelay(1);
|
||||
|
||||
/* Check if success reset */
|
||||
val = _read(xdesc, XSP_SR_OFFSET);
|
||||
if (val != XSP_DEFAULT_SR_VALUE)
|
||||
return -ENODEV;
|
||||
|
||||
/* Disable interrupts. Drivers only works with pooled mode */
|
||||
_write(xdesc, XSP_IIER_OFFSET, 0);
|
||||
|
||||
/* Deasert chip selects */
|
||||
_write(xdesc, XSP_SSR_OFFSET, 0xFFFFFFFF);
|
||||
|
||||
/* Get fifo depth */
|
||||
while (!(_read(xdesc, XSP_SR_OFFSET) & XSP_SR_TX_FULL_MASK))
|
||||
_write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA);
|
||||
xdesc->fifo_depth = _read(xdesc, XSP_TFO_OFFSET) + 1;
|
||||
|
||||
/* Configure spi device */
|
||||
val = XSP_CR_ENABLE_MASK |
|
||||
XSP_CR_MANUAL_SS_MASK |
|
||||
XSP_CR_TXFIFO_RESET_MASK |
|
||||
XSP_CR_RXFIFO_RESET_MASK |
|
||||
XSP_CR_MASTER_MODE_MASK |
|
||||
XSP_CR_TRANS_INHIBIT_MASK;
|
||||
|
||||
_write(xdesc, XSP_CR_OFFSET, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize spi_desc structure and device */
|
||||
static int32_t xil_spi_init_pl(struct spi_desc **desc,
|
||||
const struct spi_init_param *param)
|
||||
{
|
||||
struct spi_desc *ldesc;
|
||||
struct xspi_desc *xdesc;
|
||||
int32_t err;
|
||||
XSpi_Config *cfg;
|
||||
|
||||
if (!desc || !param || param->device_id >= XPAR_XSPI_NUM_INSTANCES)
|
||||
return -EINVAL;
|
||||
|
||||
cfg = XSpi_LookupConfig(param->device_id);
|
||||
if (!cfg)
|
||||
return -EINVAL;
|
||||
|
||||
if (param->chip_select > cfg->NumSlaveBits)
|
||||
return -EINVAL;
|
||||
|
||||
ldesc = (struct spi_desc *)calloc(1, sizeof(*ldesc));
|
||||
if (!ldesc)
|
||||
return -ENOMEM;
|
||||
|
||||
xdesc = (struct xspi_desc *)calloc(1, sizeof(*xdesc));
|
||||
if (!xdesc) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ldesc->bit_order = param->bit_order;
|
||||
ldesc->chip_select = param->chip_select;
|
||||
ldesc->mode = param->mode;
|
||||
xdesc->base_addr = cfg->BaseAddress;
|
||||
xdesc->disable_slaves_mask = (1 << cfg->NumSlaveBits) - 1;
|
||||
xdesc->cs_asserted = 0;
|
||||
|
||||
err = _xil_spi_init_dev(xdesc);
|
||||
if (IS_ERR_VALUE(err))
|
||||
goto error;
|
||||
|
||||
ldesc->extra = xdesc;
|
||||
*desc = ldesc;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(xdesc);
|
||||
free(ldesc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Remove allocated resources */
|
||||
static int32_t xil_spi_remove_pl(struct spi_desc *desc)
|
||||
{
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
free(desc->extra);
|
||||
free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill fifo until fifo is full or no more data available.
|
||||
* Return the number of written bytes.
|
||||
*/
|
||||
static uint32_t _wr_fifo(struct xspi_desc *xdesc, uint8_t *data,
|
||||
uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t to_write;
|
||||
uint32_t tx_available;
|
||||
|
||||
tx_available = xdesc->fifo_depth - _read(xdesc, XSP_TFO_OFFSET);
|
||||
to_write = min(tx_available, len);
|
||||
for (i = 0; i < to_write; ++i)
|
||||
if (data)
|
||||
_write(xdesc, XSP_DTR_OFFSET, data[i]);
|
||||
else
|
||||
_write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA);
|
||||
|
||||
return to_write;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read fifo until fifo is empty or no more buffer available to read into
|
||||
* Returns the number of read bytes
|
||||
*/
|
||||
static uint32_t _rd_fifo(struct xspi_desc *xdesc, uint8_t *data,
|
||||
uint32_t len)
|
||||
{
|
||||
uint32_t rx_available;
|
||||
uint32_t to_read;
|
||||
uint32_t tmp;
|
||||
uint32_t i;
|
||||
|
||||
tmp = _read(xdesc, XSP_SR_OFFSET);
|
||||
if (tmp & XSP_SR_RX_EMPTY_MASK)
|
||||
return 0;
|
||||
|
||||
rx_available = _read(xdesc, XSP_RFO_OFFSET) + 1;
|
||||
to_read = min(rx_available, len);
|
||||
for (i = 0; i < to_read; ++i) {
|
||||
tmp = _read(xdesc, XSP_DRR_OFFSET);
|
||||
if (data)
|
||||
data[i] = tmp;
|
||||
}
|
||||
|
||||
return to_read;
|
||||
}
|
||||
|
||||
/* If start is 0 stop transfer, else start it.
|
||||
* CS will be asserted if needed. If different CS othere than the one needed
|
||||
* is asserted. Deassert it and assert correct one */
|
||||
static void _xil_spi_start_transfer(struct spi_desc *desc, uint8_t start)
|
||||
{
|
||||
struct xspi_desc *xdesc;
|
||||
|
||||
xdesc = desc->extra;
|
||||
if (start) {
|
||||
if (xdesc->cs_asserted) {
|
||||
if (desc->chip_select ==
|
||||
g_spi_desc[desc->device_id].chip_select)
|
||||
return ;
|
||||
else
|
||||
/* Stop transfer to start again with new CS */
|
||||
_xil_spi_start_transfer(desc, 0);
|
||||
}
|
||||
_write(xdesc, XSP_SSR_OFFSET, ~(1 << desc->chip_select));
|
||||
_wr_mask(xdesc, XSP_CR_OFFSET, 0, XSP_CR_TRANS_INHIBIT_MASK);
|
||||
} else {
|
||||
_wr_mask(xdesc, XSP_CR_OFFSET, XSP_CR_TRANS_INHIBIT_MASK,
|
||||
XSP_CR_TRANS_INHIBIT_MASK);
|
||||
_write(xdesc, XSP_SSR_OFFSET, xdesc->disable_slaves_mask);
|
||||
}
|
||||
xdesc->cs_asserted = start;
|
||||
}
|
||||
|
||||
|
||||
/* SPI polled transfer */
|
||||
static int32_t xil_spi_write_and_read_pl(struct spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number)
|
||||
{
|
||||
struct xspi_desc *xdesc;
|
||||
uint32_t rx;
|
||||
uint32_t tx;
|
||||
|
||||
if (!desc || !desc->extra)
|
||||
return -EINVAL;
|
||||
|
||||
xdesc = desc->extra;
|
||||
_update_mode(desc);
|
||||
|
||||
_xil_spi_start_transfer(desc, 1);
|
||||
rx = 0;
|
||||
tx = 0;
|
||||
while (rx < bytes_number) {
|
||||
if (tx < bytes_number)
|
||||
tx += _wr_fifo(xdesc, data + tx, bytes_number - tx);
|
||||
rx += _rd_fifo(xdesc, data + rx, bytes_number - rx);
|
||||
}
|
||||
_xil_spi_start_transfer(desc, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get type of message. It can be READ, WRITE or both */
|
||||
static uint32_t _get_msg_type(struct spi_msg *msg)
|
||||
{
|
||||
uint32_t type;
|
||||
|
||||
type = 0;
|
||||
if (msg->tx_buff)
|
||||
type |= XPS_TYPE_WRITE;
|
||||
if (msg->rx_buff)
|
||||
type |= XPS_TYPE_READ;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Get information based on current iterator position */
|
||||
static void _get_data(struct msg_iter *it, uint8_t **buff, uint32_t *len,
|
||||
uint32_t *type)
|
||||
{
|
||||
struct spi_msg *msg;
|
||||
|
||||
if (it->i == it->len) {
|
||||
*len = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
msg = it->msgs + it->i;
|
||||
if (it->is_wr)
|
||||
*buff = msg->tx_buff;
|
||||
else
|
||||
*buff = msg->rx_buff;
|
||||
|
||||
if (*buff)
|
||||
*buff += it->buff_i;
|
||||
|
||||
*len = msg->bytes_number - it->buff_i;
|
||||
if (type)
|
||||
*type = _get_msg_type(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment iterator position with desired length.
|
||||
* If the new position has a different message type, new_type will be set to 1
|
||||
* If a CS change is needed, cs_change is set
|
||||
*/
|
||||
static void _increment_iter(struct msg_iter *it, uint32_t len,
|
||||
uint8_t *cs_change, uint8_t *new_type)
|
||||
{
|
||||
struct spi_msg *msg;
|
||||
uint32_t type;
|
||||
uint32_t extra_len;
|
||||
|
||||
if (!len)
|
||||
return ;
|
||||
|
||||
*cs_change = 0;
|
||||
*new_type = 0;
|
||||
msg = it->msgs + it->i;
|
||||
if (it->buff_i + len > msg->bytes_number)
|
||||
extra_len = it->buff_i + len - msg->bytes_number;
|
||||
else
|
||||
extra_len = 0;
|
||||
len -= extra_len;
|
||||
it->buff_i += len;
|
||||
if (it->buff_i == msg->bytes_number) {
|
||||
type = _get_msg_type(msg);
|
||||
++it->i;
|
||||
it->buff_i = 0;
|
||||
if (cs_change && msg->cs_change)
|
||||
*cs_change = 1;
|
||||
if (new_type)
|
||||
if (it->i == it->len ||
|
||||
type != _get_msg_type(it->msgs + it->i))
|
||||
*new_type = 1;
|
||||
}
|
||||
if (extra_len)
|
||||
_increment_iter(it, extra_len, cs_change, new_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* SPI polling transfer of multiple messages.
|
||||
*/
|
||||
static int32_t xil_spi_transfer_pl(struct spi_desc *desc,
|
||||
struct spi_msg *msgs,
|
||||
uint32_t len)
|
||||
|
||||
{
|
||||
struct xspi_desc *xdesc;
|
||||
uint8_t cs_change;
|
||||
uint8_t new_type;
|
||||
struct msg_iter rx = {.msgs = msgs, .len = len, .is_wr = 0};
|
||||
struct msg_iter tx = {.msgs = msgs, .len = len, .is_wr = 1};
|
||||
uint8_t *buff;
|
||||
uint32_t bytes;
|
||||
uint32_t type;
|
||||
/* Bytes to increment rx when only a write transaction is executed */
|
||||
uint32_t to_inc_rx;
|
||||
/* Difference between rx and tx iterators in bytes */
|
||||
uint32_t tx_advance;
|
||||
/* Save bytes sent during a write loop */
|
||||
uint32_t tx_sent;
|
||||
/* Used to loop if need to empty the RX FIFO */
|
||||
uint32_t loop;
|
||||
|
||||
if (!desc || !desc->extra)
|
||||
return -EINVAL;
|
||||
|
||||
xdesc = desc->extra;
|
||||
_update_mode(desc);
|
||||
|
||||
tx_advance = 0;
|
||||
to_inc_rx = 0;
|
||||
buff = NULL;
|
||||
type = 0;
|
||||
do {
|
||||
_xil_spi_start_transfer(desc, 1);
|
||||
|
||||
tx_sent = 0;
|
||||
/* Writing loop */
|
||||
do {
|
||||
_get_data(&tx, &buff, &bytes, &type);
|
||||
if (type & XPS_TYPE_READ)
|
||||
/*
|
||||
* Do not write more bytes than fifo_depth if
|
||||
* they haven't been read.
|
||||
*/
|
||||
bytes = min(bytes,
|
||||
xdesc->fifo_depth - tx_advance);
|
||||
bytes = _wr_fifo(xdesc, buff, bytes);
|
||||
tx_sent += bytes;
|
||||
_increment_iter(&tx, bytes, &cs_change, &new_type);
|
||||
tx_advance += bytes;
|
||||
} while (!cs_change && !new_type && bytes);
|
||||
|
||||
if (type & XPS_TYPE_READ) {
|
||||
loop = 1;
|
||||
/*
|
||||
* Loop only when no more data to write otherwise read
|
||||
* only available data.
|
||||
*/
|
||||
while (loop) {
|
||||
if (!new_type)
|
||||
loop = 0;
|
||||
_get_data(&rx, &buff, &bytes, NULL);
|
||||
bytes = _rd_fifo(xdesc, buff, bytes);
|
||||
_increment_iter(&rx, bytes, &cs_change, &new_type);
|
||||
tx_advance -= bytes;
|
||||
if (loop && new_type)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Clean RX FIFO if it was only a WRITE message */
|
||||
to_inc_rx += tx_sent;
|
||||
if (new_type) {
|
||||
/* Wait for TX to be sent */
|
||||
while (!(_read(xdesc, XSP_SR_OFFSET) &
|
||||
XSP_SR_TX_EMPTY_MASK))
|
||||
;
|
||||
/* Reset fifo. Only write was performed */
|
||||
_wr_mask(xdesc, XSP_CR_OFFSET,
|
||||
XSP_CR_RXFIFO_RESET_MASK,
|
||||
XSP_CR_RXFIFO_RESET_MASK);
|
||||
|
||||
_increment_iter(&rx, to_inc_rx, NULL, NULL);
|
||||
tx_advance -= to_inc_rx;
|
||||
to_inc_rx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cs_change && rx.i != len) || (!cs_change && rx.i == len))
|
||||
_xil_spi_start_transfer(desc, 0);
|
||||
} while (rx.i < len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct spi_platform_ops xil_spi_pl_ops = {
|
||||
.init = xil_spi_init_pl,
|
||||
.remove = xil_spi_remove_pl,
|
||||
.write_and_read = xil_spi_write_and_read_pl,
|
||||
.transfer = xil_spi_transfer_pl
|
||||
};
|
||||
|
||||
#endif // XPAR_XSPI_NUM_INSTANCES
|
||||
@@ -0,0 +1,456 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx/xilinx_timer.c
|
||||
* @brief Timer and GIC control module source.
|
||||
* @author Andrei Drimbarean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <xparameters.h>
|
||||
#include "timer.h"
|
||||
#include "xilinx_timer.h"
|
||||
#include "error.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
#if defined(_XPARAMETERS_PS_H_)
|
||||
#define CORE_PRIVATE_TIMER_CLOCK (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ / 2)
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Set the current counter value of the timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] new_val - New value for the timer counter.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_counter_set(struct timer_desc *desc,
|
||||
uint32_t new_val)
|
||||
{
|
||||
struct xil_timer_desc *xdesc;
|
||||
|
||||
if (!desc)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
XScuTimer_LoadTimer((XScuTimer *)xdesc->instance, new_val - 1);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
XTmrCtr_SetResetValue(xdesc->instance, xdesc->active_tmr, new_val);
|
||||
XTmrCtr_Reset(xdesc->instance, xdesc->active_tmr);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the timer clock frequency.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] freq_hz - New timer frequency in hertz.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_count_clk_set(struct timer_desc *desc,
|
||||
uint32_t freq_hz)
|
||||
{
|
||||
struct xil_timer_desc *xdesc;
|
||||
|
||||
if (!desc || !freq_hz)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
;
|
||||
uint32_t prescaler = CORE_PRIVATE_TIMER_CLOCK / freq_hz;
|
||||
if (prescaler == 0 || prescaler >= 256)
|
||||
return -1;
|
||||
XScuTimer_SetPrescaler(xdesc->instance, prescaler - 1);
|
||||
desc->freq_hz = CORE_PRIVATE_TIMER_CLOCK / prescaler;
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
(void *)xdesc;
|
||||
/** Cannot be done. */
|
||||
#endif
|
||||
return -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize hardware timer and the handler structure associated with
|
||||
* it.
|
||||
* @param [out] desc - Pointer to the reference of the device handler.
|
||||
* @param [in] param - Initialization structure.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_init(struct timer_desc **desc,
|
||||
const struct timer_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
struct timer_desc *dev;
|
||||
struct xil_timer_desc *xdesc;
|
||||
struct xil_timer_init_param *xinit;
|
||||
|
||||
if (!desc || !param)
|
||||
return -1;
|
||||
|
||||
xinit = param->extra;
|
||||
|
||||
dev = (struct timer_desc *)calloc(1, sizeof(*dev));
|
||||
if(!dev)
|
||||
return -1;
|
||||
xdesc = (struct xil_timer_desc *)calloc(1, sizeof(*xdesc));
|
||||
if(!xdesc)
|
||||
goto error_desc;
|
||||
|
||||
dev->id = param->id;
|
||||
dev->freq_hz = param->freq_hz;
|
||||
dev->ticks_count = param->ticks_count;
|
||||
dev->extra = xdesc;
|
||||
xdesc->active_tmr = xinit->active_tmr;
|
||||
xdesc->type = xinit->type;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
xdesc->config = XScuTimer_LookupConfig(dev->id);
|
||||
xdesc->instance = calloc(1, sizeof(XScuTimer));
|
||||
if (!xdesc->instance)
|
||||
goto error_xdesc;
|
||||
ret = XScuTimer_CfgInitialize(xdesc->instance, xdesc->config,
|
||||
((XScuTimer_Config *)xdesc->config)->BaseAddr);
|
||||
if (ret != XST_SUCCESS) {
|
||||
free(xdesc->instance);
|
||||
goto error_xdesc;
|
||||
}
|
||||
ret = xilinx_timer_count_clk_set(dev, param->freq_hz);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
goto error_xdesc;
|
||||
|
||||
ret = xilinx_timer_counter_set(dev, dev->ticks_count);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
goto error_xdesc;
|
||||
|
||||
XScuTimer_EnableAutoReload((XScuTimer *)xdesc->instance);
|
||||
XScuTimer_EnableInterrupt((XScuTimer *)xdesc->instance);
|
||||
break;
|
||||
#endif
|
||||
goto error_xdesc;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
xdesc->instance = (XTmrCtr *)calloc(1, sizeof(XTmrCtr));
|
||||
if (!xdesc->instance)
|
||||
return -1;
|
||||
|
||||
xdesc->config = XTmrCtr_LookupConfig(dev->id);
|
||||
if (!xdesc->config) {
|
||||
free(xdesc->instance);
|
||||
goto error_desc;
|
||||
}
|
||||
XTmrCtr_CfgInitialize(xdesc->instance, xdesc->config,
|
||||
((XTmrCtr_Config *)xdesc->config)->BaseAddress);
|
||||
ret = XTmrCtr_InitHw(xdesc->instance);
|
||||
if (ret != 0) {
|
||||
free(xdesc->instance);
|
||||
goto error_desc;
|
||||
}
|
||||
dev->freq_hz = ((XTmrCtr_Config *)xdesc->config)->SysClockFreqHz;
|
||||
|
||||
ret = XTmrCtr_SelfTest(xdesc->instance, dev->id);
|
||||
if(ret != 0)
|
||||
goto error_desc;
|
||||
XTmrCtr_SetOptions(xdesc->instance, xdesc->active_tmr,
|
||||
XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION |
|
||||
XTC_AUTO_RELOAD_OPTION);
|
||||
XTmrCtr_SetResetValue(xdesc->instance, xdesc->active_tmr,
|
||||
dev->ticks_count);
|
||||
break;
|
||||
#endif
|
||||
goto error_xdesc;
|
||||
default:
|
||||
goto error_xdesc;
|
||||
}
|
||||
|
||||
*desc = dev;
|
||||
|
||||
return 0;
|
||||
|
||||
error_xdesc:
|
||||
free(xdesc);
|
||||
error_desc:
|
||||
free(dev);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the memory allocated by timer_setup().
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_remove(struct timer_desc *desc)
|
||||
{
|
||||
struct xil_timer_desc *xdesc;
|
||||
|
||||
if(!desc)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
XScuTimer_Stop(xdesc->instance);
|
||||
free(xdesc->instance);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
XTmrCtr_Stop(xdesc->instance, xdesc->active_tmr);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(xdesc);
|
||||
free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start a timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_start(struct timer_desc *desc)
|
||||
{
|
||||
struct xil_timer_desc *xdesc;
|
||||
|
||||
if (!desc)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
XScuTimer_Start(xdesc->instance);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
XTmrCtr_Start(xdesc->instance, xdesc->active_tmr);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop a timer from counting.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_stop(struct timer_desc *desc)
|
||||
{
|
||||
struct xil_timer_desc *xdesc;
|
||||
|
||||
if (!desc)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
XScuTimer_Stop(xdesc->instance);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
XTmrCtr_Stop(xdesc->instance, xdesc->active_tmr);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current counter value of the timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [out] counter - Pointer to the current counter value.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_counter_get(struct timer_desc *desc,
|
||||
uint32_t *counter)
|
||||
{
|
||||
struct xil_timer_desc *xdesc;
|
||||
|
||||
if (!desc || !counter)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
*counter = XScuTimer_GetCounterValue((XScuTimer *)xdesc->instance);
|
||||
++(*counter);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
*counter = XTmrCtr_GetValue(xdesc->instance, xdesc->active_tmr);
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
default:
|
||||
*counter = 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the timer clock frequency.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [out] freq_hz - Pointer to the returned frequency.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t xilinx_timer_count_clk_get(struct timer_desc *desc,
|
||||
uint32_t *freq_hz)
|
||||
{
|
||||
struct xil_timer_desc *xdesc;
|
||||
|
||||
if (!desc || !freq_hz)
|
||||
return -1;
|
||||
|
||||
xdesc = desc->extra;
|
||||
|
||||
switch (xdesc->type) {
|
||||
case TIMER_PS:
|
||||
#ifdef XSCUTIMER_H
|
||||
*freq_hz = desc->freq_hz;
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
case TIMER_PL:
|
||||
#ifdef XTMRCTR_H
|
||||
*freq_hz = ((XTmrCtr_Config *)xdesc->config)->SysClockFreqHz;
|
||||
break;
|
||||
#endif
|
||||
return -1;
|
||||
default:
|
||||
*freq_hz = 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the elapsed time in nsec for the timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] elapsed_time - The elapsed time in nsec.
|
||||
* @return -ENOSYS.
|
||||
*/
|
||||
int32_t xilinx_timer_get_elapsed_time_nsec(struct timer_desc *desc,
|
||||
uint64_t *elapsed_time)
|
||||
{
|
||||
/* Function not implemented */
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific timer platform ops structure
|
||||
*/
|
||||
const struct timer_platform_ops xil_timer_ops = {
|
||||
.init = &xilinx_timer_init,
|
||||
.start = &xilinx_timer_start,
|
||||
.stop = &xilinx_timer_stop,
|
||||
.counter_get = &xilinx_timer_counter_get,
|
||||
.counter_set = &xilinx_timer_counter_set,
|
||||
.count_clk_get = &xilinx_timer_count_clk_get,
|
||||
.count_clk_set = &xilinx_timer_count_clk_set,
|
||||
.get_elapsed_time_nsec = &xilinx_timer_get_elapsed_time_nsec,
|
||||
.remove = &xilinx_timer_remove
|
||||
};
|
||||
@@ -0,0 +1,101 @@
|
||||
/***************************************************************************//**
|
||||
* @file xilinx_timer.h
|
||||
* @brief Timer control module header.
|
||||
* @author Andrei Drimbarean ([email protected])
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef XILINX_TIMER_H_
|
||||
#define XILINX_TIMER_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <xparameters.h>
|
||||
#ifdef XPAR_XSCUTIMER_NUM_INSTANCES
|
||||
#include <xscutimer.h>
|
||||
#endif
|
||||
#ifdef XPAR_XTMRCTR_NUM_INSTANCES
|
||||
#include <xtmrctr.h>
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @enum xil_timer_type
|
||||
* @brief Xilinx platform architecture sections
|
||||
*/
|
||||
enum xil_timer_type {
|
||||
/** Programmable Logic */
|
||||
TIMER_PL,
|
||||
/** Processing System */
|
||||
TIMER_PS
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_timer_desc
|
||||
* @brief Xilinx specific timer descriptor
|
||||
*/
|
||||
struct xil_timer_desc {
|
||||
/** Pointer to the BSP driver handler */
|
||||
void *instance;
|
||||
/** Pointer to the BSP driver configuration handler */
|
||||
void *config;
|
||||
/** Timer used from the PL 3-timer core */
|
||||
uint8_t active_tmr;
|
||||
/** Platform selection parameter */
|
||||
enum xil_timer_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct xil_timer_init_param
|
||||
* @brief Xilinx specific timer initialization structure
|
||||
*/
|
||||
struct xil_timer_init_param {
|
||||
/** Timer used from the PL 3-timer core */
|
||||
uint8_t active_tmr;
|
||||
/** Platform selection parameter */
|
||||
enum xil_timer_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Xilinx platform specific timer platform ops structure
|
||||
*/
|
||||
extern const struct timer_platform_ops xil_timer_ops;
|
||||
|
||||
#endif /* XILINX_TIMER_H_ */
|
||||
+7475
File diff suppressed because it is too large
Load Diff
+3568
File diff suppressed because it is too large
Load Diff
+2157
File diff suppressed because it is too large
Load Diff
+552
@@ -0,0 +1,552 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9361_api.h
|
||||
* @brief Header file of AD9361 API Driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2013(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef AD9361_API_H_
|
||||
#define AD9361_API_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include "ad9361_util.h"
|
||||
#include "gpio.h"
|
||||
#include "spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
typedef struct {
|
||||
/* Device selection */
|
||||
enum dev_id dev_sel;
|
||||
/* Reference Clock */
|
||||
uint32_t reference_clk_rate;
|
||||
/* Base Configuration */
|
||||
uint8_t two_rx_two_tx_mode_enable; /* adi,2rx-2tx-mode-enable */
|
||||
uint8_t one_rx_one_tx_mode_use_rx_num; /* adi,1rx-1tx-mode-use-rx-num */
|
||||
uint8_t one_rx_one_tx_mode_use_tx_num; /* adi,1rx-1tx-mode-use-tx-num */
|
||||
uint8_t frequency_division_duplex_mode_enable; /* adi,frequency-division-duplex-mode-enable */
|
||||
uint8_t frequency_division_duplex_independent_mode_enable; /* adi,frequency-division-duplex-independent-mode-enable */
|
||||
uint8_t tdd_use_dual_synth_mode_enable; /* adi,tdd-use-dual-synth-mode-enable */
|
||||
uint8_t tdd_skip_vco_cal_enable; /* adi,tdd-skip-vco-cal-enable */
|
||||
uint32_t tx_fastlock_delay_ns; /* adi,tx-fastlock-delay-ns */
|
||||
uint32_t rx_fastlock_delay_ns; /* adi,rx-fastlock-delay-ns */
|
||||
uint8_t rx_fastlock_pincontrol_enable; /* adi,rx-fastlock-pincontrol-enable */
|
||||
uint8_t tx_fastlock_pincontrol_enable; /* adi,tx-fastlock-pincontrol-enable */
|
||||
uint8_t external_rx_lo_enable; /* adi,external-rx-lo-enable */
|
||||
uint8_t external_tx_lo_enable; /* adi,external-tx-lo-enable */
|
||||
uint8_t dc_offset_tracking_update_event_mask; /* adi,dc-offset-tracking-update-event-mask */
|
||||
uint8_t dc_offset_attenuation_high_range; /* adi,dc-offset-attenuation-high-range */
|
||||
uint8_t dc_offset_attenuation_low_range; /* adi,dc-offset-attenuation-low-range */
|
||||
uint8_t dc_offset_count_high_range; /* adi,dc-offset-count-high-range */
|
||||
uint8_t dc_offset_count_low_range; /* adi,dc-offset-count-low-range */
|
||||
uint8_t split_gain_table_mode_enable; /* adi,split-gain-table-mode-enable */
|
||||
uint32_t trx_synthesizer_target_fref_overwrite_hz; /* adi,trx-synthesizer-target-fref-overwrite-hz */
|
||||
uint8_t qec_tracking_slow_mode_enable; /* adi,qec-tracking-slow-mode-enable */
|
||||
/* ENSM Control */
|
||||
uint8_t ensm_enable_pin_pulse_mode_enable; /* adi,ensm-enable-pin-pulse-mode-enable */
|
||||
uint8_t ensm_enable_txnrx_control_enable; /* adi,ensm-enable-txnrx-control-enable */
|
||||
/* LO Control */
|
||||
uint64_t rx_synthesizer_frequency_hz; /* adi,rx-synthesizer-frequency-hz */
|
||||
uint64_t tx_synthesizer_frequency_hz; /* adi,tx-synthesizer-frequency-hz */
|
||||
uint8_t tx_lo_powerdown_managed_enable; /* adi,tx-lo-powerdown-managed-enable */
|
||||
/* Rate & BW Control */
|
||||
uint32_t rx_path_clock_frequencies[6]; /* adi,rx-path-clock-frequencies */
|
||||
uint32_t tx_path_clock_frequencies[6]; /* adi,tx-path-clock-frequencies */
|
||||
uint32_t rf_rx_bandwidth_hz; /* adi,rf-rx-bandwidth-hz */
|
||||
uint32_t rf_tx_bandwidth_hz; /* adi,rf-tx-bandwidth-hz */
|
||||
/* RF Port Control */
|
||||
uint32_t rx_rf_port_input_select; /* adi,rx-rf-port-input-select */
|
||||
uint32_t tx_rf_port_input_select; /* adi,tx-rf-port-input-select */
|
||||
/* TX Attenuation Control */
|
||||
int32_t tx_attenuation_mdB; /* adi,tx-attenuation-mdB */
|
||||
uint8_t update_tx_gain_in_alert_enable; /* adi,update-tx-gain-in-alert-enable */
|
||||
/* Reference Clock Control */
|
||||
uint8_t xo_disable_use_ext_refclk_enable; /* adi,xo-disable-use-ext-refclk-enable */
|
||||
uint32_t dcxo_coarse_and_fine_tune[2]; /* adi,dcxo-coarse-and-fine-tune */
|
||||
uint32_t clk_output_mode_select; /* adi,clk-output-mode-select */
|
||||
/* Gain Control */
|
||||
uint8_t gc_rx1_mode; /* adi,gc-rx1-mode */
|
||||
uint8_t gc_rx2_mode; /* adi,gc-rx2-mode */
|
||||
uint8_t gc_adc_large_overload_thresh; /* adi,gc-adc-large-overload-thresh */
|
||||
uint8_t gc_adc_ovr_sample_size; /* adi,gc-adc-ovr-sample-size */
|
||||
uint8_t gc_adc_small_overload_thresh; /* adi,gc-adc-small-overload-thresh */
|
||||
uint16_t gc_dec_pow_measurement_duration; /* adi,gc-dec-pow-measurement-duration */
|
||||
uint8_t gc_dig_gain_enable; /* adi,gc-dig-gain-enable */
|
||||
uint16_t gc_lmt_overload_high_thresh; /* adi,gc-lmt-overload-high-thresh */
|
||||
uint16_t gc_lmt_overload_low_thresh; /* adi,gc-lmt-overload-low-thresh */
|
||||
uint8_t gc_low_power_thresh; /* adi,gc-low-power-thresh */
|
||||
uint8_t gc_max_dig_gain; /* adi,gc-max-dig-gain */
|
||||
uint8_t gc_use_rx_fir_out_for_dec_pwr_meas_enable; /* adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable */
|
||||
/* Gain MGC Control */
|
||||
uint8_t mgc_dec_gain_step; /* adi,mgc-dec-gain-step */
|
||||
uint8_t mgc_inc_gain_step; /* adi,mgc-inc-gain-step */
|
||||
uint8_t mgc_rx1_ctrl_inp_enable; /* adi,mgc-rx1-ctrl-inp-enable */
|
||||
uint8_t mgc_rx2_ctrl_inp_enable; /* adi,mgc-rx2-ctrl-inp-enable */
|
||||
uint8_t mgc_split_table_ctrl_inp_gain_mode; /* adi,mgc-split-table-ctrl-inp-gain-mode */
|
||||
/* Gain AGC Control */
|
||||
uint8_t agc_adc_large_overload_exceed_counter; /* adi,agc-adc-large-overload-exceed-counter */
|
||||
uint8_t agc_adc_large_overload_inc_steps; /* adi,agc-adc-large-overload-inc-steps - Name is misleading should be dec-steps*/
|
||||
uint8_t agc_adc_lmt_small_overload_prevent_gain_inc_enable; /* adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable */
|
||||
uint8_t agc_adc_small_overload_exceed_counter; /* adi,agc-adc-small-overload-exceed-counter */
|
||||
uint8_t agc_dig_gain_step_size; /* adi,agc-dig-gain-step-size */
|
||||
uint8_t agc_dig_saturation_exceed_counter; /* adi,agc-dig-saturation-exceed-counter */
|
||||
uint32_t agc_gain_update_interval_us; /* adi,agc-gain-update-interval-us */
|
||||
uint8_t agc_immed_gain_change_if_large_adc_overload_enable; /* adi,agc-immed-gain-change-if-large-adc-overload-enable */
|
||||
uint8_t agc_immed_gain_change_if_large_lmt_overload_enable; /* adi,agc-immed-gain-change-if-large-lmt-overload-enable */
|
||||
uint8_t agc_inner_thresh_high; /* adi,agc-inner-thresh-high */
|
||||
uint8_t agc_inner_thresh_high_dec_steps; /* adi,agc-inner-thresh-high-dec-steps */
|
||||
uint8_t agc_inner_thresh_low; /* adi,agc-inner-thresh-low */
|
||||
uint8_t agc_inner_thresh_low_inc_steps; /* adi,agc-inner-thresh-low-inc-steps */
|
||||
uint8_t agc_lmt_overload_large_exceed_counter; /* adi,agc-lmt-overload-large-exceed-counter */
|
||||
uint8_t agc_lmt_overload_large_inc_steps; /* adi,agc-lmt-overload-large-inc-steps */
|
||||
uint8_t agc_lmt_overload_small_exceed_counter; /* adi,agc-lmt-overload-small-exceed-counter */
|
||||
uint8_t agc_outer_thresh_high; /* adi,agc-outer-thresh-high */
|
||||
uint8_t agc_outer_thresh_high_dec_steps; /* adi,agc-outer-thresh-high-dec-steps */
|
||||
uint8_t agc_outer_thresh_low; /* adi,agc-outer-thresh-low */
|
||||
uint8_t agc_outer_thresh_low_inc_steps; /* adi,agc-outer-thresh-low-inc-steps */
|
||||
uint32_t agc_attack_delay_extra_margin_us; /* adi,agc-attack-delay-extra-margin-us */
|
||||
uint8_t agc_sync_for_gain_counter_enable; /* adi,agc-sync-for-gain-counter-enable */
|
||||
/* Fast AGC */
|
||||
uint32_t fagc_dec_pow_measuremnt_duration; /* adi,fagc-dec-pow-measurement-duration */
|
||||
uint32_t fagc_state_wait_time_ns; /* adi,fagc-state-wait-time-ns */
|
||||
/* Fast AGC - Low Power */
|
||||
uint8_t fagc_allow_agc_gain_increase; /* adi,fagc-allow-agc-gain-increase-enable */
|
||||
uint32_t fagc_lp_thresh_increment_time; /* adi,fagc-lp-thresh-increment-time */
|
||||
uint32_t fagc_lp_thresh_increment_steps; /* adi,fagc-lp-thresh-increment-steps */
|
||||
/* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */
|
||||
uint8_t fagc_lock_level_lmt_gain_increase_en; /* adi,fagc-lock-level-lmt-gain-increase-enable */
|
||||
uint32_t fagc_lock_level_gain_increase_upper_limit; /* adi,fagc-lock-level-gain-increase-upper-limit */
|
||||
/* Fast AGC - Peak Detectors and Final Settling */
|
||||
uint32_t fagc_lpf_final_settling_steps; /* adi,fagc-lpf-final-settling-steps */
|
||||
uint32_t fagc_lmt_final_settling_steps; /* adi,fagc-lmt-final-settling-steps */
|
||||
uint32_t fagc_final_overrange_count; /* adi,fagc-final-overrange-count */
|
||||
/* Fast AGC - Final Power Test */
|
||||
uint8_t fagc_gain_increase_after_gain_lock_en; /* adi,fagc-gain-increase-after-gain-lock-enable */
|
||||
/* Fast AGC - Unlocking the Gain */
|
||||
uint32_t fagc_gain_index_type_after_exit_rx_mode; /* adi,fagc-gain-index-type-after-exit-rx-mode */
|
||||
uint8_t fagc_use_last_lock_level_for_set_gain_en; /* adi,fagc-use-last-lock-level-for-set-gain-enable */
|
||||
uint8_t fagc_rst_gla_stronger_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable */
|
||||
uint32_t fagc_optimized_gain_offset; /* adi,fagc-optimized-gain-offset */
|
||||
uint32_t fagc_rst_gla_stronger_sig_thresh_above_ll; /* adi,fagc-rst-gla-stronger-sig-thresh-above-ll */
|
||||
uint8_t fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable */
|
||||
uint8_t fagc_rst_gla_engergy_lost_goto_optim_gain_en; /* adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable */
|
||||
uint32_t fagc_rst_gla_engergy_lost_sig_thresh_below_ll; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll */
|
||||
uint32_t fagc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt */
|
||||
uint8_t fagc_rst_gla_large_adc_overload_en; /* adi,fagc-rst-gla-large-adc-overload-enable */
|
||||
uint8_t fagc_rst_gla_large_lmt_overload_en; /* adi,fagc-rst-gla-large-lmt-overload-enable */
|
||||
uint8_t fagc_rst_gla_en_agc_pulled_high_en; /* adi,fagc-rst-gla-en-agc-pulled-high-enable */
|
||||
uint32_t fagc_rst_gla_if_en_agc_pulled_high_mode; /* adi,fagc-rst-gla-if-en-agc-pulled-high-mode */
|
||||
uint32_t fagc_power_measurement_duration_in_state5; /* adi,fagc-power-measurement-duration-in-state5 */
|
||||
uint32_t fagc_large_overload_inc_steps; /* adi,fagc-adc-large-overload-inc-steps - Name is misleading should be dec-steps */
|
||||
/* RSSI Control */
|
||||
uint32_t rssi_delay; /* adi,rssi-delay */
|
||||
uint32_t rssi_duration; /* adi,rssi-duration */
|
||||
uint8_t rssi_restart_mode; /* adi,rssi-restart-mode */
|
||||
uint8_t rssi_unit_is_rx_samples_enable; /* adi,rssi-unit-is-rx-samples-enable */
|
||||
uint32_t rssi_wait; /* adi,rssi-wait */
|
||||
/* Aux ADC Control */
|
||||
uint32_t aux_adc_decimation; /* adi,aux-adc-decimation */
|
||||
uint32_t aux_adc_rate; /* adi,aux-adc-rate */
|
||||
/* AuxDAC Control */
|
||||
uint8_t aux_dac_manual_mode_enable; /* adi,aux-dac-manual-mode-enable */
|
||||
uint32_t aux_dac1_default_value_mV; /* adi,aux-dac1-default-value-mV */
|
||||
uint8_t aux_dac1_active_in_rx_enable; /* adi,aux-dac1-active-in-rx-enable */
|
||||
uint8_t aux_dac1_active_in_tx_enable; /* adi,aux-dac1-active-in-tx-enable */
|
||||
uint8_t aux_dac1_active_in_alert_enable; /* adi,aux-dac1-active-in-alert-enable */
|
||||
uint32_t aux_dac1_rx_delay_us; /* adi,aux-dac1-rx-delay-us */
|
||||
uint32_t aux_dac1_tx_delay_us; /* adi,aux-dac1-tx-delay-us */
|
||||
uint32_t aux_dac2_default_value_mV; /* adi,aux-dac2-default-value-mV */
|
||||
uint8_t aux_dac2_active_in_rx_enable; /* adi,aux-dac2-active-in-rx-enable */
|
||||
uint8_t aux_dac2_active_in_tx_enable; /* adi,aux-dac2-active-in-tx-enable */
|
||||
uint8_t aux_dac2_active_in_alert_enable; /* adi,aux-dac2-active-in-alert-enable */
|
||||
uint32_t aux_dac2_rx_delay_us; /* adi,aux-dac2-rx-delay-us */
|
||||
uint32_t aux_dac2_tx_delay_us; /* adi,aux-dac2-tx-delay-us */
|
||||
/* Temperature Sensor Control */
|
||||
uint32_t temp_sense_decimation; /* adi,temp-sense-decimation */
|
||||
uint16_t temp_sense_measurement_interval_ms; /* adi,temp-sense-measurement-interval-ms */
|
||||
int8_t temp_sense_offset_signed; /* adi,temp-sense-offset-signed */
|
||||
uint8_t temp_sense_periodic_measurement_enable; /* adi,temp-sense-periodic-measurement-enable */
|
||||
/* Control Out Setup */
|
||||
uint8_t ctrl_outs_enable_mask; /* adi,ctrl-outs-enable-mask */
|
||||
uint8_t ctrl_outs_index; /* adi,ctrl-outs-index */
|
||||
/* External LNA Control */
|
||||
uint32_t elna_settling_delay_ns; /* adi,elna-settling-delay-ns */
|
||||
uint32_t elna_gain_mdB; /* adi,elna-gain-mdB */
|
||||
uint32_t elna_bypass_loss_mdB; /* adi,elna-bypass-loss-mdB */
|
||||
uint8_t elna_rx1_gpo0_control_enable; /* adi,elna-rx1-gpo0-control-enable */
|
||||
uint8_t elna_rx2_gpo1_control_enable; /* adi,elna-rx2-gpo1-control-enable */
|
||||
uint8_t elna_gaintable_all_index_enable; /* adi,elna-gaintable-all-index-enable */
|
||||
/* Digital Interface Control */
|
||||
uint8_t digital_interface_tune_skip_mode; /* adi,digital-interface-tune-skip-mode */
|
||||
uint8_t digital_interface_tune_fir_disable; /* adi,digital-interface-tune-fir-disable */
|
||||
uint8_t pp_tx_swap_enable; /* adi,pp-tx-swap-enable */
|
||||
uint8_t pp_rx_swap_enable; /* adi,pp-rx-swap-enable */
|
||||
uint8_t tx_channel_swap_enable; /* adi,tx-channel-swap-enable */
|
||||
uint8_t rx_channel_swap_enable; /* adi,rx-channel-swap-enable */
|
||||
uint8_t rx_frame_pulse_mode_enable; /* adi,rx-frame-pulse-mode-enable */
|
||||
uint8_t two_t_two_r_timing_enable; /* adi,2t2r-timing-enable */
|
||||
uint8_t invert_data_bus_enable; /* adi,invert-data-bus-enable */
|
||||
uint8_t invert_data_clk_enable; /* adi,invert-data-clk-enable */
|
||||
uint8_t fdd_alt_word_order_enable; /* adi,fdd-alt-word-order-enable */
|
||||
uint8_t invert_rx_frame_enable; /* adi,invert-rx-frame-enable */
|
||||
uint8_t fdd_rx_rate_2tx_enable; /* adi,fdd-rx-rate-2tx-enable */
|
||||
uint8_t swap_ports_enable; /* adi,swap-ports-enable */
|
||||
uint8_t single_data_rate_enable; /* adi,single-data-rate-enable */
|
||||
uint8_t lvds_mode_enable; /* adi,lvds-mode-enable */
|
||||
uint8_t half_duplex_mode_enable; /* adi,half-duplex-mode-enable */
|
||||
uint8_t single_port_mode_enable; /* adi,single-port-mode-enable */
|
||||
uint8_t full_port_enable; /* adi,full-port-enable */
|
||||
uint8_t full_duplex_swap_bits_enable; /* adi,full-duplex-swap-bits-enable */
|
||||
uint32_t delay_rx_data; /* adi,delay-rx-data */
|
||||
uint32_t rx_data_clock_delay; /* adi,rx-data-clock-delay */
|
||||
uint32_t rx_data_delay; /* adi,rx-data-delay */
|
||||
uint32_t tx_fb_clock_delay; /* adi,tx-fb-clock-delay */
|
||||
uint32_t tx_data_delay; /* adi,tx-data-delay */
|
||||
uint32_t lvds_bias_mV; /* adi,lvds-bias-mV */
|
||||
uint8_t lvds_rx_onchip_termination_enable; /* adi,lvds-rx-onchip-termination-enable */
|
||||
uint8_t rx1rx2_phase_inversion_en; /* adi,rx1-rx2-phase-inversion-enable */
|
||||
uint8_t lvds_invert1_control; /* adi,lvds-invert1-control */
|
||||
uint8_t lvds_invert2_control; /* adi,lvds-invert2-control */
|
||||
/* GPO Control */
|
||||
uint8_t gpo_manual_mode_enable; /* adi,gpo-manual-mode-enable */
|
||||
uint32_t gpo_manual_mode_enable_mask; /* adi,gpo-manual-mode-enable-mask */
|
||||
uint8_t gpo0_inactive_state_high_enable; /* adi,gpo0-inactive-state-high-enable */
|
||||
uint8_t gpo1_inactive_state_high_enable; /* adi,gpo1-inactive-state-high-enable */
|
||||
uint8_t gpo2_inactive_state_high_enable; /* adi,gpo2-inactive-state-high-enable */
|
||||
uint8_t gpo3_inactive_state_high_enable; /* adi,gpo3-inactive-state-high-enable */
|
||||
uint8_t gpo0_slave_rx_enable; /* adi,gpo0-slave-rx-enable */
|
||||
uint8_t gpo0_slave_tx_enable; /* adi,gpo0-slave-tx-enable */
|
||||
uint8_t gpo1_slave_rx_enable; /* adi,gpo1-slave-rx-enable */
|
||||
uint8_t gpo1_slave_tx_enable; /* adi,gpo1-slave-tx-enable */
|
||||
uint8_t gpo2_slave_rx_enable; /* adi,gpo2-slave-rx-enable */
|
||||
uint8_t gpo2_slave_tx_enable; /* adi,gpo2-slave-tx-enable */
|
||||
uint8_t gpo3_slave_rx_enable; /* adi,gpo3-slave-rx-enable */
|
||||
uint8_t gpo3_slave_tx_enable; /* adi,gpo3-slave-tx-enable */
|
||||
uint8_t gpo0_rx_delay_us; /* adi,gpo0-rx-delay-us */
|
||||
uint8_t gpo0_tx_delay_us; /* adi,gpo0-tx-delay-us */
|
||||
uint8_t gpo1_rx_delay_us; /* adi,gpo1-rx-delay-us */
|
||||
uint8_t gpo1_tx_delay_us; /* adi,gpo1-tx-delay-us */
|
||||
uint8_t gpo2_rx_delay_us; /* adi,gpo2-rx-delay-us */
|
||||
uint8_t gpo2_tx_delay_us; /* adi,gpo2-tx-delay-us */
|
||||
uint8_t gpo3_rx_delay_us; /* adi,gpo3-rx-delay-us */
|
||||
uint8_t gpo3_tx_delay_us; /* adi,gpo3-tx-delay-us */
|
||||
/* Tx Monitor Control */
|
||||
uint32_t low_high_gain_threshold_mdB; /* adi,txmon-low-high-thresh */
|
||||
uint32_t low_gain_dB; /* adi,txmon-low-gain */
|
||||
uint32_t high_gain_dB; /* adi,txmon-high-gain */
|
||||
uint8_t tx_mon_track_en; /* adi,txmon-dc-tracking-enable */
|
||||
uint8_t one_shot_mode_en; /* adi,txmon-one-shot-mode-enable */
|
||||
uint32_t tx_mon_delay; /* adi,txmon-delay */
|
||||
uint32_t tx_mon_duration; /* adi,txmon-duration */
|
||||
uint32_t tx1_mon_front_end_gain; /* adi,txmon-1-front-end-gain */
|
||||
uint32_t tx2_mon_front_end_gain; /* adi,txmon-2-front-end-gain */
|
||||
uint32_t tx1_mon_lo_cm; /* adi,txmon-1-lo-cm */
|
||||
uint32_t tx2_mon_lo_cm; /* adi,txmon-2-lo-cm */
|
||||
/* GPIO definitions */
|
||||
struct gpio_init_param gpio_resetb; /* reset-gpios */
|
||||
/* MCS Sync */
|
||||
struct gpio_init_param gpio_sync; /* sync-gpios */
|
||||
struct gpio_init_param gpio_cal_sw1; /* cal-sw1-gpios */
|
||||
struct gpio_init_param gpio_cal_sw2; /* cal-sw2-gpios */
|
||||
|
||||
struct spi_init_param spi_param;
|
||||
|
||||
/* External LO clocks */
|
||||
uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv);
|
||||
int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv,
|
||||
uint32_t rate);
|
||||
int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv,
|
||||
uint32_t rate);
|
||||
|
||||
} AD9361_InitParam;
|
||||
|
||||
typedef struct {
|
||||
uint32_t rx; /* 1, 2, 3(both) */
|
||||
int32_t rx_gain; /* -12, -6, 0, 6 */
|
||||
uint32_t rx_dec; /* 1, 2, 4 */
|
||||
int16_t rx_coef[128];
|
||||
uint8_t rx_coef_size;
|
||||
uint32_t rx_path_clks[6];
|
||||
uint32_t rx_bandwidth;
|
||||
} AD9361_RXFIRConfig;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tx; /* 1, 2, 3(both) */
|
||||
int32_t tx_gain; /* -6, 0 */
|
||||
uint32_t tx_int; /* 1, 2, 4 */
|
||||
int16_t tx_coef[128];
|
||||
uint8_t tx_coef_size;
|
||||
uint32_t tx_path_clks[6];
|
||||
uint32_t tx_bandwidth;
|
||||
} AD9361_TXFIRConfig;
|
||||
|
||||
enum ad9361_ensm_mode {
|
||||
ENSM_MODE_TX,
|
||||
ENSM_MODE_RX,
|
||||
ENSM_MODE_ALERT,
|
||||
ENSM_MODE_FDD,
|
||||
ENSM_MODE_WAIT,
|
||||
ENSM_MODE_SLEEP,
|
||||
ENSM_MODE_PINCTRL,
|
||||
ENSM_MODE_PINCTRL_FDD_INDEP,
|
||||
};
|
||||
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
#define RX1 0
|
||||
#define RX2 1
|
||||
|
||||
#define TX1 0
|
||||
#define TX2 1
|
||||
|
||||
#define A_BALANCED 0
|
||||
#define B_BALANCED 1
|
||||
#define C_BALANCED 2
|
||||
#define A_N 3
|
||||
#define A_P 4
|
||||
#define B_N 5
|
||||
#define B_P 6
|
||||
#define C_N 7
|
||||
#define C_P 8
|
||||
#define TX_MON1 9
|
||||
#define TX_MON2 10
|
||||
#define TX_MON1_2 11
|
||||
|
||||
#define TXA 0
|
||||
#define TXB 1
|
||||
|
||||
#define MODE_1x1 1
|
||||
#define MODE_2x2 2
|
||||
|
||||
#define HIGHEST_OSR 0
|
||||
#define NOMINAL_OSR 1
|
||||
|
||||
#define INT_LO 0
|
||||
#define EXT_LO 1
|
||||
|
||||
#define ON 0
|
||||
#define OFF 1
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
/* Initialize the AD9361 part. */
|
||||
int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy,
|
||||
AD9361_InitParam *init_param);
|
||||
/* Free the allocated resources. */
|
||||
int32_t ad9361_remove(struct ad9361_rf_phy *phy);
|
||||
/* Set the Enable State Machine (ENSM) mode. */
|
||||
int32_t ad9361_set_en_state_machine_mode (struct ad9361_rf_phy *phy,
|
||||
uint32_t mode);
|
||||
/* Get the Enable State Machine (ENSM) mode. */
|
||||
int32_t ad9361_get_en_state_machine_mode (struct ad9361_rf_phy *phy,
|
||||
uint32_t *mode);
|
||||
/* Set the receive RF gain for the selected channel. */
|
||||
int32_t ad9361_set_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
int32_t gain_db);
|
||||
/* Get current receive RF gain for the selected channel. */
|
||||
int32_t ad9361_get_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
int32_t *gain_db);
|
||||
/* Set the RX RF bandwidth. */
|
||||
int32_t ad9361_set_rx_rf_bandwidth (struct ad9361_rf_phy *phy,
|
||||
uint32_t bandwidth_hz);
|
||||
/* Get the RX RF bandwidth. */
|
||||
int32_t ad9361_get_rx_rf_bandwidth (struct ad9361_rf_phy *phy,
|
||||
uint32_t *bandwidth_hz);
|
||||
/* Set the RX sampling frequency. */
|
||||
int32_t ad9361_set_rx_sampling_freq (struct ad9361_rf_phy *phy,
|
||||
uint32_t sampling_freq_hz);
|
||||
/* Get current RX sampling frequency. */
|
||||
int32_t ad9361_get_rx_sampling_freq (struct ad9361_rf_phy *phy,
|
||||
uint32_t *sampling_freq_hz);
|
||||
/* Set the RX LO frequency. */
|
||||
int32_t ad9361_set_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz);
|
||||
/* Get current RX LO frequency. */
|
||||
int32_t ad9361_get_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz);
|
||||
/* Switch between internal and external LO. */
|
||||
int32_t ad9361_set_rx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext);
|
||||
/* Get the RSSI for the selected channel. */
|
||||
int32_t ad9361_get_rx_rssi (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
struct rf_rssi *rssi);
|
||||
/* Set the gain control mode for the selected channel. */
|
||||
int32_t ad9361_set_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
uint8_t gc_mode);
|
||||
/* Get the gain control mode for the selected channel. */
|
||||
int32_t ad9361_get_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
uint8_t *gc_mode);
|
||||
/* Set the RX FIR filter configuration. */
|
||||
int32_t ad9361_set_rx_fir_config (struct ad9361_rf_phy *phy,
|
||||
AD9361_RXFIRConfig fir_cfg);
|
||||
/* Get the RX FIR filter configuration. */
|
||||
int32_t ad9361_get_rx_fir_config(struct ad9361_rf_phy *phy, uint8_t rx_ch,
|
||||
AD9361_RXFIRConfig *fir_cfg);
|
||||
/* Enable/disable the RX FIR filter. */
|
||||
int32_t ad9361_set_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis);
|
||||
/* Get the status of the RX FIR filter. */
|
||||
int32_t ad9361_get_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis);
|
||||
/* Enable/disable the RX RFDC Tracking. */
|
||||
int32_t ad9361_set_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t en_dis);
|
||||
/* Get the status of the RX RFDC Tracking. */
|
||||
int32_t ad9361_get_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t *en_dis);
|
||||
/* Enable/disable the RX BasebandDC Tracking. */
|
||||
int32_t ad9361_set_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t en_dis);
|
||||
/* Get the status of the RX BasebandDC Tracking. */
|
||||
int32_t ad9361_get_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t *en_dis);
|
||||
/* Enable/disable the RX Quadrature Tracking. */
|
||||
int32_t ad9361_set_rx_quad_track_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t en_dis);
|
||||
/* Get the status of the RX Quadrature Tracking. */
|
||||
int32_t ad9361_get_rx_quad_track_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t *en_dis);
|
||||
/* Set the RX RF input port. */
|
||||
int32_t ad9361_set_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t mode);
|
||||
/* Get the selected RX RF input port. */
|
||||
int32_t ad9361_get_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t *mode);
|
||||
/* Store RX fastlock profile. */
|
||||
int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile);
|
||||
/* Recall RX fastlock profile. */
|
||||
int32_t ad9361_rx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile);
|
||||
/* Load RX fastlock profile. */
|
||||
int32_t ad9361_rx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile,
|
||||
uint8_t *values);
|
||||
/* Save RX fastlock profile. */
|
||||
int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile,
|
||||
uint8_t *values);
|
||||
/* Power down the RX Local Oscillator. */
|
||||
int32_t ad9361_rx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option);
|
||||
/* Get the RX Local Oscillator power status. */
|
||||
int32_t ad9361_get_rx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option);
|
||||
/* Set the transmit attenuation for the selected channel. */
|
||||
int32_t ad9361_set_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
uint32_t attenuation_mdb);
|
||||
/* Get current transmit attenuation for the selected channel. */
|
||||
int32_t ad9361_get_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
uint32_t *attenuation_mdb);
|
||||
/* Set the TX RF bandwidth. */
|
||||
int32_t ad9361_set_tx_rf_bandwidth (struct ad9361_rf_phy *phy,
|
||||
uint32_t bandwidth_hz);
|
||||
/* Get the TX RF bandwidth. */
|
||||
int32_t ad9361_get_tx_rf_bandwidth (struct ad9361_rf_phy *phy,
|
||||
uint32_t *bandwidth_hz);
|
||||
/* Set the TX sampling frequency. */
|
||||
int32_t ad9361_set_tx_sampling_freq (struct ad9361_rf_phy *phy,
|
||||
uint32_t sampling_freq_hz);
|
||||
/* Get current TX sampling frequency. */
|
||||
int32_t ad9361_get_tx_sampling_freq (struct ad9361_rf_phy *phy,
|
||||
uint32_t *sampling_freq_hz);
|
||||
/* Set the TX LO frequency. */
|
||||
int32_t ad9361_set_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz);
|
||||
/* Get current TX LO frequency. */
|
||||
int32_t ad9361_get_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz);
|
||||
/* Switch between internal and external LO. */
|
||||
int32_t ad9361_set_tx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext);
|
||||
/* Set the TX FIR filter configuration. */
|
||||
int32_t ad9361_set_tx_fir_config (struct ad9361_rf_phy *phy,
|
||||
AD9361_TXFIRConfig fir_cfg);
|
||||
/* Get the TX FIR filter configuration. */
|
||||
int32_t ad9361_get_tx_fir_config(struct ad9361_rf_phy *phy, uint8_t tx_ch,
|
||||
AD9361_TXFIRConfig *fir_cfg);
|
||||
/* Enable/disable the TX FIR filter. */
|
||||
int32_t ad9361_set_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis);
|
||||
/* Get the status of the TX FIR filter. */
|
||||
int32_t ad9361_get_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis);
|
||||
/* Get the TX RSSI for the selected channel. */
|
||||
int32_t ad9361_get_tx_rssi (struct ad9361_rf_phy *phy, uint8_t ch,
|
||||
uint32_t *rssi_db_x_1000);
|
||||
/* Set the TX RF output port. */
|
||||
int32_t ad9361_set_tx_rf_port_output (struct ad9361_rf_phy *phy, uint32_t mode);
|
||||
/* Get the selected TX RF output port. */
|
||||
int32_t ad9361_get_tx_rf_port_output (struct ad9361_rf_phy *phy,
|
||||
uint32_t *mode);
|
||||
/* Enable/disable the auto calibration. */
|
||||
int32_t ad9361_set_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t en_dis);
|
||||
/* Get the status of the auto calibration flag. */
|
||||
int32_t ad9361_get_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy,
|
||||
uint8_t *en_dis);
|
||||
/* Store TX fastlock profile. */
|
||||
int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile);
|
||||
/* Recall TX fastlock profile. */
|
||||
int32_t ad9361_tx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile);
|
||||
/* Load TX fastlock profile. */
|
||||
int32_t ad9361_tx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile,
|
||||
uint8_t *values);
|
||||
/* Save TX fastlock profile. */
|
||||
int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile,
|
||||
uint8_t *values);
|
||||
/* Power down the TX Local Oscillator. */
|
||||
int32_t ad9361_tx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option);
|
||||
/* Get the TX Local Oscillator power status. */
|
||||
int32_t ad9361_get_tx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option);
|
||||
/* Set the RX and TX path rates. */
|
||||
int32_t ad9361_set_trx_path_clks(struct ad9361_rf_phy *phy,
|
||||
uint32_t *rx_path_clks, uint32_t *tx_path_clks);
|
||||
/* Get the RX and TX path rates. */
|
||||
int32_t ad9361_get_trx_path_clks(struct ad9361_rf_phy *phy,
|
||||
uint32_t *rx_path_clks, uint32_t *tx_path_clks);
|
||||
/* Set the number of channels mode. */
|
||||
int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode);
|
||||
/* Do multi chip synchronization. */
|
||||
int32_t ad9361_do_mcs(struct ad9361_rf_phy *phy_master,
|
||||
struct ad9361_rf_phy *phy_slave);
|
||||
/* Enable/disable the TRX FIR filters. */
|
||||
int32_t ad9361_set_trx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis);
|
||||
/* Set the OSR rate governor. */
|
||||
int32_t ad9361_set_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t rate_gov);
|
||||
/* Get the OSR rate governor. */
|
||||
int32_t ad9361_get_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t *rate_gov);
|
||||
/* Perform the selected calibration. */
|
||||
int32_t ad9361_do_calib(struct ad9361_rf_phy *phy, uint32_t cal, int32_t arg);
|
||||
/* Load and enable TRX FIR filters configurations. */
|
||||
int32_t ad9361_trx_load_enable_fir(struct ad9361_rf_phy *phy,
|
||||
AD9361_RXFIRConfig rx_fir_cfg,
|
||||
AD9361_TXFIRConfig tx_fir_cfg);
|
||||
/* Do DCXO coarse tuning. */
|
||||
int32_t ad9361_do_dcxo_tune_coarse(struct ad9361_rf_phy *phy,
|
||||
uint32_t coarse);
|
||||
/* Do DCXO fine tuning. */
|
||||
int32_t ad9361_do_dcxo_tune_fine(struct ad9361_rf_phy *phy,
|
||||
uint32_t fine);
|
||||
/* Get the temperature. */
|
||||
int32_t ad9361_get_temperature(struct ad9361_rf_phy *phy,
|
||||
int32_t *temp);
|
||||
#endif
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
|
||||
/***************************************************************************//**
|
||||
* @file ad9361_conv.c
|
||||
* @brief Implementation of AD9361 Conv Driver.
|
||||
********************************************************************************
|
||||
* Copyright 2014-2015(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "ad9361.h"
|
||||
#include "ad9361_util.h"
|
||||
#include "delay.h"
|
||||
#include "../../../config/app_config.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* HDL loopback enable/disable.
|
||||
* @param phy The AD9361 state structure.
|
||||
* @param enable Enable/disable option.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Digital tune.
|
||||
* @param phy The AD9361 state structure.
|
||||
* @param max_freq Maximum frequency.
|
||||
* @param flags Flags: BE_VERBOSE, BE_MOREVERBOSE, DO_IDELAY, DO_ODELAY.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t ad9361_dig_tune(struct ad9361_rf_phy *phy, uint32_t max_freq,
|
||||
enum dig_tune_flags flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the AD9361 device.
|
||||
* @param phy The AD9361 state structure.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t ad9361_post_setup(struct ad9361_rf_phy *phy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+335
@@ -0,0 +1,335 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9361_util.c
|
||||
* @brief AD9361 Implementation of Util Driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2013(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <string.h>
|
||||
#include "ad9361_util.h"
|
||||
#include "../../../include/delay.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Macros Definitions *******************************/
|
||||
/******************************************************************************/
|
||||
#define BITS_PER_LONG 32
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief clk_prepare_enable
|
||||
*******************************************************************************/
|
||||
int32_t clk_prepare_enable(struct clk *clk)
|
||||
{
|
||||
if (clk) {
|
||||
// Unused variable - fix compiler warning
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief clk_get_rate
|
||||
*******************************************************************************/
|
||||
uint32_t clk_get_rate(struct ad9361_rf_phy *phy,
|
||||
struct refclk_scale *clk_priv)
|
||||
{
|
||||
uint32_t rate = 0;
|
||||
uint32_t source;
|
||||
|
||||
source = clk_priv->source;
|
||||
|
||||
switch (source) {
|
||||
case TX_REFCLK:
|
||||
case RX_REFCLK:
|
||||
case BB_REFCLK:
|
||||
rate = ad9361_clk_factor_recalc_rate(clk_priv,
|
||||
phy->clk_refin->rate);
|
||||
break;
|
||||
case TX_RFPLL_INT:
|
||||
case RX_RFPLL_INT:
|
||||
rate = ad9361_rfpll_int_recalc_rate(clk_priv,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
break;
|
||||
case RX_RFPLL_DUMMY:
|
||||
case TX_RFPLL_DUMMY:
|
||||
rate = ad9361_rfpll_dummy_recalc_rate(clk_priv);
|
||||
break;
|
||||
case TX_RFPLL:
|
||||
case RX_RFPLL:
|
||||
rate = ad9361_rfpll_recalc_rate(clk_priv);
|
||||
break;
|
||||
case BBPLL_CLK:
|
||||
rate = ad9361_bbpll_recalc_rate(clk_priv,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
break;
|
||||
case ADC_CLK:
|
||||
case R2_CLK:
|
||||
case R1_CLK:
|
||||
case CLKRF_CLK:
|
||||
case RX_SAMPL_CLK:
|
||||
case DAC_CLK:
|
||||
case T2_CLK:
|
||||
case T1_CLK:
|
||||
case CLKTF_CLK:
|
||||
case TX_SAMPL_CLK:
|
||||
rate = ad9361_clk_factor_recalc_rate(clk_priv,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief clk_set_rate
|
||||
*******************************************************************************/
|
||||
int32_t clk_set_rate(struct ad9361_rf_phy *phy,
|
||||
struct refclk_scale *clk_priv,
|
||||
uint32_t rate)
|
||||
{
|
||||
uint32_t source;
|
||||
int32_t i;
|
||||
uint32_t round_rate;
|
||||
|
||||
source = clk_priv->source;
|
||||
if(phy->clks[source]->rate != rate)
|
||||
{
|
||||
switch (source) {
|
||||
case TX_REFCLK:
|
||||
case RX_REFCLK:
|
||||
case BB_REFCLK:
|
||||
round_rate = ad9361_clk_factor_round_rate(clk_priv, rate,
|
||||
&phy->clk_refin->rate);
|
||||
ad9361_clk_factor_set_rate(clk_priv, round_rate,
|
||||
phy->clk_refin->rate);
|
||||
phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv,
|
||||
phy->clk_refin->rate);
|
||||
break;
|
||||
case TX_RFPLL_INT:
|
||||
case RX_RFPLL_INT:
|
||||
round_rate = ad9361_rfpll_int_round_rate(clk_priv, rate,
|
||||
&phy->clks[clk_priv->parent_source]->rate);
|
||||
ad9361_rfpll_int_set_rate(clk_priv, round_rate,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
phy->clks[source]->rate = ad9361_rfpll_int_recalc_rate(clk_priv,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
break;
|
||||
case RX_RFPLL_DUMMY:
|
||||
case TX_RFPLL_DUMMY:
|
||||
ad9361_rfpll_dummy_set_rate(clk_priv, rate);
|
||||
break;
|
||||
case TX_RFPLL:
|
||||
case RX_RFPLL:
|
||||
round_rate = ad9361_rfpll_round_rate(clk_priv, rate);
|
||||
ad9361_rfpll_set_rate(clk_priv, round_rate);
|
||||
phy->clks[source]->rate = ad9361_rfpll_recalc_rate(clk_priv);
|
||||
break;
|
||||
case BBPLL_CLK:
|
||||
round_rate = ad9361_bbpll_round_rate(clk_priv, rate,
|
||||
&phy->clks[clk_priv->parent_source]->rate);
|
||||
ad9361_bbpll_set_rate(clk_priv, round_rate,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
phy->bbpll_initialized = true;
|
||||
break;
|
||||
case ADC_CLK:
|
||||
case R2_CLK:
|
||||
case R1_CLK:
|
||||
case CLKRF_CLK:
|
||||
case RX_SAMPL_CLK:
|
||||
case DAC_CLK:
|
||||
case T2_CLK:
|
||||
case T1_CLK:
|
||||
case CLKTF_CLK:
|
||||
case TX_SAMPL_CLK:
|
||||
round_rate = ad9361_clk_factor_round_rate(clk_priv, rate,
|
||||
&phy->clks[clk_priv->parent_source]->rate);
|
||||
ad9361_clk_factor_set_rate(clk_priv, round_rate,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for(i = BB_REFCLK; i < BBPLL_CLK; i++)
|
||||
{
|
||||
phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i],
|
||||
phy->clk_refin->rate);
|
||||
}
|
||||
phy->clks[BBPLL_CLK]->rate = ad9361_bbpll_recalc_rate(phy->ref_clk_scale[BBPLL_CLK],
|
||||
phy->clks[phy->ref_clk_scale[BBPLL_CLK]->parent_source]->rate);
|
||||
for(i = ADC_CLK; i < RX_RFPLL_INT; i++)
|
||||
{
|
||||
phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i],
|
||||
phy->clks[phy->ref_clk_scale[i]->parent_source]->rate);
|
||||
}
|
||||
for(i = RX_RFPLL_INT; i < RX_RFPLL_DUMMY; i++)
|
||||
{
|
||||
phy->clks[i]->rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[i],
|
||||
phy->clks[phy->ref_clk_scale[i]->parent_source]->rate);
|
||||
}
|
||||
for(i = RX_RFPLL_DUMMY; i < RX_RFPLL; i++)
|
||||
{
|
||||
phy->clks[i]->rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[i]);
|
||||
}
|
||||
for(i = RX_RFPLL; i < NUM_AD9361_CLKS; i++)
|
||||
{
|
||||
phy->clks[i]->rate = ad9361_rfpll_recalc_rate(phy->ref_clk_scale[i]);
|
||||
}
|
||||
} else {
|
||||
if ((source == BBPLL_CLK) && !phy->bbpll_initialized) {
|
||||
round_rate = ad9361_bbpll_round_rate(clk_priv, rate,
|
||||
&phy->clks[clk_priv->parent_source]->rate);
|
||||
ad9361_bbpll_set_rate(clk_priv, round_rate,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv,
|
||||
phy->clks[clk_priv->parent_source]->rate);
|
||||
phy->bbpll_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief int_sqrt
|
||||
*******************************************************************************/
|
||||
uint32_t int_sqrt(uint32_t x)
|
||||
{
|
||||
uint32_t b, m, y = 0;
|
||||
|
||||
if (x <= 1)
|
||||
return x;
|
||||
|
||||
m = 1UL << (BITS_PER_LONG - 2);
|
||||
while (m != 0) {
|
||||
b = y + m;
|
||||
y >>= 1;
|
||||
|
||||
if (x >= b) {
|
||||
x -= b;
|
||||
y += m;
|
||||
}
|
||||
m >>= 2;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ilog2
|
||||
*******************************************************************************/
|
||||
int32_t ilog2(int32_t x)
|
||||
{
|
||||
int32_t A = !(!(x >> 16));
|
||||
int32_t count = 0;
|
||||
int32_t x_copy = x;
|
||||
|
||||
count = count + (A << 4);
|
||||
|
||||
x_copy = (((~A + 1) & (x >> 16)) + (~(~A + 1) & x));
|
||||
|
||||
A = !(!(x_copy >> 8));
|
||||
count = count + (A << 3);
|
||||
x_copy = (((~A + 1) & (x_copy >> 8)) + (~(~A + 1) & x_copy));
|
||||
|
||||
A = !(!(x_copy >> 4));
|
||||
count = count + (A << 2);
|
||||
x_copy = (((~A + 1) & (x_copy >> 4)) + (~(~A + 1) & x_copy));
|
||||
|
||||
A = !(!(x_copy >> 2));
|
||||
count = count + (A << 1);
|
||||
x_copy = (((~A + 1) & (x_copy >> 2)) + (~(~A + 1) & x_copy));
|
||||
|
||||
A = !(!(x_copy >> 1));
|
||||
count = count + A;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief find_first_bit
|
||||
*******************************************************************************/
|
||||
uint32_t find_first_bit(uint32_t word)
|
||||
{
|
||||
int32_t num = 0;
|
||||
|
||||
if ((word & 0xffff) == 0) {
|
||||
num += 16;
|
||||
word >>= 16;
|
||||
}
|
||||
if ((word & 0xff) == 0) {
|
||||
num += 8;
|
||||
word >>= 8;
|
||||
}
|
||||
if ((word & 0xf) == 0) {
|
||||
num += 4;
|
||||
word >>= 4;
|
||||
}
|
||||
if ((word & 0x3) == 0) {
|
||||
num += 2;
|
||||
word >>= 2;
|
||||
}
|
||||
if ((word & 0x1) == 0)
|
||||
num += 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ERR_PTR
|
||||
*******************************************************************************/
|
||||
void * ERR_PTR(long error)
|
||||
{
|
||||
return (void *) error;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief zmalloc
|
||||
*******************************************************************************/
|
||||
void *zmalloc(size_t size)
|
||||
{
|
||||
void *ptr = malloc(size);
|
||||
if (ptr)
|
||||
memset(ptr, 0, size);
|
||||
mdelay(1);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9361_util.h
|
||||
* @brief AD9361 Header file of Util driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2013(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef __AD9361_UTIL_H__
|
||||
#define __AD9361_UTIL_H__
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ad9361.h"
|
||||
#include "common.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
#define CLK_IGNORE_UNUSED BIT(3)
|
||||
#define CLK_GET_RATE_NOCACHE BIT(6)
|
||||
|
||||
#if defined(HAVE_VERBOSE_MESSAGES)
|
||||
#define dev_err(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); })
|
||||
#define dev_warn(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); })
|
||||
#if defined(HAVE_DEBUG_MESSAGES)
|
||||
#define dev_dbg(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); })
|
||||
#else
|
||||
#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); })
|
||||
#endif
|
||||
#define printk(format, ...) printf(format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define dev_err(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); })
|
||||
#define dev_warn(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); })
|
||||
#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); })
|
||||
#define printk(format, ...) ({ if (0) printf(format, ## __VA_ARGS__); })
|
||||
#endif
|
||||
|
||||
struct device {
|
||||
};
|
||||
|
||||
struct spi_device {
|
||||
struct device dev;
|
||||
uint8_t id_no;
|
||||
};
|
||||
|
||||
struct axiadc_state {
|
||||
struct ad9361_rf_phy *phy;
|
||||
uint32_t pcore_version;
|
||||
};
|
||||
|
||||
struct axiadc_chip_info {
|
||||
char *name;
|
||||
int32_t num_channels;
|
||||
};
|
||||
|
||||
struct axiadc_converter {
|
||||
struct axiadc_chip_info *chip_info;
|
||||
uint32_t scratch_reg[16];
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
#include "basetsd.h"
|
||||
typedef SSIZE_T ssize_t;
|
||||
#define strsep(s, ct) 0
|
||||
#define snprintf(s, n, format, ...) 0
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
int32_t clk_prepare_enable(struct clk *clk);
|
||||
uint32_t clk_get_rate(struct ad9361_rf_phy *phy,
|
||||
struct refclk_scale *clk_priv);
|
||||
int32_t clk_set_rate(struct ad9361_rf_phy *phy,
|
||||
struct refclk_scale *clk_priv,
|
||||
uint32_t rate);
|
||||
uint32_t int_sqrt(uint32_t x);
|
||||
int32_t ilog2(int32_t x);
|
||||
uint32_t find_first_bit(uint32_t word);
|
||||
void * ERR_PTR(long error);
|
||||
void *zmalloc(size_t size);
|
||||
|
||||
#endif
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/***************************************************************************//**
|
||||
* @file common.h
|
||||
* @brief Header file of Common Driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2013(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef __AD9361_COMMON_H_
|
||||
#define __AD9361_COMMON_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "../../../include/error.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
#if defined (__STDC__) && (__STDC_VERSION__ >= 199901L)
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
typedef enum { false, true } bool;
|
||||
#endif
|
||||
|
||||
struct clk {
|
||||
const char *name;
|
||||
uint32_t rate;
|
||||
};
|
||||
|
||||
struct clk_hw {
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
#endif // __AD9361_COMMON_H_
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9361_reg.c
|
||||
* @brief Implementation of AD9680 Driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include "ad9361_reg.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "../../../include/error.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9361_reg_read
|
||||
*******************************************************************************/
|
||||
int32_t ad9361_reg_read(struct ad9361_reg_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data)
|
||||
{
|
||||
uint8_t tx_buf[2];
|
||||
uint8_t rx_buf[1];
|
||||
int32_t ret;
|
||||
|
||||
tx_buf[0] = reg_addr >> 8;
|
||||
tx_buf[1] = reg_addr & 0xFF;
|
||||
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
tx_buf, rx_buf, 2, 1);
|
||||
|
||||
*reg_data = rx_buf[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9361_reg_write
|
||||
*******************************************************************************/
|
||||
int32_t ad9361_reg_write(struct ad9361_reg_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
|
||||
int32_t ret;
|
||||
|
||||
buf[0] = 0x80 | reg_addr >> 8;
|
||||
buf[1] = reg_addr & 0xFF;
|
||||
buf[2] = reg_data;
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
buf, NULL, 3, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief ad9361_reg_init
|
||||
*******************************************************************************/
|
||||
int32_t ad9361_reg_init(struct ad9361_reg_dev **device,
|
||||
const struct ad9361_reg_init_param *init_param)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
struct ad9361_reg_dev *dev;
|
||||
|
||||
dev = (struct ad9361_reg_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
ret |= gpio_get(&dev->gpio_desc_resetb, init_param->gpio_resetb);
|
||||
|
||||
gpio_direction_output(dev->gpio_desc_resetb, 0);
|
||||
|
||||
ad9361_reg_reset(dev);
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* AD9361 Device Reset
|
||||
* @param phy The AD9361 state structure.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev)
|
||||
{
|
||||
if (dev->gpio_desc_resetb) {
|
||||
gpio_set_value(dev->gpio_desc_resetb, 0);
|
||||
mdelay(10);
|
||||
gpio_set_value(dev->gpio_desc_resetb, 1);
|
||||
mdelay(10);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Free the resources allocated by ad9361_reg_setup().
|
||||
*
|
||||
* @param dev - The device structure.
|
||||
*
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*******************************************************************************/
|
||||
int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = spi_remove(dev->spi_desc);
|
||||
|
||||
free(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/***************************************************************************//**
|
||||
* @file ad9361_reg.h
|
||||
* @brief Header file of ad9361_reg Driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2014-2016(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef ad9361_reg_H_
|
||||
#define ad9361_reg_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
struct ad9361_reg_dev {
|
||||
/* SPI */
|
||||
struct spi_desc *spi_desc;
|
||||
struct gpio_desc *gpio_desc_resetb;
|
||||
};
|
||||
|
||||
struct ad9361_reg_init_param {
|
||||
/* SPI */
|
||||
struct spi_init_param *spi_init;
|
||||
struct gpio_init_param *gpio_resetb;
|
||||
};
|
||||
|
||||
enum Operation_Type{
|
||||
AD9361_WRITE,
|
||||
AD9361_READ,
|
||||
AD9361_WAIT,
|
||||
AD9361_WHEN
|
||||
};
|
||||
|
||||
struct ad9361_reg_config {
|
||||
int operation;
|
||||
uint16_t val1;
|
||||
uint16_t val2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int32_t ad9361_reg_read(struct ad9361_reg_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data);
|
||||
|
||||
int32_t ad9361_reg_write(struct ad9361_reg_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data);
|
||||
|
||||
int32_t ad9361_reg_init(struct ad9361_reg_dev **device,
|
||||
const struct ad9361_reg_init_param *init_param);
|
||||
|
||||
int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev);
|
||||
|
||||
int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev);
|
||||
|
||||
#endif
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/***************************************************************************//**
|
||||
* @file cx9261a.c
|
||||
* @brief Implementation of CX9261A Driver.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "../../../include/error.h"
|
||||
|
||||
#include "cx9261a.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief cx9261a_read
|
||||
*******************************************************************************/
|
||||
int32_t cx9261a_read(struct cx9261a_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data)
|
||||
{
|
||||
uint8_t tx_buf[2];
|
||||
uint8_t rx_buf[1];
|
||||
int32_t ret;
|
||||
|
||||
tx_buf[0] = reg_addr >> 8;
|
||||
tx_buf[1] = reg_addr & 0xFF;
|
||||
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
tx_buf, rx_buf, 2, 1);
|
||||
|
||||
*reg_data = rx_buf[0];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief cx9261a_write
|
||||
*******************************************************************************/
|
||||
int32_t cx9261a_write(struct cx9261a_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
|
||||
int32_t ret;
|
||||
|
||||
buf[0] = 0x80 | reg_addr >> 8;
|
||||
buf[1] = reg_addr & 0xFF;
|
||||
buf[2] = reg_data;
|
||||
|
||||
ret = spi_write_and_read_3wire(dev->spi_desc,
|
||||
buf, NULL, 3, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief cx9261a_init
|
||||
*******************************************************************************/
|
||||
int32_t cx9261a_init(struct cx9261a_dev **device,
|
||||
const struct cx9261a_init_param *init_param)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
struct cx9261a_dev *dev;
|
||||
|
||||
dev = (struct cx9261a_dev *)malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return FAILURE;
|
||||
|
||||
/* SPI */
|
||||
ret = spi_init(&dev->spi_desc, init_param->spi_init);
|
||||
ret |= gpio_get(&dev->gpio_desc_nrst, init_param->gpio_nrst);
|
||||
ret |= gpio_get(&dev->gpio_desc_txnrx_trx1, init_param->gpio_txnrx_trx1);
|
||||
ret |= gpio_get(&dev->gpio_desc_txnrx_trx2, init_param->gpio_txnrx_trx2);
|
||||
ret |= gpio_get(&dev->gpio_desc_txnrx_rxfb, init_param->gpio_txnrx_rxfb);
|
||||
ret |= gpio_get(&dev->gpio_desc_enable_trx1, init_param->gpio_enable_trx1);
|
||||
ret |= gpio_get(&dev->gpio_desc_enable_trx2, init_param->gpio_enable_trx2);
|
||||
ret |= gpio_get(&dev->gpio_desc_enable_rxfb, init_param->gpio_enable_rxfb);
|
||||
ret |= gpio_get(&dev->gpio_desc_pl_rst, init_param->gpio_pl_rst);
|
||||
ret |= gpio_get(&dev->gpio_desc_tr_sel, init_param->gpio_tr_sel);
|
||||
ret |= gpio_get(&dev->gpio_desc_tdd_fdd_sel, init_param->gpio_tdd_fdd_sel);
|
||||
ret |= gpio_get(&dev->gpio_desc_r1t1_r2t2_sel, init_param->gpio_r1t1_r2t2_sel);
|
||||
ret |= gpio_get(&dev->gpio_desc_sp_dp_sel, init_param->gpio_sp_dp_sel);
|
||||
ret |= gpio_get(&dev->gpio_desc_mclk_delay_ctrl0, init_param->gpio_mclk_delay_ctrl0);
|
||||
ret |= gpio_get(&dev->gpio_desc_mclk_delay_ctrl1, init_param->gpio_mclk_delay_ctrl1);
|
||||
ret |= gpio_get(&dev->gpio_desc_mclk_delay_ctrl2, init_param->gpio_mclk_delay_ctrl2);
|
||||
ret |= gpio_get(&dev->gpio_desc_hop_flag, init_param->gpio_hop_flag);
|
||||
|
||||
gpio_direction_output(dev->gpio_desc_nrst, 0);
|
||||
gpio_direction_output(dev->gpio_desc_txnrx_trx1, 0);
|
||||
gpio_direction_output(dev->gpio_desc_txnrx_trx2, 0);
|
||||
gpio_direction_output(dev->gpio_desc_txnrx_rxfb, 0);
|
||||
gpio_direction_output(dev->gpio_desc_enable_trx1, 0);
|
||||
gpio_direction_output(dev->gpio_desc_enable_trx2, 0);
|
||||
gpio_direction_output(dev->gpio_desc_enable_rxfb, 0);
|
||||
gpio_direction_output(dev->gpio_desc_pl_rst, 0);
|
||||
gpio_direction_output(dev->gpio_desc_tr_sel, 0);
|
||||
gpio_direction_output(dev->gpio_desc_tdd_fdd_sel, 0);
|
||||
gpio_direction_output(dev->gpio_desc_r1t1_r2t2_sel, 0);
|
||||
gpio_direction_output(dev->gpio_desc_sp_dp_sel, 0);
|
||||
gpio_direction_output(dev->gpio_desc_mclk_delay_ctrl0, 0);
|
||||
gpio_direction_output(dev->gpio_desc_mclk_delay_ctrl1, 0);
|
||||
gpio_direction_output(dev->gpio_desc_mclk_delay_ctrl2, 0);
|
||||
gpio_direction_input(dev->gpio_desc_hop_flag);
|
||||
|
||||
cx9261a_reset(dev);
|
||||
|
||||
*device = dev;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* AD9361 Device Reset
|
||||
* @param phy The AD9361 state structure.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t cx9261a_reset(struct cx9261a_dev *dev)
|
||||
{
|
||||
if (dev->gpio_desc_nrst) {
|
||||
gpio_set_value(dev->gpio_desc_nrst, 0);
|
||||
mdelay(10);
|
||||
gpio_set_value(dev->gpio_desc_nrst, 1);
|
||||
mdelay(10);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Free the resources allocated by cx9261a_setup().
|
||||
*
|
||||
* @param dev - The device structure.
|
||||
*
|
||||
* @return SUCCESS in case of success, negative error code otherwise.
|
||||
*******************************************************************************/
|
||||
int32_t cx9261a_remove(struct cx9261a_dev *dev)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = spi_remove(dev->spi_desc);
|
||||
|
||||
free(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/***************************************************************************//**
|
||||
* @file cx9261a.h
|
||||
* @brief Header file of cx9261a Driver.
|
||||
*******************************************************************************/
|
||||
#ifndef CX9261A_H_
|
||||
#define CX9261A_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include "delay.h"
|
||||
#include "spi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
struct cx9261a_dev {
|
||||
/* SPI */
|
||||
struct spi_desc *spi_desc;
|
||||
struct gpio_desc *gpio_desc_nrst;
|
||||
struct gpio_desc *gpio_desc_txnrx_trx1;
|
||||
struct gpio_desc *gpio_desc_txnrx_trx2;
|
||||
struct gpio_desc *gpio_desc_txnrx_rxfb;
|
||||
struct gpio_desc *gpio_desc_enable_trx1;
|
||||
struct gpio_desc *gpio_desc_enable_trx2;
|
||||
struct gpio_desc *gpio_desc_enable_rxfb;
|
||||
struct gpio_desc *gpio_desc_pl_rst;
|
||||
struct gpio_desc *gpio_desc_tr_sel;
|
||||
struct gpio_desc *gpio_desc_tdd_fdd_sel;
|
||||
struct gpio_desc *gpio_desc_r1t1_r2t2_sel;
|
||||
struct gpio_desc *gpio_desc_sp_dp_sel;
|
||||
struct gpio_desc *gpio_desc_mclk_delay_ctrl0;
|
||||
struct gpio_desc *gpio_desc_mclk_delay_ctrl1;
|
||||
struct gpio_desc *gpio_desc_mclk_delay_ctrl2;
|
||||
struct gpio_desc *gpio_desc_hop_flag;
|
||||
};
|
||||
|
||||
struct cx9261a_init_param {
|
||||
/* SPI */
|
||||
struct spi_init_param *spi_init;
|
||||
struct gpio_init_param *gpio_nrst;
|
||||
struct gpio_init_param *gpio_txnrx_trx1;
|
||||
struct gpio_init_param *gpio_txnrx_trx2;
|
||||
struct gpio_init_param *gpio_txnrx_rxfb;
|
||||
struct gpio_init_param *gpio_enable_trx1;
|
||||
struct gpio_init_param *gpio_enable_trx2;
|
||||
struct gpio_init_param *gpio_enable_rxfb;
|
||||
struct gpio_init_param *gpio_pl_rst;
|
||||
struct gpio_init_param *gpio_tr_sel;
|
||||
struct gpio_init_param *gpio_tdd_fdd_sel;
|
||||
struct gpio_init_param *gpio_r1t1_r2t2_sel;
|
||||
struct gpio_init_param *gpio_sp_dp_sel;
|
||||
struct gpio_init_param *gpio_mclk_delay_ctrl0;
|
||||
struct gpio_init_param *gpio_mclk_delay_ctrl1;
|
||||
struct gpio_init_param *gpio_mclk_delay_ctrl2;
|
||||
struct gpio_init_param *gpio_hop_flag;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int32_t cx9261a_read(struct cx9261a_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t *reg_data);
|
||||
|
||||
int32_t cx9261a_write(struct cx9261a_dev *dev,
|
||||
uint16_t reg_addr,
|
||||
uint8_t reg_data);
|
||||
|
||||
int32_t cx9261a_init(struct cx9261a_dev **device,
|
||||
const struct cx9261a_init_param *init_param);
|
||||
|
||||
int32_t cx9261a_reset(struct cx9261a_dev *dev);
|
||||
|
||||
int32_t cx9261a_remove(struct cx9261a_dev *dev);
|
||||
|
||||
#endif
|
||||
+982
@@ -0,0 +1,982 @@
|
||||
#ifndef __CX9261ADRIVER_C_H
|
||||
#define __CX9261ADRIVER_C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#define MAX_NUM_FIR 64
|
||||
#define MAX_MULTI_POINTS 64
|
||||
|
||||
typedef enum {
|
||||
CX9261A_WKM_Rx,
|
||||
CX9261A_WKM_Tx,
|
||||
CX9261A_WKM_FDD
|
||||
} CX9261A_WorkMode;
|
||||
|
||||
/**
|
||||
* @brief 收发数据通道数量
|
||||
* @note 此模式并不代表使用几个通道进行收发
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_TRM_R1T1,
|
||||
CX9261A_TRM_R2T2
|
||||
} CX9261A_TrMode;
|
||||
|
||||
/**
|
||||
* @brief 收发接口通道数量
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_PORTM_Single,
|
||||
CX9261A_PORTM_Dual
|
||||
} CX9261A_PortMode;
|
||||
|
||||
/**
|
||||
* @brief 接口模式:
|
||||
* CMOS CMOS接口模式,
|
||||
* LVDS_S LVDS顺序模式,
|
||||
* LVDS_E LVDS奇偶模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_IOM_CMOS,
|
||||
CX9261A_IOM_LVDS_S,
|
||||
CX9261A_IOM_LVDS_E
|
||||
} CX9261A_IOMode;
|
||||
|
||||
/**
|
||||
* @brief 本振来源
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_LOSRC_Pll1 = 0b00001,
|
||||
CX9261A_LOSRC_Pll2 = 0b00010,
|
||||
CX9261A_LOSRC_Pll3 = 0b00100,
|
||||
CX9261A_LOSRC_Pll4 = 0b01000,
|
||||
CX9261A_LOSRC_Pll5 = 0b10000,
|
||||
CX9261A_LOSRC_Off = 0
|
||||
} CX9261A_LoSource;
|
||||
|
||||
/**
|
||||
* @brief 接收通道
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_RXCH_Rx1 = 1,
|
||||
CX9261A_RXCH_Rx2,
|
||||
CX9261A_RXCH_Rx3
|
||||
} CX9261A_RxChannel;
|
||||
|
||||
/**
|
||||
* @brief 发射通道
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_TXCH_Tx1 = 1,
|
||||
CX9261A_TXCH_Tx2
|
||||
} CX9261A_TxChannel;
|
||||
|
||||
/**
|
||||
* @brief 电源模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_PWM_Shutdown = 0,
|
||||
CX9261A_PWM_Sleep,
|
||||
CX9261A_PWM_Alert,
|
||||
CX9261A_PWM_Calib,
|
||||
CX9261A_PWM_Receive,
|
||||
CX9261A_PWM_Transmit,
|
||||
CX9261A_PWM_Duplex,
|
||||
CX9261A_PWM_Obs
|
||||
} CX9261A_PowerMode;
|
||||
|
||||
/**
|
||||
* @brief NCO模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_NCOM_Bypass = 0,
|
||||
CX9261A_NCOM_Up,
|
||||
CX9261A_NCOM_Down,
|
||||
CX9261A_NCOM_BIST,
|
||||
CX9261A_NCOM_Master,
|
||||
CX9261A_NCOM_Slaver
|
||||
} CX9261A_NCOMode;
|
||||
|
||||
/**
|
||||
* @brief 温补模式 DAC: DAC模式 Band: 跳子带模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_TEMPCP_DAC = 0,
|
||||
CX9261A_TEMPCP_Band
|
||||
} CX9261A_TemperatureComp;
|
||||
|
||||
/**
|
||||
* @brief 校准方法 TST: 时域统计 Rx通道使用, Bisec: 二分法 Tx通道使用, MultiPoints: 多点校准
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_CALM_TST = 0,
|
||||
CX9261A_CALM_Bisec,
|
||||
CX9261A_CALM_MultiPoints,
|
||||
CX9261A_CALM_Tracking
|
||||
} CX9261A_CalibMethod;
|
||||
|
||||
/**
|
||||
* @brief DC校准方法 Tracking: 跟踪校准 HighPass: 高通滤波器滤掉直流
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_DCCALM_Tracking=0,
|
||||
CX9261A_DCCALM_HighPass
|
||||
} CX9261A_DCCalibMethod;
|
||||
|
||||
|
||||
typedef struct {
|
||||
CX9261A_LoSource first;
|
||||
CX9261A_LoSource second;
|
||||
} CX9261A_LoSourcePair;
|
||||
|
||||
typedef struct {
|
||||
CX9261A_LoSourcePair key;
|
||||
uint16_t value;
|
||||
} CX9261A_SrcMapEntry;
|
||||
|
||||
/**
|
||||
* @brief 接收通道本振来源映射表
|
||||
*/
|
||||
static const CX9261A_SrcMapEntry CX9261A_rxSrcMap[] = {
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll2 }, 0b0010000 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll1 }, 0b1101000 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll1 }, 0b0100000 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll2 }, 0b1000000 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll1 }, 0b0101010 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll2 }, 0b1010010 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Off }, 0b1001001 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Off }, 0b0110001 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Off }, 0b0011011 }
|
||||
};
|
||||
/**
|
||||
* @brief 发射通道本振来源映射表
|
||||
*/
|
||||
static const CX9261A_SrcMapEntry CX9261A_txSrcMap[] = {
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll4 }, 16 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll3 }, 104 },
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll3 }, 32 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll4 }, 64 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll2 }, 1560 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll1 }, 1944 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll1 }, 1688 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll2 }, 1816 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll3 }, 42 }, { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll4 }, 82 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll2 }, 794 }, { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll1 }, 666 },
|
||||
{ { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Off }, 73 }, { { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Off }, 49 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Off }, 1177 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Off }, 1305 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Off }, 27 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll3 }, 1320 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll4 }, 1360 }, { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll3 }, 1064 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll4 }, 1104 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll1 }, 712 },
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll1 }, 688 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll2 }, 584 },
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll2 }, 560 }
|
||||
};
|
||||
/**
|
||||
* @brief 环路参数选择表
|
||||
*/
|
||||
static const uint8_t CX9261A_coreTable[7][4][3] = {
|
||||
{ { 0x0C, 0x30, 0x08 }, { 0x0B, 0x30, 0x09 }, { 0x0C, 0x30, 0x05 }, { 0x0D, 0x30, 0x08 } },
|
||||
{ { 0x0C, 0x30, 0x0C }, { 0x0B, 0x30, 0x0E }, { 0x0C, 0x30, 0x08 }, { 0x0D, 0x30, 0x0B } },
|
||||
{ { 0x0C, 0x20, 0x10 }, { 0x0B, 0x20, 0x10 }, { 0x0C, 0x20, 0x0A }, { 0x0D, 0x20, 0x0D } },
|
||||
{ { 0x0C, 0x20, 0x11 }, { 0x0B, 0x20, 0x13 }, { 0x0C, 0x20, 0x0C }, { 0x0D, 0x20, 0x0F } },
|
||||
{ { 0x0D, 0x30, 0x14 }, { 0x0D, 0x22, 0x14 }, { 0x0D, 0x20, 0x0D }, { 0x0D, 0x15, 0x0C } },
|
||||
{ { 0x0E, 0x30, 0x18 }, { 0x0E, 0x25, 0x16 }, { 0x0E, 0x25, 0x0F }, { 0x0E, 0x18, 0x0F } },
|
||||
{ { 0x0F, 0x38, 0x1A }, { 0x0F, 0x32, 0x1C }, { 0x0F, 0x18, 0x12 }, { 0x0F, 0x18, 0x12 } }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief AGC PDT模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int pdtN;
|
||||
int pdtM;
|
||||
} CX9261A_AGCPDT;
|
||||
|
||||
/**
|
||||
* @brief AGC LMT模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int count; /**< LMT统计次数阈值*/
|
||||
int threshold1; /**< LMT阈值第一档*/
|
||||
int threshold2; /**< LMT阈值第二档*/
|
||||
int threshold3; /**< LMT阈值第三档*/
|
||||
int threshold4; /**< LMT阈值第四档*/
|
||||
} CX9261A_AGCLMT;
|
||||
|
||||
/**
|
||||
* @brief AGC DIG模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int count; /**< DIG统计次数阈值*/
|
||||
int threshold1; /**< DIG阈值第一档*/
|
||||
int threshold2; /**< DIG阈值第二档*/
|
||||
int threshold3; /**< DIG阈值第三档*/
|
||||
int threshold4; /**< DIG阈值第四档*/
|
||||
} CX9261A_AGCDIG;
|
||||
|
||||
/**
|
||||
* @brief AGC模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int mode; /**< AGC模式选择*/
|
||||
CX9261A_AGCPDT pdt; /**< AGC PDT模式的结构体*/
|
||||
CX9261A_AGCLMT lmt; /**< AGC LMT模式的结构体*/
|
||||
CX9261A_AGCDIG dig; /**< AGC DIG模式的结构体*/
|
||||
} CX9261A_AGC;
|
||||
|
||||
/**
|
||||
* @brief 时钟相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double ref; /**< 参考时钟频率,单位MHz*/
|
||||
double adc; /**< ADC频率,单位MHz*/
|
||||
int refDiv; /**< 参考时钟分频比*/
|
||||
bool bbUseIntDiv; /**< 是否使用整数分频模式*/
|
||||
bool refDoubler; /**< 是否使用参考时钟倍频器*/
|
||||
} CX9261A_Clock;
|
||||
|
||||
/**
|
||||
* @brief 校准相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool calibDC; /**< 是否开启DC Tracking*/
|
||||
CX9261A_DCCalibMethod dcCalibMethod;
|
||||
int dcTrackingLength; /**< DC Tracking长度*/
|
||||
int dcHighPassFactor; /**< DC高通滤波系数,越大代表滤波器阶数越高,滤波范围越窄*/
|
||||
uint8_t rx1CalibPll; /**< rx1校准的pll选择,Pll1 | Pll2*/
|
||||
uint8_t rx2CalibPll; /**< rx2校准的pll选择,Pll1 | Pll2*/
|
||||
uint8_t rx3CalibPll; /**< rx3校准的pll选择,Pll5*/
|
||||
uint8_t tx1CalibPll; /**< tx1校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/
|
||||
uint8_t tx2CalibPll; /**< tx2校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/
|
||||
CX9261A_CalibMethod rxMethod;
|
||||
CX9261A_CalibMethod txMethod;
|
||||
double f0; /**< 校准音频率*/
|
||||
uint32_t numRxPoint; /**< Rx多点校准的频率个数*/
|
||||
uint32_t numTxPoint; /**< Tx多点校准的频率个数*/
|
||||
double rxMultiPoints[MAX_MULTI_POINTS]; /**< Rx多点校准的频率*/
|
||||
double txMultiPoints[MAX_MULTI_POINTS]; /**< Tx多点校准的频率*/
|
||||
} CX9261A_Calib;
|
||||
|
||||
/**
|
||||
* @brief 配置PLL来源相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool rxUseExt; /**< 接收通道是否使用外本振*/
|
||||
bool txUseExt; /**< 发射通道是否使用外本振*/
|
||||
CX9261A_LoSource rx1Source; /**< Rx1通道本振来源*/
|
||||
CX9261A_LoSource rx2Source; /**< Rx2通道本振来源*/
|
||||
CX9261A_LoSource rx3Source; /**< Rx3通道本振来源*/
|
||||
CX9261A_LoSource tx1Source; /**< Tx1通道本振来源*/
|
||||
CX9261A_LoSource tx2Source; /**< Tx2通道本振来源*/
|
||||
} CX9261A_PllSource;
|
||||
|
||||
/**
|
||||
* @brief 配置PLL频率相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double pll1Freq; /**< PLL1本振时钟,单位MHz*/
|
||||
double pll2Freq; /**< PLL2本振时钟,单位MHz*/
|
||||
double pll3Freq; /**< PLL3本振时钟,单位MHz*/
|
||||
double pll4Freq; /**< PLL4本振时钟,单位MHz*/
|
||||
double pll5Freq; /**< PLL5本振时钟,单位MHz*/
|
||||
double rxExtFreq; /**< 接收通道使用外本振时,外本振频率,单位MHz*/
|
||||
double txExtFreq; /**< 发射通道使用外本振时,外本振频率,单位MHz*/
|
||||
} CX9261A_PllFreq;
|
||||
|
||||
/**
|
||||
* @brief 配置接口相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
CX9261A_WorkMode workMode; /**< 芯片工作模式*/
|
||||
CX9261A_TrMode trMode; /**< 收发数据通道模式*/
|
||||
CX9261A_PortMode portMode; /**< 收发接口通道模式*/
|
||||
CX9261A_IOMode ioMode; /**< 接口电平模式*/
|
||||
} CX9261A_Interface;
|
||||
|
||||
/**
|
||||
* @brief 配置TX NCO相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool txUseBist; /**< 是否开启BIST模式*/
|
||||
double txNCOFreq; /**< NCO频率*/
|
||||
} CX9261A_TxNCO;
|
||||
|
||||
/**
|
||||
* @brief 配置RX NCO相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool rxUseBist; /**< 是否开启BIST模式*/
|
||||
bool rxNCOBypass; /**< 是否Bypass NCO*/
|
||||
bool rxNCOUpward; /**< 开启上/下混频模式*/
|
||||
bool rxNCOMaster; /**< 使用Master/Slaver模式*/
|
||||
double rxNCOFreq; /**< NCO频率*/
|
||||
} CX9261A_RxNCO;
|
||||
|
||||
/**
|
||||
* @brief 配置接收通道相关参数结构体
|
||||
*/
|
||||
typedef struct {
|
||||
double bandwidth; /**< 接收通道1dB带宽,单位MHz*/
|
||||
int tia; /**< 接收通道TIA增益配置,推荐配置6*/
|
||||
int mixer; /**< 接收通道Mixer增益配置*/
|
||||
} CX9261A_RxConfig;
|
||||
|
||||
/**
|
||||
* @brief 配置发射通道相关参数结构体
|
||||
*/
|
||||
typedef struct {
|
||||
double bandwidth; /**< 发射通道1dB带宽,单位MHz*/
|
||||
int mixer; /**< 发射通道Mixer增益配置*/
|
||||
} CX9261A_TxConfig;
|
||||
|
||||
/**
|
||||
* @brief 配置滤波器相关参数结构体,0代表bypass
|
||||
*/
|
||||
typedef struct {
|
||||
int fir; /**< FIR滤波器抽取/插值倍数*/
|
||||
int hbf1; /**< HBF1滤波器抽取/插值倍数*/
|
||||
int hbf2; /**< HBF2滤波器抽取/插值倍数*/
|
||||
int hbf3; /**< HBF3滤波器抽取/插值倍数*/
|
||||
int cic; /**< CIC滤波器抽取/插值倍数*/
|
||||
} CX9261A_Filters;
|
||||
|
||||
/**
|
||||
* @brief 配置电源模式结构体,1代表该模块上电
|
||||
*/
|
||||
typedef struct {
|
||||
bool dig_tx2;
|
||||
bool dig_tx1;
|
||||
bool dig_rx3;
|
||||
bool dig_rx2;
|
||||
bool dig_rx1;
|
||||
bool fref1_rx;
|
||||
bool auxadc2;
|
||||
bool auxadc1;
|
||||
bool auxdac;
|
||||
bool temp_sensor;
|
||||
bool bgr;
|
||||
bool exlo;
|
||||
bool tx2;
|
||||
bool tx1;
|
||||
bool rx3;
|
||||
bool rx2;
|
||||
bool rx1;
|
||||
bool pll5_ldo;
|
||||
bool pll5;
|
||||
bool pll4_ldo;
|
||||
bool pll4;
|
||||
bool pll3_ldo;
|
||||
bool pll3;
|
||||
bool pll2_ldo;
|
||||
bool pll2;
|
||||
bool pll1_ldo;
|
||||
bool pll1;
|
||||
bool bbpll;
|
||||
} CX9261A_Power;
|
||||
|
||||
/**
|
||||
* @brief 配置电源模式管理,包含模式选择,接收模式,发射模式,FDD模式
|
||||
*/
|
||||
typedef struct {
|
||||
CX9261A_PowerMode powerMode;
|
||||
CX9261A_Power rxPower;
|
||||
CX9261A_Power txPower;
|
||||
CX9261A_Power fddPower;
|
||||
} CX9261A_PowerManagement;
|
||||
|
||||
/**
|
||||
* @brief 储存窄带校准结果的结构体
|
||||
*/
|
||||
typedef struct {
|
||||
int bHigh;
|
||||
int bLow;
|
||||
int cHigh;
|
||||
int cLow;
|
||||
int dciHigh;
|
||||
int dciLow;
|
||||
int dcqHigh;
|
||||
int dcqLow;
|
||||
} CX9261A_CalibPredis;
|
||||
|
||||
/**
|
||||
* @brief CX9261A结构体
|
||||
*/
|
||||
typedef struct {
|
||||
CX9261A_TemperatureComp tempComp; /**< 温度补偿*/
|
||||
CX9261A_AGC agc; /**< AGC结构体*/
|
||||
CX9261A_Interface interface; /**< Interface结构体*/
|
||||
CX9261A_Clock clock; /**< Clock结构体*/
|
||||
CX9261A_PllSource pllSource; /**< PllSource结构体*/
|
||||
CX9261A_Calib calib; /**< Calib结构体*/
|
||||
CX9261A_PllFreq pllFreq; /**< PllFreq结构体*/
|
||||
CX9261A_TxNCO txNco; /**< TxNCO结构体*/
|
||||
CX9261A_RxNCO rxNco; /**< RxNCO结构体*/
|
||||
CX9261A_RxConfig rx1Config; /**< RxConfig结构体*/
|
||||
CX9261A_RxConfig rx2Config; /**< RxConfig结构体*/
|
||||
CX9261A_RxConfig rx3Config; /**< RxConfig结构体*/
|
||||
CX9261A_TxConfig tx1Config; /**< TxConfig结构体*/
|
||||
CX9261A_TxConfig tx2Config; /**< TxConfig结构体*/
|
||||
CX9261A_Filters rxFilters; /**< Filters结构体*/
|
||||
CX9261A_Filters txFilters; /**< Filters结构体*/
|
||||
CX9261A_PowerManagement powerManagement; /**< PowerManagement结构体*/
|
||||
uint32_t numRxFIR;
|
||||
uint32_t numTxFIR;
|
||||
double rxFIRCoe[MAX_NUM_FIR]; /**< Rx FIR滤波器系数*/
|
||||
double txFIRCoe[MAX_NUM_FIR]; /**< Tx FIR滤波器系数*/
|
||||
} CX9261A_CX9261AConfiguration;
|
||||
|
||||
typedef struct {
|
||||
int first;
|
||||
int second;
|
||||
}QecStatePair;
|
||||
|
||||
|
||||
// 定义函数指针类型
|
||||
typedef void (*CX9261A_LoggingFunc)(const char* msg);
|
||||
typedef void (*CX9261A_WriteSpiFunc)(int address, int value);
|
||||
typedef int (*CX9261A_ReadSpiFunc)(int address);
|
||||
typedef void (*CX9261A_PauseFunc)(double ms);
|
||||
typedef void (*CX9261A_SetPinFunc)(int pin, int value);
|
||||
|
||||
/**
|
||||
* @brief 绑定日志函数
|
||||
* @param msg 要输出的内容
|
||||
*/
|
||||
void CX9261A_setLoggingFunc(CX9261A_LoggingFunc func);
|
||||
/**
|
||||
* @brief 绑定SPI写入寄存器函数
|
||||
* @param address 要写入的寄存器地址
|
||||
* @param value 要写入的寄存器值
|
||||
*/
|
||||
void CX9261A_setWriteSpiFunc(CX9261A_WriteSpiFunc func);
|
||||
/**
|
||||
* @brief 绑定等待函数
|
||||
* @param ms 等待时间,单位毫秒
|
||||
*/
|
||||
void CX9261A_setReadSpiFunc(CX9261A_ReadSpiFunc func);
|
||||
/**
|
||||
* @brief 绑定SPI读取寄存器函数
|
||||
* @param address 要读取的寄存器地址
|
||||
* @return 返回的寄存器值
|
||||
*/
|
||||
void CX9261A_setPauseFunc(CX9261A_PauseFunc func);
|
||||
/**
|
||||
* @brief 绑定配置FPGA对应寄存器函数
|
||||
* @param pin 寄存器地址
|
||||
* @param value 寄存器值
|
||||
*/
|
||||
void CX9261A_setSetPinFunc(CX9261A_SetPinFunc func);
|
||||
|
||||
/**
|
||||
* @brief 初始化芯片状态,写入与具体配置无关的寄存器值
|
||||
*/
|
||||
void CX9261A_initialChip();
|
||||
/**
|
||||
* @brief 初始化电源配置,如果只自定义配置部分模式下的电源管理,在自定义配置之前需要先调用此函数
|
||||
*/
|
||||
void CX9261A_initialPowerConfig(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief 初始化BBPLL相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialBBPLL();
|
||||
/**
|
||||
* @brief 初始化PLL1相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL1();
|
||||
/**
|
||||
* @brief 初始化PLL2相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL2();
|
||||
/**
|
||||
* @brief 初始化PLL3相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL3();
|
||||
/**
|
||||
* @brief 初始化PLL4相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL4();
|
||||
/**
|
||||
* @brief 初始化PLL5相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL5();
|
||||
/**
|
||||
* @brief 配置受参考时钟频率影响的寄存器
|
||||
* @param ref 参考时钟频率,单位MHz
|
||||
*/
|
||||
void CX9261A_configRef(double ref);
|
||||
/**
|
||||
* @brief 配置时钟相关寄存器,包括ADC和BBPLL
|
||||
* @param config CX9261A参数结构体
|
||||
*/
|
||||
void CX9261A_configBBPLL(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief BBPLL AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcBBPll();
|
||||
/**
|
||||
* @brief 配置PLL1频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll1(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll1 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll1();
|
||||
/**
|
||||
* @brief 配置PLL2频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll2(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll2 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll2();
|
||||
/**
|
||||
* @brief 配置PLL3频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll3(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll3 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll3();
|
||||
/**
|
||||
* @brief 配置PLL4频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll4(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll4 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll4();
|
||||
/**
|
||||
* @brief 配置PLL5频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll5(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll5 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll5();
|
||||
/**
|
||||
* @brief 配置AGC模式
|
||||
* @param mode 模式0~13
|
||||
*/
|
||||
void CX9261A_configAGCMode(int mode);
|
||||
/**
|
||||
* @brief 配置AGC PDT
|
||||
* @param pdt AGCPDT结构体
|
||||
*/
|
||||
void CX9261A_configAGCPDT(const CX9261A_AGCPDT *pdt);
|
||||
/**
|
||||
* @brief 配置AGC LMT
|
||||
* @param lmt AGCLMT结构体
|
||||
*/
|
||||
void CX9261A_configAGCLMT(const CX9261A_AGCLMT *lmt);
|
||||
/**
|
||||
* @brief 配置AGC DIG
|
||||
* @param dig AGCDIG结构体
|
||||
*/
|
||||
void CX9261A_configAGCDIG(const CX9261A_AGCDIG *dig);
|
||||
/**
|
||||
* @brief 配置AGC
|
||||
* @param agc AGC结构体
|
||||
*/
|
||||
void CX9261A_configAGC(const CX9261A_AGC *agc);
|
||||
/**
|
||||
* @brief 配置片内处理器,仅在使用需要处理器辅助的校准方法时需要开启处理器
|
||||
* @param on 开启/关闭
|
||||
*/
|
||||
void CX9261A_configRISCV(bool on);
|
||||
/**
|
||||
* @brief 配置温补
|
||||
* @param mode 温补模式 DAC/Band
|
||||
*/
|
||||
void CX9261A_configTemperatureCompensation(CX9261A_TemperatureComp mode);
|
||||
/**
|
||||
* @brief ADC校准
|
||||
* @param adc ADC速率
|
||||
*/
|
||||
void CX9261A_configADCCalib(double adc);
|
||||
/**
|
||||
* @brief Flash校准
|
||||
*/
|
||||
void CX9261A_configFlashCalib();
|
||||
/**
|
||||
* @brief QEC校准会改变部分寄存器配置,在进行校准之前需要保存这部分寄存器,校准后恢复
|
||||
* @return 包含寄存器地址和值的map
|
||||
*/
|
||||
void CX9261A_beforeQecState(QecStatePair* buff, size_t *len);
|
||||
/**
|
||||
* @brief 恢复QEC校准过程中改变的寄存器
|
||||
* @param state beforeQecState函数返回的map
|
||||
*/
|
||||
void CX9261A_restoreQecState(QecStatePair* buff, size_t len);
|
||||
/**
|
||||
* @brief 根据pll来源配置校准模式下的电源管理
|
||||
* @param pllSource PllSource结构体
|
||||
*/
|
||||
void CX9261A_preparePowerForRxCalib(const CX9261A_PllSource *pllSource);
|
||||
/**
|
||||
* @brief 调整校准时Pll的配置
|
||||
* @param config CX9261A配置结构体
|
||||
* @param chan 要进行校准的通道
|
||||
*/
|
||||
void CX9261A_preparePllForRxCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 等待RxTST窄带校准结束,可重写
|
||||
* @return 校准是否结束
|
||||
*/
|
||||
bool CX9261A_waitRxTSTFinished();
|
||||
/**
|
||||
* @brief RX时域统计校准
|
||||
* @param chan 校准的RX通道
|
||||
*/
|
||||
void CX9261A_rxTSTCalib(CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief RX延时线校准
|
||||
* @param fs ADC采样率
|
||||
* @param chan 校准的RX通道
|
||||
*/
|
||||
void CX9261A_rxDelayCalib(double fs, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief DC Tracking
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_configDcCalib(const CX9261A_Calib *config);
|
||||
void CX9261A_configDcCalibMethod(CX9261A_DCCalibMethod method);
|
||||
void CX9261A_configDcTrackingLength(int length);
|
||||
void CX9261A_configDcHighPassFactor(int factor);
|
||||
/**
|
||||
* @brief Rx校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param chan 要进行校准的通道
|
||||
*/
|
||||
void CX9261A_rxCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 选择校准方法
|
||||
* @param calib 校准结构体
|
||||
*/
|
||||
void CX9261A_configCalibMethod(const CX9261A_Calib *calib);
|
||||
/**
|
||||
* @brief 读取当前Rx chan通道的校准值
|
||||
* @param chan Rx通道
|
||||
* @return 校准值结构体
|
||||
*/
|
||||
CX9261A_CalibPredis CX9261A_readRxCalibPredis(CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 储存校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 接收通道
|
||||
* @param pll 使用的PLL
|
||||
*/
|
||||
void CX9261A_saveRxCalibPredis(unsigned char index, CX9261A_RxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief 加载保存的校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 指定加载校准值的通道
|
||||
* @param pll 使用的PLL
|
||||
*/
|
||||
void CX9261A_loadRxCalibPredis(unsigned char index, CX9261A_RxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief Rx窄带多点校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param points 校准点
|
||||
* @param chan 接收通道
|
||||
*/
|
||||
void CX9261A_configRxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan, const double *points, size_t len);
|
||||
/**
|
||||
* @brief 根据pll来源配置校准模式下的电源管理
|
||||
* @param pllSource PllSource结构体
|
||||
*/
|
||||
void CX9261A_preparePowerForTxCalib(const CX9261A_PllSource *pllSource);
|
||||
/**
|
||||
* @brief 调整校准时Pll的配置
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_preparePllForTxCalib(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief TX二分法QEC校准
|
||||
* @param f0 校准音频率
|
||||
* @param fs adc频率
|
||||
*/
|
||||
void CX9261A_txBisectionQecCalib(double f0, double fs);
|
||||
/**
|
||||
* @brief TX时域统计法校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param chan 要校准的通道
|
||||
*/
|
||||
void CX9261A_txTSTCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief TX二分法DC校准
|
||||
* @param f0 校准音频率
|
||||
* @param fs adc频率
|
||||
*/
|
||||
void CX9261A_txBisectionDcCalib(double f0, double fs);
|
||||
/**
|
||||
* @brief Tx多点校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param points 校准点
|
||||
*/
|
||||
void CX9261A_configTxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, const double *points, size_t len);
|
||||
/**
|
||||
* @brief Tx通道校准
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_txCalib(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief 储存校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 发射通道
|
||||
* @param pll pll
|
||||
*/
|
||||
void CX9261A_saveTxCalibPredis(unsigned char index, CX9261A_TxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief 加载保存的校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 指定加载校准值的通道
|
||||
* @param pll 指定加载校准值对应的PLL
|
||||
*/
|
||||
void CX9261A_loadTxCalibPredis(unsigned char index, CX9261A_TxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief Qec校准顶层函数,内部根据配置选择使用对应方法进行校准
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_configQecCalib(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief 配置TX NCO相关寄存器
|
||||
* @param nco TX NCO配置结构体
|
||||
* @param fs adc速率
|
||||
*/
|
||||
void CX9261A_configTxNco(const CX9261A_TxNCO *nco, double fs);
|
||||
/**
|
||||
* @brief 配置TX NCO BIST模式
|
||||
* @param bist 开启/关闭BIST
|
||||
*/
|
||||
void CX9261A_configTxBIST(bool bist);
|
||||
/**
|
||||
* @brief 配置TX NCO频率
|
||||
* @param freq 混频频率
|
||||
* @param fs adc抽取后速率
|
||||
*/
|
||||
void CX9261A_configTxNcoFreq(double freq, double fs);
|
||||
/**
|
||||
* @brief 配置RX NCO相关寄存器
|
||||
* @param nco RX NCO配置结构体
|
||||
* @param fs adc速率
|
||||
*/
|
||||
void CX9261A_configRxNco(const CX9261A_RxNCO *nco, double fs);
|
||||
/**
|
||||
* @brief 配置Rx NCO模式
|
||||
* @param mode NCO模式:Bypass/BIST/Up/Down
|
||||
*/
|
||||
void CX9261A_configRxNcoMode(CX9261A_NCOMode mode);
|
||||
/**
|
||||
* @brief 配置Rx NCO模式
|
||||
* @param mode NCO模式:Master/Slaver
|
||||
*/
|
||||
void CX9261A_configRxNcoMS(CX9261A_NCOMode mode);
|
||||
/**
|
||||
* @brief 配置Rx NCO频率
|
||||
* @param freq 混频频率
|
||||
* @param fs adc速率
|
||||
*/
|
||||
void CX9261A_configRxNcoFreq(double freq, double fs);
|
||||
/**
|
||||
* @brief 配置接口相关寄存器
|
||||
* @param interface Interface配置结构体
|
||||
*/
|
||||
void CX9261A_configInterface(const CX9261A_Interface *interface);
|
||||
/**
|
||||
* @brief 配置PLL来源
|
||||
* @param pllSource PLlSource结构体
|
||||
*/
|
||||
void CX9261A_configPllSource(const CX9261A_PllSource *pllSource);
|
||||
/**
|
||||
* @brief 切换电源模式
|
||||
* @param pm 电源模式
|
||||
*/
|
||||
void CX9261A_configPowerMode(CX9261A_PowerMode pm);
|
||||
/**
|
||||
* @brief 配置电源管理
|
||||
* @param power 电源配置结构体
|
||||
* @param pm 电源模式
|
||||
*/
|
||||
void CX9261A_configPowerPins(const CX9261A_Power *power, CX9261A_PowerMode pm);
|
||||
/**
|
||||
* @brief 配置参考倍频器
|
||||
* @param doubler 倍频器开关
|
||||
* @param ref 参考时钟频率,单位MHz
|
||||
*/
|
||||
void CX9261A_configRefDoubler(bool doubler, double ref);
|
||||
/**
|
||||
* @brief 初始化通道,调用initialChip函数会初始化RX1,RX2,RX3三个通道
|
||||
* @param chan 通道 RX1/RX2/RX3
|
||||
*/
|
||||
void CX9261A_initialRxChannel(CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx带宽
|
||||
* @note 只改变Rx带宽会导致通道增益改变,建议使用configRxChannel函数进行带宽调整
|
||||
* @param bandwidth 带宽,单位(MHz)
|
||||
* @param chan 通道 Rx1/Rx2/Rx3
|
||||
*/
|
||||
void CX9261A_configRxBandwidth(double bandwidth, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx TIA
|
||||
* @note 只改变TIA会导致通道带宽改变,建议使用configRxChannel函数进行TIA调整
|
||||
* @param tia tia档位
|
||||
* @param chan 通道 Rx1/Rx2/Rx3
|
||||
*/
|
||||
void CX9261A_configRxTIA(int tia, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx Mixer
|
||||
* @param mixer mixer档位
|
||||
*/
|
||||
void CX9261A_configRxMixer(int mixer);
|
||||
/**
|
||||
* @brief 配置Rx通道,包含TIA,Mixer以及Bandwidth
|
||||
* @param config RxConfig结构体
|
||||
* @param chan Rx1/Rx2/Rx3
|
||||
*/
|
||||
void CX9261A_configRxChannel(const CX9261A_RxConfig *config, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx FIR滤波器抽取倍数
|
||||
* @param fir 抽取倍数 0(Bypass)/1/2/3/4/8
|
||||
*/
|
||||
void CX9261A_configRxFIR(int fir);
|
||||
/**
|
||||
* @brief 配置Rx HBF1滤波器抽取倍数
|
||||
* @param hbf 抽取倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configRxHBF1(int hbf);
|
||||
/**
|
||||
* @brief 配置Rx HBF2滤波器抽取倍数
|
||||
* @param hbf 抽取倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configRxHBF2(int hbf);
|
||||
/**
|
||||
* @brief 配置Rx HBF3滤波器抽取倍数
|
||||
* @param hbf 抽取倍数 0(Bypass)/2/3
|
||||
*/
|
||||
void CX9261A_configRxHBF3(int hbf);
|
||||
/**
|
||||
* @brief 配置Rx CIC滤波器
|
||||
* @param cic 抽取倍数 0(Bypass)/20
|
||||
*/
|
||||
void CX9261A_configRxCIC(int cic);
|
||||
/**
|
||||
* @brief 配置Rx滤波器
|
||||
* @param filters Filters结构体
|
||||
*/
|
||||
void CX9261A_configRxFilters(const CX9261A_Filters *filters);
|
||||
/**
|
||||
* @brief 配置Rx FIR滤波器系数
|
||||
* @param coe 滤波器系数,长度为16的整倍数,最大128
|
||||
*/
|
||||
void CX9261A_configRxFIRCoe(const double *coe, size_t len);
|
||||
/**
|
||||
* @brief 配置Tx带宽
|
||||
* @param bandwidth 带宽,单位(MHz)
|
||||
* @param chan 通道 TX1/TX2
|
||||
*/
|
||||
void CX9261A_configTxBandwidth(double bandwidth, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 配置Tx Mixer
|
||||
* @param mixer 混频器值
|
||||
* @param chan TX1/TX2
|
||||
*/
|
||||
void CX9261A_configTxMixer(int mixer, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 初始化Tx通道
|
||||
* @param chan 通道 TX1/TX2
|
||||
*/
|
||||
void CX9261A_initialTxChannel(CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 根据Tx通道的本振频率,配置对应的参数
|
||||
* @param lo 本振频率,单位(MHz)
|
||||
* @param chan 通道(Tx1/Tx2)
|
||||
*/
|
||||
void CX9261A_configTxChannelFrequency(double lo, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 配置Tx通道,Mixer以及Bandwidth
|
||||
* @param config TxConfig结构体
|
||||
* @param chan Tx1/Tx2
|
||||
*/
|
||||
void CX9261A_configTxChannel(const CX9261A_TxConfig *config, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 配置Tx FIR滤波器插值倍数
|
||||
* @param fir 插值倍数 0(Bypass)/1/2/3/4/8
|
||||
*/
|
||||
void CX9261A_configTxFIR(int fir);
|
||||
/**
|
||||
* @brief 配置Tx HBF1滤波器插值倍数
|
||||
* @param hbf 插值倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configTxHBF1(int hbf);
|
||||
/**
|
||||
* @brief 配置Tx HBF2滤波器插值倍数
|
||||
* @param hbf 插值倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configTxHBF2(int hbf);
|
||||
/**
|
||||
* @brief 配置Tx HBF3滤波器插值倍数
|
||||
* @param hbf 插值倍数 0(Bypass)/2/3
|
||||
*/
|
||||
void CX9261A_configTxHBF3(int hbf);
|
||||
/**
|
||||
* @brief 配置Tx CIC滤波器
|
||||
* @param cic 插值倍数 0(Bypass)/8/20/32/80
|
||||
*/
|
||||
void CX9261A_configTxCIC(int cic);
|
||||
/**
|
||||
* @brief 配置Tx滤波器
|
||||
* @param filters Filters结构体
|
||||
*/
|
||||
void CX9261A_configTxFilters(const CX9261A_Filters *filters);
|
||||
/**
|
||||
* @brief 配置Tx FIR滤波器系数
|
||||
* @param coe 滤波器系数,长度为16的整倍数,最大128
|
||||
*/
|
||||
void CX9261A_configTxFIRCoe(const double *coe, size_t len);
|
||||
/**
|
||||
* @brief 读取当前Tx chan通道的校准值
|
||||
* @param chan Tx通道
|
||||
* @return 校准值结构体
|
||||
*/
|
||||
CX9261A_CalibPredis CX9261A_readTxCalibPredis(CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 此函数为Demo板配套配置函数,用于配置FPGA接口,用户开发自己的程序时应重写对应功能
|
||||
* @param interface Interface结构体
|
||||
*/
|
||||
void CX9261A_configFPGA(const CX9261A_Interface *interface);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __CX9261ADRIVER_C_H
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>link_test</name>
|
||||
<comment>Created by SDK v2019.1. standalone_ps7_cortexa9_0 - ps7_cortexa9_0</comment>
|
||||
<projects>
|
||||
<project>standalone_ps7_cortexa9_0</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,901 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Description: hwconfig.h
|
||||
*
|
||||
|
||||
* Date: 2024-02-20 13:19
|
||||
* Last Edit Time: [2024-02-20 13:19]
|
||||
*
|
||||
* Revisions: Rev 0.0
|
||||
* History:
|
||||
* [2023-05-07]: Initial edition.
|
||||
*
|
||||
* Copyright(c) 2024 Beijing Institute of Technology.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
// Standard
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
// Xilinx
|
||||
#include "xgpiops.h"
|
||||
#include "drivers/axi_core/spi_engine/spi_engine.h"
|
||||
// App
|
||||
#include "common.h"
|
||||
#include "error.h"
|
||||
#include "delay.h"
|
||||
#include "system_monitor.h"
|
||||
#include "hwconfig.h"
|
||||
#include "config/app_config.h"
|
||||
#include "dev_profile/dev_profile.h"
|
||||
|
||||
#ifdef RFSOC
|
||||
#include "xrfdc.h"
|
||||
#endif
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
/*********************** Driver Instance Definitions **************************/
|
||||
static struct hmc7044_dev *hmc7044_inst;
|
||||
ad9528Device_t *ad9528_inst;
|
||||
static struct lmk04828_dev *lmk04828_inst;
|
||||
static struct lmx2594_dev *lmx2594_adc_inst;
|
||||
static struct lmx2594_dev *lmx2594_dac_inst;
|
||||
static struct ad9361_reg_dev *ad9361_1_reg_inst;
|
||||
static struct ad9361_reg_dev *ad9361_2_reg_inst;
|
||||
static struct cx9261a_dev *cx9261a_inst;
|
||||
static struct ad9361_rf_phy *ad9361_phy;
|
||||
static struct ad9653_dev *ad9653_inst;
|
||||
static struct ad9694_dev *ad9694_inst;
|
||||
|
||||
XGpioPs Gpio;
|
||||
#ifdef RFSOC
|
||||
XRFdc RFdc;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Hardware_SwitchFreq
|
||||
*
|
||||
* @param devSysMonitor_UpdateHardwareStatus(newHwState);
|
||||
* @param freq
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq)
|
||||
{
|
||||
int32_t status = 0;
|
||||
uint8_t value = 0;
|
||||
int32_t time_out_cnt = 0;
|
||||
|
||||
switch (freq)
|
||||
{
|
||||
case TX_FREQ_125:
|
||||
{
|
||||
//************************************************************
|
||||
// Setup Tx Frequency-Dependent Syntheisizer Registers
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
|
||||
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
|
||||
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
|
||||
status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp)
|
||||
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
|
||||
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
|
||||
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
|
||||
|
||||
//************************************************************
|
||||
// Write Tx Frequency Words
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0]
|
||||
status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8]
|
||||
status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16]
|
||||
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
|
||||
status = ad9361_reg_write(dev, 0x0271, 0xA0); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
|
||||
status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting
|
||||
|
||||
//************************************************************
|
||||
// Tx Quadrature Calibration Settings
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
|
||||
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
|
||||
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
|
||||
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
|
||||
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
|
||||
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
|
||||
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
|
||||
status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index
|
||||
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
|
||||
status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used
|
||||
|
||||
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
|
||||
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
|
||||
|
||||
break;
|
||||
}
|
||||
case TX_FREQ_126:
|
||||
{
|
||||
//************************************************************
|
||||
// Setup Tx Frequency-Dependent Syntheisizer Registers
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
|
||||
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
|
||||
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
|
||||
status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp)
|
||||
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
|
||||
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
|
||||
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
|
||||
|
||||
//************************************************************
|
||||
// Write Tx Frequency Words
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x0273, 0x06); // Write Tx Synth Fractional Freq Word[7:0]
|
||||
status = ad9361_reg_write(dev, 0x0274, 0xD7); // Write Tx Synth Fractional Freq Word[15:8]
|
||||
status = ad9361_reg_write(dev, 0x0275, 0x23); // Write Tx Synth Fractional Freq Word[22:16]
|
||||
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
|
||||
status = ad9361_reg_write(dev, 0x0271, 0xA1); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
|
||||
status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting
|
||||
|
||||
//************************************************************
|
||||
// Tx Quadrature Calibration Settings
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
|
||||
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
|
||||
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
|
||||
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
|
||||
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
|
||||
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
|
||||
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
|
||||
status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index
|
||||
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
|
||||
status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used
|
||||
|
||||
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
|
||||
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
|
||||
|
||||
break;
|
||||
}
|
||||
case TX_FREQ_4125:
|
||||
{
|
||||
//************************************************************
|
||||
// Setup Tx Frequency-Dependent Syntheisizer Registers
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
|
||||
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
|
||||
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
|
||||
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
|
||||
status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp)
|
||||
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
|
||||
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
|
||||
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
|
||||
|
||||
//************************************************************
|
||||
// Write Rx Frequency Words
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0]
|
||||
status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8]
|
||||
status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16]
|
||||
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
|
||||
status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
|
||||
status = ad9361_reg_write(dev, 0x0005, 0x07); // Set LO divider setting
|
||||
|
||||
//************************************************************
|
||||
// Tx Quadrature Calibration Settings
|
||||
//************************************************************
|
||||
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
|
||||
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
|
||||
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
|
||||
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
|
||||
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
|
||||
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
|
||||
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
|
||||
status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index
|
||||
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
|
||||
status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used
|
||||
|
||||
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
|
||||
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait for cal to complete (Done when 0x016[4]==0)
|
||||
time_out_cnt = 0;
|
||||
do
|
||||
{
|
||||
status |= ad9361_reg_read(dev, 0x0016, &value);
|
||||
mdelay(1); // Wait 1ms
|
||||
time_out_cnt++;
|
||||
} while ((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// @ Get AD9361 - 1 temperature (Celsius Degree)
|
||||
/**
|
||||
* Read corresponding register to get AD9361 - 1 current temperature.
|
||||
*/
|
||||
int8_t Hardware_GetAD9361Temp_1(void)
|
||||
{
|
||||
int8_t scaleTemp;
|
||||
double temp;
|
||||
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x000B, -64);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x01); // disable aux adc
|
||||
ad9361_reg_read(ad9361_1_reg_inst, 0x000E, (uint8_t*)&scaleTemp);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x00); // enable aux adc
|
||||
|
||||
temp = ((double)scaleTemp + 64)/1.16;
|
||||
return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp);
|
||||
}
|
||||
|
||||
// @ Get AD9361 - 2 temperature (Celsius Degree)
|
||||
/**
|
||||
* Read corresponding register to get AD9361 - 2 current temperature.
|
||||
*/
|
||||
int8_t Hardware_GetAD9361Temp_2(void)
|
||||
{
|
||||
int8_t scaleTemp;
|
||||
double temp;
|
||||
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x000B, -64);
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x01); // disable aux adc
|
||||
ad9361_reg_read(ad9361_2_reg_inst, 0x000E, (uint8_t*)&scaleTemp);
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x00); // enable aux adc
|
||||
temp = ((double)scaleTemp + 64)/1.16;
|
||||
return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp);
|
||||
}
|
||||
|
||||
// @ Determine AD9361 lock state
|
||||
/**
|
||||
* Read corresponding register to determine AD9361(both) lock state.
|
||||
*/
|
||||
uint8_t Hardware_GetAD9361LockStatus(void)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
uint8_t regVal;
|
||||
|
||||
// bbpll
|
||||
ad9361_reg_read(ad9361_1_reg_inst, 0x005E, ®Val); // [D7] is lock indicator
|
||||
ret |= ((regVal & 0x80) == 0x80) ? CLK_AD0_BBPLL_LOCK : 0;
|
||||
ad9361_reg_read(ad9361_2_reg_inst, 0x005E, ®Val); // [D7] is lock indicator
|
||||
ret |= ((regVal & 0x80) == 0x80) ? CLK_AD1_BBPLL_LOCK : 0;
|
||||
|
||||
// rfpll
|
||||
ad9361_reg_read(ad9361_1_reg_inst, 0x0287, ®Val); // [D1] is lock indicator
|
||||
ret |= ((regVal & 0x02) == 0x02) ? CLK_AD0_RFPLL_LOCK : 0;
|
||||
ad9361_reg_read(ad9361_2_reg_inst, 0x0287, ®Val); // [D1] is lock indicator
|
||||
ret |= ((regVal & 0x02) == 0x02) ? CLK_AD1_RFPLL_LOCK : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// @ Determine HMC7044 lock state
|
||||
/**
|
||||
* Read corresponding register to determine clock lock state.
|
||||
*/
|
||||
uint8_t Hardware_GetHMC7044LockStatus(void)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
uint8_t regVal;
|
||||
|
||||
// pll1
|
||||
hmc7044_read(hmc7044_inst, 0x007C, ®Val); // [D5] is lock indicator
|
||||
ret |= ((regVal & 0xE0) != 0x00) ? CLK_SP_PLL0_LOCK : 0;
|
||||
|
||||
// pll2
|
||||
hmc7044_read(hmc7044_inst, 0x007D, ®Val); // [D0] is lock indicator
|
||||
ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL1_LOCK : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CX9261A_Log(const char *msg)
|
||||
{
|
||||
DBG_INFO("[CX9261A] %s\n", msg);
|
||||
}
|
||||
void CX9261A_spiWrite(int address, int value)
|
||||
{
|
||||
int32_t Status;
|
||||
|
||||
Status = cx9261a_write(cx9261a_inst,address,value);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("HW: CX9261A_spiWrite() failed!");
|
||||
}
|
||||
|
||||
}
|
||||
int CX9261A_spiRead(int address)
|
||||
{
|
||||
int32_t Status;
|
||||
uint8_t reg = 0;
|
||||
|
||||
Status = cx9261a_read(cx9261a_inst,address,®);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("HW: CX9261A_spiRead() failed!");
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
void CX9261A_mdelay(double ms)
|
||||
{
|
||||
mdelay((uint32_t)(ms));
|
||||
}
|
||||
void CX9261A_setPin(int pin, int value)
|
||||
{
|
||||
switch(pin){
|
||||
case 0:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_nrst, value);
|
||||
break;
|
||||
case 1:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_enable_trx1, value);
|
||||
break;
|
||||
case 2:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_enable_trx2, value);
|
||||
break;
|
||||
case 3:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_enable_rxfb, value);
|
||||
break;
|
||||
case 4:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_txnrx_trx1, value);
|
||||
break;
|
||||
case 5:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_txnrx_trx2, value);
|
||||
break;
|
||||
case 6:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_txnrx_rxfb, value);
|
||||
break;
|
||||
case 34:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_pl_rst, value);
|
||||
break;
|
||||
case 35:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_tr_sel, value);
|
||||
break;
|
||||
case 36:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_tdd_fdd_sel, value);
|
||||
break;
|
||||
case 37:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_r1t1_r2t2_sel, value);
|
||||
break;
|
||||
case 38:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_sp_dp_sel, value);
|
||||
break;
|
||||
case 43:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl0, value);
|
||||
break;
|
||||
case 44:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl1, value);
|
||||
break;
|
||||
case 45:
|
||||
gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl2, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cx9261a_trx_ch_pll_config(u8 pll_index)
|
||||
{
|
||||
u8 rx_data;
|
||||
u8 recv_buf[3]={0};
|
||||
u32 trx_ch_pll_data;
|
||||
|
||||
if(pll_index==1){
|
||||
trx_ch_pll_data = 0x00077DCF;
|
||||
}else if(pll_index==2){
|
||||
trx_ch_pll_data = 0x00077D0C;
|
||||
}
|
||||
|
||||
cx9261a_write(cx9261a_inst,trx_ch_pll_data >> 8, trx_ch_pll_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @brief Hardware_Init
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int32_t Hardware_Init(void)
|
||||
{
|
||||
int32_t Status;
|
||||
|
||||
// gpio initialization
|
||||
XGpioPs_Config *ConfigPtr;
|
||||
ConfigPtr = XGpioPs_LookupConfig(AD9361_GPIO_DEVICE_ID);
|
||||
Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
#ifdef RFSOC
|
||||
/**********************************************************/
|
||||
/************* RF Data Converter Configuration ************/
|
||||
/**********************************************************/
|
||||
// rf data converter initialization
|
||||
XRFdc_Config *RFdc_ConfigPtr;
|
||||
RFdc_ConfigPtr = XRFdc_LookupConfig(RFDC_DEVICE_ID);
|
||||
Status = XRFdc_CfgInitialize(&RFdc, RFdc_ConfigPtr);
|
||||
if (Status != XST_SUCCESS)
|
||||
{
|
||||
return XST_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HMC7044
|
||||
/**********************************************************/
|
||||
/****************** HMC7044 Configuration *****************/
|
||||
/**********************************************************/
|
||||
Status = hmc7044_init(&hmc7044_inst, &hmc7044_default_init_param);
|
||||
if (Status != SUCCESS)
|
||||
{
|
||||
DBG_ERROR("HDWR: hmc7044_init() error: %" PRId32 "\n", Status);
|
||||
return FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AD9528
|
||||
/**********************************************************/
|
||||
/****************** AD9528 Configuration ******************/
|
||||
/**********************************************************/
|
||||
Status = AD9528_init(&ad9528_inst, &ad9528_default_init_param);
|
||||
if (Status != SUCCESS) {
|
||||
DBG_ERROR("HDWR: AD9528_init() error: %" PRId32 "\n", Status);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
Status = AD9528_config(ad9528_inst);
|
||||
if (Status != SUCCESS) {
|
||||
return FAILURE;
|
||||
DBG_ERROR("HDWR: AD9528_config() error: %" PRId32 "\n", Status);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LMK04828
|
||||
/**********************************************************/
|
||||
/***************** LMK04828 Configuration *****************/
|
||||
/**********************************************************/
|
||||
Status = lmk04828_init(&lmk04828_inst, &lmk04828_default_init_param);
|
||||
for(int i = 0; i < lmk04828_default_config_len; i++)
|
||||
{
|
||||
Status = lmk04828_write(lmk04828_inst,
|
||||
lmk04828_default_config[i].addr, lmk04828_default_config[i].value);
|
||||
if (lmk04828_default_config[i].addr == 0x0000)
|
||||
{
|
||||
mdelay(500);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Lmk04828Read;
|
||||
|
||||
// check pll1 lock status
|
||||
Status = lmk04828_read(lmk04828_inst, 0x0182, &Lmk04828Read);
|
||||
if ((Lmk04828Read & 0x02) == 0x02) {
|
||||
DBG_INFO("HDWR: [LMK04828] PLL1 Locked.\r\n");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR("HDWR: [LMK04828] PLL1 NOT lock. It takes a while "
|
||||
"for PLL1 to lock. Lock status is shown on LED.\r\n");
|
||||
}
|
||||
|
||||
// check pll2 lock status
|
||||
Status = lmk04828_read(lmk04828_inst, 0x0183, &Lmk04828Read);
|
||||
if ((Lmk04828Read & 0x02) == 0x02) {
|
||||
DBG_INFO("HDWR: [LMK04828] PLL2 Locked.\r\n");
|
||||
}
|
||||
else {
|
||||
DBG_INFO("HDWR: [LMK04828] PLL2 NOT lock!\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LMX2594_ADC
|
||||
/**********************************************************/
|
||||
/************* LMX2594 for ADC Configuration **************/
|
||||
/**********************************************************/
|
||||
Status = lmx2594_init(&lmx2594_adc_inst, &lmx2594_adc_init_param);
|
||||
for(int i = 0; i < lmx2594_default_config_len; i++)
|
||||
{
|
||||
Status = lmx2594_write(lmx2594_adc_inst,
|
||||
lmx2594_default_config[i].addr, lmx2594_default_config[i].value);
|
||||
if (lmx2594_default_config[i].addr == 0)
|
||||
{
|
||||
mdelay(500);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Lmx2594AdcRead;
|
||||
|
||||
// check vco lock status
|
||||
Status = lmx2594_read(lmx2594_adc_inst, 110, &Lmx2594AdcRead);
|
||||
if (((Lmx2594AdcRead >> 9) & 0x0003) == 0x0002) {
|
||||
DBG_INFO("HDWR: [ADC LMX2594] Config Done.\r\n");
|
||||
}
|
||||
else {
|
||||
DBG_INFO("HDWR: [ADC LMX2594] not lock!\r\n");
|
||||
}
|
||||
|
||||
// set mux out to lock status
|
||||
Status = lmx2594_write(lmx2594_adc_inst, 0x00, 0x259C);
|
||||
DBG_INFO("HDWR: [ADC LMX2594] SPI readback disabled, "
|
||||
"lock status is shown on LED.\r\n");
|
||||
#endif
|
||||
|
||||
#ifdef LMX2594_DAC
|
||||
/**********************************************************/
|
||||
/************* LMX2594 for DAC Configuration **************/
|
||||
/**********************************************************/
|
||||
Status = lmx2594_init(&lmx2594_dac_inst, &lmx2594_dac_init_param);
|
||||
for(int i = 0; i < lmx2594_default_config_len; i++)
|
||||
{
|
||||
Status = lmx2594_write(lmx2594_dac_inst,
|
||||
lmx2594_default_config[i].addr, lmx2594_default_config[i].value);
|
||||
if (lmx2594_default_config[i].addr == 0)
|
||||
{
|
||||
mdelay(500);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Lmx2594DacRead;
|
||||
|
||||
// check vco lock status
|
||||
Status = lmx2594_read(lmx2594_dac_inst, 110, &Lmx2594DacRead);
|
||||
if (((Lmx2594DacRead >> 9) & 0x0003) == 0x0002) {
|
||||
DBG_INFO("HDWR: [DAC LMX2594] Config Done.\r\n");
|
||||
}
|
||||
else {
|
||||
DBG_INFO("HDWR: [DAC LMX2594] not lock!\r\n");
|
||||
}
|
||||
|
||||
// set mux out to lock status
|
||||
Status = lmx2594_write(lmx2594_dac_inst, 0x00, 0x259C);
|
||||
DBG_INFO("HDWR: [DAC LMX2594] SPI readback disabled, "
|
||||
"lock status is shown on LED.\r\n");
|
||||
#endif
|
||||
|
||||
#if defined(AD9361_API) || defined(AD9361_REG)
|
||||
/**********************************************************/
|
||||
/***************** AD9361-1 Configuration *****************/
|
||||
/**********************************************************/
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_TXNRX, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_ENABLE, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_EN_AGC, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_RESET_B, AD9361_GPIO_OUTPUT);
|
||||
|
||||
#ifdef AD9361_REG
|
||||
ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 0);
|
||||
ad9361_reg_config(ad9361_1_reg_inst);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 1);
|
||||
#endif
|
||||
#ifdef AD9361_API
|
||||
Status = ad9361_init(&ad9361_phy, &ad9361_default_init_param);
|
||||
if (Status != XST_SUCCESS){
|
||||
DBG_ERROR("HDWR: ad9361_init() error: %" PRId32 "\n", Status);
|
||||
return XST_FAILURE;
|
||||
}
|
||||
ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config);
|
||||
ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config);
|
||||
#endif
|
||||
/**********************************************************/
|
||||
/***************** AD9361-2 Configuration *****************/
|
||||
/**********************************************************/
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_TXNRX, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_ENABLE, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_EN_AGC, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_RESET_B, AD9361_GPIO_OUTPUT);
|
||||
|
||||
ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 0);
|
||||
ad9361_reg_config(ad9361_2_reg_inst);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 1);
|
||||
|
||||
// uint8_t rd_back;
|
||||
// Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back);
|
||||
// Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back);
|
||||
|
||||
/**********************************************************/
|
||||
/******* AD9361 Baseband Multichip Synchronization ********/
|
||||
/**********************************************************/
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_SYNC, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_RX_FIFO_RST, AD9361_GPIO_OUTPUT);
|
||||
|
||||
// SYNC BBPLL and DIGITAL SAMPLING CLOCKS
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
|
||||
mdelay(20);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin
|
||||
mdelay(500);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
|
||||
mdelay(2000);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin
|
||||
mdelay(500);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
|
||||
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits
|
||||
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08);
|
||||
|
||||
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0);
|
||||
mdelay(20);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 1);
|
||||
mdelay(20);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0);
|
||||
|
||||
/**********************************************************/
|
||||
/********* AD9361 Multichip Rx Phase Calibration **********/
|
||||
/**********************************************************/
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_TX_SWITCH, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_START, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_DONE, AD9361_GPIO_INPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_START, AD9361_GPIO_OUTPUT);
|
||||
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_DONE, AD9361_GPIO_INPUT);
|
||||
|
||||
// switch to lower frequency
|
||||
Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_126);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 1);
|
||||
mdelay(20);
|
||||
|
||||
// switch rx channel
|
||||
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x30);
|
||||
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x30);
|
||||
|
||||
// enable dual ad9361 tx channels
|
||||
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xE4); // Setup Tx Digital Filters/ Channels
|
||||
|
||||
// switch ad9361 tx channel
|
||||
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x70); // Select Rx input pin(A,B,C)/ Tx out pin (A,B)
|
||||
mdelay(20);
|
||||
|
||||
// begin to calibrate the 1st ad9361
|
||||
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 1);
|
||||
mdelay(1);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0);
|
||||
|
||||
// read calibration status
|
||||
int32_t time_out_cnt = 0;
|
||||
do
|
||||
{
|
||||
mdelay(1); // Wait 1ms
|
||||
time_out_cnt++;
|
||||
} while (((XGpioPs_ReadPin(&Gpio, AD9361_1_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH));
|
||||
|
||||
if (time_out_cnt == AD9361_TIMEOUT_TH)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// begin to calibrate the 2nd ad9361
|
||||
XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 1);
|
||||
mdelay(1);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 0);
|
||||
|
||||
// read calibration status
|
||||
time_out_cnt = 0;
|
||||
do
|
||||
{
|
||||
mdelay(1); // Wait 1ms
|
||||
time_out_cnt++;
|
||||
} while (((XGpioPs_ReadPin(&Gpio, AD9361_2_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH));
|
||||
|
||||
if (time_out_cnt == AD9361_TIMEOUT_TH)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// enable single ad9361 tx channels
|
||||
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels
|
||||
|
||||
// switch ad9361 tx & rx channel
|
||||
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x03);
|
||||
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x03);
|
||||
|
||||
// switch to higher frequency
|
||||
Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_4125);
|
||||
XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 0);
|
||||
|
||||
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 0x00); // Rx Gain
|
||||
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x00); // Rx Gain
|
||||
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x00); // Rx Gain
|
||||
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x010C, 0x00); // Rx Gain
|
||||
#endif
|
||||
|
||||
#ifdef AD9653
|
||||
/**********************************************************/
|
||||
/****************** AD9653 Configuration ******************/
|
||||
/**********************************************************/
|
||||
Status = ad9653_init(&ad9653_inst, &ad9653_default_init_param);
|
||||
for(int i = 0; i < ad9653_default_config_len; i++){
|
||||
Status = ad9653_write(ad9653_inst, ad9653_default_config[i].addr,
|
||||
ad9653_default_config[i].value);
|
||||
if (ad9653_default_config[i].addr == 0x0000){
|
||||
mdelay(500);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AD9694
|
||||
/**********************************************************/
|
||||
/****************** AD9694 Configuration ******************/
|
||||
/**********************************************************/
|
||||
Status = ad9694_init(&ad9694_inst, &ad9694_default_init_param);
|
||||
for(int i = 0; i < ad9694_default_config_len; i++){
|
||||
Status = ad9694_write(ad9694_inst, ad9694_default_config[i].addr, ad9694_default_config[i].value);
|
||||
if (ad9694_default_config[i].addr == 0x0000){
|
||||
mdelay(500);
|
||||
}
|
||||
}
|
||||
|
||||
// uint8_t reg0008;
|
||||
// uint8_t reg056F;
|
||||
// uint8_t reg0571;
|
||||
//
|
||||
// ad9694_read(ad9694_inst,0x008,®0008);
|
||||
// ad9694_read(ad9694_inst,0x56F,®056F);
|
||||
// ad9694_read(ad9694_inst,0x571,®0571);
|
||||
#endif
|
||||
|
||||
#ifdef CX9261A
|
||||
/**********************************************************/
|
||||
/***************** CX9261A Configuration ******************/
|
||||
/**********************************************************/
|
||||
cx9261a_init(&cx9261a_inst, &cx9261a_default_init_param);
|
||||
|
||||
// 绑定函数
|
||||
CX9261A_setLoggingFunc(CX9261A_Log);
|
||||
CX9261A_setWriteSpiFunc(CX9261A_spiWrite);
|
||||
CX9261A_setReadSpiFunc(CX9261A_spiRead);
|
||||
CX9261A_setPauseFunc(CX9261A_mdelay);
|
||||
CX9261A_setSetPinFunc(CX9261A_setPin);
|
||||
|
||||
// 开始配置芯片
|
||||
CX9261A_initialChip(); // 最开始需要调用此函数
|
||||
int reg;
|
||||
reg = CX9261A_spiRead(0x000);
|
||||
CX9261A_initialPowerConfig(&cx9261a_configuration);
|
||||
// 配置温补
|
||||
CX9261A_configTemperatureCompensation(cx9261a_configuration.tempComp);
|
||||
// 不需要自定义电源管理时,这部分代码可以省略
|
||||
CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.rxPower), CX9261A_PWM_Receive);
|
||||
CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.txPower), CX9261A_PWM_Transmit);
|
||||
CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.fddPower), CX9261A_PWM_Duplex);
|
||||
// 配置pll
|
||||
CX9261A_configBBPLL(&cx9261a_configuration);
|
||||
CX9261A_configPllSource(&(cx9261a_configuration.pllSource));
|
||||
CX9261A_configPll1(cx9261a_configuration.pllFreq.pll1Freq, &(cx9261a_configuration.clock));
|
||||
CX9261A_configPll2(cx9261a_configuration.pllFreq.pll2Freq, &(cx9261a_configuration.clock));
|
||||
// 配置Rx通道
|
||||
CX9261A_configRxChannel(&(cx9261a_configuration.rx1Config), CX9261A_RXCH_Rx1);
|
||||
CX9261A_configRxChannel(&(cx9261a_configuration.rx2Config), CX9261A_RXCH_Rx2);
|
||||
CX9261A_configRxChannel(&(cx9261a_configuration.rx3Config), CX9261A_RXCH_Rx3);
|
||||
// 配置Tx通道
|
||||
CX9261A_configTxChannelFrequency(cx9261a_configuration.pllFreq.pll1Freq, CX9261A_TXCH_Tx1);
|
||||
CX9261A_configTxChannelFrequency(cx9261a_configuration.pllFreq.pll2Freq, CX9261A_TXCH_Tx2);
|
||||
CX9261A_configTxChannel(&(cx9261a_configuration.tx1Config), CX9261A_TXCH_Tx1);
|
||||
CX9261A_configTxChannel(&(cx9261a_configuration.tx2Config), CX9261A_TXCH_Tx2);
|
||||
// 配置滤波器
|
||||
CX9261A_configRxFilters(&(cx9261a_configuration.rxFilters));
|
||||
CX9261A_configTxFilters(&(cx9261a_configuration.txFilters));
|
||||
// 配置NCO
|
||||
CX9261A_configRxNco(&(cx9261a_configuration.rxNco), cx9261a_configuration.clock.adc);
|
||||
int filters = max(cx9261a_configuration.rxFilters.fir, 1) * max(cx9261a_configuration.rxFilters.hbf3, 1) *
|
||||
max(cx9261a_configuration.rxFilters.hbf2, 1) *
|
||||
max(cx9261a_configuration.rxFilters.hbf1, 1) * max(cx9261a_configuration.rxFilters.cic, 1);
|
||||
CX9261A_configTxNco(&(cx9261a_configuration.txNco), cx9261a_configuration.clock.adc / filters);
|
||||
// 配置AGC
|
||||
CX9261A_configAGC(&(cx9261a_configuration.agc));
|
||||
// 切换到休眠模式
|
||||
CX9261A_configPowerMode(CX9261A_PWM_Sleep);
|
||||
CX9261A_mdelay(1000);
|
||||
// 切换到校准模式
|
||||
CX9261A_configPowerMode(CX9261A_PWM_Calib);
|
||||
CX9261A_mdelay(100);
|
||||
// 锁定BBPLL
|
||||
while (!CX9261A_afcBBPll());
|
||||
// 锁定PLL1
|
||||
while(!CX9261A_afcPll1());
|
||||
// 锁定PLL2
|
||||
while(!CX9261A_afcPll2());
|
||||
// 配置接口
|
||||
CX9261A_configInterface(&(cx9261a_configuration.interface));
|
||||
// 配置FPGA接口相关 此为示例,仅适用于Demo工程,用户应根据实际情况进行配置
|
||||
CX9261A_configFPGA(&(cx9261a_configuration.interface));
|
||||
// 配置校准
|
||||
CX9261A_configADCCalib(cx9261a_configuration.clock.adc);
|
||||
CX9261A_configFlashCalib();
|
||||
CX9261A_configDcCalib(&(cx9261a_configuration.calib));
|
||||
// CX9261A_configQecCalib(&cx9261a_configuration);
|
||||
// CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx1, CX9261A_LOSRC_Pll1);
|
||||
// CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx2, CX9261A_LOSRC_Pll1);
|
||||
// 切换到工作模式
|
||||
CX9261A_configPowerMode(cx9261a_configuration.powerManagement.powerMode);
|
||||
// 跳频
|
||||
|
||||
uint8_t hop_flag = 0;
|
||||
uint8_t hop_flag_new = 0;
|
||||
double hop_freq;
|
||||
|
||||
// while (true)
|
||||
// {
|
||||
// gpio_get_value(cx9261a_inst->gpio_desc_hop_flag, &hop_flag_new);
|
||||
// if (hop_flag != hop_flag_new)
|
||||
// {
|
||||
// hop_flag = hop_flag_new;
|
||||
//
|
||||
// double hop_freq;
|
||||
// double hop_freq1 = 800.25;
|
||||
// int pll_index=1;
|
||||
// int unlock_pll1_cnt=0,unlock_pll2_cnt=0;
|
||||
//
|
||||
// hop_freq = (rand()%(800-30))+30+(rand()%(101))/(double)100;
|
||||
//
|
||||
// if(hop_freq == hop_freq1){
|
||||
// if(pll_index == 2){
|
||||
// pll_index = 4;
|
||||
// }
|
||||
// else if(pll_index == 1){
|
||||
// pll_index = 3;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(hop_flag_new == 1)
|
||||
// {
|
||||
// if(pll_index == 1 || pll_index == 3)
|
||||
// {
|
||||
// //切换至pll2来源
|
||||
// cx9261a_trx_ch_pll_config(2);
|
||||
// //配置pll1参数
|
||||
// CX9261A_configPll1(hop_freq,&(cx9261a_configuration.clock));
|
||||
// // unlock_pll1_cnt=PLL_config(1,hop_freq,ref)-1;
|
||||
// while (!CX9261A_afcPll1()) {
|
||||
// unlock_pll1_cnt++;
|
||||
// }
|
||||
// pll_index = 2;
|
||||
// }
|
||||
// else if(pll_index == 2 || pll_index == 4)
|
||||
// {
|
||||
// //切换至pll1来源
|
||||
// cx9261a_trx_ch_pll_config(1);
|
||||
// //配置pll2参数
|
||||
// CX9261A_configPll2(hop_freq,&(cx9261a_configuration.clock));
|
||||
// // unlock_pll2_cnt=PLL_config(2,hop_freq,ref)-1;
|
||||
// while (!CX9261A_afcPll2()) {
|
||||
// unlock_pll2_cnt++;
|
||||
// }
|
||||
// pll_index = 1;
|
||||
// }
|
||||
// }
|
||||
// hop_freq1 = hop_freq;
|
||||
// if(unlock_pll2_cnt!=0 || unlock_pll1_cnt !=0){
|
||||
// DBG_ERROR("pll1 unlock num: %d; pll2 unlock num: %d;.\n", unlock_pll1_cnt, unlock_pll2_cnt);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
#endif
|
||||
DBG_INFO("HDWR: configuration Done.\n");
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Description: hwconfig.h
|
||||
*
|
||||
|
||||
* Date: 2024-02-20 13:19
|
||||
* Last Edit Time: [2024-02-20 13:19]
|
||||
*
|
||||
* Revisions: Rev 0.0
|
||||
* History:
|
||||
* [2023-05-07]: Initial edition.
|
||||
*
|
||||
* Copyright(c) 2024 Beijing Institute of Technology.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
// Standard
|
||||
#include <stdint.h>
|
||||
#include "config/app_config.h"
|
||||
#include "drivers/rf-transceiver/ad9361_reg/ad9361_reg.h"
|
||||
#include "drivers/rf-transceiver/ad9361/ad9361_api.h"
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
int32_t Hardware_Init(void);
|
||||
int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq);
|
||||
int8_t Hardware_GetAD9361Temp_1(void);
|
||||
int8_t Hardware_GetAD9361Temp_2(void);
|
||||
uint8_t Hardware_GetAD9361LockStatus(void);
|
||||
uint8_t Hardware_GetHMC7044LockStatus(void);
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/***************************************************************************//**
|
||||
* @file axi_io.h
|
||||
* @brief Header file of AXI IO.
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _AXI_IO_H_
|
||||
#define _AXI_IO_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* AXI IO Read data */
|
||||
int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data);
|
||||
|
||||
/* AXI IO Write data */
|
||||
int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data);
|
||||
|
||||
#endif // _AXI_IO_H_
|
||||
@@ -0,0 +1,100 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file circ_queue.h
|
||||
* @author FanHao (hao_fan_bit_ee@163.com)
|
||||
* @brief A simple circular FIFO bounded queue
|
||||
* @version 0.1
|
||||
* @date 2023-02-23
|
||||
* @note Forked from https://github.com/chrismerck/rpa_queue.git
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup Utility
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup CircularQueue
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CIRC_QUEUE_H
|
||||
#define CIRC_QUEUE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @struct CIRC_QUEUE
|
||||
* @brief Circular queue Instance
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
void **data;
|
||||
volatile uint32_t nelts; ///< number of elements
|
||||
uint32_t in; ///< next empty location
|
||||
uint32_t out; ///< next filled location
|
||||
uint32_t bounds; ///< max size of queue
|
||||
} CIRC_QUEUE;
|
||||
|
||||
/**
|
||||
* @brief create a FIFO queue
|
||||
* @param queue The new queue
|
||||
* @param queue_capacity maximum size of the queue
|
||||
*/
|
||||
bool CircQueueCreate(CIRC_QUEUE **queue, uint32_t queue_capacity);
|
||||
|
||||
/**
|
||||
* @brief free queue memory -- call after destroy
|
||||
*/
|
||||
void CircQueueFree(CIRC_QUEUE *queue);
|
||||
|
||||
/**
|
||||
* @brief Detects when the CIRC_QUEUE is full. This utility function is expected
|
||||
* to be called from within critical sections, and is not threadsafe.
|
||||
*/
|
||||
bool isCircQueueFull(CIRC_QUEUE *queue);
|
||||
|
||||
/**
|
||||
* @brief Detects when the CIRC_QUEUE is empty. This utility function is expected
|
||||
* to be called from within critical sections, and is not threadsafe.
|
||||
*/
|
||||
bool isCircQueueEmpty(CIRC_QUEUE *queue);
|
||||
|
||||
/**
|
||||
* @brief push/add an object to the queue, blocking if the queue is already full
|
||||
*
|
||||
* @param queue the queue
|
||||
* @param data the data
|
||||
* @return True on a successful push
|
||||
* @return False push failed
|
||||
*/
|
||||
bool CircQueuePush(CIRC_QUEUE *queue, void *data);
|
||||
|
||||
/**
|
||||
* @brief pop/get an object from the queue, blocking if the queue is already empty
|
||||
*
|
||||
* @param queue the queue
|
||||
* @param data the data
|
||||
* @return false pop failed
|
||||
* @return true on a successful pop
|
||||
*/
|
||||
bool CircQueuePop(CIRC_QUEUE *queue, void **data);
|
||||
|
||||
/**
|
||||
* @brief returns the size of the queue.
|
||||
*
|
||||
* @param queue the queue
|
||||
* @return the size of the queue
|
||||
*/
|
||||
uint32_t CircQueueSize(CIRC_QUEUE *queue);
|
||||
|
||||
#endif /* CIRC_QUEUE_H */
|
||||
|
||||
/** @} CircularQueue*/
|
||||
|
||||
/** @} Utility*/
|
||||
@@ -0,0 +1,138 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file clist.h
|
||||
* @author FanHao (hao_fan_bit_ee@163.com)
|
||||
* @brief A basic list data structure
|
||||
* @version 0.1
|
||||
* @date 2023-02-23
|
||||
* @note Forked from https://github.com/clibs/list
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup Utility
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup cList
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __CLIST_H__
|
||||
#define __CLIST_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @enum clist_direction_t
|
||||
* @brief clist_t iterator direction.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
LIST_HEAD,
|
||||
LIST_TAIL
|
||||
} clist_direction_t;
|
||||
|
||||
/**
|
||||
* @struct clist_node_t
|
||||
* @brief clist_t node struct.
|
||||
*/
|
||||
typedef struct clist_node
|
||||
{
|
||||
struct clist_node *prev; ///< previous node
|
||||
struct clist_node *next; ///< next node
|
||||
void *val;
|
||||
} clist_node_t;
|
||||
|
||||
/**
|
||||
* @struct clist_t
|
||||
* @brief clist_t struct.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
clist_node_t *head; ///< first node
|
||||
clist_node_t *tail; ///< last node
|
||||
uint32_t len; ///< list length
|
||||
void (*free)(void *val); ///< node free function handle
|
||||
int8_t (*compare)(void *a, void *b); ///< node compare function handle
|
||||
} clist_t;
|
||||
|
||||
/**
|
||||
* @struct clist_iterator_t
|
||||
* @brief clist_t iterator struct.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
clist_node_t *next; ///< next element
|
||||
clist_direction_t direction; ///< iter direction
|
||||
} clist_iterator_t;
|
||||
|
||||
// Node prototypes.
|
||||
|
||||
clist_node_t *
|
||||
clist_node_new(void *val);
|
||||
|
||||
// clist_t prototypes.
|
||||
|
||||
clist_t *
|
||||
clist_new(void);
|
||||
|
||||
clist_node_t *
|
||||
clist_rpush(clist_t *self, clist_node_t *node);
|
||||
|
||||
clist_node_t *
|
||||
clist_lpush(clist_t *self, clist_node_t *node);
|
||||
|
||||
clist_node_t *
|
||||
clist_find(clist_t *self, void *val);
|
||||
|
||||
clist_node_t *
|
||||
clist_at(clist_t *self, int index);
|
||||
|
||||
clist_node_t *
|
||||
clist_rpop(clist_t *self);
|
||||
|
||||
clist_node_t *
|
||||
clist_lpop(clist_t *self);
|
||||
|
||||
void
|
||||
clist_remove(clist_t *self, clist_node_t *node);
|
||||
|
||||
void
|
||||
clist_clear(clist_t *self);
|
||||
|
||||
void
|
||||
clist_destroy(clist_t *self);
|
||||
|
||||
// clist_t iterator prototypes.
|
||||
|
||||
clist_iterator_t *
|
||||
clist_iterator_new(clist_t *list, clist_direction_t direction);
|
||||
|
||||
clist_iterator_t *
|
||||
clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction);
|
||||
|
||||
clist_node_t *
|
||||
clist_iterator_next(clist_iterator_t *self);
|
||||
|
||||
void
|
||||
clist_iterator_destroy(clist_iterator_t *self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CLIBS_LIST_H__ */
|
||||
|
||||
/** @} cList*/
|
||||
|
||||
/** @} Utility*/
|
||||
@@ -0,0 +1,93 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file common.h
|
||||
* @author FanHao (hao_fan_bit_ee@163.com)
|
||||
* @brief Common macros
|
||||
* @version 0.0
|
||||
* @date 2022-07-16
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @defgroup COMMON_MACRO
|
||||
* @{
|
||||
*/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#ifndef __COMMON_H_
|
||||
#define __COMMON_H_
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "error.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
#define __PRINT_BLOCK(block) \
|
||||
do \
|
||||
{ \
|
||||
block \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT(exp) ((exp) ? (void)0 : AppAssert(__FILE__, __LINE__))
|
||||
#define _nop_() __asm__("nop")
|
||||
|
||||
/* Stringify */
|
||||
#define STR(x) #x
|
||||
|
||||
// #define _DEBUG_LEVEL 3
|
||||
|
||||
#if _DEBUG_LEVEL > 0
|
||||
#define DBG_PRINT(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
#if _DEBUG_LEVEL >= 1
|
||||
#define DBG_ERROR(...) __PRINT_BLOCK( \
|
||||
printf("in "__FILE__ \
|
||||
":%d [error]\t", \
|
||||
__LINE__); \
|
||||
printf(__VA_ARGS__);)
|
||||
#endif
|
||||
#if _DEBUG_LEVEL >= 2
|
||||
#define DBG_WARNING(...) __PRINT_BLOCK( \
|
||||
printf("[warning]\t"); \
|
||||
printf(__VA_ARGS__);)
|
||||
#endif
|
||||
#if _DEBUG_LEVEL >= 3
|
||||
#define DBG_INFO(...) __PRINT_BLOCK( \
|
||||
printf("[Info]\t"); \
|
||||
printf(__VA_ARGS__);)
|
||||
#endif
|
||||
|
||||
#ifndef DBG_ERROR
|
||||
#define DBG_ERROR(...) \
|
||||
{ \
|
||||
}
|
||||
#endif
|
||||
#ifndef DBG_WARNING
|
||||
#define DBG_WARNING(...) \
|
||||
{ \
|
||||
}
|
||||
#endif
|
||||
#ifndef DBG_INFO
|
||||
#define DBG_INFO(...) \
|
||||
{ \
|
||||
}
|
||||
#endif
|
||||
#ifndef DBG_PRINT
|
||||
#define DBG_PRINT(...) \
|
||||
{ \
|
||||
}
|
||||
#endif
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
void AppAssert(const char *file, int line);
|
||||
#endif /* __COMMON_H_ */
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************//**
|
||||
* @file delay.h
|
||||
* @brief Header file of Delay functions
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _DELAY_H_
|
||||
#define _DELAY_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct time
|
||||
* @brief Structure holding time data (seconds, microseconds).
|
||||
*/
|
||||
struct time {
|
||||
unsigned int s, us;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Generate microseconds delay. */
|
||||
void udelay(uint32_t usecs);
|
||||
|
||||
/* Generate miliseconds delay. */
|
||||
void mdelay(uint32_t msecs);
|
||||
|
||||
/* Get current time */
|
||||
struct time get_time(void);
|
||||
|
||||
#endif // _DELAY_H_
|
||||
@@ -0,0 +1,56 @@
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file common.h
|
||||
* @author FanHao (hao_fan_bit_ee@163.com)
|
||||
* @brief Common error numbers
|
||||
* @version 0.0
|
||||
* @date 2022-06-18
|
||||
* @copyright Copyright(c) 2024 Beijing Institute of Technology.\n
|
||||
* Lab of Communication and Network
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @addtogroup COMMON_MACRO
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef SRC_ERROR_H_
|
||||
#define SRC_ERROR_H_
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @name ERRORNO
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef SUCCESS
|
||||
#undef SUCCESS
|
||||
#endif
|
||||
#define SUCCESS 0
|
||||
#ifdef FAILURE
|
||||
#undef FAILURE
|
||||
#endif
|
||||
#define FAILURE -1
|
||||
|
||||
#define EPARAM -2 /*!< Data crc check failed */
|
||||
#define ECRC -3 /*!< Data crc check failed */
|
||||
#define EDINVAL -4 /*!< Device is invalid (sleep or power off) */
|
||||
#define EDCONF -5 /*!< Device confugure error */
|
||||
#define ETIMEOUT -6 /*!< Timeout error */
|
||||
#define EIGNORE -7 /*!< Received an unsupported command, and ignore it */
|
||||
#define EQUEUE -8 /*!< Queue overflow */
|
||||
#define EUNEXP -9 /*!< Encounter an unexpected error */
|
||||
|
||||
#define IS_ERR_VALUE(x) ((x) != SUCCESS)
|
||||
|
||||
#endif // ERROR_H_
|
||||
|
||||
/** @} ERRORNO*/
|
||||
|
||||
/** @} COMMON_MACRO*/
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifndef SRC_GLOBAL_TIMER_H_
|
||||
#define SRC_GLOBAL_TIMER_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @struct timer_init_param
|
||||
* @brief Structure holding the parameters for timer initialization
|
||||
*/
|
||||
struct global_timer_init_param {
|
||||
/** timer ID */
|
||||
uintptr_t base_addr;
|
||||
/** timer ID */
|
||||
uint16_t id;
|
||||
/** timer count frequency (Hz) */
|
||||
uint32_t freq_hz;
|
||||
/** counter start value */
|
||||
uint64_t load_value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct timer_desc
|
||||
* @brief Structure holding timer descriptor
|
||||
*/
|
||||
struct global_timer_desc {
|
||||
/** timer ID */
|
||||
uintptr_t base_addr;
|
||||
/** timer ID */
|
||||
uint16_t id;
|
||||
/** timer count frequency (Hz) */
|
||||
uint32_t freq_hz;
|
||||
/** counter start value */
|
||||
uint64_t load_value;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Initialize hardware timer and the handler structure associated with it. */
|
||||
int32_t global_timer_init(struct global_timer_desc **desc,
|
||||
struct global_timer_init_param *param);
|
||||
|
||||
/* Free the memory allocated by timer_setup(). */
|
||||
int32_t global_timer_remove(struct global_timer_desc *desc);
|
||||
|
||||
/* Start a timer. */
|
||||
int32_t global_timer_start(struct global_timer_desc *desc);
|
||||
|
||||
/* Stop a timer from counting. */
|
||||
int32_t global_timer_stop(struct global_timer_desc *desc);
|
||||
|
||||
/* Get the value of the counter register for the timer. */
|
||||
int32_t global_timer_counter_get(struct global_timer_desc *desc, uint64_t *counter);
|
||||
|
||||
/* Set the timer counter register value. */
|
||||
int32_t global_timer_counter_set(struct global_timer_desc *desc, uint64_t new_val);
|
||||
|
||||
/* Get the timer clock frequency. */
|
||||
int32_t global_timer_count_clk_get(struct global_timer_desc *desc, uint32_t *freq_hz);
|
||||
|
||||
/* Set the timer clock frequency. */
|
||||
int32_t global_timer_count_clk_set(struct global_timer_desc *desc, uint32_t freq_hz);
|
||||
|
||||
/* Enable global timer interrupt. */
|
||||
int32_t global_timer_irq_enable(struct global_timer_desc *desc);
|
||||
|
||||
/* Disable global timer interrupt. */
|
||||
int32_t global_timer_irq_disable(struct global_timer_desc *desc);
|
||||
|
||||
/* Implement a acknowledgment global timer interrupt. */
|
||||
int32_t global_timer_irq_ack(struct global_timer_desc *desc);
|
||||
|
||||
/* Set comparator register. */
|
||||
int32_t global_timer_compara_set(struct global_timer_desc *desc, uint64_t com_val);
|
||||
|
||||
/* Set auto increment register . */
|
||||
int32_t global_timer_auto_inc_set(struct global_timer_desc *desc, uint32_t inc_val);
|
||||
|
||||
/* Enable global timer auto increment mode. */
|
||||
int32_t global_timer_auto_inc_enable(struct global_timer_desc *desc);
|
||||
|
||||
/* Disable global timer auto increment mode. */
|
||||
int32_t global_timer_auto_inc_disable(struct global_timer_desc *desc);
|
||||
|
||||
#endif /* SRC_TIMER_H_ */
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/***************************************************************************//**
|
||||
* @file gpio.h
|
||||
* @brief Header file of GPIO Interface
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define GPIO_OUT 0x01
|
||||
#define GPIO_IN 0x00
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @struct gpio_platform_ops
|
||||
* @brief Structure holding gpio function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct gpio_platform_ops ;
|
||||
|
||||
/**
|
||||
* @enum gpio_pull_up
|
||||
* @brief Enum that holds the possible pull up/ pull down resistor configuration.
|
||||
*/
|
||||
enum gpio_pull_up {
|
||||
PULL_NONE,
|
||||
/** Strong pull up */
|
||||
PULL_UP,
|
||||
/** Strong pull down */
|
||||
PULL_DOWN,
|
||||
PULL_UP_WEAK,
|
||||
PULL_DOWN_WEAK
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct gpio_init_param
|
||||
* @brief Structure holding the parameters for GPIO initialization.
|
||||
*/
|
||||
struct gpio_init_param {
|
||||
/** Port number */
|
||||
int32_t port;
|
||||
/** GPIO number */
|
||||
int32_t number;
|
||||
/** Pull up/down resistor configuration */
|
||||
enum gpio_pull_up pull;
|
||||
/** GPIO platform specific functions */
|
||||
const struct gpio_platform_ops *platform_ops;
|
||||
/** GPIO extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct gpio_desc
|
||||
* @brief Structure holding the GPIO descriptor.
|
||||
*/
|
||||
struct gpio_desc {
|
||||
/** Port number */
|
||||
int32_t port;
|
||||
/** GPIO number */
|
||||
int32_t number;
|
||||
/** Pull up/down resistor configuration */
|
||||
enum gpio_pull_up pull;
|
||||
/** GPIO platform specific functions */
|
||||
const struct gpio_platform_ops *platform_ops;
|
||||
/** GPIO extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum gpio_values
|
||||
* @brief Enum that holds the possible output states of a GPIO.
|
||||
*/
|
||||
enum gpio_values {
|
||||
/** GPIO logic low */
|
||||
GPIO_LOW,
|
||||
/** GPIO logic high */
|
||||
GPIO_HIGH,
|
||||
/** GPIO high impedance */
|
||||
GPIO_HIGH_Z
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct gpio_platform_ops
|
||||
* @brief Structure holding gpio function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct gpio_platform_ops {
|
||||
/** gpio initialization function pointer */
|
||||
int32_t (*gpio_ops_get)(struct gpio_desc **,
|
||||
const struct gpio_init_param *);
|
||||
/** gpio optional descriptor function pointer */
|
||||
int32_t (*gpio_ops_get_optional)(struct gpio_desc **,
|
||||
const struct gpio_init_param *);
|
||||
/** gpio remove function pointer */
|
||||
int32_t (*gpio_ops_remove)(struct gpio_desc *);
|
||||
/** gpio direction input function pointer */
|
||||
int32_t (*gpio_ops_direction_input)(struct gpio_desc *);
|
||||
/** gpio direction output function pointer */
|
||||
int32_t (*gpio_ops_direction_output)(struct gpio_desc *, uint8_t);
|
||||
/** gpio get direction function pointer */
|
||||
int32_t (*gpio_ops_get_direction)(struct gpio_desc *, uint8_t *);
|
||||
/** gpio set value function pointer */
|
||||
int32_t (*gpio_ops_set_value)(struct gpio_desc *, uint8_t);
|
||||
/** gpio get value function pointer */
|
||||
int32_t (*gpio_ops_get_value)(struct gpio_desc *, uint8_t *);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Obtain the GPIO decriptor. */
|
||||
int32_t gpio_get(struct gpio_desc **desc,
|
||||
const struct gpio_init_param *param);
|
||||
|
||||
/* Obtain optional GPIO descriptor. */
|
||||
int32_t gpio_get_optional(struct gpio_desc **desc,
|
||||
const struct gpio_init_param *param);
|
||||
|
||||
/* Free the resources allocated by gpio_get(). */
|
||||
int32_t gpio_remove(struct gpio_desc *desc);
|
||||
|
||||
/* Enable the input direction of the specified GPIO. */
|
||||
int32_t gpio_direction_input(struct gpio_desc *desc);
|
||||
|
||||
/* Enable the output direction of the specified GPIO. */
|
||||
int32_t gpio_direction_output(struct gpio_desc *desc,
|
||||
uint8_t value);
|
||||
|
||||
/* Get the direction of the specified GPIO. */
|
||||
int32_t gpio_get_direction(struct gpio_desc *desc,
|
||||
uint8_t *direction);
|
||||
|
||||
/* Set the value of the specified GPIO. */
|
||||
int32_t gpio_set_value(struct gpio_desc *desc,
|
||||
uint8_t value);
|
||||
|
||||
/* Get the value of the specified GPIO. */
|
||||
int32_t gpio_get_value(struct gpio_desc *desc,
|
||||
uint8_t *value);
|
||||
|
||||
#endif // _GPIO_H_
|
||||
@@ -0,0 +1,134 @@
|
||||
/***************************************************************************//**
|
||||
* @file i2c.h
|
||||
* @brief Header file of I2C Interface
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _I2C_H_
|
||||
#define _I2C_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @struct i2c_platform_ops
|
||||
* @brief Structure holding I2C function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct i2c_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct i2c_init_param
|
||||
* @brief Structure holding the parameters for I2C initialization.
|
||||
*/
|
||||
struct i2c_init_param {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** I2C maximum transfer speed supported */
|
||||
uint32_t max_speed_hz;
|
||||
/** Slave address */
|
||||
uint8_t slave_address;
|
||||
/** I2C platform specific functions */
|
||||
const struct i2c_platform_ops *platform_ops;
|
||||
/** I2C extra parameters (device specific parameters) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct i2c_desc
|
||||
* @brief Structure holding I2C descriptor
|
||||
*/
|
||||
struct i2c_desc {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** I2C maximum transfer speed supported */
|
||||
uint32_t max_speed_hz;
|
||||
/** Slave address */
|
||||
uint8_t slave_address;
|
||||
/** I2C platform specific functions */
|
||||
const struct i2c_platform_ops *platform_ops;
|
||||
/** I2C extra parameters (device specific parameters) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct i2c_platform_ops
|
||||
* @brief Structure holding i2c function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct i2c_platform_ops {
|
||||
/** i2c initialization function pointer */
|
||||
int32_t (*i2c_ops_init)(struct i2c_desc **,
|
||||
const struct i2c_init_param *);
|
||||
/** i2c write function pointer */
|
||||
int32_t (*i2c_ops_write)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t);
|
||||
/** i2c write function pointer */
|
||||
int32_t (*i2c_ops_read)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t);
|
||||
/** i2c remove function pointer */
|
||||
int32_t (*i2c_ops_remove)(struct i2c_desc *);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Initialize the I2C communication peripheral. */
|
||||
int32_t i2c_init(struct i2c_desc **desc,
|
||||
const struct i2c_init_param *param);
|
||||
|
||||
/* Free the resources allocated by i2c_init(). */
|
||||
int32_t i2c_remove(struct i2c_desc *desc);
|
||||
|
||||
/* Write data to a slave device. */
|
||||
int32_t i2c_write(struct i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit);
|
||||
|
||||
/* Read data from a slave device. */
|
||||
int32_t i2c_read(struct i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit);
|
||||
|
||||
#endif // _I2C_H_
|
||||
@@ -0,0 +1,235 @@
|
||||
/***************************************************************************//**
|
||||
* @file irq.h
|
||||
* @brief Header file of IRQ interface.
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _IRQ_H_
|
||||
#define _IRQ_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @enum irq_uart_event_e
|
||||
* @brief Possible events for uart interrupt
|
||||
* @todo replace this with enum irq_event
|
||||
*/
|
||||
enum irq_uart_event_e {
|
||||
/** Write operation finalized */
|
||||
IRQ_WRITE_DONE,
|
||||
/** Read operation finalized */
|
||||
IRQ_READ_DONE,
|
||||
/** An error occurred */
|
||||
IRQ_ERROR
|
||||
};
|
||||
|
||||
enum irq_event {
|
||||
EVT_GPIO,
|
||||
EVT_UART_TX_COMPLETE,
|
||||
EVT_UART_RX_COMPLETE,
|
||||
EVT_UART_ERROR,
|
||||
EVT_RTC,
|
||||
EVT_XINT,
|
||||
EVT_TIM_ELAPSED
|
||||
};
|
||||
|
||||
enum irq_trig_level {
|
||||
IRQ_LEVEL_LOW,
|
||||
IRQ_LEVEL_HIGH,
|
||||
IRQ_EDGE_FALLING,
|
||||
IRQ_EDGE_RISING,
|
||||
IRQ_EDGE_BOTH
|
||||
};
|
||||
|
||||
enum irq_peripheral {
|
||||
GPIO_IRQ,
|
||||
UART_IRQ,
|
||||
RTC_IRQ,
|
||||
TIM_IRQ
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct irq_platform_ops
|
||||
* @brief Structure holding IRQ function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct irq_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct irq_init_param
|
||||
* @brief Structure holding the initial parameters for Interrupt Request.
|
||||
*/
|
||||
struct irq_init_param {
|
||||
/** Interrupt request controller ID. */
|
||||
uint32_t irq_ctrl_id;
|
||||
/** Platform specific IRQ platform ops structure. */
|
||||
const struct irq_platform_ops *platform_ops;
|
||||
/**
|
||||
* This is intended to store irq controller specific configurations,
|
||||
* it should not be a reference to any peripheral descriptor.
|
||||
*/
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct irq_desc
|
||||
* @brief Structure for Interrupt Request descriptor.
|
||||
*/
|
||||
struct irq_ctrl_desc {
|
||||
/** Interrupt request controller ID. */
|
||||
uint32_t irq_ctrl_id;
|
||||
/** Platform specific IRQ platform ops structure. */
|
||||
const struct irq_platform_ops *platform_ops;
|
||||
/**
|
||||
* This is intended to store irq controller specific configurations,
|
||||
* it should not be a reference to any peripheral descriptor.
|
||||
*/
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct callback_desc
|
||||
* @brief Structure describing a callback to be registered
|
||||
* @todo: remove this, use struct irq_callback instead.
|
||||
*/
|
||||
struct callback_desc {
|
||||
/** Callback to be called when the event an event occurs. */
|
||||
void (*callback)(void *context);
|
||||
/**
|
||||
* Callback to be called when the event an event occurs
|
||||
* @param ctx - Same as \ref callback_desc.ctx
|
||||
* @param event - Event that generated the callback
|
||||
* @param extra - Platform specific data
|
||||
*/
|
||||
void (*legacy_callback)(void *ctx, uint32_t event,
|
||||
void *extra); /* TODO: remove this. */
|
||||
/** Parameter to be passed when the callback is called */
|
||||
void *ctx;
|
||||
/** Platform specific configuration for a callback */
|
||||
void *legacy_config; /* TODO: remove this. */
|
||||
/** Platform specific event that triggers the calling of the callback. */
|
||||
enum irq_event event;
|
||||
/** Interrupt source peripheral specifier. */
|
||||
enum irq_peripheral peripheral;
|
||||
/** This will be used to store HAL specific descriptors */
|
||||
void *handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct irq_platform_ops
|
||||
* @brief Structure holding IRQ function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct irq_platform_ops {
|
||||
/** Initialize a interrupt controller peripheral. */
|
||||
int32_t (*init)(struct irq_ctrl_desc **desc,
|
||||
const struct irq_init_param *param);
|
||||
/** Register a legacy_callback to handle the irq events */
|
||||
int32_t (*register_callback)(struct irq_ctrl_desc *desc, uint32_t irq_id,
|
||||
struct callback_desc *callback);
|
||||
/** Unregisters a generic IRQ handling function */
|
||||
int32_t (*unregister_callback)(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct callback_desc *callback);
|
||||
/** Global interrupt enable */
|
||||
int32_t (*global_enable)(struct irq_ctrl_desc *desc);
|
||||
/** Global interrupt disable */
|
||||
int32_t (*global_disable)(struct irq_ctrl_desc *desc);
|
||||
/** Set interrupt trigger level. */
|
||||
int32_t (*trigger_level_set)(struct irq_ctrl_desc *desc, uint32_t irq_id,
|
||||
enum irq_trig_level trig);
|
||||
/** Enable specific interrupt */
|
||||
int32_t (*enable)(struct irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
/** Disable specific interrupt */
|
||||
int32_t (*disable)(struct irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
/** Set the priority level for a specific interrupt */
|
||||
int32_t (*set_priority)(struct irq_ctrl_desc *desc, uint32_t irq_id,
|
||||
uint32_t priority_level);
|
||||
/** IRQ remove function pointer */
|
||||
int32_t (*remove)(struct irq_ctrl_desc *desc);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Initialize a interrupt controller peripheral. */
|
||||
int32_t irq_ctrl_init(struct irq_ctrl_desc **desc,
|
||||
const struct irq_init_param *param);
|
||||
|
||||
/* Free the resources allocated by irq_ctrl_init(). */
|
||||
int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc);
|
||||
|
||||
/* Register a callback to handle the irq events */
|
||||
int32_t irq_register_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct callback_desc *callback_desc);
|
||||
|
||||
/* Unregisters a generic IRQ handling function */
|
||||
int32_t irq_unregister_callback(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct callback_desc *callback_desc);
|
||||
|
||||
/* Global interrupt enable */
|
||||
int32_t irq_global_enable(struct irq_ctrl_desc *desc);
|
||||
|
||||
/* Global interrupt disable */
|
||||
int32_t irq_global_disable(struct irq_ctrl_desc *desc);
|
||||
|
||||
/* Set interrupt trigger level. */
|
||||
int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
enum irq_trig_level trig);
|
||||
|
||||
/* Enable specific interrupt */
|
||||
int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
|
||||
/* Disable specific interrupt */
|
||||
int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
|
||||
/** Set the priority level for a specific interrupt */
|
||||
int32_t irq_set_priority(struct irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
uint32_t priority_level);
|
||||
#endif // _IRQ_H_
|
||||
@@ -0,0 +1,327 @@
|
||||
/***************************************************************************//**
|
||||
* @file list.h
|
||||
* @brief List library header
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* @copyright
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
********************************************************************************
|
||||
*
|
||||
* @section list_details Library description
|
||||
* This library handles double linked lists and it expose inseart,
|
||||
* read, get and delete functions. \n
|
||||
* It also can be accesed using it member functions which wrapp function for
|
||||
* usual list types.\n
|
||||
* @subsection example Sample code
|
||||
* @code{.c}
|
||||
* // -- Use a generic list
|
||||
* struct list_desc *list1;
|
||||
* struct iterator *it;
|
||||
* uint32_t a;
|
||||
* // Create list list1
|
||||
* list_init(&list1, LIST_DEFAULT, NULL);
|
||||
* // Add items to the list
|
||||
* list_add_last(list1, 1);
|
||||
* list_add_last(list1, 2);
|
||||
* list_add_last(list1, 3);
|
||||
* // Here the list will be: 1 -> 2 - > 3
|
||||
*
|
||||
* list_read_last(list1, &a);
|
||||
* printf("Last: %d\n", a);
|
||||
* // 3 will be printed
|
||||
* // Create an iterator on the end of the list
|
||||
* iterator_init(&it, list1, 0);
|
||||
* // Move the iterator backword with one position
|
||||
* iterator_move(it, -1);
|
||||
* // Read the data at the current position
|
||||
* iterator_read(it, &a);
|
||||
* printf("Current: %d\n", a);
|
||||
* // 2 will be printed
|
||||
* iterator_remove(it);
|
||||
* list_remove(list1);
|
||||
*
|
||||
* // -- Use a popular list
|
||||
* struct list_desc *stack;
|
||||
* // Create a FIFO list
|
||||
* list_init(&stack, LIST_STACK, NULL);
|
||||
* // Put elements in the list
|
||||
* stack->push(stack, 1);
|
||||
* stack->push(stack, 2);
|
||||
* stack->push(stack, 3);
|
||||
* // Read from the stack
|
||||
* stack->pop(stack, &a);
|
||||
* printf("Last: %d\n", a);
|
||||
* // 3 will be printed
|
||||
* list_remove(stack);
|
||||
* @endcode
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LIST_H_
|
||||
#define _LIST_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @struct list_desc
|
||||
* @brief Structure storing the list and function wrapper for usual list types
|
||||
*
|
||||
* With this structure the funtionalities of usual list types
|
||||
* ( \ref adapter_type ) can be accesed with the functions referenced in this
|
||||
* structure.
|
||||
* For example:
|
||||
* @code{.c}
|
||||
* my_queue->push(my_queue, my_data);
|
||||
* @endcode
|
||||
*/
|
||||
struct list_desc;
|
||||
|
||||
/**
|
||||
* @struct list_iterator
|
||||
* @brief Structure used to iterate through the list using Iterator functions.
|
||||
*/
|
||||
struct iterator;
|
||||
|
||||
/**
|
||||
* @brief Prototype of the compare function.
|
||||
*
|
||||
* The function used to compare the elements of the liste when doing
|
||||
* operations on an ordered list.
|
||||
* @param data1 - First element to be compared
|
||||
* @param data2 - Second element to be compared
|
||||
* @return
|
||||
* - -1 - If data1 < data2
|
||||
* - 0 - If data1 == data2
|
||||
* - 1 - If data1 > data2
|
||||
*/
|
||||
typedef int32_t (*f_cmp)(void *data1, void *data2);
|
||||
|
||||
/**
|
||||
* @name Generic functions
|
||||
* Each function interacting with the list have one of the following formats.\n
|
||||
* Aditionaly they may have one more parametere for specific functionalities.\n
|
||||
* In the Iterator functions, the list reference is replaced by the iterator's
|
||||
* one.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Add an element in the list.
|
||||
*
|
||||
* The element of the list is created and the data field is stored in it.
|
||||
* @param list_desc - Reference to the list. Created by \ref list_init.
|
||||
* @param data - Data to store in a list element
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
typedef int32_t (*f_add)(struct list_desc *list_desc, void *data);
|
||||
|
||||
/**
|
||||
* @brief Edit an element in the list. The content is replaced by new_data.
|
||||
* @param list_desc - Reference to the list. Created by \ref list_init.
|
||||
* @param new_data - New data to replace the old one
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
typedef int32_t (*f_edit)(struct list_desc *list_desc, void *new_data);
|
||||
|
||||
/**
|
||||
* @brief Read an element from the list.
|
||||
* @param list_desc - Reference to the list. Created by \ref list_init.
|
||||
* @param result - If not null, result is filled with:
|
||||
* @param data - Content of the list element, NULL if some error occur.
|
||||
* @return \n
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
* @note If the content of an element can be 0 then the result must be checked
|
||||
* to see if the functions has succeded
|
||||
*/
|
||||
typedef int32_t (*f_read)(struct list_desc *list_desc, void **data);
|
||||
|
||||
/**
|
||||
* @brief Read and remove an element from the list.
|
||||
* @param list_desc - Reference to the list. Created by \ref list_init.
|
||||
* @param result - If not null, result is filled with:
|
||||
* @param data - Content of the list element, NULL if some error occur.
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
typedef int32_t (*f_get)(struct list_desc *list_desc, void **data);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @enum adapter_type
|
||||
* @brief Selects functionalities for functions in \ref list_desc
|
||||
*/
|
||||
enum adapter_type {
|
||||
/** Default type is LIST_STACK */
|
||||
LIST_DEFAULT,
|
||||
/**
|
||||
* Functions for a FIFO list (First-in first-out). Elements are inserted
|
||||
* in one end and extracted from the other end.
|
||||
* - \e Push: Insert element
|
||||
* - \e Pop: Get next element (Read and remove)
|
||||
* - \e Top_next: Read next element
|
||||
* - \e Back: Read first element
|
||||
* - \e Swap: Edit the content of the next element
|
||||
*/
|
||||
LIST_QUEUE,
|
||||
/**
|
||||
* Functions for a LIFO list (Last-in first-out). Elements are inserted
|
||||
* and extracted only from the same end.
|
||||
* - \e Push: Insert element
|
||||
* - \e Pop: Get top element (Read and remove)
|
||||
* - \e Top_next: Read top element
|
||||
* - \e Back: Read bottom element
|
||||
* - \e Swap: Edit the content of the top element
|
||||
*/
|
||||
LIST_STACK,
|
||||
/**
|
||||
* Functions for ordered list. The order of element is determinated
|
||||
* usinge the \ref f_cmp.
|
||||
* - \e Push: Insert element
|
||||
* - \e Pop: Get lowest element (Read and remove)
|
||||
* - \e Top_next: Read lowest element
|
||||
* - \e Back: Read the biggest element
|
||||
* - \e Swap: Edit the lowest element
|
||||
*/
|
||||
LIST_PRIORITY_LIST
|
||||
};
|
||||
|
||||
struct list_desc {
|
||||
/** Refer to \ref adapter_type */
|
||||
f_add push;
|
||||
/** Refer to \ref adapter_type */
|
||||
f_get pop;
|
||||
/** Refer to \ref adapter_type */
|
||||
f_read top_next;
|
||||
/** Refer to \ref adapter_type */
|
||||
f_read back;
|
||||
/** Refer to \ref adapter_type */
|
||||
f_edit swap;
|
||||
/** Structure storing the list internal parameters */
|
||||
void *priv_desc;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
int32_t list_init(struct list_desc **list_desc,
|
||||
enum adapter_type type,
|
||||
f_cmp comparator);
|
||||
int32_t list_remove(struct list_desc *list_desc);
|
||||
int32_t list_get_size(struct list_desc *list_desc,
|
||||
uint32_t *out_size);
|
||||
|
||||
/**
|
||||
* @name Iterator functions
|
||||
* An iterator is used to iterate through the list. For a list, any number of
|
||||
* iterators can be created. All must be removed before removing a list.
|
||||
* @{
|
||||
*/
|
||||
int32_t iterator_init(struct iterator **iter,
|
||||
struct list_desc *list_desc,
|
||||
bool start);
|
||||
int32_t iterator_remove(struct iterator *iter);
|
||||
int32_t iterator_move(struct iterator *iter, int32_t steps);
|
||||
int32_t iterator_move_to_idx(struct iterator *iter, int32_t idx);
|
||||
int32_t iterator_find(struct iterator *iter, void *cmp_data);
|
||||
int32_t iterator_insert(struct iterator *iter, void *data,
|
||||
bool after);
|
||||
int32_t iterator_edit(struct iterator *iter, void *new_data);
|
||||
int32_t iterator_read(struct iterator *iter, void **data);
|
||||
int32_t iterator_get(struct iterator *iter, void **data);
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @name Operations on the ends of the list
|
||||
* These functions will operate on the first or last element of the list
|
||||
* @{
|
||||
*/
|
||||
int32_t list_add_first(struct list_desc *list_desc, void *data);
|
||||
int32_t list_edit_first(struct list_desc *list_desc,
|
||||
void *new_data);
|
||||
int32_t list_read_first(struct list_desc *list_desc, void **data);
|
||||
int32_t list_get_first(struct list_desc *list_desc, void **data);
|
||||
|
||||
int32_t list_add_last(struct list_desc *list_desc, void *data);
|
||||
int32_t list_edit_last(struct list_desc *list_desc, void *new_data);
|
||||
int32_t list_read_last(struct list_desc *list_desc, void **data);
|
||||
int32_t list_get_last(struct list_desc *list_desc, void **data);
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @name Operations by index
|
||||
* These functions use an index to identify the element in the list.
|
||||
* @{
|
||||
*/
|
||||
int32_t list_add_idx(struct list_desc *list_desc, void *data,
|
||||
uint32_t idx);
|
||||
int32_t list_edit_idx(struct list_desc *list_desc, void *new_data,
|
||||
uint32_t idx);
|
||||
int32_t list_read_idx(struct list_desc *list_desc, void **data,
|
||||
uint32_t idx);
|
||||
int32_t list_get_idx(struct list_desc *list_desc, void **data,
|
||||
uint32_t idx);
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @name Operations by comparation
|
||||
* These functions use the specified \ref f_cmp at \ref list_init to identify
|
||||
* the element this will operate on.
|
||||
* @{
|
||||
*/
|
||||
int32_t list_add_find(struct list_desc *list_desc, void *data);
|
||||
int32_t list_edit_find(struct list_desc *list_desc, void *new_data,
|
||||
void *cmp_data);
|
||||
int32_t list_read_find(struct list_desc *list_desc, void **data,
|
||||
void *cmp_data);
|
||||
int32_t list_get_find(struct list_desc *list_desc, void **data,
|
||||
void *cmp_data);
|
||||
/** @}*/
|
||||
|
||||
#endif // _LIST_H_
|
||||
@@ -0,0 +1,209 @@
|
||||
/***************************************************************************//**
|
||||
* @file spi.h
|
||||
* @brief Header file of SPI Interface
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _SPI_H_
|
||||
#define _SPI_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/******************************************************************************/
|
||||
/********************** Macros and Constants Definitions **********************/
|
||||
/******************************************************************************/
|
||||
|
||||
#define SPI_CPHA 0x01
|
||||
#define SPI_CPOL 0x02
|
||||
#define SPI_3WIRE 0x04
|
||||
|
||||
/******************************************************************************/
|
||||
/*************************** Types Declarations *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/**
|
||||
* @enum spi_mode
|
||||
* @brief SPI configuration for clock phase and polarity.
|
||||
*/
|
||||
enum spi_mode {
|
||||
/** Data on rising, shift out on falling */
|
||||
SPI_MODE_0 = (0 | 0),
|
||||
/** Data on falling, shift out on rising */
|
||||
SPI_MODE_1 = (0 | SPI_CPHA),
|
||||
/** Data on rising, shift out on falling */
|
||||
SPI_MODE_2 = (SPI_CPOL | 0),
|
||||
/** Data on falling, shift out on rising */
|
||||
SPI_MODE_3 = (SPI_CPOL | SPI_CPHA),
|
||||
/** Data on rising, shift out on falling */
|
||||
SPI_MODE_4 = SPI_3WIRE
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum spi_bit_order
|
||||
* @brief SPI configuration for bit order (MSB/LSB).
|
||||
*/
|
||||
enum spi_bit_order {
|
||||
/** Most-significant bit (MSB) first */
|
||||
SPI_BIT_ORDER_MSB_FIRST = 0,
|
||||
/** Least-significant bit (LSB) first */
|
||||
SPI_BIT_ORDER_LSB_FIRST = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct spi_msg_list
|
||||
* @brief List item describing a SPI transfer
|
||||
*/
|
||||
struct spi_msg {
|
||||
/** Buffer with data to send. If NULL, 0x00 will be sent */
|
||||
uint8_t *tx_buff;
|
||||
/** Buffer where to store data. If NULL, incoming data won't be saved */
|
||||
uint8_t *rx_buff;
|
||||
/** Length of buffers. Must have equal size. */
|
||||
uint32_t bytes_number;
|
||||
/** If set, CS will be deasserted after the transfer */
|
||||
uint8_t cs_change;
|
||||
/**
|
||||
* Minimum delay (in us) between the CS de-assert event of the current message
|
||||
* and the assert of the next one.
|
||||
*/
|
||||
uint32_t cs_change_delay;
|
||||
/** Delay (in us) between the CS assert and the first SCLK edge. */
|
||||
uint32_t cs_delay_first;
|
||||
/** Delay (in us) between the last SCLK edge and the CS deassert */
|
||||
uint32_t cs_delay_last;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct spi_platform_ops
|
||||
* @brief Structure holding SPI function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct spi_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct spi_init_param
|
||||
* @brief Structure holding the parameters for SPI initialization
|
||||
*/
|
||||
struct spi_init_param {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** maximum transfer speed */
|
||||
uint32_t max_speed_hz;
|
||||
/** SPI chip select */
|
||||
uint8_t chip_select;
|
||||
/** SPI mode */
|
||||
enum spi_mode mode;
|
||||
/** SPI bit order */
|
||||
enum spi_bit_order bit_order;
|
||||
const struct spi_platform_ops *platform_ops;
|
||||
/** SPI extra parameters (device specific) */
|
||||
void *extra;
|
||||
/** Parent of the device */
|
||||
struct spi_desc *parent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct spi_desc
|
||||
* @brief Structure holding SPI descriptor.
|
||||
*/
|
||||
struct spi_desc {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** maximum transfer speed */
|
||||
uint32_t max_speed_hz;
|
||||
/** SPI chip select */
|
||||
uint8_t chip_select;
|
||||
/** SPI mode */
|
||||
enum spi_mode mode;
|
||||
/** SPI bit order */
|
||||
enum spi_bit_order bit_order;
|
||||
const struct spi_platform_ops *platform_ops;
|
||||
/** SPI extra parameters (device specific) */
|
||||
void *extra;
|
||||
/** Parent of the device */
|
||||
struct spi_desc *parent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct spi_platform_ops
|
||||
* @brief Structure holding SPI function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct spi_platform_ops {
|
||||
/** SPI initialization function pointer */
|
||||
int32_t (*init)(struct spi_desc **, const struct spi_init_param *);
|
||||
/** SPI write/read function pointer */
|
||||
int32_t (*write_and_read)(struct spi_desc *, uint8_t *, uint16_t);
|
||||
/** SPI write function pointer */
|
||||
int32_t (*write_and_read_3wire)(struct spi_desc *, uint8_t *,uint8_t *,uint16_t, uint16_t);
|
||||
/** Iterate over the spi_msg array and send all messages at once */
|
||||
int32_t (*transfer)(struct spi_desc *, struct spi_msg *, uint32_t);
|
||||
/** SPI remove function pointer */
|
||||
int32_t (*remove)(struct spi_desc *);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************ Functions Declarations ******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* Initialize the SPI communication peripheral. */
|
||||
int32_t spi_init(struct spi_desc **desc,
|
||||
const struct spi_init_param *param);
|
||||
|
||||
/* Free the resources allocated by spi_init(). */
|
||||
int32_t spi_remove(struct spi_desc *desc);
|
||||
|
||||
/* Write and read data to/from SPI. */
|
||||
int32_t spi_write_and_read(struct spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number);
|
||||
int32_t spi_write_and_read_3wire(struct spi_desc *desc,
|
||||
uint8_t *write_data,
|
||||
uint8_t *read_data,
|
||||
uint16_t write_bytes_number,
|
||||
uint16_t read_bytes_number);
|
||||
|
||||
/* Iterate over the spi_msg array and send all messages at once */
|
||||
int32_t spi_transfer(struct spi_desc *desc,
|
||||
struct spi_msg *msgs,
|
||||
uint32_t len);
|
||||
|
||||
|
||||
#endif // _SPI_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user