diff options
Diffstat (limited to 'common/recipes-utils/openbmc-gpio/files')
10 files changed, 1203 insertions, 0 deletions
diff --git a/common/recipes-utils/openbmc-gpio/files/COPYING b/common/recipes-utils/openbmc-gpio/files/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, 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 Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + 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 a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 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 St, 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 + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/common/recipes-utils/openbmc-gpio/files/board_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/board_gpio_table.py new file mode 100644 index 0000000..3261f51 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/board_gpio_table.py @@ -0,0 +1,23 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +# This is an dummy board GPIO table. If this is included in the final image, +# please double check the configuration of your image to define the correct +# GPIO table to be used for your board. + +board_gpio_table = [ +] diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio.py new file mode 100644 index 0000000..9e92324 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio.py @@ -0,0 +1,164 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import logging +import os +import string + + +_gpio_shadow = '/tmp/gpionames' + + +def setup_shadow(shadow=None): + global _gpio_shadow + if shadow is not None: + _gpio_shadow = shadow + if not os.path.exists(_gpio_shadow): + os.makedirs(_gpio_shadow) + + +def gpio_name2value(name): + name = str(name).lower() + if name.startswith('gpio'): + name = name[4:] + try: + return int(name) + except: + # it is not just value, try treat it as name like 'A0' + pass + val = 0 + try: + if len(name) != 2 and len(name) != 3: + raise + for idx in range(0, len(name)): + ch = name[idx] + if ch in string.ascii_lowercase: + # letter cannot be the last character + if idx == len(name) - 1: + raise + tmp = ord(ch) - ord('a') + 1 + val = val * 26 + tmp + elif ch in string.digits: + # digit must be the last character + if idx != len(name) - 1: + raise + # the digit must be 0-7 + tmp = ord(ch) - ord('0') + if tmp > 7: + raise + # 'A4' is value 4 + if val > 0: + val -= 1 + val = val * 8 + tmp + else: + raise + except: + logging.exception('Invalid GPIO name "%s"' % name) + return val + + +def gpio_dir(name, check_shadow=True): + GPIODIR_FMT = '/sys/class/gpio/gpio{gpio}' + if check_shadow: + shadowdir = os.path.join(_gpio_shadow, name) + if os.path.isdir(shadowdir): + return shadowdir + val = gpio_name2value(name) + return GPIODIR_FMT.format(gpio=val) + + +def gpio_get_shadow(name): + path = gpio_dir(name, check_shadow=False) + for child in os.listdir(_gpio_shadow): + try: + child = os.path.join(_gpio_shadow, child) + if os.readlink(child) == path: + return child + except: + pass + return None + + +def gpio_export(name, shadow=None): + GPIOEXPORT = '/sys/class/gpio/export' + if shadow is not None or shadow != '': + shadowdir = os.path.join(_gpio_shadow, shadow) + if os.path.exists(shadowdir): + raise Exception('Shadow "%s" exists already' % shadowdir) + old_shadow = gpio_get_shadow(name) + if old_shadow is not None: + raise Exception('Shadow "%s" already exists for %s' + % (old_shadow, name)) + + val = gpio_name2value(name) + try: + with open(GPIOEXPORT, 'w') as f: + f.write('%d\n' % val) + except: + # in case the GPIO has been exported already + pass + if shadow is not None: + gpiodir = gpio_dir(val, check_shadow=False) + os.symlink(gpiodir, shadowdir) + + +def gpio_get(name, change_direction=True): + path = gpio_dir(name) + if change_direction: + with open(os.path.join(path, 'direction'), 'w') as f: + f.write('in\n') + with open(os.path.join(path, 'value'), 'r') as f: + val = int(f.read().rstrip('\n')) + return val + + +def gpio_set(name, value, change_direction=True): + path = gpio_dir(name) + with open(os.path.join(path, 'value'), 'w') as f: + f.write('%d\n' % (1 if value else 0)) + if change_direction: + with open(os.path.join(path, 'direction'), 'w') as f: + f.write('out\n') + + +def gpio_info(name): + res = {} + # first check if name is shadow + path = None + shadow = os.path.join(_gpio_shadow, name) + if os.path.exists(shadow): + if not os.path.islink(shadow) or not os.path.isdir(shadow): + raise Exception('Path "%s" is not a valid shadow path' % shadow) + path = os.readlink(shadow) + else: + path = gpio_dir(name, check_shadow=False) + shadow = gpio_get_shadow(name) + res['path'] = path + res['shadow'] = shadow + if os.path.isdir(path): + with open(os.path.join(path, 'direction'), 'r') as f: + res['direction'] = f.read().rstrip('\n') + with open(os.path.join(path, 'value'), 'r') as f: + res['value'] = int(f.read().rstrip('\n')) + else: + res['direction'] = None + res['value'] = None + return res diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py new file mode 100644 index 0000000..7c126d9 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py @@ -0,0 +1,76 @@ +#!/usr/bin/python -tt +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from board_gpio_table import board_gpio_table +from soc_gpio_table import soc_gpio_table + +import openbmc_gpio +import openbmc_gpio_table + +import logging +import sys + + +def setup_board_gpio(soc_gpio_table, board_gpio_table, validate=True): + soc = openbmc_gpio_table.SocGPIOTable(soc_gpio_table) + gpio_configured = [] + for gpio in board_gpio_table: + try: + soc.config_function(gpio.gpio, write_through=False) + gpio_configured.append(gpio.gpio) + except openbmc_gpio_table.ConfigUnknownFunction as e: + # not multiple-function GPIO pin + pass + except openbmc_gpio_table.NotSmartEnoughException as e: + logging.error('Failed to configure "%s" for "%s": %s' + % (gpio.gpio, gpio.shadow, str(e))) + + soc.write_to_hw() + + if validate: + all_functions = set(soc.get_active_functions(refresh=True)) + for gpio in gpio_configured: + if gpio not in all_functions: + raise Exception('Failed to configure function "%s"' % gpio) + + for gpio in board_gpio_table: + openbmc_gpio.gpio_export(gpio.gpio, gpio.shadow) + if gpio.value == openbmc_gpio_table.GPIO_INPUT: + continue + elif gpio.value == openbmc_gpio_table.GPIO_OUT_HIGH: + openbmc_gpio.gpio_set(gpio.gpio, 1) + elif gpio.value == openbmc_gpio_table.GPIO_OUT_LOW: + openbmc_gpio.gpio_set(gpio.gpio, 0) + else: + raise Exception('Invalid value "%s"' % gpio.value) + +def main(): + print('Setting up GPIOs ... ', end='') + sys.stdout.flush() + openbmc_gpio.setup_shadow() + setup_board_gpio(soc_gpio_table, board_gpio_table) + print('Done') + sys.stdout.flush() + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py new file mode 100644 index 0000000..dda8a98 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py @@ -0,0 +1,269 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from soc_gpio import soc_get_register + +import logging +import os +import sys + + +class NotSmartEnoughException(Exception): + '''There are few cases the code cannot make good decision on how to configure + the registers automatically. In such cases, this exception is thrown. + ''' + pass + + +class ConfigUnknownFunction(Exception): + '''Unknown function to configure exception''' + pass + + +class BitsEqual(object): + def __init__(self, register, bits, value): + self.register = register + self.bits = bits + self.value = value + + def __str__(self): + return '%s[%s]==0x%x' \ + % (str(soc_get_register(self.register)), self.bits, self.value) + + def get_registers(self): + return set([self.register]) + + def check(self): + return soc_get_register(self.register).bits_value(self.bits) \ + == self.value + + def satisfy(self, **kwargs): + if BitsEqual.check(self): + return + reg = soc_get_register(self.register) + value = self.value + for bit in sorted(self.bits): + if value & 0x1 == 0x1: + reg.set_bit(bit, **kwargs) + else: + reg.clear_bit(bit, **kwargs) + value >>= 1 + + def unsatisfy(self, **kwargs): + if not BitsEqual.check(self): + return + if len(self.bits) > 1: + raise NotSmartEnoughException('Not able to unsatisfy ' + 'multi-bits equal') + bit = self.bits[0] + reg = soc_get_register(self.register) + value = self.value + if value & 0x1 == 0x1: + reg.clear_bit(bit, **kwargs) + else: + reg.set_bit(bit, **kwargs) + + +class BitsNotEqual(BitsEqual): + def __str__(self): + return '%s[%s]!=0x%x' \ + % (str(soc_get_register(self.register)), self.bits, self.value) + + def check(self): + return not BitsEqual.check(self) + + def satisfy(self, **kwargs): + BitsEqual.unsatisfy(self, **kwargs) + + def unsatisfy(self, **kwargs): + BitsEqual.satisfy(self, **kwargs) + + +class AndOrBase(object): + def __init__(self, left, right): + self.left = left + self.right = right + + def get_registers(self): + return self.left.get_registers() | self.right.get_registers() + + def check(self): + raise Exception('This method must be implemented in subclass') + + +class And(AndOrBase): + def __str__(self): + return 'AND(%s, %s)' % (str(self.left), str(self.right)) + + def check(self): + return self.left.check() and self.right.check() + + def satisfy(self, **kwargs): + if self.check(): + return + self.left.satisfy(**kwargs) + self.right.satisfy(**kwargs) + + def unsatisfy(self, **kwargs): + if not self.check(): + return + raise NotSmartEnoughException('Not able to unsatisfy an AND condition') + + +class Or(AndOrBase): + def __str__(self): + return 'OR(%s, %s)' % (str(self.left), str(self.right)) + + def check(self): + return self.left.check() or self.right.check() + + def satisfy(self, **kwargs): + if self.check(): + return + raise NotSmartEnoughException('Not able to satisfy an OR condition') + + def unsatisfy(self, **kwargs): + if not self.check(): + return + self.left.unsatisfy(**kwargs) + self.right.unsatisfy(**kwargs) + + +class Function(object): + def __init__(self, name, condition=None): + self.name = name + self.condition = condition + + def __str__(self): + return 'Function(\'%s\', %s)' % (self.name, str(self.condition)) + + +class SocGPIOTable(object): + def __init__(self, gpio_table): + self.soc_gpio_table = gpio_table + self.registers = set([]) # all HW registers used for GPIO control + self.functions = {} + + self._parse_gpio_table() + self._sync_from_hw() + + def _parse_gpio_table(self): + # first get list of registers based on the SoC GPIO table + for pin, funcs in self.soc_gpio_table.iteritems(): + for func in funcs: + assert func.name not in self.functions + self.functions[func.name] = pin + if func.condition is not None: + self.registers |= func.condition.get_registers() + + def _sync_from_hw(self): + # for each register, create an object and read the value from HW + for reg in self.registers: + soc_get_register(reg).read(refresh=True) + + def write_to_hw(self): + for reg in self.registers: + soc_get_register(reg).write() + + def config_function(self, func_name, write_through=True): + logging.debug('Configure function "%s"' % func_name) + if func_name not in self.functions: + # The function is not multi-function pin + raise ConfigUnknownFunction('Unknown function "%s" ' % func_name) + funcs = self.soc_gpio_table[self.functions[func_name]] + for func in funcs: + cond = func.condition + if func.name == func_name: + # this is the function we want to configure. + # if the condition is None, we are good to go, + # otherwiset, satisfy the condition + if cond is not None: + cond.satisfy(write_through=write_through) + break + else: + # this is not the funciton we want to configure. + # have to make this condition unsatisfied, so that we can go + # to the next function + assert cond is not None + cond.unsatisfy(write_through=write_through) + + def _get_one_pin(self, pin, refresh): + if refresh: + self._sync_from_hw() + funcs = self.soc_gpio_table[pin] + active_func = None + all_funcs = [] + for func in funcs: + cond = func.condition + all_funcs.append('%s:%s' % (func.name, str(cond))) + if active_func is None and (cond is None or cond.check()): + active_func = func.name + + if active_func is None: + logging.error('Pin "%s" has no function set up. ' + 'All possibile functions are %s.' + % (pin, ', '.join(all_funcs))) + return ('', '') + else: + desc = '%s => %s, functions: %s' \ + % (pin, active_func, ', '.join(all_funcs)) + return (active_func, desc) + + def dump_pin(self, pin, out=sys.stdout, refresh=False): + if pin not in self.soc_gpio_table: + raise Exception('"%s" is not a valid pin' % pin) + + _, desc = self._get_one_pin(pin, refresh) + out.write('%s\n' % desc) + + def dump_function(self, func_name, out=sys.stdout, refresh=False): + if func_name not in self.functions: + raise Exception('"%s" is not a valid function name' % func_name) + pin = self.functions[func_name] + self.dump_pin(pin, out=out, refresh=refresh) + + def dump_functions(self, out=sys.stdout, refresh=False): + if refresh: + self._sync_from_hw() + + for pin in self.soc_gpio_table: + self.dump_pin(pin, out=out, refresh=False) + + def get_active_functions(self, refresh=False): + if refresh: + self._sync_from_hw() + + all = [] + for pin in self.soc_gpio_table: + active, _ = self._get_one_pin(pin, False) + all.append(active) + return all + + +GPIO_INPUT = 'input' +GPIO_OUT_HIGH = 'high' +GPIO_OUT_LOW = 'low' + +class BoardGPIO(object): + def __init__(self, gpio, shadow, value=GPIO_INPUT): + self.gpio = gpio + self.shadow = shadow + self.value = value diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_util.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_util.py new file mode 100644 index 0000000..e4b40b0 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_util.py @@ -0,0 +1,153 @@ +#!/usr/bin/python -tt +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from soc_gpio_table import soc_gpio_table + +import openbmc_gpio +import openbmc_gpio_table + +import argparse +import logging +import sys + + +def _get_gpio_table(): + gpio = openbmc_gpio_table.SocGPIOTable(soc_gpio_table) + return gpio + + +def dump_func(args): + gpio = _get_gpio_table() + gpio.dump_functions() + return 0 + + +def config_func(args): + gpio = _get_gpio_table() + try: + gpio.config_function(args.function) + except openbmc_gpio_table.NotSmartEnoughException as e: + print('The code is not smart enough to set function "%s": %s\n' + 'Please set the function manually.' + % (args.function, str(e))) + print('The current HW setting for this function is:') + gpio.dump_function(args.function) + return -1 + except Exception as e: + print('Failed to set function "%s": %s\n' + 'Please set the function manually.' + % (args.function, str(e))) + print('The current HW setting for this function is:') + gpio.dump_function(args.function) + logging.exception('Exception:') + return -2 + + print('Function "%s" is set' % args.function) + return 0 + + +def export_func(args): + openbmc_gpio.gpio_export(args.gpio, args.shadow) + + +def set_func(args): + openbmc_gpio.gpio_set(args.gpio, args.value, + change_direction=False if args.keep else True) + + +def get_func(args): + val = openbmc_gpio.gpio_get( + args.gpio, change_direction=False if args.keep else True) + print('%d' % val) + + +def info_func(args): + res = openbmc_gpio.gpio_info(args.gpio) + print('GPIO info for %s:' % args.gpio) + print('Path: %s\nShadow: %s\nDirection: %s\nValue: %s' + % (res['path'], res['shadow'], res['direction'], res['value'])) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('--debug', action='store_true', + help='Enable debug messages') + + subparser = ap.add_subparsers() + + dump_parser = subparser.add_parser( + 'dump', help='Dump the current HW GPIO settings') + dump_parser.set_defaults(func=dump_func) + + config_parser = subparser.add_parser( + 'config', help='Configure one HW pin to a function') + config_parser.add_argument( + 'function', help='The function name to set') + config_parser.set_defaults(func=config_func) + + export_parser = subparser.add_parser( + 'export', help='Export a GPIO directory') + export_parser.add_argument( + 'gpio', help='The GPIO name, i.e. "A4", or "GPIOD2"') + export_parser.add_argument( + 'shadow', default=None, + help='The shadow name given to this GPIO') + export_parser.set_defaults(func=export_func) + + + set_parser = subparser.add_parser( + 'set', help='Set a value for a GPIO') + set_parser.add_argument( + 'gpio', help='The GPIO name or number') + set_parser.add_argument( + 'value', type=int, choices=[0, 1], + help='The value to set') + set_parser.add_argument( + '-k', '--keep', action='store_true', + help='Keep the GPIO direction') + set_parser.set_defaults(func=set_func) + + get_parser = subparser.add_parser( + 'get', help='Get a GPIO\'s value') + get_parser.add_argument( + 'gpio', help='The GPIO name or number') + get_parser.add_argument( + '-k', '--keep', action='store_true', + help='Keep the GPIO direction') + get_parser.set_defaults(func=get_func) + + info_parser = subparser.add_parser( + 'info', help='Get a GPIO\'s info') + info_parser.add_argument( + 'gpio', help='The GPIO name or number') + info_parser.set_defaults(func=info_func) + + args = ap.parse_args() + + logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO, + format='%(asctime)s: %(message)s') + + return args.func(args) + + +rc = main() +sys.exit(rc) diff --git a/common/recipes-utils/openbmc-gpio/files/phymemory.py b/common/recipes-utils/openbmc-gpio/files/phymemory.py new file mode 100644 index 0000000..97a0d6e --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/phymemory.py @@ -0,0 +1,100 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import subprocess +import logging + + +class PhyMemory(object): + def __init__(self, addr, name=''): + self.addr = addr + self.name = name + self.write_pending = False + self.value = 0 + + def __del__(self): + if self.write_pending: + logging.warning('Value (0x%x) is not wrote back to address (0x%x)' + % (self.value, self.addr)) + + def __str__(self): + if self.name == '': + return '0x%x' % self.addr + else: + return self.name + + def _read_hw(self): + if self.write_pending: + raise Exception('Value (0x%x) is not wrote back to address (0x%x) ' + 'before reading HW' % (self.value, self.addr)) + cmd = ['devmem', '0x%x' % self.addr] + out = subprocess.check_output(cmd) + self.value = int(out, 16) + logging.debug('Read from %s @0x%x, got value (0x%x)' + % (str(self), self.addr, self.value)) + + def read(self, refresh=True): + if refresh: + self._read_hw() + return self.value + + def write(self, force=False): + if not force and not self.write_pending: + return + cmd = ['devmem', '0x%x' % self.addr, '32', '0x%x' % self.value] + subprocess.check_call(cmd) + self.write_pending = False + logging.debug('Wrote to %s address @0x%x with value (0x%x)' + % (str(self), self.addr, self.value)) + + def set_bit(self, bit, write_through=True): + assert 0 <= bit <= 31 + self.value |= 1 << bit + self.write_pending = True + logging.debug('Set bit %s[%d] (0x%x)' % (str(self), bit, self.value)) + if write_through: + self.write() + + def clear_bit(self, bit, write_through=True): + assert 0 <= bit <= 31 + self.value &= ~(1 << bit) + self.write_pending = True + logging.debug('Clear bit %s[%d] (0x%x)' % (str(self), bit, self.value)) + if write_through: + self.write() + + def is_bit_set(self, bit, refresh=False): + assert 0 <= bit <= 31 + self.read(refresh=refresh) + rc = True if self.value & (0x1 << bit) else False + logging.debug('Test bit %s[%d](0x%x): %s' + % (str(self), bit, self.value, rc)) + return rc + + def bits_value(self, bits, refresh=False): + self.read(refresh=refresh) + value = 0 + for bit in sorted(bits, reverse=True): + assert 0 <= bit <= 31 + value = (value << 1) | ((self.value >> bit) & 0x1) + logging.debug('%s%s is 0x%x (0x%x)' + % (str(self), bits, value, self.value)) + return value diff --git a/common/recipes-utils/openbmc-gpio/files/setup.py b/common/recipes-utils/openbmc-gpio/files/setup.py new file mode 100644 index 0000000..59c7de4 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/setup.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + + +from distutils.core import setup + +setup( + name = 'openbmc-gpio', + version = '1.0', + description = 'OpenBMC GPIO utilities', + author = 'Tian Fang', + author_email = 'tfang@fb.com', + license = 'GPLv2', + py_modules=['openbmc_gpio', + 'openbmc_gpio_table', + 'phymemory', + 'soc_gpio', + 'soc_gpio_table', + 'board_gpio_table', + ], +) diff --git a/common/recipes-utils/openbmc-gpio/files/soc_gpio.py b/common/recipes-utils/openbmc-gpio/files/soc_gpio.py new file mode 100644 index 0000000..2718af8 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/soc_gpio.py @@ -0,0 +1,19 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +def soc_get_register(addr): + raise Exception('Virtual function. Not implemented') diff --git a/common/recipes-utils/openbmc-gpio/files/soc_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/soc_gpio_table.py new file mode 100644 index 0000000..45713e9 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/soc_gpio_table.py @@ -0,0 +1,23 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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 in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +# This is an dummy SoC GPIO table. If this is included in the final image, +# please double check the configuration of your image to define the correct +# SoC GPIO table to be used for your board. + +soc_gpio_table = { +} |