diff --git a/LICENSES/GPL-2.0-only.txt b/LICENSES/GPL-2.0-only.txt new file mode 100644 index 000000000..17cb28643 --- /dev/null +++ b/LICENSES/GPL-2.0-only.txt @@ -0,0 +1,117 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +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 convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice diff --git a/LICENSES/GPL-2.0-or-later.txt b/LICENSES/GPL-2.0-or-later.txt new file mode 100644 index 000000000..17cb28643 --- /dev/null +++ b/LICENSES/GPL-2.0-or-later.txt @@ -0,0 +1,117 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +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 convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice diff --git a/build.zig b/build.zig index 3ff102735..04056f24d 100644 --- a/build.zig +++ b/build.zig @@ -26,6 +26,11 @@ const DriverClass = struct { virtio }; + const Clock = enum { + meson, + imx, + }; + const I2cHost = enum { meson, }; @@ -202,6 +207,60 @@ fn addBlockDriver( return driver; } +fn addClockDriver( + b: *std.Build, + clk_config_include: LazyPath, + util: *std.Build.Step.Compile, + class: DriverClass.Clock, + target: std.Build.ResolvedTarget, + optimize: std.builtin.OptimizeMode, +) *std.Build.Step.Compile { + const driver = addPd(b, .{ + .name = b.fmt("driver_clk_{s}.elf", .{@tagName(class)}), + .target = target, + .optimize = optimize, + .strip = false, + }); + + switch (class) { + .meson => { + const files: []const []const u8 = &.{ + "drivers/clk/meson/clk-meson.c", + "drivers/clk/meson/clk-measure.c", + "drivers/clk/meson/sm1-clk.c", + }; + driver.addCSourceFiles(.{ .files = files }); + }, + .imx => { + const files: []const []const u8 = &.{ + "drivers/clk/imx/clk-imx.c", + "drivers/clk/imx/clk-imx8mq.c", + }; + driver.addCSourceFiles(.{ .files = files }); + }, + } + + const common_src_files = .{ + "clk-operations.c", + "clk.c", + }; + + inline for (common_src_files) |f| { + driver.addCSourceFile(.{ + .file = b.path(b.fmt("drivers/clk/{s}", .{ f })) + }); + } + + driver.defineCMacro(b.fmt("BOARD_CLASS_{s}", .{ @tagName(class) }), "1"); + driver.addIncludePath(clk_config_include); + driver.addIncludePath(b.path("include")); + driver.addIncludePath(b.path("drivers/clk")); + driver.addIncludePath(b.path(b.fmt("drivers/clk/{s}/include", .{@tagName(class)}))); + driver.linkLibrary(util); + + return driver; +} + fn addMmcDriver( b: *std.Build, blk_config_include: LazyPath, @@ -301,6 +360,8 @@ pub fn build(b: *std.Build) void { const net_config_include_option = b.option([]const u8, "net_config_include", "Include path to network config header") orelse ""; const i2c_client_include_option = b.option([]const u8, "i2c_client_include", "Include path to client config header") orelse ""; const gpu_config_include_option = b.option([]const u8, "gpu_config_include", "Include path to gpu config header") orelse ""; + const clk_conf_include_option = b.option([]const u8, "clk_conf_include", "Include path to client config header") orelse ""; + const dtb_path = b.option([]const u8, "dtb_path", "Path to the DTB file") orelse ""; // TODO: Right now this is not super ideal. What's happening is that we do not // always need a serial config include, but we must always specify it @@ -312,6 +373,7 @@ pub fn build(b: *std.Build) void { const net_config_include = LazyPath{ .cwd_relative = net_config_include_option }; const i2c_client_include = LazyPath{ .cwd_relative = i2c_client_include_option }; const gpu_config_include = LazyPath{ .cwd_relative = gpu_config_include_option }; + const clk_client_include = LazyPath{ .cwd_relative = clk_conf_include_option }; // libmicrokit // We're declaring explicitly here instead of with anonymous structs due to a bug. See https://github.com/ziglang/zig/issues/19832 libmicrokit = LazyPath{ .cwd_relative = libmicrokit_opt.? }; @@ -454,6 +516,22 @@ pub fn build(b: *std.Build) void { b.installArtifact(driver); } + // Clock drivers + inline for (std.meta.fields(DriverClass.Clock)) |class| { + const driver = addClockDriver(b, clk_client_include, util, @enumFromInt(class.value), target, optimize); + driver.linkLibrary(util_putchar_debug); + + const clk_config = b.addSystemCommand(&.{ + "python", + "drivers/clk/create_clk_config.py", + dtb_path, + }); // Creates a system command which runs the python interpreter + const clk_config_include = clk_config.addOutputDirectoryArg("test"); + driver.addIncludePath(clk_config_include); + + b.installArtifact(driver); + } + // I2C components const i2c_virt = addPd(b, .{ .name = "i2c_virt.elf", diff --git a/drivers/clk/clk-operations.c b/drivers/clk/clk-operations.c new file mode 100644 index 000000000..3a39a686d --- /dev/null +++ b/drivers/clk/clk-operations.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +/* + * Operations for MPLL clocks are derived from: + * https://github.com/torvalds/linux/blob/ + * befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/meson/clk-mpll.c + * + * Copyright (c) 2016 AmLogic, Inc. + * Author: Michael Turquette + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for PLL clocks are derived from: + * https://github.com/torvalds/linux/blob/ + * befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/meson/clk-pll.c + * + * Copyright (c) 2015 Endless Mobile, Inc. + * Author: Carlo Caione + * + * Copyright (c) 2018 Baylibre, SAS. + * Author: Jerome Brunet + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for gate clocks are derived from: + * https://github.com/torvalds/linux/blob/ + * befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/meson/clk-regmap.c + * + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for fixed factor clocks are derived from: + * https://github.com/torvalds/linux/blob/ + * befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/clk-fixed-factor.c + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for divider clocks are derived from: + * https://github.com/torvalds/linux/blob/ + * befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/clk-divider.c + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * Copyright (C) 2011 Richard Zhao, Linaro + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd + * + * Adjustable divider clock implementation + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for multiplexer clocks are derived from: + * https://github.com/torvalds/linux/blob/ + * befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/clk-mux.c + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * Copyright (C) 2011 Richard Zhao, Linaro + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd + * + * Simple multiplexer clock implementation + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for meson_vid_pll_div are derived from: + * https://github.com/torvalds/linux/blob/ + * 7ec462100ef9142344ddbf86f2c3008b97acddbe/drivers/clk/meson/vid-pll-div.c + * https://github.com/torvalds/linux/blob/ + * 7ec462100ef9142344ddbf86f2c3008b97acddbe/drivers/clk/meson/vclk.c + * + * Copyright (c) 2018 BayLibre, SAS. + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include + +static inline int clk_gate_enable(struct clk *clk) +{ + struct clk_gate_data *data = (struct clk_gate_data *)(clk->data); + + return regmap_update_bits(clk->base, data->offset, data->bit_idx, MASK(1), 1); +} + +static inline int clk_gate_disable(struct clk *clk) +{ + struct clk_gate_data *data = (struct clk_gate_data *)(clk->data); + + regmap_update_bits(clk->base, data->offset, data->bit_idx, MASK(1), 0); + return 0; +} + +static inline int clk_gate_is_enabled(struct clk *clk) +{ + struct clk_gate_data *data = (struct clk_gate_data *)(clk->data); + + /* TODO: to be checked */ + /* if (gate->flags & CLK_GATE_SET_TO_DISABLE) */ + /* val ^= BIT(gate->bit_idx); */ + + /* val &= BIT(gate->bit_idx); */ + /* return val ? 1 : 0; */ + + return regmap_read_bits(clk->base, data->offset, data->bit_idx, MASK(1)); +} + +const struct clk_ops clk_gate_ops = { + .enable = clk_gate_enable, + .disable = clk_gate_disable, + .is_enabled = clk_gate_is_enabled, +}; + +const struct clk_ops clk_gate_ro_ops = { + .is_enabled = clk_gate_is_enabled, +}; + +static inline uint64_t clk_div_recalc_rate(const struct clk *clk, uint64_t prate) +{ + + struct clk_div_data *data = (struct clk_div_data *)(clk->data); + uint32_t div = regmap_read_bits(clk->base, data->offset, data->shift, MASK(data->width)); + + /* TODO: Need to verify the following cases */ + if (data->flags & CLK_DIVIDER_ONE_BASED) { + ; + } else if (data->flags & CLK_DIVIDER_POWER_OF_TWO) { + div = 1 << div; + } else if (data->flags & CLK_DIVIDER_MAX_AT_ZERO) { + div = div ? div : MASK(data->width) + 1; + } else { + div += 1; + } + + return DIV_ROUND_UP_ULL((uint64_t)prate, div); +} + +static inline int clk_div_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct clk_div_data *data = (struct clk_div_data *)(clk->data); + uint32_t div = DIV_ROUND_UP(parent_rate, rate); + + if (data->flags & CLK_DIVIDER_ONE_BASED) { + /* TODO: to be implemented */ + ; + } else if (data->flags & CLK_DIVIDER_POWER_OF_TWO) { + /* div = __ffs(div); */ + } else if (data->flags & CLK_DIVIDER_MAX_AT_ZERO) { + div = (div == MASK(data->width) + 1) ? 0 : div; + } else { + div -= 1; + } + return regmap_update_bits(clk->base, data->offset, data->shift, MASK(data->width), div); +} + +const struct clk_ops clk_divider_ops = { + .enable = NULL, + .recalc_rate = clk_div_recalc_rate, + /* .determine_rate = clk_div_determine_rate, */ + .set_rate = clk_div_set_rate, +}; + +const struct clk_ops clk_divider_ro_ops = { + .recalc_rate = clk_div_recalc_rate, + /* .determine_rate = clk_div_determine_rate, */ +}; + +static inline int clk_mux_get_parent(const struct clk *clk, uint8_t *index) +{ + struct clk_mux_data *data = (struct clk_mux_data *)(clk->data); + uint32_t num_parents = clk->hw.init->num_parents; + uint32_t val = regmap_read_bits(clk->base, data->offset, data->shift, data->mask); + + if (data->table) { + int i; + for (i = 0; i < num_parents; i++) { + if (data->table[i] == val) { + *index = i; + return 0; + } + } + return CLK_UNKNOWN_TARGET; + } + + /* if (val && (flags & CLK_MUX_INDEX_BIT)) */ + /* val = ffs(val) - 1; */ + + /* if (val && (flags & CLK_MUX_INDEX_ONE)) */ + /* val--; */ + + if (val >= num_parents) + return CLK_UNKNOWN_TARGET; + + *index = val; + return 0; +} + +static inline int clk_mux_set_parent(struct clk *clk, uint8_t index) +{ + struct clk_mux_data *data = (struct clk_mux_data *)(clk->data); + + if (data->table) { + uint32_t val = data->table[index]; + return regmap_update_bits(clk->base, data->offset, data->shift, data->mask, val); + } + + return regmap_update_bits(clk->base, data->offset, data->shift, data->mask, index); +} + +const struct clk_ops clk_mux_ops = { + .get_parent = clk_mux_get_parent, .set_parent = clk_mux_set_parent, + /* .determine_rate = clk_mux_determine_rate, */ +}; + +const struct clk_ops clk_mux_ro_ops = { + .get_parent = clk_mux_get_parent, +}; + +static inline uint64_t clk_factor_recalc_rate(const struct clk *clk, uint64_t parent_rate) +{ + struct clk_fixed_factor_data *data = (struct clk_fixed_factor_data *)(clk->data); + uint64_t rate; + + rate = (uint64_t)parent_rate * data->mult; + do_div(rate, data->div); + return (uint64_t)rate; +} + +const struct clk_ops clk_fixed_factor_ops = { + /* .round_rate = clk_factor_round_rate, */ + /* .set_rate = clk_factor_set_rate, */ + .recalc_rate = clk_factor_recalc_rate, + /* .recalc_accuracy = clk_factor_recalc_accuracy, */ +}; + +static inline int clk_source_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct clk_source_data *data = (struct clk_source_data *)(clk->data); + data->rate = rate; + + return 0; +} + +static inline uint64_t clk_source_get_rate(const struct clk *clk, uint64_t prate) +{ + struct clk_source_data *data = (struct clk_source_data *)(clk->data); + + return data->rate; +} + +const struct clk_ops clk_source_ops = { + .recalc_rate = clk_source_get_rate, + .set_rate = clk_source_set_rate, +}; diff --git a/drivers/clk/clk-operations.h b/drivers/clk/clk-operations.h new file mode 100644 index 000000000..361075af8 --- /dev/null +++ b/drivers/clk/clk-operations.h @@ -0,0 +1,186 @@ +/* + * Copyright 2024, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +#define CLK_INCORRECT_ARGS -1 +#define CLK_INVALID_OP -2 +#define CLK_INVALID_ID -3 +#define CLK_UNKNOWN_REQ -4 +#define CLK_UNKNOWN_TARGET -5 +#define CLK_FAILED_OP -6 + +/* TODO: Replace this doggy delay() with a standard interface */ +static inline void delay_us(uint32_t us) +{ + uint64_t start_time = sddf_timer_time_now(TIMER_CH); + uint64_t now_time = start_time; + while (now_time - start_time < us) { + now_time = sddf_timer_time_now(TIMER_CH); + } +} + +static inline int reg_write(uint64_t base, uint32_t offset, uint32_t val) +{ + volatile uint32_t *clk_reg = ((void *)base + offset); + *clk_reg = val; + + return 0; +} + +static inline int regmap_update_bits(uint64_t base, uint32_t offset, uint8_t shift, uint32_t mask, uint32_t val) +{ + volatile uint32_t *clk_reg = ((void *)base + offset); + uint32_t reg_val = *clk_reg; + + reg_val &= ~(mask << shift); + reg_val |= ((mask & val) << shift); + + *clk_reg = reg_val; + + return 0; +} + +static inline uint32_t regmap_read_bits(uint64_t base, uint32_t offset, uint8_t shift, uint32_t mask) +{ + volatile uint32_t *clk_reg = ((void *)base + offset); + uint32_t reg_val = *clk_reg; + + reg_val >>= shift; + reg_val &= mask; + + return reg_val; +} + +extern const struct clk_ops clk_source_ops; +extern const struct clk_ops clk_fixed_factor_ops; +extern const struct clk_ops clk_divider_ops; +extern const struct clk_ops clk_divider_ro_ops; +extern const struct clk_ops clk_mux_ops; +extern const struct clk_ops clk_mux_ro_ops; +extern const struct clk_ops clk_gate_ops; +extern const struct clk_ops clk_gate_ro_ops; + +#define CLK_FIXED_FACTOR(_name, _mult, _div, _data_flags, _parent_clks, _num_parents, _init_flags) \ +struct clk _name = { \ + .data = &(struct clk_fixed_factor_data) { \ + .mult = (_mult), \ + .div = (_div), \ + .flags = (_data_flags), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_fixed_factor_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = (_num_parents), \ + .flags = (_init_flags), \ + }, \ +} + +#define CLK_GATE(_name, _offset, _bit, _data_flags, _parent_clks, _num_parents, _init_flags) \ +struct clk _name = { \ + .data = &(struct clk_gate_data) { \ + .offset = (_offset), \ + .bit_idx = (_bit), \ + .flags = (_data_flags), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_gate_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = _num_parents, \ + .flags = (_init_flags), \ + }, \ +} + +#define CLK_GATE_RO(_name, _offset, _bit, _data_flags, _parent_clks, _num_parents, _init_flags) \ +struct clk _name = { \ + .data = &(struct clk_gate_data) { \ + .offset = (_offset), \ + .bit_idx = (_bit), \ + .flags = (_data_flags), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_gate_ro_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = _num_parents, \ + .flags = (_init_flags), \ + }, \ +} + +#define CLK_MUX(_name, _offset, _mask, _shift, _table, _data_flags, _parent_data, _num_parents, _init_flags) \ +struct clk _name = { \ + .data = &(struct clk_mux_data) { \ + .offset = (_offset), \ + .mask = (_mask), \ + .shift = (_shift), \ + .table = (_table), \ + .flags = (_data_flags), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_mux_ops, \ + .parent_data = (_parent_data), \ + .num_parents = (_num_parents), \ + .flags = (_init_flags), \ + }, \ +} + +#define CLK_MUX_RO(_name, _offset, _mask, _shift, _table, _data_flags, _parent_data, _num_parents, _init_flags) \ +struct clk _name = { \ + .data = &(struct clk_mux_data) { \ + .offset = (_offset), \ + .mask = (_mask), \ + .shift = (_shift), \ + .table = (_table), \ + .flags = (_data_flags), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_mux_ro_ops, \ + .parent_data = (_parent_data), \ + .num_parents = (_num_parents), \ + .flags = (_init_flags), \ + }, \ +} + +#define CLK_DIV(_name, _offset, _shift, _width, _data_flags, _parent_clks, _num_parents, _init_flags) \ +struct clk _name = { \ + .data = &(struct clk_div_data) { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .flags = (_data_flags), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_divider_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = (_num_parents), \ + .flags = (_init_flags), \ + }, \ +} + +#define CLK_DIV_RO(_name, _offset, _shift, _width, _data_flags, _parent_clks, _num_parents, _init_flags) \ +struct clk _name = { \ + .data = &(struct clk_div_data) { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .flags = (_data_flags), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_divider_ro_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = (_num_parents), \ + .flags = (_init_flags), \ + }, \ +} diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c new file mode 100644 index 000000000..3b34f1b08 --- /dev/null +++ b/drivers/clk/clk.c @@ -0,0 +1,360 @@ +/* + * Copyright 2024, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Terry Bai: tianyi.bai@unsw.edu.au + */ + +#include +#include +#include +#include +#include +#include /* common definitions and interfaces */ +#include /* ops of common clocks e.g., div, mux, fixed factor, and gate*/ +#include /* configuration parsed from device tree */ + +#ifdef BOARD_CLASS_meson +#include /* operations for meson-specific clocks */ +#include /* implementation of clock measurements */ +#include /* g12a-specific definitions */ +#include /* offsets of control registers */ +#elif BOARD_CLASS_imx +#include /* operations for imx-specific clocks */ +#include /* imx8mq-specific definitions */ +#else +#error "The platform is not supported!\n" +#endif + +// Logging +/* #define DEBUG_DRIVER */ + +#ifdef DEBUG_DRIVER +#define LOG_DRIVER(...) do{ sddf_dprintf("CLK DRIVER|INFO: "); sddf_dprintf(__VA_ARGS__); }while(0) +#else +#define LOG_DRIVER(...) do{}while(0) +#endif + +#define LOG_DRIVER_ERR(...) do{ sddf_printf("CLK DRIVER|ERROR: "); sddf_printf(__VA_ARGS__); }while(0) + +#ifndef NUM_CLK_LIST +#error "Constant \"NUM_CLK_LIST\" should be defined\n") +#endif + +#define CLIENT_CH 0 + +struct clk **clk_list; + +struct clk *get_clk_by_name(const char *name) +{ + for (int i = 0; i < NUM_CLK_LIST; i++) { + if (clk_list[i] && sddf_strcmp(clk_list[i]->hw.init->name, name) == 0) { + return clk_list[i]; + } + } + return NULL; +} + +const struct clk *get_parent(const struct clk *clk) +{ + if (!clk) + return NULL; + + const struct clk_init_data *init = (struct clk_init_data *)clk->hw.init; + uint32_t num_parents = init->num_parents; + + if (init->parent_data) { + uint8_t parent_idx = 0; + int err = num_parents > 1 ? init->ops->get_parent(clk, &parent_idx) : 0; + if (err) + return NULL; + + struct clk_parent_data parent_data = init->parent_data[parent_idx]; + + if (parent_data.clk) { + return parent_data.clk; + } + if (parent_data.name) { + return get_clk_by_name(parent_data.name); + } + } + + if (num_parents > 0) { + return init->parent_clks[0]; + } + + return NULL; +} + +int clk_get_parent_id(const struct clk *clk, uint32_t *parent_clk_id) +{ + if (!clk) + return CLK_UNKNOWN_TARGET; + + const struct clk *pclk = get_parent(clk); + + if (pclk == NULL) + return CLK_INVALID_OP; + + for (int i = 0; i < NUM_CLK_LIST; i++) { + if (pclk == clk_list[i]) { + *parent_clk_id = i; + return 0; + } + } + + return CLK_UNKNOWN_TARGET; +} + +/* The user needs to know which parent clock the value represents, and check + * if the target parent clock is configured correctly with clk_get_parent() */ +int clk_set_parent_by_val(struct clk *clk, uint32_t parent_idx) +{ + if (!clk) + return CLK_UNKNOWN_TARGET; + + const struct clk_init_data *init = (struct clk_init_data *)clk->hw.init; + if (init->ops->set_parent) { + init->ops->set_parent(clk, parent_idx); + return 0; + } + LOG_DRIVER_ERR("clock \"%s\" has no set_parent() interface\n", init->name); + return CLK_INVALID_OP; +} + +int clk_set_parent_by_id(struct clk *clk, uint32_t pclk_id) +{ + const struct clk *pclk = clk_list[pclk_id]; + const struct clk_init_data *init = (struct clk_init_data *)clk->hw.init; + uint32_t num_parents = init->num_parents; + for (int i = 0; i < num_parents; i++) { + if (init->parent_clks && init->parent_clks[i] == pclk) { + return clk_set_parent_by_val(clk, i); + } else if (get_clk_by_name(init->parent_data[i].name) == pclk) { + return clk_set_parent_by_val(clk, i); + } + } + + return CLK_UNKNOWN_TARGET; +} + +/* TODO: Should be just read from the structure, but need to update everytime when */ +/* related clocks are modified */ +int clk_get_rate(const struct clk *clk, uint64_t *rate) +{ + if (!clk) + return CLK_UNKNOWN_TARGET; + + const struct clk_init_data *init = (struct clk_init_data *)clk->hw.init; + uint64_t parent_rate = 0; + int err = 0; + + const struct clk *parent_clk = get_parent(clk); + + if (parent_clk) { + err = clk_get_rate(parent_clk, &parent_rate); + } + + if (err) + return err; + + *rate = parent_rate; + if (init->ops->recalc_rate) { + *rate = init->ops->recalc_rate(clk, parent_rate); + } + + return 0; +} + +int clk_enable(struct clk *clk) +{ + if (!clk) + return CLK_UNKNOWN_TARGET; + + if (clk->hw.init->ops->enable != NULL) { + return clk->hw.init->ops->enable(clk); + } + + return CLK_INVALID_OP; +} + +int clk_disable(struct clk *clk) +{ + if (!clk) + return CLK_UNKNOWN_TARGET; + + if (clk->hw.init->ops->disable != NULL) { + return clk->hw.init->ops->disable(clk); + } + + return CLK_INVALID_OP; +} + +int clk_set_rate(struct clk *clk, uint64_t req_rate, uint64_t *rate) +{ + if (!clk) + return CLK_UNKNOWN_TARGET; + + /* TODO: we only propagate request to one level up. More operations need to be + * invoked by clients until a dynamic configration algorithm implemented */ + if (clk->hw.init->ops->init) { + clk->hw.init->ops->init(clk); + } + + const struct clk *pclk = get_parent(clk); + uint64_t prate = 0; + int err = clk_get_rate(pclk, &prate); + if (err) { + LOG_DRIVER_ERR("Failed to get parent clock's rate\n"); + return err; + } + + if (clk->hw.init->ops->set_rate) { + *rate = clk->hw.init->ops->set_rate(clk, req_rate, prate); + return 0; + } + if (pclk && pclk->hw.init->ops->set_rate) { + const struct clk *ppclk = get_parent(pclk); + uint64_t pprate = 0; + int err = clk_get_rate(ppclk, &pprate); + if (!err) { + pclk->hw.init->ops->set_rate(pclk, prate, pprate); + return 0; + } + return err; + } + + return CLK_INVALID_OP; +} + +void notified(microkit_channel ch) +{ +} + +void init(void) +{ + int err = 0; + clk_list = get_clk_list(); + + clk_probe(clk_list); + clk_msr_stat(clk_list); + + for (int i = 0; i < NUM_DEVICE_CLKS; i++) { + struct clk *clk = clk_list[clk_configs[i].clk_id]; + + /* Enable the clock */ + clk_enable(clk); + + /* Set parent for clocks as configured in device tree */ + if (clk_configs[i].pclk_id) { + err = clk_set_parent_by_id(clk, clk_configs[i].pclk_id); + if (err) { + LOG_DRIVER_ERR("Failed to set parent %u for clock %u: err - %d\n", clk_configs[i].pclk_id, + clk_configs[i].clk_id, err); + } + } + + if (clk_configs[i].frequency > 0) { + LOG_DRIVER("set rate for %s\n", clk->hw.init->name); + uint64_t rate = 0; + uint32_t err = clk_set_rate(clk, clk_configs[i].frequency, &rate); + if (err) { + LOG_DRIVER_ERR("Failed to set rate [%d] for clk_id: %d\n", clk_configs[i].frequency, + clk_configs[i].clk_id); + } + } + } +} + +microkit_msginfo protected(microkit_channel ch, microkit_msginfo msginfo) +{ + int err = 0; + uint32_t ret_num = 0; + uint32_t argc = microkit_msginfo_get_count(msginfo); + + /* TODO: Check if the channel is valid */ + switch (microkit_msginfo_get_label(msginfo)) { + + case SDDF_CLK_ENABLE: { + if (argc != 1) { + LOG_DRIVER_ERR("Incorrect number of arguments %u != 1\n", argc); + err = CLK_INCORRECT_ARGS; + break; + } + uint32_t clk_id = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_ID); + LOG_DRIVER("get request clk_enable(%d)\n", clk_id); + err = clk_enable(clk_list[clk_id]); + break; + } + case SDDF_CLK_DISABLE: { + if (argc != 1) { + LOG_DRIVER_ERR("Incorrect number of arguments %u != 1\n", argc); + err = CLK_INCORRECT_ARGS; + break; + } + uint32_t clk_id = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_ID); + LOG_DRIVER("get request clk_disable(%d)\n", clk_id); + err = clk_disable(clk_list[clk_id]); + break; + } + case SDDF_CLK_GET_RATE: { + if (argc != 1) { + LOG_DRIVER_ERR("Incorrect number of arguments %u != 1\n", argc); + err = CLK_INCORRECT_ARGS; + break; + } + uint32_t clk_id = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_ID); + uint64_t rate = 0; + err = clk_get_rate(clk_list[clk_id], &rate); + microkit_mr_set(0, rate); + ret_num = 1; + break; + } + case SDDF_CLK_SET_RATE: { + if (argc != 2) { + LOG_DRIVER_ERR("Incorrect number of arguments %u != 1\n", argc); + err = CLK_INCORRECT_ARGS; + break; + } + uint32_t clk_id = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_ID); + uint64_t req_rate = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_RATE); + uint64_t rate = 0; + err = clk_set_rate(clk_list[clk_id], req_rate, &rate); + microkit_mr_set(0, rate); + ret_num = 1; + break; + } + case SDDF_CLK_GET_PARENT: { + if (argc != 1) { + LOG_DRIVER_ERR("Incorrect number of arguments %u != 1\n", argc); + err = CLK_INCORRECT_ARGS; + break; + } + uint32_t clk_id = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_ID); + uint32_t pclk_id = 0; + err = clk_get_parent_id(clk_list[clk_id], &pclk_id); + microkit_mr_set(0, pclk_id); + ret_num = 1; + break; + } + case SDDF_CLK_SET_PARENT: { + if (argc != 2) { + LOG_DRIVER_ERR("Incorrect number of arguments %u != 1\n", argc); + err = CLK_INCORRECT_ARGS; + break; + } + uint32_t clk_id = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_ID); + uint32_t pclk_idx = (uint32_t)microkit_mr_get(SDDF_CLK_PARAM_PCLK_IDX); + err = clk_set_parent_by_val(clk_list[clk_id], pclk_idx); + microkit_mr_set(0, pclk_idx); + ret_num = 1; + break; + } + default: + LOG_DRIVER_ERR("Unknown request %lu to clockk driver from channel %u\n", microkit_msginfo_get_label(msginfo), + ch); + err = CLK_UNKNOWN_REQ; + } + return microkit_msginfo_new(err, ret_num); +} diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h new file mode 100644 index 000000000..fc2c6d2ee --- /dev/null +++ b/drivers/clk/clk.h @@ -0,0 +1,400 @@ + +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2011 Jeremy Kerr + * Copyright (C) 2011-2012 Linaro Ltd + * + * This file is derived from: + * https://github.com/torvalds/linux/blob/ + * 6485cf5ea253d40d507cd71253c9568c5470cd27/include/linux/clk-provider.h + */ + +#pragma once + +#include + +#define TIMER_CH 1 + +// Logging +/* #define DEBUG_DRIVER */ + +#ifdef DEBUG_DRIVER +#define LOG_DRIVER(...) do{ sddf_dprintf("CLK DRIVER|INFO: "); sddf_dprintf(__VA_ARGS__); }while(0) +#else +#define LOG_DRIVER(...) do{}while(0) +#endif + +#define LOG_DRIVER_ERR(...) do{ sddf_printf("CLK DRIVER|ERROR: "); sddf_printf(__VA_ARGS__); }while(0) + +/* + * flags used across common struct clk. these flags should only affect the + * top-level framework. custom flags for dealing with hardware specifics + * belong in struct clk_foo + */ +#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */ +#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */ +#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */ +#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */ + /* unused */ + /* unused */ +#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ +#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ +#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ +#define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ +#define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */ +#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ +/* parents need enable during gate/ungate, set rate and re-parent */ +#define CLK_OPS_PARENT_ENABLE BIT(12) +/* duty cycle call may be forwarded to the parent clock */ +#define CLK_DUTY_CYCLE_PARENT BIT(13) + +#define CLK_GATE_SET_TO_DISABLE BIT(0) +#define CLK_GATE_HIWORD_MASK BIT(1) +#define CLK_GATE_BIG_ENDIAN BIT(2) + +#define CLK_DIVIDER_ONE_BASED BIT(0) +#define CLK_DIVIDER_POWER_OF_TWO BIT(1) +#define CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define CLK_DIVIDER_HIWORD_MASK BIT(3) +#define CLK_DIVIDER_ROUND_CLOSEST BIT(4) +#define CLK_DIVIDER_READ_ONLY BIT(5) +#define CLK_DIVIDER_MAX_AT_ZERO BIT(6) +#define CLK_DIVIDER_BIG_ENDIAN BIT(7) + +#define CLK_MUX_INDEX_ONE BIT(0) +#define CLK_MUX_INDEX_BIT BIT(1) +#define CLK_MUX_HIWORD_MASK BIT(2) +#define CLK_MUX_READ_ONLY BIT(3) /* mux can't be changed */ +#define CLK_MUX_ROUND_CLOSEST BIT(4) +#define CLK_MUX_BIG_ENDIAN BIT(5) + +#define CLK_FRAC_DIVIDER_ZERO_BASED BIT(0) +#define CLK_FRAC_DIVIDER_BIG_ENDIAN BIT(1) +#define CLK_FRAC_DIVIDER_POWER_OF_TWO_PS BIT(2) + +struct clk; +struct clk_hw; +struct clk_init_data; + +/** + * struct clk_hw - handle for traversing from a struct clk to its corresponding + * hardware-specific structure. struct clk_hw should be declared within struct + * clk_foo and then referenced by the struct clk instance that uses struct + * clk_foo's clk_ops + * + * @init: pointer to struct clk_init_data that contains the init data shared + * with the common clock framework. + */ +struct clk_hw { + struct clk *clk; + struct clk_init_data *init; +}; + +/** + * struct clk_ops - Callback operations for hardware clocks; these are to + * be provided by the clock implementation, and will be called by drivers + * through the clk_* api. + * + * @enable: Enable the clock atomically. This must not return until the + * clock is generating a valid clock signal, usable by consumer + * devices. Called with enable_lock held. This function must not + * sleep. + * + * @disable: Disable the clock atomically. Called with enable_lock held. + * This function must not sleep. + * + * @is_enabled: Queries the hardware to determine if the clock is enabled. + * This function must not sleep. Optional, if this op is not + * set then the enable count will be used. + * + * @recalc_rate: Recalculate the rate of this clock, by querying hardware. The + * parent rate is an input parameter. It is up to the caller to + * ensure that the prepare_mutex is held across this call. If the + * driver cannot figure out a rate for this clock, it must return + * 0. Returns the calculated rate. Optional, but recommended - if + * this op is not set then clock rate will be initialized to 0. + * + * @round_rate: Given a target rate as input, returns the closest rate actually + * supported by the clock. The parent rate is an input/output + * parameter. + * + * @determine_rate: Given a target rate as input, returns the closest rate + * actually supported by the clock, and optionally the parent clock + * that should be used to provide the clock rate. + * + * @set_parent: Change the input source of this clock; for clocks with multiple + * possible parents specify a new parent by passing in the index + * as a u8 corresponding to the parent in either the .parent_names + * or .parents arrays. This function in affect translates an + * array index into the value programmed into the hardware. + * Returns 0 on success, -EERROR otherwise. + * + * @get_parent: Queries the hardware to determine the parent of a clock. The + * return value is a u8 which specifies the index corresponding to + * the parent clock. This index can be applied to either the + * .parent_names or .parents arrays. In short, this function + * translates the parent value read from hardware into an array + * index. Currently only called when the clock is initialized by + * __clk_init. This callback is mandatory for clocks with + * multiple parents. It is optional (and unnecessary) for clocks + * with 0 or 1 parents. + * + * @set_rate: Change the rate of this clock. The requested rate is specified + * by the second argument, which should typically be the return + * of .round_rate call. The third argument gives the parent rate + * which is likely helpful for most .set_rate implementation. + * Returns 0 on success, -EERROR otherwise. + * + * @init: Perform platform-specific initialization magic. + * This is not used by any of the basic clock types. + * This callback exist for HW which needs to perform some + * initialisation magic for CCF to get an accurate view of the + * clock. It may also be used dynamic resource allocation is + * required. It shall not used to deal with clock parameters, + * such as rate or parents. + * Returns 0 on success, -EERROR otherwise. + * + */ +struct clk_ops { + int (*get_parent)(const struct clk *clk, uint8_t *index); + int (*set_parent)(struct clk *clk, uint8_t index); + uint64_t (*recalc_rate)(const struct clk *clk, uint64_t parent_rate); + int (*set_rate)(const struct clk *clk, uint64_t rate, uint64_t parent_rate); + void (*init)(struct clk *clk); + int (*enable)(struct clk *clk); + int (*disable)(struct clk *clk); + int (*is_enabled)(struct clk *clk); +}; + +struct clk { + struct clk_hw hw; + void *data; + uint64_t base; +}; + +/** + * struct clk_parent_data - clk parent information + * @hw: parent clk_hw pointer (used for clk providers with internal clks) + * @name: globally unique parent name (used as a fallback) + */ +struct clk_parent_data { + const struct clk *clk; + const char *name; +}; + +/** + * struct clk_init_data - holds init data that's common to all clocks and is + * shared between the clock provider and the common clock framework. + * + * @name: clock name + * @ops: operations this clock supports + * @parent_names: array of string names for all possible parents + * @parent_data: array of parent data for all possible parents (when some + * parents are external to the clk controller) + * @parent_clks: array of pointers to all possible parents (when all parents + * are internal to the clk controller) + * @num_parents: number of possible parents + * @flags: framework-level hints and quirks + */ +struct clk_init_data { + uint32_t num_parents; + uint32_t flags; + const char *name; + const struct clk_ops *ops; + const struct clk **parent_clks; + const struct clk_parent_data *parent_data; +}; + +/** + * struct clk_source_data - clock source data + * + * @rate: ouput rate of clock hardware + * + */ +struct clk_source_data { + uint64_t rate; +}; + +/** + * struct clk_gate_data - gate specific data + * + * @offset: offset of the register controlling gate + * @bit_idx: single bit controlling gate + * @flags: hardware-specific flags + * + * Flags: + * CLK_GATE_SET_TO_DISABLE - by default this clock sets the bit at bit_idx to + * enable the clock. Setting this flag does the opposite: setting the bit + * disable the clock and clearing it enables the clock + * CLK_GATE_HIWORD_MASK - The gate settings are only in lower 16-bit + * of this register, and mask of gate bits are in higher 16-bit of this + * register. While setting the gate bits, higher 16-bit should also be + * updated to indicate changing gate bits. + */ +struct clk_gate_data { + uint32_t offset; + uint8_t bit_idx; + uint8_t flags; +}; + +/** + * struct clk_div_data - adjustable divider clock + * + * @reg: register containing the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @table: array of value/divider pairs, last entry should have div = 0 + * @lock: register lock + * + * Clock with an adjustable divider affecting its output frequency. Implements + * .recalc_rate, .set_rate and .round_rate + * + * @flags: + * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the + * register plus one. If CLK_DIVIDER_ONE_BASED is set then the divider is + * the raw value read from the register, with the value of zero considered + * invalid, unless CLK_DIVIDER_ALLOW_ZERO is set. + * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from + * the hardware register + * CLK_DIVIDER_ALLOW_ZERO - Allow zero divisors. For dividers which have + * CLK_DIVIDER_ONE_BASED set, it is possible to end up with a zero divisor. + * Some hardware implementations gracefully handle this case and allow a + * zero divisor by not modifying their input clock + * (divide by one / bypass). + * CLK_DIVIDER_HIWORD_MASK - The divider settings are only in lower 16-bit + * of this register, and mask of divider bits are in higher 16-bit of this + * register. While setting the divider bits, higher 16-bit should also be + * updated to indicate changing divider bits. + * CLK_DIVIDER_ROUND_CLOSEST - Makes the best calculated divider to be rounded + * to the closest integer instead of the up one. + * CLK_DIVIDER_READ_ONLY - The divider settings are preconfigured and should + * not be changed by the clock framework. + * CLK_DIVIDER_MAX_AT_ZERO - For dividers which are like CLK_DIVIDER_ONE_BASED + * except when the value read from the register is zero, the divisor is + * 2^width of the field. + */ +struct clk_div_data { + uint32_t offset; + uint8_t shift; + uint8_t width; + uint8_t flags; + /* const struct clk_div_table *table; */ +}; + +/** + * struct clk_fixed_factor_data - fixed multiplier and divider clock + * + * @mult: multiplier + * @div: divider + * @flags: behavior modifying flags + * + * Clock with a fixed multiplier and divider. The output frequency is the + * parent clock rate divided by div and multiplied by mult. + * Implements .recalc_rate, .set_rate, .round_rate and .recalc_accuracy + * + * Flags: + * * CLK_FIXED_FACTOR_FIXED_ACCURACY - Use the value in @acc instead of the + * parent clk accuracy. + */ +struct clk_fixed_factor_data { + uint32_t mult; + uint32_t div; + uint8_t flags; +}; + +/** + * struct clk_mux_data - multiplexer clock + * + * @reg: register controlling multiplexer + * @table: array of register values corresponding to the parent index + * @shift: shift to multiplexer bit field + * @mask: mask of mutliplexer bit field + * @flags: hardware-specific flags + * @lock: register lock + * + * Clock with multiple selectable parents. Implements .get_parent, .set_parent + * and .recalc_rate + * + * Flags: + * CLK_MUX_INDEX_ONE - register index starts at 1, not 0 + * CLK_MUX_INDEX_BIT - register index is a single bit (power of two) + * CLK_MUX_HIWORD_MASK - The mux settings are only in lower 16-bit of this + * register, and mask of mux bits are in higher 16-bit of this register. + * While setting the mux bits, higher 16-bit should also be updated to + * indicate changing mux bits. + * CLK_MUX_READ_ONLY - The mux registers can't be written, only read in the + * .get_parent clk_op. + * CLK_MUX_ROUND_CLOSEST - Use the parent rate that is closest to the desired + * frequency. + */ +struct clk_mux_data { + uint32_t offset; + uint32_t *table; + uint32_t mask; + uint8_t shift; + uint8_t flags; +}; + +/** + * function clk_msr_stat() - measure clock rates + * + * @clk_list: array of pointers to the clocks on SoC + * + * All parent clocks will be parsed by name and bound to the struct clk + */ +int clk_msr_stat(struct clk *clk_list[]); + +/** + * function clk_probe() - initialise all clocks + * + * @clk_list: array of pointers to the clocks on SoC + * + * All parent clocks will be parsed by name and bound to the struct clk + */ +void clk_probe(struct clk *clk_list[]); + +/** + * function get_clk_list() - initialise all clocks + * + * get a list of clock components for specific board + */ +struct clk **get_clk_list(); + +/** + * function get_parent() - get the current parent clk + * + * @clk: pointer to the current clk + */ +const struct clk *get_parent(const struct clk *clk); + +/** + * function clk_get_rate() - get the rate of target clock + * + * @clk: pointer to the current clk + * + */ +int clk_get_rate(const struct clk *clk, uint64_t *rate); + +/** + * function clk_enable() - enable the target clock signal + * + * @clk: pointer to the current clk + */ +int clk_enable(struct clk *clk); + +/** + * function clk_disable() - disable the target clock signal + * + * @clk: pointer to the current clk + */ +int clk_disable(struct clk *clk); + +/** + * function clk_set_rate() - set the nearest rate to the requested rate for + * the target clock + * + * @clk: pointer to the current clk + * @req_rate: request rate + * @rate: pointer to result variable + */ +int clk_set_rate(struct clk *clk, uint64_t req_rate, uint64_t *rate); diff --git a/drivers/clk/clk_utils.h b/drivers/clk/clk_utils.h new file mode 100644 index 000000000..d22d451e7 --- /dev/null +++ b/drivers/clk/clk_utils.h @@ -0,0 +1,35 @@ +/* + * Copyright 2024, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#define MASK(width) ((1UL << width) - 1) + +#define abs(x) ( ( (x) < 0) ? -(x) : (x) ) + +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +#define do_div(n, base) ({ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + __rem = ((uint64_t)(n)) % __base; \ + (n) = ((uint64_t)(n)) / __base; \ + __rem; \ + }) + +#define DIV_ROUND_DOWN_ULL(ll, d) \ + ({ uint64_t _tmp = (ll); do_div(_tmp, d); _tmp; }) + +#define DIV_ROUND_UP_ULL(ll, d) \ + DIV_ROUND_DOWN_ULL((uint64_t)(ll) + (d) - 1, (d)) + +#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \ +{ \ + typeof(divisor) __d = divisor; \ + unsigned long long _tmp = (x) + (__d) / 2; \ + do_div(_tmp, __d); \ + _tmp; \ +} \ +) diff --git a/drivers/clk/create_clk_config.py b/drivers/clk/create_clk_config.py new file mode 100644 index 000000000..f1255ccec --- /dev/null +++ b/drivers/clk/create_clk_config.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 + +# Copyright 2024, UNSW +# SPDX-License-Identifier: BSD-2-Clause + +import os +import sys +from typing import List +from devicetree import edtlib, dtlib + +supported_compat_str_board = { "hardkernel,odroid-c4", "fsl,imx8mm-evk", "fsl,imx8mq" } + +debug_parser = True +clock_list = {} + +def log_normal_parser(print_str: str) -> None: + if (debug_parser): + print("PARSER|INFO: " + print_str) + +def log_warning_parser(print_str: str) -> None: + sys.stderr.write("PARSER|WARNING: " + print_str) + +def log_error_parser(print_str: str) -> None: + sys.stderr.write("PARSER|ERROR: " + print_str) + +def parse_clock_list(dt: dtlib.DT, clocks: List) -> (List, List): + pnodes = [] + clk_ids = [] + i = 0 + + while (i < len(clocks)): + if clocks[i] == 0: + clk_ids.append(clocks[i]) + i += 1 + continue + pnode = devicetree.phandle2node[clocks[i]] + if "#clock-cells" in pnode.props and pnode.props["#clock-cells"].to_num() == 0: + # TODO: consider the case of `xtal` and represent this clock another way + clk_ids.append(clocks[i]) + pnodes.append(pnode) + elif clocks[i] > 0: + clk_ids.append(clocks[i+1]) + pnodes.append(pnode) + i += 1 + else: + clk_ids.append(-1) + i += 1 + + return clk_ids, pnodes + +def add_clock(clk_id: int, frequency: int, pclk_id: int): + if clk_id in clock_list.keys(): + if clock_list[clk_id][0] == 0 and frequency: + clock_list[clk_id] = (frequency, clock_list[clk_id][1]) + if clock_list[clk_id][1] == 0 and pclk_id: + clock_list[clk_id] = (clock_list[clk_id][0], pclk_id) + else: + clock_list[clk_id] = (frequency, pclk_id) + +def extract_clocks(dt: dtlib.DT, node: dtlib.Node) -> List: + props = list(node.props.keys()) + if "clocks" in props: + clocks = node.props["clocks"].to_nums() + clock_ids, pnodes = parse_clock_list(devicetree, clocks) + for clk_id in clock_ids: + add_clock(clk_id, 0, 0) + for pnode in pnodes: + if pnode != node: + extract_clocks(dt, pnode) + + if "max-frequency" in props: + max_frequency = node.props["max-frequency"].to_nums() + + if "assigned-clocks" in props and "assigned-clock-rates" in props: + assigned_clocks, pnodes = parse_clock_list(devicetree, node.props["assigned-clocks"].to_nums()) + assigned_clock_rates = node.props["assigned-clock-rates"].to_nums() + for clk_id, clk_rate in zip(assigned_clocks, assigned_clock_rates): + if (clk_rate): + add_clock(clk_id, clk_rate, 0) + for pnode in pnodes: + if pnode != node: + extract_clocks(dt, pnode) + + if "assigned-clocks" in props and "assigned-clock-parents" in props: + assigned_clocks, pnodes = parse_clock_list(devicetree, node.props["assigned-clocks"].to_nums()) + assigned_clock_parents, ppnodes = parse_clock_list(devicetree, node.props["assigned-clock-parents"].to_nums()) + for clk_id, pclk_id in zip(assigned_clocks, assigned_clock_parents): + if (pclk_id): + add_clock(clk_id, 0, pclk_id) + for pnode in pnodes: + if pnode != node: + extract_clocks(dt, pnode) + for pnode in ppnodes: + if pnode != node: + extract_clocks(dt, pnode) + +def write_configs_to_headerfile(path: str) -> None: + with open(path + '/clk_config.h', "w") as f: + f.write("#include \n") + f.write("#define NUM_DEVICE_CLKS {}\n\n".format(len(clock_list))) + + clk_cfg_strs = [] + for key, value in clock_list.items(): + clk_cfg_strs.append(" {{ .clk_id = {}, .frequency = {}, .pclk_id = {} }}".format(key, value[0], value[1])) + + f.write("static struct clk_cfg clk_configs[] = {{\n{}\n}};".format(",\n".join(clk_cfg_strs))) + +if __name__ == "__main__": + supported = False + devicetree = dtlib.DT(sys.argv[1], force=True) + for compat_str in devicetree.root.props["compatible"].to_strings(): + if compat_str in supported_compat_str_board: + supported = True + break + + if not supported: + log_error_parser("this board is not supported.") + exit(1) + + + for node in devicetree.node_iter(): + props = list(node.props.keys()) + if "status" in props: + status = node.props["status"].to_string() + if status == "okay": + extract_clocks(devicetree, node) + + write_configs_to_headerfile(sys.argv[2]) + + print('Initial clock configuration has been saved in ' + sys.argv[2] + '/clk_config.h') diff --git a/drivers/clk/imx/clk-imx.c b/drivers/clk/imx/clk-imx.c new file mode 100644 index 000000000..6691ab0c2 --- /dev/null +++ b/drivers/clk/imx/clk-imx.c @@ -0,0 +1,446 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2010-2011 Canonical Ltd + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd + * + * Gated clock implementation + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-gate2.c + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2018 NXP. + * + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-frac-pll.c + */ + +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright 2018 NXP. + * + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-sscg-pll.c + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2018 NXP + * + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-composite-8m.c + */ + +#include +#include +#include +#include + +#define PLL_FRAC_DENOM 0x1000000 + +static int clk_gate2_enable(struct clk *clk) +{ + struct clk_gate_data *data = (struct clk_gate_data *)(clk->data); + + return regmap_update_bits(clk->base, data->offset, data->bit_idx, MASK(2), 0x3); +} + +static int clk_gate2_disable(struct clk *clk) +{ + struct clk_gate_data *data = (struct clk_gate_data *)(clk->data); + + return regmap_update_bits(clk->base, data->offset, data->bit_idx, MASK(2), 0); +} + +static int clk_gate2_is_enabled(struct clk *clk) +{ + struct clk_gate_data *data = (struct clk_gate_data *)(clk->data); + + if (regmap_read_bits(clk->base, data->offset, data->bit_idx, MASK(2)) == 0x3) + return 1; + + return 0; +} + +const struct clk_ops clk_gate2_ops = { + .enable = clk_gate2_enable, + .disable = clk_gate2_disable, + /* .disable_unused = clk_gate2_disable_unused, */ + .is_enabled = clk_gate2_is_enabled, +}; + +static uint64_t clk_pll_recalc_rate(const struct clk *clk, uint64_t prate) +{ + /* TODO: This function is derived from Linux codebase, but seems wrong + * according to the datasheet as PLL_REFCLK_DIV_VAL[5:10] is never used. */ + struct clk_frac_pll_data *data = (struct clk_frac_pll_data *)(clk->data); + uint64_t temp_rate = prate; + uint64_t rate; + + /* Output Divider value is (n + 1) * 2 */ + uint32_t output_div_val = regmap_read_bits(clk->base, data->offset, 0, MASK(5)); + output_div_val = (output_div_val + 1) * 2; + + /* Valid Frac Divider value is 1 to 2^24 */ + uint32_t frac_div_val = regmap_read_bits(clk->base, data->offset + 0x4, 7, MASK(24)); + + /* Valid Int Divider value is 1 to 32 */ + uint32_t int_div_val = regmap_read_bits(clk->base, data->offset + 0x4, 0, MASK(7)); + + temp_rate *= prate; + temp_rate *= frac_div_val; + do_div(temp_rate, PLL_FRAC_DENOM); + do_div(temp_rate, output_div_val); + + /* Frac Divider value is (n) */ + rate = prate * 8 * (int_div_val + 1); + do_div(rate, output_div_val); + rate += temp_rate; + + return rate; +} + +static int clk_pll_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct clk_frac_pll_data *data = (struct clk_frac_pll_data *)(clk->data); + uint32_t divfi, divff; + uint64_t temp64; + int ret; + + parent_rate *= 8; + rate *= 2; + divfi = rate / parent_rate; + temp64 = parent_rate * divfi; + temp64 = rate - temp64; + temp64 *= PLL_FRAC_DENOM; + do_div(temp64, parent_rate); + divff = temp64; + + /** + * Keep PLL_OUTPUT_VAL at zero. + * + * pllout = parent_rate * 8 / 2 * DIVF_VAL; + * where DIVF_VAL = 1 + DIVFI + DIVFF / 2^24. + */ + + /* Write PLL_FRAC_DIV_CTL */ + ret = regmap_update_bits(clk->base, data->offset + 0x4, 7, 24, divff); + if (ret) + return ret; + + /* Write PLL_INT_DIV_CTL */ + ret = regmap_update_bits(clk->base, data->offset + 0x4, 0, 7, divfi - 1); + if (ret) + return ret; + + /* Clear PLL_OUTPUT_DIV_VAL */ + ret = regmap_update_bits(clk->base, data->offset, 0, 5, 0); + if (ret) + return ret; + + /* Set the NEV_DIV_VAL to reload the DIVFI and DIVFF */ + ret = regmap_update_bits(clk->base, data->offset, 12, 1, 1); + if (ret) + return ret; + + // Wait ack + uint32_t timeout = 1000; + while (timeout--) { + if (regmap_read_bits(clk->base, data->offset, 12, 1)) { + break; + } + } + if (!timeout) + return CLK_FAILED_OP; + + /* clear the NEV_DIV_VAL */ + return regmap_update_bits(clk->base, data->offset, 12, 1, 1); +} + +const struct clk_ops clk_frac_pll_ops = { + /* .prepare = clk_pll_prepare, */ + /* .unprepare = clk_pll_unprepare, */ + /* .is_prepared = clk_pll_is_prepared, */ + .recalc_rate = clk_pll_recalc_rate, + /* .round_rate = clk_pll_round_rate, */ + .set_rate = clk_pll_set_rate, +}; + +static uint64_t clk_sscg_pll_recalc_rate(const struct clk *clk, uint64_t prate) +{ + struct clk_sscg_pll_data *data = (struct clk_sscg_pll_data *)(clk->data); + uint64_t temp_rate = prate; + + uint32_t divr1 = regmap_read_bits(clk->base, data->offset + 0x8, 25, MASK(3)); + uint32_t divr2 = regmap_read_bits(clk->base, data->offset + 0x8, 19, MASK(6)); + uint32_t divf1 = regmap_read_bits(clk->base, data->offset + 0x8, 13, MASK(6)); + uint32_t divf2 = regmap_read_bits(clk->base, data->offset + 0x8, 7, MASK(6)); + uint32_t divq = regmap_read_bits(clk->base, data->offset + 0x8, 1, MASK(6)); + + if (regmap_read_bits(clk->base, data->offset, 4, MASK(1))) { + temp_rate = prate; + } else if (regmap_read_bits(clk->base, data->offset, 5, MASK(1))) { + temp_rate *= divf2; + do_div(temp_rate, (divr2 + 1) * (divq + 1)); + } else { + temp_rate *= 2; + temp_rate *= (divf1 + 1) * (divf2 + 1); + do_div(temp_rate, (divr1 + 1) * (divr2 + 1) * (divq + 1)); + } + + return 0; +} + +static int clk_sscg_pll_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + /* struct clk_sscg_pll_data *data = (struct clk_sscg_pll_data *)(clk->data); */ + + /* TODO: to be implemented. */ + + return 0; +} + +static int clk_sscg_pll_get_parent(const struct clk *clk, uint8_t *index) +{ + struct clk_sscg_pll_data *data = (struct clk_sscg_pll_data *)(clk->data); + + if (regmap_read_bits(clk->base, data->offset, 4, MASK(1))) { + *index = data->bypass2; + } else if (regmap_read_bits(clk->base, data->offset, 5, MASK(1))) { + *index = data->bypass1; + } + + return 0; +} + +static int clk_sscg_pll_set_parent(struct clk *clk, uint8_t index) +{ + /* struct clk_sscg_pll_data *data = (struct clk_sscg_pll_data *)(clk->data); */ + + /* TODO: This operation is based on `setup.bypass` instead of index + * passed from callee, need to be decided by clock manager */ + + return 0; +} + +const struct clk_ops clk_sscg_pll_ops = { + /* .prepare = clk_sscg_pll_prepare, */ + /* .unprepare = clk_sscg_pll_unprepare, */ + /* .is_prepared = clk_sscg_pll_is_prepared, */ + .recalc_rate = clk_sscg_pll_recalc_rate, + /* .set_rate = clk_sscg_pll_set_rate, */ + .set_parent = clk_sscg_pll_set_parent, + .get_parent = clk_sscg_pll_get_parent, + /* .determine_rate = clk_sscg_pll_determine_rate, */ +}; + +static int imx8mx_clk_composite_determine_rate(uint64_t rate, uint64_t parent_rate, uint32_t *prev_div, + uint32_t *post_div) +{ + uint32_t min_error = UINT_MAX; + int ret = CLK_FAILED_OP; + + for (int i = 1; i <= PCG_PREDIV_MAX; i++) { + for (int j = 1; j <= PCG_DIV_MAX; j++) { + uint32_t error = abs(((parent_rate / i) / j) - rate); + if (error < min_error) { + *prev_div = i; + *post_div = j; + min_error = error; + ret = 0; + } + } + } + + return ret; +} + +static uint64_t imx8m_clk_core_slice_recalc_rate(const struct clk *clk, uint64_t prate) +{ + struct clk_core_slice_data *data = (struct clk_core_slice_data *)(clk->data); + + uint32_t div_val = regmap_read_bits(clk->base, data->offset, data->div_shift, MASK(data->div_width)); + /* Divider value is n+1 */ + return DIV_ROUND_UP_ULL((uint64_t)prate, div_val + 1); +} + +static int imx8m_clk_core_slice_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct clk_core_slice_data *data = (struct clk_core_slice_data *)(clk->data); + + uint32_t div = DIV_ROUND_UP(parent_rate, rate) - 1; + + return regmap_update_bits(clk->base, data->offset, data->div_shift, MASK(data->div_width), div); +} + +static int imx8m_clk_core_slice_get_parent(const struct clk *clk, uint8_t *index) +{ + struct clk_core_slice_data *data = (struct clk_core_slice_data *)(clk->data); + + uint32_t num_parents = clk->hw.init->num_parents; + uint32_t val = regmap_read_bits(clk->base, data->offset, data->mux_shift, data->mux_mask); + + if (val >= num_parents) + return CLK_UNKNOWN_TARGET; + + *index = val; + return 0; +} + +static int imx8m_clk_core_slice_set_parent(struct clk *clk, uint8_t index) +{ + struct clk_core_slice_data *data = (struct clk_core_slice_data *)(clk->data); + + /* + * write twice to make sure non-target interface + * SEL_A/B point the same clk input. + */ + regmap_update_bits(clk->base, data->offset, data->mux_shift, data->mux_mask, index); + regmap_update_bits(clk->base, data->offset, data->mux_shift, data->mux_mask, index); + + return 0; +} + +const struct clk_ops clk_core_slice_ops = { + .recalc_rate = imx8m_clk_core_slice_recalc_rate, + /* .round_rate = imx8m_clk_core_slice_round_rate, */ + .set_rate = imx8m_clk_core_slice_set_rate, + /* .determine_rate = imx8m_clk_core_slice_determine_rate, */ + .get_parent = imx8m_clk_core_slice_get_parent, + .set_parent = imx8m_clk_core_slice_set_parent, +}; + +static uint64_t imx8m_clk_common_slice_recalc_rate(const struct clk *clk, uint64_t prate) +{ + struct clk_common_slice_data *data = (struct clk_common_slice_data *)(clk->data); + + uint32_t prediv_val = regmap_read_bits(clk->base, data->offset, data->prevdiv_shift, MASK(data->prevdiv_width)); + /* Divider value is n+1 */ + uint64_t prediv_rate = DIV_ROUND_UP_ULL((uint64_t)prate, prediv_val + 1); + + uint32_t postdiv_val = regmap_read_bits(clk->base, data->offset, data->postdiv_shift, MASK(data->postdiv_width)); + /* Divider value is n+1 */ + return DIV_ROUND_UP_ULL((uint64_t)prediv_rate, postdiv_val + 1); +} + +static int imx8m_clk_common_slice_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct clk_common_slice_data *data = (struct clk_common_slice_data *)(clk->data); + uint32_t prev_div = 1; + uint32_t post_div = 1; + + int ret = imx8mx_clk_composite_determine_rate(rate, parent_rate, &prev_div, &post_div); + if (ret) + return ret; + + ret = regmap_update_bits(clk->base, data->offset, data->prevdiv_shift, MASK(data->prevdiv_width), prev_div); + if (ret) + return ret; + + return regmap_update_bits(clk->base, data->offset, data->postdiv_shift, MASK(data->postdiv_width), post_div); +} + +static int imx8m_clk_common_slice_get_parent(const struct clk *clk, uint8_t *index) +{ + struct clk_common_slice_data *data = (struct clk_common_slice_data *)(clk->data); + + uint32_t num_parents = clk->hw.init->num_parents; + uint32_t val = regmap_read_bits(clk->base, data->offset, data->mux_shift, data->mux_mask); + + if (val >= num_parents) + return CLK_UNKNOWN_TARGET; + + *index = val; + return 0; +} + +static int imx8m_clk_common_slice_set_parent(struct clk *clk, uint8_t index) +{ + struct clk_common_slice_data *data = (struct clk_common_slice_data *)(clk->data); + + /* + * write twice to make sure non-target interface + * SEL_A/B point the same clk input. + */ + regmap_update_bits(clk->base, data->offset, data->mux_shift, data->mux_mask, index); + regmap_update_bits(clk->base, data->offset, data->mux_shift, data->mux_mask, index); + + return 0; +} + +const struct clk_ops clk_common_slice_ops = { + .recalc_rate = imx8m_clk_common_slice_recalc_rate, + /* .round_rate = imx8m_clk_common_slice_round_rate, */ + .set_rate = imx8m_clk_common_slice_set_rate, + /* .determine_rate = imx8m_clk_common_slice_determine_rate, */ + .get_parent = imx8m_clk_common_slice_get_parent, + .set_parent = imx8m_clk_common_slice_set_parent, +}; + +static uint64_t imx8m_clk_bus_slice_recalc_rate(const struct clk *clk, uint64_t prate) +{ + struct clk_bus_slice_data *data = (struct clk_bus_slice_data *)(clk->data); + + uint32_t prediv_val = regmap_read_bits(clk->base, data->offset, data->prevdiv_shift, MASK(data->prevdiv_width)); + /* Divider value is n+1 */ + uint64_t prediv_rate = DIV_ROUND_UP_ULL((uint64_t)prate, prediv_val + 1); + + uint32_t postdiv_val = regmap_read_bits(clk->base, data->offset, data->postdiv_shift, MASK(data->postdiv_width)); + /* Divider value is n+1 */ + return DIV_ROUND_UP_ULL((uint64_t)prediv_rate, postdiv_val + 1); +} + +static int imx8m_clk_bus_slice_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct clk_bus_slice_data *data = (struct clk_bus_slice_data *)(clk->data); + uint32_t prev_div = 1; + uint32_t post_div = 1; + + int ret = imx8mx_clk_composite_determine_rate(rate, parent_rate, &prev_div, &post_div); + if (ret) + return ret; + + ret = regmap_update_bits(clk->base, data->offset, data->prevdiv_shift, MASK(data->prevdiv_width), prev_div); + if (ret) + return ret; + + return regmap_update_bits(clk->base, data->offset, data->postdiv_shift, MASK(data->postdiv_width), post_div); +} + +static int imx8m_clk_bus_slice_get_parent(const struct clk *clk, uint8_t *index) +{ + struct clk_bus_slice_data *data = (struct clk_bus_slice_data *)(clk->data); + + uint32_t num_parents = clk->hw.init->num_parents; + uint32_t val = regmap_read_bits(clk->base, data->offset, data->mux_shift, data->mux_mask); + + if (val >= num_parents) + return CLK_UNKNOWN_TARGET; + + *index = val; + return 0; +} + +static int imx8m_clk_bus_slice_set_parent(struct clk *clk, uint8_t index) +{ + struct clk_bus_slice_data *data = (struct clk_bus_slice_data *)(clk->data); + + /* + * write twice to make sure non-target interface + * SEL_A/B point the same clk input. + */ + regmap_update_bits(clk->base, data->offset, data->mux_shift, data->mux_mask, index); + regmap_update_bits(clk->base, data->offset, data->mux_shift, data->mux_mask, index); + + return 0; +} + +const struct clk_ops clk_bus_slice_ops = { + .recalc_rate = imx8m_clk_bus_slice_recalc_rate, + /* .round_rate = imx8m_clk_composite_divider_round_rate, */ + .set_rate = imx8m_clk_bus_slice_set_rate, + /* .determine_rate = imx8m_divider_determine_rate, */ + .get_parent = imx8m_clk_bus_slice_get_parent, + .set_parent = imx8m_clk_bus_slice_set_parent, +}; diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c new file mode 100644 index 000000000..1a5406457 --- /dev/null +++ b/drivers/clk/imx/clk-imx8mq.c @@ -0,0 +1,2957 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2018 NXP. + * Copyright (C) 2017 Pengutronix, Lucas Stach + */ + +#include +#include +#include +#include +#include +#include +#include + +uintptr_t ccm_base; +uintptr_t ccm_analog_base; + +static struct clk_parent_data pll_ref_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "osc_27m", + }, + { + .name = "hdmi_phy_27m", + }, + { + .name = "dummy", + }, +}; + +static struct clk_parent_data arm_pll_bypass_sels[] = { + { + .name = "arm_pll", + }, + { + .name = "arm_pll_ref_sel", + }, +}; + +static struct clk_parent_data gpu_pll_bypass_sels[] = { + { + .name = "gpu_pll", + }, + { + .name = "gpu_pll_ref_sel", + }, +}; + +static struct clk_parent_data vpu_pll_bypass_sels[] = { + { + .name = "vpu_pll", + }, + { + .name = "vpu_pll_ref_sel", + }, +}; + +static struct clk_parent_data audio_pll1_bypass_sels[] = { + { + .name = "audio_pll1", + }, + { + .name = "audio_pll1_ref_sel", + }, +}; + +static struct clk_parent_data audio_pll2_bypass_sels[] = { + { + .name = "audio_pll2", + }, + { + .name = "audio_pll2_ref_sel", + }, +}; + +static struct clk_parent_data video_pll1_bypass_sels[] = { + { + .name = "video_pll1", + }, + { + .name = "video_pll1_ref_sel", + }, +}; + +static struct clk_parent_data sys3_pll_out_sels[] = { + { + .name = "sys3_pll1_ref_sel", + }, +}; + +static struct clk_parent_data dram_pll_out_sels[] = { + { + .name = "dram_pll1_ref_sel", + }, +}; + +static struct clk_parent_data video2_pll_out_sels[] = { + { + .name = "video2_pll1_ref_sel", + }, +}; + +static struct clk_parent_data imx8mq_a53_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "arm_pll_out", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "sys3_pll_out", + }, +}; + +static struct clk_parent_data imx8mq_a53_core_sels[] = { + { + .name = "arm_a53_div", + }, + { + .name = "arm_pll_out", + }, +}; + +static struct clk_parent_data imx8mq_arm_m4_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys3_pll_out", + }, +}; + +static struct clk_parent_data imx8mq_vpu_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "arm_pll_out", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "vpu_pll_out", + }, +}; + +static struct clk_parent_data imx8mq_gpu_core_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "gpu_pll_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_gpu_shader_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "gpu_pll_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_main_axi_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_333m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_100m", + }, +}; + +static struct clk_parent_data imx8mq_enet_axi_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys3_pll_out", + }, +}; + +static struct clk_parent_data imx8mq_nand_usdhc_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "audio_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_vpu_bus_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_100m", + }, +}; + +static struct clk_parent_data imx8mq_disp_axi_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "clk_ext1", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_disp_apb_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "clk_ext1", + }, + { + .name = "clk_ext3", + }, +}; + +static struct clk_parent_data imx8mq_disp_rtrm_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, +}; + +static struct clk_parent_data imx8mq_usb_bus_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext4", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_gpu_axi_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "gpu_pll_out", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_gpu_ahb_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "gpu_pll_out", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_noc_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_noc_apb_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_333m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_ahb_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_audio_ahb_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys2_pll_166m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_dsi_ahb_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_dram_alt_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys1_pll_100m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "sys1_pll_266m", + }, +}; + +static struct clk_parent_data imx8mq_dram_apb_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_vpu_g1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys1_pll_100m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_vpu_g2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys1_pll_100m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_disp_dtrc_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_disp_dc8000_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_pcie1_ctrl_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys2_pll_333m", + }, + { + .name = "sys3_pll_out", + }, +}; + +static struct clk_parent_data imx8mq_pcie1_phy_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "clk_ext1", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_pcie1_aux_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys2_pll_50m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_200m", + }, +}; + +static struct clk_parent_data imx8mq_dc_pixel_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_lcdif_pixel_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_sai1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext1", + }, + { + .name = "clk_ext2", + }, +}; + +static struct clk_parent_data imx8mq_sai2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, +}; + +static struct clk_parent_data imx8mq_sai3_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext3", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_sai4_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext1", + }, + { + .name = "clk_ext2", + }, +}; + +static struct clk_parent_data imx8mq_sai5_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, +}; + +static struct clk_parent_data imx8mq_sai6_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext3", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_spdif1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, +}; + +static struct clk_parent_data imx8mq_spdif2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "osc_27m", + }, + { + .name = "clk_ext3", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_enet_ref_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "clk_ext4", + }, +}; + +static struct clk_parent_data imx8mq_enet_timer_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "clk_ext1", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "clk_ext4", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_enet_phy_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_50m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_nand_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_qspi_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys1_pll_100m", + }, +}; + +static struct clk_parent_data imx8mq_usdhc1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys1_pll_100m", + }, +}; + +static struct clk_parent_data imx8mq_usdhc2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys1_pll_100m", + }, +}; + +static struct clk_parent_data imx8mq_i2c1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys2_pll_50m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys1_pll_133m", + }, +}; + +static struct clk_parent_data imx8mq_i2c2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys2_pll_50m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys1_pll_133m", + }, +}; + +static struct clk_parent_data imx8mq_i2c3_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys2_pll_50m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys1_pll_133m", + }, +}; + +static struct clk_parent_data imx8mq_i2c4_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys2_pll_50m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys1_pll_133m", + }, +}; + +static struct clk_parent_data imx8mq_uart1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext4", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_uart2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_uart3_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext4", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_uart4_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_usb_core_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_100m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_usb_phy_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_100m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_gic_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_ecspi1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_ecspi2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_pwm1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext1", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_pwm2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext1", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_pwm3_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext2", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_pwm4_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext2", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_gpt1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "clk_ext1", + }, +}; + +static struct clk_parent_data imx8mq_wdog_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_133m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys2_pll_166m", + }, +}; + +static struct clk_parent_data imx8mq_wrclk_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys1_pll_100m", + }, +}; + +static struct clk_parent_data imx8mq_dsi_core_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_dsi_phy_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "clk_ext2", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_dsi_dbi_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_dsi_esc_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_csi1_core_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_csi1_phy_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "clk_ext2", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_csi1_esc_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_csi2_core_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_csi2_phy_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_125m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "clk_ext2", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "video_pll1_out", + }, +}; + +static struct clk_parent_data imx8mq_csi2_esc_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_1000m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "clk_ext3", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_pcie2_ctrl_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_266m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "sys2_pll_333m", + }, + { + .name = "sys3_pll_out", + }, +}; + +static struct clk_parent_data imx8mq_pcie2_phy_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "clk_ext1", + }, + { + .name = "clk_ext2", + }, + { + .name = "clk_ext3", + }, + { + .name = "clk_ext4", + }, + { + .name = "sys1_pll_400m", + }, +}; + +static struct clk_parent_data imx8mq_pcie2_aux_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys2_pll_50m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_100m", + }, + { + .name = "sys1_pll_80m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_200m", + }, +}; + +static struct clk_parent_data imx8mq_ecspi3_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_40m", + }, + { + .name = "sys1_pll_160m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "sys2_pll_250m", + }, + { + .name = "audio_pll2_out", + }, +}; + +static struct clk_parent_data imx8mq_dram_core_sels[] = { + { + .name = "dram_pll_out", + }, + { + .name = "dram_alt_root", + }, +}; + +static struct clk_parent_data imx8mq_clko1_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys1_pll_800m", + }, + { + .name = "osc_27m", + }, + { + .name = "sys1_pll_200m", + }, + { + .name = "audio_pll2_out", + }, + { + .name = "sys2_pll_500m", + }, + { + .name = "vpu_pll_out", + }, + { + .name = "sys1_pll_80m", + }, +}; + +static struct clk_parent_data imx8mq_clko2_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "sys2_pll_200m", + }, + { + .name = "sys1_pll_400m", + }, + { + .name = "sys2_pll_166m", + }, + { + .name = "sys3_pll_out", + }, + { + .name = "audio_pll1_out", + }, + { + .name = "video_pll1_out", + }, + { + .name = "ckil", + }, +}; + +static struct clk_parent_data pllout_monitor_sels[] = { + { + .name = "osc_25m", + }, + { + .name = "osc_27m", + }, + { + .name = "dummy", + }, + { + .name = "dummy", + }, + { + .name = "ckil", + }, + { + .name = "audio_pll1_out_monitor", + }, + { + .name = "audio_pll2_out_monitor", + }, + { + .name = "video_pll1_out_monitor", + }, + { + .name = "gpu_pll_out_monitor", + }, + { + .name = "vpu_pll_out_monitor", + }, + { + .name = "arm_pll_out_monitor", + }, + { + .name = "sys_pll1_out_monitor", + }, + { + .name = "sys_pll2_out_monitor", + }, + { + .name = "sys_pll3_out_monitor", + }, + { + .name = "dram_pll_out_monitor", + }, + { + .name = "video_pll2_out_monitor", + }, +}; + +static IMX_CLK_SOURCE(dummy, 0); +static IMX_CLK_SOURCE(ckil, 0x8000); +static IMX_CLK_SOURCE(osc_25m, 0x17d7840); +static IMX_CLK_SOURCE(osc_27m, 0x19bfcc0); +static IMX_CLK_SOURCE(clk_ext1, 0x7ed6b40); +static IMX_CLK_SOURCE(clk_ext2, 0x7ed6b40); +static IMX_CLK_SOURCE(clk_ext3, 0x7ed6b40); +static IMX_CLK_SOURCE(clk_ext4, 0x7ed6b40); + +static IMX_CLK_MUX(arm_pll_ref_sel, CCM_ANALOG_BASE, 0x28, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(gpu_pll_ref_sel, CCM_ANALOG_BASE, 0x18, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(vpu_pll_ref_sel, CCM_ANALOG_BASE, 0x20, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(audio_pll1_ref_sel, CCM_ANALOG_BASE, 0x0, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(audio_pll2_ref_sel, CCM_ANALOG_BASE, 0x8, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(video_pll1_ref_sel, CCM_ANALOG_BASE, 0x10, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(sys3_pll1_ref_sel, CCM_ANALOG_BASE, 0x48, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(dram_pll1_ref_sel, CCM_ANALOG_BASE, 0x60, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +static IMX_CLK_MUX(video2_pll1_ref_sel, CCM_ANALOG_BASE, 0x54, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + +static IMX_CLK_DIV(arm_pll_ref_div, { &arm_pll_ref_sel }, CCM_ANALOG_BASE, 0x28, 5, 6); +static IMX_CLK_DIV(gpu_pll_ref_div, { &gpu_pll_ref_sel }, CCM_ANALOG_BASE, 0x18, 5, 6); +static IMX_CLK_DIV(vpu_pll_ref_div, { &vpu_pll_ref_sel }, CCM_ANALOG_BASE, 0x20, 5, 6); +static IMX_CLK_DIV(audio_pll1_ref_div, { &audio_pll1_ref_sel }, CCM_ANALOG_BASE, 0x0, 5, 6); +static IMX_CLK_DIV(audio_pll2_ref_div, { &audio_pll2_ref_sel }, CCM_ANALOG_BASE, 0x8, 5, 6); +static IMX_CLK_DIV(video_pll1_ref_div, { &video_pll1_ref_sel }, CCM_ANALOG_BASE, 0x10, 5, 6); + +static IMX_CLK_FRAC_PLL(arm_pll, { &arm_pll_ref_div }, CCM_ANALOG_BASE, 0x28); +static IMX_CLK_FRAC_PLL(gpu_pll, { &gpu_pll_ref_div }, CCM_ANALOG_BASE, 0x18); +static IMX_CLK_FRAC_PLL(vpu_pll, { &vpu_pll_ref_div }, CCM_ANALOG_BASE, 0x20); +static IMX_CLK_FRAC_PLL(audio_pll1, { &audio_pll1_ref_div }, CCM_ANALOG_BASE, 0x0); +static IMX_CLK_FRAC_PLL(audio_pll2, { &audio_pll2_ref_div }, CCM_ANALOG_BASE, 0x8); +static IMX_CLK_FRAC_PLL(video_pll1, { &video_pll1_ref_div }, CCM_ANALOG_BASE, 0x10); + +/* PLL bypass out */ +static IMX_CLK_MUX_FLAGS(arm_pll_bypass, CCM_ANALOG_BASE, 0x28, 14, 1, arm_pll_bypass_sels, + ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT); +static IMX_CLK_MUX(gpu_pll_bypass, CCM_ANALOG_BASE, 0x18, 14, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels)); +static IMX_CLK_MUX(vpu_pll_bypass, CCM_ANALOG_BASE, 0x20, 14, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels)); +static IMX_CLK_MUX(audio_pll1_bypass, CCM_ANALOG_BASE, 0x0, 14, 1, audio_pll1_bypass_sels, + ARRAY_SIZE(audio_pll1_bypass_sels)); +static IMX_CLK_MUX(audio_pll2_bypass, CCM_ANALOG_BASE, 0x8, 14, 1, audio_pll2_bypass_sels, + ARRAY_SIZE(audio_pll2_bypass_sels)); +static IMX_CLK_MUX(video_pll1_bypass, CCM_ANALOG_BASE, 0x10, 14, 1, video_pll1_bypass_sels, + ARRAY_SIZE(video_pll1_bypass_sels)); + +/* PLL OUT GATE */ +static IMX_CLK_GATE(arm_pll_out, { &arm_pll_bypass }, CCM_ANALOG_BASE, 0x28, 21); +static IMX_CLK_GATE(gpu_pll_out, { &gpu_pll_bypass }, CCM_ANALOG_BASE, 0x18, 21); +static IMX_CLK_GATE(vpu_pll_out, { &vpu_pll_bypass }, CCM_ANALOG_BASE, 0x20, 21); +static IMX_CLK_GATE(audio_pll1_out, { &audio_pll1_bypass }, CCM_ANALOG_BASE, 0x0, 21); +static IMX_CLK_GATE(audio_pll2_out, { &audio_pll2_bypass }, CCM_ANALOG_BASE, 0x8, 21); +static IMX_CLK_GATE(video_pll1_out, { &video_pll1_bypass }, CCM_ANALOG_BASE, 0x10, 21); + +static IMX_CLK_FIXED(sys1_pll_out, 800000000); +static IMX_CLK_FIXED(sys2_pll_out, 1000000000); +static IMX_CLK_SSCG_PLL(sys3_pll_out, sys3_pll_out_sels, ARRAY_SIZE(sys3_pll_out_sels), 0, 0, 0, CCM_ANALOG_BASE, 0x48, + CLK_IS_CRITICAL); +static IMX_CLK_SSCG_PLL(dram_pll_out, dram_pll_out_sels, ARRAY_SIZE(dram_pll_out_sels), 0, 0, 0, CCM_ANALOG_BASE, 0x60, + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); +static IMX_CLK_SSCG_PLL(video2_pll_out, video2_pll_out_sels, ARRAY_SIZE(video2_pll_out_sels), 0, 0, 0, CCM_ANALOG_BASE, + 0x54, 0); + +/* SYS PLL1 fixed output */ +static IMX_CLK_FIXED_FACTOR(sys1_pll_40m, { &sys1_pll_out }, 1, 20); +static IMX_CLK_FIXED_FACTOR(sys1_pll_80m, { &sys1_pll_out }, 1, 10); +static IMX_CLK_FIXED_FACTOR(sys1_pll_100m, { &sys1_pll_out }, 1, 8); +static IMX_CLK_FIXED_FACTOR(sys1_pll_133m, { &sys1_pll_out }, 1, 6); +static IMX_CLK_FIXED_FACTOR(sys1_pll_160m, { &sys1_pll_out }, 1, 5); +static IMX_CLK_FIXED_FACTOR(sys1_pll_200m, { &sys1_pll_out }, 1, 4); +static IMX_CLK_FIXED_FACTOR(sys1_pll_266m, { &sys1_pll_out }, 1, 3); +static IMX_CLK_FIXED_FACTOR(sys1_pll_400m, { &sys1_pll_out }, 1, 2); +static IMX_CLK_FIXED_FACTOR(sys1_pll_800m, { &sys1_pll_out }, 1, 1); + +/* SYS PLL2 fixed output */ +static IMX_CLK_FIXED_FACTOR(sys2_pll_50m, { &sys2_pll_out }, 1, 20); +static IMX_CLK_FIXED_FACTOR(sys2_pll_100m, { &sys2_pll_out }, 1, 10); +static IMX_CLK_FIXED_FACTOR(sys2_pll_125m, { &sys2_pll_out }, 1, 8); +static IMX_CLK_FIXED_FACTOR(sys2_pll_166m, { &sys2_pll_out }, 1, 6); +static IMX_CLK_FIXED_FACTOR(sys2_pll_200m, { &sys2_pll_out }, 1, 5); +static IMX_CLK_FIXED_FACTOR(sys2_pll_250m, { &sys2_pll_out }, 1, 4); +static IMX_CLK_FIXED_FACTOR(sys2_pll_333m, { &sys2_pll_out }, 1, 3); +static IMX_CLK_FIXED_FACTOR(sys2_pll_500m, { &sys2_pll_out }, 1, 2); +static IMX_CLK_FIXED_FACTOR(sys2_pll_1000m, { &sys2_pll_out }, 1, 1); + +static IMX_CLK_DIV(audio_pll1_out_monitor, { &audio_pll1_bypass }, CCM_ANALOG_BASE, 0x78, 0, 3); +static IMX_CLK_DIV(audio_pll2_out_monitor, { &audio_pll2_bypass }, CCM_ANALOG_BASE, 0x78, 4, 3); +static IMX_CLK_DIV(video_pll1_out_monitor, { &video_pll1_bypass }, CCM_ANALOG_BASE, 0x78, 8, 3); +static IMX_CLK_DIV(gpu_pll_out_monitor, { &gpu_pll_bypass }, CCM_ANALOG_BASE, 0x78, 12, 3); +static IMX_CLK_DIV(vpu_pll_out_monitor, { &vpu_pll_bypass }, CCM_ANALOG_BASE, 0x78, 16, 3); +static IMX_CLK_DIV(arm_pll_out_monitor, { &arm_pll_bypass }, CCM_ANALOG_BASE, 0x78, 20, 3); +static IMX_CLK_DIV(sys_pll1_out_monitor, { &sys1_pll_out }, CCM_ANALOG_BASE, 0x7c, 0, 3); +static IMX_CLK_DIV(sys_pll2_out_monitor, { &sys2_pll_out }, CCM_ANALOG_BASE, 0x7c, 4, 3); +static IMX_CLK_DIV(sys_pll3_out_monitor, { &sys3_pll_out }, CCM_ANALOG_BASE, 0x7c, 8, 3); +static IMX_CLK_DIV(dram_pll_out_monitor, { &dram_pll_out }, CCM_ANALOG_BASE, 0x7c, 12, 3); +static IMX_CLK_DIV(video_pll2_out_monitor, { &video2_pll_out }, CCM_ANALOG_BASE, 0x7c, 16, 3); +static IMX_CLK_MUX(pllout_monitor_sel, CCM_ANALOG_BASE, 0x74, 0, 4, pllout_monitor_sels, + ARRAY_SIZE(pllout_monitor_sels)); +static IMX_CLK_GATE(pllout_monitor_clk2, { &pllout_monitor_sel }, CCM_ANALOG_BASE, 0x74, 4); + +/* CORE */ +static IMX_CLK_COMPOSITE_CORE(arm_a53_div, imx8mq_a53_sels, CCM_BASE, 0x8000); + +static IMX_CLK_COMPOSITE_CORE(arm_m4_core, imx8mq_arm_m4_sels, CCM_BASE, 0x8080); +static IMX_CLK_COMPOSITE_CORE(vpu_core, imx8mq_vpu_sels, CCM_BASE, 0x8100); +static IMX_CLK_COMPOSITE_CORE(gpu_core, imx8mq_gpu_core_sels, CCM_BASE, 0x8180); +static IMX_CLK_COMPOSITE(gpu_shader, imx8mq_gpu_shader_sels, CCM_BASE, 0x8200); + +/* CORE SEL */ +static IMX_CLK_MUX2(arm_a53_core, CCM_BASE, 0x9880, 24, 1, imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels)); + +/* BUS */ +static IMX_CLK_COMPOSITE_BUS(main_axi, imx8mq_main_axi_sels, CCM_BASE, 0x8800); +static IMX_CLK_COMPOSITE_BUS(enet_axi, imx8mq_enet_axi_sels, CCM_BASE, 0x8880); +static IMX_CLK_COMPOSITE_BUS(nand_usdhc_bus, imx8mq_nand_usdhc_sels, CCM_BASE, 0x8900); +static IMX_CLK_COMPOSITE_BUS(vpu_bus, imx8mq_vpu_bus_sels, CCM_BASE, 0x8980); +static IMX_CLK_COMPOSITE_BUS(disp_axi, imx8mq_disp_axi_sels, CCM_BASE, 0x8a00); +static IMX_CLK_COMPOSITE_BUS(disp_apb, imx8mq_disp_apb_sels, CCM_BASE, 0x8a80); +static IMX_CLK_COMPOSITE_BUS(disp_rtrm, imx8mq_disp_rtrm_sels, CCM_BASE, 0x8b00); +static IMX_CLK_COMPOSITE_BUS(usb_bus, imx8mq_usb_bus_sels, CCM_BASE, 0x8b80); +static IMX_CLK_COMPOSITE_BUS(gpu_axi, imx8mq_gpu_axi_sels, CCM_BASE, 0x8c00); +static IMX_CLK_COMPOSITE_BUS(gpu_ahb, imx8mq_gpu_ahb_sels, CCM_BASE, 0x8c80); +static IMX_CLK_COMPOSITE_BUS(noc, imx8mq_noc_sels, CCM_BASE, 0x8d00); +static IMX_CLK_COMPOSITE_BUS(noc_apb, imx8mq_noc_apb_sels, CCM_BASE, 0x8d80); + +/* AHB */ +/* AHB clock is used by the AHB bus therefore marked as critical */ +static IMX_CLK_COMPOSITE_BUS(ahb, imx8mq_ahb_sels, CCM_BASE, 0x9000); +static IMX_CLK_COMPOSITE_BUS(audio_ahb, imx8mq_audio_ahb_sels, CCM_BASE, 0x9100); + +/* IPG */ +static IMX_CLK_DIV2(ipg_root, { &ahb }, CCM_BASE, 0x9080, 0, 1); +static IMX_CLK_DIV2(ipg_audio_root, { &audio_ahb }, CCM_BASE, 0x9180, 0, 1); + +/* + * DRAM clocks are manipulated from TF-A outside clock framework. + * The fw_managed helper sets GET_RATE_NOCACHE and clears SET_PARENT_GATE + * as div value should always be read from hardware + */ +static IMX_CLK_MUX2_FLAGS(dram_core_clk, CCM_BASE, 0x9800, 24, 1, imx8mq_dram_core_sels, + ARRAY_SIZE(imx8mq_dram_core_sels), CLK_IS_CRITICAL); +static IMX_CLK_COMPOSITE_FW_MANAGED(dram_alt, imx8mq_dram_alt_sels, CCM_BASE, 0xa000); +static IMX_CLK_COMPOSITE_FW_MANAGED_CRITICAL(dram_apb, imx8mq_dram_apb_sels, CCM_BASE, 0xa080); + +/* IP */ +static IMX_CLK_COMPOSITE(vpu_g1, imx8mq_vpu_g1_sels, CCM_BASE, 0xa100); +static IMX_CLK_COMPOSITE(vpu_g2, imx8mq_vpu_g2_sels, CCM_BASE, 0xa180); +static IMX_CLK_COMPOSITE(disp_dtrc, imx8mq_disp_dtrc_sels, CCM_BASE, 0xa200); +static IMX_CLK_COMPOSITE(disp_dc8000, imx8mq_disp_dc8000_sels, CCM_BASE, 0xa280); +static IMX_CLK_COMPOSITE(pcie1_ctrl, imx8mq_pcie1_ctrl_sels, CCM_BASE, 0xa300); +static IMX_CLK_COMPOSITE(pcie1_phy, imx8mq_pcie1_phy_sels, CCM_BASE, 0xa380); +static IMX_CLK_COMPOSITE(pcie1_aux, imx8mq_pcie1_aux_sels, CCM_BASE, 0xa400); +static IMX_CLK_COMPOSITE(dc_pixel, imx8mq_dc_pixel_sels, CCM_BASE, 0xa480); +static IMX_CLK_COMPOSITE(lcdif_pixel, imx8mq_lcdif_pixel_sels, CCM_BASE, 0xa500); +static IMX_CLK_COMPOSITE(sai1, imx8mq_sai1_sels, CCM_BASE, 0xa580); +static IMX_CLK_COMPOSITE(sai2, imx8mq_sai2_sels, CCM_BASE, 0xa600); +static IMX_CLK_COMPOSITE(sai3, imx8mq_sai3_sels, CCM_BASE, 0xa680); +static IMX_CLK_COMPOSITE(sai4, imx8mq_sai4_sels, CCM_BASE, 0xa700); +static IMX_CLK_COMPOSITE(sai5, imx8mq_sai5_sels, CCM_BASE, 0xa780); +static IMX_CLK_COMPOSITE(sai6, imx8mq_sai6_sels, CCM_BASE, 0xa800); +static IMX_CLK_COMPOSITE(spdif1, imx8mq_spdif1_sels, CCM_BASE, 0xa880); +static IMX_CLK_COMPOSITE(spdif2, imx8mq_spdif2_sels, CCM_BASE, 0xa900); +static IMX_CLK_COMPOSITE(enet_ref, imx8mq_enet_ref_sels, CCM_BASE, 0xa980); +static IMX_CLK_COMPOSITE(enet_timer, imx8mq_enet_timer_sels, CCM_BASE, 0xaa00); +static IMX_CLK_COMPOSITE(enet_phy, imx8mq_enet_phy_sels, CCM_BASE, 0xaa80); +static IMX_CLK_COMPOSITE(nand, imx8mq_nand_sels, CCM_BASE, 0xab00); +static IMX_CLK_COMPOSITE(qspi, imx8mq_qspi_sels, CCM_BASE, 0xab80); +static IMX_CLK_COMPOSITE(usdhc1, imx8mq_usdhc1_sels, CCM_BASE, 0xac00); +static IMX_CLK_COMPOSITE(usdhc2, imx8mq_usdhc2_sels, CCM_BASE, 0xac80); +static IMX_CLK_COMPOSITE(i2c1, imx8mq_i2c1_sels, CCM_BASE, 0xad00); +static IMX_CLK_COMPOSITE(i2c2, imx8mq_i2c2_sels, CCM_BASE, 0xad80); +static IMX_CLK_COMPOSITE(i2c3, imx8mq_i2c3_sels, CCM_BASE, 0xae00); +static IMX_CLK_COMPOSITE(i2c4, imx8mq_i2c4_sels, CCM_BASE, 0xae80); +static IMX_CLK_COMPOSITE(uart1, imx8mq_uart1_sels, CCM_BASE, 0xaf00); +static IMX_CLK_COMPOSITE(uart2, imx8mq_uart2_sels, CCM_BASE, 0xaf80); +static IMX_CLK_COMPOSITE(uart3, imx8mq_uart3_sels, CCM_BASE, 0xb000); +static IMX_CLK_COMPOSITE(uart4, imx8mq_uart4_sels, CCM_BASE, 0xb080); +static IMX_CLK_COMPOSITE(usb_core_ref, imx8mq_usb_core_sels, CCM_BASE, 0xb100); +static IMX_CLK_COMPOSITE(usb_phy_ref, imx8mq_usb_phy_sels, CCM_BASE, 0xb180); +static IMX_CLK_COMPOSITE(gic, imx8mq_gic_sels, CCM_BASE, 0xb200); +static IMX_CLK_COMPOSITE(ecspi1, imx8mq_ecspi1_sels, CCM_BASE, 0xb280); +static IMX_CLK_COMPOSITE(ecspi2, imx8mq_ecspi2_sels, CCM_BASE, 0xb300); +static IMX_CLK_COMPOSITE(pwm1, imx8mq_pwm1_sels, CCM_BASE, 0xb380); +static IMX_CLK_COMPOSITE(pwm2, imx8mq_pwm2_sels, CCM_BASE, 0xb400); +static IMX_CLK_COMPOSITE(pwm3, imx8mq_pwm3_sels, CCM_BASE, 0xb480); +static IMX_CLK_COMPOSITE(pwm4, imx8mq_pwm4_sels, CCM_BASE, 0xb500); +static IMX_CLK_COMPOSITE(gpt1, imx8mq_gpt1_sels, CCM_BASE, 0xb580); +static IMX_CLK_COMPOSITE(wdog, imx8mq_wdog_sels, CCM_BASE, 0xb900); +static IMX_CLK_COMPOSITE(wrclk, imx8mq_wrclk_sels, CCM_BASE, 0xb980); +static IMX_CLK_COMPOSITE(clko1, imx8mq_clko1_sels, CCM_BASE, 0xba00); +static IMX_CLK_COMPOSITE(clko2, imx8mq_clko2_sels, CCM_BASE, 0xba80); +static IMX_CLK_COMPOSITE(dsi_core, imx8mq_dsi_core_sels, CCM_BASE, 0xbb00); +static IMX_CLK_COMPOSITE(dsi_phy_ref, imx8mq_dsi_phy_sels, CCM_BASE, 0xbb80); +static IMX_CLK_COMPOSITE(dsi_dbi, imx8mq_dsi_dbi_sels, CCM_BASE, 0xbc00); +static IMX_CLK_COMPOSITE(dsi_esc, imx8mq_dsi_esc_sels, CCM_BASE, 0xbc80); +static IMX_CLK_COMPOSITE(dsi_ahb, imx8mq_dsi_ahb_sels, CCM_BASE, 0x9200); +static IMX_CLK_DIV2(dsi_ipg_div, { &dsi_ahb }, CCM_BASE, 0x9280, 0, 6); +static IMX_CLK_COMPOSITE(csi1_core, imx8mq_csi1_core_sels, CCM_BASE, 0xbd00); +static IMX_CLK_COMPOSITE(csi1_phy_ref, imx8mq_csi1_phy_sels, CCM_BASE, 0xbd80); +static IMX_CLK_COMPOSITE(csi1_esc, imx8mq_csi1_esc_sels, CCM_BASE, 0xbe00); +static IMX_CLK_COMPOSITE(csi2_core, imx8mq_csi2_core_sels, CCM_BASE, 0xbe80); +static IMX_CLK_COMPOSITE(csi2_phy_ref, imx8mq_csi2_phy_sels, CCM_BASE, 0xbf00); +static IMX_CLK_COMPOSITE(csi2_esc, imx8mq_csi2_esc_sels, CCM_BASE, 0xbf80); +static IMX_CLK_COMPOSITE(pcie2_ctrl, imx8mq_pcie2_ctrl_sels, CCM_BASE, 0xc000); +static IMX_CLK_COMPOSITE(pcie2_phy, imx8mq_pcie2_phy_sels, CCM_BASE, 0xc080); +static IMX_CLK_COMPOSITE(pcie2_aux, imx8mq_pcie2_aux_sels, CCM_BASE, 0xc100); +static IMX_CLK_COMPOSITE(ecspi3, imx8mq_ecspi3_sels, CCM_BASE, 0xc180); + +static IMX_CLK_GATE4(ecspi1_root_clk, { &ecspi1 }, CCM_BASE, 0x4070, 0); +static IMX_CLK_GATE4(ecspi2_root_clk, { &ecspi2 }, CCM_BASE, 0x4080, 0); +static IMX_CLK_GATE4(ecspi3_root_clk, { &ecspi3 }, CCM_BASE, 0x4090, 0); +static IMX_CLK_GATE4(enet1_root_clk, { &enet_axi }, CCM_BASE, 0x40a0, 0); +static IMX_CLK_GATE4(gpio1_root_clk, { &ipg_root }, CCM_BASE, 0x40b0, 0); +static IMX_CLK_GATE4(gpio2_root_clk, { &ipg_root }, CCM_BASE, 0x40c0, 0); +static IMX_CLK_GATE4(gpio3_root_clk, { &ipg_root }, CCM_BASE, 0x40d0, 0); +static IMX_CLK_GATE4(gpio4_root_clk, { &ipg_root }, CCM_BASE, 0x40e0, 0); +static IMX_CLK_GATE4(gpio5_root_clk, { &ipg_root }, CCM_BASE, 0x40f0, 0); +static IMX_CLK_GATE4(gpt1_root_clk, { &gpt1 }, CCM_BASE, 0x4100, 0); +static IMX_CLK_GATE4(i2c1_root_clk, { &i2c1 }, CCM_BASE, 0x4170, 0); +static IMX_CLK_GATE4(i2c2_root_clk, { &i2c2 }, CCM_BASE, 0x4180, 0); +static IMX_CLK_GATE4(i2c3_root_clk, { &i2c3 }, CCM_BASE, 0x4190, 0); +static IMX_CLK_GATE4(i2c4_root_clk, { &i2c4 }, CCM_BASE, 0x41a0, 0); +static IMX_CLK_GATE4(mu_root_clk, { &ipg_root }, CCM_BASE, 0x4210, 0); +static IMX_CLK_GATE4(ocotp_root_clk, { &ipg_root }, CCM_BASE, 0x4220, 0); +static IMX_CLK_GATE4(pcie1_root_clk, { &pcie1_ctrl }, CCM_BASE, 0x4250, 0); +static IMX_CLK_GATE4(pcie2_root_clk, { &pcie2_ctrl }, CCM_BASE, 0x4640, 0); +static IMX_CLK_GATE4(pwm1_root_clk, { &pwm1 }, CCM_BASE, 0x4280, 0); +static IMX_CLK_GATE4(pwm2_root_clk, { &pwm2 }, CCM_BASE, 0x4290, 0); +static IMX_CLK_GATE4(pwm3_root_clk, { &pwm3 }, CCM_BASE, 0x42a0, 0); +static IMX_CLK_GATE4(pwm4_root_clk, { &pwm4 }, CCM_BASE, 0x42b0, 0); +static IMX_CLK_GATE4(qspi_root_clk, { &qspi }, CCM_BASE, 0x42f0, 0); + +static IMX_CLK_GATE2_SHARED2(nand_root_clk, { &nand }, CCM_BASE, 0x4300, 0, &share_count_nand); +static IMX_CLK_GATE2_SHARED2(nand_usdhc_rawnand_clk, { &nand_usdhc_bus }, CCM_BASE, 0x4300, 0, &share_count_nand); +static IMX_CLK_GATE2_SHARED2(sai1_root_clk, { &sai1 }, CCM_BASE, 0x4330, 0, &share_count_sai1); +static IMX_CLK_GATE2_SHARED2(sai1_ipg_clk, { &ipg_audio_root }, CCM_BASE, 0x4330, 0, &share_count_sai1); +static IMX_CLK_GATE2_SHARED2(sai2_root_clk, { &sai2 }, CCM_BASE, 0x4340, 0, &share_count_sai2); +static IMX_CLK_GATE2_SHARED2(sai2_ipg_clk, { &ipg_root }, CCM_BASE, 0x4340, 0, &share_count_sai2); +static IMX_CLK_GATE2_SHARED2(sai3_root_clk, { &sai3 }, CCM_BASE, 0x4350, 0, &share_count_sai3); +static IMX_CLK_GATE2_SHARED2(sai3_ipg_clk, { &ipg_root }, CCM_BASE, 0x4350, 0, &share_count_sai3); +static IMX_CLK_GATE2_SHARED2(sai4_root_clk, { &sai4 }, CCM_BASE, 0x4360, 0, &share_count_sai4); +static IMX_CLK_GATE2_SHARED2(sai4_ipg_clk, { &ipg_audio_root }, CCM_BASE, 0x4360, 0, &share_count_sai4); +static IMX_CLK_GATE2_SHARED2(sai5_root_clk, { &sai5 }, CCM_BASE, 0x4370, 0, &share_count_sai5); +static IMX_CLK_GATE2_SHARED2(sai5_ipg_clk, { &ipg_audio_root }, CCM_BASE, 0x4370, 0, &share_count_sai5); +static IMX_CLK_GATE2_SHARED2(sai6_root_clk, { &sai6 }, CCM_BASE, 0x4380, 0, &share_count_sai6); +static IMX_CLK_GATE2_SHARED2(sai6_ipg_clk, { &ipg_audio_root }, CCM_BASE, 0x4380, 0, &share_count_sai6); +static IMX_CLK_GATE4(uart1_root_clk, { &uart1 }, CCM_BASE, 0x4490, 0); +static IMX_CLK_GATE4(uart2_root_clk, { &uart2 }, CCM_BASE, 0x44a0, 0); +static IMX_CLK_GATE4(uart3_root_clk, { &uart3 }, CCM_BASE, 0x44b0, 0); +static IMX_CLK_GATE4(uart4_root_clk, { &uart4 }, CCM_BASE, 0x44c0, 0); +static IMX_CLK_GATE4(usb1_ctrl_root_clk, { &usb_bus }, CCM_BASE, 0x44d0, 0); +static IMX_CLK_GATE4(usb2_ctrl_root_clk, { &usb_bus }, CCM_BASE, 0x44e0, 0); +static IMX_CLK_GATE4(usb1_phy_root_clk, { &usb_phy_ref }, CCM_BASE, 0x44f0, 0); +static IMX_CLK_GATE4(usb2_phy_root_clk, { &usb_phy_ref }, CCM_BASE, 0x4500, 0); +static IMX_CLK_GATE4(usdhc1_root_clk, { &usdhc1 }, CCM_BASE, 0x4510, 0); +static IMX_CLK_GATE4(usdhc2_root_clk, { &usdhc2 }, CCM_BASE, 0x4520, 0); +static IMX_CLK_GATE4(wdog1_root_clk, { &wdog }, CCM_BASE, 0x4530, 0); +static IMX_CLK_GATE4(wdog2_root_clk, { &wdog }, CCM_BASE, 0x4540, 0); +static IMX_CLK_GATE4(wdog3_root_clk, { &wdog }, CCM_BASE, 0x4550, 0); +static IMX_CLK_GATE2_FLAGS(vpu_g1_root_clk, { &vpu_g1 }, CCM_BASE, 0x4560, 0, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); +static IMX_CLK_GATE4(gpu_root_clk, { &gpu_core }, CCM_BASE, 0x4570, 0); +static IMX_CLK_GATE2_FLAGS(vpu_g2_root_clk, { &vpu_g2 }, CCM_BASE, 0x45a0, 0, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); +static IMX_CLK_GATE2_SHARED2(disp_root_clk, { &disp_dc8000 }, CCM_BASE, 0x45d0, 0, &share_count_dcss); +static IMX_CLK_GATE2_SHARED2(disp_axi_root_clk, { &disp_axi }, CCM_BASE, 0x45d0, 0, &share_count_dcss); +static IMX_CLK_GATE2_SHARED2(disp_apb_root_clk, { &disp_apb }, CCM_BASE, 0x45d0, 0, &share_count_dcss); +static IMX_CLK_GATE2_SHARED2(disp_rtrm_root_clk, { &disp_rtrm }, CCM_BASE, 0x45d0, 0, &share_count_dcss); +static IMX_CLK_GATE4(tmu_root_clk, { &ipg_root }, CCM_BASE, 0x4620, 0); +static IMX_CLK_GATE2_FLAGS(vpu_dec_root_clk, { &vpu_bus }, CCM_BASE, 0x4630, 0, + CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); +static IMX_CLK_GATE4(csi1_root_clk, { &csi1_core }, CCM_BASE, 0x4650, 0); +static IMX_CLK_GATE4(csi2_root_clk, { &csi2_core }, CCM_BASE, 0x4660, 0); +static IMX_CLK_GATE4(sdma1_clk, { &ipg_root }, CCM_BASE, 0x43a0, 0); +static IMX_CLK_GATE4(sdma2_clk, { &ipg_audio_root }, CCM_BASE, 0x43b0, 0); + +static IMX_CLK_FIXED_FACTOR(gpt_3m, { &osc_25m }, 1, 8); +static IMX_CLK_FIXED_FACTOR(dram_alt_root, { &dram_alt }, 1, 4); + +/* hws[IMX8MQ_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", */ +/* hws[IMX8MQ_CLK_A53_CORE]->clk, */ +/* hws[IMX8MQ_CLK_A53_CORE]->clk, */ +/* hws[IMX8MQ_ARM_PLL_OUT]->clk, */ +/* hws[IMX8MQ_CLK_A53_DIV]->clk); */ + +static struct clk *imx8mq_clks[IMX8MQ_CLK_END] = { + [IMX8MQ_CLK_DUMMY] = &dummy, + [IMX8MQ_CLK_32K] = &ckil, + [IMX8MQ_CLK_25M] = &osc_25m, + [IMX8MQ_CLK_27M] = &osc_27m, + [IMX8MQ_CLK_EXT1] = &clk_ext1, + [IMX8MQ_CLK_EXT2] = &clk_ext2, + [IMX8MQ_CLK_EXT3] = &clk_ext3, + [IMX8MQ_CLK_EXT4] = &clk_ext4, + [IMX8MQ_ARM_PLL_REF_SEL] = &arm_pll_ref_sel, + [IMX8MQ_GPU_PLL_REF_SEL] = &gpu_pll_ref_sel, + [IMX8MQ_VPU_PLL_REF_SEL] = &vpu_pll_ref_sel, + [IMX8MQ_AUDIO_PLL1_REF_SEL] = &audio_pll1_ref_sel, + [IMX8MQ_AUDIO_PLL2_REF_SEL] = &audio_pll2_ref_sel, + [IMX8MQ_VIDEO_PLL1_REF_SEL] = &video_pll1_ref_sel, + [IMX8MQ_SYS3_PLL1_REF_SEL] = &sys3_pll1_ref_sel, + [IMX8MQ_DRAM_PLL1_REF_SEL] = &dram_pll1_ref_sel, + [IMX8MQ_VIDEO2_PLL1_REF_SEL] = &video2_pll1_ref_sel, + [IMX8MQ_ARM_PLL_REF_DIV] = &arm_pll_ref_div, + [IMX8MQ_GPU_PLL_REF_DIV] = &gpu_pll_ref_div, + [IMX8MQ_VPU_PLL_REF_DIV] = &vpu_pll_ref_div, + [IMX8MQ_AUDIO_PLL1_REF_DIV] = &audio_pll1_ref_div, + [IMX8MQ_AUDIO_PLL2_REF_DIV] = &audio_pll2_ref_div, + [IMX8MQ_VIDEO_PLL1_REF_DIV] = &video_pll1_ref_div, + [IMX8MQ_ARM_PLL] = &arm_pll, + [IMX8MQ_GPU_PLL] = &gpu_pll, + [IMX8MQ_VPU_PLL] = &vpu_pll, + [IMX8MQ_AUDIO_PLL1] = &audio_pll1, + [IMX8MQ_AUDIO_PLL2] = &audio_pll2, + [IMX8MQ_VIDEO_PLL1] = &video_pll1, + [IMX8MQ_ARM_PLL_BYPASS] = &arm_pll_bypass, + [IMX8MQ_GPU_PLL_BYPASS] = &gpu_pll_bypass, + [IMX8MQ_VPU_PLL_BYPASS] = &vpu_pll_bypass, + [IMX8MQ_AUDIO_PLL1_BYPASS] = &audio_pll1_bypass, + [IMX8MQ_AUDIO_PLL2_BYPASS] = &audio_pll2_bypass, + [IMX8MQ_VIDEO_PLL1_BYPASS] = &video_pll1_bypass, + [IMX8MQ_ARM_PLL_OUT] = &arm_pll_out, + [IMX8MQ_GPU_PLL_OUT] = &gpu_pll_out, + [IMX8MQ_VPU_PLL_OUT] = &vpu_pll_out, + [IMX8MQ_AUDIO_PLL1_OUT] = &audio_pll1_out, + [IMX8MQ_AUDIO_PLL2_OUT] = &audio_pll2_out, + [IMX8MQ_VIDEO_PLL1_OUT] = &video_pll1_out, + [IMX8MQ_SYS1_PLL_OUT] = &sys1_pll_out, + [IMX8MQ_SYS2_PLL_OUT] = &sys2_pll_out, + [IMX8MQ_SYS3_PLL_OUT] = &sys3_pll_out, + [IMX8MQ_DRAM_PLL_OUT] = &dram_pll_out, + [IMX8MQ_VIDEO2_PLL_OUT] = &video2_pll_out, + [IMX8MQ_SYS1_PLL_40M] = &sys1_pll_40m, + [IMX8MQ_SYS1_PLL_80M] = &sys1_pll_80m, + [IMX8MQ_SYS1_PLL_100M] = &sys1_pll_100m, + [IMX8MQ_SYS1_PLL_133M] = &sys1_pll_133m, + [IMX8MQ_SYS1_PLL_160M] = &sys1_pll_160m, + [IMX8MQ_SYS1_PLL_200M] = &sys1_pll_200m, + [IMX8MQ_SYS1_PLL_266M] = &sys1_pll_266m, + [IMX8MQ_SYS1_PLL_400M] = &sys1_pll_400m, + [IMX8MQ_SYS1_PLL_800M] = &sys1_pll_800m, + [IMX8MQ_SYS2_PLL_50M] = &sys2_pll_50m, + [IMX8MQ_SYS2_PLL_100M] = &sys2_pll_100m, + [IMX8MQ_SYS2_PLL_125M] = &sys2_pll_125m, + [IMX8MQ_SYS2_PLL_166M] = &sys2_pll_166m, + [IMX8MQ_SYS2_PLL_200M] = &sys2_pll_200m, + [IMX8MQ_SYS2_PLL_250M] = &sys2_pll_250m, + [IMX8MQ_SYS2_PLL_333M] = &sys2_pll_333m, + [IMX8MQ_SYS2_PLL_500M] = &sys2_pll_500m, + [IMX8MQ_SYS2_PLL_1000M] = &sys2_pll_1000m, + [IMX8MQ_CLK_MON_AUDIO_PLL1_DIV] = &audio_pll1_out_monitor, + [IMX8MQ_CLK_MON_AUDIO_PLL2_DIV] = &audio_pll2_out_monitor, + [IMX8MQ_CLK_MON_VIDEO_PLL1_DIV] = &video_pll1_out_monitor, + [IMX8MQ_CLK_MON_GPU_PLL_DIV] = &gpu_pll_out_monitor, + [IMX8MQ_CLK_MON_VPU_PLL_DIV] = &vpu_pll_out_monitor, + [IMX8MQ_CLK_MON_ARM_PLL_DIV] = &arm_pll_out_monitor, + [IMX8MQ_CLK_MON_SYS_PLL1_DIV] = &sys_pll1_out_monitor, + [IMX8MQ_CLK_MON_SYS_PLL2_DIV] = &sys_pll2_out_monitor, + [IMX8MQ_CLK_MON_SYS_PLL3_DIV] = &sys_pll3_out_monitor, + [IMX8MQ_CLK_MON_DRAM_PLL_DIV] = &dram_pll_out_monitor, + [IMX8MQ_CLK_MON_VIDEO_PLL2_DIV] = &video_pll2_out_monitor, + [IMX8MQ_CLK_MON_SEL] = &pllout_monitor_sel, + [IMX8MQ_CLK_MON_CLK2_OUT] = &pllout_monitor_clk2, + [IMX8MQ_CLK_A53_DIV] = &arm_a53_div, + [IMX8MQ_CLK_A53_CG] = &arm_a53_div, + [IMX8MQ_CLK_A53_SRC] = &arm_a53_div, + [IMX8MQ_CLK_M4_CORE] = &arm_m4_core, + [IMX8MQ_CLK_VPU_CORE] = &vpu_core, + [IMX8MQ_CLK_GPU_CORE] = &gpu_core, + [IMX8MQ_CLK_GPU_SHADER] = &gpu_shader, + [IMX8MQ_CLK_M4_SRC] = &arm_m4_core, + [IMX8MQ_CLK_M4_CG] = &arm_m4_core, + [IMX8MQ_CLK_M4_DIV] = &arm_m4_core, + [IMX8MQ_CLK_VPU_SRC] = &vpu_core, + [IMX8MQ_CLK_VPU_CG] = &vpu_core, + [IMX8MQ_CLK_VPU_DIV] = &vpu_core, + [IMX8MQ_CLK_GPU_CORE_SRC] = &gpu_core, + [IMX8MQ_CLK_GPU_CORE_CG] = &gpu_core, + [IMX8MQ_CLK_GPU_CORE_DIV] = &gpu_core, + [IMX8MQ_CLK_GPU_SHADER_SRC] = &gpu_shader, + [IMX8MQ_CLK_GPU_SHADER_CG] = &gpu_shader, + [IMX8MQ_CLK_GPU_SHADER_DIV] = &gpu_shader, + [IMX8MQ_CLK_A53_CORE] = &arm_a53_core, + [IMX8MQ_CLK_MAIN_AXI] = &main_axi, + [IMX8MQ_CLK_ENET_AXI] = &enet_axi, + [IMX8MQ_CLK_NAND_USDHC_BUS] = &nand_usdhc_bus, + [IMX8MQ_CLK_VPU_BUS] = &vpu_bus, + [IMX8MQ_CLK_DISP_AXI] = &disp_axi, + [IMX8MQ_CLK_DISP_APB] = &disp_apb, + [IMX8MQ_CLK_DISP_RTRM] = &disp_rtrm, + [IMX8MQ_CLK_USB_BUS] = &usb_bus, + [IMX8MQ_CLK_GPU_AXI] = &gpu_axi, + [IMX8MQ_CLK_GPU_AHB] = &gpu_ahb, + [IMX8MQ_CLK_NOC] = &noc, + [IMX8MQ_CLK_NOC_APB] = &noc_apb, + [IMX8MQ_CLK_AHB] = &ahb, + [IMX8MQ_CLK_AUDIO_AHB] = &audio_ahb, + [IMX8MQ_CLK_IPG_ROOT] = &ipg_root, + [IMX8MQ_CLK_IPG_AUDIO_ROOT] = &ipg_audio_root, + [IMX8MQ_CLK_DRAM_CORE] = &dram_core_clk, + [IMX8MQ_CLK_DRAM_ALT] = &dram_alt, + [IMX8MQ_CLK_DRAM_APB] = &dram_apb, + [IMX8MQ_CLK_VPU_G1] = &vpu_g1, + [IMX8MQ_CLK_VPU_G2] = &vpu_g2, + [IMX8MQ_CLK_DISP_DTRC] = &disp_dtrc, + [IMX8MQ_CLK_DISP_DC8000] = &disp_dc8000, + [IMX8MQ_CLK_PCIE1_CTRL] = &pcie1_ctrl, + [IMX8MQ_CLK_PCIE1_PHY] = &pcie1_phy, + [IMX8MQ_CLK_PCIE1_AUX] = &pcie1_aux, + [IMX8MQ_CLK_DC_PIXEL] = &dc_pixel, + [IMX8MQ_CLK_LCDIF_PIXEL] = &lcdif_pixel, + [IMX8MQ_CLK_SAI1] = &sai1, + [IMX8MQ_CLK_SAI2] = &sai2, + [IMX8MQ_CLK_SAI3] = &sai3, + [IMX8MQ_CLK_SAI4] = &sai4, + [IMX8MQ_CLK_SAI5] = &sai5, + [IMX8MQ_CLK_SAI6] = &sai6, + [IMX8MQ_CLK_SPDIF1] = &spdif1, + [IMX8MQ_CLK_SPDIF2] = &spdif2, + [IMX8MQ_CLK_ENET_REF] = &enet_ref, + [IMX8MQ_CLK_ENET_TIMER] = &enet_timer, + [IMX8MQ_CLK_ENET_PHY_REF] = &enet_phy, + [IMX8MQ_CLK_NAND] = &nand, + [IMX8MQ_CLK_QSPI] = &qspi, + [IMX8MQ_CLK_USDHC1] = &usdhc1, + [IMX8MQ_CLK_USDHC2] = &usdhc2, + [IMX8MQ_CLK_I2C1] = &i2c1, + [IMX8MQ_CLK_I2C2] = &i2c2, + [IMX8MQ_CLK_I2C3] = &i2c3, + [IMX8MQ_CLK_I2C4] = &i2c4, + [IMX8MQ_CLK_UART1] = &uart1, + [IMX8MQ_CLK_UART2] = &uart2, + [IMX8MQ_CLK_UART3] = &uart3, + [IMX8MQ_CLK_UART4] = &uart4, + [IMX8MQ_CLK_USB_CORE_REF] = &usb_core_ref, + [IMX8MQ_CLK_USB_PHY_REF] = &usb_phy_ref, + [IMX8MQ_CLK_GIC] = &gic, + [IMX8MQ_CLK_ECSPI1] = &ecspi1, + [IMX8MQ_CLK_ECSPI2] = &ecspi2, + [IMX8MQ_CLK_PWM1] = &pwm1, + [IMX8MQ_CLK_PWM2] = &pwm2, + [IMX8MQ_CLK_PWM3] = &pwm3, + [IMX8MQ_CLK_PWM4] = &pwm4, + [IMX8MQ_CLK_GPT1] = &gpt1, + [IMX8MQ_CLK_WDOG] = &wdog, + [IMX8MQ_CLK_WRCLK] = &wrclk, + [IMX8MQ_CLK_CLKO1] = &clko1, + [IMX8MQ_CLK_CLKO2] = &clko2, + [IMX8MQ_CLK_DSI_CORE] = &dsi_core, + [IMX8MQ_CLK_DSI_PHY_REF] = &dsi_phy_ref, + [IMX8MQ_CLK_DSI_DBI] = &dsi_dbi, + [IMX8MQ_CLK_DSI_ESC] = &dsi_esc, + [IMX8MQ_CLK_DSI_AHB] = &dsi_ahb, + [IMX8MQ_CLK_DSI_IPG_DIV] = &dsi_ipg_div, + [IMX8MQ_CLK_CSI1_CORE] = &csi1_core, + [IMX8MQ_CLK_CSI1_PHY_REF] = &csi1_phy_ref, + [IMX8MQ_CLK_CSI1_ESC] = &csi1_esc, + [IMX8MQ_CLK_CSI2_CORE] = &csi2_core, + [IMX8MQ_CLK_CSI2_PHY_REF] = &csi2_phy_ref, + [IMX8MQ_CLK_CSI2_ESC] = &csi2_esc, + [IMX8MQ_CLK_PCIE2_CTRL] = &pcie2_ctrl, + [IMX8MQ_CLK_PCIE2_PHY] = &pcie2_phy, + [IMX8MQ_CLK_PCIE2_AUX] = &pcie2_aux, + [IMX8MQ_CLK_ECSPI3] = &ecspi3, + [IMX8MQ_CLK_ECSPI1_ROOT] = &ecspi1_root_clk, + [IMX8MQ_CLK_ECSPI2_ROOT] = &ecspi2_root_clk, + [IMX8MQ_CLK_ECSPI3_ROOT] = &ecspi3_root_clk, + [IMX8MQ_CLK_ENET1_ROOT] = &enet1_root_clk, + [IMX8MQ_CLK_GPIO1_ROOT] = &gpio1_root_clk, + [IMX8MQ_CLK_GPIO2_ROOT] = &gpio2_root_clk, + [IMX8MQ_CLK_GPIO3_ROOT] = &gpio3_root_clk, + [IMX8MQ_CLK_GPIO4_ROOT] = &gpio4_root_clk, + [IMX8MQ_CLK_GPIO5_ROOT] = &gpio5_root_clk, + [IMX8MQ_CLK_GPT1_ROOT] = &gpt1_root_clk, + [IMX8MQ_CLK_I2C1_ROOT] = &i2c1_root_clk, + [IMX8MQ_CLK_I2C2_ROOT] = &i2c2_root_clk, + [IMX8MQ_CLK_I2C3_ROOT] = &i2c3_root_clk, + [IMX8MQ_CLK_I2C4_ROOT] = &i2c4_root_clk, + [IMX8MQ_CLK_MU_ROOT] = &mu_root_clk, + [IMX8MQ_CLK_OCOTP_ROOT] = &ocotp_root_clk, + [IMX8MQ_CLK_PCIE1_ROOT] = &pcie1_root_clk, + [IMX8MQ_CLK_PCIE2_ROOT] = &pcie2_root_clk, + [IMX8MQ_CLK_PWM1_ROOT] = &pwm1_root_clk, + [IMX8MQ_CLK_PWM2_ROOT] = &pwm2_root_clk, + [IMX8MQ_CLK_PWM3_ROOT] = &pwm3_root_clk, + [IMX8MQ_CLK_PWM4_ROOT] = &pwm4_root_clk, + [IMX8MQ_CLK_QSPI_ROOT] = &qspi_root_clk, + [IMX8MQ_CLK_RAWNAND_ROOT] = &nand_root_clk, + [IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = &nand_usdhc_rawnand_clk, + [IMX8MQ_CLK_SAI1_ROOT] = &sai1_root_clk, + [IMX8MQ_CLK_SAI1_IPG] = &sai1_ipg_clk, + [IMX8MQ_CLK_SAI2_ROOT] = &sai2_root_clk, + [IMX8MQ_CLK_SAI2_IPG] = &sai2_ipg_clk, + [IMX8MQ_CLK_SAI3_ROOT] = &sai3_root_clk, + [IMX8MQ_CLK_SAI3_IPG] = &sai3_ipg_clk, + [IMX8MQ_CLK_SAI4_ROOT] = &sai4_root_clk, + [IMX8MQ_CLK_SAI4_IPG] = &sai4_ipg_clk, + [IMX8MQ_CLK_SAI5_ROOT] = &sai5_root_clk, + [IMX8MQ_CLK_SAI5_IPG] = &sai5_ipg_clk, + [IMX8MQ_CLK_SAI6_ROOT] = &sai6_root_clk, + [IMX8MQ_CLK_SAI6_IPG] = &sai6_ipg_clk, + [IMX8MQ_CLK_UART1_ROOT] = &uart1_root_clk, + [IMX8MQ_CLK_UART2_ROOT] = &uart2_root_clk, + [IMX8MQ_CLK_UART3_ROOT] = &uart3_root_clk, + [IMX8MQ_CLK_UART4_ROOT] = &uart4_root_clk, + [IMX8MQ_CLK_USB1_CTRL_ROOT] = &usb1_ctrl_root_clk, + [IMX8MQ_CLK_USB2_CTRL_ROOT] = &usb2_ctrl_root_clk, + [IMX8MQ_CLK_USB1_PHY_ROOT] = &usb1_phy_root_clk, + [IMX8MQ_CLK_USB2_PHY_ROOT] = &usb2_phy_root_clk, + [IMX8MQ_CLK_USDHC1_ROOT] = &usdhc1_root_clk, + [IMX8MQ_CLK_USDHC2_ROOT] = &usdhc2_root_clk, + [IMX8MQ_CLK_WDOG1_ROOT] = &wdog1_root_clk, + [IMX8MQ_CLK_WDOG2_ROOT] = &wdog2_root_clk, + [IMX8MQ_CLK_WDOG3_ROOT] = &wdog3_root_clk, + [IMX8MQ_CLK_VPU_G1_ROOT] = &vpu_g1_root_clk, + [IMX8MQ_CLK_GPU_ROOT] = &gpu_root_clk, + [IMX8MQ_CLK_VPU_G2_ROOT] = &vpu_g2_root_clk, + [IMX8MQ_CLK_DISP_ROOT] = &disp_root_clk, + [IMX8MQ_CLK_DISP_AXI_ROOT] = &disp_axi_root_clk, + [IMX8MQ_CLK_DISP_APB_ROOT] = &disp_apb_root_clk, + [IMX8MQ_CLK_DISP_RTRM_ROOT] = &disp_rtrm_root_clk, + [IMX8MQ_CLK_TMU_ROOT] = &tmu_root_clk, + [IMX8MQ_CLK_VPU_DEC_ROOT] = &vpu_dec_root_clk, + [IMX8MQ_CLK_CSI1_ROOT] = &csi1_root_clk, + [IMX8MQ_CLK_CSI2_ROOT] = &csi2_root_clk, + [IMX8MQ_CLK_SDMA1_ROOT] = &sdma1_clk, + [IMX8MQ_CLK_SDMA2_ROOT] = &sdma2_clk, + [IMX8MQ_GPT_3M_CLK] = &gpt_3m, + [IMX8MQ_CLK_DRAM_ALT_ROOT] = &dram_alt_root, +}; + +int clk_msr_stat(struct clk *clk_list[]) +{ +#ifdef DEBUG_DRIVER + int i; + uint64_t rate = 0; + int err; + + LOG_DRIVER("-------Expected clock rates------\n"); + for (i = 0; i < NUM_CLK_LIST; i++) { + if (clk_list[i]) { + err = clk_get_rate(clk_list[i], &rate); + if (err) { + LOG_DRIVER_ERR("Failed to get rate of %s: -%u\n", clk_list[i]->hw.init->name, err); + return err; + } + LOG_DRIVER("[%4d][%10luHz] %s\n", i, rate, clk_list[i]->hw.init->name); + } + } + LOG_DRIVER("-----------------------------\n"); +#endif + + return 0; +} + +struct clk **get_clk_list(void) +{ + return imx8mq_clks; +} + +void clk_probe(struct clk *clk_list[]) +{ + for (int i = 0; i < NUM_CLK_LIST; i++) { + if (!clk_list[i]) { + continue; + } + + struct clk_init_data *init_data = clk_list[i]->hw.init; + + if (clk_list[i]->base == CCM_BASE) { + clk_list[i]->base = ccm_base; + } else if (clk_list[i]->base == CCM_ANALOG_BASE) { + clk_list[i]->base = ccm_analog_base; + } + + if (clk_list[i] && init_data->ops->init) { + init_data->ops->init(clk_list[i]); + } + } +} diff --git a/drivers/clk/imx/clk_driver.mk b/drivers/clk/imx/clk_driver.mk new file mode 100644 index 000000000..624ab5ac1 --- /dev/null +++ b/drivers/clk/imx/clk_driver.mk @@ -0,0 +1,37 @@ +# +# Copyright 2024, UNSW +# +# SPDX-License-Identifier: BSD-2-Clause + +CLK_DRIVER_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +CLK_CONFIG_HEADER := $(BUILD_DIR)/clk_config.h +CLK_DRIVER_CONF_INC := $(SDDF)/include/sddf/clk +CLK_DRIVER_INC := $(CLK_DRIVER_DIR)/include +CLK_DRIVER_COMMON_DIR := $(SDDF)/drivers/clk/ + +CLK_DRIVER_BOARD_SOURCES := clk-imx.c clk-imx8mq.c +CLK_DRIVER_COMMON_SOURCES := clk.c clk-operations.c +CLK_DRIVER_SOURCES := $(addprefix $(CLK_DRIVER_DIR), $(CLK_DRIVER_BOARD_SOURCES)) \ + $(addprefix $(CLK_DRIVER_COMMON_DIR), $(CLK_DRIVER_COMMON_SOURCES)) +CLK_DRIVER_OBJS = $(patsubst $(CLK_DRIVER_COMMON_DIR)%.c, clk_driver/%.o, $(CLK_DRIVER_SOURCES)) + +$(CLK_DRIVER_OBJS): CFLAGS += -I${CLK_DRIVER_INC} \ + -I${CLK_DRIVER_CONF_INC} \ + -I${BUILD_DIR} \ + -I${UART_DRIVER_DIR}/include \ + -I${CLK_DRIVER_COMMON_DIR} +clk_driver/%.o: $(CLK_DRIVER_COMMON_DIR)/%.c $(CLK_CONFIG_HEADER) + mkdir -p $(dir $@) + $(CC) -c $(CFLAGS) -o $@ $< + +clk_driver.elf: $(CLK_DRIVER_OBJS) libsddf_util_debug.a + $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ + +$(CLK_CONFIG_HEADER): $(DTS_FILE) $(CLK_DRIVER_COMMON_DIR)/create_clk_config.py + $(PYTHON) $(CLK_DRIVER_COMMON_DIR)/create_clk_config.py $(DTS_FILE) $(BUILD_DIR) + +clean:: + rm -f clk_driver.o + +clobber:: + rm -rf clk_driver.elf diff --git a/drivers/clk/imx/include/clk-imx.h b/drivers/clk/imx/include/clk-imx.h new file mode 100644 index 000000000..3fd64c125 --- /dev/null +++ b/drivers/clk/imx/include/clk-imx.h @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2010-2011 Canonical Ltd + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd + * + * Gated clock implementation + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-gate2.c + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2018 NXP. + * + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-frac-pll.c + */ + +// SPDX-License-Identifier: GPL-2.0-only OR MIT +/* + * Copyright 2018 NXP. + * + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-sscg-pll.c + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2018 NXP + * + * Source: https://github.com/torvalds/linux/blob/ + * cfaaa7d010d1fc58f9717fcc8591201e741d2d49/drivers/clk/imx/clk-composite-8m.c + */ +#pragma once + +#include + +/* These two magic numbers are used to define static clock + * structures at compile time, and will be replaced with + * real base addresses in clk_probe(). + */ +#define CCM_BASE 0x1234 +#define CCM_ANALOG_BASE 0x5678 + +#define PCG_PREDIV_SHIFT 16 +#define PCG_PREDIV_WIDTH 3 +#define PCG_PREDIV_MAX 8 + +#define PCG_DIV_SHIFT 0 +#define PCG_CORE_DIV_WIDTH 3 +#define PCG_DIV_WIDTH 6 +#define PCG_DIV_MAX 64 + +#define PCG_PCS_SHIFT 24 +#define PCG_PCS_MASK 0x7 + +#define PCG_CGC_SHIFT 28 + +struct clk_gate2 { + uint8_t bit_idx; + uint8_t cgr_val; + uint8_t cgr_mask; + uint8_t flags; + uint32_t *share_count; +}; + +struct clk_frac_pll_data { + uint32_t offset; +}; + +struct clk_sscg_pll_data { + /* struct clk_sscg_pll_setup setup; */ + uint32_t offset; + uint8_t parent; + uint8_t bypass1; + uint8_t bypass2; +}; + +/** + * Refer to section 5.1.5.4.1 Core clock slice in datasheet. + */ +struct clk_core_slice_data { + /* Common */ + uint32_t offset; + /* Mux */ + uint8_t mux_shift; + uint8_t mux_mask; + /* Gate */ + uint8_t gate_shift; + /* Divider */ + uint8_t div_shift; + uint8_t div_width; +}; + +/** + * Refer to section 5.1.5.4.2 Bus clock slice in datasheet. + */ +struct clk_bus_slice_data { + /* Common */ + uint32_t offset; + /* Mux */ + uint8_t mux_shift; + uint8_t mux_mask; + /* Gate */ + uint8_t gate_shift; + /* Prev Divider */ + uint8_t prevdiv_shift; + uint8_t prevdiv_width; + /* Post Divider */ + uint8_t postdiv_shift; + uint8_t postdiv_width; +}; + +/** + * Refer to section 5.1.5.4.3 Peripheral clock slice in datasheet. + */ +struct clk_common_slice_data { + /* Common */ + uint32_t offset; + /* Mux */ + uint8_t mux_shift; + uint8_t mux_mask; + /* Gate */ + uint8_t gate_shift; + /* Prev Divider */ + uint8_t prevdiv_shift; + uint8_t prevdiv_width; + /* Post Divider */ + uint8_t postdiv_shift; + uint8_t postdiv_width; +}; + +extern const struct clk_ops clk_gate2_ops; +extern const struct clk_ops clk_frac_pll_ops; +extern const struct clk_ops clk_sscg_pll_ops; +extern const struct clk_ops clk_core_slice_ops; +extern const struct clk_ops clk_bus_slice_ops; +extern const struct clk_ops clk_common_slice_ops; + +struct clk **get_clk_list(void); + +#define IMX_CLK_SOURCE(_name, _rate) \ +struct clk _name = { \ + .data = &(struct clk_source_data){ \ + .rate = (_rate), \ + }, \ + .hw.init = &(struct clk_init_data){ \ + .name = #_name, \ + .ops = &clk_source_ops, \ + } \ +} + +/* need to see difference between fixed clk and source clk */ +#define IMX_CLK_FIXED(_name, _rate) \ +IMX_CLK_SOURCE(_name, _rate) + +#define IMX_CLK_MUX_FLAGS(_name, _base, _offset, _shift, _width, _parent_data, _num_parents, _init_flags) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_mux_data) { \ + .offset = (_offset), \ + .mask = MASK(_width), \ + .shift = (_shift), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_mux_ops, \ + .parent_data = (_parent_data), \ + .num_parents = (_num_parents), \ + .flags = (_init_flags), \ + }, \ +} + +#define IMX_CLK_MUX(_name, _base, _offset, _shift, _width, _parent_data, _num_parents) \ +IMX_CLK_MUX_FLAGS(_name, _base, _offset, _shift, _width, \ + _parent_data, _num_parents, 0) + +#define IMX_CLK_MUX2(_name, _base, _offset, _shift, _width, _parent_data, _num_parents) \ +IMX_CLK_MUX_FLAGS(_name, _base, _offset, _shift, _width, \ + _parent_data, _num_parents, CLK_OPS_PARENT_ENABLE) + +#define IMX_CLK_MUX2_FLAGS(_name, _base, _offset, _shift, _width, _parent_data, _num_parents, _flags) \ +IMX_CLK_MUX_FLAGS(_name, _base, _offset, _shift, _width, \ + _parent_data, _num_parents, _flags | CLK_OPS_PARENT_ENABLE) + +#define IMX_CLK_DIV_FLAGS(_name, _parent_clks, _base, _offset, _shift, _width, _flags) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_div_data) { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_divider_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = 1, \ + .flags = 0, \ + }, \ +} + +#define IMX_CLK_DIV(_name, _parent_clks, _base, _offset, _shift, _width) \ +IMX_CLK_DIV_FLAGS(_name, _parent_clks, _base, _offset, _shift, _width, 0) + +#define IMX_CLK_DIV2(_name, _parent_clks, _base, _offset, _shift, _width) \ +IMX_CLK_DIV_FLAGS(_name, _parent_clks, _base, _offset, _shift, \ + _width, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE) + +#define IMX_CLK_FRAC_PLL(_name, _parent_clks, _base, _offset) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_frac_pll_data) { \ + .offset = (_offset), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_frac_pll_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = 1, \ + }, \ +} + +#define IMX_CLK_GATE1(_name, _parent_clks, _base, _offset, _shift) \ +CLK_GATE(_name, _offset, _shift, 0, _parent_clks, 1, 0) + +#define IMX_CLK_GATE(_name, _parent_clks, _base, _offset, _shift) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_gate_data) { \ + .offset = (_offset), \ + .bit_idx = (_shift), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_gate_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = 1, \ + }, \ +} + +#define IMX_CLK_GATE2_FLAGS(_name, _parent_clks, _base, _offset, _shift, _flags) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_gate_data) { \ + .offset = (_offset), \ + .bit_idx = (_shift), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_gate2_ops, \ + .parent_clks = (const struct clk *[]) _parent_clks, \ + .num_parents = 1, \ + }, \ +} + +#define IMX_CLK_GATE2_SHARED2(_name, _parent_clks, _base, _offset, _shift, _shared_count) \ +IMX_CLK_GATE2_FLAGS(_name, _parent_clks, _base, _offset, _shift, 0) + +#define IMX_CLK_GATE4(_name, _parent_clks, _base, _offset, _shift) \ +IMX_CLK_GATE2_FLAGS(_name, _parent_clks, _base, _offset, _shift, 0) + +#define IMX_CLK_FIXED_FACTOR(_name, _parent_clks, _mult, _div) \ +CLK_FIXED_FACTOR(_name, _mult, _div, 0, _parent_clks, 1, CLK_SET_RATE_PARENT) + +#define IMX_CLK_SSCG_PLL(_name, _parent_data, _num_parents, _parent, _bypass1, _bypass2, _base, _offset, _flags) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_sscg_pll_data) { \ + .offset = (_offset), \ + .parent = (_parent), \ + .bypass1 = (_bypass1), \ + .bypass2 = (_bypass2), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_sscg_pll_ops, \ + .parent_data = (_parent_data), \ + .num_parents = 1, \ + .flags = _flags, \ + }, \ +} + +#define IMX_CLK_COMPOSITE_CORE(_name, _parent_data, _base, _offset) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_core_slice_data) { \ + .offset = (_offset), \ + .mux_shift = PCG_PCS_SHIFT, \ + .mux_mask = PCG_PCS_MASK, \ + .div_shift = PCG_DIV_SHIFT, \ + .div_width = PCG_CORE_DIV_WIDTH, \ + .gate_shift = PCG_CGC_SHIFT, \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_core_slice_ops, \ + .parent_data = (_parent_data), \ + .num_parents = ARRAY_SIZE(_parent_data), \ + .flags = (CLK_DIVIDER_ROUND_CLOSEST | \ + CLK_SET_RATE_NO_REPARENT | \ + CLK_OPS_PARENT_ENABLE) \ + }, \ +} + +#define IMX_CLK_COMPOSITE_BUS(_name, _parent_data, _base, _offset) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_bus_slice_data) { \ + .offset = (_offset), \ + .mux_shift = PCG_PCS_SHIFT, \ + .mux_mask = PCG_PCS_MASK, \ + .prevdiv_shift = PCG_PREDIV_SHIFT, \ + .prevdiv_width = PCG_PREDIV_WIDTH, \ + .postdiv_shift = PCG_DIV_SHIFT, \ + .postdiv_width = PCG_DIV_WIDTH, \ + .gate_shift = PCG_CGC_SHIFT, \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_bus_slice_ops, \ + .parent_data = (_parent_data), \ + .num_parents = ARRAY_SIZE(_parent_data), \ + .flags = (CLK_DIVIDER_ROUND_CLOSEST | \ + CLK_SET_RATE_NO_REPARENT | \ + CLK_OPS_PARENT_ENABLE) \ + }, \ +} + +#define IMX_CLK_COMPOSITE_FLAGS(_name, _parent_data, _base, _offset, _flags) \ +struct clk _name = { \ + .base = (_base), \ + .data = &(struct clk_common_slice_data) { \ + .offset = (_offset), \ + .mux_shift = PCG_PCS_SHIFT, \ + .mux_mask = PCG_PCS_MASK, \ + .prevdiv_shift = PCG_PREDIV_SHIFT, \ + .prevdiv_width = PCG_PREDIV_WIDTH, \ + .postdiv_shift = PCG_DIV_SHIFT, \ + .postdiv_width = PCG_DIV_WIDTH, \ + .gate_shift = PCG_CGC_SHIFT, \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_common_slice_ops, \ + .parent_data = (_parent_data), \ + .num_parents = ARRAY_SIZE(_parent_data), \ + .flags = CLK_DIVIDER_ROUND_CLOSEST | \ + CLK_SET_RATE_NO_REPARENT | \ + CLK_OPS_PARENT_ENABLE | \ + (_flags), \ + }, \ +} + +#define IMX_CLK_COMPOSITE(_name, _parent_data, _base, _offset) \ +IMX_CLK_COMPOSITE_FLAGS(_name, _parent_data, _base, _offset, \ + CLK_OPS_PARENT_ENABLE) + +#define IMX_CLK_COMPOSITE_FW_MANAGED(_name, _parent_data, _base, _offset) \ +IMX_CLK_COMPOSITE_FLAGS(_name, _parent_data, _base, _offset, \ + (CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE \ + | CLK_GET_RATE_NOCACHE)) + +#define IMX_CLK_COMPOSITE_FW_MANAGED_CRITICAL(_name, _parent_data, _base, _offset) \ +IMX_CLK_COMPOSITE_FLAGS(_name, _parent_data, _base, _offset, \ + (CLK_SET_RATE_NO_REPARENT | \ + CLK_OPS_PARENT_ENABLE | \ + CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL)) diff --git a/drivers/clk/imx/include/clk-imx8mq.h b/drivers/clk/imx/include/clk-imx8mq.h new file mode 100644 index 000000000..4140ce3cb --- /dev/null +++ b/drivers/clk/imx/include/clk-imx8mq.h @@ -0,0 +1,11 @@ +/* + * Copyright 2024, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#define NUM_CLK_LIST IMX8MQ_CLK_END diff --git a/drivers/clk/meson/clk-measure.c b/drivers/clk/meson/clk-measure.c new file mode 100644 index 000000000..3869944ed --- /dev/null +++ b/drivers/clk/meson/clk-measure.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * This program is derived from: + * https://github.com/hardkernel/u-boot/blob/odroidg12-v2015.01/arch/arm/cpu/armv8/g12a/clock.c + * + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include + +#define TIMER_CH 1 + +#define MSR_CLK_BASE 0x03300000 +#define MSR_CLK_DUTY 0x00 +#define MSR_CLK_REG0 0x01 +#define MSR_CLK_REG1 0x02 +#define MSR_CLK_REG2 0x03 + +#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \ +{ \ + typeof(divisor) __d = divisor; \ + unsigned long long _tmp = (x) + (__d) / 2; \ + do_div(_tmp, __d); \ + _tmp; \ +} \ +) + +static const char *const sm1_table[] = { + [0] = "am_ring_osc_clk_out_ee[0]", + [1] = "am_ring_osc_clk_out_ee[1]", + [2] = "am_ring_osc_clk_out_ee[2]", + [3] = "am_ring_osc_clk_out_ee[3]", + [4] = "gp0_pll_clk", + [5] = "gp1_pll_clk", + [6] = "cts_enci_clk", + [7] = "clk81", + [8] = "cts_encp_clk", + [9] = "cts_encl_clk", + [10] = "cts_vdac_clk", + [11] = "mac_eth_tx_clk", + [12] = "hifi_pll_clk", + [13] = "mod_tcon_clko", + [14] = "cts_FEC_CLK_0", + [15] = "cts_FEC_CLK_1", + [16] = "cts_FEC_CLK_2", + [17] = "sys_pll_div16", + [18] = "sys_cpu_clk_div16", + [19] = "lcd_an_clk_ph2", + [20] = "rtc_osc_clk_out", + [21] = "lcd_an_clk_ph3", + [22] = "mac_eth_phy_ref_clk", + [23] = "mpll_clk_50m", + [24] = "cts_eth_clk125Mhz", + [25] = "cts_eth_clk_rmii", + [26] = "sc_clk_int", + [27] = "co_clkin_to_mac", + [28] = "cts_sar_adc_clk", + [29] = "pcie_clk_inp", + [30] = "pcie_clk_inn", + [31] = "mpll_clk_test_out", + [32] = "cts_vdec_clk", + [33] = "1'b0", + [34] = "eth_mppll_50m_ckout", + [35] = "cts_mali_clk", + [36] = "cts_hdmi_tx_pixel_clk", + [37] = "cts_cdac_clk_c", + [38] = "cts_vdin_meas_clk", + [39] = "cts_bt656_clk0", + [40] = "arm_ring_osc_clk_out[4]", + [41] = "mac_eth_rx_clk_rmii", + [42] = "mp0_clk_out", + [43] = "fclk_div5", + [44] = "cts_pwm_B_clk", + [45] = "cts_pwm_A_clk", + [46] = "cts_vpu_clk", + [47] = "ddr_dpll_pt_clk", + [48] = "mp1_clk_out", + [49] = "mp2_clk_out", + [50] = "mp3_clk_out", + [51] = "cts_sd_emmc_clk_C", + [52] = "cts_sd_emmc_clk_B", + [53] = "cts_sd_emmc_clk_A", + [54] = "cts_vpu_clkc", + [55] = "vid_pll_div_clk_out", + [56] = "cts_wave420l_aclk", + [57] = "cts_wave420l_cclk", + [58] = "cts_wave420l_bclk", + [59] = "cts_hcodec_clk", + [60] = "arm_ring_osc_clk_out[5]", + [61] = "gpio_clk_msr", + [62] = "cts_hevcb_clk", + [63] = "cts_dsi_meas_clk", + [64] = "cts_spicc_1_clk", + [65] = "cts_spicc_0_clk", + [66] = "cts_vid_lock_clk", + [67] = "cts_dsi_phy_clk", + [68] = "cts_hdcp22_esmclk", + [69] = "cts_hdcp22_skpclk", + [70] = "cts_pwm_F_clk", + [71] = "cts_pwm_E_clk", + [72] = "cts_pwm_D_clk", + [73] = "cts_pwm_C_clk", + [74] = "arm_ring_osc_clk_out[6]", + [75] = "cts_hevcf_clk", + [76] = "arm_ring_osc_clk_out[7]", + [77] = "rng_ring_osc_clk[0]", + [78] = "rng_ring_osc_clk[1]", + [79] = "rng_ring_osc_clk[2]", + [80] = "rng_ring_osc_clk[3]", + [81] = "cts_vapbclk", + [82] = "cts_ge2d_clk", + [83] = "co_rx_clk", + [84] = "co_tx_clk", + [85] = "arm_ring_osc_clk_out[8]", + [86] = "arm_ring_osc_clk_out[9]", + [87] = "mipi_csi_phy_clk", + [88] = "csi2_adapt_clk", + [89] = "HDMI_CLK_TODIG", + [90] = "cts_hdmitx_sys_clk", + [91] = "nna_core_clk", + [92] = "nna_axi_clk", + [93] = "vad_clk", + [94] = "eth_phy_rxclk", + [95] = "eth_phy_plltxclk", + [96] = "cts_vpu_clkb", + [97] = "cts_vpu_clkb_tmp", + [98] = "cts_ts_clk", + [99] = "arm_ring_osc_clk_out[10]", + [100] = "arm_ring_osc_clk_out[11]", + [101] = "arm_ring_osc_clk_out[12]", + [102] = "arm_ring_osc_clk_out[13]", + [103] = "arm_ring_osc_clk_out[14]", + [104] = "arm_ring_osc_clk_out[15]", + [105] = "arm_ring_osc_clk_out[16]", + [106] = "ephy_test_clk", + [107] = "au_dac_clk_g128x", + [108] = "c_alocker_in_clk", + [109] = "c_alocker_out_clk", + [110] = "audio_tdmout_c_sclk", + [111] = "audio_tdmout_b_sclk", + [112] = "audio_tdmout_a_sclk", + [113] = "audio_tdmin_lb_sclk", + [114] = "audio_tdmin_c_sclk", + [115] = "audio_tdmin_b_sclk", + [116] = "audio_tdmin_a_sclk", + [117] = "audio_resampleA_clk", + [118] = "audio_pdm_sysclk", + [119] = "audio_spdifout_b_mst_clk", + [120] = "audio_spdifout_mst_clk", + [121] = "audio_spdifin_mst_clk", + [122] = "mod_audio_pdm_dclk_o", + [123] = "audio_resampled_clk", + [124] = "earcx_pll_(dmac)_clk", + [125] = "earcrx_pll_test_clk", + [126] = "csi_phy0_clk_out", + [127] = "clk_csi2_data", +}; + +unsigned long clk_msr(unsigned long clk_mux) +{ + volatile uint32_t *mclk_reg0 = ((void *)MSR_CLK_BASE + (MSR_CLK_REG0 << 2)); + volatile uint32_t *mclk_reg2 = ((void *)MSR_CLK_BASE + (MSR_CLK_REG2 << 2)); + uint32_t duration = 640; + uint32_t regval = 0; + + /* Disable continuous measurement */ + /* Disable interrupts */ + *mclk_reg0 = regval; + + regval |= duration; /* 64uS is enough for measure the frequence? */ + *mclk_reg0 = regval; + + regval |= (clk_mux << 20); /* Select MUX */ + *mclk_reg0 = regval; + + regval |= (1 << 19); /* enable the clock */ + regval |= (1 << 16); /* enable measuring */ + *mclk_reg0 = regval; + + regval = *mclk_reg0; + + uint64_t start_time = sddf_timer_time_now(TIMER_CH); + uint64_t now_time = start_time; + + /* TODO: Check the busy bit */ + /* if (regval & (1 << 31)) */ + /* sddf_dprintf("CLK | ERR: The clock measure logic is busy\n"); */ + + /* Wait for the measurement to be done */ + while (true) { + now_time = sddf_timer_time_now(TIMER_CH); + + if ((now_time - start_time) > 1000000) { + break; + } + /* TODO: Could be optimised via timeouts */ + /* if (sleep_us) */ + /* udelay(sleep_us); */ + } + + regval &= ~(1 << 16); /* disable measuring */ + *mclk_reg0 = regval; + + uint32_t msr_val = *mclk_reg2; + + return DIV_ROUND_CLOSEST_ULL((msr_val & ((1 << 19) - 1)) * 1000000ULL, duration); +} + +const char *const *get_msr_clk_list(void) +{ + return sm1_table; +} diff --git a/drivers/clk/meson/clk-meson.c b/drivers/clk/meson/clk-meson.c new file mode 100644 index 000000000..45399a334 --- /dev/null +++ b/drivers/clk/meson/clk-meson.c @@ -0,0 +1,471 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +/* + * Operations for MPLL clocks are derived from: + * https://github.com/torvalds/linux/blob/befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/meson/clk-mpll.c + * + * Copyright (c) 2016 AmLogic, Inc. + * Author: Michael Turquette + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for PLL clocks are derived from: + * https://github.com/torvalds/linux/blob/befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/meson/clk-pll.c + * + * Copyright (c) 2015 Endless Mobile, Inc. + * Author: Carlo Caione + * + * Copyright (c) 2018 Baylibre, SAS. + * Author: Jerome Brunet + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for gate clocks are derived from: + * https://github.com/torvalds/linux/blob/befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/meson/clk-regmap.c + * + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for fixed factor clocks are derived from: + * https://github.com/torvalds/linux/blob/befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/clk-fixed-factor.c + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for divider clocks are derived from: + * https://github.com/torvalds/linux/blob/befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/clk-divider.c + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * Copyright (C) 2011 Richard Zhao, Linaro + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd + * + * Adjustable divider clock implementation + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for multiplexer clocks are derived from: + * https://github.com/torvalds/linux/blob/befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/clk-mux.c + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * Copyright (C) 2011 Richard Zhao, Linaro + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd + * + * Simple multiplexer clock implementation + */ + +// SPDX-License-Identifier: GPL-2.0-only +/* + * Operations for meson_vid_pll_div are derived from: + * https://github.com/torvalds/linux/blob/7ec462100ef9142344ddbf86f2c3008b97acddbe/drivers/clk/meson/vid-pll-div.c + * https://github.com/torvalds/linux/blob/7ec462100ef9142344ddbf86f2c3008b97acddbe/drivers/clk/meson/vclk.c + * + * Copyright (c) 2018 BayLibre, SAS. + * Author: Neil Armstrong + */ + +#include +#include +#include +#include + +static inline uint32_t meson_parm_read(uint64_t base, struct parm parm) +{ + return regmap_read_bits(base, parm.reg_off, parm.shift, MASK(parm.width)); +} + +int regmap_multi_reg_write(uint64_t base, const struct reg_sequence *regs, int num_regs) +{ + int i; + for (i = 0; i < num_regs; i++) { + reg_write(base, regs[i].reg, regs[i].def); + if (regs[i].delay_us) { + delay_us(regs[i].delay_us); + } + } + return 0; +} + +static void meson_clk_pll_init(struct clk *clk) +{ + struct meson_clk_pll_data *data = (struct meson_clk_pll_data *)(clk->data); + if ((data->flags & CLK_MESON_PLL_NOINIT_ENABLED) && clk->hw.init->ops->is_enabled(clk)) + return; + + if (data->init_count) { + /* Set the reset bit */ + regmap_update_bits(clk->base, data->rst.reg_off, data->rst.shift, MASK(data->rst.width), 1); + + regmap_multi_reg_write(clk->base, data->init_regs, data->init_count); + + /* Clear the reset bit */ + regmap_update_bits(clk->base, data->rst.reg_off, data->rst.shift, MASK(data->rst.width), 0); + } +} + +static unsigned long meson_clk_pll_recalc_rate(const struct clk *clk, unsigned long parent_rate) +{ + struct meson_clk_pll_data *data = (struct meson_clk_pll_data *)(clk->data); + uint32_t n, m, frac; + + n = regmap_read_bits(clk->base, data->n.reg_off, data->n.shift, MASK(data->n.width)); + if (n == 0) + return 0; + + m = regmap_read_bits(clk->base, data->m.reg_off, data->m.shift, MASK(data->m.width)); + + frac = data->frac.width ? regmap_read_bits(clk->base, data->frac.reg_off, data->frac.shift, MASK(data->frac.width)) + : 0; + + uint64_t rate = (uint64_t)parent_rate * m; + + if (frac) { + uint64_t frac_rate = (uint64_t)parent_rate * frac; + rate += DIV_ROUND_UP_ULL(frac_rate, (1 << data->frac.width)); + } + + return DIV_ROUND_UP_ULL(rate, n); +} + +static int meson_clk_pll_is_enabled(struct clk *clk) +{ + struct meson_clk_pll_data *data = (struct meson_clk_pll_data *)(clk->data); + + if (data->rst.width && meson_parm_read(clk->base, data->rst)) { + return 0; + } + + if (!meson_parm_read(clk->base, data->en) || !meson_parm_read(clk->base, data->l)) { + return 0; + } + + return 1; +} + +static int meson_clk_pll_enable(struct clk *clk) +{ + struct meson_clk_pll_data *data = (struct meson_clk_pll_data *)(clk->data); + + if (meson_clk_pll_is_enabled(clk)) + return 0; + + regmap_update_bits(clk->base, data->rst.reg_off, data->rst.shift, MASK(data->rst.width), 1); + regmap_update_bits(clk->base, data->en.reg_off, data->en.shift, MASK(data->en.width), 1); + regmap_update_bits(clk->base, data->rst.reg_off, data->rst.shift, MASK(data->rst.width), 1); + + regmap_update_bits(clk->base, data->current_en.reg_off, data->current_en.shift, MASK(data->current_en.width), 1); + return 0; +} + +static int meson_clk_pll_disable(struct clk *clk) +{ + struct meson_clk_pll_data *data = (struct meson_clk_pll_data *)(clk->data); + + regmap_update_bits(clk->base, data->rst.reg_off, data->rst.shift, MASK(data->rst.width), 1); + regmap_update_bits(clk->base, data->en.reg_off, data->en.shift, MASK(data->en.width), 0); + return 0; +} + +const struct clk_ops meson_clk_pll_ops = { + .init = meson_clk_pll_init, + .recalc_rate = meson_clk_pll_recalc_rate, + /* .determine_rate = meson_clk_pll_determine_rate, */ + /* .set_rate = meson_clk_pll_set_rate, */ + .is_enabled = meson_clk_pll_is_enabled, + .enable = meson_clk_pll_enable, + .disable = meson_clk_pll_disable, +}; + +const struct clk_ops meson_clk_pll_ro_ops = { + .recalc_rate = meson_clk_pll_recalc_rate, + .is_enabled = meson_clk_pll_is_enabled, +}; + +#define SDM_DEN 16384 +#define N2_MIN 4 +#define N2_MAX 511 + +static uint64_t mpll_recalc_rate(const struct clk *clk, uint64_t prate) +{ + struct meson_clk_mpll_data *data = (struct meson_clk_mpll_data *)(clk->data); + uint32_t sdm, n2; + + sdm = regmap_read_bits(clk->base, data->sdm.reg_off, data->sdm.shift, MASK(data->sdm.width)); + n2 = regmap_read_bits(clk->base, data->n2.reg_off, data->n2.shift, MASK(data->n2.width)); + + uint32_t divisor = (SDM_DEN * n2) + sdm; + if (n2 < N2_MIN) + return -1; + + return DIV_ROUND_UP_ULL((uint64_t)prate * SDM_DEN, divisor); +} + +static int mpll_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct meson_clk_mpll_data *data = (struct meson_clk_mpll_data *)(clk->data); + uint64_t div = parent_rate; + uint64_t frac = do_div(div, rate); + uint32_t sdm, n2; + + frac *= SDM_DEN; + + if (data->flags & CLK_MESON_MPLL_ROUND_CLOSEST) + sdm = DIV_ROUND_CLOSEST_ULL(frac, rate); + else + sdm = DIV_ROUND_UP_ULL(frac, rate); + + if (sdm == SDM_DEN) { + sdm = 0; + div += 1; + } + + if (div < N2_MIN) { + n2 = N2_MIN; + sdm = 0; + } else if (div > N2_MAX) { + n2 = N2_MAX; + sdm = SDM_DEN - 1; + } else { + n2 = div; + } + + regmap_update_bits(clk->base, data->sdm.reg_off, data->sdm.shift, MASK(data->sdm.width), sdm); + regmap_update_bits(clk->base, data->n2.reg_off, data->n2.shift, MASK(data->n2.width), n2); + + return 0; +} + +static void mpll_init(struct clk *clk) +{ + struct meson_clk_mpll_data *data = (struct meson_clk_mpll_data *)(clk->data); + if (data->init_count) { + regmap_multi_reg_write(clk->base, data->init_regs, data->init_count); + } + + /* Enable the fractional part */ + regmap_update_bits(clk->base, data->sdm_en.reg_off, data->sdm_en.shift, MASK(data->sdm_en.width), 1); + + /* Set spread spectrum if possible */ + uint32_t ss = data->flags & CLK_MESON_MPLL_SPREAD_SPECTRUM ? 1 : 0; + regmap_update_bits(clk->base, data->ssen.reg_off, data->ssen.shift, MASK(data->ssen.width), ss); +} + +const struct clk_ops meson_clk_mpll_ops = { + .recalc_rate = mpll_recalc_rate, + /* .determine_rate = mpll_determine_rate, */ + .set_rate = mpll_set_rate, + .init = mpll_init, +}; + +static int meson_clk_pcie_pll_enable(struct clk *clk) +{ + struct meson_clk_pll_data *data = (struct meson_clk_pll_data *)(clk->data); + int retries = 10; + int delay = 5000; + + do { + meson_clk_pll_init(clk); + do { + if (meson_parm_read(clk->base, data->l)) { + return 0; + } + delay_us(20); + } while (--delay); + } while (--retries); + + return -1; +} + +const struct clk_ops meson_clk_pcie_pll_ops = { + .init = meson_clk_pll_init, + .recalc_rate = meson_clk_pll_recalc_rate, + /* .determine_rate = meson_clk_pll_determine_rate, */ + .is_enabled = meson_clk_pll_is_enabled, + .enable = meson_clk_pcie_pll_enable, + .disable = meson_clk_pll_disable, +}; + +struct vid_pll_div { + unsigned int shift_val; + unsigned int shift_sel; + unsigned int divider; + unsigned int multiplier; +}; + +#define VID_PLL_DIV(_val, _sel, _ft, _fb) \ + { \ + .shift_val = (_val), \ + .shift_sel = (_sel), \ + .divider = (_ft), \ + .multiplier = (_fb), \ + } + +static const struct vid_pll_div vid_pll_div_table[] = { + VID_PLL_DIV(0x0aaa, 0, 2, 1), /* 2/1 => /2 */ + VID_PLL_DIV(0x5294, 2, 5, 2), /* 5/2 => /2.5 */ + VID_PLL_DIV(0x0db6, 0, 3, 1), /* 3/1 => /3 */ + VID_PLL_DIV(0x36cc, 1, 7, 2), /* 7/2 => /3.5 */ + VID_PLL_DIV(0x6666, 2, 15, 4), /* 15/4 => /3.75 */ + VID_PLL_DIV(0x0ccc, 0, 4, 1), /* 4/1 => /4 */ + VID_PLL_DIV(0x739c, 2, 5, 1), /* 5/1 => /5 */ + VID_PLL_DIV(0x0e38, 0, 6, 1), /* 6/1 => /6 */ + VID_PLL_DIV(0x0000, 3, 25, 4), /* 25/4 => /6.25 */ + VID_PLL_DIV(0x3c78, 1, 7, 1), /* 7/1 => /7 */ + VID_PLL_DIV(0x78f0, 2, 15, 2), /* 15/2 => /7.5 */ + VID_PLL_DIV(0x0fc0, 0, 12, 1), /* 12/1 => /12 */ + VID_PLL_DIV(0x3f80, 1, 14, 1), /* 14/1 => /14 */ + VID_PLL_DIV(0x7f80, 2, 15, 1), /* 15/1 => /15 */ +}; + +static unsigned long meson_vid_pll_div_recalc_rate(const struct clk *clk, unsigned long prate) +{ + struct meson_vid_pll_div_data *data = (struct meson_vid_pll_div_data *)(clk->data); + const struct vid_pll_div *div; + uint32_t shift_val, shift_sel; + + shift_val = regmap_read_bits(clk->base, data->val.reg_off, data->val.shift, MASK(data->val.width)); + shift_sel = regmap_read_bits(clk->base, data->sel.reg_off, data->sel.shift, MASK(data->sel.width)); + + int i; + + for (i = 0; i < ARRAY_SIZE(vid_pll_div_table); ++i) { + if (vid_pll_div_table[i].shift_val == shift_val && vid_pll_div_table[i].shift_sel == shift_sel) { + div = &vid_pll_div_table[i]; + return DIV_ROUND_UP_ULL(prate * div->multiplier, div->divider); + } + } + + /* Return 0 if the vid pll is not configured */ + return 0; +} + +const struct clk_ops meson_vid_pll_div_ro_ops = { + .recalc_rate = meson_vid_pll_div_recalc_rate, +}; + +static int meson_vclk_gate_enable(struct clk *clk) +{ + struct meson_vclk_gate_data *data = (struct meson_vclk_gate_data *)(clk->data); + + regmap_update_bits(clk->base, data->enable.reg_off, data->enable.shift, MASK(data->enable.width), 1); + + /* Do a reset pulse */ + regmap_update_bits(clk->base, data->reset.reg_off, data->reset.shift, MASK(data->reset.width), 1); + regmap_update_bits(clk->base, data->reset.reg_off, data->reset.shift, MASK(data->reset.width), 0); + + return 0; +} + +static int meson_vclk_gate_disable(struct clk *clk) +{ + struct meson_vclk_gate_data *data = (struct meson_vclk_gate_data *)(clk->data); + + regmap_update_bits(clk->base, data->enable.reg_off, data->enable.shift, MASK(data->enable.width), 0); + return 0; +} + +static int meson_vclk_gate_is_enabled(struct clk *clk) +{ + struct meson_vclk_gate_data *data = (struct meson_vclk_gate_data *)(clk->data); + return regmap_read_bits(clk->base, data->enable.reg_off, data->enable.shift, MASK(data->enable.width)); +} + +const struct clk_ops meson_vclk_gate_ops = { + .enable = meson_vclk_gate_enable, + .disable = meson_vclk_gate_disable, + .is_enabled = meson_vclk_gate_is_enabled, +}; + +static unsigned long meson_vclk_div_recalc_rate(const struct clk *clk, unsigned long prate) +{ + struct meson_vclk_div_data *data = (struct meson_vclk_div_data *)(clk->data); + uint32_t div = regmap_read_bits(clk->base, data->div.reg_off, data->div.shift, MASK(data->div.width)); + + /* TODO: Need to verify the following cases */ + if (data->flags & CLK_DIVIDER_ONE_BASED) { + ; + } else if (data->flags & CLK_DIVIDER_POWER_OF_TWO) { + div = 1 << div; + } else if (data->flags & CLK_DIVIDER_MAX_AT_ZERO) { + div = div ? div : MASK(data->div.width) + 1; + } else { + div += 1; + } + + return DIV_ROUND_UP_ULL((uint64_t)prate, div); +} + +static int meson_vclk_div_set_rate(const struct clk *clk, uint64_t rate, uint64_t parent_rate) +{ + struct meson_vclk_div_data *data = (struct meson_vclk_div_data *)(clk->data); + + uint32_t div = DIV_ROUND_UP(parent_rate, rate); + + if (data->flags & CLK_DIVIDER_ONE_BASED) { + /* TODO: to be implemented */ + ; + } else if (data->flags & CLK_DIVIDER_POWER_OF_TWO) { + /* div = __ffs(div); */ + } else if (data->flags & CLK_DIVIDER_MAX_AT_ZERO) { + div = (div == MASK(data->div.width) + 1) ? 0 : div; + } else { + div -= 1; + } + return regmap_update_bits(clk->base, data->div.reg_off, data->div.shift, MASK(data->div.width), div); +} + +static int meson_vclk_div_enable(struct clk *clk) +{ + struct meson_vclk_div_data *data = (struct meson_vclk_div_data *)(clk->data); + + regmap_update_bits(clk->base, data->reset.reg_off, data->reset.shift, MASK(data->reset.width), 0); + regmap_update_bits(clk->base, data->enable.reg_off, data->enable.shift, MASK(data->enable.width), 1); + + return 0; +} + +static int meson_vclk_div_disable(struct clk *clk) +{ + struct meson_vclk_div_data *data = (struct meson_vclk_div_data *)(clk->data); + + regmap_update_bits(clk->base, data->enable.reg_off, data->enable.shift, MASK(data->enable.width), 0); + regmap_update_bits(clk->base, data->reset.reg_off, data->reset.shift, MASK(data->reset.width), 1); + return 0; +} + +static int meson_vclk_div_is_enabled(struct clk *clk) +{ + struct meson_vclk_div_data *data = (struct meson_vclk_div_data *)(clk->data); + return regmap_read_bits(clk->base, data->enable.reg_off, data->enable.shift, MASK(data->enable.width)); +} + +const struct clk_ops meson_vclk_div_ops = { + .recalc_rate = meson_vclk_div_recalc_rate, + /* .determine_rate = meson_vclk_div_determine_rate, */ + .set_rate = meson_vclk_div_set_rate, + .enable = meson_vclk_div_enable, + .disable = meson_vclk_div_disable, + .is_enabled = meson_vclk_div_is_enabled, +}; + +static unsigned long meson_clk_cpu_dyndiv_recalc_rate(const struct clk *clk, unsigned long prate) +{ + struct meson_clk_cpu_dyndiv_data *data = (struct meson_clk_cpu_dyndiv_data *)(clk->data); + uint32_t div = meson_parm_read(clk->base, data->div); + + div += 1; + + return DIV_ROUND_UP_ULL((uint64_t)prate, div); +} + +const struct clk_ops meson_clk_cpu_dyndiv_ops = { + .recalc_rate = meson_clk_cpu_dyndiv_recalc_rate, + /* .determine_rate = meson_clk_cpu_dyndiv_determine_rate, */ + /* .set_rate = meson_clk_cpu_dyndiv_set_rate, */ +}; diff --git a/drivers/clk/meson/clk_driver.mk b/drivers/clk/meson/clk_driver.mk new file mode 100644 index 000000000..9e147ba08 --- /dev/null +++ b/drivers/clk/meson/clk_driver.mk @@ -0,0 +1,37 @@ +# +# Copyright 2024, UNSW +# +# SPDX-License-Identifier: BSD-2-Clause + +CLK_DRIVER_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +CLK_CONFIG_HEADER := $(BUILD_DIR)/clk_config.h +CLK_DRIVER_CONF_INC := $(SDDF)/include/sddf/clk +CLK_DRIVER_INC := $(CLK_DRIVER_DIR)/include +CLK_DRIVER_COMMON_DIR := $(SDDF)/drivers/clk/ + +CLK_DRIVER_BOARD_SOURCES := clk-measure.c clk-meson.c sm1-clk.c +CLK_DRIVER_COMMON_SOURCES := clk.c clk-operations.c +CLK_DRIVER_SOURCES := $(addprefix $(CLK_DRIVER_DIR), $(CLK_DRIVER_BOARD_SOURCES)) \ + $(addprefix $(CLK_DRIVER_COMMON_DIR), $(CLK_DRIVER_COMMON_SOURCES)) +CLK_DRIVER_OBJS = $(patsubst $(CLK_DRIVER_COMMON_DIR)%.c, clk_driver/%.o, $(CLK_DRIVER_SOURCES)) + +$(CLK_DRIVER_OBJS): CFLAGS += -I${CLK_DRIVER_INC} \ + -I${CLK_DRIVER_CONF_INC} \ + -I${BUILD_DIR} \ + -I${UART_DRIVER_DIR}/include \ + -I${CLK_DRIVER_COMMON_DIR} +clk_driver/%.o: $(CLK_DRIVER_COMMON_DIR)/%.c $(CLK_CONFIG_HEADER) + mkdir -p $(dir $@) + $(CC) -c $(CFLAGS) -o $@ $< + +clk_driver.elf: $(CLK_DRIVER_OBJS) libsddf_util_debug.a + $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ + +$(CLK_CONFIG_HEADER): $(DTS_FILE) $(CLK_DRIVER_COMMON_DIR)/create_clk_config.py + $(PYTHON) $(CLK_DRIVER_COMMON_DIR)/create_clk_config.py $(DTS_FILE) $(BUILD_DIR) + +clean:: + rm -f clk_driver.o + +clobber:: + rm -rf clk_driver.elf diff --git a/drivers/clk/meson/include/clk-measure.h b/drivers/clk/meson/include/clk-measure.h new file mode 100644 index 000000000..7de22a6b1 --- /dev/null +++ b/drivers/clk/meson/include/clk-measure.h @@ -0,0 +1,9 @@ +/* + * Copyright 2024, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +const char *const *get_msr_clk_list(void); +unsigned long clk_msr(unsigned long clk_mux); diff --git a/drivers/clk/meson/include/clk-meson.h b/drivers/clk/meson/include/clk-meson.h new file mode 100644 index 000000000..77e52d97c --- /dev/null +++ b/drivers/clk/meson/include/clk-meson.h @@ -0,0 +1,174 @@ +#pragma once + +#include + +#define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0) +#define CLK_MESON_MPLL_SPREAD_SPECTRUM BIT(1) + +#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0) +#define CLK_MESON_PLL_NOINIT_ENABLED BIT(1) + +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2015 Endless Mobile, Inc. + * Author: Carlo Caione + * + * Derived from: https://github.com/torvalds/linux/blob/6485cf5ea253d40d507cd71253c9568c5470cd27/drivers/clk/meson/parm.h + */ +/** + * struct parm - struct defines bits of a clock control field in registers + * + * @reg_off: offset of the register + * @shift: shift of the control field + * @width: width of the control field + * + * Register/value pairs for sequences of writes with an optional delay in + * microseconds to be applied after each write. + */ +struct parm { + uint16_t reg_off; + uint8_t shift; + uint8_t width; +}; + +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2011 Wolfson Microelectronics plc + * + * Author: Mark Brown + * + * Derived from: https://github.com/torvalds/linux/blob/6485cf5ea253d40d507cd71253c9568c5470cd27/include/linux/regmap.h + */ +/** + * struct reg_sequence - An individual write from a sequence of writes. + * + * @reg: Register address. + * @def: Register value. + * @delay_us: Delay to be applied after the register write in microseconds + */ +struct reg_sequence { + unsigned int reg; + unsigned int def; + unsigned int delay_us; +}; + +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019 BayLibre, SAS. + * Author: Jerome Brunet + */ +/** + * struct reg_sequence - An individual write from a sequence of writes. + * + * @m: Register address. + * @n: Register value. + * @delay_us: Delay to be applied after the register write in microseconds + * + * Register/value pairs for sequences of writes with an optional delay in + * microseconds to be applied after each write. + */ +struct pll_params_table { + unsigned int m; + unsigned int n; +}; + +struct meson_clk_cpu_dyndiv_data { + struct parm div; + struct parm dyn; +}; + +struct meson_clk_pll_data { + struct parm en; + struct parm m; + struct parm n; + struct parm frac; + struct parm l; + struct parm rst; + struct parm current_en; + struct parm l_detect; + const struct reg_sequence *init_regs; + unsigned int init_count; + const struct pll_params_table *table; + /* const struct pll_mult_range *range; */ + uint8_t range_min; + uint8_t range_max; + uint8_t flags; +}; + +struct meson_clk_mpll_data { + struct parm sdm; + struct parm sdm_en; + struct parm n2; + struct parm ssen; + struct parm misc; + const struct reg_sequence *init_regs; + unsigned int init_count; + /* spinlock_t *lock; */ + uint8_t flags; +}; + +struct meson_vid_pll_div_data { + struct parm val; + struct parm sel; +}; + +struct meson_vclk_gate_data { + struct parm enable; + struct parm reset; + uint8_t flags; +}; + +struct meson_vclk_div_data { + struct parm div; + struct parm enable; + struct parm reset; + const struct clk_div_table *table; + uint8_t flags; +}; + +extern const struct clk_ops meson_clk_pll_ops; +extern const struct clk_ops meson_clk_pll_ro_ops; +extern const struct clk_ops meson_clk_mpll_ops; +extern const struct clk_ops meson_clk_pcie_pll_ops; +extern const struct clk_ops meson_vid_pll_div_ro_ops; +extern const struct clk_ops meson_vclk_gate_ops; +extern const struct clk_ops meson_vclk_div_ops; +extern const struct clk_ops meson_clk_cpu_dyndiv_ops; + +#define MESON_CLK81_GATE(_name, _reg, _bit) \ +struct clk _name = { \ + .data = &(struct clk_gate_data) { \ + .offset = (_reg), \ + .bit_idx = (_bit), \ + .flags = 0, \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_gate_ops, \ + .parent_clks = (const struct clk *[]) { \ + &g12a_clk81, \ + }, \ + .num_parents = 1, \ + .flags = 0, \ + }, \ +} + +#define MESON_CLK81_GATE_RO(_name, _reg, _bit) \ +struct clk _name = { \ + .data = &(struct clk_gate_data) { \ + .offset = (_reg), \ + .bit_idx = (_bit), \ + .flags = 0, \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = #_name, \ + .ops = &clk_gate_ro_ops, \ + .parent_clks = (const struct clk *[]) { \ + &g12a_clk81, \ + }, \ + .num_parents = 1, \ + .flags = 0, \ + }, \ +} + +struct clk **get_clk_list(void); diff --git a/drivers/clk/meson/include/clk-sm1.h b/drivers/clk/meson/include/clk-sm1.h new file mode 100644 index 000000000..1ac3e05eb --- /dev/null +++ b/drivers/clk/meson/include/clk-sm1.h @@ -0,0 +1,11 @@ +/* + * Copyright 2024, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#define NUM_CLK_LIST 280 diff --git a/drivers/clk/meson/include/g12a-regs.h b/drivers/clk/meson/include/g12a-regs.h new file mode 100644 index 000000000..9c1a91305 --- /dev/null +++ b/drivers/clk/meson/include/g12a-regs.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) */ +/* + * Copyright (c) 2016 Amlogic, Inc. + * Author: Michael Turquette + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai + * Author: Jian Hu + * + * Source: https://github.com/torvalds/linux/blob/20371ba120635d9ab7fc7670497105af8f33eb08/drivers/clk/meson/g12a.h + */ +#ifndef __G12A_H +#define __G12A_H + +/* + * Clock controller register offsets + * + * Register offsets from the data sheet must be multiplied by 4 before + * adding them to the base address to get the right value. + */ +#define HHI_MIPI_CNTL0 0x000 +#define HHI_MIPI_CNTL1 0x004 +#define HHI_MIPI_CNTL2 0x008 +#define HHI_MIPI_STS 0x00C +#define HHI_GP0_PLL_CNTL0 0x040 +#define HHI_GP0_PLL_CNTL1 0x044 +#define HHI_GP0_PLL_CNTL2 0x048 +#define HHI_GP0_PLL_CNTL3 0x04C +#define HHI_GP0_PLL_CNTL4 0x050 +#define HHI_GP0_PLL_CNTL5 0x054 +#define HHI_GP0_PLL_CNTL6 0x058 +#define HHI_GP0_PLL_STS 0x05C +#define HHI_GP1_PLL_CNTL0 0x060 +#define HHI_GP1_PLL_CNTL1 0x064 +#define HHI_GP1_PLL_CNTL2 0x068 +#define HHI_GP1_PLL_CNTL3 0x06C +#define HHI_GP1_PLL_CNTL4 0x070 +#define HHI_GP1_PLL_CNTL5 0x074 +#define HHI_GP1_PLL_CNTL6 0x078 +#define HHI_GP1_PLL_STS 0x07C +#define HHI_PCIE_PLL_CNTL0 0x098 +#define HHI_PCIE_PLL_CNTL1 0x09C +#define HHI_PCIE_PLL_CNTL2 0x0A0 +#define HHI_PCIE_PLL_CNTL3 0x0A4 +#define HHI_PCIE_PLL_CNTL4 0x0A8 +#define HHI_PCIE_PLL_CNTL5 0x0AC +#define HHI_PCIE_PLL_STS 0x0B8 +#define HHI_HIFI_PLL_CNTL0 0x0D8 +#define HHI_HIFI_PLL_CNTL1 0x0DC +#define HHI_HIFI_PLL_CNTL2 0x0E0 +#define HHI_HIFI_PLL_CNTL3 0x0E4 +#define HHI_HIFI_PLL_CNTL4 0x0E8 +#define HHI_HIFI_PLL_CNTL5 0x0EC +#define HHI_HIFI_PLL_CNTL6 0x0F0 +#define HHI_VIID_CLK_DIV 0x128 +#define HHI_VIID_CLK_CNTL 0x12C +#define HHI_GCLK_MPEG0 0x140 +#define HHI_GCLK_MPEG1 0x144 +#define HHI_GCLK_MPEG2 0x148 +#define HHI_GCLK_OTHER 0x150 +#define HHI_GCLK_OTHER2 0x154 +#define HHI_SYS_CPU_CLK_CNTL1 0x15c +#define HHI_VID_CLK_DIV 0x164 +#define HHI_MPEG_CLK_CNTL 0x174 +#define HHI_AUD_CLK_CNTL 0x178 +#define HHI_VID_CLK_CNTL 0x17c +#define HHI_TS_CLK_CNTL 0x190 +#define HHI_VID_CLK_CNTL2 0x194 +#define HHI_SYS_CPU_CLK_CNTL0 0x19c +#define HHI_VID_PLL_CLK_DIV 0x1A0 +#define HHI_MALI_CLK_CNTL 0x1b0 +#define HHI_VPU_CLKC_CNTL 0x1b4 +#define HHI_VPU_CLK_CNTL 0x1bC +#define HHI_ISP_CLK_CNTL 0x1C0 +#define HHI_NNA_CLK_CNTL 0x1C8 +#define HHI_HDMI_CLK_CNTL 0x1CC +#define HHI_VDEC_CLK_CNTL 0x1E0 +#define HHI_VDEC2_CLK_CNTL 0x1E4 +#define HHI_VDEC3_CLK_CNTL 0x1E8 +#define HHI_VDEC4_CLK_CNTL 0x1EC +#define HHI_HDCP22_CLK_CNTL 0x1F0 +#define HHI_VAPBCLK_CNTL 0x1F4 +#define HHI_SYS_CPUB_CLK_CNTL1 0x200 +#define HHI_SYS_CPUB_CLK_CNTL 0x208 +#define HHI_VPU_CLKB_CNTL 0x20C +#define HHI_SYS_CPU_CLK_CNTL2 0x210 +#define HHI_SYS_CPU_CLK_CNTL3 0x214 +#define HHI_SYS_CPU_CLK_CNTL4 0x218 +#define HHI_SYS_CPU_CLK_CNTL5 0x21c +#define HHI_SYS_CPU_CLK_CNTL6 0x220 +#define HHI_GEN_CLK_CNTL 0x228 +#define HHI_VDIN_MEAS_CLK_CNTL 0x250 +#define HHI_MIPIDSI_PHY_CLK_CNTL 0x254 +#define HHI_NAND_CLK_CNTL 0x25C +#define HHI_SD_EMMC_CLK_CNTL 0x264 +#define HHI_MPLL_CNTL0 0x278 +#define HHI_MPLL_CNTL1 0x27C +#define HHI_MPLL_CNTL2 0x280 +#define HHI_MPLL_CNTL3 0x284 +#define HHI_MPLL_CNTL4 0x288 +#define HHI_MPLL_CNTL5 0x28c +#define HHI_MPLL_CNTL6 0x290 +#define HHI_MPLL_CNTL7 0x294 +#define HHI_MPLL_CNTL8 0x298 +#define HHI_FIX_PLL_CNTL0 0x2A0 +#define HHI_FIX_PLL_CNTL1 0x2A4 +#define HHI_FIX_PLL_CNTL3 0x2AC +#define HHI_SYS_PLL_CNTL0 0x2f4 +#define HHI_SYS_PLL_CNTL1 0x2f8 +#define HHI_SYS_PLL_CNTL2 0x2fc +#define HHI_SYS_PLL_CNTL3 0x300 +#define HHI_SYS_PLL_CNTL4 0x304 +#define HHI_SYS_PLL_CNTL5 0x308 +#define HHI_SYS_PLL_CNTL6 0x30c +#define HHI_HDMI_PLL_CNTL0 0x320 +#define HHI_HDMI_PLL_CNTL1 0x324 +#define HHI_HDMI_PLL_CNTL2 0x328 +#define HHI_HDMI_PLL_CNTL3 0x32c +#define HHI_HDMI_PLL_CNTL4 0x330 +#define HHI_HDMI_PLL_CNTL5 0x334 +#define HHI_HDMI_PLL_CNTL6 0x338 +#define HHI_SPICC_CLK_CNTL 0x3dc +#define HHI_SYS1_PLL_CNTL0 0x380 +#define HHI_SYS1_PLL_CNTL1 0x384 +#define HHI_SYS1_PLL_CNTL2 0x388 +#define HHI_SYS1_PLL_CNTL3 0x38c +#define HHI_SYS1_PLL_CNTL4 0x390 +#define HHI_SYS1_PLL_CNTL5 0x394 +#define HHI_SYS1_PLL_CNTL6 0x398 + +#endif /* __G12A_H */ diff --git a/drivers/clk/meson/sm1-clk.c b/drivers/clk/meson/sm1-clk.c new file mode 100644 index 000000000..a47bb4ae4 --- /dev/null +++ b/drivers/clk/meson/sm1-clk.c @@ -0,0 +1,1592 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Amlogic Meson-G12A Clock Controller Driver + * + * Copyright (c) 2016 Baylibre SAS. + * Author: Michael Turquette + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai + * Author: Jian Hu + * + * Derived from: https://github.com/torvalds/linux/blob/befe87380e21f0d37633273e1068c9318f8135ff/drivers/clk/meson/g12a.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +uintptr_t clk_regs; +uintptr_t msr_clk_base; + +static struct clk g12a_xtal = { .data = + &(struct clk_source_data) { + .rate = 24000000, + }, + .hw.init = &(struct clk_init_data) { + .name = "xtal", + .ops = &clk_source_ops, + } }; + +static struct clk g12a_fixed_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = HHI_FIX_PLL_CNTL1, + .shift = 0, + .width = 17, + }, + .l = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_FIX_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .name = "xtal", + }, + .num_parents = 1, + }, +}; +static CLK_DIV_RO(g12a_fixed_pll, HHI_FIX_PLL_CNTL0, 16, 2, CLK_DIVIDER_POWER_OF_TWO, { &g12a_fixed_pll_dco }, 1, 0); +static struct clk g12a_sys_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .l = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_SYS_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + .range_min = 128, + .range_max = 250, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .name = "xtal", + }, + .num_parents = 1, + /* This clock feeds the CPU, avoid disabling it */ + .flags = CLK_IS_CRITICAL, + }, +}; +static CLK_DIV(g12a_sys_pll, HHI_SYS_PLL_CNTL0, 16, 3, CLK_DIVIDER_POWER_OF_TWO, { &g12a_sys_pll_dco }, 1, 0); +static CLK_GATE_RO(g12a_sys_pll_div16_en, HHI_SYS_CPU_CLK_CNTL1, 24, 0, { &g12a_sys_pll }, 1, 0); +static CLK_FIXED_FACTOR(g12a_sys_pll_div16, 1, 16, 0, { &g12a_sys_pll_div16_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_fclk_div2_div, 1, 2, 0, { &g12a_fixed_pll }, 1, 0); +static CLK_GATE(g12a_fclk_div2, HHI_FIX_PLL_CNTL1, 24, 0, { &g12a_fclk_div2_div }, 1, 0); +static CLK_FIXED_FACTOR(g12a_fclk_div3_div, 1, 3, 0, { &g12a_fixed_pll }, 1, 0); +static CLK_GATE(g12a_fclk_div3, HHI_FIX_PLL_CNTL1, 20, 0, { &g12a_fclk_div3_div }, 1, 0); +const struct clk_parent_data g12a_cpu_clk_premux0_parent_table[] = { + { + .name = "xtal", + }, + { .clk = &g12a_fclk_div2 }, + { .clk = &g12a_fclk_div3 }, +}; +static CLK_MUX(g12a_cpu_clk_premux0, HHI_SYS_CPU_CLK_CNTL0, 0x3, 0, 0, CLK_MUX_ROUND_CLOSEST, + g12a_cpu_clk_premux0_parent_table, 3, 0); +const struct clk_parent_data g12a_cpu_clk_premux1_parent_table[] = { + { + .name = "xtal", + }, + { .clk = &g12a_fclk_div2 }, + { .clk = &g12a_fclk_div3 }, +}; +static CLK_MUX(g12a_cpu_clk_premux1, HHI_SYS_CPU_CLK_CNTL0, 0x3, 16, 0, 0, g12a_cpu_clk_premux1_parent_table, 3, 0); +static struct clk g12a_cpu_clk_mux0_div = { + .data = &(struct meson_clk_cpu_dyndiv_data){ + .div = { + .reg_off = HHI_SYS_CPU_CLK_CNTL0, + .shift = 4, + .width = 6, + }, + .dyn = { + .reg_off = HHI_SYS_CPU_CLK_CNTL0, + .shift = 26, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn0_div", + .ops = &meson_clk_cpu_dyndiv_ops, + .parent_clks = (const struct clk *[]) { + &g12a_cpu_clk_premux0 + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; +const struct clk_parent_data g12a_cpu_clk_postmux0_parent_table[] = { + { .clk = &g12a_cpu_clk_premux0 }, + { .clk = &g12a_cpu_clk_mux0_div }, +}; +static CLK_MUX(g12a_cpu_clk_postmux0, HHI_SYS_CPU_CLK_CNTL0, 0x1, 2, 0, CLK_MUX_ROUND_CLOSEST, + g12a_cpu_clk_postmux0_parent_table, 2, 0); +static CLK_DIV_RO(g12a_cpu_clk_mux1_div, HHI_SYS_CPU_CLK_CNTL0, 20, 6, 0, { &g12a_cpu_clk_premux1 }, 1, 0); +const struct clk_parent_data g12a_cpu_clk_postmux1_parent_table[] = { + { .clk = &g12a_cpu_clk_premux1 }, + { .clk = &g12a_cpu_clk_mux1_div }, +}; +static CLK_MUX(g12a_cpu_clk_postmux1, HHI_SYS_CPU_CLK_CNTL0, 0x1, 18, 0, 0, g12a_cpu_clk_postmux1_parent_table, 2, 0); +const struct clk_parent_data g12a_cpu_clk_dyn_parent_table[] = { + { .clk = &g12a_cpu_clk_postmux0 }, + { .clk = &g12a_cpu_clk_postmux1 }, +}; +static CLK_MUX(g12a_cpu_clk_dyn, HHI_SYS_CPU_CLK_CNTL0, 0x1, 10, 0, CLK_MUX_ROUND_CLOSEST, + g12a_cpu_clk_dyn_parent_table, 2, 0); +const struct clk_parent_data g12a_cpu_clk_parent_table[] = { + { .clk = &g12a_cpu_clk_dyn }, + { .clk = &g12a_sys_pll }, +}; +static CLK_MUX(g12a_cpu_clk, HHI_SYS_CPU_CLK_CNTL0, 0x1, 11, 0, CLK_MUX_ROUND_CLOSEST, g12a_cpu_clk_parent_table, 2, 0); + +static const struct reg_sequence g12a_gp0_init_regs[] = { + { .reg = HHI_GP0_PLL_CNTL1, .def = 0x00000000 }, { .reg = HHI_GP0_PLL_CNTL2, .def = 0x00000000 }, + { .reg = HHI_GP0_PLL_CNTL3, .def = 0x48681c00 }, { .reg = HHI_GP0_PLL_CNTL4, .def = 0x33771290 }, + { .reg = HHI_GP0_PLL_CNTL5, .def = 0x39272000 }, { .reg = HHI_GP0_PLL_CNTL6, .def = 0x56540000 }, +}; +static struct clk g12a_gp0_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = HHI_GP0_PLL_CNTL1, + .shift = 0, + .width = 17, + }, + .l = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_GP0_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + .range_min = 125, + .range_max = 255, + .init_regs = g12a_gp0_init_regs, + .init_count = ARRAY_SIZE(g12a_gp0_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "gp0_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .name = "xtal", + }, + .num_parents = 1, + }, +}; +static CLK_DIV(g12a_gp0_pll, HHI_GP0_PLL_CNTL0, 16, 3, (CLK_DIVIDER_POWER_OF_TWO | CLK_DIVIDER_ROUND_CLOSEST), + { &g12a_gp0_pll_dco }, 1, 0); +static struct clk sm1_gp1_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = HHI_GP1_PLL_CNTL1, + .shift = 0, + .width = 17, + }, + .l = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_GP1_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "gp1_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .name = "xtal", + }, + .num_parents = 1, + /* This clock feeds the DSU, avoid disabling it */ + .flags = CLK_IS_CRITICAL, + }, +}; +static CLK_DIV_RO(sm1_gp1_pll, HHI_GP1_PLL_CNTL0, 16, 3, (CLK_DIVIDER_POWER_OF_TWO | CLK_DIVIDER_ROUND_CLOSEST), + { &sm1_gp1_pll_dco }, 1, 0); + +const struct clk_parent_data sm1_dsu_clk_premux0_parent_table[] = { + { + .name = "xtal", + }, + { .clk = &g12a_fclk_div2 }, + { .clk = &g12a_fclk_div3 }, + { .clk = &sm1_gp1_pll }, +}; +static CLK_MUX_RO(sm1_dsu_clk_premux0, HHI_SYS_CPU_CLK_CNTL5, 0x3, 0, 0, 0, sm1_dsu_clk_premux0_parent_table, 4, 0); +const struct clk_parent_data sm1_dsu_clk_premux1_parent_table[] = { + { + .name = "xtal", + }, + { .clk = &g12a_fclk_div2 }, + { .clk = &g12a_fclk_div3 }, + { .clk = &sm1_gp1_pll }, +}; +static CLK_MUX_RO(sm1_dsu_clk_premux1, HHI_SYS_CPU_CLK_CNTL5, 0x3, 16, 0, 0, sm1_dsu_clk_premux1_parent_table, 4, 0); +static CLK_DIV_RO(sm1_dsu_clk_mux0_div, HHI_SYS_CPU_CLK_CNTL5, 4, 6, 0, { &sm1_dsu_clk_premux0 }, 1, 0); +const struct clk_parent_data sm1_dsu_clk_postmux0_parent_table[] = { + { + .clk = &sm1_dsu_clk_premux0, + }, + { .clk = &sm1_dsu_clk_mux0_div }, +}; +static CLK_MUX_RO(sm1_dsu_clk_postmux0, HHI_SYS_CPU_CLK_CNTL5, 0x1, 2, 0, 0, sm1_dsu_clk_postmux0_parent_table, 2, 0); +static CLK_DIV_RO(sm1_dsu_clk_mux1_div, HHI_SYS_CPU_CLK_CNTL5, 20, 6, 0, { &sm1_dsu_clk_premux1 }, 1, 0); + +const struct clk_parent_data sm1_dsu_clk_postmux1_parent_table[] = { + { + .clk = &sm1_dsu_clk_premux1, + }, + { .clk = &sm1_dsu_clk_mux1_div }, +}; +static CLK_MUX_RO(sm1_dsu_clk_postmux1, HHI_SYS_CPU_CLK_CNTL5, 0x1, 18, 0, 0, sm1_dsu_clk_postmux1_parent_table, 2, 0); +const struct clk_parent_data sm1_dsu_clk_dyn_parent_table[] = { + { + .clk = &sm1_dsu_clk_premux0, + }, + { + .clk = &sm1_dsu_clk_postmux1, + }, +}; +static CLK_MUX_RO(sm1_dsu_clk_dyn, HHI_SYS_CPU_CLK_CNTL5, 0x1, 10, 0, 0, sm1_dsu_clk_dyn_parent_table, 2, 0); +const struct clk_parent_data sm1_dsu_final_clk_parent_table[] = { + { + .clk = &sm1_dsu_clk_dyn, + }, + { + .clk = &g12a_sys_pll, + }, +}; +static CLK_MUX_RO(sm1_dsu_final_clk, HHI_SYS_CPU_CLK_CNTL5, 0x1, 11, 0, 0, sm1_dsu_final_clk_parent_table, 2, 0); +const struct clk_parent_data sm1_cpu_clk_parent_table[] = { + { + .clk = &g12a_cpu_clk, + }, +}; +static CLK_MUX_RO(sm1_cpu1_clk, HHI_SYS_CPU_CLK_CNTL6, 0x1, 24, 0, 0, sm1_cpu_clk_parent_table, 1, 0); +static CLK_MUX_RO(sm1_cpu2_clk, HHI_SYS_CPU_CLK_CNTL6, 0x1, 25, 0, 0, sm1_cpu_clk_parent_table, 1, 0); +static CLK_MUX_RO(sm1_cpu3_clk, HHI_SYS_CPU_CLK_CNTL6, 0x1, 26, 0, 0, sm1_cpu_clk_parent_table, 1, 0); +const struct clk_parent_data sm1_dsu_clk_parent_table[] = { + { + .clk = &g12a_cpu_clk, + }, + { + .clk = &sm1_dsu_final_clk, + }, +}; +static CLK_MUX_RO(sm1_dsu_clk, HHI_SYS_CPU_CLK_CNTL6, 0x1, 27, 0, 0, sm1_dsu_clk_parent_table, 2, 0); +static CLK_GATE_RO(g12a_cpu_clk_div16_en, HHI_SYS_CPU_CLK_CNTL1, 1, 0, { &g12a_cpu_clk }, 1, 0); +static CLK_FIXED_FACTOR(g12a_cpu_clk_div16, 1, 16, 0, { &g12a_cpu_clk_div16_en }, 1, 0); +static CLK_DIV_RO(g12a_cpu_clk_apb_div, HHI_SYS_CPU_CLK_CNTL1, 3, 3, CLK_DIVIDER_POWER_OF_TWO, { &g12a_cpu_clk }, 1, 0); +static CLK_GATE_RO(g12a_cpu_clk_apb, HHI_SYS_CPU_CLK_CNTL1, 1, 0, { &g12a_cpu_clk_apb_div }, 1, 0); +static CLK_DIV_RO(g12a_cpu_clk_atb_div, HHI_SYS_CPU_CLK_CNTL1, 6, 3, CLK_DIVIDER_POWER_OF_TWO, { &g12a_cpu_clk }, 1, 0); +static CLK_GATE_RO(g12a_cpu_clk_atb, HHI_SYS_CPU_CLK_CNTL1, 17, 0, { &g12a_cpu_clk_atb_div }, 1, 0); +static CLK_DIV_RO(g12a_cpu_clk_axi_div, HHI_SYS_CPU_CLK_CNTL1, 9, 3, CLK_DIVIDER_POWER_OF_TWO, { &g12a_cpu_clk }, 1, 0); +static CLK_GATE_RO(g12a_cpu_clk_axi, HHI_SYS_CPU_CLK_CNTL1, 18, 0, { &g12a_cpu_clk_axi_div }, 1, 0); +/* TODO: special case, ignore its parent clk at the moment */ +static CLK_DIV_RO(g12a_cpu_clk_trace_div, HHI_SYS_CPU_CLK_CNTL1, 20, 3, CLK_DIVIDER_POWER_OF_TWO, {}, 0, 0); +static CLK_GATE_RO(g12a_cpu_clk_trace, HHI_SYS_CPU_CLK_CNTL1, 23, 0, { &g12a_cpu_clk_trace_div }, 1, 0); + +static const struct reg_sequence g12a_hifi_init_regs[] = { + { .reg = HHI_HIFI_PLL_CNTL1, .def = 0x00000000 }, { .reg = HHI_HIFI_PLL_CNTL2, .def = 0x00000000 }, + { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x6a285c00 }, { .reg = HHI_HIFI_PLL_CNTL4, .def = 0x65771290 }, + { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x39272000 }, { .reg = HHI_HIFI_PLL_CNTL6, .def = 0x56540000 }, +}; + +static struct clk g12a_hifi_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = HHI_HIFI_PLL_CNTL1, + .shift = 0, + .width = 17, + }, + .l = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_HIFI_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + .range_min = 125, + .range_max = 255, + .init_regs = g12a_hifi_init_regs, + .init_count = ARRAY_SIZE(g12a_hifi_init_regs), + .flags = CLK_MESON_PLL_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll_dco", + .ops = &meson_clk_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .name = "xtal", + }, + .num_parents = 1, + }, +}; +static CLK_DIV(g12a_hifi_pll, HHI_HIFI_PLL_CNTL0, 16, 2, (CLK_DIVIDER_POWER_OF_TWO | CLK_DIVIDER_ROUND_CLOSEST), + { &g12a_hifi_pll_dco }, 1, 0); + +/* + * The Meson G12A PCIE PLL is fined tuned to deliver a very precise + * 100MHz reference clock for the PCIe Analog PHY, and thus requires + * a strict register sequence to enable the PLL. + */ +static const struct reg_sequence g12a_pcie_pll_init_regs[] = { + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x20090496 }, + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x30090496 }, + { .reg = HHI_PCIE_PLL_CNTL1, .def = 0x00000000 }, + { .reg = HHI_PCIE_PLL_CNTL2, .def = 0x00001100 }, + { .reg = HHI_PCIE_PLL_CNTL3, .def = 0x10058e00 }, + { .reg = HHI_PCIE_PLL_CNTL4, .def = 0x000100c0 }, + { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x68000048 }, + { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x68000068, .delay_us = 20 }, + { .reg = HHI_PCIE_PLL_CNTL4, .def = 0x008100c0, .delay_us = 10 }, + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x34090496 }, + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x14090496, .delay_us = 10 }, + { .reg = HHI_PCIE_PLL_CNTL2, .def = 0x00001000 }, +}; +/* Keep a single entry table for recalc/round_rate() ops */ +static const struct pll_params_table g12a_pcie_pll_table[] = { + { .m = 150, .n = 1 }, + { .m = 0, .n = 0 }, +}; +static struct clk g12a_pcie_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = HHI_PCIE_PLL_CNTL1, + .shift = 0, + .width = 12, + }, + .l = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + .table = g12a_pcie_pll_table, + .init_regs = g12a_pcie_pll_init_regs, + .init_count = ARRAY_SIZE(g12a_pcie_pll_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "pcie_pll_dco", + .ops = &meson_clk_pcie_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .name = "xtal", + }, + .num_parents = 1, + }, +}; +static CLK_FIXED_FACTOR(g12a_pcie_pll_dco_div2, 1, 2, 0, { &g12a_pcie_pll_dco }, 1, 0); +static CLK_DIV(g12a_pcie_pll_od, HHI_PCIE_PLL_CNTL0, 16, 5, + CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, { &g12a_pcie_pll_dco_div2 }, + 1, 0); +static CLK_FIXED_FACTOR(g12a_pcie_pll, 1, 2, 0, { &g12a_pcie_pll_od }, 1, 0); +static struct clk g12a_hdmi_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_HDMI_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_HDMI_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_HDMI_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = HHI_HDMI_PLL_CNTL1, + .shift = 0, + .width = 16, + }, + .l = { + .reg_off = HHI_HDMI_PLL_CNTL0, + .shift = 30, + .width = 1, + }, + .rst = { + .reg_off = HHI_HDMI_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "hdmi_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .name = "xtal", + }, + .num_parents = 1, + /* + * Display directly handle hdmi pll registers ATM, we need + * NOCACHE to keep our view of the clock as accurate as possible + */ + .flags = CLK_GET_RATE_NOCACHE, + }, +}; +static CLK_DIV_RO(g12a_hdmi_pll_od, HHI_HDMI_PLL_CNTL0, 16, 2, CLK_DIVIDER_POWER_OF_TWO, { &g12a_hdmi_pll_dco }, 1, 0); +static CLK_DIV_RO(g12a_hdmi_pll_od2, HHI_HDMI_PLL_CNTL0, 18, 2, CLK_DIVIDER_POWER_OF_TWO, { &g12a_hdmi_pll_od }, 1, 0); +static CLK_DIV_RO(g12a_hdmi_pll, HHI_HDMI_PLL_CNTL0, 20, 2, CLK_DIVIDER_POWER_OF_TWO, { &g12a_hdmi_pll_od2 }, 1, 0); +static CLK_FIXED_FACTOR(g12a_fclk_div4_div, 1, 4, 0, { &g12a_fixed_pll }, 1, 0); +static CLK_GATE(g12a_fclk_div4, HHI_FIX_PLL_CNTL1, 21, 0, { &g12a_fclk_div4_div }, 1, 0); +static CLK_FIXED_FACTOR(g12a_fclk_div5_div, 1, 5, 0, { &g12a_fixed_pll }, 1, 0); +static CLK_GATE(g12a_fclk_div5, HHI_FIX_PLL_CNTL1, 22, 0, { &g12a_fclk_div5_div }, 1, 0); +static CLK_FIXED_FACTOR(g12a_fclk_div7_div, 1, 7, 0, { &g12a_fixed_pll }, 1, 0); +static CLK_GATE(g12a_fclk_div7, HHI_FIX_PLL_CNTL1, 23, 0, { &g12a_fclk_div7_div }, 1, 0); +static CLK_FIXED_FACTOR(g12a_fclk_div2p5_div, 1, 5, 0, { &g12a_fixed_pll_dco }, 1, 0); +static CLK_GATE(g12a_fclk_div2p5, HHI_FIX_PLL_CNTL1, 25, 0, { &g12a_fclk_div2p5_div }, 1, 0); +static CLK_FIXED_FACTOR(g12a_mpll_50m_div, 1, 80, 0, { &g12a_fixed_pll_dco }, 1, 0); +const static struct clk_parent_data g12a_mpll_50m_parent_table[] = { + { + .name = "xtal", + }, + { .clk = &g12a_mpll_50m_div }, +}; +static CLK_MUX_RO(g12a_mpll_50m, HHI_FIX_PLL_CNTL3, 0x1, 5, 0, 0, g12a_mpll_50m_parent_table, 2, 0); +static CLK_FIXED_FACTOR(g12a_mpll_prediv, 1, 2, 0, { &g12a_fixed_pll_dco }, 1, 0); + +static const struct reg_sequence g12a_mpll0_init_regs[] = { + { .reg = HHI_MPLL_CNTL2, .def = 0x40000033 }, +}; +static struct clk g12a_mpll0_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL1, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL1, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL1, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = HHI_MPLL_CNTL1, + .shift = 29, + .width = 1, + }, + /* .lock = &meson_clk_lock, */ + .init_regs = g12a_mpll0_init_regs, + .init_count = ARRAY_SIZE(g12a_mpll0_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll0_div", + .ops = &meson_clk_mpll_ops, + .parent_clks = (const struct clk *[]) { + &g12a_mpll_prediv + }, + .num_parents = 1, + }, +}; +static CLK_GATE(g12a_mpll0, HHI_MPLL_CNTL1, 31, 0, { &g12a_mpll0_div }, 1, 0); +static const struct reg_sequence g12a_mpll1_init_regs[] = { + { .reg = HHI_MPLL_CNTL4, .def = 0x40000033 }, +}; +static struct clk g12a_mpll1_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL3, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL3, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL3, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = HHI_MPLL_CNTL3, + .shift = 29, + .width = 1, + }, + /* .lock = &meson_clk_lock, */ + .init_regs = g12a_mpll1_init_regs, + .init_count = ARRAY_SIZE(g12a_mpll1_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll1_div", + .ops = &meson_clk_mpll_ops, + .parent_clks = (const struct clk *[]) { + &g12a_mpll_prediv + }, + .num_parents = 1, + }, +}; +static CLK_GATE(g12a_mpll1, HHI_MPLL_CNTL3, 31, 0, { &g12a_mpll1_div }, 1, 0); +static const struct reg_sequence g12a_mpll2_init_regs[] = { + { .reg = HHI_MPLL_CNTL6, .def = 0x40000033 }, +}; +static struct clk g12a_mpll2_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL5, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL5, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL5, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = HHI_MPLL_CNTL5, + .shift = 29, + .width = 1, + }, + /* .lock = &meson_clk_lock, */ + .init_regs = g12a_mpll2_init_regs, + .init_count = ARRAY_SIZE(g12a_mpll2_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll2_div", + .ops = &meson_clk_mpll_ops, + .parent_clks = (const struct clk *[]) { + &g12a_mpll_prediv + }, + .num_parents = 1, + }, +}; +static CLK_GATE(g12a_mpll2, HHI_MPLL_CNTL5, 31, 0, { &g12a_mpll2_div }, 1, 0); +static const struct reg_sequence g12a_mpll3_init_regs[] = { + { .reg = HHI_MPLL_CNTL8, .def = 0x40000033 }, +}; +static struct clk g12a_mpll3_div = { + .data = &(struct meson_clk_mpll_data){ + .sdm = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 0, + .width = 14, + }, + .sdm_en = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 30, + .width = 1, + }, + .n2 = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 20, + .width = 9, + }, + .ssen = { + .reg_off = HHI_MPLL_CNTL7, + .shift = 29, + .width = 1, + }, + /* .lock = &meson_clk_lock, */ + .init_regs = g12a_mpll3_init_regs, + .init_count = ARRAY_SIZE(g12a_mpll3_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "mpll3_div", + .ops = &meson_clk_mpll_ops, + .parent_clks = (const struct clk *[]) { + &g12a_mpll_prediv + }, + .num_parents = 1, + }, +}; +static CLK_GATE(g12a_mpll3, HHI_MPLL_CNTL7, 31, 0, { &g12a_mpll3_div }, 1, 0); + +static uint32_t mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; +static const struct clk_parent_data clk81_parent_data[] = { + { + .name = "xtal", + }, + { .clk = &g12a_fclk_div7 }, + { .clk = &g12a_mpll1 }, + { .clk = &g12a_mpll2 }, + { .clk = &g12a_fclk_div4 }, + { .clk = &g12a_fclk_div3 }, + { .clk = &g12a_fclk_div5 }, +}; +static CLK_MUX_RO(g12a_mpeg_clk_sel, HHI_MPEG_CLK_CNTL, 0x7, 12, mux_table_clk81, 0, clk81_parent_data, + ARRAY_SIZE(clk81_parent_data), 0); +static CLK_DIV(g12a_mpeg_clk_div, HHI_MPEG_CLK_CNTL, 0, 7, 0, { &g12a_mpeg_clk_sel }, 1, 0); +static CLK_GATE(g12a_clk81, HHI_MPEG_CLK_CNTL, 7, 0, { &g12a_mpeg_clk_div }, 1, 0); +static const struct clk_parent_data g12a_sd_emmc_clk0_parent_data[] = { + { + .name = "xtal", + }, + { .clk = &g12a_fclk_div2 }, + { .clk = &g12a_fclk_div3 }, + { .clk = &g12a_fclk_div5 }, + { .clk = &g12a_fclk_div7 }, +}; +static CLK_MUX(g12a_sd_emmc_a_clk0_sel, HHI_SD_EMMC_CLK_CNTL, 0x7, 9, 0, 0, g12a_sd_emmc_clk0_parent_data, 5, + CLK_SET_RATE_PARENT); +static CLK_DIV(g12a_sd_emmc_a_clk0_div, HHI_SD_EMMC_CLK_CNTL, 0, 7, 0, { &g12a_sd_emmc_a_clk0_sel }, 1, 0); +static CLK_GATE(g12a_sd_emmc_a_clk0, HHI_SD_EMMC_CLK_CNTL, 7, 0, { &g12a_sd_emmc_a_clk0_div }, 1, 0); +static CLK_MUX(g12a_sd_emmc_b_clk0_sel, HHI_SD_EMMC_CLK_CNTL, 0x7, 25, 0, 0, g12a_sd_emmc_clk0_parent_data, 5, + CLK_SET_RATE_PARENT); +static CLK_DIV(g12a_sd_emmc_b_clk0_div, HHI_SD_EMMC_CLK_CNTL, 16, 7, 0, { &g12a_sd_emmc_b_clk0_sel }, 1, 0); +static CLK_GATE(g12a_sd_emmc_b_clk0, HHI_SD_EMMC_CLK_CNTL, 23, 0, { &g12a_sd_emmc_b_clk0_div }, 1, 0); +static CLK_MUX(g12a_sd_emmc_c_clk0_sel, HHI_NAND_CLK_CNTL, 0x7, 9, 0, 0, g12a_sd_emmc_clk0_parent_data, 5, + CLK_SET_RATE_PARENT); +static CLK_DIV(g12a_sd_emmc_c_clk0_div, HHI_NAND_CLK_CNTL, 0, 7, 0, { &g12a_sd_emmc_c_clk0_sel }, 1, 0); +static CLK_GATE(g12a_sd_emmc_c_clk0, HHI_NAND_CLK_CNTL, 7, 0, { &g12a_sd_emmc_c_clk0_div }, 1, 0); +static struct clk g12a_vid_pll_div = { + .data = &(struct meson_vid_pll_div_data){ + .val = { + .reg_off = HHI_VID_PLL_CLK_DIV, + .shift = 0, + .width = 15, + }, + .sel = { + .reg_off = HHI_VID_PLL_CLK_DIV, + .shift = 16, + .width = 2, + }, + }, + .hw.init = &(struct clk_init_data) { + .name = "vid_pll_div", + .ops = &meson_vid_pll_div_ro_ops, + .parent_clks = (const struct clk *[]) { &g12a_hdmi_pll }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, + }, +}; +static const struct clk_parent_data g12a_vid_pll_parent_table[] = { + { + .clk = &g12a_vid_pll_div, + }, + { + .clk = &g12a_hdmi_pll, + }, +}; + +static CLK_MUX(g12a_vid_pll_sel, HHI_VID_PLL_CLK_DIV, 0x1, 18, 0, 0, g12a_vid_pll_parent_table, 0, + CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE); +static CLK_GATE(g12a_vid_pll, HHI_VID_PLL_CLK_DIV, 19, 0, { &g12a_vid_pll_sel }, 1, 0); +const static struct clk_parent_data g12a_vpu_sel_parent_table[] = { + { + .clk = &g12a_fclk_div3, + }, + { + .clk = &g12a_fclk_div4, + }, + { + .clk = &g12a_fclk_div5, + }, + { + .clk = &g12a_fclk_div7, + }, + { + .clk = &g12a_mpll1, + }, + { + .clk = &g12a_vid_pll, + }, + { + .clk = &g12a_hifi_pll, + }, + { + .clk = &g12a_gp0_pll, + }, +}; +static CLK_MUX(g12a_vpu_0_sel, HHI_VPU_CLK_CNTL, 0x7, 9, 0, 0, g12a_vpu_sel_parent_table, 0, CLK_SET_RATE_NO_REPARENT); +static CLK_DIV(g12a_vpu_0_div, HHI_VPU_CLK_CNTL, 0, 7, 0, { &g12a_vpu_0_sel }, 1, 0); +static CLK_GATE(g12a_vpu_0, HHI_VPU_CLK_CNTL, 8, 0, { &g12a_vpu_0_div }, 1, 0); +static CLK_MUX(g12a_vpu_1_sel, HHI_VPU_CLK_CNTL, 0x7, 25, 0, 0, g12a_vpu_sel_parent_table, 0, CLK_SET_RATE_NO_REPARENT); +static CLK_DIV(g12a_vpu_1_div, HHI_VPU_CLK_CNTL, 16, 7, 0, { &g12a_vpu_1_sel }, 1, 0); +static CLK_GATE(g12a_vpu_1, HHI_VPU_CLK_CNTL, 24, 0, { &g12a_vpu_1_div }, 1, 0); +const struct clk_parent_data g12a_vpu_parent_table[] = { + { .clk = &g12a_vpu_0 }, + { .clk = &g12a_vpu_1 }, +}; +static CLK_MUX(g12a_vpu, HHI_VPU_CLK_CNTL, 1, 31, 0, 0, g12a_vpu_parent_table, 2, 0); +static const struct clk_parent_data g12a_vdec_parent_table[] = { + { + .clk = &g12a_fclk_div2p5, + }, + { + .clk = &g12a_fclk_div3, + }, + { + .clk = &g12a_fclk_div4, + }, + { + .clk = &g12a_fclk_div5, + }, + { + .clk = &g12a_fclk_div7, + }, + { + .clk = &g12a_hifi_pll, + }, + { + .clk = &g12a_gp0_pll, + }, +}; + +static CLK_MUX(g12a_vdec_1_sel, HHI_VDEC_CLK_CNTL, 0x7, 9, 0, CLK_MUX_ROUND_CLOSEST, g12a_vdec_parent_table, 7, + CLK_SET_RATE_PARENT); +static CLK_DIV(g12a_vdec_1_div, HHI_VDEC_CLK_CNTL, 0, 7, CLK_DIVIDER_ROUND_CLOSEST, { &g12a_vdec_1_sel }, 1, 0); +static CLK_GATE(g12a_vdec_1, HHI_VDEC_CLK_CNTL, 8, 0, { &g12a_vdec_1_div }, 1, 0); +static CLK_MUX(g12a_vdec_hevcf_sel, HHI_VDEC2_CLK_CNTL, 0x7, 9, 0, CLK_MUX_ROUND_CLOSEST, g12a_vdec_parent_table, 7, + CLK_SET_RATE_PARENT); +static CLK_DIV(g12a_vdec_hevcf_div, HHI_VDEC2_CLK_CNTL, 0, 7, CLK_DIVIDER_ROUND_CLOSEST, { &g12a_vdec_hevcf_sel }, 1, + 0); +static CLK_GATE(g12a_vdec_hevcf, HHI_VDEC2_CLK_CNTL, 8, 0, { &g12a_vdec_hevcf_div }, 1, 0); +static CLK_MUX(g12a_vdec_hevc_sel, HHI_VDEC2_CLK_CNTL, 0x7, 25, 0, CLK_MUX_ROUND_CLOSEST, g12a_vdec_parent_table, 7, + CLK_SET_RATE_PARENT); +static CLK_DIV(g12a_vdec_hevc_div, HHI_VDEC2_CLK_CNTL, 16, 7, CLK_DIVIDER_ROUND_CLOSEST, { &g12a_vdec_hevc_sel }, 1, 0); +static CLK_GATE(g12a_vdec_hevc, HHI_VDEC2_CLK_CNTL, 24, 0, { &g12a_vdec_hevc_div }, 1, 0); +static const struct clk_parent_data g12a_vapb_parent_table[] = { + { + .clk = &g12a_fclk_div4, + }, + { + .clk = &g12a_fclk_div3, + }, + { + .clk = &g12a_fclk_div5, + }, + { + .clk = &g12a_fclk_div7, + }, + { + .clk = &g12a_mpll1, + }, + { + .clk = &g12a_vid_pll, + }, + { + .clk = &g12a_mpll2, + }, + { + .clk = &g12a_fclk_div2p5, + }, +}; +static CLK_MUX(g12a_vapb_0_sel, HHI_VAPBCLK_CNTL, 0x3, 9, 0, 0, g12a_vapb_parent_table, 8, CLK_SET_RATE_NO_REPARENT); +static CLK_DIV(g12a_vapb_0_div, HHI_VAPBCLK_CNTL, 0, 7, 0, { &g12a_vapb_0_sel }, 1, 0); +static CLK_GATE(g12a_vapb_0, HHI_VAPBCLK_CNTL, 8, 0, { &g12a_vapb_0_div }, 1, 0); +static CLK_MUX(g12a_vapb_1_sel, HHI_VAPBCLK_CNTL, 0x3, 25, 0, 0, g12a_vapb_parent_table, 8, CLK_SET_RATE_NO_REPARENT); +static CLK_DIV(g12a_vapb_1_div, HHI_VAPBCLK_CNTL, 16, 7, 0, { &g12a_vapb_1_sel }, 1, 0); +static CLK_GATE(g12a_vapb_1, HHI_VAPBCLK_CNTL, 24, 0, { &g12a_vapb_1_div }, 1, 0); +const struct clk_parent_data g12a_vapb_sel_parent_table[] = { + { .clk = &g12a_vapb_0 }, + { .clk = &g12a_vapb_1 }, +}; +static CLK_MUX(g12a_vapb_sel, HHI_VAPBCLK_CNTL, 1, 31, 0, 0, g12a_vapb_sel_parent_table, 2, 0); +static CLK_GATE(g12a_vapb, HHI_VAPBCLK_CNTL, 30, 0, { &g12a_vapb_sel }, 1, 0); +static const struct clk_parent_data g12a_vclk_parent_table[] = { + { + .clk = &g12a_vid_pll, + }, + { + .clk = &g12a_gp0_pll, + }, + { + .clk = &g12a_hifi_pll, + }, + { + .clk = &g12a_mpll1, + }, + { + .clk = &g12a_fclk_div3, + }, + { + .clk = &g12a_fclk_div4, + }, + { + .clk = &g12a_fclk_div5, + }, + { + .clk = &g12a_fclk_div7, + }, +}; +static CLK_MUX(g12a_vclk_sel, HHI_VID_CLK_CNTL, 0x7, 16, 0, 0, g12a_vclk_parent_table, 8, + CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE); +static CLK_MUX(g12a_vclk2_sel, HHI_VIID_CLK_CNTL, 0x7, 16, 0, 0, g12a_vclk_parent_table, 8, CLK_SET_RATE_NO_REPARENT); +static CLK_GATE(g12a_vclk_input, HHI_VID_CLK_DIV, 16, 0, { &g12a_vclk_sel }, 1, 0); +static CLK_GATE(g12a_vclk2_input, HHI_VIID_CLK_DIV, 16, 0, { &g12a_vclk2_sel }, 1, 0); +static CLK_DIV(g12a_vclk_div, HHI_VID_CLK_DIV, 0, 8, 0, { &g12a_vclk_input }, 1, 0); +static struct clk g12a_vclk2_div = { + .data = &(struct meson_vclk_div_data){ + .div = { + .reg_off = HHI_VIID_CLK_DIV, + .shift = 0, + .width = 8, + }, + .enable = { + .reg_off = HHI_VIID_CLK_DIV, + .shift = 16, + .width = 1, + }, + .reset = { + .reg_off = HHI_VIID_CLK_DIV, + .shift = 17, + .width = 1, + }, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_div", + .ops = &meson_vclk_div_ops, + .parent_clks = (const struct clk *[]) { + &g12a_vclk2_input + }, + .num_parents = 1, + .flags = CLK_SET_RATE_GATE, + }, +}; +static CLK_GATE(g12a_vclk, HHI_VID_CLK_CNTL, 19, 0, { &g12a_vclk_div }, 1, 0); +static struct clk g12a_vclk2 = { + .data = &(struct meson_vclk_gate_data){ + .enable = { + .reg_off = HHI_VIID_CLK_CNTL, + .shift = 19, + .width = 1, + }, + .reset = { + .reg_off = HHI_VIID_CLK_CNTL, + .shift = 15, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data) { + .name = "vclk2", + .ops = &meson_vclk_gate_ops, + .parent_clks = (const struct clk *[]) { &g12a_vclk2_div }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; +static CLK_GATE(g12a_vclk_div1, HHI_VID_CLK_CNTL, 0, 0, { &g12a_vclk }, 1, 0); +static CLK_GATE(g12a_vclk_div2_en, HHI_VID_CLK_CNTL, 1, 0, { &g12a_vclk }, 1, 0); +static CLK_GATE(g12a_vclk_div4_en, HHI_VID_CLK_CNTL, 2, 0, { &g12a_vclk }, 1, 0); +static CLK_GATE(g12a_vclk_div6_en, HHI_VID_CLK_CNTL, 3, 0, { &g12a_vclk }, 1, 0); +static CLK_GATE(g12a_vclk_div12_en, HHI_VID_CLK_CNTL, 4, 0, { &g12a_vclk }, 1, 0); +static CLK_GATE(g12a_vclk2_div1, HHI_VIID_CLK_CNTL, 0, 0, { &g12a_vclk2 }, 1, 0); +static CLK_GATE(g12a_vclk2_div2_en, HHI_VIID_CLK_CNTL, 1, 0, { &g12a_vclk2 }, 1, 0); +static CLK_GATE(g12a_vclk2_div4_en, HHI_VIID_CLK_CNTL, 2, 0, { &g12a_vclk2 }, 1, 0); +static CLK_GATE(g12a_vclk2_div6_en, HHI_VIID_CLK_CNTL, 3, 0, { &g12a_vclk2 }, 1, 0); +static CLK_GATE(g12a_vclk2_div12_en, HHI_VIID_CLK_CNTL, 4, 0, { &g12a_vclk2 }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk_div2, 1, 2, 0, { &g12a_vclk_div2_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk_div4, 1, 4, 0, { &g12a_vclk_div4_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk_div6, 1, 6, 0, { &g12a_vclk_div6_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk_div12, 1, 12, 0, { &g12a_vclk_div12_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk2_div2, 1, 2, 0, { &g12a_vclk2_div2_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk2_div4, 1, 4, 0, { &g12a_vclk2_div4_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk2_div6, 1, 6, 0, { &g12a_vclk2_div6_en }, 1, 0); +static CLK_FIXED_FACTOR(g12a_vclk2_div12, 1, 12, 0, { &g12a_vclk2_div12_en }, 1, 0); +static uint32_t mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; +static const struct clk_parent_data g12a_cts_parent_table[] = { + { + .clk = &g12a_vclk_div1, + }, + { + .clk = &g12a_vclk_div2, + }, + { + .clk = &g12a_vclk_div4, + }, + { + .clk = &g12a_vclk_div6, + }, + { + .clk = &g12a_vclk_div12, + }, + { + .clk = &g12a_vclk2_div1, + }, + { + .clk = &g12a_vclk2_div2, + }, + { + .clk = &g12a_vclk2_div4, + }, + { + .clk = &g12a_vclk2_div6, + }, + { + .clk = &g12a_vclk2_div12, + }, +}; +static CLK_MUX(g12a_cts_enci_sel, HHI_VID_CLK_DIV, 0xf, 28, mux_table_cts_sel, 0, g12a_cts_parent_table, + ARRAY_SIZE(g12a_cts_parent_table), CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE); +static CLK_MUX(g12a_cts_encp_sel, HHI_VID_CLK_DIV, 0xf, 20, mux_table_cts_sel, 0, g12a_cts_parent_table, + ARRAY_SIZE(g12a_cts_parent_table), CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE); +static CLK_MUX(g12a_cts_encl_sel, HHI_VIID_CLK_DIV, 0xf, 12, mux_table_cts_sel, 0, g12a_cts_parent_table, + ARRAY_SIZE(g12a_cts_parent_table), CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT); +static CLK_MUX(g12a_cts_vdac_sel, HHI_VIID_CLK_DIV, 0xf, 28, mux_table_cts_sel, 0, g12a_cts_parent_table, + ARRAY_SIZE(g12a_cts_parent_table), CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE); +static uint32_t mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 }; +static const struct clk_parent_data g12a_cts_hdmi_tx_parent_table[] = { + { + .clk = &g12a_vclk_div1, + }, + { + .clk = &g12a_vclk_div2, + }, + { + .clk = &g12a_vclk_div4, + }, + { + .clk = &g12a_vclk_div6, + }, + { + .clk = &g12a_vclk_div12, + }, + { + .clk = &g12a_vclk2_div1, + }, + { + .clk = &g12a_vclk2_div2, + }, + { + .clk = &g12a_vclk2_div4, + }, + { + .clk = &g12a_vclk2_div6, + }, + { + .clk = &g12a_vclk2_div12, + }, +}; +static CLK_MUX(g12a_hdmi_tx_sel, HHI_HDMI_CLK_CNTL, 0xf, 16, mux_table_hdmi_tx_sel, 0, g12a_cts_hdmi_tx_parent_table, + ARRAY_SIZE(g12a_cts_hdmi_tx_parent_table), CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE); +static CLK_GATE(g12a_cts_enci, HHI_VID_CLK_CNTL2, 0, 0, { &g12a_cts_enci_sel }, 1, 0); +static CLK_GATE(g12a_cts_encp, HHI_VID_CLK_CNTL2, 2, 0, { &g12a_cts_encp_sel }, 1, 0); +static CLK_GATE(g12a_cts_encl, HHI_VID_CLK_CNTL2, 3, 0, { &g12a_cts_encl_sel }, 1, 0); +static CLK_GATE(g12a_cts_vdac, HHI_VID_CLK_CNTL2, 4, 0, { &g12a_cts_vdac_sel }, 1, 0); +static CLK_GATE(g12a_hdmi_tx, HHI_VID_CLK_CNTL2, 5, 0, { &g12a_hdmi_tx_sel }, 1, 0); +static const struct clk_parent_data g12a_mipi_dsi_pxclk_parent_table[] = { + { + .clk = &g12a_vid_pll, + }, + { + .clk = &g12a_gp0_pll, + }, + { + .clk = &g12a_hifi_pll, + }, + { + .clk = &g12a_mpll1, + }, + { + .clk = &g12a_fclk_div2, + }, + { + .clk = &g12a_fclk_div2p5, + }, + { + .clk = &g12a_fclk_div3, + }, + { + .clk = &g12a_fclk_div7, + }, +}; +static CLK_MUX(g12a_mipi_dsi_pxclk_sel, HHI_MIPIDSI_PHY_CLK_CNTL, 0x7, 12, 0, CLK_MUX_ROUND_CLOSEST, + g12a_mipi_dsi_pxclk_parent_table, ARRAY_SIZE(g12a_mipi_dsi_pxclk_parent_table), + CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT); +static CLK_DIV(g12a_mipi_dsi_pxclk_div, HHI_MIPIDSI_PHY_CLK_CNTL, 0, 7, 0, { &g12a_mipi_dsi_pxclk_sel }, 1, 0); +static CLK_GATE(g12a_mipi_dsi_pxclk, HHI_MIPIDSI_PHY_CLK_CNTL, 8, 0, { &g12a_mipi_dsi_pxclk_div }, 1, 0); +static const struct clk_parent_data g12a_hdmi_parent_table[] = { + { + .name = "xtal", + }, + { .clk = &g12a_fclk_div4 }, + { .clk = &g12a_fclk_div3 }, + { .clk = &g12a_fclk_div5 }, +}; +static CLK_MUX(g12a_hdmi_sel, HHI_HDMI_CLK_CNTL, 0x3, 9, 0, CLK_MUX_ROUND_CLOSEST, g12a_hdmi_parent_table, + ARRAY_SIZE(g12a_hdmi_parent_table), CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE); +static CLK_DIV(g12a_hdmi_div, HHI_HDMI_CLK_CNTL, 0, 7, 0, { &g12a_hdmi_sel }, 1, 0); +static CLK_GATE(g12a_hdmi, HHI_HDMI_CLK_CNTL, 8, 0, { &g12a_hdmi_div }, 1, 0); +static const struct clk_parent_data g12a_mali_0_1_parent_data[] = { + { + .name = "xtal", + }, + { .clk = &g12a_gp0_pll }, + { .clk = &g12a_hifi_pll }, + { .clk = &g12a_fclk_div2p5 }, + { .clk = &g12a_fclk_div3 }, + { .clk = &g12a_fclk_div4 }, + { .clk = &g12a_fclk_div5 }, + { .clk = &g12a_fclk_div7 }, +}; +static CLK_MUX(g12a_mali_0_sel, HHI_MALI_CLK_CNTL, 0x7, 9, 0, 0, g12a_mali_0_1_parent_data, 8, 0); +static CLK_DIV(g12a_mali_0_div, HHI_MALI_CLK_CNTL, 0, 7, 0, { &g12a_mali_0_sel }, 1, 0); +static CLK_GATE(g12a_mali_0, HHI_MALI_CLK_CNTL, 8, 0, { &g12a_mali_0_div }, 1, 0); +static CLK_MUX(g12a_mali_1_sel, HHI_MALI_CLK_CNTL, 0x7, 25, 0, 0, g12a_mali_0_1_parent_data, 8, 0); +static CLK_DIV(g12a_mali_1_div, HHI_MALI_CLK_CNTL, 16, 7, 0, { &g12a_mali_1_sel }, 1, 0); +static CLK_GATE(g12a_mali_1, HHI_MALI_CLK_CNTL, 24, 0, { &g12a_mali_1_div }, 1, 0); +static const struct clk_parent_data g12a_mali_parent_table[] = { + { + .clk = &g12a_mali_0, + }, + { + .clk = &g12a_mali_1, + }, +}; +static CLK_MUX(g12a_mali, HHI_MALI_CLK_CNTL, 1, 31, 0, 0, g12a_mali_parent_table, 2, CLK_SET_RATE_PARENT); +static CLK_DIV_RO(g12a_ts_div, HHI_TS_CLK_CNTL, 0, 8, 0, { &g12a_ts_div }, 1, 0); +static CLK_GATE(g12a_ts, HHI_TS_CLK_CNTL, 8, 0, { &g12a_ts_div }, 1, 0); +static const struct clk_parent_data spicc_sclk_parent_data[] = { + { + .name = "xtal", + }, + { .clk = &g12a_clk81 }, + { .clk = &g12a_fclk_div4 }, + { .clk = &g12a_fclk_div3 }, + { .clk = &g12a_fclk_div5 }, + { .clk = &g12a_fclk_div7 }, +}; + +static CLK_MUX(g12a_spicc0_sclk_sel, HHI_SPICC_CLK_CNTL, 7, 7, 0, 0, spicc_sclk_parent_data, 6, 0); +static CLK_DIV(g12a_spicc0_sclk_div, HHI_SPICC_CLK_CNTL, 0, 6, 0, { &g12a_spicc0_sclk_sel }, 1, 0); +static CLK_GATE(g12a_spicc0_sclk, HHI_SPICC_CLK_CNTL, 6, 0, { &g12a_spicc0_sclk_div }, 1, 0); +static CLK_MUX(g12a_spicc1_sclk_sel, HHI_SPICC_CLK_CNTL, 7, 23, 0, 0, spicc_sclk_parent_data, 6, 0); +static CLK_DIV(g12a_spicc1_sclk_div, HHI_SPICC_CLK_CNTL, 16, 6, 0, { &g12a_spicc1_sclk_sel }, 1, 0); +static CLK_GATE(g12a_spicc1_sclk, HHI_SPICC_CLK_CNTL, 22, 0, { &g12a_spicc1_sclk_div }, 1, 0); +static const struct clk_parent_data nna_clk_parent_data[] = { + { + .name = "xtal", + }, + { + .clk = &g12a_gp0_pll, + }, + { + .clk = &g12a_hifi_pll, + }, + { + .clk = &g12a_fclk_div2p5, + }, + { + .clk = &g12a_fclk_div3, + }, + { + .clk = &g12a_fclk_div4, + }, + { + .clk = &g12a_fclk_div5, + }, + { .clk = &g12a_fclk_div7 }, +}; +static CLK_MUX(sm1_nna_axi_clk_sel, HHI_NNA_CLK_CNTL, 7, 9, 0, 0, nna_clk_parent_data, 8, 0); +static CLK_DIV(sm1_nna_axi_clk_div, HHI_NNA_CLK_CNTL, 0, 7, 0, { &sm1_nna_axi_clk_sel }, 1, 0); +static CLK_GATE(sm1_nna_axi_clk, HHI_NNA_CLK_CNTL, 8, 0, { &sm1_nna_axi_clk_div }, 1, 0); +static CLK_MUX(sm1_nna_core_clk_sel, HHI_NNA_CLK_CNTL, 7, 25, 0, 0, nna_clk_parent_data, 8, 0); +static CLK_DIV(sm1_nna_core_clk_div, HHI_NNA_CLK_CNTL, 16, 7, 0, { &sm1_nna_core_clk_sel }, 1, 0); +static CLK_GATE(sm1_nna_core_clk, HHI_NNA_CLK_CNTL, 24, 0, { &sm1_nna_core_clk_div }, 1, 0); + +/* Everything Else (EE) domain gates */ +static MESON_CLK81_GATE(g12a_ddr, HHI_GCLK_MPEG0, 0); +static MESON_CLK81_GATE(g12a_dos, HHI_GCLK_MPEG0, 1); +static MESON_CLK81_GATE(g12a_audio_locker, HHI_GCLK_MPEG0, 2); +static MESON_CLK81_GATE(g12a_mipi_dsi_host, HHI_GCLK_MPEG0, 3); +static MESON_CLK81_GATE(g12a_eth_phy, HHI_GCLK_MPEG0, 4); +static MESON_CLK81_GATE(g12a_isa, HHI_GCLK_MPEG0, 5); +static MESON_CLK81_GATE(g12a_pl301, HHI_GCLK_MPEG0, 6); +static MESON_CLK81_GATE(g12a_periphs, HHI_GCLK_MPEG0, 7); +static MESON_CLK81_GATE(g12a_spicc_0, HHI_GCLK_MPEG0, 8); +static MESON_CLK81_GATE(g12a_i2c, HHI_GCLK_MPEG0, 9); +static MESON_CLK81_GATE(g12a_sana, HHI_GCLK_MPEG0, 10); +static MESON_CLK81_GATE(g12a_sd, HHI_GCLK_MPEG0, 11); +static MESON_CLK81_GATE(g12a_rng0, HHI_GCLK_MPEG0, 12); +static MESON_CLK81_GATE(g12a_uart0, HHI_GCLK_MPEG0, 13); +static MESON_CLK81_GATE(g12a_spicc_1, HHI_GCLK_MPEG0, 14); +static MESON_CLK81_GATE(g12a_hiu_reg, HHI_GCLK_MPEG0, 19); +static MESON_CLK81_GATE(g12a_mipi_dsi_phy, HHI_GCLK_MPEG0, 20); +static MESON_CLK81_GATE(g12a_assist_misc, HHI_GCLK_MPEG0, 23); +static MESON_CLK81_GATE(g12a_emmc_a, HHI_GCLK_MPEG0, 4); +static MESON_CLK81_GATE(g12a_emmc_b, HHI_GCLK_MPEG0, 25); +static MESON_CLK81_GATE(g12a_emmc_c, HHI_GCLK_MPEG0, 26); +static MESON_CLK81_GATE(g12a_audio_codec, HHI_GCLK_MPEG0, 28); + +static MESON_CLK81_GATE(g12a_audio, HHI_GCLK_MPEG1, 0); +static MESON_CLK81_GATE(g12a_eth_core, HHI_GCLK_MPEG1, 3); +static MESON_CLK81_GATE(g12a_demux, HHI_GCLK_MPEG1, 4); +static MESON_CLK81_GATE(g12a_audio_ififo, HHI_GCLK_MPEG1, 11); +static MESON_CLK81_GATE(g12a_adc, HHI_GCLK_MPEG1, 13); +static MESON_CLK81_GATE(g12a_uart1, HHI_GCLK_MPEG1, 16); +static MESON_CLK81_GATE(g12a_g2d, HHI_GCLK_MPEG1, 20); +static MESON_CLK81_GATE(g12a_reset, HHI_GCLK_MPEG1, 23); +static MESON_CLK81_GATE(g12a_pcie_comb, HHI_GCLK_MPEG1, 24); +static MESON_CLK81_GATE(g12a_parser, HHI_GCLK_MPEG1, 25); +static MESON_CLK81_GATE(g12a_usb_general, HHI_GCLK_MPEG1, 26); +static MESON_CLK81_GATE(g12a_pcie_phy, HHI_GCLK_MPEG1, 27); +static MESON_CLK81_GATE(g12a_ahb_arb0, HHI_GCLK_MPEG1, 29); + +static MESON_CLK81_GATE(g12a_ahb_data_bus, HHI_GCLK_MPEG2, 1); +static MESON_CLK81_GATE(g12a_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2); +static MESON_CLK81_GATE(g12a_htx_hdcp22, HHI_GCLK_MPEG2, 3); +static MESON_CLK81_GATE(g12a_htx_pclk, HHI_GCLK_MPEG2, 4); +static MESON_CLK81_GATE(g12a_bt656, HHI_GCLK_MPEG2, 6); +static MESON_CLK81_GATE(g12a_usb1_to_ddr, HHI_GCLK_MPEG2, 8); +static MESON_CLK81_GATE(g12a_mmc_pclk, HHI_GCLK_MPEG2, 11); +static MESON_CLK81_GATE(g12a_uart2, HHI_GCLK_MPEG2, 15); +static MESON_CLK81_GATE(g12a_vpu_intr, HHI_GCLK_MPEG2, 25); +static MESON_CLK81_GATE(g12a_gic, HHI_GCLK_MPEG2, 30); + +static MESON_CLK81_GATE(g12a_vclk2_venci0, HHI_GCLK_OTHER, 1); +static MESON_CLK81_GATE(g12a_vclk2_venci1, HHI_GCLK_OTHER, 2); +static MESON_CLK81_GATE(g12a_vclk2_vencp0, HHI_GCLK_OTHER, 3); +static MESON_CLK81_GATE(g12a_vclk2_vencp1, HHI_GCLK_OTHER, 4); +static MESON_CLK81_GATE(g12a_vclk2_venct0, HHI_GCLK_OTHER, 5); +static MESON_CLK81_GATE(g12a_vclk2_venct1, HHI_GCLK_OTHER, 6); +static MESON_CLK81_GATE(g12a_vclk2_other, HHI_GCLK_OTHER, 7); +static MESON_CLK81_GATE(g12a_vclk2_enci, HHI_GCLK_OTHER, 8); +static MESON_CLK81_GATE(g12a_vclk2_encp, HHI_GCLK_OTHER, 9); +static MESON_CLK81_GATE(g12a_dac_clk, HHI_GCLK_OTHER, 10); +static MESON_CLK81_GATE(g12a_aoclk_gate, HHI_GCLK_OTHER, 14); +static MESON_CLK81_GATE(g12a_iec958_gate, HHI_GCLK_OTHER, 16); +static MESON_CLK81_GATE(g12a_enc480p, HHI_GCLK_OTHER, 20); +static MESON_CLK81_GATE(g12a_rng1, HHI_GCLK_OTHER, 21); +static MESON_CLK81_GATE(g12a_vclk2_enct, HHI_GCLK_OTHER, 22); +static MESON_CLK81_GATE(g12a_vclk2_encl, HHI_GCLK_OTHER, 23); +static MESON_CLK81_GATE(g12a_vclk2_venclmmc, HHI_GCLK_OTHER, 24); +static MESON_CLK81_GATE(g12a_vclk2_vencl, HHI_GCLK_OTHER, 25); +static MESON_CLK81_GATE(g12a_vclk2_other1, HHI_GCLK_OTHER, 26); + +static MESON_CLK81_GATE_RO(g12a_dma, HHI_GCLK_OTHER2, 0); +static MESON_CLK81_GATE_RO(g12a_efuse, HHI_GCLK_OTHER2, 1); +static MESON_CLK81_GATE_RO(g12a_rom_boot, HHI_GCLK_OTHER2, 2); +static MESON_CLK81_GATE_RO(g12a_reset_sec, HHI_GCLK_OTHER2, 3); +static MESON_CLK81_GATE_RO(g12a_sec_ahb_apb3, HHI_GCLK_OTHER2, 4); + +static struct clk *sm1_clks[] = { + [CLKID_SYS_PLL] = &g12a_sys_pll, + [CLKID_FIXED_PLL] = &g12a_fixed_pll, + [CLKID_FCLK_DIV2] = &g12a_fclk_div2, + [CLKID_FCLK_DIV3] = &g12a_fclk_div3, + [CLKID_FCLK_DIV4] = &g12a_fclk_div4, + [CLKID_FCLK_DIV5] = &g12a_fclk_div5, + [CLKID_FCLK_DIV7] = &g12a_fclk_div7, + [CLKID_FCLK_DIV2P5] = &g12a_fclk_div2p5, + [CLKID_GP0_PLL] = &g12a_gp0_pll, + [CLKID_MPEG_SEL] = &g12a_mpeg_clk_sel, + [CLKID_MPEG_DIV] = &g12a_mpeg_clk_div, + [CLKID_CLK81] = &g12a_clk81, + [CLKID_MPLL0] = &g12a_mpll0, + [CLKID_MPLL1] = &g12a_mpll1, + [CLKID_MPLL2] = &g12a_mpll2, + [CLKID_MPLL3] = &g12a_mpll3, + [CLKID_DDR] = &g12a_ddr, + [CLKID_DOS] = &g12a_dos, + [CLKID_AUDIO_LOCKER] = &g12a_audio_locker, + [CLKID_MIPI_DSI_HOST] = &g12a_mipi_dsi_host, + [CLKID_ETH_PHY] = &g12a_eth_phy, + [CLKID_ISA] = &g12a_isa, + [CLKID_PL301] = &g12a_pl301, + [CLKID_PERIPHS] = &g12a_periphs, + [CLKID_SPICC0] = &g12a_spicc_0, + [CLKID_I2C] = &g12a_i2c, + [CLKID_SANA] = &g12a_sana, + [CLKID_SD] = &g12a_sd, + [CLKID_RNG0] = &g12a_rng0, + [CLKID_UART0] = &g12a_uart0, + [CLKID_SPICC1] = &g12a_spicc_1, + [CLKID_HIU_IFACE] = &g12a_hiu_reg, + [CLKID_MIPI_DSI_PHY] = &g12a_mipi_dsi_phy, + [CLKID_ASSIST_MISC] = &g12a_assist_misc, + [CLKID_SD_EMMC_A] = &g12a_emmc_a, + [CLKID_SD_EMMC_B] = &g12a_emmc_b, + [CLKID_SD_EMMC_C] = &g12a_emmc_c, + [CLKID_AUDIO_CODEC] = &g12a_audio_codec, + [CLKID_AUDIO] = &g12a_audio, + [CLKID_ETH] = &g12a_eth_core, + [CLKID_DEMUX] = &g12a_demux, + [CLKID_AUDIO_IFIFO] = &g12a_audio_ififo, + [CLKID_ADC] = &g12a_adc, + [CLKID_UART1] = &g12a_uart1, + [CLKID_G2D] = &g12a_g2d, + [CLKID_RESET] = &g12a_reset, + [CLKID_PCIE_COMB] = &g12a_pcie_comb, + [CLKID_PARSER] = &g12a_parser, + [CLKID_USB] = &g12a_usb_general, + [CLKID_PCIE_PHY] = &g12a_pcie_phy, + [CLKID_AHB_ARB0] = &g12a_ahb_arb0, + [CLKID_AHB_DATA_BUS] = &g12a_ahb_data_bus, + [CLKID_AHB_CTRL_BUS] = &g12a_ahb_ctrl_bus, + [CLKID_HTX_HDCP22] = &g12a_htx_hdcp22, + [CLKID_HTX_PCLK] = &g12a_htx_pclk, + [CLKID_BT656] = &g12a_bt656, + [CLKID_USB1_DDR_BRIDGE] = &g12a_usb1_to_ddr, + [CLKID_MMC_PCLK] = &g12a_mmc_pclk, + [CLKID_UART2] = &g12a_uart2, + [CLKID_VPU_INTR] = &g12a_vpu_intr, + [CLKID_GIC] = &g12a_gic, + [CLKID_SD_EMMC_A_CLK0_SEL] = &g12a_sd_emmc_a_clk0_sel, + [CLKID_SD_EMMC_A_CLK0_DIV] = &g12a_sd_emmc_a_clk0_div, + [CLKID_SD_EMMC_A_CLK0] = &g12a_sd_emmc_a_clk0, + [CLKID_SD_EMMC_B_CLK0_SEL] = &g12a_sd_emmc_b_clk0_sel, + [CLKID_SD_EMMC_B_CLK0_DIV] = &g12a_sd_emmc_b_clk0_div, + [CLKID_SD_EMMC_B_CLK0] = &g12a_sd_emmc_b_clk0, + [CLKID_SD_EMMC_C_CLK0_SEL] = &g12a_sd_emmc_c_clk0_sel, + [CLKID_SD_EMMC_C_CLK0_DIV] = &g12a_sd_emmc_c_clk0_div, + [CLKID_SD_EMMC_C_CLK0] = &g12a_sd_emmc_c_clk0, + [CLKID_MPLL0_DIV] = &g12a_mpll0_div, + [CLKID_MPLL1_DIV] = &g12a_mpll1_div, + [CLKID_MPLL2_DIV] = &g12a_mpll2_div, + [CLKID_MPLL3_DIV] = &g12a_mpll3_div, + [CLKID_FCLK_DIV2_DIV] = &g12a_fclk_div2_div, + [CLKID_FCLK_DIV3_DIV] = &g12a_fclk_div3_div, + [CLKID_FCLK_DIV4_DIV] = &g12a_fclk_div4_div, + [CLKID_FCLK_DIV5_DIV] = &g12a_fclk_div5_div, + [CLKID_FCLK_DIV7_DIV] = &g12a_fclk_div7_div, + [CLKID_FCLK_DIV2P5_DIV] = &g12a_fclk_div2p5_div, + [CLKID_HIFI_PLL] = &g12a_hifi_pll, + [CLKID_VCLK2_VENCI0] = &g12a_vclk2_venci0, + [CLKID_VCLK2_VENCI1] = &g12a_vclk2_venci1, + [CLKID_VCLK2_VENCP0] = &g12a_vclk2_vencp0, + [CLKID_VCLK2_VENCP1] = &g12a_vclk2_vencp1, + [CLKID_VCLK2_VENCT0] = &g12a_vclk2_venct0, + [CLKID_VCLK2_VENCT1] = &g12a_vclk2_venct1, + [CLKID_VCLK2_OTHER] = &g12a_vclk2_other, + [CLKID_VCLK2_ENCI] = &g12a_vclk2_enci, + [CLKID_VCLK2_ENCP] = &g12a_vclk2_encp, + [CLKID_DAC_CLK] = &g12a_dac_clk, + [CLKID_AOCLK] = &g12a_aoclk_gate, + [CLKID_IEC958] = &g12a_iec958_gate, + [CLKID_ENC480P] = &g12a_enc480p, + [CLKID_RNG1] = &g12a_rng1, + [CLKID_VCLK2_ENCT] = &g12a_vclk2_enct, + [CLKID_VCLK2_ENCL] = &g12a_vclk2_encl, + [CLKID_VCLK2_VENCLMMC] = &g12a_vclk2_venclmmc, + [CLKID_VCLK2_VENCL] = &g12a_vclk2_vencl, + [CLKID_VCLK2_OTHER1] = &g12a_vclk2_other1, + [CLKID_FIXED_PLL_DCO] = &g12a_fixed_pll_dco, + [CLKID_SYS_PLL_DCO] = &g12a_sys_pll_dco, + [CLKID_GP0_PLL_DCO] = &g12a_gp0_pll_dco, + [CLKID_HIFI_PLL_DCO] = &g12a_hifi_pll_dco, + [CLKID_DMA] = &g12a_dma, + [CLKID_EFUSE] = &g12a_efuse, + [CLKID_ROM_BOOT] = &g12a_rom_boot, + [CLKID_RESET_SEC] = &g12a_reset_sec, + [CLKID_SEC_AHB_APB3] = &g12a_sec_ahb_apb3, + [CLKID_MPLL_PREDIV] = &g12a_mpll_prediv, + [CLKID_VPU_0_SEL] = &g12a_vpu_0_sel, + [CLKID_VPU_0_DIV] = &g12a_vpu_0_div, + [CLKID_VPU_0] = &g12a_vpu_0, + [CLKID_VPU_1_SEL] = &g12a_vpu_1_sel, + [CLKID_VPU_1_DIV] = &g12a_vpu_1_div, + [CLKID_VPU_1] = &g12a_vpu_1, + [CLKID_VPU] = &g12a_vpu, + [CLKID_VAPB_0_SEL] = &g12a_vapb_0_sel, + [CLKID_VAPB_0_DIV] = &g12a_vapb_0_div, + [CLKID_VAPB_0] = &g12a_vapb_0, + [CLKID_VAPB_1_SEL] = &g12a_vapb_1_sel, + [CLKID_VAPB_1_DIV] = &g12a_vapb_1_div, + [CLKID_VAPB_1] = &g12a_vapb_1, + [CLKID_VAPB_SEL] = &g12a_vapb_sel, + [CLKID_VAPB] = &g12a_vapb, + [CLKID_HDMI_PLL_DCO] = &g12a_hdmi_pll_dco, + [CLKID_HDMI_PLL_OD] = &g12a_hdmi_pll_od, + [CLKID_HDMI_PLL_OD2] = &g12a_hdmi_pll_od2, + [CLKID_HDMI_PLL] = &g12a_hdmi_pll, + [CLKID_VID_PLL] = &g12a_vid_pll_div, + [CLKID_VID_PLL_SEL] = &g12a_vid_pll_sel, + [CLKID_VID_PLL_DIV] = &g12a_vid_pll, + [CLKID_VCLK_SEL] = &g12a_vclk_sel, + [CLKID_VCLK2_SEL] = &g12a_vclk2_sel, + [CLKID_VCLK_INPUT] = &g12a_vclk_input, + [CLKID_VCLK2_INPUT] = &g12a_vclk2_input, + [CLKID_VCLK_DIV] = &g12a_vclk_div, + [CLKID_VCLK2_DIV] = &g12a_vclk2_div, + [CLKID_VCLK] = &g12a_vclk, + [CLKID_VCLK2] = &g12a_vclk2, + [CLKID_VCLK_DIV1] = &g12a_vclk_div1, + [CLKID_VCLK_DIV2_EN] = &g12a_vclk_div2_en, + [CLKID_VCLK_DIV4_EN] = &g12a_vclk_div4_en, + [CLKID_VCLK_DIV6_EN] = &g12a_vclk_div6_en, + [CLKID_VCLK_DIV12_EN] = &g12a_vclk_div12_en, + [CLKID_VCLK2_DIV1] = &g12a_vclk2_div1, + [CLKID_VCLK2_DIV2_EN] = &g12a_vclk2_div2_en, + [CLKID_VCLK2_DIV4_EN] = &g12a_vclk2_div4_en, + [CLKID_VCLK2_DIV6_EN] = &g12a_vclk2_div6_en, + [CLKID_VCLK2_DIV12_EN] = &g12a_vclk2_div12_en, + [CLKID_VCLK_DIV2] = &g12a_vclk_div2, + [CLKID_VCLK_DIV4] = &g12a_vclk_div4, + [CLKID_VCLK_DIV6] = &g12a_vclk_div6, + [CLKID_VCLK_DIV12] = &g12a_vclk_div12, + [CLKID_VCLK2_DIV2] = &g12a_vclk2_div2, + [CLKID_VCLK2_DIV4] = &g12a_vclk2_div4, + [CLKID_VCLK2_DIV6] = &g12a_vclk2_div6, + [CLKID_VCLK2_DIV12] = &g12a_vclk2_div12, + [CLKID_CTS_ENCI_SEL] = &g12a_cts_enci_sel, + [CLKID_CTS_ENCP_SEL] = &g12a_cts_encp_sel, + [CLKID_CTS_ENCL_SEL] = &g12a_cts_encl_sel, + [CLKID_CTS_VDAC_SEL] = &g12a_cts_vdac_sel, + [CLKID_HDMI_TX_SEL] = &g12a_hdmi_tx_sel, + [CLKID_CTS_ENCI] = &g12a_cts_enci, + [CLKID_CTS_ENCP] = &g12a_cts_encp, + [CLKID_CTS_ENCL] = &g12a_cts_encl, + [CLKID_CTS_VDAC] = &g12a_cts_vdac, + [CLKID_HDMI_TX] = &g12a_hdmi_tx, + [CLKID_HDMI_SEL] = &g12a_hdmi_sel, + [CLKID_HDMI_DIV] = &g12a_hdmi_div, + [CLKID_HDMI] = &g12a_hdmi, + [CLKID_MALI_0_SEL] = &g12a_mali_0_sel, + [CLKID_MALI_0_DIV] = &g12a_mali_0_div, + [CLKID_MALI_0] = &g12a_mali_0, + [CLKID_MALI_1_SEL] = &g12a_mali_1_sel, + [CLKID_MALI_1_DIV] = &g12a_mali_1_div, + [CLKID_MALI_1] = &g12a_mali_1, + [CLKID_MALI] = &g12a_mali, + [CLKID_MPLL_50M_DIV] = &g12a_mpll_50m_div, + [CLKID_MPLL_50M] = &g12a_mpll_50m, + [CLKID_SYS_PLL_DIV16_EN] = &g12a_sys_pll_div16_en, + [CLKID_SYS_PLL_DIV16] = &g12a_sys_pll_div16, + [CLKID_CPU_CLK_DYN0_SEL] = &g12a_cpu_clk_premux0, + [CLKID_CPU_CLK_DYN0_DIV] = &g12a_cpu_clk_mux0_div, + [CLKID_CPU_CLK_DYN0] = &g12a_cpu_clk_postmux0, + [CLKID_CPU_CLK_DYN1_SEL] = &g12a_cpu_clk_premux1, + [CLKID_CPU_CLK_DYN1_DIV] = &g12a_cpu_clk_mux1_div, + [CLKID_CPU_CLK_DYN1] = &g12a_cpu_clk_postmux1, + [CLKID_CPU_CLK_DYN] = &g12a_cpu_clk_dyn, + [CLKID_CPU_CLK] = &g12a_cpu_clk, + [CLKID_CPU_CLK_DIV16_EN] = &g12a_cpu_clk_div16_en, + [CLKID_CPU_CLK_DIV16] = &g12a_cpu_clk_div16, + [CLKID_CPU_CLK_APB_DIV] = &g12a_cpu_clk_apb_div, + [CLKID_CPU_CLK_APB] = &g12a_cpu_clk_apb, + [CLKID_CPU_CLK_ATB_DIV] = &g12a_cpu_clk_atb_div, + [CLKID_CPU_CLK_ATB] = &g12a_cpu_clk_atb, + [CLKID_CPU_CLK_AXI_DIV] = &g12a_cpu_clk_axi_div, + [CLKID_CPU_CLK_AXI] = &g12a_cpu_clk_axi, + [CLKID_CPU_CLK_TRACE_DIV] = &g12a_cpu_clk_trace_div, + [CLKID_CPU_CLK_TRACE] = &g12a_cpu_clk_trace, + [CLKID_PCIE_PLL_DCO] = &g12a_pcie_pll_dco, + [CLKID_PCIE_PLL_DCO_DIV2] = &g12a_pcie_pll_dco_div2, + [CLKID_PCIE_PLL_OD] = &g12a_pcie_pll_od, + [CLKID_PCIE_PLL] = &g12a_pcie_pll, + [CLKID_VDEC_1_SEL] = &g12a_vdec_1_sel, + [CLKID_VDEC_1_DIV] = &g12a_vdec_1_div, + [CLKID_VDEC_1] = &g12a_vdec_1, + [CLKID_VDEC_HEVC_SEL] = &g12a_vdec_hevc_sel, + [CLKID_VDEC_HEVC_DIV] = &g12a_vdec_hevc_div, + [CLKID_VDEC_HEVC] = &g12a_vdec_hevc, + [CLKID_VDEC_HEVCF_SEL] = &g12a_vdec_hevcf_sel, + [CLKID_VDEC_HEVCF_DIV] = &g12a_vdec_hevcf_div, + [CLKID_VDEC_HEVCF] = &g12a_vdec_hevcf, + [CLKID_TS_DIV] = &g12a_ts_div, + [CLKID_TS] = &g12a_ts, + [CLKID_GP1_PLL_DCO] = &sm1_gp1_pll_dco, + [CLKID_GP1_PLL] = &sm1_gp1_pll, + [CLKID_DSU_CLK_DYN0_SEL] = &sm1_dsu_clk_premux0, + [CLKID_DSU_CLK_DYN0_DIV] = &sm1_dsu_clk_premux1, + [CLKID_DSU_CLK_DYN0] = &sm1_dsu_clk_mux0_div, + [CLKID_DSU_CLK_DYN1_SEL] = &sm1_dsu_clk_postmux0, + [CLKID_DSU_CLK_DYN1_DIV] = &sm1_dsu_clk_mux1_div, + [CLKID_DSU_CLK_DYN1] = &sm1_dsu_clk_postmux1, + [CLKID_DSU_CLK_DYN] = &sm1_dsu_clk_dyn, + [CLKID_DSU_CLK_FINAL] = &sm1_dsu_final_clk, + [CLKID_DSU_CLK] = &sm1_dsu_clk, + [CLKID_CPU1_CLK] = &sm1_cpu1_clk, + [CLKID_CPU2_CLK] = &sm1_cpu2_clk, + [CLKID_CPU3_CLK] = &sm1_cpu3_clk, + [CLKID_SPICC0_SCLK_SEL] = &g12a_spicc0_sclk_sel, + [CLKID_SPICC0_SCLK_DIV] = &g12a_spicc0_sclk_div, + [CLKID_SPICC0_SCLK] = &g12a_spicc0_sclk, + [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel, + [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div, + [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk, + [CLKID_NNA_AXI_CLK_SEL] = &sm1_nna_axi_clk_sel, + [CLKID_NNA_AXI_CLK_DIV] = &sm1_nna_axi_clk_div, + [CLKID_NNA_AXI_CLK] = &sm1_nna_axi_clk, + [CLKID_NNA_CORE_CLK_SEL] = &sm1_nna_core_clk_sel, + [CLKID_NNA_CORE_CLK_DIV] = &sm1_nna_core_clk_div, + [CLKID_NNA_CORE_CLK] = &sm1_nna_core_clk, + [CLKID_MIPI_DSI_PXCLK_SEL] = &g12a_mipi_dsi_pxclk_sel, + [CLKID_MIPI_DSI_PXCLK_DIV] = &g12a_mipi_dsi_pxclk_div, + [CLKID_MIPI_DSI_PXCLK] = &g12a_mipi_dsi_pxclk, + [CLKID_G12A_XTAL] = &g12a_xtal, +}; + +int clk_msr_stat(struct clk *clk_list[]) +{ +#ifdef DEBUG_DRIVER + unsigned long clk_freq; + int i = 0; + uint64_t rate = 0; + int err; + + const char *const *clk_msr_list = get_msr_clk_list(); + + LOG_DRIVER("-------Expected clock rates------\n"); + for (i = 0; i < NUM_CLK_LIST; i++) { + err = clk_get_rate(clk_list[i], &rate); + if (err) { + LOG_DRIVER("Failed to get rate of %s: -%u\n", clk_list[i]->hw.init->name, err); + } + LOG_DRIVER("[%4d][%4luHz] %s\n", i, rate, clk_list[i]->hw.init->name); + } + LOG_DRIVER("---------------------------------\n"); + LOG_DRIVER("---------Clock measurement-------\n"); + for (i = 0; i < 128; i++) { + clk_freq = clk_msr(i); + LOG_DRIVER("[%4d][%4ldHz] %s\n", i, clk_freq, clk_msr_list[i]); + } + LOG_DRIVER("-----------------------------\n"); + +#endif + + return 0; +} + +/* TODO: Should be configured with init_regs */ +/* static struct clk_cfg fixed_clk_configs[] = { */ +/* { .clk_id = CLKID_FCLK_DIV2_DIV, .frequency = 1000000000 }, */ +/* { .clk_id = CLKID_FCLK_DIV3_DIV, .frequency = 666666667 }, */ +/* { .clk_id = CLKID_FCLK_DIV4_DIV, .frequency = 500000000 }, */ +/* { .clk_id = CLKID_FCLK_DIV5_DIV, .frequency = 400000000 }, */ +/* { .clk_id = CLKID_FCLK_DIV7_DIV, .frequency = 285700000 }, */ +/* } */ + +void clk_probe(struct clk *clk_list[]) +{ + int i; + for (i = 0; i < NUM_CLK_LIST; i++) { + if (!clk_list[i]) + continue; + clk_list[i]->base = (uint64_t)clk_regs; + if (clk_list[i]->hw.init->ops->init) { + clk_list[i]->hw.init->ops->init(clk_list[i]); + LOG_DRIVER("Initialise %s\n", clk_list[i]->hw.init->name); + } + } +} + +struct clk **get_clk_list(void) +{ + return sm1_clks; +} diff --git a/examples/clk/Makefile b/examples/clk/Makefile new file mode 100644 index 000000000..df144ac1f --- /dev/null +++ b/examples/clk/Makefile @@ -0,0 +1,44 @@ +# +# Copyright 2024, UNSW +# +# SPDX-License-Identifier: BSD-2-Clause +# + +ifeq ($(strip $(MICROKIT_SDK)),) +$(error MICROKIT_SDK must be specified) +endif +override MICROKIT_SDK := $(abspath ${MICROKIT_SDK}) + +ifeq ($(strip $(MICROKIT_BOARD)),) +$(error MICROKIT_BOARD must be specified) +endif +export MICROKIT_BOARD + +BUILD_DIR ?= build +# By default we make a debug build so that the client debug prints can be seen. +MICROKIT_CONFIG ?= debug + +export TOP:= $(abspath $(dir ${MAKEFILE_LIST})) + +CC := clang +LD := ld.lld +export MICROKIT_TOOL ?= $(abspath $(MICROKIT_SDK)/bin/microkit) + +export BOARD_DIR := $(abspath $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG)) +export SDDF := $(abspath ../..) +IMAGE_FILE := $(BUILD_DIR)/loader.img +REPORT_FILE := $(BUILD_DIR)/report.txt + +all: clean ${IMAGE_FILE} + +${IMAGE_FILE}: ${BUILD_DIR}/Makefile + ${MAKE} -C ${BUILD_DIR} MICROKIT_SDK=${MICROKIT_SDK} $(notdir $@) + +${BUILD_DIR}/Makefile: clk.mk + mkdir -p ${BUILD_DIR} + cp clk.mk ${BUILD_DIR}/Makefile + +clean: + rm -rfd $(BUILD_DIR) + +FORCE: diff --git a/examples/clk/board/maaxboard/clk.system b/examples/clk/board/maaxboard/clk.system new file mode 100644 index 000000000..5d6f69373 --- /dev/null +++ b/examples/clk/board/maaxboard/clk.system @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/clk/board/odroidc4/clk.system b/examples/clk/board/odroidc4/clk.system new file mode 100644 index 000000000..c9d24da0c --- /dev/null +++ b/examples/clk/board/odroidc4/clk.system @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/clk/build.zig b/examples/clk/build.zig new file mode 100644 index 000000000..583dd6a01 --- /dev/null +++ b/examples/clk/build.zig @@ -0,0 +1,147 @@ +// +// Copyright 2024, UNSW +// SPDX-License-Identifier: BSD-2-Clause +// +const std = @import("std"); + +const MicrokitBoard = enum { odroidc4, maaxboard }; + +const Target = struct { + board: MicrokitBoard, + zig_target: std.Target.Query, +}; + +const targets = [_]Target{ + .{ + .board = MicrokitBoard.odroidc4, + .zig_target = std.Target.Query{ + .cpu_arch = .aarch64, + .cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_a55 }, + .os_tag = .freestanding, + .abi = .none, + }, + }, + .{ + .board = MicrokitBoard.maaxboard, + .zig_target = std.Target.Query{ + .cpu_arch = .aarch64, + .cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_a53 }, + .os_tag = .freestanding, + .abi = .none, + }, + }, +}; + +fn findTarget(board: MicrokitBoard) std.Target.Query { + for (targets) |target| { + if (board == target.board) { + return target.zig_target; + } + } + + std.log.err("Board '{}' is not supported\n", .{board}); + std.posix.exit(1); +} + +const ConfigOptions = enum { debug, release, benchmark }; + +pub fn build(b: *std.Build) void { + const optimize = b.standardOptimizeOption(.{}); + + // Getting the path to the Microkit SDK before doing anything else + const microkit_sdk_arg = b.option([]const u8, "sdk", "Path to Microkit SDK"); + if (microkit_sdk_arg == null) { + std.log.err("Missing -Dsdk=/path/to/sdk argument being passed\n", .{}); + std.posix.exit(1); + } + const microkit_sdk = microkit_sdk_arg.?; + + const microkit_config_option = b.option(ConfigOptions, "config", "Microkit config to build for") orelse ConfigOptions.debug; + const microkit_config = @tagName(microkit_config_option); + + // Get the Microkit SDK board we want to target + const microkit_board_option = b.option(MicrokitBoard, "board", "Microkit board to target"); + + if (microkit_board_option == null) { + std.log.err("Missing -Dboard= argument being passed\n", .{}); + std.posix.exit(1); + } + const target = b.resolveTargetQuery(findTarget(microkit_board_option.?)); + const microkit_board = @tagName(microkit_board_option.?); + + const microkit_board_dir = b.fmt("{s}/board/{s}/{s}", .{ microkit_sdk, microkit_board, microkit_config }); + const microkit_tool = b.fmt("{s}/bin/microkit", .{microkit_sdk}); + const libmicrokit = b.fmt("{s}/lib/libmicrokit.a", .{microkit_board_dir}); + const libmicrokit_include = b.fmt("{s}/include", .{microkit_board_dir}); + const libmicrokit_linker_script = b.fmt("{s}/lib/microkit.ld", .{microkit_board_dir}); + + const dtb_arg = b.option([]const u8, "dtb", "Path to DTB file"); + if (dtb_arg == null) { + std.log.err("Missing -Dsdk=/path/to/dtb argument being passed\n", .{}); + std.posix.exit(1); + } + const dtb_path = std.Build.LazyPath{ .cwd_relative = dtb_arg.? }; + // TODO: Need to define this with built-in output path + const clk_conf_include = std.Build.LazyPath{ .cwd_relative = "zig-out/bin/" }; + const sddf_dep = b.dependency("sddf", .{ + .target = target, + .optimize = optimize, + .libmicrokit = @as([]const u8, libmicrokit), + .libmicrokit_include = @as([]const u8, libmicrokit_include), + .libmicrokit_linker_script = @as([]const u8, libmicrokit_linker_script), + .i2c_client_include = @as([]const u8, ""), + .clk_conf_include = @as([]const u8, clk_conf_include.getPath(b)), + .dtb_path = @as([]const u8, dtb_path.getPath(b) ), + }); + + const timer_driver_class = switch (microkit_board_option.?) { + .odroidc4 => "meson", + .maaxboard => "imx", + }; + + const clk_driver_class = switch (microkit_board_option.?) { + .odroidc4 => "meson", + .maaxboard => "imx", + }; + const clk_driver = sddf_dep.artifact(b.fmt("driver_clk_{s}.elf", .{clk_driver_class})); + const clk_driver_install = b.addInstallArtifact(clk_driver, .{ .dest_sub_path = "clk_driver.elf" }); + + const timer_driver = sddf_dep.artifact(b.fmt("driver_timer_{s}.elf", .{timer_driver_class})); + // This is required because the SDF file is expecting a different name to the artifact we + // are dealing with. + const timer_driver_install = b.addInstallArtifact(timer_driver, .{ .dest_sub_path = "timer_driver.elf" }); + + const client = b.addExecutable(.{ + .name = "client.elf", + .target = target, + .optimize = optimize, + .strip = false, + }); + client.addCSourceFile(.{ .file = b.path("client.c") }); + client.defineCMacro(b.fmt("TEST_BOARD_{s}", .{ microkit_board }), "1"); + client.addIncludePath(sddf_dep.path("include")); + client.linkLibrary(sddf_dep.artifact("util")); + client.linkLibrary(sddf_dep.artifact("util_putchar_debug")); + client.addIncludePath(.{ .cwd_relative = libmicrokit_include }); + client.addObjectFile(.{ .cwd_relative = libmicrokit }); + client.setLinkerScriptPath(.{ .cwd_relative = libmicrokit_linker_script }); + + b.installArtifact(client); + + const system_description_path = b.fmt("board/{s}/clk.system", .{microkit_board}); + const final_image_dest = b.getInstallPath(.bin, "./loader.img"); + const microkit_tool_cmd = b.addSystemCommand(&[_][]const u8{ + microkit_tool, + system_description_path, + "--search-path", b.getInstallPath(.bin, ""), + "--board", microkit_board, + "--config", microkit_config, + "-o", final_image_dest, + "-r", b.getInstallPath(.prefix, "./report.txt") }); + microkit_tool_cmd.step.dependOn(b.getInstallStep()); + microkit_tool_cmd.step.dependOn(&timer_driver_install.step); + microkit_tool_cmd.step.dependOn(&clk_driver_install.step); + const microkit_step = b.step("microkit", "Compile and build the final bootable image"); + microkit_step.dependOn(µkit_tool_cmd.step); + b.default_step = microkit_step; +} diff --git a/examples/clk/build.zig.zon b/examples/clk/build.zig.zon new file mode 100644 index 000000000..6deea19f4 --- /dev/null +++ b/examples/clk/build.zig.zon @@ -0,0 +1,18 @@ +// +// Copyright 2024, UNSW +// SPDX-License-Identifier: BSD-2-Clause +// +.{ + .name = "sddf_clk_example", + .version = "1.0.0", + + .dependencies = .{ + .sddf = .{ + .path = "../../" + }, + }, + .paths = .{ + "build.zig", + "build.zig.zon", + } +} diff --git a/examples/clk/client.c b/examples/clk/client.c new file mode 100644 index 000000000..4b6e21bc7 --- /dev/null +++ b/examples/clk/client.c @@ -0,0 +1,142 @@ +/* + * Copyright 2024, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +#define CLK_DRIVER_CH 0 + +#ifdef TEST_BOARD_odroidc4 +#include +#elif TEST_BOARD_maaxboard +#include +#else +#error "The target board is not supported\n" +#endif + +void init(void) +{ + sddf_dprintf("--------------------\n"); + sddf_dprintf("Clock Driver Test\n"); + +#ifdef TEST_BOARD_odroidc4 + sddf_dprintf("Test board: odroidc4\n"); + + /** + * CLKID_CLK81 = 10 + * CLKID_I2C = 24 + * CLKID_CPU_CLK = 187 + * + * see `sddf/drivers/clk/meson/include/g12a-bindings.h` for more clock indices. + * + **/ + uint32_t clk_id_to_enable = CLKID_CLK81; + int ret = sddf_clk_enable(CLK_DRIVER_CH, clk_id_to_enable); + if (ret) { + sddf_dprintf("Failed to enable clock %u: err - %d\n", clk_id_to_enable, ret); + } else { + sddf_dprintf("Successfully enabled clock %u\n", clk_id_to_enable); + } + + uint32_t clk_id_to_disable = CLKID_I2C; + ret = sddf_clk_disable(CLK_DRIVER_CH, clk_id_to_disable); + if (ret) { + sddf_dprintf("Failed to disable clock %u: err - %d\n", clk_id_to_enable, ret); + } else { + sddf_dprintf("Successfully disabled clock %u\n", clk_id_to_enable); + } + + uint64_t rate = 0; + uint32_t clk_id_to_set_rate = CLKID_CLK81; + ret = sddf_clk_get_rate(CLK_DRIVER_CH, clk_id_to_set_rate, &rate); + if (ret) { + sddf_dprintf("Failed to get the rate of clock %u: err - %d\n", clk_id_to_set_rate, ret); + } else { + sddf_dprintf("The rate of clock %u: %lu\n", clk_id_to_set_rate, rate); + } + + ret = sddf_clk_set_rate(CLK_DRIVER_CH, clk_id_to_set_rate, 150000000, &rate); + if (ret) { + sddf_dprintf("Failed to set the rate of clock %u: err - %d\n", clk_id_to_set_rate, ret); + } else { + sddf_dprintf("Set the rate of clock %u to %lu\n", ret, rate); + } + + uint32_t clk_id_to_get_rate = CLKID_CPU_CLK; + ret = sddf_clk_get_rate(CLK_DRIVER_CH, clk_id_to_get_rate, &rate); + if (ret) { + sddf_dprintf("Failed to get the rate of clock %u: err - %d\n", clk_id_to_get_rate, ret); + } else { + sddf_dprintf("The rate of clock %u: %lu\n", clk_id_to_get_rate, rate); + } + + uint32_t clk_id_to_test_parent = CLKID_SD_EMMC_A_CLK0_SEL; + uint32_t parent_id = 0; + ret = sddf_clk_get_parent(CLK_DRIVER_CH, clk_id_to_test_parent, &parent_id); + if (ret) { + sddf_dprintf("Failed to get the parent of clock %u: err - %d\n", clk_id_to_test_parent, ret); + } else { + sddf_dprintf("The parent of clock %u: %u\n", clk_id_to_test_parent, parent_id); + } + + uint32_t pclk_idx = 3; + ret = sddf_clk_set_parent(CLK_DRIVER_CH, clk_id_to_test_parent, pclk_idx); + if (ret) { + sddf_dprintf("Failed to set the parent of clock %u: err - %d\n", clk_id_to_test_parent, ret); + } else { + ret = sddf_clk_get_parent(CLK_DRIVER_CH, clk_id_to_test_parent, &parent_id); + sddf_dprintf("The parent of clock %u has been set to: %u\n", clk_id_to_test_parent, parent_id); + } + +#elif TEST_BOARD_maaxboard + sddf_dprintf("Test board: maaxboard\n"); + int ret = 0; + + /** + * IMX8MQ_CLK_SAI1_ROOT = 196 + * IMX8MQ_CLK_I2C1 = 144 + * + * see `sddf/drivers/clk/imx/include/imx8mq-bindings.h` for more clock indices. + * */ + + uint32_t clk_id_to_enable = IMX8MQ_CLK_SAI1_ROOT; + ret = sddf_clk_enable(CLK_DRIVER_CH, clk_id_to_enable); + if (ret) { + sddf_dprintf("Failed to enable clock %u: err - %d\n", clk_id_to_enable, ret); + } else { + sddf_dprintf("Successfully enabled clock %u\n", clk_id_to_enable); + } + + uint32_t clk_id_to_test_parent = IMX8MQ_CLK_I2C1; + uint32_t parent_id = 0; + ret = sddf_clk_get_parent(CLK_DRIVER_CH, clk_id_to_test_parent, &parent_id); + if (ret) { + sddf_dprintf("Failed to get the parent of clock %u: err - %d\n", clk_id_to_test_parent, ret); + } else { + sddf_dprintf("The parent of clock %u: %u\n", clk_id_to_test_parent, parent_id); + } + + uint32_t pclk_idx = 3; + ret = sddf_clk_set_parent(CLK_DRIVER_CH, clk_id_to_test_parent, pclk_idx); + if (ret) { + sddf_dprintf("Failed to set the parent of clock %u: err - %d\n", clk_id_to_test_parent, ret); + } else { + ret = sddf_clk_get_parent(CLK_DRIVER_CH, clk_id_to_test_parent, &parent_id); + sddf_dprintf("The parent of clock %u has been set to: %u\n", clk_id_to_test_parent, parent_id); + } + +#else + sddf_dprintf("No tests for the target board\n", ret); +#endif + + sddf_dprintf("--------------------\n"); +} + +void notified(microkit_channel ch) +{ +} diff --git a/examples/clk/clk.mk b/examples/clk/clk.mk new file mode 100644 index 000000000..258e6f25c --- /dev/null +++ b/examples/clk/clk.mk @@ -0,0 +1,89 @@ +# +# Copyright 2024, UNSW +# +# SPDX-License-Identifier: BSD-2-Clause +# + +ifeq ($(strip $(MICROKIT_SDK)),) +$(error MICROKIT_SDK must be specified) +endif + + +ifeq ($(strip $(MICROKIT_BOARD)), odroidc4) + CPU := cortex-a55 + DTS_FILE := $(TOP)/dts/odroidc4.dts + SYSTEM_FILE := ${TOP}/board/odroidc4/clk.system + ARCH := aarch64 + DRIVER_DIR := meson + DRIVER_CLASS := meson + CPU := cortex-a55 +else ifeq ($(strip $(MICROKIT_BOARD)), maaxboard) + ARCH := aarch64 + DTS_FILE := $(TOP)/dts/maaxboard.dts + SYSTEM_FILE := ${TOP}/board/maaxboard/clk.system + DRIVER_DIR := imx + DRIVER_CLASS := imx + CPU := cortex-a53 +else +$(error Unsupported MICROKIT_BOARD given) +endif + +BUILD_DIR ?= $(TOP)/build +# By default we make a debug build so that the client debug prints can be seen. +MICROKIT_CONFIG ?= debug + +CC := aarch64-none-elf-gcc +LD := aarch64-none-elf-ld +AR := aarch64-none-elf-ar +AS := aarch64-none-elf-as +RANLIB := aarch64-none-elf-ranlib +PYTHON := python3 + +MICROKIT_TOOL ?= $(MICROKIT_SDK)/bin/microkit + +BOARD_DIR := $(MICROKIT_SDK)/board/$(MICROKIT_BOARD)/$(MICROKIT_CONFIG) +UTIL := $(SDDF)/util + +IMAGES := timer_driver.elf clk_driver.elf client.elf +CFLAGS := -mcpu=$(CPU) \ + -mstrict-align \ + -nostdlib \ + -ffreestanding \ + -g3 \ + -Wall -Wno-unused-function -Werror -Wno-unused-command-line-argument \ + -I$(BOARD_DIR)/include \ + -I$(SDDF)/include \ + -I$(LIBMICROKITCO_PATH) \ + -I$(TOP) \ + -DBOARD_CLASS_$(DRIVER_CLASS) + +LDFLAGS := -L$(BOARD_DIR)/lib -L. +LIBS := --start-group -lmicrokit -Tmicrokit.ld libsddf_util_debug.a --end-group + +IMAGE_FILE := loader.img +REPORT_FILE := report.txt +CLIENT_OBJS := client.o +CLK_DRIVER := $(SDDF)/drivers/clk/$(DRIVER_DIR) +TIMER_DRIVER := $(SDDF)/drivers/timer/$(DRIVER_DIR) + +all: $(IMAGE_FILE) + +${IMAGES}: libsddf_util_debug.a + +include ${SDDF}/util/util.mk +include ${TIMER_DRIVER}/timer_driver.mk +include ${CLK_DRIVER}/clk_driver.mk + +client.o: ${TOP}/client.c + $(CC) -c $(CFLAGS) $(CHIP_HEADER_INC) -DTEST_BOARD_${MICROKIT_BOARD} $< -o client.o + +client.elf: client.o + $(LD) $(LDFLAGS) $^ $(LIBS) -o $@ + +$(IMAGE_FILE) $(REPORT_FILE): $(IMAGES) $(SYSTEM_FILE) + $(MICROKIT_TOOL) $(SYSTEM_FILE) --search-path $(TOP)/build --board $(MICROKIT_BOARD) --config $(MICROKIT_CONFIG) -o $(IMAGE_FILE) -r $(REPORT_FILE) + +clean:: + rm -f client.o +clobber:: clean + rm -f client.elf ${IMAGE_FILE} ${REPORT_FILE} diff --git a/examples/clk/dts/maaxboard.dts b/examples/clk/dts/maaxboard.dts new file mode 100644 index 000000000..434b0e863 --- /dev/null +++ b/examples/clk/dts/maaxboard.dts @@ -0,0 +1,1950 @@ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * Copyright (C) 2017-2018 Pengutronix, Lucas Stach + * Copyright 2019 EMBEST + * Copyright 2022 Capgemini Engineering + * + * SPDX-License-Identifier: GPL-2.0-only + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * This file is derived from a DTS file supplied by Avnet. + * + * The licenses of all input files to this process are compatible + * with GPL-2.0. + * + * The following commands were used to derive this file: + * > git clone https://github.com/Avnet/linux-imx.git + * > cd linux-imx + * > cpp -nostdinc -I include -I arch -undef -x assembler-with-cpp \ + * > arch/arm64/boot/dts/freescale/maaxboard-dcss-hdmi.dts temp.dts + * > dtc -o temp.dtb temp.dts + * > dtc -o maaxboard.dts temp.dtb + * > rm temp.dts temp.dtb + */ + +/dts-v1/; + +/ { + interrupt-parent = <0x01>; + #address-cells = <0x02>; + #size-cells = <0x02>; + model = "Avnet Maaxboard"; + compatible = "avnet/embest,maaxboard\0fsl,imx8mq"; + + aliases { + csi0 = "/soc@0/bus@30800000/mipi_csi1@30a70000"; + csi1 = "/soc@0/bus@30800000/mipi_csi2@30b60000"; + ethernet0 = "/soc@0/bus@30800000/ethernet@30be0000"; + gpio0 = "/soc@0/bus@30000000/gpio@30200000"; + gpio1 = "/soc@0/bus@30000000/gpio@30210000"; + gpio2 = "/soc@0/bus@30000000/gpio@30220000"; + gpio3 = "/soc@0/bus@30000000/gpio@30230000"; + gpio4 = "/soc@0/bus@30000000/gpio@30240000"; + i2c0 = "/soc@0/bus@30800000/i2c@30a20000"; + i2c1 = "/soc@0/bus@30800000/i2c@30a30000"; + i2c2 = "/soc@0/bus@30800000/i2c@30a40000"; + i2c3 = "/soc@0/bus@30800000/i2c@30a50000"; + mmc0 = "/soc@0/bus@30800000/mmc@30b40000"; + mmc1 = "/soc@0/bus@30800000/mmc@30b50000"; + serial0 = "/soc@0/bus@30800000/serial@30860000"; + serial1 = "/soc@0/bus@30800000/serial@30890000"; + serial2 = "/soc@0/bus@30800000/serial@30880000"; + serial3 = "/soc@0/bus@30800000/serial@30a60000"; + spi0 = "/soc@0/bus@30800000/spi@30820000"; + spi1 = "/soc@0/bus@30800000/spi@30830000"; + spi2 = "/soc@0/bus@30800000/spi@30840000"; + }; + + clock-ckil { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x8000>; + clock-output-names = "ckil"; + phandle = <0x15>; + }; + + clock-osc-25m { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x17d7840>; + clock-output-names = "osc_25m"; + phandle = <0x16>; + }; + + clock-osc-27m { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x19bfcc0>; + clock-output-names = "osc_27m"; + phandle = <0x17>; + }; + + clock-ext1 { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x7ed6b40>; + clock-output-names = "clk_ext1"; + phandle = <0x18>; + }; + + clock-ext2 { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x7ed6b40>; + clock-output-names = "clk_ext2"; + phandle = <0x19>; + }; + + clock-ext3 { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x7ed6b40>; + clock-output-names = "clk_ext3"; + phandle = <0x1a>; + }; + + clock-ext4 { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x7ed6b40>; + clock-output-names = "clk_ext4"; + phandle = <0x1b>; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x00>; + clock-latency = <0xee6c>; + clocks = <0x02 0x102>; + enable-method = "psci"; + next-level-cache = <0x03>; + operating-points-v2 = <0x04>; + #cooling-cells = <0x02>; + nvmem-cells = <0x05>; + nvmem-cell-names = "speed_grade"; + cpu-idle-states = <0x06>; + phandle = <0x08>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x01>; + clock-latency = <0xee6c>; + clocks = <0x02 0x102>; + enable-method = "psci"; + next-level-cache = <0x03>; + operating-points-v2 = <0x04>; + #cooling-cells = <0x02>; + cpu-idle-states = <0x06>; + phandle = <0x09>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x02>; + clock-latency = <0xee6c>; + clocks = <0x02 0x102>; + enable-method = "psci"; + next-level-cache = <0x03>; + operating-points-v2 = <0x04>; + #cooling-cells = <0x02>; + cpu-idle-states = <0x06>; + phandle = <0x0a>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x03>; + clock-latency = <0xee6c>; + clocks = <0x02 0x102>; + enable-method = "psci"; + next-level-cache = <0x03>; + operating-points-v2 = <0x04>; + #cooling-cells = <0x02>; + cpu-idle-states = <0x06>; + phandle = <0x0b>; + }; + + l2-cache0 { + compatible = "cache"; + phandle = <0x03>; + }; + + idle-states { + entry-method = "psci"; + + cpu-sleep { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x10033>; + local-timer-stop; + entry-latency-us = <0x3e8>; + exit-latency-us = <0x2bc>; + min-residency-us = <0xa8c>; + wakeup-latency-us = <0x5dc>; + phandle = <0x06>; + }; + }; + }; + + opp-table { + compatible = "operating-points-v2"; + opp-shared; + phandle = <0x04>; + + opp-800000000 { + opp-hz = <0x00 0x2faf0800>; + opp-microvolt = <0xdbba0>; + opp-supported-hw = <0x0f 0x04>; + clock-latency-ns = <0x249f0>; + opp-suspend; + }; + + opp-1000000000 { + opp-hz = <0x00 0x3b9aca00>; + opp-microvolt = <0xdbba0>; + opp-supported-hw = <0x0e 0x03>; + clock-latency-ns = <0x249f0>; + opp-suspend; + }; + + opp-1300000000 { + opp-hz = <0x00 0x4d7c6d00>; + opp-microvolt = <0xf4240>; + opp-supported-hw = <0x0c 0x04>; + clock-latency-ns = <0x249f0>; + opp-suspend; + }; + + opp-1500000000 { + opp-hz = <0x00 0x59682f00>; + opp-microvolt = <0xf4240>; + opp-supported-hw = <0x08 0x03>; + clock-latency-ns = <0x249f0>; + opp-suspend; + }; + }; + + pmu { + compatible = "arm,cortex-a53-pmu"; + interrupts = <0x01 0x07 0x04>; + interrupt-parent = <0x07>; + interrupt-affinity = <0x08 0x09 0x0a 0x0b>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0xfa>; + polling-delay = <0x7d0>; + thermal-sensors = <0x0c 0x00>; + + trips { + + cpu-alert { + temperature = <0x13880>; + hysteresis = <0x7d0>; + type = "passive"; + }; + + cpu-crit { + temperature = <0x17318>; + hysteresis = <0x7d0>; + type = "critical"; + }; + + trip0 { + temperature = <0x13880>; + hysteresis = <0x7d0>; + type = "passive"; + phandle = <0x0d>; + }; + + trip1 { + temperature = <0x14c08>; + hysteresis = <0x7d0>; + type = "passive"; + phandle = <0x0f>; + }; + }; + + cooling-maps { + + map0 { + trip = <0x0d>; + cooling-device = <0x0e 0x00 0x01 0x08 0xffffffff 0xffffffff 0x09 0xffffffff 0xffffffff 0x0a 0xffffffff 0xffffffff 0x0b 0xffffffff 0xffffffff>; + }; + + map1 { + trip = <0x0f>; + cooling-device = <0x0e 0x00 0x02>; + }; + }; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <0x01 0x0d 0x08 0x01 0x0e 0x08 0x01 0x0b 0x08 0x01 0x0a 0x08>; + interrupt-parent = <0x07>; + arm,no-tick-in-suspend; + }; + + busfreq { + compatible = "fsl,imx_busfreq"; + clocks = <0x02 0xea 0x02 0x76 0x02 0x77 0x02 0x77 0x02 0xfc 0x02 0xfb 0x02 0x46 0x02 0x4d 0x02 0x48 0x02 0x4e 0x02 0x71 0x02 0x67 0x02 0x74 0x02 0x02 0x02 0x55 0x02 0x49>; + clock-names = "dram_pll\0dram_alt_src\0dram_apb_src\0dram_apb_pre_div\0dram_core\0dram_alt_root\0sys1_pll_40m\0sys1_pll_400m\0sys1_pll_100m\0sys1_pll_800m\0noc_div\0main_axi_src\0ahb_div\0osc_25m\0sys2_pll_333m\0sys1_pll_133m"; + interrupts = <0x00 0x66 0x04 0x00 0x6d 0x04 0x00 0x6e 0x04 0x00 0x6f 0x04>; + interrupt-name = "irq_busfreq_0\0irq_busfreq_1\0irq_busfreq_2\0irq_busfreq_3"; + }; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x00 0x00 0x00 0x3e000000>; + dma-ranges = <0x40000000 0x00 0x40000000 0xc0000000>; + + caam-sm@100000 { + compatible = "fsl,imx6q-caam-sm"; + reg = <0x100000 0x8000>; + }; + + bus@30000000 { + compatible = "fsl,imx8mq-aips-bus\0simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x30000000 0x30000000 0x400000>; + + sai@30010000 { + compatible = "fsl,imx8mq-sai\0fsl,imx6sx-sai"; + reg = <0x30010000 0x10000>; + interrupts = <0x00 0x5f 0x04>; + clocks = <0x02 0xee 0x02 0x00 0x02 0xc4 0x02 0x00 0x02 0x00>; + clock-names = "bus\0mclk0\0mclk1\0mclk2\0mclk3"; + dmas = <0x10 0x08 0x01 0x00 0x10 0x09 0x01 0x00>; + dma-names = "rx\0tx"; + fsl,dataline = <0x00 0xff 0xff>; + status = "disabled"; + }; + + sai@30030000 { + compatible = "fsl,imx8mq-sai\0fsl,imx6sx-sai"; + reg = <0x30030000 0x10000>; + interrupts = <0x00 0x5a 0x04>; + clocks = <0x02 0xf3 0x02 0x00 0x02 0xc9 0x02 0x00 0x02 0x00>; + clock-names = "bus\0mclk0\0mclk1\0mclk2\0mclk3"; + dmas = <0x10 0x04 0x18 0x00 0x10 0x05 0x18 0x00>; + dma-names = "rx\0tx"; + fsl,shared-interrupt; + status = "disabled"; + }; + + sai@30040000 { + compatible = "fsl,imx8mq-sai\0fsl,imx6sx-sai"; + reg = <0x30040000 0x10000>; + interrupts = <0x00 0x5a 0x04>; + clocks = <0x02 0xf2 0x02 0x00 0x02 0xc8 0x02 0x00 0x02 0x00>; + clock-names = "bus\0mclk0\0mclk1\0mclk2\0mclk3"; + dmas = <0x10 0x02 0x18 0x00 0x10 0x03 0x18 0x00>; + dma-names = "rx\0tx"; + fsl,shared-interrupt; + fsl,dataline = <0x00 0x0f 0x0f>; + status = "disabled"; + }; + + sai@30050000 { + compatible = "fsl,imx8mq-sai\0fsl,imx6sx-sai"; + reg = <0x30050000 0x10000>; + interrupts = <0x00 0x64 0x04>; + clocks = <0x02 0xf1 0x02 0x00 0x02 0xc7 0x02 0x00 0x02 0x00 0x02 0x1b 0x02 0x20>; + clock-names = "bus\0mclk0\0mclk1\0mclk2\0mclk3\0pll8k\0pll11k"; + dmas = <0x10 0x00 0x18 0x00 0x10 0x01 0x18 0x00>; + dma-names = "rx\0tx"; + fsl,dataline = <0x00 0x00 0x0f>; + status = "okay"; + assigned-clocks = <0x02 0x84>; + assigned-clock-parents = <0x02 0x1b>; + assigned-clock-rates = <0x1770000>; + phandle = <0x55>; + }; + + gpio@30200000 { + compatible = "fsl,imx8mq-gpio\0fsl,imx35-gpio"; + reg = <0x30200000 0x10000>; + interrupts = <0x00 0x40 0x04 0x00 0x41 0x04>; + clocks = <0x02 0x103>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x11 0x00 0x0a 0x1e>; + phandle = <0x2e>; + }; + + gpio@30210000 { + compatible = "fsl,imx8mq-gpio\0fsl,imx35-gpio"; + reg = <0x30210000 0x10000>; + interrupts = <0x00 0x42 0x04 0x00 0x43 0x04>; + clocks = <0x02 0x104>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x11 0x00 0x28 0x15>; + phandle = <0x43>; + }; + + gpio@30220000 { + compatible = "fsl,imx8mq-gpio\0fsl,imx35-gpio"; + reg = <0x30220000 0x10000>; + interrupts = <0x00 0x44 0x04 0x00 0x45 0x04>; + clocks = <0x02 0x105>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x11 0x00 0x3d 0x1a>; + phandle = <0x30>; + }; + + gpio@30230000 { + compatible = "fsl,imx8mq-gpio\0fsl,imx35-gpio"; + reg = <0x30230000 0x10000>; + interrupts = <0x00 0x46 0x04 0x00 0x47 0x04>; + clocks = <0x02 0x106>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x11 0x00 0x57 0x20>; + }; + + gpio@30240000 { + compatible = "fsl,imx8mq-gpio\0fsl,imx35-gpio"; + reg = <0x30240000 0x10000>; + interrupts = <0x00 0x48 0x04 0x00 0x49 0x04>; + clocks = <0x02 0x107>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x11 0x00 0x77 0x1e>; + phandle = <0x23>; + }; + + tmu@30260000 { + compatible = "fsl,imx8mq-tmu"; + reg = <0x30260000 0x10000>; + interrupt = <0x00 0x31 0x04>; + clocks = <0x02 0xf6>; + little-endian; + fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>; + fsl,tmu-calibration = <0x00 0x23 0x01 0x29 0x02 0x2f 0x03 0x35 0x04 0x3d 0x05 0x43 0x06 0x4b 0x07 0x51 0x08 0x57 0x09 0x5f 0x0a 0x67 0x0b 0x6f 0x10000 0x1b 0x10001 0x23 0x10002 0x2b 0x10003 0x33 0x10004 0x3b 0x10005 0x43 0x10006 0x4b 0x10007 0x55 0x10008 0x5d 0x10009 0x67 0x1000a 0x70 0x20000 0x17 0x20001 0x23 0x20002 0x2d 0x20003 0x37 0x20004 0x41 0x20005 0x4b 0x20006 0x57 0x20007 0x63 0x20008 0x6f 0x30000 0x15 0x30001 0x21 0x30002 0x2d 0x30003 0x39 0x30004 0x45 0x30005 0x53 0x30006 0x5f 0x30007 0x71>; + #thermal-sensor-cells = <0x00>; + phandle = <0x0c>; + + throttle-cfgs { + + devfreq { + throttle,max_state = <0x02>; + #cooling-cells = <0x02>; + phandle = <0x0e>; + }; + }; + }; + + watchdog@30280000 { + compatible = "fsl,imx8mq-wdt\0fsl,imx21-wdt"; + reg = <0x30280000 0x10000>; + interrupts = <0x00 0x4e 0x04>; + clocks = <0x02 0xd4>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x12>; + fsl,ext-reset-output; + }; + + watchdog@30290000 { + compatible = "fsl,imx8mq-wdt\0fsl,imx21-wdt"; + reg = <0x30290000 0x10000>; + interrupts = <0x00 0x4f 0x04>; + clocks = <0x02 0xd5>; + status = "disabled"; + }; + + watchdog@302a0000 { + compatible = "fsl,imx8mq-wdt\0fsl,imx21-wdt"; + reg = <0x302a0000 0x10000>; + interrupts = <0x00 0x0a 0x04>; + clocks = <0x02 0xd6>; + status = "disabled"; + }; + + sdma@302c0000 { + compatible = "fsl,imx8mq-sdma\0fsl,imx7d-sdma"; + reg = <0x302c0000 0x10000>; + interrupts = <0x00 0x67 0x04>; + clocks = <0x02 0xe4 0x02 0xe4>; + clock-names = "ipg\0ahb"; + #dma-cells = <0x03>; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; + phandle = <0x10>; + }; + + lcdif@30320000 { + compatible = "fsl,imx8mq-lcdif\0fsl,imx28-lcdif"; + reg = <0x30320000 0x10000>; + clocks = <0x02 0x80>; + clock-names = "pix"; + assigned-clocks = <0x02 0x80 0x02 0x24 0x02 0x21>; + assigned-clock-parents = <0x02 0x25 0x02 0x23 0x02 0x03>; + interrupts = <0x00 0x05 0x04>; + status = "disabled"; + }; + + iomuxc@30330000 { + compatible = "fsl,imx8mq-iomuxc"; + reg = <0x30330000 0x10000>; + pinctrl-names = "default"; + pinctrl-0 = <0x13>; + phandle = <0x11>; + + imx8mq-evk { + + gpio_ledsgrp { + fsl,pins = <0x3c 0x2a4 0x00 0x00 0x00 0x19 0x48 0x2b0 0x00 0x00 0x00 0x19>; + phandle = <0x53>; + }; + + gpio_keysgrp { + fsl,pins = <0x110 0x378 0x00 0x05 0x00 0x56 0x10c 0x374 0x00 0x05 0x00 0x56>; + phandle = <0x54>; + }; + + uart1grp { + fsl,pins = <0x234 0x49c 0x4f4 0x00 0x00 0x49 0x238 0x4a0 0x00 0x00 0x00 0x49>; + phandle = <0x24>; + }; + + uart4grp { + fsl,pins = <0x24c 0x4b4 0x50c 0x00 0x02 0x49 0x250 0x4b8 0x00 0x00 0x00 0x49 0x210 0x478 0x508 0x01 0x01 0x49 0x20c 0x474 0x00 0x01 0x00 0x49 0x208 0x470 0x00 0x05 0x00 0x19>; + phandle = <0x36>; + }; + + wlangrp { + fsl,pins = <0xec 0x354 0x00 0x05 0x00 0x19 0xd0 0x338 0x00 0x05 0x00 0x19 0x28 0x290 0x00 0x05 0x00 0x05>; + phandle = <0x57>; + }; + + reg3V3wfgrp { + fsl,pins = <0xf0 0x358 0x00 0x05 0x00 0x19>; + phandle = <0x56>; + }; + + usdhc1grp { + fsl,pins = <0xa0 0x308 0x00 0x00 0x00 0x83 0xa4 0x30c 0x00 0x00 0x00 0xc3 0xa8 0x310 0x00 0x00 0x00 0xc3 0xac 0x314 0x00 0x00 0x00 0xc3 0xb0 0x318 0x00 0x00 0x00 0xc3 0xb4 0x31c 0x00 0x00 0x00 0xc3 0x40 0x2a8 0x00 0x00 0x00 0x19>; + phandle = <0x3d>; + }; + + usdhc1grp100mhz { + fsl,pins = <0xa0 0x308 0x00 0x00 0x00 0x85 0xa4 0x30c 0x00 0x00 0x00 0xc5 0xa8 0x310 0x00 0x00 0x00 0xc5 0xac 0x314 0x00 0x00 0x00 0xc5 0xb0 0x318 0x00 0x00 0x00 0xc5 0xb4 0x31c 0x00 0x00 0x00 0xc5 0x40 0x2a8 0x00 0x00 0x00 0x19>; + phandle = <0x3e>; + }; + + usdhc1grp200mhz { + fsl,pins = <0xa0 0x308 0x00 0x00 0x00 0x87 0xa4 0x30c 0x00 0x00 0x00 0xc7 0xa8 0x310 0x00 0x00 0x00 0xc7 0xac 0x314 0x00 0x00 0x00 0xc7 0xb0 0x318 0x00 0x00 0x00 0xc7 0xb4 0x31c 0x00 0x00 0x00 0xc7 0x40 0x2a8 0x00 0x00 0x00 0x19>; + phandle = <0x3f>; + }; + + usdhc2grp { + fsl,pins = <0xd4 0x33c 0x00 0x00 0x00 0x83 0xd8 0x340 0x00 0x00 0x00 0xc3 0xdc 0x344 0x00 0x00 0x00 0xc3 0xe0 0x348 0x00 0x00 0x00 0xc3 0xe4 0x34c 0x00 0x00 0x00 0xc3 0xe8 0x350 0x00 0x00 0x00 0xc3>; + phandle = <0x40>; + }; + + i2c1grp { + fsl,pins = <0x214 0x47c 0x00 0x00 0x00 0x4000007f 0x218 0x480 0x00 0x00 0x00 0x4000007f>; + phandle = <0x2b>; + }; + + i2c4grp { + fsl,pins = <0x22c 0x494 0x00 0x00 0x00 0x4000007f 0x230 0x498 0x00 0x00 0x00 0x4000007f>; + phandle = <0x35>; + }; + + csi1grp { + fsl,pins = <0x13c 0x3a4 0x00 0x05 0x00 0x19 0x12c 0x394 0x00 0x05 0x00 0x19>; + phandle = <0x2f>; + }; + + pmicirq { + fsl,pins = <0x44 0x2ac 0x00 0x00 0x00 0x19>; + phandle = <0x2c>; + }; + + wdoggrp { + fsl,pins = <0x30 0x298 0x00 0x01 0x00 0xc6>; + phandle = <0x12>; + }; + + fec1grp { + fsl,pins = <0x68 0x2d0 0x00 0x00 0x00 0x03 0x6c 0x2d4 0x4c0 0x00 0x01 0x23 0x70 0x2d8 0x00 0x00 0x00 0x1f 0x74 0x2dc 0x00 0x00 0x00 0x1f 0x78 0x2e0 0x00 0x00 0x00 0x1f 0x7c 0x2e4 0x00 0x00 0x00 0x1f 0x9c 0x304 0x00 0x00 0x00 0x91 0x98 0x300 0x00 0x00 0x00 0x91 0x94 0x2fc 0x00 0x00 0x00 0x91 0x90 0x2f8 0x00 0x00 0x00 0x91 0x84 0x2ec 0x00 0x00 0x00 0x1f 0x8c 0x2f4 0x00 0x00 0x00 0x91 0x88 0x2f0 0x00 0x00 0x00 0x91 0x80 0x2e8 0x00 0x00 0x00 0x1f 0x4c 0x2b4 0x00 0x00 0x00 0x19>; + phandle = <0x46>; + }; + + hoggrp { + fsl,pins = <0x134 0x39c 0x00 0x05 0x00 0x19 0x138 0x3a0 0x00 0x05 0x00 0x19 0x114 0x37c 0x00 0x05 0x00 0x19 0x118 0x380 0x00 0x05 0x00 0x19 0x130 0x398 0x00 0x05 0x00 0x19 0x34 0x29c 0x00 0x00 0x00 0x19 0x120 0x388 0x00 0x05 0x00 0x19 0xfc 0x364 0x00 0x05 0x00 0x19 0x108 0x370 0x00 0x05 0x00 0x19 0x11c 0x384 0x00 0x05 0x00 0x19>; + phandle = <0x13>; + }; + + ecspi1grp { + fsl,pins = <0x200 0x468 0x00 0x05 0x00 0x19 0x1f8 0x460 0x00 0x00 0x00 0x19 0x1fc 0x464 0x00 0x00 0x00 0x19 0x1f4 0x45c 0x00 0x00 0x00 0x19>; + phandle = <0x22>; + }; + + i2c2grp { + fsl,pins = <0x21c 0x484 0x00 0x00 0x00 0x4000007f 0x220 0x488 0x00 0x00 0x00 0x4000007f>; + phandle = <0x32>; + }; + + i2c3grp { + fsl,pins = <0x224 0x48c 0x00 0x00 0x00 0x4000007f 0x228 0x490 0x00 0x00 0x00 0x4000007f>; + phandle = <0x34>; + }; + + uart2grp { + fsl,pins = <0x23c 0x4a4 0x4fc 0x00 0x00 0x49 0x240 0x4a8 0x00 0x00 0x00 0x49>; + phandle = <0x25>; + }; + + pwm2_grp { + fsl,pins = <0x5c 0x2c4 0x00 0x05 0x00 0x06>; + phandle = <0x1f>; + }; + + pwm4_grp { + fsl,pins = <0x64 0x2cc 0x00 0x05 0x00 0x06>; + phandle = <0x20>; + }; + + sai2grp { + fsl,pins = <0x1bc 0x424 0x00 0x00 0x00 0xd6 0x1c0 0x428 0x00 0x00 0x00 0xd6 0x1b8 0x420 0x00 0x00 0x00 0xd6 0x1c4 0x42c 0x00 0x00 0x00 0xd6>; + phandle = <0x26>; + }; + }; + }; + + syscon@30340000 { + compatible = "fsl,imx8mq-iomuxc-gpr\0fsl,imx6q-iomuxc-gpr\0syscon\0simple-mfd"; + reg = <0x30340000 0x10000>; + phandle = <0x39>; + + mux-controller { + compatible = "mmio-mux"; + #mux-control-cells = <0x01>; + mux-reg-masks = <0x34 0x04>; + phandle = <0x29>; + }; + }; + + ocotp-ctrl@30350000 { + compatible = "fsl,imx8mq-ocotp\0syscon"; + reg = <0x30350000 0x10000>; + clocks = <0x02 0xfa>; + #address-cells = <0x01>; + #size-cells = <0x01>; + + speed-grade@10 { + reg = <0x10 0x04>; + phandle = <0x05>; + }; + + mac-address@640 { + reg = <0x90 0x06>; + phandle = <0x45>; + }; + }; + + syscon@30360000 { + compatible = "fsl,imx8mq-anatop\0syscon"; + reg = <0x30360000 0x10000>; + interrupts = <0x00 0x31 0x04>; + }; + + caam_secvio { + compatible = "fsl,imx6q-caam-secvio"; + interrupts = <0x00 0x14 0x04>; + jtag-tamper = "disabled"; + watchdog-tamper = "enabled"; + internal-boot-tamper = "enabled"; + external-pin-tamper = "disabled"; + }; + + caam-snvs@30370000 { + compatible = "fsl,imx6q-caam-snvs"; + reg = <0x30370000 0x10000>; + }; + + snvs@30370000 { + compatible = "fsl,sec-v4.0-mon\0syscon\0simple-mfd"; + reg = <0x30370000 0x10000>; + phandle = <0x14>; + + snvs-rtc-lp { + compatible = "fsl,sec-v4.0-mon-rtc-lp"; + regmap = <0x14>; + offset = <0x34>; + interrupts = <0x00 0x13 0x04 0x00 0x14 0x04>; + clocks = <0x02 0x108>; + clock-names = "snvs-rtc"; + }; + + snvs-powerkey { + compatible = "fsl,sec-v4.0-pwrkey"; + regmap = <0x14>; + interrupts = <0x00 0x04 0x04>; + clocks = <0x02 0x108>; + clock-names = "snvs"; + linux,keycode = <0x74>; + wakeup-source; + status = "okay"; + }; + }; + + clock-controller@30380000 { + compatible = "fsl,imx8mq-ccm"; + reg = <0x30380000 0x10000>; + interrupts = <0x00 0x55 0x04 0x00 0x56 0x04>; + #clock-cells = <0x01>; + clocks = <0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + clock-names = "ckil\0osc_25m\0osc_27m\0clk_ext1\0clk_ext2\0clk_ext3\0clk_ext4"; + assigned-clocks = <0x02 0x69 0x02 0x75 0x02 0x19 0x02 0x1e>; + assigned-clock-parents = <0x02 0x4c 0x02 0x56>; + assigned-clock-rates = <0x00 0x00 0x2ee00000 0x2b110000>; + phandle = <0x02>; + }; + + reset-controller@30390000 { + compatible = "fsl,imx8mq-src\0syscon"; + reg = <0x30390000 0x10000>; + #reset-cells = <0x01>; + phandle = <0x28>; + }; + + gpc@303a0000 { + compatible = "fsl,imx8mq-gpc"; + reg = <0x303a0000 0x10000>; + interrupt-parent = <0x07>; + interrupt-controller; + broken-wake-request-signals; + #interrupt-cells = <0x03>; + phandle = <0x01>; + + pgc { + #address-cells = <0x01>; + #size-cells = <0x00>; + + power-domain@0 { + #power-domain-cells = <0x00>; + reg = <0x00>; + phandle = <0x27>; + }; + + power-domain@1 { + #power-domain-cells = <0x00>; + reg = <0x01>; + power-domains = <0x1c>; + phandle = <0x50>; + }; + + power-domain@2 { + #power-domain-cells = <0x00>; + reg = <0x02>; + }; + + power-domain@3 { + #power-domain-cells = <0x00>; + reg = <0x03>; + phandle = <0x4e>; + }; + + power-domain@4 { + #power-domain-cells = <0x00>; + reg = <0x04>; + }; + + power-domain@5 { + #power-domain-cells = <0x00>; + reg = <0x05>; + clocks = <0x02 0xd7 0x02 0x66 0x02 0x6f 0x02 0x70>; + power-supply = <0x1d>; + phandle = <0x4b>; + }; + + power-domain@6 { + #power-domain-cells = <0x00>; + reg = <0x06>; + power-supply = <0x1e>; + phandle = <0x51>; + }; + + power-domain@7 { + #power-domain-cells = <0x00>; + reg = <0x07>; + }; + + power-domain@8 { + #power-domain-cells = <0x00>; + reg = <0x08>; + phandle = <0x38>; + }; + + power-domain@9 { + #power-domain-cells = <0x00>; + reg = <0x09>; + phandle = <0x44>; + }; + + power-domain@a { + #power-domain-cells = <0x00>; + reg = <0x0a>; + phandle = <0x1c>; + }; + }; + }; + }; + + bus@30400000 { + compatible = "fsl,imx8mq-aips-bus\0simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x30400000 0x30400000 0x400000>; + + pwm@30660000 { + compatible = "fsl,imx8mq-pwm\0fsl,imx27-pwm"; + reg = <0x30660000 0x10000>; + interrupts = <0x00 0x51 0x04>; + clocks = <0x02 0xbf 0x02 0xbf>; + clock-names = "ipg\0per"; + #pwm-cells = <0x02>; + status = "disabled"; + }; + + pwm@30670000 { + compatible = "fsl,imx8mq-pwm\0fsl,imx27-pwm"; + reg = <0x30670000 0x10000>; + interrupts = <0x00 0x52 0x04>; + clocks = <0x02 0xc0 0x02 0xc0>; + clock-names = "ipg\0per"; + #pwm-cells = <0x02>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x1f>; + }; + + pwm@30680000 { + compatible = "fsl,imx8mq-pwm\0fsl,imx27-pwm"; + reg = <0x30680000 0x10000>; + interrupts = <0x00 0x53 0x04>; + clocks = <0x02 0xc1 0x02 0xc1>; + clock-names = "ipg\0per"; + #pwm-cells = <0x02>; + status = "disabled"; + }; + + pwm@30690000 { + compatible = "fsl,imx8mq-pwm\0fsl,imx27-pwm"; + reg = <0x30690000 0x10000>; + interrupts = <0x00 0x54 0x04>; + clocks = <0x02 0xc2 0x02 0xc2>; + clock-names = "ipg\0per"; + #pwm-cells = <0x02>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x20>; + }; + + timer@306a0000 { + compatible = "nxp,sysctr-timer"; + reg = <0x306a0000 0x20000>; + interrupts = <0x00 0x2f 0x04>; + clocks = <0x16>; + clock-names = "per"; + }; + }; + + bus@30800000 { + compatible = "fsl,imx8mq-aips-bus\0simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x30800000 0x30800000 0x400000 0x8000000 0x8000000 0x10000000>; + + spdif@30810000 { + compatible = "fsl,imx8mm-spdif\0fsl,imx35-spdif"; + reg = <0x30810000 0x10000>; + interrupts = <0x00 0x06 0x04>; + clocks = <0x02 0xec 0x02 0x02 0x02 0x87 0x02 0x00 0x02 0x00 0x02 0x00 0x02 0xec 0x02 0x00 0x02 0x00 0x02 0x00>; + clock-names = "core\0rxtx0\0rxtx1\0rxtx2\0rxtx3\0rxtx4\0rxtx5\0rxtx6\0rxtx7\0spba"; + dmas = <0x21 0x08 0x12 0x00 0x21 0x09 0x12 0x00>; + dma-names = "rx\0tx"; + status = "disabled"; + }; + + spi@30820000 { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "fsl,imx8mq-ecspi\0fsl,imx51-ecspi"; + reg = <0x30820000 0x10000>; + interrupts = <0x00 0x1f 0x04>; + clocks = <0x02 0xb3 0x02 0xb3>; + clock-names = "ipg\0per"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x22>; + fsl,spi-num-chipselects = <0x01>; + cs-gpios = <0x23 0x09 0x00>; + + spidev@0 { + compatible = "fsl,spidev\0semtech,sx1301"; + reg = <0x00>; + spi-max-frequency = <0x1e8480>; + }; + }; + + spi@30830000 { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "fsl,imx8mq-ecspi\0fsl,imx51-ecspi"; + reg = <0x30830000 0x10000>; + interrupts = <0x00 0x20 0x04>; + clocks = <0x02 0xb4 0x02 0xb4>; + clock-names = "ipg\0per"; + status = "disabled"; + }; + + spi@30840000 { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "fsl,imx8mq-ecspi\0fsl,imx51-ecspi"; + reg = <0x30840000 0x10000>; + interrupts = <0x00 0x21 0x04>; + clocks = <0x02 0xb5 0x02 0xb5>; + clock-names = "ipg\0per"; + status = "disabled"; + }; + + serial@30860000 { + compatible = "fsl,imx8mq-uart\0fsl,imx6q-uart"; + reg = <0x30860000 0x10000>; + interrupts = <0x00 0x1a 0x04>; + clocks = <0x02 0xca 0x02 0xca>; + clock-names = "ipg\0per"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x24>; + assigned-clocks = <0x02 0x94>; + assigned-clock-parents = <0x02 0x02>; + }; + + serial@30880000 { + compatible = "fsl,imx8mq-uart\0fsl,imx6q-uart"; + reg = <0x30880000 0x10000>; + interrupts = <0x00 0x1c 0x04>; + clocks = <0x02 0xcc 0x02 0xcc>; + clock-names = "ipg\0per"; + status = "disabled"; + }; + + serial@30890000 { + compatible = "fsl,imx8mq-uart\0fsl,imx6q-uart"; + reg = <0x30890000 0x10000>; + interrupts = <0x00 0x1b 0x04>; + clocks = <0x02 0xcb 0x02 0xcb>; + clock-names = "ipg\0per"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x25>; + assigned-clocks = <0x02 0x95>; + assigned-clock-parents = <0x02 0x02>; + }; + + spdif@308a0000 { + compatible = "fsl,imx8mm-spdif\0fsl,imx35-spdif"; + reg = <0x308a0000 0x10000>; + interrupts = <0x00 0x0d 0x04>; + clocks = <0x02 0xec 0x02 0x02 0x02 0x88 0x02 0x00 0x02 0x00 0x02 0x00 0x02 0xec 0x02 0x00 0x02 0x00 0x02 0x00>; + clock-names = "core\0rxtx0\0rxtx1\0rxtx2\0rxtx3\0rxtx4\0rxtx5\0rxtx6\0rxtx7\0spba"; + dmas = <0x21 0x10 0x12 0x00 0x21 0x11 0x12 0x00>; + dma-names = "rx\0tx"; + status = "disabled"; + }; + + sai@308b0000 { + #sound-dai-cells = <0x00>; + compatible = "fsl,imx8mq-sai"; + reg = <0x308b0000 0x10000>; + interrupts = <0x00 0x60 0x04>; + clocks = <0x02 0xef 0x02 0x00 0x02 0xc5 0x02 0x00 0x02 0x00>; + clock-names = "bus\0mclk0\0mclk1\0mclk2\0mclk3"; + dmas = <0x21 0x0a 0x18 0x00 0x21 0x0b 0x18 0x00>; + dma-names = "rx\0tx"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x26>; + assigned-clocks = <0x02 0x82>; + assigned-clock-parents = <0x02 0x1b>; + assigned-clock-rates = <0x1770000>; + phandle = <0x59>; + }; + + sai@308c0000 { + compatible = "fsl,imx8mq-sai\0fsl,imx6sx-sai"; + reg = <0x308c0000 0x10000>; + interrupts = <0x00 0x32 0x04>; + clocks = <0x02 0xf0 0x02 0x00 0x02 0xc6 0x02 0x00 0x02 0x00>; + clock-names = "bus\0mclk0\0mclk1\0mclk2\0mclk3"; + dmas = <0x21 0x0c 0x18 0x00 0x21 0x0d 0x18 0x00>; + dma-names = "rx\0tx"; + status = "disabled"; + }; + + crypto@30900000 { + compatible = "fsl,sec-v4.0"; + #address-cells = <0x01>; + #size-cells = <0x01>; + reg = <0x30900000 0x40000>; + ranges = <0x00 0x30900000 0x40000>; + interrupts = <0x00 0x5b 0x04>; + clocks = <0x02 0x74 0x02 0xec>; + clock-names = "aclk\0ipg"; + + jr@1000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x1000 0x1000>; + interrupts = <0x00 0x69 0x04>; + }; + + jr@2000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x2000 0x1000>; + interrupts = <0x00 0x6a 0x04>; + }; + + jr@3000 { + compatible = "fsl,sec-v4.0-job-ring"; + reg = <0x3000 0x1000>; + interrupts = <0x00 0x72 0x04>; + }; + }; + + dphy@30a00300 { + compatible = "fsl,imx8mq-mipi-dphy"; + reg = <0x30a00300 0x100>; + clocks = <0x02 0xa4>; + clock-names = "phy_ref"; + assigned-clocks = <0x02 0xa4>; + assigned-clock-parents = <0x02 0x25>; + assigned-clock-rates = <0x16e3600>; + #phy-cells = <0x00>; + power-domains = <0x27>; + status = "disabled"; + phandle = <0x2a>; + }; + + mipi_dsi@30a00000 { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "fsl,imx8mq-nwl-dsi"; + reg = <0x30a00000 0x300>; + clocks = <0x02 0xa3 0x02 0xf4 0x02 0xf5 0x02 0xa4 0x02 0x23 0x02 0x80>; + clock-names = "core\0rx_esc\0tx_esc\0phy_ref\0video_pll\0lcdif"; + assigned-clocks = <0x02 0xa4 0x02 0xa3 0x02 0xf4 0x02 0xf5>; + assigned-clock-parents = <0x02 0x25 0x02 0x4c 0x02 0x47>; + assigned-clock-rates = <0x19bfcc0 0xfdad680 0x4c4b400 0x1312d00>; + interrupts = <0x00 0x22 0x04>; + power-domains = <0x27>; + resets = <0x28 0x15 0x28 0x17 0x28 0x18 0x28 0x19>; + reset-names = "byte\0dpi\0esc\0pclk"; + mux-controls = <0x29 0x00>; + phys = <0x2a>; + phy-names = "dphy"; + status = "disabled"; + }; + + i2c@30a20000 { + compatible = "fsl,imx8mq-i2c\0fsl,imx21-i2c"; + reg = <0x30a20000 0x10000>; + interrupts = <0x00 0x23 0x04>; + clocks = <0x02 0xb8>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + clock-frequency = <0x186a0>; + pinctrl-names = "default"; + pinctrl-0 = <0x2b>; + + pmic@4b { + compatible = "rohm,bd71837"; + reg = <0x4b>; + pinctrl-names = "default"; + pinctrl-0 = <0x2c>; + clocks = <0x2d>; + clock-names = "osc"; + clock-output-names = "pmic_clk"; + interrupt-parent = <0x2e>; + interrupts = <0x07 0x01>; + interrupt-names = "irq"; + rohm,reset-snvs-powered; + + regulators { + + BUCK1 { + regulator-name = "buck1"; + regulator-min-microvolt = <0xaae60>; + regulator-max-microvolt = <0x13d620>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <0x4e2>; + rohm,dvs-run-voltage = <0xdbba0>; + rohm,dvs-idle-voltage = <0xcf850>; + rohm,dvs-suspend-voltage = <0xc3500>; + }; + + BUCK2 { + regulator-name = "buck2"; + regulator-min-microvolt = <0xaae60>; + regulator-max-microvolt = <0x13d620>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <0x4e2>; + rohm,dvs-run-voltage = <0xf4240>; + rohm,dvs-idle-voltage = <0xdbba0>; + }; + + BUCK3 { + regulator-name = "buck3"; + regulator-min-microvolt = <0xaae60>; + regulator-max-microvolt = <0x13d620>; + regulator-boot-on; + rohm,dvs-run-voltage = <0xf4240>; + regulator-enable-ramp-delay = <0xb4>; + phandle = <0x1d>; + }; + + BUCK4 { + regulator-name = "buck4"; + regulator-min-microvolt = <0xaae60>; + regulator-max-microvolt = <0x13d620>; + rohm,dvs-run-voltage = <0xf4240>; + regulator-boot-on; + regulator-enable-ramp-delay = <0xb4>; + phandle = <0x1e>; + }; + + BUCK5 { + regulator-name = "buck5"; + regulator-min-microvolt = <0xdbba0>; + regulator-max-microvolt = <0xf4240>; + regulator-boot-on; + regulator-always-on; + }; + + BUCK6 { + regulator-name = "buck6"; + regulator-min-microvolt = <0x2dc6c0>; + regulator-max-microvolt = <0x325aa0>; + regulator-boot-on; + regulator-always-on; + }; + + BUCK7 { + regulator-name = "buck7"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1cfde0>; + regulator-boot-on; + regulator-always-on; + }; + + BUCK8 { + regulator-name = "buck8"; + regulator-min-microvolt = <0x124f80>; + regulator-max-microvolt = <0x13d620>; + regulator-boot-on; + regulator-always-on; + }; + + LDO1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <0x2dc6c0>; + regulator-max-microvolt = <0x325aa0>; + regulator-boot-on; + regulator-always-on; + }; + + LDO2 { + regulator-name = "ldo2"; + regulator-min-microvolt = <0xdbba0>; + regulator-max-microvolt = <0xdbba0>; + regulator-boot-on; + regulator-always-on; + }; + + LDO3 { + regulator-name = "ldo3"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1cfde0>; + regulator-boot-on; + regulator-always-on; + }; + + LDO4 { + regulator-name = "ldo4"; + regulator-min-microvolt = <0xdbba0>; + regulator-max-microvolt = <0xf4240>; + regulator-boot-on; + regulator-always-on; + }; + + LDO5 { + regulator-name = "ldo5"; + regulator-min-microvolt = <0x2625a0>; + regulator-max-microvolt = <0x27ac40>; + regulator-boot-on; + regulator-always-on; + }; + + LDO6 { + regulator-name = "ldo6"; + regulator-min-microvolt = <0xdbba0>; + regulator-max-microvolt = <0xf4240>; + regulator-boot-on; + regulator-always-on; + }; + + LDO7 { + regulator-name = "ldo7"; + regulator-min-microvolt = <0x2dc6c0>; + regulator-max-microvolt = <0x325aa0>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + + ov5640_mipi@3c { + compatible = "ovti,ov5640_mipi"; + reg = <0x3c>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x2f>; + clocks = <0x02 0xff>; + clock-names = "csi_mclk"; + csi_id = <0x00>; + pwn-gpios = <0x30 0x0e 0x00>; + rst-gpios = <0x30 0x12 0x00>; + mclk = <0x16e3600>; + mclk_source = <0x00>; + + port { + + endpoint { + remote-endpoint = <0x31>; + phandle = <0x3a>; + }; + }; + }; + }; + + i2c@30a30000 { + compatible = "fsl,imx8mq-i2c\0fsl,imx21-i2c"; + reg = <0x30a30000 0x10000>; + interrupts = <0x00 0x24 0x04>; + clocks = <0x02 0xb9>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + clock-frequency = <0x61a80>; + pinctrl-names = "default"; + pinctrl-0 = <0x32>; + + wm8960@1a { + #sound-dai-cells = <0x00>; + compatible = "wlf,wm8960"; + reg = <0x1a>; + clocks = <0x33>; + clock-names = "mclk"; + wlf,shared-lrclk; + phandle = <0x5a>; + }; + }; + + i2c@30a40000 { + compatible = "fsl,imx8mq-i2c\0fsl,imx21-i2c"; + reg = <0x30a40000 0x10000>; + interrupts = <0x00 0x25 0x04>; + clocks = <0x02 0xba>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + clock-frequency = <0x186a0>; + pinctrl-names = "default"; + pinctrl-0 = <0x34>; + }; + + i2c@30a50000 { + compatible = "fsl,imx8mq-i2c\0fsl,imx21-i2c"; + reg = <0x30a50000 0x10000>; + interrupts = <0x00 0x26 0x04>; + clocks = <0x02 0xbb>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x61a80>; + pinctrl-names = "default"; + pinctrl-0 = <0x35>; + }; + + serial@30a60000 { + compatible = "fsl,imx8mq-uart\0fsl,imx6q-uart"; + reg = <0x30a60000 0x10000>; + interrupts = <0x00 0x1d 0x04>; + clocks = <0x02 0xcd 0x02 0xcd>; + clock-names = "ipg\0per"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x36>; + assigned-clocks = <0x02 0x97>; + assigned-clock-parents = <0x02 0x47>; + fsl,uart-has-rtscts; + resets = <0x37>; + }; + + mipi_csi1@30a70000 { + compatible = "fsl,mxc-mipi-csi2_yav"; + reg = <0x30a70000 0x1000>; + interrupts = <0x00 0x2c 0x04>; + clocks = <0x02 0xa7 0x02 0xa9 0x02 0xa8>; + clock-names = "clk_core\0clk_esc\0clk_pxl"; + assigned-clocks = <0x02 0xa7 0x02 0xa8 0x02 0xa9>; + assigned-clock-rates = <0x7ed6b40 0x5f5e100 0x3ef1480>; + power-domains = <0x38>; + csis-phy-reset = <0x28 0x4c 0x07>; + phy-gpr = <0x39 0x88>; + status = "okay"; + #address-cells = <0x01>; + #size-cells = <0x00>; + + port { + + endpoint@0 { + remote-endpoint = <0x3a>; + data-lanes = <0x01 0x02>; + bus-type = <0x04>; + phandle = <0x31>; + }; + + endpoint@1 { + remote-endpoint = <0x3b>; + phandle = <0x3c>; + }; + }; + }; + + csi1_bridge@30a90000 { + compatible = "fsl,imx8mq-csi\0fsl,imx6s-csi"; + reg = <0x30a90000 0x10000>; + interrupts = <0x00 0x2a 0x04>; + clocks = <0x02 0x00 0x02 0xe0 0x02 0x00>; + clock-names = "disp-axi\0csi_mclk\0disp_dcic"; + status = "okay"; + fsl,mipi-mode; + fsl,two-8bit-sensor-mode; + + port { + + endpoint { + remote-endpoint = <0x3c>; + phandle = <0x3b>; + }; + }; + }; + + mu@30aa0000 { + compatible = "fsl,imx8mq-mu\0fsl,imx6sx-mu"; + reg = <0x30aa0000 0x10000>; + interrupts = <0x00 0x58 0x04>; + clocks = <0x02 0xfd>; + clock-names = "mu"; + #mbox-cells = <0x02>; + phandle = <0x52>; + }; + + mmc@30b40000 { + compatible = "fsl,imx8mq-usdhc\0fsl,imx7d-usdhc"; + reg = <0x30b40000 0x10000>; + interrupts = <0x00 0x16 0x04>; + clocks = <0x02 0xec 0x02 0x69 0x02 0xd2>; + clock-names = "ipg\0ahb\0per"; + assigned-clocks = <0x02 0x8e>; + assigned-clock-rates = <0x17d78400>; + fsl,tuning-start-tap = <0x14>; + fsl,tuning-step = <0x02>; + bus-width = <0x04>; + status = "okay"; + pinctrl-names = "default\0state_100mhz\0state_200mhz"; + pinctrl-0 = <0x3d>; + pinctrl-1 = <0x3e>; + pinctrl-2 = <0x3f>; + non-removable; + no-sdio; + no-1-8-v; + }; + + mmc@30b50000 { + compatible = "fsl,imx8mq-usdhc\0fsl,imx7d-usdhc"; + reg = <0x30b50000 0x10000>; + interrupts = <0x00 0x17 0x04>; + clocks = <0x02 0xec 0x02 0x69 0x02 0xd3>; + clock-names = "ipg\0ahb\0per"; + fsl,tuning-start-tap = <0x14>; + fsl,tuning-step = <0x02>; + bus-width = <0x04>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x40>; + vmmc-supply = <0x41>; + mmc-pwrseq = <0x42>; + no-1-8-v; + non-removable; + pm-ignore-notify; + keep-power-in-suspend; + #address-cells = <0x01>; + #size-cells = <0x00>; + + bcrmf@1 { + reg = <0x01>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <0x43>; + interrupts = <0x0c 0x08>; + interrupt-names = "host-wake"; + }; + }; + + mipi_csi2@30b60000 { + compatible = "fsl,mxc-mipi-csi2_yav"; + reg = <0x30b60000 0x1000>; + interrupts = <0x00 0x2d 0x04>; + clocks = <0x02 0xaa 0x02 0xac 0x02 0xab>; + clock-names = "clk_core\0clk_esc\0clk_pxl"; + assigned-clocks = <0x02 0xaa 0x02 0xab 0x02 0xac>; + assigned-clock-rates = <0x7ed6b40 0x5f5e100 0x3ef1480>; + power-domains = <0x44>; + csis-phy-reset = <0x28 0x50 0x07>; + phy-gpr = <0x39 0xa4>; + status = "disabled"; + }; + + csi2_bridge@30b80000 { + compatible = "fsl,imx8mq-csi\0fsl,imx6s-csi"; + reg = <0x30b80000 0x10000>; + interrupts = <0x00 0x2b 0x04>; + clocks = <0x02 0x00 0x02 0xe1 0x02 0x00>; + clock-names = "disp-axi\0csi_mclk\0disp_dcic"; + status = "disabled"; + }; + + spi@30bb0000 { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "fsl,imx8mq-qspi\0fsl,imx7d-qspi"; + reg = <0x30bb0000 0x10000 0x8000000 0x10000000>; + reg-names = "QuadSPI\0QuadSPI-memory"; + interrupts = <0x00 0x6b 0x04>; + clocks = <0x02 0xc3 0x02 0xc3>; + clock-names = "qspi_en\0qspi"; + status = "disabled"; + }; + + sdma@30bd0000 { + compatible = "fsl,imx8mq-sdma\0fsl,imx7d-sdma"; + reg = <0x30bd0000 0x10000>; + interrupts = <0x00 0x02 0x04>; + clocks = <0x02 0xe3 0x02 0x74>; + clock-names = "ipg\0ahb"; + #dma-cells = <0x03>; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; + phandle = <0x21>; + }; + + ethernet@30be0000 { + compatible = "fsl,imx8mq-fec\0fsl,imx6sx-fec"; + reg = <0x30be0000 0x10000>; + interrupts = <0x00 0x76 0x04 0x00 0x77 0x04 0x00 0x78 0x04>; + clocks = <0x02 0xb6 0x02 0xb6 0x02 0x8a 0x02 0x89 0x02 0x8b>; + clock-names = "ipg\0ahb\0ptp\0enet_clk_ref\0enet_out"; + fsl,num-tx-queues = <0x03>; + fsl,num-rx-queues = <0x03>; + nvmem-cells = <0x45>; + nvmem-cell-names = "mac-address"; + nvmem_macaddr_swap; + stop-mode = <0x39 0x10 0x03>; + fsl,wakeup_irq = <0x02>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x46>; + phy-mode = "rgmii-id"; + phy-handle = <0x47>; + fsl,magic-packet; + phy-reset-gpios = <0x2e 0x09 0x01>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x04>; + at803x,eee-disabled; + phandle = <0x47>; + }; + }; + }; + }; + + bus@32c00000 { + compatible = "fsl,imx8mq-aips-bus\0simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x32c00000 0x32c00000 0x400000>; + + hdmi@32c00000 { + reg = <0x32c00000 0x100000 0x32e40000 0x40000>; + interrupts = <0x00 0x10 0x04 0x00 0x19 0x04>; + interrupt-names = "plug_in\0plug_out"; + compatible = "cdn,imx8mq-hdmi"; + lane-mapping = <0xe4>; + status = "okay"; + + port@1 { + + endpoint { + remote-endpoint = <0x48>; + phandle = <0x4a>; + }; + }; + }; + + interrupt-controller@32e2d000 { + compatible = "fsl,imx8m-irqsteer\0fsl,imx-irqsteer"; + reg = <0x32e2d000 0x1000>; + interrupts = <0x00 0x12 0x04>; + clocks = <0x02 0xf8>; + clock-names = "ipg"; + fsl,channel = <0x00>; + fsl,num-irqs = <0x40>; + interrupt-controller; + #interrupt-cells = <0x01>; + status = "okay"; + phandle = <0x49>; + }; + + display-controller@32e00000 { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "nxp,imx8mq-dcss"; + reg = <0x32e00000 0x2d000 0x32e2f000 0x1000>; + interrupts = <0x06 0x08 0x09 0x10 0x11>; + interrupt-names = "ctx_ld\0ctxld_kick\0vblank\0dtrc_ch1\0dtrc_ch2"; + interrupt-parent = <0x49>; + clocks = <0x02 0xf8 0x02 0xf7 0x02 0xf9 0x02 0xfe 0x02 0x7a 0x02 0x10a 0x02 0x10b>; + clock-names = "apb\0axi\0rtrm\0pix\0dtrc\0pll_src\0pll_phy_ref"; + assigned-clocks = <0x02 0x6b 0x02 0x6d 0x02 0x10a>; + assigned-clock-parents = <0x02 0x4e 0x02 0x4e 0x02 0x03>; + assigned-clock-rates = <0x2faf0800 0x17d78400>; + status = "okay"; + + port@0 { + + endpoint { + remote-endpoint = <0x4a>; + phandle = <0x48>; + }; + }; + }; + }; + + gpu@38000000 { + compatible = "vivante,gc"; + reg = <0x38000000 0x40000>; + interrupts = <0x00 0x03 0x04>; + clocks = <0x02 0xd7 0x02 0x66 0x02 0x6f 0x02 0x70>; + clock-names = "core\0shader\0bus\0reg"; + assigned-clocks = <0x02 0x61 0x02 0x64 0x02 0x6f 0x02 0x70 0x02 0x10>; + assigned-clock-parents = <0x02 0x11 0x02 0x11 0x02 0x11 0x02 0x11 0x02 0x0f>; + assigned-clock-rates = <0x2faf0800 0x2faf0800 0x2faf0800 0x2faf0800 0x00>; + power-domains = <0x4b>; + status = "disabled"; + }; + + usb@38100000 { + compatible = "fsl,imx8mq-dwc3\0snps,dwc3"; + reg = <0x38100000 0x10000>; + clocks = <0x02 0xce 0x02 0x98 0x02 0x01>; + clock-names = "bus_early\0ref\0suspend"; + assigned-clocks = <0x02 0x6e 0x02 0x98>; + assigned-clock-parents = <0x02 0x56 0x02 0x48>; + assigned-clock-rates = <0x1dcd6500 0x5f5e100>; + interrupts = <0x00 0x28 0x04>; + phys = <0x4c 0x4c>; + phy-names = "usb2-phy\0usb3-phy"; + usb3-resume-missing-cas; + snps,power-down-scale = <0x02>; + status = "okay"; + dr_mode = "host"; + }; + + usb-phy@381f0040 { + compatible = "fsl,imx8mq-usb-phy"; + reg = <0x381f0040 0x40>; + clocks = <0x02 0xd0>; + clock-names = "phy"; + assigned-clocks = <0x02 0x99>; + assigned-clock-parents = <0x02 0x48>; + assigned-clock-rates = <0x5f5e100>; + #phy-cells = <0x00>; + status = "okay"; + phandle = <0x4c>; + }; + + usb@38200000 { + compatible = "fsl,imx8mq-dwc3\0snps,dwc3"; + reg = <0x38200000 0x10000>; + clocks = <0x02 0xcf 0x02 0x98 0x02 0x01>; + clock-names = "bus_early\0ref\0suspend"; + assigned-clocks = <0x02 0x6e 0x02 0x98>; + assigned-clock-parents = <0x02 0x56 0x02 0x48>; + assigned-clock-rates = <0x1dcd6500 0x5f5e100>; + interrupts = <0x00 0x29 0x04>; + phys = <0x4d 0x4d>; + phy-names = "usb2-phy\0usb3-phy"; + power-domains = <0x4e>; + usb3-resume-missing-cas; + snps,power-down-scale = <0x02>; + status = "okay"; + dr_mode = "host"; + }; + + usb-phy@382f0040 { + compatible = "fsl,imx8mq-usb-phy"; + reg = <0x382f0040 0x40>; + clocks = <0x02 0xd1>; + clock-names = "phy"; + assigned-clocks = <0x02 0x99>; + assigned-clock-parents = <0x02 0x48>; + assigned-clock-rates = <0x5f5e100>; + #phy-cells = <0x00>; + status = "okay"; + phandle = <0x4d>; + }; + + dma-apbh@33000000 { + compatible = "fsl,imx7d-dma-apbh\0fsl,imx28-dma-apbh"; + reg = <0x33000000 0x2000>; + interrupts = <0x00 0x0c 0x04 0x00 0x0c 0x04 0x00 0x0c 0x04 0x00 0x0c 0x04>; + interrupt-names = "gpmi0\0gpmi1\0gpmi2\0gpmi3"; + #dma-cells = <0x01>; + dma-channels = <0x04>; + clocks = <0x02 0x100>; + phandle = <0x4f>; + }; + + gpmi-nand@33002000 { + compatible = "fsl,imx7d-gpmi-nand"; + #address-cells = <0x01>; + #size-cells = <0x01>; + reg = <0x33002000 0x2000 0x33004000 0x4000>; + reg-names = "gpmi-nand\0bch"; + interrupts = <0x00 0x0e 0x04>; + interrupt-names = "bch"; + clocks = <0x02 0xe2 0x02 0x100>; + clock-names = "gpmi_io\0gpmi_bch_apb"; + dmas = <0x4f 0x00>; + dma-names = "rx-tx"; + status = "disabled"; + }; + + pcie@33800000 { + compatible = "fsl,imx8mq-pcie"; + reg = <0x33800000 0x400000 0x1ff00000 0x80000>; + reg-names = "dbi\0config"; + #address-cells = <0x03>; + #size-cells = <0x02>; + device_type = "pci"; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x00 0x1ff80000 0x00 0x10000 0x82000000 0x00 0x18000000 0x18000000 0x00 0x7f00000>; + num-lanes = <0x01>; + num-viewport = <0x04>; + interrupts = <0x00 0x7a 0x04 0x00 0x7f 0x04>; + interrupt-names = "msi\0dma"; + #interrupt-cells = <0x01>; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x07 0x00 0x7d 0x04 0x00 0x00 0x00 0x02 0x07 0x00 0x7c 0x04 0x00 0x00 0x00 0x03 0x07 0x00 0x7b 0x04 0x00 0x00 0x00 0x04 0x07 0x00 0x7a 0x04>; + fsl,max-link-speed = <0x02>; + power-domains = <0x50>; + resets = <0x28 0x1a 0x28 0x1c 0x28 0x1d>; + reset-names = "pciephy\0apps\0turnoff"; + status = "disabled"; + }; + + pcie@33c00000 { + compatible = "fsl,imx8mq-pcie"; + reg = <0x33c00000 0x400000 0x27f00000 0x80000>; + reg-names = "dbi\0config"; + #address-cells = <0x03>; + #size-cells = <0x02>; + device_type = "pci"; + ranges = <0x81000000 0x00 0x00 0x27f80000 0x00 0x10000 0x82000000 0x00 0x20000000 0x20000000 0x00 0x7f00000>; + num-lanes = <0x01>; + num-viewport = <0x04>; + interrupts = <0x00 0x4a 0x04 0x00 0x50 0x04>; + interrupt-names = "msi\0dma"; + #interrupt-cells = <0x01>; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x07 0x00 0x4d 0x04 0x00 0x00 0x00 0x02 0x07 0x00 0x4c 0x04 0x00 0x00 0x00 0x03 0x07 0x00 0x4b 0x04 0x00 0x00 0x00 0x04 0x07 0x00 0x4a 0x04>; + fsl,max-link-speed = <0x02>; + power-domains = <0x50>; + resets = <0x28 0x22 0x28 0x24 0x28 0x25>; + reset-names = "pciephy\0apps\0turnoff"; + status = "disabled"; + }; + + interrupt-controller@38800000 { + compatible = "arm,gic-v3"; + reg = <0x38800000 0x10000 0x38880000 0xc0000 0x31000000 0x2000 0x31010000 0x2000 0x31020000 0x2000>; + #interrupt-cells = <0x03>; + interrupt-controller; + interrupts = <0x01 0x09 0x04>; + interrupt-parent = <0x07>; + phandle = <0x07>; + }; + + ddr-pmu@3d800000 { + compatible = "fsl,imx8mq-ddr-pmu\0fsl,imx8m-ddr-pmu"; + reg = <0x3d800000 0x400000>; + interrupt-parent = <0x07>; + interrupts = <0x00 0x62 0x04>; + }; + + vpu@38300000 { + compatible = "nxp,imx8mq-hantro"; + reg = <0x38300000 0x200000>; + reg-names = "regs_hantro"; + interrupts = <0x00 0x07 0x04 0x00 0x08 0x04>; + interrupt-names = "irq_hantro_g1\0irq_hantro_g2"; + clocks = <0x02 0xe5 0x02 0xe6 0x02 0xdf>; + clock-names = "clk_hantro_g1\0clk_hantro_g2\0clk_hantro_bus"; + assigned-clocks = <0x02 0x78 0x02 0x79 0x02 0x6a>; + assigned-clock-parents = <0x02 0x16 0x02 0x16 0x02 0x4e>; + assigned-clock-rates = <0x23c34600 0x23c34600 0x2faf0800>; + power-domains = <0x51>; + status = "okay"; + }; + }; + + gpu3d@38000000 { + compatible = "fsl,imx8mq-gpu\0fsl,imx6q-gpu"; + reg = <0x00 0x38000000 0x00 0x40000 0x00 0x40000000 0x00 0xc0000000 0x00 0x00 0x00 0x10000000>; + reg-names = "iobase_3d\0phys_baseaddr\0contiguous_mem"; + interrupts = <0x00 0x03 0x04>; + interrupt-names = "irq_3d"; + clocks = <0x02 0xd7 0x02 0x66 0x02 0x6f 0x02 0x70>; + clock-names = "gpu3d_clk\0gpu3d_shader_clk\0gpu3d_axi_clk\0gpu3d_ahb_clk"; + assigned-clocks = <0x02 0x61 0x02 0x64 0x02 0x6f 0x02 0x70>; + assigned-clock-parents = <0x02 0x11 0x02 0x11 0x02 0x11 0x02 0x11>; + assigned-clock-rates = <0x2faf0800 0x2faf0800 0x2faf0800 0x2faf0800>; + power-domains = <0x4b>; + status = "okay"; + }; + + rpmsg { + compatible = "fsl,imx8mq-rpmsg"; + mbox-names = "tx\0rx\0rxdb"; + mboxes = <0x52 0x00 0x01 0x52 0x01 0x01 0x52 0x03 0x01>; + status = "disabled"; + }; + + chosen { + stdout-path = "/soc@0/bus@30800000/serial@30860000"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x00 0x40000000 0x00 0x80000000>; + }; + + reserved-memory { + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x00 0x3c000000>; + alloc-ranges = <0x00 0x40000000 0x00 0x40000000>; + linux,cma-default; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <0x53>; + status = "okay"; + + sys_led { + label = "sys_led"; + gpios = <0x2e 0x05 0x00>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + + usr_led { + label = "usr_led"; + gpios = <0x2e 0x08 0x00>; + default-state = "on"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <0x54>; + + home { + label = "home Button"; + gpios = <0x30 0x07 0x01>; + linux,code = <0x66>; + gpio-key,wakeup; + }; + + back { + label = "back Button"; + gpios = <0x30 0x06 0x01>; + linux,code = <0x19c>; + }; + }; + + gpiomem { + compatible = "maaxboard,maaxboard-gpiomem"; + status = "okay"; + }; + + sound-hdmi { + compatible = "fsl,imx8mq-evk-cdnhdmi\0fsl,imx-audio-cdnhdmi"; + model = "imx-audio-hdmi"; + audio-cpu = <0x55>; + protocol = <0x01>; + hdmi-out; + constraint-rate = <0xac44 0x15888 0x2b110 0x7d00 0xbb80 0x17700 0x2ee00>; + status = "okay"; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x00>; + + regulator@1 { + compatible = "regulator-fixed"; + reg = <0x01>; + pinctrl-names = "default"; + pinctrl-0 = <0x56>; + regulator-name = "WF_3V3"; + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + gpio = <0x43 0x14 0x00>; + regulator-always-on; + enable-active-high; + phandle = <0x41>; + }; + }; + + sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + pinctrl-names = "default"; + pinctrl-0 = <0x57>; + reset-gpios = <0x43 0x13 0x01>; + phandle = <0x42>; + }; + + bt_reset { + compatible = "gpio-reset"; + reset-gpios = <0x23 0x0b 0x01>; + reset-delay-us = <0x3e8>; + reset-post-delay-ms = <0x28>; + #reset-cells = <0x00>; + phandle = <0x37>; + }; + + clock-pmic { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x8000>; + clock-output-names = "pmic_osc"; + phandle = <0x2d>; + }; + + sound-wm8960 { + compatible = "simple-audio-card"; + simple-audio-card,name = "wm8960-sound-audio"; + simple-audio-card,bitclock-master = <0x58>; + simple-audio-card,frame-master = <0x58>; + simple-audio-card,format = "i2s"; + status = "okay"; + simple-audio-card,widgets = "Microphone\0Mic Jack\0Line\0Line In\0Line\0Line Out\0Speaker\0Speaker\0Headphone\0Headphone Jack"; + simple-audio-card,routing = "Headphone Jack\0HP_L\0Headphone Jack\0HP_R\0Speaker\0SPK_LP\0Speaker\0SPK_LN\0Speaker\0SPK_RP\0Speaker\0SPK_RN\0LINPUT1\0Mic Jack\0LINPUT3\0Mic Jack\0RINPUT1\0Mic Jack\0RINPUT2\0Mic Jack\0Mic Jack\0MICB"; + + simple-audio-card,cpu { + sound-dai = <0x59>; + }; + + simple-audio-card,codec { + sound-dai = <0x5a>; + clocks = <0x33>; + phandle = <0x58>; + }; + }; + + wm8960_mclk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-frequency = <0x16e3600>; + clock-output-names = "wm8960-mclk"; + phandle = <0x33>; + }; +}; diff --git a/examples/clk/dts/odroidc4.dts b/examples/clk/dts/odroidc4.dts new file mode 100644 index 000000000..2cc3083c0 --- /dev/null +++ b/examples/clk/dts/odroidc4.dts @@ -0,0 +1,3150 @@ +/* + * Copyright Linux Kernel Team + * + * SPDX-License-Identifier: GPL-2.0-only + * + * This file is derived from an intermediate build stage of the + * Linux kernel. The licenses of all input files to this process + * are compatible with GPL-2.0-only. + */ + +/dts-v1/; + +/ { + interrupt-parent = <0x01>; + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "hardkernel,odroid-c4\0amlogic,sm1"; + model = "Hardkernel ODROID-C4"; + + aliases { + mmc0 = "/soc/sd@ffe05000"; + mmc1 = "/soc/mmc@ffe07000"; + mmc2 = "/soc/sd@ffe03000"; + serial0 = "/soc/bus@ff800000/serial@3000"; + ethernet0 = "/soc/ethernet@ff3f0000"; + }; + + chosen { + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + stdout-path = "serial0:115200n8"; + + framebuffer-cvbs { + compatible = "amlogic,simple-framebuffer\0simple-framebuffer"; + amlogic,pipeline = "vpu-cvbs"; + clocks = <0x02 0xa8 0x02 0x35 0x02 0x3a>; + status = "disabled"; + power-domains = <0x03 0x00>; + }; + + framebuffer-hdmi { + compatible = "amlogic,simple-framebuffer\0simple-framebuffer"; + amlogic,pipeline = "vpu-hdmi"; + clocks = <0x02 0xa8 0x02 0x35 0x02 0x3a>; + status = "disabled"; + power-domains = <0x03 0x00>; + }; + }; + + efuse { + compatible = "amlogic,meson-gxbb-efuse"; + clocks = <0x02 0x6a>; + #address-cells = <0x01>; + #size-cells = <0x01>; + read-only; + secure-monitor = <0x04>; + }; + + gpu-opp-table { + compatible = "operating-points-v2"; + phandle = <0x38>; + + opp-124999998 { + opp-hz = <0x00 0x773593e>; + opp-microvolt = <0xc3500>; + }; + + opp-249999996 { + opp-hz = <0x00 0xee6b27c>; + opp-microvolt = <0xc3500>; + }; + + opp-285714281 { + opp-hz = <0x00 0x1107a769>; + opp-microvolt = <0xc3500>; + }; + + opp-399999994 { + opp-hz = <0x00 0x17d783fa>; + opp-microvolt = <0xc3500>; + }; + + opp-499999992 { + opp-hz = <0x00 0x1dcd64f8>; + opp-microvolt = <0xc3500>; + }; + + opp-666666656 { + opp-hz = <0x00 0x27bc86a0>; + opp-microvolt = <0xc3500>; + }; + + opp-799999987 { + opp-hz = <0x00 0x2faf07f3>; + opp-microvolt = <0xc3500>; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + + secmon@5000000 { + reg = <0x00 0x5000000 0x00 0x300000>; + no-map; + }; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x00 0x10000000>; + alignment = <0x00 0x400000>; + linux,cma-default; + }; + }; + + secure-monitor { + compatible = "amlogic,meson-gxbb-sm"; + phandle = <0x04>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + + pcie@fc000000 { + compatible = "amlogic,g12a-pcie\0snps,dw-pcie"; + reg = <0x00 0xfc000000 0x00 0x400000 0x00 0xff648000 0x00 0x2000 0x00 0xfc400000 0x00 0x200000>; + reg-names = "elbi\0cfg\0config"; + interrupts = <0x00 0xdd 0x04>; + #interrupt-cells = <0x01>; + interrupt-map-mask = <0x00 0x00 0x00 0x00>; + interrupt-map = <0x00 0x00 0x00 0x00 0x01 0x00 0xdf 0x04>; + bus-range = <0x00 0xff>; + #address-cells = <0x03>; + #size-cells = <0x02>; + device_type = "pci"; + ranges = <0x81000000 0x00 0x00 0x00 0xfc600000 0x00 0x100000 0x82000000 0x00 0xfc700000 0x00 0xfc700000 0x00 0x1900000>; + clocks = <0x02 0x30 0x02 0x2d 0x02 0xc9>; + clock-names = "general\0pclk\0port"; + resets = <0x05 0x0c 0x05 0x0f>; + reset-names = "port\0apb"; + num-lanes = <0x01>; + phys = <0x06 0x02>; + phy-names = "pcie"; + status = "disabled"; + power-domains = <0x03 0x03>; + }; + + thermal-zones { + + cpu-thermal { + polling-delay = <0x3e8>; + polling-delay-passive = <0x64>; + thermal-sensors = <0x07>; + + trips { + + cpu-passive { + temperature = <0x14c08>; + hysteresis = <0x7d0>; + type = "passive"; + phandle = <0x08>; + }; + + cpu-hot { + temperature = <0x17318>; + hysteresis = <0x7d0>; + type = "hot"; + phandle = <0x0d>; + }; + + cpu-critical { + temperature = <0x1adb0>; + hysteresis = <0x7d0>; + type = "critical"; + }; + }; + + cooling-maps { + + map0 { + trip = <0x08>; + cooling-device = <0x09 0xffffffff 0xffffffff 0x0a 0xffffffff 0xffffffff 0x0b 0xffffffff 0xffffffff 0x0c 0xffffffff 0xffffffff>; + }; + + map1 { + trip = <0x0d>; + cooling-device = <0x09 0xffffffff 0xffffffff 0x0a 0xffffffff 0xffffffff 0x0b 0xffffffff 0xffffffff 0x0c 0xffffffff 0xffffffff>; + }; + }; + }; + + ddr-thermal { + polling-delay = <0x3e8>; + polling-delay-passive = <0x64>; + thermal-sensors = <0x0e>; + + trips { + + ddr-passive { + temperature = <0x14c08>; + hysteresis = <0x7d0>; + type = "passive"; + phandle = <0x0f>; + }; + + ddr-critical { + temperature = <0x1adb0>; + hysteresis = <0x7d0>; + type = "critical"; + }; + }; + + cooling-maps { + + map { + trip = <0x0f>; + cooling-device = <0x10 0xffffffff 0xffffffff>; + }; + }; + }; + }; + + ethernet@ff3f0000 { + compatible = "amlogic,meson-g12a-dwmac\0snps,dwmac-3.70a\0snps,dwmac"; + reg = <0x00 0xff3f0000 0x00 0x10000 0x00 0xff634540 0x00 0x08>; + interrupts = <0x00 0x08 0x04>; + interrupt-names = "macirq"; + clocks = <0x02 0x26 0x02 0x02 0x02 0x0d 0x02 0x02>; + clock-names = "stmmaceth\0clkin0\0clkin1\0timing-adjustment"; + rx-fifo-depth = <0x1000>; + tx-fifo-depth = <0x800>; + status = "okay"; + power-domains = <0x03 0x06>; + pinctrl-0 = <0x11 0x12>; + pinctrl-names = "default"; + phy-mode = "rgmii"; + phy-handle = <0x13>; + amlogic,tx-delay-ns = <0x02>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "snps,dwmac-mdio"; + phandle = <0x1e>; + }; + }; + + bus@ff600000 { + compatible = "simple-bus"; + reg = <0x00 0xff600000 0x00 0x200000>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0xff600000 0x00 0x200000>; + + hdmi-tx@0 { + compatible = "amlogic,meson-g12a-dw-hdmi"; + reg = <0x00 0x00 0x00 0x10000>; + interrupts = <0x00 0x39 0x01>; + resets = <0x05 0x13 0x05 0x42 0x05 0x4f>; + reset-names = "hdmitx_apb\0hdmitx\0hdmitx_phy"; + clocks = <0x02 0xa8 0x02 0x35 0x02 0x3a>; + clock-names = "isfr\0iahb\0venci"; + #address-cells = <0x01>; + #size-cells = <0x00>; + #sound-dai-cells = <0x00>; + status = "okay"; + pinctrl-0 = <0x14 0x15>; + pinctrl-names = "default"; + hdmi-supply = <0x16>; + phandle = <0x47>; + + port@0 { + reg = <0x00>; + + endpoint { + remote-endpoint = <0x17>; + phandle = <0x28>; + }; + }; + + port@1 { + reg = <0x01>; + + endpoint { + remote-endpoint = <0x18>; + phandle = <0x40>; + }; + }; + }; + + bus@30000 { + compatible = "simple-bus"; + reg = <0x00 0x30000 0x00 0x2000>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0x30000 0x00 0x2000>; + + rng@218 { + compatible = "amlogic,meson-rng"; + reg = <0x00 0x218 0x00 0x04>; + clocks = <0x02 0x1b>; + clock-names = "core"; + }; + }; + + audio-controller@32000 { + compatible = "amlogic,t9015"; + reg = <0x00 0x32000 0x00 0x14>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "ACODEC"; + clocks = <0x02 0x24>; + clock-names = "pclk"; + resets = <0x05 0x3d>; + status = "disabled"; + }; + + bus@34400 { + compatible = "simple-bus"; + reg = <0x00 0x34400 0x00 0x400>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0x34400 0x00 0x400>; + + pinctrl@40 { + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + phandle = <0x19>; + + bank@40 { + reg = <0x00 0x40 0x00 0x4c 0x00 0xe8 0x00 0x18 0x00 0x120 0x00 0x18 0x00 0x2c0 0x00 0x40 0x00 0x340 0x00 0x1c>; + reg-names = "gpio\0pull\0pull-enable\0mux\0ds"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-ranges = <0x19 0x00 0x00 0x56>; + gpio-line-names = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0PIN_36\0PIN_26\0PIN_32\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\0PIN_27\0PIN_28\0PIN_16\0PIN_18\0PIN_22\0PIN_11\0PIN_13\0PIN_7\0PIN_33\0PIN_15\0PIN_19\0PIN_21\0PIN_24\0PIN_23\0PIN_8\0PIN_10\0PIN_29\0PIN_31\0PIN_12\0PIN_3\0PIN_5\0PIN_35"; + phandle = <0x2b>; + + hog-0 { + gpio-hog; + gpios = <0x14 0x00>; + output-high; + line-name = "usb-hub-reset"; + }; + }; + + cec_ao_a_h { + + mux { + groups = "cec_ao_a_h"; + function = "cec_ao_a_h"; + bias-disable; + }; + }; + + cec_ao_b_h { + + mux { + groups = "cec_ao_b_h"; + function = "cec_ao_b_h"; + bias-disable; + }; + }; + + emmc-ctrl { + phandle = <0x2e>; + + mux-0 { + groups = "emmc_cmd"; + function = "emmc"; + bias-pull-up; + drive-strength-microamp = <0xfa0>; + }; + + mux-1 { + groups = "emmc_clk"; + function = "emmc"; + bias-disable; + drive-strength-microamp = <0xfa0>; + }; + }; + + emmc-data-4b { + + mux-0 { + groups = "emmc_nand_d0\0emmc_nand_d1\0emmc_nand_d2\0emmc_nand_d3"; + function = "emmc"; + bias-pull-up; + drive-strength-microamp = <0xfa0>; + }; + }; + + emmc-data-8b { + phandle = <0x2f>; + + mux-0 { + groups = "emmc_nand_d0\0emmc_nand_d1\0emmc_nand_d2\0emmc_nand_d3\0emmc_nand_d4\0emmc_nand_d5\0emmc_nand_d6\0emmc_nand_d7"; + function = "emmc"; + bias-pull-up; + drive-strength-microamp = <0xfa0>; + }; + }; + + emmc-ds { + phandle = <0x30>; + + mux { + groups = "emmc_nand_ds"; + function = "emmc"; + bias-pull-down; + drive-strength-microamp = <0xfa0>; + }; + }; + + emmc_clk_gate { + phandle = <0x31>; + + mux { + groups = "BOOT_8"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <0xfa0>; + }; + }; + + hdmitx_ddc { + phandle = <0x15>; + + mux { + groups = "hdmitx_sda\0hdmitx_sck"; + function = "hdmitx"; + bias-disable; + drive-strength-microamp = <0xfa0>; + }; + }; + + hdmitx_hpd { + phandle = <0x14>; + + mux { + groups = "hdmitx_hpd_in"; + function = "hdmitx"; + bias-disable; + }; + }; + + i2c0-sda-c { + + mux { + groups = "i2c0_sda_c"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c0-sck-c { + + mux { + groups = "i2c0_sck_c"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c0-sda-z0 { + + mux { + groups = "i2c0_sda_z0"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c0-sck-z1 { + + mux { + groups = "i2c0_sck_z1"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c0-sda-z7 { + + mux { + groups = "i2c0_sda_z7"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c0-sda-z8 { + + mux { + groups = "i2c0_sda_z8"; + function = "i2c0"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c1-sda-x { + + mux { + groups = "i2c1_sda_x"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c1-sck-x { + + mux { + groups = "i2c1_sck_x"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c1-sda-h2 { + + mux { + groups = "i2c1_sda_h2"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c1-sck-h3 { + + mux { + groups = "i2c1_sck_h3"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c1-sda-h6 { + + mux { + groups = "i2c1_sda_h6"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c1-sck-h7 { + + mux { + groups = "i2c1_sck_h7"; + function = "i2c1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c2-sda-x { + + mux { + groups = "i2c2_sda_x"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c2-sck-x { + + mux { + groups = "i2c2_sck_x"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c2-sda-z { + + mux { + groups = "i2c2_sda_z"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c2-sck-z { + + mux { + groups = "i2c2_sck_z"; + function = "i2c2"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c3-sda-h { + + mux { + groups = "i2c3_sda_h"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c3-sck-h { + + mux { + groups = "i2c3_sck_h"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c3-sda-a { + + mux { + groups = "i2c3_sda_a"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c3-sck-a { + + mux { + groups = "i2c3_sck_a"; + function = "i2c3"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + mclk0-a { + + mux { + groups = "mclk0_a"; + function = "mclk0"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + mclk1-a { + + mux { + groups = "mclk1_a"; + function = "mclk1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + mclk1-x { + + mux { + groups = "mclk1_x"; + function = "mclk1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + mclk1-z { + + mux { + groups = "mclk1_z"; + function = "mclk1"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + nor { + + mux { + groups = "nor_d\0nor_q\0nor_c\0nor_cs"; + function = "nor"; + bias-disable; + }; + }; + + pdm-din0-a { + + mux { + groups = "pdm_din0_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din0-c { + + mux { + groups = "pdm_din0_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din0-x { + + mux { + groups = "pdm_din0_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din0-z { + + mux { + groups = "pdm_din0_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din1-a { + + mux { + groups = "pdm_din1_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din1-c { + + mux { + groups = "pdm_din1_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din1-x { + + mux { + groups = "pdm_din1_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din1-z { + + mux { + groups = "pdm_din1_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din2-a { + + mux { + groups = "pdm_din2_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din2-c { + + mux { + groups = "pdm_din2_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din2-x { + + mux { + groups = "pdm_din2_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din2-z { + + mux { + groups = "pdm_din2_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din3-a { + + mux { + groups = "pdm_din3_a"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din3-c { + + mux { + groups = "pdm_din3_c"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din3-x { + + mux { + groups = "pdm_din3_x"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-din3-z { + + mux { + groups = "pdm_din3_z"; + function = "pdm"; + bias-disable; + }; + }; + + pdm-dclk-a { + + mux { + groups = "pdm_dclk_a"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <0x1f4>; + }; + }; + + pdm-dclk-c { + + mux { + groups = "pdm_dclk_c"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <0x1f4>; + }; + }; + + pdm-dclk-x { + + mux { + groups = "pdm_dclk_x"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <0x1f4>; + }; + }; + + pdm-dclk-z { + + mux { + groups = "pdm_dclk_z"; + function = "pdm"; + bias-disable; + drive-strength-microamp = <0x1f4>; + }; + }; + + pwm-a { + + mux { + groups = "pwm_a"; + function = "pwm_a"; + bias-disable; + }; + }; + + pwm-b-x7 { + + mux { + groups = "pwm_b_x7"; + function = "pwm_b"; + bias-disable; + }; + }; + + pwm-b-x19 { + + mux { + groups = "pwm_b_x19"; + function = "pwm_b"; + bias-disable; + }; + }; + + pwm-c-c { + + mux { + groups = "pwm_c_c"; + function = "pwm_c"; + bias-disable; + }; + }; + + pwm-c-x5 { + + mux { + groups = "pwm_c_x5"; + function = "pwm_c"; + bias-disable; + }; + }; + + pwm-c-x8 { + + mux { + groups = "pwm_c_x8"; + function = "pwm_c"; + bias-disable; + }; + }; + + pwm-d-x3 { + + mux { + groups = "pwm_d_x3"; + function = "pwm_d"; + bias-disable; + }; + }; + + pwm-d-x6 { + + mux { + groups = "pwm_d_x6"; + function = "pwm_d"; + bias-disable; + }; + }; + + pwm-e { + + mux { + groups = "pwm_e"; + function = "pwm_e"; + bias-disable; + }; + }; + + pwm-f-x { + + mux { + groups = "pwm_f_x"; + function = "pwm_f"; + bias-disable; + }; + }; + + pwm-f-h { + + mux { + groups = "pwm_f_h"; + function = "pwm_f"; + bias-disable; + }; + }; + + sdcard_c { + phandle = <0x29>; + + mux-0 { + groups = "sdcard_d0_c\0sdcard_d1_c\0sdcard_d2_c\0sdcard_d3_c\0sdcard_cmd_c"; + function = "sdcard"; + bias-pull-up; + drive-strength-microamp = <0xfa0>; + }; + + mux-1 { + groups = "sdcard_clk_c"; + function = "sdcard"; + bias-disable; + drive-strength-microamp = <0xfa0>; + }; + }; + + sdcard_clk_gate_c { + phandle = <0x2a>; + + mux { + groups = "GPIOC_4"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <0xfa0>; + }; + }; + + sdcard_z { + + mux-0 { + groups = "sdcard_d0_z\0sdcard_d1_z\0sdcard_d2_z\0sdcard_d3_z\0sdcard_cmd_z"; + function = "sdcard"; + bias-pull-up; + drive-strength-microamp = <0xfa0>; + }; + + mux-1 { + groups = "sdcard_clk_z"; + function = "sdcard"; + bias-disable; + drive-strength-microamp = <0xfa0>; + }; + }; + + sdcard_clk_gate_z { + + mux { + groups = "GPIOZ_6"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <0xfa0>; + }; + }; + + sdio { + + mux { + groups = "sdio_d0\0sdio_d1\0sdio_d2\0sdio_d3\0sdio_clk\0sdio_cmd"; + function = "sdio"; + bias-disable; + drive-strength-microamp = <0xfa0>; + }; + }; + + sdio_clk_gate { + + mux { + groups = "GPIOX_4"; + function = "gpio_periphs"; + bias-pull-down; + drive-strength-microamp = <0xfa0>; + }; + }; + + spdif-in-a10 { + + mux { + groups = "spdif_in_a10"; + function = "spdif_in"; + bias-disable; + }; + }; + + spdif-in-a12 { + + mux { + groups = "spdif_in_a12"; + function = "spdif_in"; + bias-disable; + }; + }; + + spdif-in-h { + + mux { + groups = "spdif_in_h"; + function = "spdif_in"; + bias-disable; + }; + }; + + spdif-out-h { + + mux { + groups = "spdif_out_h"; + function = "spdif_out"; + drive-strength-microamp = <0x1f4>; + bias-disable; + }; + }; + + spdif-out-a11 { + + mux { + groups = "spdif_out_a11"; + function = "spdif_out"; + drive-strength-microamp = <0x1f4>; + bias-disable; + }; + }; + + spdif-out-a13 { + + mux { + groups = "spdif_out_a13"; + function = "spdif_out"; + drive-strength-microamp = <0x1f4>; + bias-disable; + }; + }; + + spicc0-x { + + mux { + groups = "spi0_mosi_x\0spi0_miso_x\0spi0_clk_x"; + function = "spi0"; + drive-strength-microamp = <0xfa0>; + bias-disable; + }; + }; + + spicc0-ss0-x { + + mux { + groups = "spi0_ss0_x"; + function = "spi0"; + drive-strength-microamp = <0xfa0>; + bias-disable; + }; + }; + + spicc0-c { + + mux { + groups = "spi0_mosi_c\0spi0_miso_c\0spi0_ss0_c\0spi0_clk_c"; + function = "spi0"; + drive-strength-microamp = <0xfa0>; + bias-disable; + }; + }; + + spicc1 { + + mux { + groups = "spi1_mosi\0spi1_miso\0spi1_clk"; + function = "spi1"; + drive-strength-microamp = <0xfa0>; + }; + }; + + spicc1-ss0 { + + mux { + groups = "spi1_ss0"; + function = "spi1"; + drive-strength-microamp = <0xfa0>; + bias-disable; + }; + }; + + tdm-a-din0 { + + mux { + groups = "tdm_a_din0"; + function = "tdm_a"; + bias-disable; + }; + }; + + tdm-a-din1 { + + mux { + groups = "tdm_a_din1"; + function = "tdm_a"; + bias-disable; + }; + }; + + tdm-a-dout0 { + + mux { + groups = "tdm_a_dout0"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-a-dout1 { + + mux { + groups = "tdm_a_dout1"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-a-fs { + + mux { + groups = "tdm_a_fs"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-a-sclk { + + mux { + groups = "tdm_a_sclk"; + function = "tdm_a"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-a-slv-fs { + + mux { + groups = "tdm_a_slv_fs"; + function = "tdm_a"; + bias-disable; + }; + }; + + tdm-a-slv-sclk { + + mux { + groups = "tdm_a_slv_sclk"; + function = "tdm_a"; + bias-disable; + }; + }; + + tdm-b-din0 { + + mux { + groups = "tdm_b_din0"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm-b-din1 { + + mux { + groups = "tdm_b_din1"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm-b-din2 { + + mux { + groups = "tdm_b_din2"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm-b-din3-a { + + mux { + groups = "tdm_b_din3_a"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm-b-din3-h { + + mux { + groups = "tdm_b_din3_h"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm-b-dout0 { + + mux { + groups = "tdm_b_dout0"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-b-dout1 { + + mux { + groups = "tdm_b_dout1"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-b-dout2 { + + mux { + groups = "tdm_b_dout2"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-b-dout3-a { + + mux { + groups = "tdm_b_dout3_a"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-b-dout3-h { + + mux { + groups = "tdm_b_dout3_h"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-b-fs { + + mux { + groups = "tdm_b_fs"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-b-sclk { + + mux { + groups = "tdm_b_sclk"; + function = "tdm_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-b-slv-fs { + + mux { + groups = "tdm_b_slv_fs"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm-b-slv-sclk { + + mux { + groups = "tdm_b_slv_sclk"; + function = "tdm_b"; + bias-disable; + }; + }; + + tdm-c-din0-a { + + mux { + groups = "tdm_c_din0_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-din0-z { + + mux { + groups = "tdm_c_din0_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-din1-a { + + mux { + groups = "tdm_c_din1_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-din1-z { + + mux { + groups = "tdm_c_din1_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-din2-a { + + mux { + groups = "tdm_c_din2_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + eth-leds { + + mux { + groups = "eth_link_led\0eth_act_led"; + function = "eth"; + bias-disable; + }; + }; + + eth { + phandle = <0x11>; + + mux { + groups = "eth_mdio\0eth_mdc\0eth_rgmii_rx_clk\0eth_rx_dv\0eth_rxd0\0eth_rxd1\0eth_txen\0eth_txd0\0eth_txd1"; + function = "eth"; + drive-strength-microamp = <0xfa0>; + bias-disable; + }; + }; + + eth-rgmii { + phandle = <0x12>; + + mux { + groups = "eth_rxd2_rgmii\0eth_rxd3_rgmii\0eth_rgmii_tx_clk\0eth_txd2_rgmii\0eth_txd3_rgmii"; + function = "eth"; + drive-strength-microamp = <0xfa0>; + bias-disable; + }; + }; + + tdm-c-din2-z { + + mux { + groups = "tdm_c_din2_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-din3-a { + + mux { + groups = "tdm_c_din3_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-din3-z { + + mux { + groups = "tdm_c_din3_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-dout0-a { + + mux { + groups = "tdm_c_dout0_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-dout0-z { + + mux { + groups = "tdm_c_dout0_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-dout1-a { + + mux { + groups = "tdm_c_dout1_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-dout1-z { + + mux { + groups = "tdm_c_dout1_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-dout2-a { + + mux { + groups = "tdm_c_dout2_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-dout2-z { + + mux { + groups = "tdm_c_dout2_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-dout3-a { + + mux { + groups = "tdm_c_dout3_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-dout3-z { + + mux { + groups = "tdm_c_dout3_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-fs-a { + + mux { + groups = "tdm_c_fs_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-fs-z { + + mux { + groups = "tdm_c_fs_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-sclk-a { + + mux { + groups = "tdm_c_sclk_a"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-sclk-z { + + mux { + groups = "tdm_c_sclk_z"; + function = "tdm_c"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-c-slv-fs-a { + + mux { + groups = "tdm_c_slv_fs_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-slv-fs-z { + + mux { + groups = "tdm_c_slv_fs_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-slv-sclk-a { + + mux { + groups = "tdm_c_slv_sclk_a"; + function = "tdm_c"; + bias-disable; + }; + }; + + tdm-c-slv-sclk-z { + + mux { + groups = "tdm_c_slv_sclk_z"; + function = "tdm_c"; + bias-disable; + }; + }; + + uart-a { + + mux { + groups = "uart_a_tx\0uart_a_rx"; + function = "uart_a"; + bias-disable; + }; + }; + + uart-a-cts-rts { + + mux { + groups = "uart_a_cts\0uart_a_rts"; + function = "uart_a"; + bias-disable; + }; + }; + + uart-b { + + mux { + groups = "uart_b_tx\0uart_b_rx"; + function = "uart_b"; + bias-disable; + }; + }; + + uart-c { + + mux { + groups = "uart_c_tx\0uart_c_rx"; + function = "uart_c"; + bias-disable; + }; + }; + + uart-c-cts-rts { + + mux { + groups = "uart_c_cts\0uart_c_rts"; + function = "uart_c"; + bias-disable; + }; + }; + }; + }; + + temperature-sensor@34800 { + compatible = "amlogic,g12a-cpu-thermal\0amlogic,g12a-thermal"; + reg = <0x00 0x34800 0x00 0x50>; + interrupts = <0x00 0x23 0x01>; + clocks = <0x02 0xd4>; + #thermal-sensor-cells = <0x00>; + amlogic,ao-secure = <0x1a>; + phandle = <0x07>; + }; + + temperature-sensor@34c00 { + compatible = "amlogic,g12a-ddr-thermal\0amlogic,g12a-thermal"; + reg = <0x00 0x34c00 0x00 0x50>; + interrupts = <0x00 0x24 0x01>; + clocks = <0x02 0xd4>; + #thermal-sensor-cells = <0x00>; + amlogic,ao-secure = <0x1a>; + phandle = <0x0e>; + }; + + phy@36000 { + compatible = "amlogic,g12a-usb2-phy"; + reg = <0x00 0x36000 0x00 0x2000>; + clocks = <0x1b>; + clock-names = "xtal"; + resets = <0x05 0x30>; + reset-names = "phy"; + #phy-cells = <0x00>; + phy-supply = <0x16>; + phandle = <0x35>; + }; + + bus@38000 { + compatible = "simple-bus"; + reg = <0x00 0x38000 0x00 0x400>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0x38000 0x00 0x400>; + + video-lut@48 { + compatible = "amlogic,canvas"; + reg = <0x00 0x48 0x00 0x14>; + phandle = <0x27>; + }; + }; + + phy@3a000 { + compatible = "amlogic,g12a-usb2-phy"; + reg = <0x00 0x3a000 0x00 0x2000>; + clocks = <0x1b>; + clock-names = "xtal"; + resets = <0x05 0x31>; + reset-names = "phy"; + #phy-cells = <0x00>; + phy-supply = <0x1c>; + phandle = <0x36>; + }; + + bus@3c000 { + compatible = "simple-bus"; + reg = <0x00 0x3c000 0x00 0x1400>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0x3c000 0x00 0x1400>; + + system-controller@0 { + compatible = "amlogic,meson-gx-hhi-sysctrl\0simple-mfd\0syscon"; + reg = <0x00 0x00 0x00 0x400>; + + clock-controller { + compatible = "amlogic,sm1-clkc"; + #clock-cells = <0x01>; + clocks = <0x1b>; + clock-names = "xtal"; + phandle = <0x02>; + }; + + power-controller { + compatible = "amlogic,meson-sm1-pwrc"; + #power-domain-cells = <0x01>; + amlogic,ao-sysctrl = <0x1d>; + resets = <0x05 0x05 0x05 0x0a 0x05 0x0d 0x05 0x25 0x05 0x85 0x05 0x86 0x05 0x87 0x05 0x89 0x05 0x8c 0x05 0x8d 0x05 0xe7>; + reset-names = "viu\0venc\0vcbus\0bt656\0rdma\0venci\0vencp\0vdac\0vdi6\0vencl\0vid_lock"; + clocks = <0x02 0x74 0x02 0x7c>; + clock-names = "vpu\0vapb"; + assigned-clocks = <0x02 0x6e 0x02 0x70 0x02 0x74 0x02 0x75 0x02 0x77 0x02 0x7b>; + assigned-clock-parents = <0x02 0x03 0x00 0x02 0x70 0x02 0x04 0x00 0x02 0x77>; + assigned-clock-rates = <0x00 0x27bc86aa 0x00 0x00 0xee6b280 0x00>; + phandle = <0x03>; + }; + }; + }; + + phy@46000 { + compatible = "amlogic,g12a-usb3-pcie-phy"; + reg = <0x00 0x46000 0x00 0x2000>; + clocks = <0x02 0xc9>; + clock-names = "ref_clk"; + resets = <0x05 0x0e>; + reset-names = "phy"; + assigned-clocks = <0x02 0xc9>; + assigned-clock-rates = <0x5f5e100>; + #phy-cells = <0x01>; + phandle = <0x06>; + }; + + mdio-multiplexer@4c000 { + compatible = "amlogic,g12a-mdio-mux"; + reg = <0x00 0x4c000 0x00 0xa4>; + clocks = <0x02 0x13 0x1b 0x02 0xb1>; + clock-names = "pclk\0clkin0\0clkin1"; + mdio-parent-bus = <0x1e>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + mdio@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet-phy@0 { + reg = <0x00>; + max-speed = <0x3e8>; + interrupt-parent = <0x1f>; + interrupts = <0x1a 0x08>; + phandle = <0x13>; + }; + }; + + mdio@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + + ethernet_phy@8 { + compatible = "ethernet-phy-id0180.3301\0ethernet-phy-ieee802.3-c22"; + interrupts = <0x00 0x09 0x04>; + reg = <0x08>; + max-speed = <0x64>; + }; + }; + }; + + bus@60000 { + compatible = "simple-bus"; + reg = <0x00 0x60000 0x00 0x1000>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0x60000 0x00 0x1000>; + + clock-controller@0 { + status = "okay"; + compatible = "amlogic,sm1-audio-clkc"; + reg = <0x00 0x00 0x00 0xb4>; + #clock-cells = <0x01>; + #reset-cells = <0x01>; + clocks = <0x02 0x25 0x02 0x0b 0x02 0x0c 0x02 0x0d 0x02 0x0e 0x02 0x4a 0x02 0x03 0x02 0x04 0x02 0x05>; + clock-names = "pclk\0mst_in0\0mst_in1\0mst_in2\0mst_in3\0mst_in4\0mst_in5\0mst_in6\0mst_in7"; + resets = <0x05 0x41>; + phandle = <0x20>; + }; + + audio-controller@100 { + compatible = "amlogic,sm1-toddr\0amlogic,axg-toddr"; + reg = <0x00 0x100 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "TODDR_A"; + interrupts = <0x00 0x94 0x01>; + clocks = <0x20 0x29>; + resets = <0x21 0x00 0x20 0x06>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x2000>; + status = "disabled"; + }; + + audio-controller@140 { + compatible = "amlogic,sm1-toddr\0amlogic,axg-toddr"; + reg = <0x00 0x140 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "TODDR_B"; + interrupts = <0x00 0x95 0x01>; + clocks = <0x20 0x2a>; + resets = <0x21 0x01 0x20 0x07>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x100>; + status = "disabled"; + }; + + audio-controller@180 { + compatible = "amlogic,sm1-toddr\0amlogic,axg-toddr"; + reg = <0x00 0x180 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "TODDR_C"; + interrupts = <0x00 0x96 0x01>; + clocks = <0x20 0x2b>; + resets = <0x21 0x02 0x20 0x08>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x100>; + status = "disabled"; + }; + + audio-controller@1c0 { + compatible = "amlogic,sm1-frddr\0amlogic,axg-frddr"; + reg = <0x00 0x1c0 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "FRDDR_A"; + interrupts = <0x00 0x98 0x01>; + clocks = <0x20 0x26>; + resets = <0x21 0x03 0x20 0x09>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x200>; + status = "okay"; + phandle = <0x42>; + }; + + audio-controller@200 { + compatible = "amlogic,sm1-frddr\0amlogic,axg-frddr"; + reg = <0x00 0x200 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "FRDDR_B"; + interrupts = <0x00 0x99 0x01>; + clocks = <0x20 0x27>; + resets = <0x21 0x04 0x20 0x0a>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x100>; + status = "okay"; + phandle = <0x43>; + }; + + audio-controller@240 { + compatible = "amlogic,sm1-frddr\0amlogic,axg-frddr"; + reg = <0x00 0x240 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "FRDDR_C"; + interrupts = <0x00 0x9a 0x01>; + clocks = <0x20 0x28>; + resets = <0x21 0x05 0x20 0x0b>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x100>; + status = "okay"; + phandle = <0x44>; + }; + + reset-controller@280 { + status = "okay"; + compatible = "amlogic,meson-sm1-audio-arb"; + reg = <0x00 0x280 0x00 0x04>; + #reset-cells = <0x01>; + clocks = <0x20 0x1d>; + phandle = <0x21>; + }; + + audio-controller@300 { + compatible = "amlogic,sm1-tdmin\0amlogic,axg-tdmin"; + reg = <0x00 0x300 0x00 0x40>; + sound-name-prefix = "TDMIN_A"; + resets = <0x20 0x01>; + clocks = <0x20 0x1f 0x20 0x7b 0x20 0x74 0x20 0x82 0x20 0x82>; + clock-names = "pclk\0sclk\0sclk_sel\0lrclk\0lrclk_sel"; + status = "disabled"; + }; + + audio-controller@340 { + compatible = "amlogic,sm1-tdmin\0amlogic,axg-tdmin"; + reg = <0x00 0x340 0x00 0x40>; + sound-name-prefix = "TDMIN_B"; + resets = <0x20 0x02>; + clocks = <0x20 0x20 0x20 0x7c 0x20 0x75 0x20 0x83 0x20 0x83>; + clock-names = "pclk\0sclk\0sclk_sel\0lrclk\0lrclk_sel"; + status = "disabled"; + }; + + audio-controller@380 { + compatible = "amlogic,sm1-tdmin\0amlogic,axg-tdmin"; + reg = <0x00 0x380 0x00 0x40>; + sound-name-prefix = "TDMIN_C"; + resets = <0x20 0x03>; + clocks = <0x20 0x21 0x20 0x7d 0x20 0x76 0x20 0x84 0x20 0x84>; + clock-names = "pclk\0sclk\0sclk_sel\0lrclk\0lrclk_sel"; + status = "disabled"; + }; + + audio-controller@3c0 { + compatible = "amlogic,sm1-tdmin\0amlogic,axg-tdmin"; + reg = <0x00 0x3c0 0x00 0x40>; + sound-name-prefix = "TDMIN_LB"; + resets = <0x20 0x04>; + clocks = <0x20 0x22 0x20 0x7e 0x20 0x77 0x20 0x85 0x20 0x85>; + clock-names = "pclk\0sclk\0sclk_sel\0lrclk\0lrclk_sel"; + status = "disabled"; + }; + + audio-controller@500 { + compatible = "amlogic,sm1-tdmout"; + reg = <0x00 0x500 0x00 0x40>; + sound-name-prefix = "TDMOUT_A"; + resets = <0x20 0x0c>; + clocks = <0x20 0x23 0x20 0x7f 0x20 0x78 0x20 0x86 0x20 0x86>; + clock-names = "pclk\0sclk\0sclk_sel\0lrclk\0lrclk_sel"; + status = "disabled"; + }; + + audio-controller@540 { + compatible = "amlogic,sm1-tdmout"; + reg = <0x00 0x540 0x00 0x40>; + sound-name-prefix = "TDMOUT_B"; + resets = <0x20 0x0d>; + clocks = <0x20 0x24 0x20 0x80 0x20 0x79 0x20 0x87 0x20 0x87>; + clock-names = "pclk\0sclk\0sclk_sel\0lrclk\0lrclk_sel"; + status = "okay"; + phandle = <0x41>; + }; + + audio-controller@580 { + compatible = "amlogic,sm1-tdmout"; + reg = <0x00 0x580 0x00 0x40>; + sound-name-prefix = "TDMOUT_C"; + resets = <0x20 0x0e>; + clocks = <0x20 0x25 0x20 0x81 0x20 0x7a 0x20 0x88 0x20 0x88>; + clock-names = "pclk\0sclk\0sclk_sel\0lrclk\0lrclk_sel"; + status = "disabled"; + }; + + audio-controller@744 { + compatible = "amlogic,sm1-tohdmitx\0amlogic,g12a-tohdmitx"; + reg = <0x00 0x744 0x00 0x04>; + #sound-dai-cells = <0x01>; + sound-name-prefix = "TOHDMITX"; + resets = <0x20 0x18>; + status = "okay"; + phandle = <0x46>; + }; + + audio-controller@840 { + compatible = "amlogic,sm1-toddr\0amlogic,axg-toddr"; + reg = <0x00 0x840 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "TODDR_D"; + interrupts = <0x00 0x31 0x01>; + clocks = <0x20 0xab>; + resets = <0x21 0x06 0x20 0x21>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x100>; + status = "disabled"; + }; + + audio-controller@880 { + compatible = "amlogic,sm1-frddr\0amlogic,axg-frddr"; + reg = <0x00 0x880 0x00 0x2c>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "FRDDR_D"; + interrupts = <0x00 0x32 0x01>; + clocks = <0x20 0xaa>; + resets = <0x21 0x07 0x20 0x20>; + reset-names = "arb\0rst"; + amlogic,fifo-depth = <0x100>; + status = "disabled"; + }; + }; + + audio-controller@61000 { + compatible = "amlogic,sm1-pdm\0amlogic,axg-pdm"; + reg = <0x00 0x61000 0x00 0x34>; + #sound-dai-cells = <0x00>; + sound-name-prefix = "PDM"; + clocks = <0x20 0x1e 0x20 0x39 0x20 0x3a>; + clock-names = "pclk\0dclk\0sysclk"; + resets = <0x20 0x00>; + status = "disabled"; + }; + }; + + bus@ff800000 { + compatible = "simple-bus"; + reg = <0x00 0xff800000 0x00 0x100000>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0xff800000 0x00 0x100000>; + + sys-ctrl@0 { + compatible = "amlogic,meson-gx-ao-sysctrl\0simple-mfd\0syscon"; + reg = <0x00 0x00 0x00 0x100>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0x00 0x00 0x100>; + phandle = <0x1d>; + + clock-controller { + compatible = "amlogic,meson-g12a-aoclkc"; + #clock-cells = <0x01>; + #reset-cells = <0x01>; + clocks = <0x1b 0x02 0x0a>; + clock-names = "xtal\0mpeg-clk"; + phandle = <0x23>; + }; + + pinctrl@14 { + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + phandle = <0x22>; + + bank@14 { + reg = <0x00 0x14 0x00 0x08 0x00 0x1c 0x00 0x08 0x00 0x24 0x00 0x14>; + reg-names = "mux\0ds\0gpio"; + gpio-controller; + #gpio-cells = <0x02>; + gpio-ranges = <0x22 0x00 0x00 0x0f>; + gpio-line-names = "\0\0\0\0PIN_47\0\0\0PIN_45\0PIN_46\0PIN_44\0PIN_42\0\0\0\0"; + phandle = <0x3c>; + }; + + i2c_ao_sck_pins { + + mux { + groups = "i2c_ao_sck"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c_ao_sda { + + mux { + groups = "i2c_ao_sda"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c_ao_sck_e { + + mux { + groups = "i2c_ao_sck_e"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + i2c_ao_sda_e { + + mux { + groups = "i2c_ao_sda_e"; + function = "i2c_ao"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + mclk0-ao { + + mux { + groups = "mclk0_ao"; + function = "mclk0_ao"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-ao-b-din0 { + + mux { + groups = "tdm_ao_b_din0"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + spdif-ao-out { + + mux { + groups = "spdif_ao_out"; + function = "spdif_ao_out"; + drive-strength-microamp = <0x1f4>; + bias-disable; + }; + }; + + tdm-ao-b-din1 { + + mux { + groups = "tdm_ao_b_din1"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + tdm-ao-b-din2 { + + mux { + groups = "tdm_ao_b_din2"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + tdm-ao-b-dout0 { + + mux { + groups = "tdm_ao_b_dout0"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-ao-b-dout1 { + + mux { + groups = "tdm_ao_b_dout1"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-ao-b-dout2 { + + mux { + groups = "tdm_ao_b_dout2"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-ao-b-fs { + + mux { + groups = "tdm_ao_b_fs"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-ao-b-sclk { + + mux { + groups = "tdm_ao_b_sclk"; + function = "tdm_ao_b"; + bias-disable; + drive-strength-microamp = <0xbb8>; + }; + }; + + tdm-ao-b-slv-fs { + + mux { + groups = "tdm_ao_b_slv_fs"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + tdm-ao-b-slv-sclk { + + mux { + groups = "tdm_ao_b_slv_sclk"; + function = "tdm_ao_b"; + bias-disable; + }; + }; + + uart-a-ao { + phandle = <0x25>; + + mux { + groups = "uart_ao_a_tx\0uart_ao_a_rx"; + function = "uart_ao_a"; + bias-disable; + }; + }; + + uart-ao-a-cts-rts { + + mux { + groups = "uart_ao_a_cts\0uart_ao_a_rts"; + function = "uart_ao_a"; + bias-disable; + }; + }; + + pwm-a-e { + + mux { + groups = "pwm_a_e"; + function = "pwm_a_e"; + bias-disable; + }; + }; + + pwm-ao-a { + + mux { + groups = "pwm_ao_a"; + function = "pwm_ao_a"; + bias-disable; + }; + }; + + pwm-ao-b { + + mux { + groups = "pwm_ao_b"; + function = "pwm_ao_b"; + bias-disable; + }; + }; + + pwm-ao-c-4 { + + mux { + groups = "pwm_ao_c_4"; + function = "pwm_ao_c"; + bias-disable; + }; + }; + + pwm-ao-c-6 { + + mux { + groups = "pwm_ao_c_6"; + function = "pwm_ao_c"; + bias-disable; + }; + }; + + pwm-ao-d-5 { + + mux { + groups = "pwm_ao_d_5"; + function = "pwm_ao_d"; + bias-disable; + }; + }; + + pwm-ao-d-10 { + + mux { + groups = "pwm_ao_d_10"; + function = "pwm_ao_d"; + bias-disable; + }; + }; + + pwm-ao-d-e { + phandle = <0x24>; + + mux { + groups = "pwm_ao_d_e"; + function = "pwm_ao_d"; + }; + }; + + remote-input-ao { + phandle = <0x26>; + + mux { + groups = "remote_ao_input"; + function = "remote_ao_input"; + bias-disable; + }; + }; + }; + }; + + rtc@a8 { + compatible = "amlogic,meson-vrtc"; + reg = <0x00 0xa8 0x00 0x04>; + }; + + cec@100 { + compatible = "amlogic,meson-gx-ao-cec"; + reg = <0x00 0x100 0x00 0x14>; + interrupts = <0x00 0xc7 0x01>; + clocks = <0x23 0x1b>; + clock-names = "core"; + status = "disabled"; + }; + + ao-secure@140 { + compatible = "amlogic,meson-gx-ao-secure\0syscon"; + reg = <0x00 0x140 0x00 0x140>; + amlogic,has-chip-id; + phandle = <0x1a>; + }; + + cec@280 { + compatible = "amlogic,meson-sm1-ao-cec"; + reg = <0x00 0x280 0x00 0x1c>; + interrupts = <0x00 0xcb 0x01>; + clocks = <0x23 0x13>; + clock-names = "oscin"; + status = "disabled"; + }; + + pwm@2000 { + compatible = "amlogic,meson-g12a-ao-pwm-cd"; + reg = <0x00 0x2000 0x00 0x20>; + #pwm-cells = <0x03>; + status = "okay"; + pinctrl-0 = <0x24>; + pinctrl-names = "default"; + clocks = <0x1b>; + clock-names = "clkin1"; + phandle = <0x3f>; + }; + + serial@3000 { + compatible = "amlogic,meson-gx-uart\0amlogic,meson-ao-uart"; + reg = <0x00 0x3000 0x00 0x18>; + interrupts = <0x00 0xc1 0x01>; + clocks = <0x1b 0x23 0x04 0x1b>; + clock-names = "xtal\0pclk\0baud"; + status = "okay"; + pinctrl-0 = <0x25>; + pinctrl-names = "default"; + }; + + serial@4000 { + compatible = "amlogic,meson-gx-uart\0amlogic,meson-ao-uart"; + reg = <0x00 0x4000 0x00 0x18>; + interrupts = <0x00 0xc5 0x01>; + clocks = <0x1b 0x23 0x06 0x1b>; + clock-names = "xtal\0pclk\0baud"; + status = "disabled"; + }; + + i2c@5000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x00 0x5000 0x00 0x20>; + interrupts = <0x00 0xc3 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x02 0x18>; + }; + + pwm@7000 { + compatible = "amlogic,meson-g12a-ao-pwm-ab"; + reg = <0x00 0x7000 0x00 0x20>; + #pwm-cells = <0x03>; + status = "disabled"; + }; + + ir@8000 { + compatible = "amlogic,meson-gxbb-ir"; + reg = <0x00 0x8000 0x00 0x20>; + interrupts = <0x00 0xc4 0x01>; + status = "okay"; + pinctrl-0 = <0x26>; + pinctrl-names = "default"; + linux,rc-map-name = "rc-odroid"; + }; + + adc@9000 { + compatible = "amlogic,meson-g12a-saradc\0amlogic,meson-saradc"; + reg = <0x00 0x9000 0x00 0x48>; + #io-channel-cells = <0x01>; + interrupts = <0x00 0xc8 0x01>; + clocks = <0x1b 0x23 0x08 0x23 0x12 0x23 0x10>; + clock-names = "clkin\0core\0adc_clk\0adc_sel"; + status = "okay"; + }; + }; + + video-decoder@ff620000 { + compatible = "amlogic,sm1-vdec"; + reg = <0x00 0xff620000 0x00 0x10000 0x00 0xffd0e180 0x00 0xe4>; + reg-names = "dos\0esparser"; + interrupts = <0x00 0x2c 0x01 0x00 0x20 0x01>; + interrupt-names = "vdec\0esparser"; + amlogic,ao-sysctrl = <0x1d>; + amlogic,canvas = <0x27>; + clocks = <0x02 0x2e 0x02 0x10 0x02 0xcc 0x02 0xcf 0x02 0xd2>; + clock-names = "dos_parser\0dos\0vdec_1\0vdec_hevc\0vdec_hevcf"; + resets = <0x05 0x28>; + reset-names = "esparser"; + }; + + vpu@ff900000 { + compatible = "amlogic,meson-g12a-vpu"; + reg = <0x00 0xff900000 0x00 0x100000 0x00 0xff63c000 0x00 0x1000>; + reg-names = "vpu\0hhi"; + interrupts = <0x00 0x03 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + amlogic,canvas = <0x27>; + power-domains = <0x03 0x00>; + + port@0 { + reg = <0x00>; + }; + + port@1 { + reg = <0x01>; + + endpoint { + remote-endpoint = <0x28>; + phandle = <0x17>; + }; + }; + }; + + interrupt-controller@ffc01000 { + compatible = "arm,gic-400"; + reg = <0x00 0xffc01000 0x00 0x1000 0x00 0xffc02000 0x00 0x2000 0x00 0xffc04000 0x00 0x2000 0x00 0xffc06000 0x00 0x2000>; + interrupt-controller; + interrupts = <0x01 0x09 0xff04>; + #interrupt-cells = <0x03>; + #address-cells = <0x00>; + phandle = <0x01>; + }; + + bus@ffd00000 { + compatible = "simple-bus"; + reg = <0x00 0xffd00000 0x00 0x100000>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x00 0x00 0xffd00000 0x00 0x100000>; + + reset-controller@1004 { + compatible = "amlogic,meson-axg-reset"; + reg = <0x00 0x1004 0x00 0x9c>; + #reset-cells = <0x01>; + phandle = <0x05>; + }; + + interrupt-controller@f080 { + compatible = "amlogic,meson-sm1-gpio-intc\0amlogic,meson-gpio-intc"; + reg = <0x00 0xf080 0x00 0x10>; + interrupt-controller; + #interrupt-cells = <0x02>; + amlogic,channel-interrupts = <0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47>; + phandle = <0x1f>; + }; + + watchdog@f0d0 { + compatible = "amlogic,meson-gxbb-wdt"; + reg = <0x00 0xf0d0 0x00 0x10>; + clocks = <0x1b>; + }; + + spi@13000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x00 0x13000 0x00 0x44>; + interrupts = <0x00 0x51 0x04>; + clocks = <0x02 0x17 0x02 0x102>; + clock-names = "core\0pclk"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@15000 { + compatible = "amlogic,meson-g12a-spicc"; + reg = <0x00 0x15000 0x00 0x44>; + interrupts = <0x00 0x5a 0x04>; + clocks = <0x02 0x1d 0x02 0x105>; + clock-names = "core\0pclk"; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@14000 { + compatible = "amlogic,meson-gxbb-spifc"; + status = "disabled"; + reg = <0x00 0x14000 0x00 0x80>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x02 0x0a>; + }; + + pwm@19000 { + compatible = "amlogic,meson-g12a-ee-pwm"; + reg = <0x00 0x19000 0x00 0x20>; + #pwm-cells = <0x03>; + status = "disabled"; + }; + + pwm@1a000 { + compatible = "amlogic,meson-g12a-ee-pwm"; + reg = <0x00 0x1a000 0x00 0x20>; + #pwm-cells = <0x03>; + status = "disabled"; + }; + + pwm@1b000 { + compatible = "amlogic,meson-g12a-ee-pwm"; + reg = <0x00 0x1b000 0x00 0x20>; + #pwm-cells = <0x03>; + status = "disabled"; + }; + + i2c@1c000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x00 0x1c000 0x00 0x20>; + interrupts = <0x00 0x27 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x02 0x18>; + }; + + i2c@1d000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x00 0x1d000 0x00 0x20>; + interrupts = <0x00 0xd7 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x02 0x18>; + }; + + i2c@1e000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x00 0x1e000 0x00 0x20>; + interrupts = <0x00 0xd6 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x02 0x18>; + }; + + i2c@1f000 { + compatible = "amlogic,meson-axg-i2c"; + status = "disabled"; + reg = <0x00 0x1f000 0x00 0x20>; + interrupts = <0x00 0x15 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x02 0x18>; + }; + + clock-measure@18000 { + compatible = "amlogic,meson-sm1-clk-measure"; + reg = <0x00 0x18000 0x00 0x10>; + }; + + serial@22000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x00 0x22000 0x00 0x18>; + interrupts = <0x00 0x5d 0x01>; + clocks = <0x1b 0x02 0x39 0x1b>; + clock-names = "xtal\0pclk\0baud"; + status = "disabled"; + }; + + serial@23000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x00 0x23000 0x00 0x18>; + interrupts = <0x00 0x4b 0x01>; + clocks = <0x1b 0x02 0x2a 0x1b>; + clock-names = "xtal\0pclk\0baud"; + status = "disabled"; + }; + + serial@24000 { + compatible = "amlogic,meson-gx-uart"; + reg = <0x00 0x24000 0x00 0x18>; + interrupts = <0x00 0x1a 0x01>; + clocks = <0x1b 0x02 0x1c 0x1b>; + clock-names = "xtal\0pclk\0baud"; + status = "disabled"; + }; + }; + + sd@ffe03000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x00 0xffe03000 0x00 0x800>; + interrupts = <0x00 0xbd 0x01>; + status = "disabled"; + clocks = <0x02 0x21 0x02 0x3c 0x02 0x02>; + clock-names = "core\0clkin0\0clkin1"; + resets = <0x05 0x2c>; + }; + + sd@ffe05000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x00 0xffe05000 0x00 0x800>; + interrupts = <0x00 0xbe 0x01>; + status = "okay"; + clocks = <0x02 0x22 0x02 0x3d 0x02 0x02>; + clock-names = "core\0clkin0\0clkin1"; + resets = <0x05 0x2d>; + pinctrl-0 = <0x29>; + pinctrl-1 = <0x2a>; + pinctrl-names = "default\0clk-gate"; + bus-width = <0x04>; + cap-sd-highspeed; + max-frequency = <0xbebc200>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; + disable-wp; + cd-gpios = <0x2b 0x2f 0x01>; + vmmc-supply = <0x2c>; + vqmmc-supply = <0x2d>; + }; + + mmc@ffe07000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x00 0xffe07000 0x00 0x800>; + interrupts = <0x00 0xbf 0x01>; + status = "okay"; + clocks = <0x02 0x23 0x02 0x3e 0x02 0x02>; + clock-names = "core\0clkin0\0clkin1"; + resets = <0x05 0x2e>; + pinctrl-0 = <0x2e 0x2f 0x30>; + pinctrl-1 = <0x31>; + pinctrl-names = "default\0clk-gate"; + bus-width = <0x08>; + cap-mmc-highspeed; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + max-frequency = <0xbebc200>; + disable-wp; + mmc-pwrseq = <0x32>; + vmmc-supply = <0x33>; + vqmmc-supply = <0x34>; + }; + + usb@ffe09000 { + status = "okay"; + compatible = "amlogic,meson-g12a-usb-ctrl"; + reg = <0x00 0xffe09000 0x00 0xa0>; + interrupts = <0x00 0x10 0x04>; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges; + clocks = <0x02 0x2f>; + resets = <0x05 0x22>; + dr_mode = "otg"; + phys = <0x35 0x36 0x06 0x04>; + phy-names = "usb2-phy0\0usb2-phy1\0usb3-phy0"; + power-domains = <0x03 0x02>; + vbus-supply = <0x37>; + + usb@ff400000 { + compatible = "amlogic,meson-g12a-usb\0snps,dwc2"; + reg = <0x00 0xff400000 0x00 0x40000>; + interrupts = <0x00 0x1f 0x04>; + clocks = <0x02 0x37>; + clock-names = "otg"; + phys = <0x36>; + phy-names = "usb2-phy"; + dr_mode = "peripheral"; + g-rx-fifo-size = <0xc0>; + g-np-tx-fifo-size = <0x80>; + g-tx-fifo-size = <0x80 0x80 0x10 0x10 0x10>; + }; + + usb@ff500000 { + compatible = "snps,dwc3"; + reg = <0x00 0xff500000 0x00 0x100000>; + interrupts = <0x00 0x1e 0x04>; + dr_mode = "host"; + snps,dis_u2_susphy_quirk; + snps,quirk-frame-length-adjustment = <0x20>; + snps,parkmode-disable-ss-quirk; + }; + }; + + gpu@ffe40000 { + compatible = "amlogic,meson-g12a-mali\0arm,mali-bifrost"; + reg = <0x00 0xffe40000 0x00 0x40000>; + interrupt-parent = <0x01>; + interrupts = <0x00 0xa2 0x04 0x00 0xa1 0x04 0x00 0xa0 0x04>; + interrupt-names = "job\0mmu\0gpu"; + clocks = <0x02 0xaf>; + resets = <0x05 0x14 0x05 0x4e>; + operating-points-v2 = <0x38>; + #cooling-cells = <0x02>; + phandle = <0x10>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <0x01 0x0d 0xff08 0x01 0x0e 0xff08 0x01 0x0b 0xff08 0x01 0x0a 0xff08>; + arm,no-tick-in-suspend; + }; + + xtal-clk { + compatible = "fixed-clock"; + clock-frequency = <0x16e3600>; + clock-output-names = "xtal"; + #clock-cells = <0x00>; + phandle = <0x1b>; + }; + + audio-controller-0 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0x00>; + sound-name-prefix = "TDM_A"; + clocks = <0x20 0x31 0x20 0x4f 0x20 0x56>; + clock-names = "mclk\0sclk\0lrclk"; + status = "disabled"; + }; + + audio-controller-1 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0x00>; + sound-name-prefix = "TDM_B"; + clocks = <0x20 0x32 0x20 0x50 0x20 0x57>; + clock-names = "mclk\0sclk\0lrclk"; + status = "okay"; + phandle = <0x45>; + }; + + audio-controller-2 { + compatible = "amlogic,axg-tdm-iface"; + #sound-dai-cells = <0x00>; + sound-name-prefix = "TDM_C"; + clocks = <0x20 0x33 0x20 0x51 0x20 0x58>; + clock-names = "mclk\0sclk\0lrclk"; + status = "disabled"; + }; + + cpus { + #address-cells = <0x02>; + #size-cells = <0x00>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x00 0x00>; + enable-method = "psci"; + next-level-cache = <0x39>; + #cooling-cells = <0x02>; + cpu-supply = <0x3a>; + operating-points-v2 = <0x3b>; + clocks = <0x02 0xbb>; + clock-latency = <0xc350>; + phandle = <0x09>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x00 0x01>; + enable-method = "psci"; + next-level-cache = <0x39>; + #cooling-cells = <0x02>; + cpu-supply = <0x3a>; + operating-points-v2 = <0x3b>; + clocks = <0x02 0xfd>; + clock-latency = <0xc350>; + phandle = <0x0a>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x00 0x02>; + enable-method = "psci"; + next-level-cache = <0x39>; + #cooling-cells = <0x02>; + cpu-supply = <0x3a>; + operating-points-v2 = <0x3b>; + clocks = <0x02 0xfe>; + clock-latency = <0xc350>; + phandle = <0x0b>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x00 0x03>; + enable-method = "psci"; + next-level-cache = <0x39>; + #cooling-cells = <0x02>; + cpu-supply = <0x3a>; + operating-points-v2 = <0x3b>; + clocks = <0x02 0xff>; + clock-latency = <0xc350>; + phandle = <0x0c>; + }; + + l2-cache0 { + compatible = "cache"; + phandle = <0x39>; + }; + }; + + opp-table { + compatible = "operating-points-v2"; + opp-shared; + phandle = <0x3b>; + + opp-100000000 { + opp-hz = <0x00 0x5f5e100>; + opp-microvolt = <0xb2390>; + }; + + opp-250000000 { + opp-hz = <0x00 0xee6b280>; + opp-microvolt = <0xb2390>; + }; + + opp-500000000 { + opp-hz = <0x00 0x1dcd6500>; + opp-microvolt = <0xb2390>; + }; + + opp-667000000 { + opp-hz = <0x00 0x27bc86aa>; + opp-microvolt = <0xb71b0>; + }; + + opp-1000000000 { + opp-hz = <0x00 0x3b9aca00>; + opp-microvolt = <0xbbfd0>; + }; + + opp-1200000000 { + opp-hz = <0x00 0x47868c00>; + opp-microvolt = <0xbe6e0>; + }; + + opp-1404000000 { + opp-hz = <0x00 0x53af5700>; + opp-microvolt = <0xc0df0>; + }; + + opp-1500000000 { + opp-hz = <0x00 0x59682f00>; + opp-microvolt = <0xc3500>; + }; + + opp-1608000000 { + opp-hz = <0x00 0x5fd82200>; + opp-microvolt = <0xc5c10>; + }; + + opp-1704000000 { + opp-hz = <0x00 0x6590fa00>; + opp-microvolt = <0xcf850>; + }; + + opp-1800000000 { + opp-hz = <0x00 0x6b49d200>; + opp-microvolt = <0xdbba0>; + }; + + opp-1908000000 { + opp-hz = <0x00 0x71b9c500>; + opp-microvolt = <0xe7ef0>; + }; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00 0x00 0xf5800000>; + }; + + emmc-pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <0x2b 0x25 0x01>; + phandle = <0x32>; + }; + + regulator-tflash_vdd { + compatible = "regulator-fixed"; + regulator-name = "TFLASH_VDD"; + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + gpio = <0x3c 0x03 0x06>; + enable-active-high; + regulator-always-on; + phandle = <0x2c>; + }; + + gpio-regulator-tf_io { + compatible = "regulator-gpio"; + regulator-name = "TF_IO"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x325aa0>; + gpios = <0x3c 0x06 0x00>; + gpios-states = <0x00>; + states = <0x325aa0 0x00 0x1b7740 0x01>; + phandle = <0x2d>; + }; + + regulator-flash_1v8 { + compatible = "regulator-fixed"; + regulator-name = "FLASH_1V8"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + vin-supply = <0x33>; + regulator-always-on; + phandle = <0x34>; + }; + + regulator-main_12v { + compatible = "regulator-fixed"; + regulator-name = "12V"; + regulator-min-microvolt = <0xb71b00>; + regulator-max-microvolt = <0xb71b00>; + regulator-always-on; + phandle = <0x3d>; + }; + + regulator-vcc_5v { + compatible = "regulator-fixed"; + regulator-name = "5V"; + regulator-min-microvolt = <0x4c4b40>; + regulator-max-microvolt = <0x4c4b40>; + regulator-always-on; + vin-supply = <0x3d>; + phandle = <0x16>; + }; + + regulator-vcc_1v8 { + compatible = "regulator-fixed"; + regulator-name = "VCC_1V8"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + vin-supply = <0x33>; + regulator-always-on; + }; + + regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + vin-supply = <0x3e>; + regulator-always-on; + phandle = <0x33>; + }; + + regulator-vddcpu { + compatible = "pwm-regulator"; + regulator-name = "VDDCPU"; + regulator-min-microvolt = <0xb0068>; + regulator-max-microvolt = <0xf9830>; + vin-supply = <0x3d>; + pwms = <0x3f 0x01 0x4e2 0x00>; + pwm-dutycycle-range = <0x64 0x00>; + regulator-boot-on; + regulator-always-on; + phandle = <0x3a>; + }; + + regulator-usb_pwr_en { + compatible = "regulator-fixed"; + regulator-name = "USB_PWR_EN"; + regulator-min-microvolt = <0x4c4b40>; + regulator-max-microvolt = <0x4c4b40>; + vin-supply = <0x16>; + gpio = <0x3c 0x02 0x00>; + enable-active-high; + phandle = <0x37>; + }; + + regulator-vddao_1v8 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_1V8"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + vin-supply = <0x3e>; + regulator-always-on; + }; + + regulator-vddao_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VDDAO_3V3"; + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + vin-supply = <0x3d>; + regulator-always-on; + phandle = <0x3e>; + }; + + hdmi-connector { + compatible = "hdmi-connector"; + type = [61 00]; + + port { + + endpoint { + remote-endpoint = <0x40>; + phandle = <0x18>; + }; + }; + }; + + sound { + compatible = "amlogic,axg-sound-card"; + audio-aux-devs = <0x41>; + audio-routing = "TDMOUT_B IN 0\0FRDDR_A OUT 1\0TDMOUT_B IN 1\0FRDDR_B OUT 1\0TDMOUT_B IN 2\0FRDDR_C OUT 1\0TDM_B Playback\0TDMOUT_B OUT"; + assigned-clocks = <0x02 0x0d 0x02 0x0b 0x02 0x0c>; + assigned-clock-parents = <0x00 0x00 0x00>; + assigned-clock-rates = <0x11940000 0x10266000 0x17700000>; + status = "okay"; + model = "ODROID-C4"; + + dai-link-0 { + sound-dai = <0x42>; + }; + + dai-link-1 { + sound-dai = <0x43>; + }; + + dai-link-2 { + sound-dai = <0x44>; + }; + + dai-link-3 { + sound-dai = <0x45>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-0 = <0x01 0x01>; + dai-tdm-slot-tx-mask-1 = <0x01 0x01>; + dai-tdm-slot-tx-mask-2 = <0x01 0x01>; + dai-tdm-slot-tx-mask-3 = <0x01 0x01>; + mclk-fs = <0x100>; + + codec { + sound-dai = <0x46 0x01>; + }; + }; + + dai-link-4 { + sound-dai = <0x46 0x03>; + + codec { + sound-dai = <0x47>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-blue { + color = <0x03>; + function = "status"; + gpios = <0x3c 0x0b 0x00>; + linux,default-trigger = "heartbeat"; + panic-indicator; + }; + }; + + regulator-hub_5v { + compatible = "regulator-fixed"; + regulator-name = "HUB_5V"; + regulator-min-microvolt = <0x4c4b40>; + regulator-max-microvolt = <0x4c4b40>; + vin-supply = <0x16>; + gpio = <0x2b 0x14 0x00>; + enable-active-high; + phandle = <0x1c>; + }; +}; diff --git a/include/sddf/clk/client.h b/include/sddf/clk/client.h new file mode 100644 index 000000000..ec1e22847 --- /dev/null +++ b/include/sddf/clk/client.h @@ -0,0 +1,116 @@ +/* + * Copyright 2024, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +/** + * Send a clock enabling request via PPC into the passive clock driver. + * Use the label to indicate this request. + * @param channel of clock driver. + * @param identifier of target clock. + */ +static inline int sddf_clk_enable(microkit_channel channel, uint32_t clk_id) +{ + microkit_msginfo msginfo = microkit_msginfo_new(SDDF_CLK_ENABLE, 1); + microkit_mr_set(SDDF_CLK_PARAM_ID, clk_id); + + msginfo = microkit_ppcall(channel, msginfo); + + return (int)microkit_msginfo_get_label(msginfo); +} + +/** + * Send a clock disabling request via PPC into the passive clock driver. + * Use the label to indicate this request. + * @param channel of clock driver. + * @param identifier of target clock. + */ +static inline int sddf_clk_disable(microkit_channel channel, uint32_t clk_id) +{ + microkit_msginfo msginfo = microkit_msginfo_new(SDDF_CLK_DISABLE, 1); + microkit_mr_set(SDDF_CLK_PARAM_ID, clk_id); + + msginfo = microkit_ppcall(channel, msginfo); + + return (int)microkit_msginfo_get_label(msginfo); +} + +/** + * Send a clock get_rate request via PPC into the passive clock driver. + * Use the label to indicate this request. + * @param channel of clock driver. + * @param identifier of target clock. + * @param pointer to result variable. + */ +static inline int sddf_clk_get_rate(microkit_channel channel, uint32_t clk_id, uint64_t *rate) +{ + microkit_msginfo msginfo = microkit_msginfo_new(SDDF_CLK_GET_RATE, 1); + microkit_mr_set(SDDF_CLK_PARAM_ID, clk_id); + + msginfo = microkit_ppcall(channel, msginfo); + + *rate = microkit_mr_get(0); + return (int)microkit_msginfo_get_label(msginfo); +} + +/** + * Send a clock set_rate request via PPC into the passive clock driver. + * Use the label to indicate this request. + * @param channel of clock driver. + * @param identifier of target clock. + * @param target clock frequency. + * @param pointer to result variable. + */ +static inline int sddf_clk_set_rate(microkit_channel channel, uint32_t clk_id, uint64_t req_rate, uint64_t *rate) +{ + microkit_msginfo msginfo = microkit_msginfo_new(SDDF_CLK_SET_RATE, 2); + microkit_mr_set(SDDF_CLK_PARAM_ID, clk_id); + microkit_mr_set(SDDF_CLK_PARAM_RATE, req_rate); + + msginfo = microkit_ppcall(channel, msginfo); + + *rate = microkit_mr_get(0); + return (int)microkit_msginfo_get_label(msginfo); +} + +/** + * Send a clock get_parent request via PPC into the passive clock driver. + * Use the label to indicate this request. + * @param channel of clock driver. + * @param pointer to result (i.e. pclk_id) + */ +static inline int sddf_clk_get_parent(microkit_channel channel, uint32_t clk_id, uint32_t *pclk_id) +{ + microkit_msginfo msginfo = microkit_msginfo_new(SDDF_CLK_GET_PARENT, 1); + microkit_mr_set(SDDF_CLK_PARAM_ID, clk_id); + + msginfo = microkit_ppcall(channel, msginfo); + + *pclk_id = microkit_mr_get(0); + return (int)microkit_msginfo_get_label(msginfo); +} + +/** + * Send a clock set_parent request via PPC into the passive clock driver. + * Use the label to indicate this request. + * @param channel of clock driver. + * @param identifier of target clock. + * @param indice of target clock. + */ +static inline int sddf_clk_set_parent(microkit_channel channel, uint32_t clk_id, uint32_t parent_idx) +{ + microkit_msginfo msginfo = microkit_msginfo_new(SDDF_CLK_SET_PARENT, 2); + microkit_mr_set(SDDF_CLK_PARAM_ID, clk_id); + microkit_mr_set(SDDF_CLK_PARAM_PCLK_IDX, parent_idx); + + msginfo = microkit_ppcall(channel, msginfo); + + return (int)microkit_msginfo_get_label(msginfo); +} diff --git a/include/sddf/clk/g12a-bindings.h b/include/sddf/clk/g12a-bindings.h new file mode 100644 index 000000000..f987c8e5a --- /dev/null +++ b/include/sddf/clk/g12a-bindings.h @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR MIT */ +/* + * Meson-G12A clock tree IDs + * + * Copyright (c) 2018 Amlogic, Inc. All rights reserved. + * + * Source: https://github.com/torvalds/linux/blob/20371ba120635d9ab7fc7670497105af8f33eb08/include/dt-bindings/clock/g12a-clkc.h + */ + +#pragma once + +#define CLKID_SYS_PLL 0 +#define CLKID_FIXED_PLL 1 +#define CLKID_FCLK_DIV2 2 +#define CLKID_FCLK_DIV3 3 +#define CLKID_FCLK_DIV4 4 +#define CLKID_FCLK_DIV5 5 +#define CLKID_FCLK_DIV7 6 +#define CLKID_GP0_PLL 7 +#define CLKID_MPEG_SEL 8 +#define CLKID_MPEG_DIV 9 +#define CLKID_CLK81 10 +#define CLKID_MPLL0 11 +#define CLKID_MPLL1 12 +#define CLKID_MPLL2 13 +#define CLKID_MPLL3 14 +#define CLKID_DDR 15 +#define CLKID_DOS 16 +#define CLKID_AUDIO_LOCKER 17 +#define CLKID_MIPI_DSI_HOST 18 +#define CLKID_ETH_PHY 19 +#define CLKID_ISA 20 +#define CLKID_PL301 21 +#define CLKID_PERIPHS 22 +#define CLKID_SPICC0 23 +#define CLKID_I2C 24 +#define CLKID_SANA 25 +#define CLKID_SD 26 +#define CLKID_RNG0 27 +#define CLKID_UART0 28 +#define CLKID_SPICC1 29 +#define CLKID_HIU_IFACE 30 +#define CLKID_MIPI_DSI_PHY 31 +#define CLKID_ASSIST_MISC 32 +#define CLKID_SD_EMMC_A 33 +#define CLKID_SD_EMMC_B 34 +#define CLKID_SD_EMMC_C 35 +#define CLKID_AUDIO_CODEC 36 +#define CLKID_AUDIO 37 +#define CLKID_ETH 38 +#define CLKID_DEMUX 39 +#define CLKID_AUDIO_IFIFO 40 +#define CLKID_ADC 41 +#define CLKID_UART1 42 +#define CLKID_G2D 43 +#define CLKID_RESET 44 +#define CLKID_PCIE_COMB 45 +#define CLKID_PARSER 46 +#define CLKID_USB 47 +#define CLKID_PCIE_PHY 48 +#define CLKID_AHB_ARB0 49 +#define CLKID_AHB_DATA_BUS 50 +#define CLKID_AHB_CTRL_BUS 51 +#define CLKID_HTX_HDCP22 52 +#define CLKID_HTX_PCLK 53 +#define CLKID_BT656 54 +#define CLKID_USB1_DDR_BRIDGE 55 +#define CLKID_MMC_PCLK 56 +#define CLKID_UART2 57 +#define CLKID_VPU_INTR 58 +#define CLKID_GIC 59 +#define CLKID_SD_EMMC_A_CLK0 60 +#define CLKID_SD_EMMC_B_CLK0 61 +#define CLKID_SD_EMMC_C_CLK0 62 +#define CLKID_SD_EMMC_A_CLK0_SEL 63 +#define CLKID_SD_EMMC_A_CLK0_DIV 64 +#define CLKID_SD_EMMC_B_CLK0_SEL 65 +#define CLKID_SD_EMMC_B_CLK0_DIV 66 +#define CLKID_SD_EMMC_C_CLK0_SEL 67 +#define CLKID_SD_EMMC_C_CLK0_DIV 68 +#define CLKID_MPLL0_DIV 69 +#define CLKID_MPLL1_DIV 70 +#define CLKID_MPLL2_DIV 71 +#define CLKID_MPLL3_DIV 72 +#define CLKID_MPLL_PREDIV 73 +#define CLKID_HIFI_PLL 74 +#define CLKID_FCLK_DIV2_DIV 75 +#define CLKID_FCLK_DIV3_DIV 76 +#define CLKID_FCLK_DIV4_DIV 77 +#define CLKID_FCLK_DIV5_DIV 78 +#define CLKID_FCLK_DIV7_DIV 79 +#define CLKID_VCLK2_VENCI0 80 +#define CLKID_VCLK2_VENCI1 81 +#define CLKID_VCLK2_VENCP0 82 +#define CLKID_VCLK2_VENCP1 83 +#define CLKID_VCLK2_VENCT0 84 +#define CLKID_VCLK2_VENCT1 85 +#define CLKID_VCLK2_OTHER 86 +#define CLKID_VCLK2_ENCI 87 +#define CLKID_VCLK2_ENCP 88 +#define CLKID_DAC_CLK 89 +#define CLKID_AOCLK 90 +#define CLKID_IEC958 91 +#define CLKID_ENC480P 92 +#define CLKID_RNG1 93 +#define CLKID_VCLK2_ENCT 94 +#define CLKID_VCLK2_ENCL 95 +#define CLKID_VCLK2_VENCLMMC 96 +#define CLKID_VCLK2_VENCL 97 +#define CLKID_VCLK2_OTHER1 98 +#define CLKID_FCLK_DIV2P5 99 +#define CLKID_FCLK_DIV2P5_DIV 100 +#define CLKID_FIXED_PLL_DCO 101 +#define CLKID_SYS_PLL_DCO 102 +#define CLKID_GP0_PLL_DCO 103 +#define CLKID_HIFI_PLL_DCO 104 +#define CLKID_DMA 105 +#define CLKID_EFUSE 106 +#define CLKID_ROM_BOOT 107 +#define CLKID_RESET_SEC 108 +#define CLKID_SEC_AHB_APB3 109 +#define CLKID_VPU_0_SEL 110 +#define CLKID_VPU_0_DIV 111 +#define CLKID_VPU_0 112 +#define CLKID_VPU_1_SEL 113 +#define CLKID_VPU_1_DIV 114 +#define CLKID_VPU_1 115 +#define CLKID_VPU 116 +#define CLKID_VAPB_0_SEL 117 +#define CLKID_VAPB_0_DIV 118 +#define CLKID_VAPB_0 119 +#define CLKID_VAPB_1_SEL 120 +#define CLKID_VAPB_1_DIV 121 +#define CLKID_VAPB_1 122 +#define CLKID_VAPB_SEL 123 +#define CLKID_VAPB 124 +#define CLKID_HDMI_PLL_DCO 125 +#define CLKID_HDMI_PLL_OD 126 +#define CLKID_HDMI_PLL_OD2 127 +#define CLKID_HDMI_PLL 128 +#define CLKID_VID_PLL 129 +#define CLKID_VID_PLL_SEL 130 +#define CLKID_VID_PLL_DIV 131 +#define CLKID_VCLK_SEL 132 +#define CLKID_VCLK2_SEL 133 +#define CLKID_VCLK_INPUT 134 +#define CLKID_VCLK2_INPUT 135 +#define CLKID_VCLK_DIV 136 +#define CLKID_VCLK2_DIV 137 +#define CLKID_VCLK 138 +#define CLKID_VCLK2 139 +#define CLKID_VCLK_DIV2_EN 140 +#define CLKID_VCLK_DIV4_EN 141 +#define CLKID_VCLK_DIV6_EN 142 +#define CLKID_VCLK_DIV12_EN 143 +#define CLKID_VCLK2_DIV2_EN 144 +#define CLKID_VCLK2_DIV4_EN 145 +#define CLKID_VCLK2_DIV6_EN 146 +#define CLKID_VCLK2_DIV12_EN 147 +#define CLKID_VCLK_DIV1 148 +#define CLKID_VCLK_DIV2 149 +#define CLKID_VCLK_DIV4 150 +#define CLKID_VCLK_DIV6 151 +#define CLKID_VCLK_DIV12 152 +#define CLKID_VCLK2_DIV1 153 +#define CLKID_VCLK2_DIV2 154 +#define CLKID_VCLK2_DIV4 155 +#define CLKID_VCLK2_DIV6 156 +#define CLKID_VCLK2_DIV12 157 +#define CLKID_CTS_ENCI_SEL 158 +#define CLKID_CTS_ENCP_SEL 159 +#define CLKID_CTS_VDAC_SEL 160 +#define CLKID_HDMI_TX_SEL 161 +#define CLKID_CTS_ENCI 162 +#define CLKID_CTS_ENCP 163 +#define CLKID_CTS_VDAC 164 +#define CLKID_HDMI_TX 165 +#define CLKID_HDMI_SEL 166 +#define CLKID_HDMI_DIV 167 +#define CLKID_HDMI 168 +#define CLKID_MALI_0_SEL 169 +#define CLKID_MALI_0_DIV 170 +#define CLKID_MALI_0 171 +#define CLKID_MALI_1_SEL 172 +#define CLKID_MALI_1_DIV 173 +#define CLKID_MALI_1 174 +#define CLKID_MALI 175 +#define CLKID_MPLL_50M_DIV 176 +#define CLKID_MPLL_50M 177 +#define CLKID_SYS_PLL_DIV16_EN 178 +#define CLKID_SYS_PLL_DIV16 179 +#define CLKID_CPU_CLK_DYN0_SEL 180 +#define CLKID_CPU_CLK_DYN0_DIV 181 +#define CLKID_CPU_CLK_DYN0 182 +#define CLKID_CPU_CLK_DYN1_SEL 183 +#define CLKID_CPU_CLK_DYN1_DIV 184 +#define CLKID_CPU_CLK_DYN1 185 +#define CLKID_CPU_CLK_DYN 186 +#define CLKID_CPU_CLK 187 +#define CLKID_CPU_CLK_DIV16_EN 188 +#define CLKID_CPU_CLK_DIV16 189 +#define CLKID_CPU_CLK_APB_DIV 190 +#define CLKID_CPU_CLK_APB 191 +#define CLKID_CPU_CLK_ATB_DIV 192 +#define CLKID_CPU_CLK_ATB 193 +#define CLKID_CPU_CLK_AXI_DIV 194 +#define CLKID_CPU_CLK_AXI 195 +#define CLKID_CPU_CLK_TRACE_DIV 196 +#define CLKID_CPU_CLK_TRACE 197 +#define CLKID_PCIE_PLL_DCO 198 +#define CLKID_PCIE_PLL_DCO_DIV2 199 +#define CLKID_PCIE_PLL_OD 200 +#define CLKID_PCIE_PLL 201 +#define CLKID_VDEC_1_SEL 202 +#define CLKID_VDEC_1_DIV 203 +#define CLKID_VDEC_1 204 +#define CLKID_VDEC_HEVC_SEL 205 +#define CLKID_VDEC_HEVC_DIV 206 +#define CLKID_VDEC_HEVC 207 +#define CLKID_VDEC_HEVCF_SEL 208 +#define CLKID_VDEC_HEVCF_DIV 209 +#define CLKID_VDEC_HEVCF 210 +#define CLKID_TS_DIV 211 +#define CLKID_TS 212 +#define CLKID_SYS1_PLL_DCO 213 +#define CLKID_SYS1_PLL 214 +#define CLKID_SYS1_PLL_DIV16_EN 215 +#define CLKID_SYS1_PLL_DIV16 216 +#define CLKID_CPUB_CLK_DYN0_SEL 217 +#define CLKID_CPUB_CLK_DYN0_DIV 218 +#define CLKID_CPUB_CLK_DYN0 219 +#define CLKID_CPUB_CLK_DYN1_SEL 220 +#define CLKID_CPUB_CLK_DYN1_DIV 221 +#define CLKID_CPUB_CLK_DYN1 222 +#define CLKID_CPUB_CLK_DYN 223 +#define CLKID_CPUB_CLK 224 +#define CLKID_CPUB_CLK_DIV16_EN 225 +#define CLKID_CPUB_CLK_DIV16 226 +#define CLKID_CPUB_CLK_DIV2 227 +#define CLKID_CPUB_CLK_DIV3 228 +#define CLKID_CPUB_CLK_DIV4 229 +#define CLKID_CPUB_CLK_DIV5 230 +#define CLKID_CPUB_CLK_DIV6 231 +#define CLKID_CPUB_CLK_DIV7 232 +#define CLKID_CPUB_CLK_DIV8 233 +#define CLKID_CPUB_CLK_APB_SEL 234 +#define CLKID_CPUB_CLK_APB 235 +#define CLKID_CPUB_CLK_ATB_SEL 236 +#define CLKID_CPUB_CLK_ATB 237 +#define CLKID_CPUB_CLK_AXI_SEL 238 +#define CLKID_CPUB_CLK_AXI 239 +#define CLKID_CPUB_CLK_TRACE_SEL 240 +#define CLKID_CPUB_CLK_TRACE 241 +#define CLKID_GP1_PLL_DCO 242 +#define CLKID_GP1_PLL 243 +#define CLKID_DSU_CLK_DYN0_SEL 244 +#define CLKID_DSU_CLK_DYN0_DIV 245 +#define CLKID_DSU_CLK_DYN0 246 +#define CLKID_DSU_CLK_DYN1_SEL 247 +#define CLKID_DSU_CLK_DYN1_DIV 248 +#define CLKID_DSU_CLK_DYN1 249 +#define CLKID_DSU_CLK_DYN 250 +#define CLKID_DSU_CLK_FINAL 251 +#define CLKID_DSU_CLK 252 +#define CLKID_CPU1_CLK 253 +#define CLKID_CPU2_CLK 254 +#define CLKID_CPU3_CLK 255 +#define CLKID_SPICC0_SCLK_SEL 256 +#define CLKID_SPICC0_SCLK_DIV 257 +#define CLKID_SPICC0_SCLK 258 +#define CLKID_SPICC1_SCLK_SEL 259 +#define CLKID_SPICC1_SCLK_DIV 260 +#define CLKID_SPICC1_SCLK 261 +#define CLKID_NNA_AXI_CLK_SEL 262 +#define CLKID_NNA_AXI_CLK_DIV 263 +#define CLKID_NNA_AXI_CLK 264 +#define CLKID_NNA_CORE_CLK_SEL 265 +#define CLKID_NNA_CORE_CLK_DIV 266 +#define CLKID_NNA_CORE_CLK 267 +#define CLKID_MIPI_DSI_PXCLK_DIV 268 +#define CLKID_MIPI_DSI_PXCLK_SEL 269 +#define CLKID_MIPI_DSI_PXCLK 270 +#define CLKID_CTS_ENCL 271 +#define CLKID_CTS_ENCL_SEL 272 +#define CLKID_MIPI_ISP_DIV 273 +#define CLKID_MIPI_ISP_SEL 274 +#define CLKID_MIPI_ISP 275 +#define CLKID_MIPI_ISP_GATE 276 +#define CLKID_MIPI_ISP_CSI_PHY0 277 +#define CLKID_MIPI_ISP_CSI_PHY1 278 + +#define CLKID_G12A_XTAL 279 diff --git a/include/sddf/clk/imx8mq-bindings.h b/include/sddf/clk/imx8mq-bindings.h new file mode 100644 index 000000000..5af8332ce --- /dev/null +++ b/include/sddf/clk/imx8mq-bindings.h @@ -0,0 +1,430 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * Source: https://github.com/torvalds/linux/blob/master/include/dt-bindings/clock/imx8mq-clock.h + */ + +#pragma once + +#define IMX8MQ_CLK_DUMMY 0 +#define IMX8MQ_CLK_32K 1 +#define IMX8MQ_CLK_25M 2 +#define IMX8MQ_CLK_27M 3 +#define IMX8MQ_CLK_EXT1 4 +#define IMX8MQ_CLK_EXT2 5 +#define IMX8MQ_CLK_EXT3 6 +#define IMX8MQ_CLK_EXT4 7 + +/* ANAMIX PLL clocks */ +/* FRAC PLLs */ +/* ARM PLL */ +#define IMX8MQ_ARM_PLL_REF_SEL 8 +#define IMX8MQ_ARM_PLL_REF_DIV 9 +#define IMX8MQ_ARM_PLL 10 +#define IMX8MQ_ARM_PLL_BYPASS 11 +#define IMX8MQ_ARM_PLL_OUT 12 + +/* GPU PLL */ +#define IMX8MQ_GPU_PLL_REF_SEL 13 +#define IMX8MQ_GPU_PLL_REF_DIV 14 +#define IMX8MQ_GPU_PLL 15 +#define IMX8MQ_GPU_PLL_BYPASS 16 +#define IMX8MQ_GPU_PLL_OUT 17 + +/* VPU PLL */ +#define IMX8MQ_VPU_PLL_REF_SEL 18 +#define IMX8MQ_VPU_PLL_REF_DIV 19 +#define IMX8MQ_VPU_PLL 20 +#define IMX8MQ_VPU_PLL_BYPASS 21 +#define IMX8MQ_VPU_PLL_OUT 22 + +/* AUDIO PLL1 */ +#define IMX8MQ_AUDIO_PLL1_REF_SEL 23 +#define IMX8MQ_AUDIO_PLL1_REF_DIV 24 +#define IMX8MQ_AUDIO_PLL1 25 +#define IMX8MQ_AUDIO_PLL1_BYPASS 26 +#define IMX8MQ_AUDIO_PLL1_OUT 27 + +/* AUDIO PLL2 */ +#define IMX8MQ_AUDIO_PLL2_REF_SEL 28 +#define IMX8MQ_AUDIO_PLL2_REF_DIV 29 +#define IMX8MQ_AUDIO_PLL2 30 +#define IMX8MQ_AUDIO_PLL2_BYPASS 31 +#define IMX8MQ_AUDIO_PLL2_OUT 32 + +/* VIDEO PLL1 */ +#define IMX8MQ_VIDEO_PLL1_REF_SEL 33 +#define IMX8MQ_VIDEO_PLL1_REF_DIV 34 +#define IMX8MQ_VIDEO_PLL1 35 +#define IMX8MQ_VIDEO_PLL1_BYPASS 36 +#define IMX8MQ_VIDEO_PLL1_OUT 37 + +/* SYS1 PLL */ +#define IMX8MQ_SYS1_PLL1_REF_SEL 38 +#define IMX8MQ_SYS1_PLL1_REF_DIV 39 +#define IMX8MQ_SYS1_PLL1 40 +#define IMX8MQ_SYS1_PLL1_OUT 41 +#define IMX8MQ_SYS1_PLL1_OUT_DIV 42 +#define IMX8MQ_SYS1_PLL2 43 +#define IMX8MQ_SYS1_PLL2_DIV 44 +#define IMX8MQ_SYS1_PLL2_OUT 45 + +/* SYS2 PLL */ +#define IMX8MQ_SYS2_PLL1_REF_SEL 46 +#define IMX8MQ_SYS2_PLL1_REF_DIV 47 +#define IMX8MQ_SYS2_PLL1 48 +#define IMX8MQ_SYS2_PLL1_OUT 49 +#define IMX8MQ_SYS2_PLL1_OUT_DIV 50 +#define IMX8MQ_SYS2_PLL2 51 +#define IMX8MQ_SYS2_PLL2_DIV 52 +#define IMX8MQ_SYS2_PLL2_OUT 53 + +/* SYS3 PLL */ +#define IMX8MQ_SYS3_PLL1_REF_SEL 54 +#define IMX8MQ_SYS3_PLL1_REF_DIV 55 +#define IMX8MQ_SYS3_PLL1 56 +#define IMX8MQ_SYS3_PLL1_OUT 57 +#define IMX8MQ_SYS3_PLL1_OUT_DIV 58 +#define IMX8MQ_SYS3_PLL2 59 +#define IMX8MQ_SYS3_PLL2_DIV 60 +#define IMX8MQ_SYS3_PLL2_OUT 61 + +/* DRAM PLL */ +#define IMX8MQ_DRAM_PLL1_REF_SEL 62 +#define IMX8MQ_DRAM_PLL1_REF_DIV 63 +#define IMX8MQ_DRAM_PLL1 64 +#define IMX8MQ_DRAM_PLL1_OUT 65 +#define IMX8MQ_DRAM_PLL1_OUT_DIV 66 +#define IMX8MQ_DRAM_PLL2 67 +#define IMX8MQ_DRAM_PLL2_DIV 68 +#define IMX8MQ_DRAM_PLL2_OUT 69 + +/* SYS PLL DIV */ +#define IMX8MQ_SYS1_PLL_40M 70 +#define IMX8MQ_SYS1_PLL_80M 71 +#define IMX8MQ_SYS1_PLL_100M 72 +#define IMX8MQ_SYS1_PLL_133M 73 +#define IMX8MQ_SYS1_PLL_160M 74 +#define IMX8MQ_SYS1_PLL_200M 75 +#define IMX8MQ_SYS1_PLL_266M 76 +#define IMX8MQ_SYS1_PLL_400M 77 +#define IMX8MQ_SYS1_PLL_800M 78 + +#define IMX8MQ_SYS2_PLL_50M 79 +#define IMX8MQ_SYS2_PLL_100M 80 +#define IMX8MQ_SYS2_PLL_125M 81 +#define IMX8MQ_SYS2_PLL_166M 82 +#define IMX8MQ_SYS2_PLL_200M 83 +#define IMX8MQ_SYS2_PLL_250M 84 +#define IMX8MQ_SYS2_PLL_333M 85 +#define IMX8MQ_SYS2_PLL_500M 86 +#define IMX8MQ_SYS2_PLL_1000M 87 + +/* CCM ROOT clocks */ +/* A53 */ +#define IMX8MQ_CLK_A53_SRC 88 +#define IMX8MQ_CLK_A53_CG 89 +#define IMX8MQ_CLK_A53_DIV 90 +/* M4 */ +#define IMX8MQ_CLK_M4_SRC 91 +#define IMX8MQ_CLK_M4_CG 92 +#define IMX8MQ_CLK_M4_DIV 93 +/* VPU */ +#define IMX8MQ_CLK_VPU_SRC 94 +#define IMX8MQ_CLK_VPU_CG 95 +#define IMX8MQ_CLK_VPU_DIV 96 +/* GPU CORE */ +#define IMX8MQ_CLK_GPU_CORE_SRC 97 +#define IMX8MQ_CLK_GPU_CORE_CG 98 +#define IMX8MQ_CLK_GPU_CORE_DIV 99 +/* GPU SHADER */ +#define IMX8MQ_CLK_GPU_SHADER_SRC 100 +#define IMX8MQ_CLK_GPU_SHADER_CG 101 +#define IMX8MQ_CLK_GPU_SHADER_DIV 102 + +/* BUS TYPE */ +/* MAIN AXI */ +#define IMX8MQ_CLK_MAIN_AXI 103 +/* ENET AXI */ +#define IMX8MQ_CLK_ENET_AXI 104 +/* NAND_USDHC_BUS */ +#define IMX8MQ_CLK_NAND_USDHC_BUS 105 +/* VPU BUS */ +#define IMX8MQ_CLK_VPU_BUS 106 +/* DISP_AXI */ +#define IMX8MQ_CLK_DISP_AXI 107 +/* DISP APB */ +#define IMX8MQ_CLK_DISP_APB 108 +/* DISP RTRM */ +#define IMX8MQ_CLK_DISP_RTRM 109 +/* USB_BUS */ +#define IMX8MQ_CLK_USB_BUS 110 +/* GPU_AXI */ +#define IMX8MQ_CLK_GPU_AXI 111 +/* GPU_AHB */ +#define IMX8MQ_CLK_GPU_AHB 112 +/* NOC */ +#define IMX8MQ_CLK_NOC 113 +/* NOC_APB */ +#define IMX8MQ_CLK_NOC_APB 115 + +/* AHB */ +#define IMX8MQ_CLK_AHB 116 +/* AUDIO AHB */ +#define IMX8MQ_CLK_AUDIO_AHB 117 + +/* DRAM_ALT */ +#define IMX8MQ_CLK_DRAM_ALT 118 +/* DRAM APB */ +#define IMX8MQ_CLK_DRAM_APB 119 +/* VPU_G1 */ +#define IMX8MQ_CLK_VPU_G1 120 +/* VPU_G2 */ +#define IMX8MQ_CLK_VPU_G2 121 +/* DISP_DTRC */ +#define IMX8MQ_CLK_DISP_DTRC 122 +/* DISP_DC8000 */ +#define IMX8MQ_CLK_DISP_DC8000 123 +/* PCIE_CTRL */ +#define IMX8MQ_CLK_PCIE1_CTRL 124 +/* PCIE_PHY */ +#define IMX8MQ_CLK_PCIE1_PHY 125 +/* PCIE_AUX */ +#define IMX8MQ_CLK_PCIE1_AUX 126 +/* DC_PIXEL */ +#define IMX8MQ_CLK_DC_PIXEL 127 +/* LCDIF_PIXEL */ +#define IMX8MQ_CLK_LCDIF_PIXEL 128 +/* SAI1~6 */ +#define IMX8MQ_CLK_SAI1 129 + +#define IMX8MQ_CLK_SAI2 130 + +#define IMX8MQ_CLK_SAI3 131 + +#define IMX8MQ_CLK_SAI4 132 + +#define IMX8MQ_CLK_SAI5 133 + +#define IMX8MQ_CLK_SAI6 134 +/* SPDIF1 */ +#define IMX8MQ_CLK_SPDIF1 135 +/* SPDIF2 */ +#define IMX8MQ_CLK_SPDIF2 136 +/* ENET_REF */ +#define IMX8MQ_CLK_ENET_REF 137 +/* ENET_TIMER */ +#define IMX8MQ_CLK_ENET_TIMER 138 +/* ENET_PHY */ +#define IMX8MQ_CLK_ENET_PHY_REF 139 +/* NAND */ +#define IMX8MQ_CLK_NAND 140 +/* QSPI */ +#define IMX8MQ_CLK_QSPI 141 +/* USDHC1 */ +#define IMX8MQ_CLK_USDHC1 142 +/* USDHC2 */ +#define IMX8MQ_CLK_USDHC2 143 +/* I2C1 */ +#define IMX8MQ_CLK_I2C1 144 +/* I2C2 */ +#define IMX8MQ_CLK_I2C2 145 +/* I2C3 */ +#define IMX8MQ_CLK_I2C3 146 +/* I2C4 */ +#define IMX8MQ_CLK_I2C4 147 +/* UART1 */ +#define IMX8MQ_CLK_UART1 148 +/* UART2 */ +#define IMX8MQ_CLK_UART2 149 +/* UART3 */ +#define IMX8MQ_CLK_UART3 150 +/* UART4 */ +#define IMX8MQ_CLK_UART4 151 +/* USB_CORE_REF */ +#define IMX8MQ_CLK_USB_CORE_REF 152 +/* USB_PHY_REF */ +#define IMX8MQ_CLK_USB_PHY_REF 153 +/* ECSPI1 */ +#define IMX8MQ_CLK_ECSPI1 154 +/* ECSPI2 */ +#define IMX8MQ_CLK_ECSPI2 155 +/* PWM1 */ +#define IMX8MQ_CLK_PWM1 156 +/* PWM2 */ +#define IMX8MQ_CLK_PWM2 157 +/* PWM3 */ +#define IMX8MQ_CLK_PWM3 158 +/* PWM4 */ +#define IMX8MQ_CLK_PWM4 159 +/* GPT1 */ +#define IMX8MQ_CLK_GPT1 160 +/* WDOG */ +#define IMX8MQ_CLK_WDOG 161 +/* WRCLK */ +#define IMX8MQ_CLK_WRCLK 162 +/* DSI_CORE */ +#define IMX8MQ_CLK_DSI_CORE 163 +/* DSI_PHY */ +#define IMX8MQ_CLK_DSI_PHY_REF 164 +/* DSI_DBI */ +#define IMX8MQ_CLK_DSI_DBI 165 +/*DSI_ESC */ +#define IMX8MQ_CLK_DSI_ESC 166 +/* CSI1_CORE */ +#define IMX8MQ_CLK_CSI1_CORE 167 +/* CSI1_PHY */ +#define IMX8MQ_CLK_CSI1_PHY_REF 168 +/* CSI_ESC */ +#define IMX8MQ_CLK_CSI1_ESC 169 +/* CSI2_CORE */ +#define IMX8MQ_CLK_CSI2_CORE 170 +/* CSI2_PHY */ +#define IMX8MQ_CLK_CSI2_PHY_REF 171 +/* CSI2_ESC */ +#define IMX8MQ_CLK_CSI2_ESC 172 +/* PCIE2_CTRL */ +#define IMX8MQ_CLK_PCIE2_CTRL 173 +/* PCIE2_PHY */ +#define IMX8MQ_CLK_PCIE2_PHY 174 +/* PCIE2_AUX */ +#define IMX8MQ_CLK_PCIE2_AUX 175 +/* ECSPI3 */ +#define IMX8MQ_CLK_ECSPI3 176 + +/* CCGR clocks */ +#define IMX8MQ_CLK_A53_ROOT 177 +#define IMX8MQ_CLK_DRAM_ROOT 178 +#define IMX8MQ_CLK_ECSPI1_ROOT 179 +#define IMX8MQ_CLK_ECSPI2_ROOT 180 +#define IMX8MQ_CLK_ECSPI3_ROOT 181 +#define IMX8MQ_CLK_ENET1_ROOT 182 +#define IMX8MQ_CLK_GPT1_ROOT 183 +#define IMX8MQ_CLK_I2C1_ROOT 184 +#define IMX8MQ_CLK_I2C2_ROOT 185 +#define IMX8MQ_CLK_I2C3_ROOT 186 +#define IMX8MQ_CLK_I2C4_ROOT 187 +#define IMX8MQ_CLK_M4_ROOT 188 +#define IMX8MQ_CLK_PCIE1_ROOT 189 +#define IMX8MQ_CLK_PCIE2_ROOT 190 +#define IMX8MQ_CLK_PWM1_ROOT 191 +#define IMX8MQ_CLK_PWM2_ROOT 192 +#define IMX8MQ_CLK_PWM3_ROOT 193 +#define IMX8MQ_CLK_PWM4_ROOT 194 +#define IMX8MQ_CLK_QSPI_ROOT 195 +#define IMX8MQ_CLK_SAI1_ROOT 196 +#define IMX8MQ_CLK_SAI2_ROOT 197 +#define IMX8MQ_CLK_SAI3_ROOT 198 +#define IMX8MQ_CLK_SAI4_ROOT 199 +#define IMX8MQ_CLK_SAI5_ROOT 200 +#define IMX8MQ_CLK_SAI6_ROOT 201 +#define IMX8MQ_CLK_UART1_ROOT 202 +#define IMX8MQ_CLK_UART2_ROOT 203 +#define IMX8MQ_CLK_UART3_ROOT 204 +#define IMX8MQ_CLK_UART4_ROOT 205 +#define IMX8MQ_CLK_USB1_CTRL_ROOT 206 +#define IMX8MQ_CLK_USB2_CTRL_ROOT 207 +#define IMX8MQ_CLK_USB1_PHY_ROOT 208 +#define IMX8MQ_CLK_USB2_PHY_ROOT 209 +#define IMX8MQ_CLK_USDHC1_ROOT 210 +#define IMX8MQ_CLK_USDHC2_ROOT 211 +#define IMX8MQ_CLK_WDOG1_ROOT 212 +#define IMX8MQ_CLK_WDOG2_ROOT 213 +#define IMX8MQ_CLK_WDOG3_ROOT 214 +#define IMX8MQ_CLK_GPU_ROOT 215 +#define IMX8MQ_CLK_HEVC_ROOT 216 +#define IMX8MQ_CLK_AVC_ROOT 217 +#define IMX8MQ_CLK_VP9_ROOT 218 +#define IMX8MQ_CLK_HEVC_INTER_ROOT 219 +#define IMX8MQ_CLK_DISP_ROOT 220 +#define IMX8MQ_CLK_HDMI_ROOT 221 +#define IMX8MQ_CLK_HDMI_PHY_ROOT 222 +#define IMX8MQ_CLK_VPU_DEC_ROOT 223 +#define IMX8MQ_CLK_CSI1_ROOT 224 +#define IMX8MQ_CLK_CSI2_ROOT 225 +#define IMX8MQ_CLK_RAWNAND_ROOT 226 +#define IMX8MQ_CLK_SDMA1_ROOT 227 +#define IMX8MQ_CLK_SDMA2_ROOT 228 +#define IMX8MQ_CLK_VPU_G1_ROOT 229 +#define IMX8MQ_CLK_VPU_G2_ROOT 230 + +/* SCCG PLL GATE */ +#define IMX8MQ_SYS1_PLL_OUT 231 +#define IMX8MQ_SYS2_PLL_OUT 232 +#define IMX8MQ_SYS3_PLL_OUT 233 +#define IMX8MQ_DRAM_PLL_OUT 234 + +#define IMX8MQ_GPT_3M_CLK 235 + +#define IMX8MQ_CLK_IPG_ROOT 236 +#define IMX8MQ_CLK_IPG_AUDIO_ROOT 237 +#define IMX8MQ_CLK_SAI1_IPG 238 +#define IMX8MQ_CLK_SAI2_IPG 239 +#define IMX8MQ_CLK_SAI3_IPG 240 +#define IMX8MQ_CLK_SAI4_IPG 241 +#define IMX8MQ_CLK_SAI5_IPG 242 +#define IMX8MQ_CLK_SAI6_IPG 243 + +/* DSI AHB/IPG clocks */ +/* rxesc clock */ +#define IMX8MQ_CLK_DSI_AHB 244 +/* txesc clock */ +#define IMX8MQ_CLK_DSI_IPG_DIV 245 + +#define IMX8MQ_CLK_TMU_ROOT 246 + +/* Display root clocks */ +#define IMX8MQ_CLK_DISP_AXI_ROOT 247 +#define IMX8MQ_CLK_DISP_APB_ROOT 248 +#define IMX8MQ_CLK_DISP_RTRM_ROOT 249 + +#define IMX8MQ_CLK_OCOTP_ROOT 250 + +#define IMX8MQ_CLK_DRAM_ALT_ROOT 251 +#define IMX8MQ_CLK_DRAM_CORE 252 + +#define IMX8MQ_CLK_MU_ROOT 253 +#define IMX8MQ_VIDEO2_PLL_OUT 254 + +#define IMX8MQ_CLK_CLKO2 255 + +#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK 256 + +#define IMX8MQ_CLK_CLKO1 257 +#define IMX8MQ_CLK_ARM 258 + +#define IMX8MQ_CLK_GPIO1_ROOT 259 +#define IMX8MQ_CLK_GPIO2_ROOT 260 +#define IMX8MQ_CLK_GPIO3_ROOT 261 +#define IMX8MQ_CLK_GPIO4_ROOT 262 +#define IMX8MQ_CLK_GPIO5_ROOT 263 + +#define IMX8MQ_CLK_SNVS_ROOT 264 +#define IMX8MQ_CLK_GIC 265 + +#define IMX8MQ_VIDEO2_PLL1_REF_SEL 266 + +#define IMX8MQ_CLK_GPU_CORE 285 +#define IMX8MQ_CLK_GPU_SHADER 286 +#define IMX8MQ_CLK_M4_CORE 287 +#define IMX8MQ_CLK_VPU_CORE 288 + +#define IMX8MQ_CLK_A53_CORE 289 + +#define IMX8MQ_CLK_MON_AUDIO_PLL1_DIV 290 +#define IMX8MQ_CLK_MON_AUDIO_PLL2_DIV 291 +#define IMX8MQ_CLK_MON_VIDEO_PLL1_DIV 292 +#define IMX8MQ_CLK_MON_GPU_PLL_DIV 293 +#define IMX8MQ_CLK_MON_VPU_PLL_DIV 294 +#define IMX8MQ_CLK_MON_ARM_PLL_DIV 295 +#define IMX8MQ_CLK_MON_SYS_PLL1_DIV 296 +#define IMX8MQ_CLK_MON_SYS_PLL2_DIV 297 +#define IMX8MQ_CLK_MON_SYS_PLL3_DIV 298 +#define IMX8MQ_CLK_MON_DRAM_PLL_DIV 299 +#define IMX8MQ_CLK_MON_VIDEO_PLL2_DIV 300 +#define IMX8MQ_CLK_MON_SEL 301 +#define IMX8MQ_CLK_MON_CLK2_OUT 302 + +#define IMX8MQ_CLK_END 303 diff --git a/include/sddf/clk/protocol.h b/include/sddf/clk/protocol.h new file mode 100644 index 000000000..781483ced --- /dev/null +++ b/include/sddf/clk/protocol.h @@ -0,0 +1,31 @@ +/* + * Copyright 2024, UNSW + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once +#include + +/* Shared functionality/definitions between pinctrl drivers and clients */ + +#ifdef ODROID_C4 +#include +#endif + +#define SDDF_CLK_ENABLE 0 +#define SDDF_CLK_DISABLE 1 +#define SDDF_CLK_GET_RATE 2 +#define SDDF_CLK_SET_RATE 3 +#define SDDF_CLK_GET_PARENT 4 +#define SDDF_CLK_SET_PARENT 5 + +#define SDDF_CLK_PARAM_ID 0 +#define SDDF_CLK_PARAM_RATE 1 + +#define SDDF_CLK_PARAM_PCLK_IDX 1 + +struct clk_cfg { + uint32_t clk_id; + uint32_t frequency; + uint32_t pclk_id; +};