summaryrefslogtreecommitdiffstats
path: root/meta-facebook/meta-wedge/recipes-wedge/fbutils/files
diff options
context:
space:
mode:
Diffstat (limited to 'meta-facebook/meta-wedge/recipes-wedge/fbutils/files')
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/COPYING340
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions222
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py260
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py178
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py452
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py260
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf37
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh41
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh83
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py124
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh61
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh105
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh72
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh49
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early25
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local26
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh36
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh349
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh99
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py49
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh37
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h362
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h59
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh47
-rwxr-xr-xmeta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh34
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh201
-rw-r--r--meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh29
27 files changed, 3637 insertions, 0 deletions
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/COPYING b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/COPYING
new file mode 100644
index 0000000..3912109
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/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/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions
new file mode 100644
index 0000000..dd53ad1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/ast-functions
@@ -0,0 +1,222 @@
+# Copyright 2014-present Facebook. All Rights Reserved.
+DEVMEM=/sbin/devmem
+
+devmem_set_bit() {
+ local addr
+ local val
+ addr=$1
+ val=$($DEVMEM $addr)
+ val=$((val | (0x1 << $2)))
+ $DEVMEM $addr 32 $val
+}
+
+devmem_clear_bit() {
+ local addr
+ local val
+ addr=$1
+ val=$($DEVMEM $addr)
+ val=$((val & ~(0x1 << $2)))
+ $DEVMEM $addr 32 $val
+}
+
+scu_addr() {
+ echo $((0x1E6E2000 + 0x$1))
+}
+
+GPIODIR="/sys/class/gpio"
+GPIOEXPORT="$GPIODIR/export"
+
+gpio_dir() {
+ echo "$GPIODIR/gpio$1"
+}
+
+gpio_name2value() {
+ local first remaining base val
+ remaining=$1
+ val=0
+ while [ -n "$remaining" ]; do
+ first=${remaining:0:1}
+ case "$first" in
+ [[:lower:]])
+ base=$(printf "%d" "'$first'")
+ base=$((base - 96))
+ val=$((val * 26 + base))
+ ;;
+ [[:upper:]])
+ base=$(printf "%d" "'$first'")
+ base=$((base - 64))
+ val=$((val * 26 + base))
+ ;;
+ *)
+ if [ $val -gt 0 ]; then
+ val=$((val-1))
+ fi
+ val=$((val * 8 + $remaining))
+ break
+ ;;
+ esac
+ remaining=${remaining:1}
+ done
+ echo "$val"
+}
+
+gpio_export() {
+ local gpio
+ gpio=$(gpio_name2value $1)
+ dir=$(gpio_dir $gpio)
+ if [ ! -d ${dir} ]; then
+ echo $gpio > $GPIOEXPORT
+ fi
+}
+
+gpio_set() {
+ local gpio
+ local val
+ gpio=$(gpio_name2value $1)
+ val=$2
+ dir=$(gpio_dir $gpio)
+ if [ ! -d ${dir} ]; then
+ echo $gpio > $GPIOEXPORT
+ fi
+ echo out > ${dir}/direction
+ echo $val > ${dir}/value
+}
+
+gpio_get() {
+ local gpio
+ local val
+ gpio=$(gpio_name2value $1)
+ dir=$(gpio_dir $gpio)
+ if [ ! -d ${dir} ]; then
+ echo $gpio > $GPIOEXPORT
+ fi
+ echo in > ${dir}/direction
+ cat ${dir}/value
+}
+
+wedge_iso_buf_enable() {
+ # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0
+ devmem_clear_bit $(scu_addr 90) 0
+ devmem_clear_bit $(scu_addr 90) 24
+ gpio_set 18 0
+}
+
+wedge_iso_buf_disable() {
+ # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0
+ devmem_clear_bit $(scu_addr 90) 0
+ devmem_clear_bit $(scu_addr 90) 24
+ gpio_set 18 1
+}
+
+wedge_is_us_on() {
+ local val n retries prog
+ if [ $# -gt 0 ]; then
+ retries="$1"
+ else
+ retries=1
+ fi
+ if [ $# -gt 1 ]; then
+ prog="$2"
+ else
+ prog=""
+ fi
+ n=1
+ while true; do
+ val=$(cat /sys/class/i2c-adapter/i2c-4/4-0040/gpio_inputs 2>/dev/null)
+ if [ -n "$val" ]; then
+ break
+ fi
+ n=$((n+1))
+ if [ $n -gt $retries ]; then
+ echo -n " failed to read GPIO. "
+ val=0
+ break
+ fi
+ echo -n "$prog"
+ sleep 1
+ done
+ if [ "$((val & (0x1 << 14)))" != "0" ]; then
+ # powered on already
+ return 0
+ else
+ return 1
+ fi
+}
+
+
+# Return the board type, 'LC', 'FC-LEFT', 'FC-RIGHT', or, 'WEDGE'
+wedge_board_type() {
+ local pn
+ pn=$(/usr/bin/weutil 2> /dev/null | grep -i '^Location on Fabric:')
+ case "$pn" in
+ *LEFT*)
+ echo 'FC-LEFT'
+ ;;
+ *RIGHT*)
+ echo 'FC-RIGHT'
+ ;;
+ *LC*)
+ echo 'LC'
+ ;;
+ *)
+ echo 'WEDGE'
+ ;;
+ esac
+}
+
+# On FC, FAB_SLOT_ID (GPIOU0), low == FC0; high == FC1
+# On LC, Wedge,
+# board rev < 3:
+# GPIOU0(ID0), GPIOU1(ID1), GPIOU2(ID2), GPIOU3(ID3)
+# else:
+# GPIOU6(ID0), GPIOU7(ID1), GPIOV0(ID2), GPIOV1(ID3)
+#
+# ID[2:0] ID3 Slot#
+# 000 0 1
+# 000 1 2
+# 001 0 3
+# 001 1 4
+# 010 0 5
+# 010 1 6
+# 011 0 7
+# 011 1 8
+
+wedge_slot_id() {
+ local type slot id3 id2 id1 id0 FC_CARD_BASE board_rev
+ FC_CARD_BASE=65
+ if [ "$1" = "FC-LEFT" ]; then
+ # fabric card left
+ slot=$(gpio_get U0)
+ slot=$((FC_CARD_BASE + slot * 2))
+ elif [ "$1" = "FC-RIGHT" ]; then
+ # fabric card right
+ slot=$(gpio_get U0)
+ slot=$((FC_CARD_BASE + slot * 2 + 1))
+ else
+ # either edge or LC
+ # need to check the board rev
+ board_rev=$(wedge_board_rev)
+ if [ $board_rev -lt 3 ]; then
+ id0=$(gpio_get U0)
+ id1=$(gpio_get U1)
+ id2=$(gpio_get U2)
+ id3=$(gpio_get U3)
+ else
+ id0=$(gpio_get U6)
+ id1=$(gpio_get U7)
+ id2=$(gpio_get V0)
+ id3=$(gpio_get V1)
+ fi
+ slot=$(((id2 * 4 + id1 * 2 + id0) * 2 + id3 + 1))
+ fi
+ echo "$slot"
+}
+
+# wedge_board_rev() is only valid after GPIO Y0, Y1, and Y2 are enabled
+wedge_board_rev() {
+ local val0 val1 val2
+ val0=$(cat /sys/class/gpio/gpio192/value 2>/dev/null)
+ val1=$(cat /sys/class/gpio/gpio193/value 2>/dev/null)
+ val2=$(cat /sys/class/gpio/gpio194/value 2>/dev/null)
+ echo $((val0 | (val1 << 1) | (val2 << 2)))
+}
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py
new file mode 100644
index 0000000..368b807
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46.py
@@ -0,0 +1,260 @@
+# Copyright 2004-present Facebook. All rights reserved.
+
+import subprocess
+import struct
+import sys
+
+class VerboseLogger:
+ def __init__(self, verbose=False):
+ self.verbose = verbose
+
+ def _verbose_print(self, caption, bytestream=None):
+ '''
+ Print a bytestream to stdout if verbose is enabled.
+ '''
+ if self.verbose:
+ if bytestream is not None:
+ sys.stderr.write("{}: {}\n".format(caption, " ".join(['{:02X}'.format(ord(x)) for x in bytestream])))
+ else:
+ sys.stderr.write("{}\n".format(caption))
+
+class AT93C46SPI(VerboseLogger):
+ '''The class to access AT93C46 through SPI intf'''
+ SPI_CMD = 'spi-bb'
+
+ def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di,
+ verbose=False):
+ if bus_width != 8 and bus_width != 16:
+ raise Exception("Invalid bus width for AT93C46!")
+
+ self.bus_width = bus_width
+ self.gpio_cs = gpio_cs
+ self.gpio_ck = gpio_ck
+ self.gpio_do = gpio_do
+ self.gpio_di = gpio_di
+ self.verbose = verbose
+
+ self.addr_bits = 6 if self.bus_width == 16 else 7
+ self.addr_mask = 0x3F if self.bus_width == 16 else 0x7F
+
+ def __shift(self, bytestream, value):
+ '''
+ Shift an entire byte stream by value bits.
+ '''
+ binary = "".join(['{:08b}'.format(ord(x)) for x in bytestream])
+ if value > 0:
+ binary = binary[value:] + '0' * value
+ else:
+ binary = '0' * (-value) + binary[:value]
+ return "".join([chr(int(binary[x:x+8],2)) for x in range(0, len(binary), 8)])
+
+ def __io(self, op, addr, data=None):
+ '''
+ Perform an IO operation against the EEPROM
+ '''
+ write_bits = self.addr_bits + 3
+ if data is not None:
+ # If giving data, we are doing a write command so
+ # no need to read any data.
+ write_bits = write_bits + self.bus_width
+ read_bits = 0
+ else:
+ # If not giving data, we are doing either a read
+ # command or a set command, so read the result.
+ # We pad with an extra bit due to a dummy bit introduced
+ # by a delay for address decoding on chip.
+ read_bits = self.addr_bits + 4 + self.bus_width
+
+ # Format the command itself
+ cmd_loc = 6 if self.bus_width == 16 else 7
+ instruction = addr & self.addr_mask
+ instruction = instruction | ((0x4 | (op & 0x3)) << cmd_loc)
+ if data is not None:
+ if self.bus_width == 16:
+ write_data = struct.pack(">HH", instruction, data & 0xFFFF)
+ else:
+ write_data = struct.pack(">HB", instruction, data & 0xFF)
+ else:
+ write_data = struct.pack(">H", instruction)
+ write_data = self.__shift(write_data, 16 - (cmd_loc + 3))
+
+ self._verbose_print("Write data", write_data)
+
+ # Run the command with the bitbang driver
+ if read_bits > 0:
+ data_portion = "-r {} -w {}".format(read_bits, write_bits)
+ else:
+ data_portion = "-w {}".format(write_bits)
+
+ cmd = "{} -s {} -c {} -o {} -i {} -b {}".format(
+ self.SPI_CMD, self.gpio_cs, self.gpio_ck, self.gpio_do,
+ self.gpio_di, data_portion
+ )
+
+ self._verbose_print("Command: {}".format(cmd))
+
+ out = subprocess.Popen(cmd.split(),
+ stdout=subprocess.PIPE,
+ stdin = subprocess.PIPE)\
+ .communicate(input=write_data)
+
+ # Format the response
+ read_data = self.__shift(out[0], cmd_loc + 4)
+ if self.bus_width == 16:
+ read_data = read_data[:2]
+ self._verbose_print("Read data", read_data)
+ return struct.unpack(">H", read_data)[0]
+ else:
+ read_data = read_data[:1]
+ self._verbose_print("Read data", read_data)
+ return struct.unpack(">B", read_data)[0]
+
+ def read(self, addr):
+ return self.__io(0x2, addr)
+
+ def ewen(self):
+ self.__io(0x0, 0x3 << (self.addr_bits - 2))
+
+ def erase(self, addr):
+ self.__io(0x3, addr)
+
+ def write(self, addr, data):
+ self.__io(0x1, addr, data)
+
+ def eral(self):
+ self.__io(0x0, 0x2 << (self.addr_bits - 2))
+
+ def wral(self, data):
+ self.__io(0x0, 0x1 << (self.addr_bits - 2), data)
+
+ def ewds(self):
+ self.__io(0x0, 0x0)
+
+class AT93C46(VerboseLogger):
+ '''
+ The class which handles accessing memory on the AT93C46 chip.
+ '''
+ AT93C46_MEMORY_SIZE = 128
+
+ def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di,
+ byte_swap, verbose=False):
+ self.bus_width = bus_width
+ self.verbose = verbose
+ self.byte_swap = byte_swap
+
+ self.spi = AT93C46SPI(bus_width=bus_width, gpio_cs=gpio_cs,
+ gpio_ck=gpio_ck, gpio_do=gpio_do,
+ gpio_di=gpio_di, verbose=verbose)
+
+ def __swap(self, value):
+ '''
+ Swap bytes for a 16-bit integer if instructed to do so.
+ '''
+ if self.bus_width == 16:
+ if self.byte_swap:
+ return ((value >> 8) & 0xFF) | ((value << 8) & 0xFF00)
+ else:
+ return value
+ else:
+ return value
+
+ def erase(self, offset=None, limit=None):
+ '''
+ Erase the chip.
+ '''
+ if offset is None:
+ offset = 0
+ if limit is None:
+ limit = self.AT93C46_MEMORY_SIZE
+
+ if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE:
+ raise Exception("Erase would be out of bounds!")
+ if self.bus_width == 16 and \
+ ((offset & 1) != 0 or ((offset + limit) & 1) != 0):
+ raise Exception("Erase can't start or end on odd boundary in 16-bit mode!")
+
+ if offset == 0 and limit == self.AT93C46_MEMORY_SIZE:
+ # Special case when we are erasing the entire chip
+ self.spi.ewen()
+ self.spi.eral()
+ self.spi.ewds()
+
+ self._verbose_print("Erased entire chip")
+ else:
+ # Regular case
+ if self.bus_width == 16:
+ real_offset = offset / 2
+ real_limit = limit / 2
+ else:
+ real_offset = offset
+ real_limit = limit
+
+ self.spi.ewen()
+ for addr in range(real_offset, real_offset + real_limit):
+ self.spi.erase(addr)
+ self.spi.ewds()
+
+ self._verbose_print("Erased {} bytes from offset {}".format(limit, offset))
+
+ def read(self, offset=None, limit=None):
+ '''
+ Read the chip into a memory buffer.
+ '''
+ if offset is None:
+ offset = 0
+ if limit is None:
+ limit = self.AT93C46_MEMORY_SIZE
+
+ if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE:
+ raise Exception("Read would be out of bounds!")
+ if self.bus_width == 16 and \
+ ((offset & 1) != 0 or ((offset + limit) & 1) != 0):
+ raise Exception("Read can't start or end on odd boundary in 16-bit mode!")
+
+ output = ""
+ if self.bus_width == 16:
+ real_offset = offset / 2
+ real_limit = limit / 2
+ pack_instruction = "=H"
+ else:
+ real_offset = offset
+ real_offset
+ pack_instruction = "=B"
+
+ for addr in range(real_offset, real_offset + real_limit):
+ output = output + struct.pack(pack_instruction, self.__swap(self.spi.read(addr)))
+
+ self._verbose_print("Read {} bytes from offset {}".format(limit, offset), output)
+
+ return output
+
+ def write(self, data, offset=None):
+ '''
+ Write a memory buffer to the chip.
+ '''
+ if offset is None:
+ offset = 0
+
+ if offset < 0 or offset + len(data) > self.AT93C46_MEMORY_SIZE:
+ raise Exception("Write would be out of bounds!")
+ if self.bus_width == 16 and \
+ ((offset & 1) != 0 or ((offset + len(data)) & 1) != 0):
+ raise Exception("Write can't start or end on odd boundary in 16-bit mode!")
+
+ if self.bus_width == 16:
+ offset_divisor = 2
+ pack_instruction = "=H"
+ else:
+ offset_divisor = 1
+ pack_instruction = "=B"
+
+ self.spi.ewen()
+ for addr in range(offset, offset + len(data), offset_divisor):
+ actual_addr = addr / offset_divisor
+ value = self.__swap(struct.unpack(pack_instruction, data[(addr - offset):(addr - offset) + offset_divisor])[0])
+
+ self.spi.erase(actual_addr)
+ self.spi.write(actual_addr, value)
+ self.spi.ewds()
+
+ self._verbose_print("Wrote {} bytes from offset {}".format(len(data), offset), data)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py
new file mode 100755
index 0000000..8910002
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93c46_util.py
@@ -0,0 +1,178 @@
+#!/usr/bin/python -S
+# Copyright 2004-present Facebook. All rights reserved.
+
+from argparse import ArgumentParser
+from at93c46 import AT93C46, AT93C46SPI
+import sys
+
+def get_raw(args):
+ return AT93C46SPI(args.bus_width, args.cs, args.clk, args.mosi, args.miso,
+ args.verbose)
+
+def get_chip(args):
+ return AT93C46(args.bus_width, args.cs, args.clk, args.mosi, args.miso,
+ args.byte_swap, args.verbose)
+
+def access_parser(ap):
+ # Default, based on currenct HW configuration
+ SPI_CS_DEFAULT = 68
+ SPI_CLK_DEFAULT = 69
+ SPI_MOSI_DEFAULT = 70
+ SPI_MISO_DEFAULT = 71
+
+ spi_group = ap.add_argument_group('SPI Access')
+ spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT,
+ help='The GPIO number for SPI CS pin (default: %s)'
+ % SPI_CS_DEFAULT)
+ spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT,
+ help='The GPIO number for SPI CLK pin (default: %s)'
+ % SPI_CLK_DEFAULT)
+ spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT,
+ help='The GPIO number for SPI MOSI pin (default: %s)'
+ % SPI_MOSI_DEFAULT)
+ spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT,
+ help='The GPIO number for SPI MISO pin (default: %s)'
+ % SPI_MISO_DEFAULT)
+
+def bus_width_parser(ap):
+ # Default, based on currenct HW configuration
+ AT83C46_BUS_WIDTH = 16
+
+ bus_group = ap.add_argument_group('Bus Width')
+ bus_group.add_argument('--bus-width', type=int, default=AT83C46_BUS_WIDTH,
+ help='The configured bus width (default: %s)'
+ % AT83C46_BUS_WIDTH)
+
+def read_raw(args):
+ raw = get_raw(args)
+ val = raw.read(args.address)
+
+ if args.int:
+ print "{}".format(val)
+ else:
+ if args.bus_width == 16:
+ print "0x{:04X}".format(val)
+ else:
+ print "0x{:02X}".format(val)
+
+def write_raw(args):
+ if args.value[:2] == "0x":
+ value = int(args.value, 16)
+ else:
+ value = int(args.value)
+
+ raw = get_raw(args)
+ raw.ewen()
+ raw.erase(args.address)
+ raw.write(args.address, value)
+ raw.ewds()
+
+def erase_raw(args):
+ raw = get_raw(args)
+ raw.ewen()
+ raw.erase(args.address)
+ raw.ewds()
+
+def raw_subparser(subparsers):
+ raw_parser = subparsers.add_parser('raw', help='Raw memory access')
+ raw_sub = raw_parser.add_subparsers()
+
+ read_parser = raw_sub.add_parser('read', help='Read a single memory address')
+ read_parser.add_argument('address', type=int, help='The memory address')
+ read_parser.add_argument('--int', action='store_true',
+ help='Display output as an integer')
+ read_parser.set_defaults(func=read_raw)
+
+ write_parser = raw_sub.add_parser('write', help='Write a single memory address')
+ write_parser.add_argument('address', type=int, help='The memory address')
+ write_parser.add_argument('value', type=str, help='The value to write, either integer or hex')
+ write_parser.set_defaults(func=write_raw)
+
+ erase_parser = raw_sub.add_parser('erase', help='Erase a single memory address')
+ erase_parser.add_argument('address', type=int, help='The memory address')
+ erase_parser.set_defaults(func=erase_raw)
+
+def read_chip(args):
+ chip = get_chip(args)
+ data = chip.read(args.start, args.length)
+
+ if args.file is None:
+ sys.stdout.write(data)
+ else:
+ fp = open(args.file, "wb")
+ fp.write(data)
+
+def write_chip(args):
+ chip = get_chip(args)
+
+ # Either way, limit reads to the size of the chip
+ if args.file is None:
+ data = sys.stdin.read(AT93C46.AT93C46_MEMORY_SIZE)
+ else:
+ fp = open(args.file, "rb")
+ data = fp.read(AT93C46.AT93C46_MEMORY_SIZE)
+
+ if args.length is not None:
+ # Make sure length is correct
+ if len(data) < args.length:
+ data = data + '\x00' * (args.length - len(data))
+ if len(data) > args.length:
+ data = data[:args.length]
+
+ chip.write(data, args.start)
+
+def erase_chip(args):
+ chip = get_chip(args)
+ chip.erase(args.start, args.length)
+
+def chip_subparser(subparsers):
+ chip_parser = subparsers.add_parser('chip', help='Chip-level access')
+ chip_sub = chip_parser.add_subparsers()
+
+ read_parser = chip_sub.add_parser('read', help='Read from the chip')
+ read_parser.add_argument('--start', type=int,
+ help='The memory address to start at (default: 0)')
+ read_parser.add_argument('--length', type=int,
+ help='The number of bytes to read (default: whole chip)')
+ read_parser.add_argument('--file', type=str,
+ help='File to operate on (default: stdout)')
+ read_parser.add_argument('--byte-swap', action='store_true',
+ help='Byte swap values for 16-bit reads/writes')
+ read_parser.set_defaults(func=read_chip)
+
+ write_parser = chip_sub.add_parser('write', help='Write to the chip')
+ write_parser.add_argument('--start', type=int,
+ help='The memory address to start at (default: 0)')
+ write_parser.add_argument('--length', type=int,
+ help='The number of bytes to write (default: file length)')
+ write_parser.add_argument('--file', type=str,
+ help='File to operate on (default: stdin)')
+ write_parser.add_argument('--byte-swap', action='store_true',
+ help='Byte swap values for 16-bit reads/writes')
+ write_parser.set_defaults(func=write_chip)
+
+ erase_parser = chip_sub.add_parser('erase', help='Erase the chip')
+ erase_parser.add_argument('--start', type=int,
+ help='The memory address to start at (default: 0)')
+ erase_parser.add_argument('--length', type=int,
+ help='The number of bytes to erase (default: whole chip)')
+ erase_parser.set_defaults(func=erase_chip)
+
+if __name__ == "__main__":
+ # General arguments
+ ap = ArgumentParser()
+ ap.add_argument('--verbose', action='store_true',
+ help='Print verbose debugging information')
+
+ # SPI and bus width arguments
+ access_parser(ap)
+ bus_width_parser(ap)
+
+ # Functionality
+ subparsers = ap.add_subparsers()
+ raw_subparser(subparsers)
+ chip_subparser(subparsers)
+
+ # Command runner
+ args = ap.parse_args()
+ args.func(args)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py
new file mode 100644
index 0000000..e1aba47
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py
@@ -0,0 +1,452 @@
+#
+# Copyright 2004-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
+#
+
+import subprocess
+import time
+
+class Bcm5396MDIO:
+ '''The class to access BCM5396 through MDIO intf'''
+ MDIO_CMD = 'mdio-bb'
+
+ PHYADDR = 0x1E
+
+ ACCESS_CTRL_REG = 16
+ IO_CTRL_REG = 17
+ STATUS_REG = 18
+ DATA0_REG = 24
+ DATA1_REG = 25
+ DATA2_REG = 26
+ DATA3_REG = 27
+
+ def __init__(self, mdc, mdio):
+ self.mdc = mdc
+ self.mdio = mdio
+ self.page = -1
+
+ def __io(self, op, reg, val=0):
+ cmd = '%s -p -c %s -d %s %s %s %s' \
+ % (self.MDIO_CMD, self.mdc, self.mdio, op, str(self.PHYADDR),
+ str(reg))
+ if op == 'write':
+ cmd += ' %s' % val
+ out = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)\
+ .communicate()[0]
+ if op == 'write':
+ return val
+ # need to parse the result for read
+ rc = 0
+ for line in out.split('\n'):
+ if not line.startswith('Read:'):
+ continue
+ rc = int(line.split(':')[1], 0)
+ return rc
+
+ def __read_mdio(self, reg):
+ return self.__io('read', reg)
+
+ def __write_mdio(self, reg, val):
+ return self.__io('write', reg, val)
+
+ def __set_page(self, page):
+ if self.page == page:
+ return
+ # Write MII register ACCESS_CTRL_REG:
+ # set bit 0 as "1" to enable MDIO access
+ # set "page number to bit 15:8
+ val = 0x1 | ((page & 0xff) << 8)
+ self.__write_mdio(self.ACCESS_CTRL_REG, val)
+ self.page = page
+
+ def __wait_for_done(self):
+ # Read MII register IO_CTRL_REG:
+ # Check op_code = "00"
+ while (self.__read_mdio(self.IO_CTRL_REG) & 0x3):
+ time.sleep(0.010) # 10ms
+
+ def read(self, page, reg, n_bytes):
+ self.__set_page(page)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "00"
+ # set "Register Address" to bit 15:8
+ val = 0x00 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "10"
+ # set "Register Address" to bit 15:8
+ val = 0x2 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ self.__wait_for_done()
+ # Read MII register DATA0_REG for bit 15:0
+ val = long(self.__read_mdio(self.DATA0_REG))
+ # Read MII register DATA1_REG for bit 31:16
+ val |= self.__read_mdio(self.DATA1_REG) << 16
+ # Read MII register DATA2_REG for bit 47:32
+ val |= self.__read_mdio(self.DATA2_REG) << 32
+ # Read MII register DATA3_REG for bit 63:48
+ val |= self.__read_mdio(self.DATA3_REG) << 48
+ return val
+
+ def write(self, page, reg, val, n_bytes):
+ self.__set_page(page)
+ # Write MII register DATA0_REG for bit 15:0
+ self.__write_mdio(self.DATA0_REG, val & 0xFFFF)
+ # Write MII register DATA1_REG for bit 31:16
+ self.__write_mdio(self.DATA1_REG, (val >> 16) & 0xFFFF)
+ # Write MII register DATA2_REG for bit 47:32
+ self.__write_mdio(self.DATA2_REG, (val >> 32) & 0xFFFF)
+ # Write MII register DATA3_REG for bit 63:48
+ self.__write_mdio(self.DATA3_REG, (val >> 48) & 0xFFFF)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "00"
+ # set "Register Address" to bit 15:8
+ val = 0x00 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ # Write MII register IO_CTRL_REG:
+ # set "Operation Code as "01"
+ # set "Register Address" to bit 15:8
+ val = 0x1 | ((reg & 0xff) << 8)
+ self.__write_mdio(self.IO_CTRL_REG, val)
+ self.__wait_for_done()
+
+
+class Bcm5396SPI:
+ '''The class to access BCM5396 through SPI interface'''
+ SPI_CMD = 'spi-bb'
+
+ READ_CMD = 0x60
+ WRITE_CMD = 0x61
+
+ SPI_STS_DIO = 0xF0
+ SPI_STS_REG = 0xFE
+ SPI_STS_REG_RACK = 0x1 << 5
+ SPI_STS_REG_SPIF = 0x1 << 7
+ PAGE_REG = 0xFF
+
+ def __init__(self, cs, clk, mosi, miso):
+ self.cs = cs
+ self.clk = clk
+ self.mosi = mosi
+ self.miso = miso
+ self.page = -1
+
+ def __bytes2val(self, values):
+ # LSB first, MSB last
+ pos = 0
+ result = 0L
+ for byte in values:
+ if type(byte) is str:
+ byte = int(byte, 16)
+ if byte > 255:
+ raise Exception('%s is not a byte in the list %s'\
+ % (byte, values))
+ result |= byte << pos
+ pos += 8
+ return result
+
+ def __val2bytes(self, value, n):
+ result = []
+ for _ in range(n):
+ result.append(value & 0xFF)
+ value >>= 8
+ if value > 0:
+ raise Exception('Value, %s, is too large for %s bytes'
+ % (value, n))
+ return result
+
+ def __io(self, bytes_to_write, to_read=0):
+ # TODO: check parameters
+ cmd = '%s -s %s -S low -c %s -o %s -i %s '\
+ % (self.SPI_CMD, self.cs, self.clk, self.mosi, self.miso)
+ if len(bytes_to_write):
+ write_cmd = '-w %s %s '\
+ % (len(bytes_to_write) * 8,
+ ' '.join([str(byte) for byte in bytes_to_write]))
+ else:
+ write_cmd = ''
+ if to_read:
+ # spi-bb will first return the exact number of bits used for
+ # writing. So, total number of bits to read should also include
+ # the number of bits written.
+ cmd += '-r %s ' % str((len(bytes_to_write) + to_read) * 8)
+ cmd += write_cmd
+ rc = 0L
+ out = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)\
+ .communicate()[0]
+ if to_read:
+ # need to parse the result
+ for line in out.split('\n'):
+ if not line.startswith('Read'):
+ continue
+ res = line.split(':')[1]
+ rc = self.__bytes2val(res.split()[len(bytes_to_write):])
+ break
+ return rc
+
+ def __set_page(self, page):
+ page &= 0xff
+ if self.page == page:
+ return
+ self.__io([self.WRITE_CMD, self.PAGE_REG, page])
+ self.page = page
+
+ def __read_spi_reg(self, reg):
+ reg &= 0xFF
+ return self.__io([self.READ_CMD, reg], 1)
+
+ def __read_spi_sts(self):
+ return self.__read_spi_reg(self.SPI_STS_REG)
+
+ def __read_spi_dio(self):
+ return self.__read_spi_reg(self.SPI_STS_DIO)
+
+ def read(self, page, reg, n_bytes):
+ '''Read a register value from a page.'''
+ if n_bytes > 8:
+ print('TODO to support reading more than 8 bytes')
+ return 0
+ if page > 0xff or reg > 0xff:
+ print('Page and register must be <= 255')
+ return 0
+ try:
+ self.__set_page(page)
+ self.__io([self.READ_CMD, reg], 1)
+ while True:
+ # check sts
+ sts = self.__read_spi_sts()
+ if sts & self.SPI_STS_REG_RACK:
+ break
+ bytes = []
+ for _ in range(n_bytes):
+ bytes.append(self.__read_spi_dio())
+ except Exception as e:
+ print(e)
+ return self.__bytes2val(bytes)
+
+ def write(self, page, reg, val, n_bytes):
+ '''Write a value as n bytes to a register on a page.'''
+ if page > 0xff or reg > 0xff:
+ print('Page and register must be <= 255')
+ return
+ bytes = self.__val2bytes(val, n_bytes)
+ if len(bytes) > 8:
+ print('TODO to support writing more than 8 bytes')
+ return
+ bytes = [self.WRITE_CMD, reg] + bytes
+ try:
+ self.__set_page(page)
+ self.__io(bytes)
+ except Exception as e:
+ print(e)
+
+class Bcm5396:
+ '''The class for BCM5396 Switch'''
+
+ MDIO_ACCESS = 0
+ SPI_ACCESS = 1
+
+ def __init__(self, access, **kwargs):
+ if access == self.MDIO_ACCESS:
+ self.access = Bcm5396MDIO(**kwargs)
+ else:
+ self.access = Bcm5396SPI(**kwargs)
+
+ def write(self, page, reg, value, n_bytes):
+ return self.access.write(page, reg, value, n_bytes)
+
+ def read(self, page, reg, n_bytes):
+ return self.access.read(page, reg, n_bytes)
+
+ def __add_remove_vlan(self, add, vid, untag, fwd, spt):
+ VLAN_PAGE = 0x5
+ CTRL_ADDR = 0x60
+ CTRL_START_DONE = (0x1 << 7)
+ VID_ADDR = 0x61
+ ENTRY_ADDR = 0x63
+
+ fwd_map = self.__ports2portmap(fwd)
+ untag_map = self.__ports2portmap(untag)
+
+ # mark it as write and stop the previous action
+ ctrl = 0
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ # write entry
+ if (add):
+ entry = 0x1L | ((spt & 0x1F) << 1) \
+ | (fwd_map << 6) | (untag_map << 23)
+ else:
+ entry = 0x0L
+ self.write(VLAN_PAGE, ENTRY_ADDR, entry, 8)
+ # write vid as the index
+ self.write(VLAN_PAGE, VID_ADDR, vid & 0xFFF, 2)
+ # start the write
+ ctrl = CTRL_START_DONE
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ while True:
+ ctrl = self.read(VLAN_PAGE, CTRL_ADDR, 1)
+ if not (ctrl & CTRL_START_DONE):
+ # done
+ break
+ time.sleep(0.010) # 10ms
+
+ def add_vlan(self, vid, untag, fwd, spt=0):
+ return self.__add_remove_vlan(True, vid, untag, fwd, spt)
+
+ def remove_vlan(self, vid):
+ return self.__add_remove_vlan(False, vid, [], [], 0)
+
+ def get_vlan(self, vid):
+ VLAN_PAGE = 0x5
+ CTRL_ADDR = 0x60
+ CTRL_START_DONE = (0x1 << 7)
+ CTRL_READ = 0x1
+ VID_ADDR = 0x61
+ ENTRY_ADDR = 0x63
+
+ # mark it as read and stop the previous action
+ ctrl = CTRL_READ
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ # write the vid as the index
+ self.write(VLAN_PAGE, VID_ADDR, vid & 0xFFF, 2)
+ # start the read
+ ctrl = CTRL_READ|CTRL_START_DONE
+ self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1)
+ while True:
+ ctrl = self.read(VLAN_PAGE, CTRL_ADDR, 1)
+ if not (ctrl & CTRL_START_DONE):
+ # done
+ break
+ time.sleep(0.010) # 10ms
+ entry = self.read(VLAN_PAGE, ENTRY_ADDR, 8)
+ res = {}
+ res['valid'] = True if entry & 0x1 else False
+ res['spt'] = (entry >> 1) & 0x1f
+ res['fwd'] = self.__portmap2ports((entry >> 6) & 0x1ffff)
+ res['untag'] = self.__portmap2ports((entry >> 23) & 0x1ffff)
+ return res
+
+ def __portmap2ports(self, port_map):
+ return list(set([port if port_map & (0x1 << port) else None
+ for port in range (0, 17)])
+ - set([None]))
+
+ def __ports2portmap(self, ports):
+ port_map = 0
+ for port in ports:
+ port_map |= (0x1 << port)
+ return port_map & 0x1FFFF
+
+ def __parse_arl_result(self, vid, result):
+ is_bitset = lambda bit: True if result & (0x1 << bit) else False
+ if not is_bitset(3):
+ return None
+ res = {}
+ # parse vid first
+ res['vid'] = (vid >> 48) & 0xfff
+ mac_val = vid & 0xffffffffffffL
+ mac_list = []
+ for pos in range(5, -1, -1):
+ mac_list.append('{:02x}'.format((mac_val >> (pos * 8)) & 0xff))
+ res['mac'] = ':'.join(mac_list)
+ if mac_val & (0x1 << 40):
+ res['ports'] = self.__portmap2ports((result >> 6) & 0xffff)
+ else:
+ res['ports'] = [(result >> 6) & 0xf]
+ res['static'] = is_bitset(5)
+ res['age'] = is_bitset(4)
+ res['valid'] = is_bitset(3)
+ res['priority'] = result & 0x7
+ return res
+
+ def get_all_arls(self):
+ ARL_PAGE = 0x5
+ SEARCH_CTRL_ADDR = 0x30
+ SEARCH_CTRL_START_DONE = (0x1 << 7)
+ SEARCH_CTRL_SR_VALID = (0x1)
+
+ VID0_ADDR = 0x33
+ RESULT0_ADDR = 0x3B
+ VID1_ADDR = 0x40
+ RESULT1_ADDR = 0x48
+
+ all = []
+ # write START to search control
+ ctrl = SEARCH_CTRL_START_DONE
+ self.write(ARL_PAGE, SEARCH_CTRL_ADDR, ctrl, 1)
+ while True:
+ ctrl = self.read(ARL_PAGE, SEARCH_CTRL_ADDR, 1)
+ if not (ctrl & SEARCH_CTRL_START_DONE):
+ # Done
+ break
+ if not (ctrl & SEARCH_CTRL_SR_VALID):
+ # result is not ready, sleep and retry
+ time.sleep(0.010) # 10ms
+ continue
+ for vid_addr, result_addr in [[VID1_ADDR, RESULT1_ADDR],
+ [VID0_ADDR, RESULT0_ADDR]]:
+ vid = self.read(ARL_PAGE, vid_addr, 8)
+ result = self.read(ARL_PAGE, result_addr, 4)
+ one = self.__parse_arl_result(vid, result)
+ if one:
+ all.append(one)
+ return all
+
+ def vlan_ctrl(self, enable):
+ VLAN_CTRL_PAGE = 0x34
+ VLAN_CTRL0_REG = 0x0
+ VLAN_CTRL0_B_EN_1QVLAN = 0x1 << 7
+
+ ctrl = self.read(VLAN_CTRL_PAGE, VLAN_CTRL0_REG, 1)
+ need_write = False
+ if enable:
+ if not ctrl & VLAN_CTRL0_B_EN_1QVLAN:
+ need_write = True;
+ ctrl |= VLAN_CTRL0_B_EN_1QVLAN
+ else:
+ if ctrl & VLAN_CTRL0_B_EN_1QVLAN:
+ need_write = True;
+ ctrl &= (~VLAN_CTRL0_B_EN_1QVLAN) & 0xFF
+ if need_write:
+ self.write(VLAN_CTRL_PAGE, VLAN_CTRL0_REG, ctrl, 1)
+
+ def vlan_set_port_default(self, port, vid, pri=0):
+ VLAN_PORT_PAGE = 0x34
+ VLAN_PORT_REG_BASE = 0x10
+
+ if port < 0 or port > 16:
+ raise Exception('Invalid port number %s' % port)
+ if pri < 0 or pri > 7:
+ raise Exception('Invalid priority %s' % pri)
+ if vid < 0 or vid > 0xFFF:
+ raise Exception('Invalid VLAN %s' % vid)
+ reg = VLAN_PORT_REG_BASE + port * 2
+ ctrl = (pri << 13) | vid
+ self.write(VLAN_PORT_PAGE, reg, ctrl, 2)
+
+ def vlan_get_port_default(self, port):
+ VLAN_PORT_PAGE = 0x34
+ VLAN_PORT_REG_BASE = 0x10
+
+ if port < 0 or port > 16:
+ raise Exception('Invalid port number %s' % port)
+ reg = VLAN_PORT_REG_BASE + port * 2
+ val = self.read(VLAN_PORT_PAGE, reg, 2)
+ res = {}
+ res['priority'] = (val >> 13) & 0x7
+ res['vid'] = val & 0xFFF
+ return res
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py
new file mode 100644
index 0000000..1496412
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py
@@ -0,0 +1,260 @@
+#!/usr/bin/python
+# Copyright 2004-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 argparse import ArgumentParser
+from bcm5396 import Bcm5396
+
+def auto_long(x):
+ return long(x, 0)
+
+def auto_int(x):
+ return int(x, 0)
+
+def get_bcm(args):
+ if args.spi:
+ return Bcm5396(Bcm5396.SPI_ACCESS, cs=args.cs, clk=args.clk,
+ mosi=args.mosi, miso=args.miso)
+ else:
+ return Bcm5396(Bcm5396.MDIO_ACCESS, mdc=args.mdc, mdio=args.mdio)
+
+
+def read_register(args):
+ bcm = get_bcm(args)
+ val = bcm.read(args.page, args.register, args.size)
+ print('Read from BCM5396 ({}:{}.{}): {}'
+ .format(hex(args.page), hex(args.register), args.size, hex(val)))
+
+def write_register(args):
+ bcm = get_bcm(args)
+ val = bcm.write(args.page, args.register, args.value, args.size)
+ print('Write to BCM5396 ({}.{}): {}'
+ .format(hex(args.page), hex(args.register), hex(args.value)))
+
+def register_parser(subparser):
+ reg_parser = subparser.add_parser('register', help='Register IO')
+ reg_sub = reg_parser.add_subparsers()
+
+ read_parser = reg_sub.add_parser('read', help='read switch register')
+ read_parser.set_defaults(func=read_register)
+ read_parser.add_argument('page', type=auto_int,
+ help='The page of the register')
+ read_parser.add_argument('register', type=auto_int,
+ help='The register to read from')
+ read_parser.add_argument('size', type=auto_int,
+ help='Number of bytes',
+ choices=range(1, 9))
+
+ write_parser = reg_sub.add_parser('write', help='write switch register')
+ write_parser.set_defaults(func=write_register)
+ write_parser.add_argument('page', type=auto_int,
+ help='The page oof the register')
+ write_parser.add_argument('register', type=auto_int,
+ help='The register to write to')
+ write_parser.add_argument('value', type=auto_long,
+ help='The value to write')
+ write_parser.add_argument('size', type=auto_int,
+ help='Number of bytes',
+ choices=range(1, 9))
+
+
+def dump_arl(args):
+ bcm = get_bcm(args)
+ arls = bcm.get_all_arls()
+ print('All ARLs are:')
+ for entry in arls:
+ print(entry)
+
+def arl_parser(subparser):
+ dump_parser = subparser.add_parser('arl', help='dump all ARL entries')
+ dump_parser.set_defaults(func=dump_arl)
+
+
+def __parse_port_list(parm):
+ '''Parse the port numbers to a list'''
+ if len(parm) == 0:
+ return []
+ ports=[]
+ for port in parm.split(','):
+ idx = port.find('-')
+ if idx == -1:
+ p = int(port)
+ if p < 0 or p > 15:
+ raise Exception('Invalid port number %s' % p)
+ # just one port
+ ports.append(p)
+ else:
+ start = int(port[:idx])
+ end = int(port[idx+1:])
+ if start > end or start < 0 or end > 15:
+ raise Exception('Invalid port range %s-%s' % (start, end))
+ ports.extend(range(start, end + 1))
+ return ports
+
+def enable_vlan(args):
+ bcm = get_bcm(args)
+ bcm.vlan_ctrl(True)
+ print('VLAN function is enabled.')
+
+def disable_vlan(args):
+ bcm = get_bcm(args)
+ bcm.vlan_ctrl(False)
+ print('VLAN function is disabled.')
+
+def add_vlan(args):
+ bcm = get_bcm(args)
+ vid = args.vid
+ fwd = sorted(__parse_port_list(args.fwd))
+ untag = sorted(__parse_port_list(args.untag))
+ spt = args.spt
+ # make sure untag is subset of fwd
+ if not set(untag).issubset(set(fwd)):
+ raise Exception('Some untagged ports, %s, are not part of forward ports'
+ % (set(untag) - set(fwd)))
+ bcm.add_vlan(vid, untag, fwd, spt)
+ print('Added VLAN: %s' % vid)
+ print('Ports in VLAN: %s' % sorted(fwd))
+ print('Ports without VLAN tag: %s' % sorted(untag))
+
+def remove_vlan(args):
+ bcm = get_bcm(args)
+ vid = args.vid
+ bcm.remove_vlan(vid)
+ print('Removed VLAN: %s' % vid)
+
+def show_vlan(args):
+ bcm = get_bcm(args)
+ vid = args.vid
+ vlan = bcm.get_vlan(vid)
+ if not vlan['valid']:
+ print('VLAN %s does not exist' % vid)
+ else:
+ print('VLAN: %s' % vid)
+ print('Spanning tree index: %s' % vlan['spt'])
+ print('Ports in VLAN: %s' % sorted(vlan['fwd']))
+ print('Untagged ports in VLAN: %s' % sorted(vlan['untag']))
+
+def set_port_vlan(args):
+ bcm = get_bcm(args)
+ bcm.vlan_set_port_default(args.port, args.vid, args.pri)
+ print('Set VLAN default for port: %s' % args.port)
+ print('Default VLAN: %s' % args.vid)
+ print('Default priority %s' % args.pri)
+
+def get_port_vlan(args):
+ bcm = get_bcm(args)
+ port = bcm.vlan_get_port_default(args.port)
+ print('Get VLAN default for port: %s' % args.port)
+ print('Default VLAN: %s' % port['vid'])
+ print('Default priority: %s' % port['priority'])
+
+def vlan_parser(subparser):
+ UNTAG_DEFAULT = ''
+ SPT_DEFAULT = 0
+ PRI_DEFAULT = 0
+
+ vlan_parser = subparser.add_parser('vlan', help='Manage vlan function')
+ vlan_sub = vlan_parser.add_subparsers()
+
+ add_parser = vlan_sub.add_parser('add', help='Add or modify a VLAN entry')
+ add_parser.add_argument('vid', type=int, help='The VLAN ID')
+ add_parser.add_argument('fwd', type=str,
+ help='Ports belonging to this VLAN. i.e. 1,4,5-8')
+ add_parser.add_argument('untag', type=str, default=UNTAG_DEFAULT, nargs='?',
+ help='Ports that do not add VLAN tag. i.e. 1,4,5-8'
+ ' (default: all ports are tagged)')
+ add_parser.add_argument('spt', type=int, default=SPT_DEFAULT, nargs='?',
+ help='Spanning tree index (default: %s)'
+ % SPT_DEFAULT)
+ add_parser.set_defaults(func=add_vlan)
+
+ remove_parser = vlan_sub.add_parser('remove', help='Remove a VLAN entry')
+ remove_parser.add_argument('vid', type=int, help='The VLAN ID')
+ remove_parser.set_defaults(func=remove_vlan)
+
+ show_parser = vlan_sub.add_parser('show', help='Show a VLAN entry')
+ show_parser.add_argument('vid', type=int, help='The VLAN ID')
+ show_parser.set_defaults(func=show_vlan)
+
+ enable_parser = vlan_sub.add_parser('enable', help='Enable VLAN function')
+ enable_parser.set_defaults(func=enable_vlan)
+
+ disable_parser = vlan_sub.add_parser('disable', help='Enable VLAN function')
+ disable_parser.set_defaults(func=disable_vlan)
+
+ port_parser = vlan_sub.add_parser('port',
+ help='Set/Get VLAN default for a port')
+ port_sub = port_parser.add_subparsers()
+ set_port = port_sub.add_parser('set', help='Set VLAN default for a port')
+ set_port.add_argument('port', type=int, help='The port number (0..16)')
+ set_port.add_argument('vid', type=int,
+ help='The default VLAN for this port')
+ set_port.add_argument('pri', type=int, default=PRI_DEFAULT, nargs='?',
+ help='The default priority for this port '
+ '(default: %s)' % PRI_DEFAULT)
+ set_port.set_defaults(func=set_port_vlan)
+
+ get_port = port_sub.add_parser('get', help='Get VLAN default for a port')
+ get_port.add_argument('port', type=int, help='The port number (0..16)')
+ get_port.set_defaults(func=get_port_vlan)
+
+def access_parser(ap):
+ SPI_CS_DEFAULT = 68
+ SPI_CLK_DEFAULT = 69
+ SPI_MOSI_DEFAULT = 70
+ SPI_MISO_DEFAULT = 71
+
+ MDIO_MDC_DEFAULT = 6
+ MDIO_MDIO_DEFAULT = 7
+
+ spi_group = ap.add_argument_group('SPI Access')
+ spi_group.add_argument('--spi', action='store_true',
+ help='Access through SPI.')
+ spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT,
+ help='The GPIO number for SPI CS pin (default: %s)'
+ % SPI_CS_DEFAULT)
+ spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT,
+ help='The GPIO number for SPI CLK pin (default: %s)'
+ % SPI_CLK_DEFAULT)
+ spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT,
+ help='The GPIO number for SPI MOSI pin (default: %s)'
+ % SPI_MOSI_DEFAULT)
+ spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT,
+ help='The GPIO number for SPI MISO pin (default: %s)'
+ % SPI_MISO_DEFAULT)
+ mdio_group = ap.add_argument_group('MDIO Access (default)')
+ mdio_group.add_argument('--mdc', type=int, default=MDIO_MDC_DEFAULT,
+ help='The GPIO number for MDC pin (default: %s)'
+ % MDIO_MDC_DEFAULT)
+ mdio_group.add_argument('--mdio', type=int, default=MDIO_MDIO_DEFAULT,
+ help='The GPIO number for MDIO pin (default: %s)'
+ % MDIO_MDIO_DEFAULT)
+ return ap
+
+
+if __name__ == '__main__':
+ ap = ArgumentParser()
+ access_parser(ap)
+
+ subparsers = ap.add_subparsers()
+ register_parser(subparsers)
+ arl_parser(subparsers)
+ vlan_parser(subparsers)
+ args = ap.parse_args()
+
+ args.func(args)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf
new file mode 100644
index 0000000..2cf7a9a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+# only care about 'eth0' and 'oob' intf
+[ "$IFACE" != "eth0" ] && [ "$IFACE" != "oob" ] && exit 0
+
+. /usr/local/fbpackages/utils/ast-functions
+
+board=$(wedge_board_type)
+
+[ "$board" = "WEDGE" ] && exit 0
+
+vlan=4088
+intf="${IFACE}.${vlan}"
+slot=$(wedge_slot_id $board)
+
+vconfig add $IFACE $vlan
+ifconfig $intf up "fe80::$(printf "%x" $slot):1/64"
+
+exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh
new file mode 100644
index 0000000..1cdbcb6
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+### BEGIN INIT INFO
+# Provides: eth0_mac_fixup.sh
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Fixup the MAC address for eth0 based on wedge EEPROM
+### END INIT INFO
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+mac=$(weutil 2>/dev/null | grep '^Local MAC' 2>/dev/null | cut -d' ' -f3 2>/dev/null)
+
+if [ -n "$mac" ]; then
+ ifconfig eth0 hw ether $mac
+ # compare the 'ethaddr' from u-boot env
+ ethaddr=$(fw_printenv ethaddr 2>/dev/null | cut -d'=' -f2 2>/dev/null)
+ if [ "$ethaddr" != "$mac" ]; then
+ fw_setenv "ethaddr" "$mac"
+ fi
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh
new file mode 100755
index 0000000..53e24f3
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/fcswitcher.sh
@@ -0,0 +1,83 @@
+#! /bin/sh
+#
+# Copyright 2014-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
+#
+
+### BEGIN INIT INFO
+# Provides: usbcons
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop: 0 6
+# Short-Description: Creates a virtual USB serial device and starts a console
+# on it.
+#
+### END INIT INFO
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+NAME="FC Switcher"
+DESC="FC Failover Daemon"
+
+# source function library
+. /etc/init.d/functions
+
+. /usr/local/fbpackages/utils/ast-functions
+
+STOPPER=
+ACTION="$1"
+
+case "$ACTION" in
+ start)
+ if [ "$(wedge_board_type)" = "LC" ]; then
+ # Ability to prevent this from starting by editing cmdline in u-boot.
+ # Keeping this here until I get gadget switching working properly. (t4906522)
+ /usr/local/bin/watch-fc.sh > /dev/null 2>&1 &
+ echo "$NAME."
+ else
+ echo 'skipping watch-fc.sh: only necessary on six-pack line cards.'
+ fi
+ ;;
+ stop)
+ echo -n "Stopping $DESC: "
+ killall watch-fc.sh
+ echo "$NAME."
+ ;;
+ restart|force-reload)
+ echo -n "Restarting $DESC: "
+ killall watch-fc.sh
+ if [ "$(wedge_board_type)" = "LC" ]; then
+ sleep 1
+ /usr/local/bin/watch-fc.sh > /dev/null 2>&1 &
+ echo "$NAME."
+ else
+ echo 'skipping watch-fc.sh: only necessary on six-pack line cards.'
+ fi
+ ;;
+ status)
+ status watch-fc.sh
+ exit $?
+ ;;
+ *)
+ N=${0##*/}
+ N=${N#[SK]??}
+ echo "Usage: $N {start|stop|status|restart|force-reload}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py
new file mode 100755
index 0000000..aa7d4bf
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mdio.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+#
+# Copyright 2014-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 argparse import ArgumentParser
+import subprocess
+import time
+
+IO_BASE = [ 0x1e660000, 0x1e680000 ]
+PHYCR_REG_OFFSET = 0x60
+PHYCR_READ_BIT = 0x1 << 26
+PHYCR_WRITE_BIT = 0x1 << 27
+phycr_reg = lambda mac: IO_BASE[mac - 1] + PHYCR_REG_OFFSET
+PHYDATA_REG_OFFSET = 0x64
+phydata_reg = lambda mac: IO_BASE[mac - 1] + PHYDATA_REG_OFFSET
+
+
+devmem_read_cmd = lambda reg: [ 'devmem', hex(reg) ]
+devmem_write_cmd = lambda reg, val: [ 'devmem', hex(reg), '32', hex(val)]
+
+
+def devmem_read(reg):
+ cmd = devmem_read_cmd(reg)
+ #print('Cmd: {}'.format(cmd))
+ out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
+ return int(out, 0)
+
+
+def devmem_write(reg, val):
+ cmd = devmem_write_cmd(reg, val)
+ #print('Cmd: {}'.format(cmd))
+ subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
+
+
+def wait_for_mdio_done(args):
+ reg = phycr_reg(args.mac)
+ while devmem_read(reg) & (PHYCR_READ_BIT|PHYCR_WRITE_BIT):
+ time.sleep(0.010) # 10ms
+
+
+def read_mdio(args):
+ reg = phycr_reg(args.mac)
+ ctrl = devmem_read(reg)
+ ctrl &= 0x3000003f
+ ctrl |= (args.phy & 0x1F) << 16
+ ctrl |= (args.register & 0x1F) << 21
+ ctrl |= PHYCR_READ_BIT
+ devmem_write(reg, ctrl)
+ wait_for_mdio_done(args)
+ val = devmem_read(phydata_reg(args.mac)) >> 16
+ print('Read from PHY ({}.{}): {}'
+ .format(hex(args.phy), hex(args.register), hex(val)))
+
+
+def write_mdio(args):
+ ctrl_reg = phycr_reg(args.mac)
+ ctrl = devmem_read(ctrl_reg)
+ ctrl &= 0x3000003f
+ ctrl |= (args.phy & 0x1F) << 16
+ ctrl |= (args.register & 0x1F) << 21
+ ctrl |= PHYCR_WRITE_BIT
+ data_reg = phydata_reg(args.mac)
+ # write data first
+ devmem_write(data_reg, args.value)
+ # then ctrl
+ devmem_write(ctrl_reg, ctrl)
+ wait_for_mdio_done(args)
+ print('Write to PHY ({}.{}): {}'
+ .format(hex(args.phy), hex(args.register), hex(args.value)))
+
+
+def auto_int(x):
+ return int(x, 0)
+
+if __name__ == '__main__':
+ ap = ArgumentParser()
+ ap.add_argument('--mac', '-m', type=int, default=2,
+ help='The MAC')
+ ap.add_argument('--phy', '-p', type=auto_int, default=0x1f,
+ help='The PHY address')
+
+ subparsers = ap.add_subparsers()
+
+ read_parser = subparsers.add_parser('read',
+ help='read MDIO')
+ read_parser.set_defaults(func=read_mdio)
+ read_parser.add_argument('register', type=auto_int,
+ help='The register to read from')
+
+ write_parser = subparsers.add_parser('write',
+ help='write MDIO')
+ write_parser.set_defaults(func=write_mdio)
+ write_parser.add_argument('register', type=auto_int,
+ help='The register to write to')
+ write_parser.add_argument('value', type=auto_int,
+ help='The value to write to')
+
+ args = ap.parse_args()
+
+ if args.mac != 2 and args.mac != 1:
+ print("MAC can only be either 1 or 2.")
+ exit(-1)
+
+ if args.phy > 0x1f:
+ printf("PHY address must be smaller than 0x1f.")
+ exit(-2)
+
+ args.func(args)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh
new file mode 100755
index 0000000..6986be5
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/mount_data0.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# Copyright 2014-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
+#
+
+### BEGIN INIT INFO
+# Provides: mount_data0
+# Required-Start: mountvirtfs
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Mount data0 partition from flash chip.
+# Description:
+### END INIT INFO
+
+. /etc/default/rcS
+
+# Find out which device maps to 'data0' on mtd
+# Note: /proc/mtd lists partitions using mtdX, where X is a number,
+# but we mount using /dev/mtdblockX. We'll do some magic here
+# to get the mtdX (char device) and mtdblockX (block device)
+# names.
+MOUNT_POINT="/mnt/data"
+DATA_CHAR_DEV=$(cat /proc/mtd | awk '{ if ($4 == "\"data0\"") print $1 }' |
+ cut -d ':' -f 1 | awk '{ print "/dev/" $1 }')
+if [ -z "$DATA_CHAR_DEV" ]
+then
+ echo "No data0 partition found. Not mounting anything to $MOUNT_POINT."
+else
+ DEVICE_ID=$(echo $DATA_CHAR_DEV | tail -c 2)
+ DATA_BLOCK_DEV=${DATA_CHAR_DEV/mtd/mtdblock}
+
+ echo "data0 partition found on $DATA_BLOCK_DEV; mounting to $MOUNT_POINT."
+ mount -t jffs2 $DATA_BLOCK_DEV $MOUNT_POINT
+
+ # if the mount failed, format the partition and remount
+ if [ $? -ne 0 ]
+ then
+ echo "Mount failed; formatting $DATA_BLOCK_DEV and remounting."
+ flash_eraseall $DATA_CHAR_DEV
+ mount -t jffs2 $DATA_BLOCK_DEV $MOUNT_POINT
+ fi
+fi
+
+: exit 0
+
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh
new file mode 100644
index 0000000..c23349f
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+#
+# Copyright 2004-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
+#
+
+usage() {
+ echo "Displays values onto the debug header LEDs."
+ echo "Hex and decimal accepted."
+ echo "Usage: $0 <value>"
+}
+
+. /usr/local/fbpackages/utils/ast-functions
+
+# Function to set the less significant hex digit
+display_lower() {
+ local bit0=$(expr $1 % 2)
+ local bit1=$(expr $1 / 2 % 2)
+ local bit2=$(expr $1 / 4 % 2)
+ local bit3=$(expr $1 / 8 % 2)
+
+ # Set the pins to the correct operating mode.
+ # The relevant pins are GPIOG[0...3].
+ # For GPIO bank G, SCU84[0..3] must be 0.
+ devmem_clear_bit $(scu_addr 84) 0
+ devmem_clear_bit $(scu_addr 84) 1
+ devmem_clear_bit $(scu_addr 84) 2
+ devmem_clear_bit $(scu_addr 84) 3
+
+ # Now set the GPIOs to the right binary values
+ gpio_set 48 $bit0
+ gpio_set 49 $bit1
+ gpio_set 50 $bit2
+ gpio_set 51 $bit3
+}
+
+# Function to set the more significant hex digit
+display_upper() {
+ local bit0=$(expr $1 % 2)
+ local bit1=$(expr $1 / 2 % 2)
+ local bit2=$(expr $1 / 4 % 2)
+ local bit3=$(expr $1 / 8 % 2)
+
+ # Set the pins to the correct operating mode.
+ # The relevant pins are GPIOB[4...7].
+ # GPIOB4: SCU80[12] = 0 and Strap[14] = 0
+ # GPIOB5: SCU80[13] = 0
+ # GPIOB6: SCU80[14] = 0
+ # GPIOB7: SCU80[15] = 0
+ devmem_clear_bit $(scu_addr 70) 14
+ devmem_clear_bit $(scu_addr 80) 12
+ devmem_clear_bit $(scu_addr 80) 13
+ devmem_clear_bit $(scu_addr 80) 14
+ devmem_clear_bit $(scu_addr 80) 15
+
+ gpio_set 12 $bit0
+ gpio_set 13 $bit1
+ gpio_set 14 $bit2
+ gpio_set 15 $bit3
+}
+
+# Check number of parameters
+if [ $# -ne 1 ]
+then
+ usage
+ exit 1
+fi
+
+# Make sure input is actually numeric
+DEC_VALUE=$(printf "%d" $1 2>/dev/null)
+if [ $? -eq 1 ]
+then
+ echo "Unable to parse input as numeric value."
+ exit 1
+fi
+
+# Make sure input is within proper range
+if [ $DEC_VALUE -lt 0 ] || [ $DEC_VALUE -gt 255 ]
+then
+ echo "Value $DEC_VALUE is outside of displayable range 0 - 0xff (255)."
+ exit 1
+fi
+
+# Get upper/lower decimal values
+LOWER_DEC_VALUE=$(expr $DEC_VALUE % 16)
+UPPER_DEC_VALUE=$(expr $DEC_VALUE / 16)
+
+# Display the results
+display_lower $LOWER_DEC_VALUE
+display_upper $UPPER_DEC_VALUE
+
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh
new file mode 100644
index 0000000..843b79a
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# Copyright 2014-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
+
+### BEGIN INIT INFO
+# Provides: power-on
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Power on micro-server
+### END INIT INFO
+. /usr/local/fbpackages/utils/ast-functions
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+echo -n "Checking microserver power status ... "
+if wedge_is_us_on 10 "."; then
+ echo "on"
+ on=1
+else
+ echo "off"
+ on=0
+fi
+
+if [ $on -eq 0 ]; then
+ # Reset USB hub
+ /usr/local/bin/reset_usb.sh
+ # Set up ROV
+ /usr/local/bin/setup_rov.sh
+ # Configure the management switch on LEFT side of FC.
+ # Must do so after setup_rov.sh, as setup_rov.sh might reset
+ # T2, which also resets the switch.
+ if [ "$(wedge_board_type)" = "FC-LEFT" ]; then
+ echo -n "Configure management switch ... "
+ if [ $(wedge_board_rev) -gt 1 ]; then
+ echo "skip. Need new switch setup script!!!"
+ else
+ # configure MDIO as GPIO output
+ gpio_set A6 1
+ gpio_set A7 1
+ # set the switch to be configured by CPU
+ gpio_set E2 1
+ # set the switch to be configured by CPU, then reset the switch,
+ # which also cause T2 reset in the current board
+ gpio_set E2 1
+ gpio_set C0 0
+ sleep 1
+ gpio_set C0 1
+ # configure the switch
+ setup_switch.py
+ echo "done"
+ fi
+ fi
+ # Power on now
+ wedge_power.sh on -f
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh
new file mode 100755
index 0000000..20206a1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+usage() {
+ echo "Usage: $1 <on | off>"
+ exit -1
+}
+
+. /usr/local/fbpackages/utils/ast-functions
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+set -e
+
+if [ $# != 1 ]; then
+ usage $0
+fi
+
+if [ $1 = "on" ]; then
+ val=1
+elif [ $1 = "off" ]; then
+ val=0
+else
+ usage $0
+fi
+
+# To use GPIOE5 (37), SCU80[21], SCU8C[14], and SCU70[22] must be 0
+devmem_clear_bit $(scu_addr 80) 21
+devmem_clear_bit $(scu_addr 8C) 14
+devmem_clear_bit $(scu_addr 70) 22
+
+gpio_set 37 $val
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early
new file mode 100644
index 0000000..0f47c72
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.early
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright 2014-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 script will be executed at rcS S04 level, which is right after mount /mnt/data
+# and before almost anything else.
+
+if [ -x /mnt/data/etc/rc.early ]; then
+ /mnt/data/etc/rc.early
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local
new file mode 100644
index 0000000..36fa0f1
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/rc.local
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright 2014-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 script will be executed *after* all the other init scripts.
+
+if [ -x /mnt/data/etc/rc.local ]; then
+ /mnt/data/etc/rc.local
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh
new file mode 100644
index 0000000..7d1c2c6
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright 2014-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
+#
+
+. /usr/local/fbpackages/utils/ast-functions
+
+echo -n "Reset USB Switch ... "
+
+# To use GPIOD7 (31), SCU90[1], SCU8C[11], and SCU70[21] must be 0
+devmem_clear_bit $(scu_addr 8C) 11
+devmem_clear_bit $(scu_addr 70) 21
+devmem_clear_bit $(scu_addr 90) 1
+
+gpio_set 31 1
+sleep 1
+gpio_set 31 0
+sleep 1
+gpio_set 31 1
+
+echo "Done"
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh
new file mode 100755
index 0000000..9f0b543
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh
@@ -0,0 +1,349 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+### BEGIN INIT INFO
+# Provides: gpio-setup
+# Required-Start:
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Set up GPIO pins as appropriate
+### END INIT INFO
+
+# This file contains definitions for the GPIO pins that were not otherwise
+# defined in other files. We should probably move some more of the
+# definitions to this file at some point.
+
+# The commented-out sections are generally already defined elsewhere,
+# and defining them twice generates errors.
+
+# The exception to this is the definition of the GPIO H0, H1, and H2
+# pins, which seem to adversely affect the rebooting of the system.
+# When defined, the system doesn't reboot cleanly. We're still
+# investigating this.
+
+. /usr/local/fbpackages/utils/ast-functions
+
+# Set up to read the board revision pins, Y0, Y1, Y2
+devmem_set_bit $(scu_addr 70) 19
+devmem_clear_bit $(scu_addr a4) 8
+devmem_clear_bit $(scu_addr a4) 9
+devmem_clear_bit $(scu_addr a4) 10
+echo 192 > /sys/class/gpio/export
+echo 193 > /sys/class/gpio/export
+echo 194 > /sys/class/gpio/export
+
+# enabled Y0, Y1, Y2, we can use wedge_board_rev() now
+board_rev=$(wedge_board_rev)
+
+# Set up ISO_SVR_ID[0-3], GPION[2-5]
+# On wedge, these 4 GPIOs are not connected. And the corresponding
+# 4 pins from uS are strapped to low.
+# On fabic, these 4 pins are connected to uS SVR_ID pins,
+# which are used to set the uS FPGA i2c address.
+# Force all pins to low to have the same uS FPGA i2c address on wedge
+# and fabric
+# To use GPION[2-5], SCU90[4:5] must be 0, and SCU88[2-5] must be 0 also
+devmem_clear_bit $(scu_addr 90) 4
+devmem_clear_bit $(scu_addr 90) 5
+devmem_clear_bit $(scu_addr 88) 2
+devmem_clear_bit $(scu_addr 88) 3
+devmem_clear_bit $(scu_addr 88) 4
+devmem_clear_bit $(scu_addr 88) 5
+gpio_set 106 0
+gpio_set 107 0
+gpio_set 108 0
+gpio_set 109 0
+
+## CARD_EN, GPIO C3
+#devmem_clear_bit $(scu_addr 90) 0
+#devmem_clear_bit $(scu_addr 90) 24
+#echo 18 > /sys/class/gpio/export
+
+# T2_RESET_N, RESET_SEQ0, RESET_SEQ1, on GPIO C0, F2, and F3
+devmem_clear_bit $(scu_addr 90) 0
+devmem_clear_bit $(scu_addr 90) 23
+devmem_clear_bit $(scu_addr 80) 26
+devmem_clear_bit $(scu_addr a4) 13
+devmem_clear_bit $(scu_addr 80) 27
+devmem_clear_bit $(scu_addr a4) 14
+devmem_set_bit $(scu_addr 70) 19
+echo 16 > /sys/class/gpio/export
+echo 42 > /sys/class/gpio/export
+echo 43 > /sys/class/gpio/export
+# output
+
+# PANTHER_PRSNT_N, uServer presence, on GPIO E4
+devmem_clear_bit $(scu_addr 80) 20
+devmem_clear_bit $(scu_addr 8c) 14
+devmem_clear_bit $(scu_addr 70) 22
+echo 36 > /sys/class/gpio/export
+
+# MRSRVR_SYS_RST, reset the uServer, on GPIO C1
+devmem_clear_bit $(scu_addr 90) 0
+devmem_clear_bit $(scu_addr 90) 23
+echo 17 > /sys/class/gpio/export
+# output
+
+# BMC_PWR_BTN_IN_N, uServer power button in, on GPIO D0
+# BMC_PWR_BTN_OUT_N, uServer power button out, on GPIO D1
+devmem_clear_bit $(scu_addr 90) 1
+devmem_clear_bit $(scu_addr 8c) 8
+devmem_clear_bit $(scu_addr 70) 21
+echo 24 > /sys/class/gpio/export
+# we have to ensure that BMC_PWR_BTN_OUT_N is high so that
+# when we enable the isolation buffer, uS will not be powered down
+gpio_set 25 1
+
+## BMC_READY_IN, BMC signal that it's up, on GPIO P7
+# To use GPIOP7 (127), SCU88[23] must be 0
+devmem_clear_bit $(scu_addr 88) 23
+# Put GPIOP7 (127) to low so that we can control uS power now
+# This must be after 'gpio_set 25 1'
+gpio_set 127 0
+
+# PANTHER_I2C_ALERT_N, alert for uServer I2C, GPIO B0
+devmem_clear_bit $(scu_addr 80) 8
+echo 8 > /sys/class/gpio/export
+
+# MNSERV_NIC_SMBUS_ALRT, alert for uServer NIC, GPIO B1
+devmem_clear_bit $(scu_addr 80) 9
+echo 9 > /sys/class/gpio/export
+
+# LED_PWR_BLUE, blue power light, GPIO E5
+devmem_clear_bit $(scu_addr 80) 21
+devmem_clear_bit $(scu_addr 8c) 14
+devmem_clear_bit $(scu_addr 70) 22
+echo 37 > /sys/class/gpio/export
+# output
+
+# BMC_HEARTBEAT_N, heartbeat LED, GPIO Q7
+devmem_clear_bit $(scu_addr 90) 28
+echo 135 > /sys/class/gpio/export
+# output
+
+# XXX: setting those causes the system to lock up on reboot
+## T2 ROV1, ROV2, ROV3 -- voltage reading, GPIOs H0, H1, and H2
+#devmem_clear_bit $(scu_addr 90) 6
+#devmem_clear_bit $(scu_addr 90) 7
+#devmem_clear_bit $(scu_addr 70) 4
+## Do I need to set 70:1 and 70:0 to 1?
+echo 56 > /sys/class/gpio/export
+echo 57 > /sys/class/gpio/export
+echo 58 > /sys/class/gpio/export
+
+# HOTSWAP_PG, hotswap issues, GPIO L3
+devmem_clear_bit $(scu_addr 90) 5
+devmem_clear_bit $(scu_addr 90) 4
+devmem_clear_bit $(scu_addr 84) 19
+echo 99 > /sys/class/gpio/export
+
+# XXX: These interfere with i2c bus 11 (on Linux, it's 12 on the hardware)
+# which we need to talk to the power supplies on certain hardware.
+## Hardware presence pins C4 and C5
+#devmem_clear_bit $(scu_addr 90) 0
+#devmem_clear_bit $(scu_addr 90) 24
+#echo 20 > /sys/class/gpio/export
+#echo 21 > /sys/class/gpio/export
+
+# FAB_GE_SEL, uServer GE connection, GPIO A0
+devmem_clear_bit $(scu_addr 80) 0
+echo 0 > /sys/class/gpio/export
+# output
+
+# USB_OCS_N1, resettable fuse tripped, GPIO Q6
+devmem_clear_bit $(scu_addr 90) 28
+echo 136 > /sys/class/gpio/export
+
+# RX loss signal?
+
+# System SPI
+# Strap 12 must be 0 and Strape 13 must be 1
+devmem_clear_bit $(scu_addr 70) 12
+devmem_set_bit $(scu_addr 70) 13
+# GPIOQ4 is ISO_FLASH_WP, must be 1 to avoid write protection
+# GPIOQ5 is ISO_FLASH_HOLD, must be 1 to be out of reset
+# To use GPIOQ4 and GPIOQ5, SCU90[27] must be 0
+devmem_clear_bit $(scu_addr 90) 27
+gpio_set 134 1
+gpio_set 135 1
+# GPIOD6 is ISO_FL_PRG_SEL, set it to 0 so that BMC does not have control
+# on the EEPROM by default.
+# To use GPIOD6, SCU90[1] must be 0, SCU8C[21] must be 0, and Strap[21] must be 0
+devmem_clear_bit $(scu_addr 90) 1
+devmem_clear_bit $(scu_addr 8c) 8
+devmem_clear_bit $(scu_addr 70) 21
+gpio_set 30 0
+
+# DEBUG_RST_BTN_N, Debug Reset button on front panel, GPIO R2
+devmem_clear_bit $(scu_addr 88) 26
+echo 138 > /sys/class/gpio/export
+
+# DEBUG_PORT_UART_SEL_N, Debug Select button, GPIO B2
+devmem_clear_bit $(scu_addr 80) 10
+echo 10 > /sys/class/gpio/export
+
+# DEBUG_UART_SEL_0, select uServer UART to the debug header, GPIO E0
+devmem_clear_bit $(scu_addr 80) 16
+devmem_clear_bit $(scu_addr 8c) 12
+devmem_clear_bit $(scu_addr 70) 22
+echo 32 > /sys/class/gpio/export
+# output
+
+# RS485 transceiver TX/RX toggle (RTS) pin, GPIOF5
+devmem_clear_bit $(scu_addr 80) 29
+echo 45 > /sys/class/gpio/export
+gpio_set 45 0
+
+# Bloodhound GPIOs, P0-6, G4, J1-3, Y3
+# Make sure GPIOP0,1,2,3,6 are enabled.
+for i in {16..19} 22; do
+ devmem_clear_bit $(scu_addr 88) $i
+done
+# Enable GPIOY3
+devmem_clear_bit $(scu_addr a4) 11
+# GPIOG4
+devmem_clear_bit $(scu_addr 2c) 1
+# GPIOJ1
+devmem_clear_bit $(scu_addr 84) 9
+# GPIOJ2
+devmem_clear_bit $(scu_addr 84) 10
+# GPIOJ11
+devmem_clear_bit $(scu_addr 84) 11
+
+# Export all the GPIOs
+for i in {120..126} 52 {73..75} 195; do
+ echo $i > /sys/class/gpio/export
+done
+
+# Enable the isolation buffer
+wedge_iso_buf_enable
+
+# Get the board type by parsing the EEPROM.
+# This must be after enabling isolation buffer as the i2c bus
+# is isolated by the buffer
+board_type=$(wedge_board_type)
+
+case "$board_type" in
+ FC-LEFT|FC-RIGHT)
+ # On FC
+ # FAB_SLOT_ID is GPIOU0
+ # PEER_FAB_PRSNT is GPIOU1
+ devmem_set_bit $(scu_addr a0) 8
+ devmem_set_bit $(scu_addr a0) 9
+ gpio_export U0
+ gpio_export U1
+ # T2_POWER_UP is GPIOT6
+ devmem_set_bit $(scu_addr a0) 6
+ gpio_export T6
+ # HS_FAULT_N is GPIOT7
+ devmem_set_bit $(scu_addr a0) 7
+ gpio_export T7
+ if [ "$board_type" = "FC-LEFT" ]; then
+ # GPIOE2 is CPU_EEPROM_SEL, on FC-LEFT
+ devmem_clear_bit $(scu_addr 80) 18
+ devmem_clear_bit $(scu_addr 8c) 13
+ devmem_clear_bit $(scu_addr 70) 22
+ gpio_export E2
+ # GPIOA6 and GPIOA7 are MAC2 MDIO pins, we use them as
+ # GPIO for bitbang driver
+ devmem_clear_bit $(scu_addr 90) 2
+ devmem_clear_bit $(scu_addr 80) 6
+ devmem_clear_bit $(scu_addr 80) 7
+ gpio_export A6
+ gpio_export A7
+ fi
+ ;;
+ *)
+ # Set up to watch for FC presence, and switch between interfaces.
+ # GPIOC0..C7, interested in C4, C5
+ devmem_clear_bit $(scu_addr 90) 0
+ devmem_clear_bit $(scu_addr 90) 25
+ if [ $board_rev -lt 3 ]; then
+ # Prior to DVTC
+ # BP_SLOT_ID GPIO pins are U0, U1, U2, U3
+ devmem_set_bit $(scu_addr a0) 8
+ devmem_set_bit $(scu_addr a0) 9
+ devmem_set_bit $(scu_addr a0) 10
+ devmem_set_bit $(scu_addr a0) 11
+ gpio_export U0
+ gpio_export U1
+ gpio_export U2
+ gpio_export U3
+ # T2_POWER_UP is GPIOT6
+ devmem_set_bit $(scu_addr a0) 6
+ gpio_export T6
+ # HS_FAULT_N is GPIOT7
+ devmem_set_bit $(scu_addr a0) 7
+ gpio_export T7
+ else
+ # Starting from DVTC
+ # BP_SLOT_ID GPIO pins are U6, U7, V0, V1
+ devmem_set_bit $(scu_addr 70) 6
+ devmem_set_bit $(scu_addr a0) 14
+ devmem_set_bit $(scu_addr a0) 15
+ devmem_set_bit $(scu_addr a0) 16
+ devmem_set_bit $(scu_addr a0) 17
+ gpio_export U6
+ gpio_export U7
+ gpio_export V0
+ gpio_export V1
+ # T2_POWER_UP is GPIOU4
+ devmem_set_bit $(scu_addr a0) 12
+ gpio_export U4
+ # HS_FAULT_N is GPIOU5
+ devmem_set_bit $(scu_addr a0) 13
+ gpio_export U5
+ fi
+ ;;
+esac
+
+# Make it possible to turn off T2 if fand sees overheating via GPIOF1
+# Do not change the GPIO direction here as the default value of this GPIO
+# is low, which causes a Non-maskable interrupt to the uS.
+devmem_clear_bit $(scu_addr 80) 25
+devmem_clear_bit $(scu_addr a4) 12
+echo 41 > /sys/class/gpio/export
+
+# Allow us to set the fan LEDs boards.
+# This is GPIO G5, G6, G7, and J0
+
+devmem_clear_bit $(scu_addr 70) 23
+devmem_clear_bit $(scu_addr 84) 5
+devmem_clear_bit $(scu_addr 84) 6
+devmem_clear_bit $(scu_addr 84) 7
+devmem_clear_bit $(scu_addr 84) 8
+
+echo 53 > /sys/class/gpio/export
+echo 54 > /sys/class/gpio/export
+echo 55 > /sys/class/gpio/export
+echo 72 > /sys/class/gpio/export
+echo "out" > /sys/class/gpio/gpio53/direction
+echo "out" > /sys/class/gpio/gpio54/direction
+echo "out" > /sys/class/gpio/gpio55/direction
+echo "out" > /sys/class/gpio/gpio72/direction
+
+# Once we set "out", output values will be random unless we set them
+# to something
+
+echo "0" > /sys/class/gpio/gpio53/value
+echo "0" > /sys/class/gpio/gpio54/value
+echo "0" > /sys/class/gpio/gpio55/value
+echo "0" > /sys/class/gpio/gpio72/value
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh
new file mode 100755
index 0000000..749fe65
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+# The T2 chip can prefer different input voltages, depending, presumably
+# of manufacturing variations. We need to determine whether it wants
+# 0.95V or 1.025V, reset the T2 to reduce total power usage, set the
+# outgoing voltage on the first buck converter, and bring T2 up out of
+# reset.
+
+. /usr/local/fbpackages/utils/ast-functions
+
+# read the T2 ROV after the GPIOs are enabled
+t2_rov() {
+ local val0 val1 val2
+ # Note that the values are *not* read in order.
+ val0=$(cat /sys/class/gpio/gpio58/value 2>/dev/null)
+ val1=$(cat /sys/class/gpio/gpio56/value 2>/dev/null)
+ val2=$(cat /sys/class/gpio/gpio57/value 2>/dev/null)
+ echo $((val0 | (val1 << 1) | (val2 << 2)))
+}
+
+rov=$(t2_rov)
+
+# target_volts come from the data sheet and 18mV of loss and
+# some fudging based on actual measurements to get either 1.025V
+# or 0.95V at T2
+if [ $rov -eq 1 ]; then
+ target_volts=0x5a
+elif [ $rov -eq 2 ]; then
+ target_volts=0x65
+else
+ echo "Unrecognized T2 ROV value $rov, setting failed."
+ exit 1
+fi
+target_volts=$(( $target_volts * 1 )) # normalize to decimal
+
+# We shouldn't have to rmmod pmbus, because it hasn't been loaded yet,
+# but if the script is rerun after the system is up, it may be necessary.
+rmmod pmbus
+reload=$?
+
+# Get current voltage value
+cur_volts=$(i2cget -y 1 0x60 0x8b w)
+cur_volts=$(( $cur_volts * 1 )) # normalize to decimal
+
+# Only bounce the T2 if we actually need to modify the voltage
+if [ $cur_volts -ne $target_volts ]; then
+ # Set values before turning out output; we're using "PCIE, then MCS"
+ echo 1 > /sys/class/gpio/gpio42/value
+ echo 1 > /sys/class/gpio/gpio43/value
+ echo out > /sys/class/gpio/gpio42/direction
+ echo out > /sys/class/gpio/gpio43/direction
+ echo 0 > /sys/class/gpio/gpio16/value
+ echo out > /sys/class/gpio/gpio16/direction
+ # T2 is in reset; note that this may cause NMI messages on the uServer,
+ # which shouldn't be up anyway when this is first run.
+
+ # Set the requested value to the current value to avoid rapid shifts
+ i2cset -y 1 0x60 0x21 $cur_volts w
+ # Enable the requested voltage
+ i2cset -y 1 0x60 0xd2 0x5a
+ i2cset -y 1 0x60 0xd3 0x5a
+ sleep 1
+
+ # Set the target voltage
+ i2cset -y 1 0x60 0x21 $target_volts w
+
+ sleep 1
+
+ # Let T2 come out of reset
+ echo 1 > /sys/class/gpio/gpio16/value
+ echo "T2 ROV value set based on $rov."
+ sleep 2
+ echo 0 > /sys/class/gpio/gpio42/value
+ echo 0 > /sys/class/gpio/gpio43/value
+else
+ echo "T2 ROV already correctly set."
+fi
+# Bring back pmbus if necessary
+if [ $reload -eq 0 ]; then
+ modprobe pmbus
+fi
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py
new file mode 100644
index 0000000..995cec8
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_switch.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+#
+# Copyright 2004-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 script combines multiple switch configuration into one python script.
+# All such configuration can be done directly through bcm5396_util.py.
+# But, it turns out it took several seconds to just start the python script.
+# Involking the script 16 times (2 to create vlan, 13 to set port vlan default,
+# and 1 to enable vlan function) contributes 1 minute delay.
+
+from bcm5396 import Bcm5396
+
+MDC_GPIO = 6
+MDIO_GPIO = 7
+
+INTERNAL_VLAN = 4088
+DEFAULT_VLAN=4090
+
+INTERNAL_PORTS = [3, 10, 1, 11, 0, 8, 2, 9, 4, 12, 14, 13]
+FRONT_PORT=5
+
+if __name__ == '__main__':
+ bcm = Bcm5396(Bcm5396.MDIO_ACCESS, mdc=MDC_GPIO, mdio=MDIO_GPIO)
+ # create default VLAN including internal ports and front panel
+ # port (un-tagged)
+ bcm.add_vlan(DEFAULT_VLAN, INTERNAL_PORTS + [FRONT_PORT],
+ INTERNAL_PORTS + [FRONT_PORT], 0)
+ # set ingress vlan for internal ports and front panel port to default vlan
+ for port in INTERNAL_PORTS + [FRONT_PORT]:
+ bcm.vlan_set_port_default(port, DEFAULT_VLAN, 0)
+ # create internal vlan including internal ports only (tagged)
+ bcm.add_vlan(INTERNAL_VLAN, [], INTERNAL_PORTS, 0)
+ # enable vlan
+ bcm.vlan_ctrl(True)
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh
new file mode 100755
index 0000000..ccbdc61
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Copyright 2014-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
+#
+
+CONSOLE_SH=/usr/local/fbpackages/utils/us_console.sh
+
+$CONSOLE_SH connect
+
+echo "You are in SOL session."
+echo "Use ctrl-x to quit."
+echo "-----------------------"
+echo
+
+trap '"$CONSOLE_SH" disconnect' INT TERM QUIT EXIT
+
+/usr/bin/microcom -s 57600 /dev/ttyS1
+
+echo
+echo
+echo "-----------------------"
+echo "Exit from SOL session."
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h
new file mode 100644
index 0000000..eefb6e4
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/i2c-dev.h
@@ -0,0 +1,362 @@
+/*
+ i2c-dev.h - i2c-bus driver, char device interface
+
+ Copyright (C) 1995-97 Simon G. Vogl
+ Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+
+ 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.
+*/
+
+#ifndef _LINUX_I2C_DEV_H
+#define _LINUX_I2C_DEV_H
+
+#include <linux/types.h>
+#include <sys/ioctl.h>
+#include <stddef.h>
+#include <string.h>
+
+
+/* -- i2c.h -- */
+
+#define _I2C_MIN(a, b) (((a) <= (b)) ? (a) : (b))
+
+/*
+ * I2C Message - used for pure i2c transaction, also from /dev interface
+ */
+struct i2c_msg {
+ __u16 addr; /* slave address */
+ unsigned short flags;
+#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
+#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
+#define I2C_M_RD 0x0001 /* read data, from slave to master */
+#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
+ short len; /* msg length */
+ char *buf; /* pointer to msg data */
+};
+
+/* To determine what functionality is present */
+
+#define I2C_FUNC_I2C 0x00000001
+#define I2C_FUNC_10BIT_ADDR 0x00000002
+#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
+#define I2C_FUNC_SMBUS_PEC 0x00000008
+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
+#define I2C_FUNC_SMBUS_QUICK 0x00010000
+#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
+#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
+#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
+#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
+#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
+#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
+#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
+#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
+
+#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
+ I2C_FUNC_SMBUS_WRITE_BYTE)
+#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
+#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA)
+#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
+#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
+
+/* Old name, for compatibility */
+#define I2C_FUNC_SMBUS_HWPEC_CALC I2C_FUNC_SMBUS_PEC
+
+/*
+ * Data for SMBus Messages
+ */
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
+union i2c_smbus_data {
+ __u8 byte;
+ __u16 word;
+ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+ /* and one more for PEC */
+};
+
+#define I2C_SMBUS_BLOCK_LARGE_MAX 240
+union i2c_smbus_large_data {
+ union i2c_smbus_data data;
+ __u8 block[I2C_SMBUS_BLOCK_LARGE_MAX + 2]; /* block[0] is used for length */
+ /* and one more for PEC */
+};
+
+/* smbus_access read or write markers */
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+/* SMBus transaction types (size parameter in the above functions)
+ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_PROC_CALL 4
+#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+#define I2C_SMBUS_BLOCK_LARGE_DATA 9
+
+
+/* /dev/i2c-X ioctl commands. The ioctl's parameter is always an
+ * unsigned long, except for:
+ * - I2C_FUNCS, takes pointer to an unsigned long
+ * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data
+ * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data
+ */
+#define I2C_RETRIES 0x0701 /* number of times a device address should
+ be polled when not acknowledging */
+#define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */
+
+/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
+ * are NOT supported! (due to code brokenness)
+ */
+#define I2C_SLAVE 0x0703 /* Use this slave address */
+#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it
+ is already in use by a driver! */
+#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
+
+#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */
+
+#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */
+
+#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */
+#define I2C_SMBUS 0x0720 /* SMBus transfer */
+
+
+/* This is the structure as used in the I2C_SMBUS ioctl call */
+struct i2c_smbus_ioctl_data {
+ __u8 read_write;
+ __u8 command;
+ __u32 size;
+ union i2c_smbus_data *data;
+};
+
+/* This is the structure as used in the I2C_RDWR ioctl call */
+struct i2c_rdwr_ioctl_data {
+ struct i2c_msg *msgs; /* pointers to i2c_msgs */
+ __u32 nmsgs; /* number of i2c_msgs */
+};
+
+#define I2C_RDRW_IOCTL_MAX_MSGS 42
+
+
+static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ struct i2c_smbus_ioctl_data args;
+
+ args.read_write = read_write;
+ args.command = command;
+ args.size = size;
+ args.data = data;
+ return ioctl(file,I2C_SMBUS,&args);
+}
+
+
+static inline __s32 i2c_smbus_write_quick(int file, __u8 value)
+{
+ return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL);
+}
+
+static inline __s32 i2c_smbus_read_byte(int file)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
+}
+
+static inline __s32 i2c_smbus_write_byte(int file, __u8 value)
+{
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,value,
+ I2C_SMBUS_BYTE,NULL);
+}
+
+static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BYTE_DATA,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
+}
+
+static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command,
+ __u8 value)
+{
+ union i2c_smbus_data data;
+ data.byte = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BYTE_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_WORD_DATA,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
+}
+
+static inline __s32 i2c_smbus_write_word_data(int file, __u8 command,
+ __u16 value)
+{
+ union i2c_smbus_data data;
+ data.word = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_WORD_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
+{
+ union i2c_smbus_data data;
+ data.word = value;
+ if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_PROC_CALL,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
+}
+
+
+/* Returns the number of read bytes */
+static inline __s32 i2c_smbus_read_block_data(int file, __u8 command,
+ __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BLOCK_DATA,&data))
+ return -1;
+ else {
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX));
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_block_data(int file, __u8 command,
+ __u8 length, const __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (length > 32)
+ length = 32;
+ memcpy(&data.block[1], values, length);
+ data.block[0] = length;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_read_block_large_data(int file, __u8 command,
+ __u8 *values)
+{
+ union i2c_smbus_large_data data;
+ if (i2c_smbus_access(file, I2C_SMBUS_READ, command,
+ I2C_SMBUS_BLOCK_LARGE_DATA,
+ (union i2c_smbus_data *)&data)) {
+ return -1;
+ } else {
+ /* the first byte is the length which is not copied */
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_LARGE_MAX));
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_block_large_data(int file, __u8 command,
+ __u8 length,
+ const __u8 *values)
+{
+ union i2c_smbus_large_data data;
+ if (length > I2C_SMBUS_BLOCK_LARGE_MAX) {
+ length = I2C_SMBUS_BLOCK_LARGE_MAX;
+ }
+ data.block[0] = length;
+ memcpy(&data.block[1], values, length);
+ return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_BLOCK_LARGE_DATA,
+ (union i2c_smbus_data *)&data);
+}
+
+/* Returns the number of read bytes */
+/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
+ ask for less than 32 bytes, your code will only work with kernels
+ 2.6.23 and later. */
+static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command,
+ __u8 length, __u8 *values)
+{
+ union i2c_smbus_data data;
+
+ if (length > 32)
+ length = 32;
+ data.block[0] = length;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
+ I2C_SMBUS_I2C_BLOCK_DATA,&data))
+ return -1;
+ else {
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX));
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
+ __u8 length,
+ const __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (length > 32)
+ length = 32;
+ memcpy(&data.block[1], values, length);
+ data.block[0] = length;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
+}
+
+/* Returns the number of read bytes */
+static inline __s32 i2c_smbus_block_process_call(int file, __u8 command,
+ __u8 length, __u8 *values)
+{
+ union i2c_smbus_data data;
+ if (length > 32)
+ length = 32;
+ memcpy(&data.block[1], values, length);
+ data.block[0] = length;
+ if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_PROC_CALL,&data))
+ return -1;
+ else {
+ memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX));
+ return data.block[0];
+ }
+}
+
+#undef _I2C_MIN
+
+#endif /* _LINUX_I2C_DEV_H */
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h
new file mode 100644
index 0000000..a69d69e
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/src/include/log.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-present Facebook. 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef LOG_H
+#define LOG_H
+
+#include <stdio.h>
+#include <string.h>
+
+//#define DEBUG
+//#define VERBOSE
+
+#define _LOG(dst, fmt, ...) do { \
+ fprintf(dst, "%s:%d " fmt "\n", \
+ __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ fflush(dst); \
+} while(0)
+
+#define LOG_ERR(err, fmt, ...) do { \
+ char buf[128]; \
+ strerror_r(err, buf, sizeof(buf)); \
+ _LOG(stderr, "ERROR " fmt ": %s", ##__VA_ARGS__, buf); \
+} while(0)
+
+#define LOG_INFO(fmt, ...) do { \
+ _LOG(stdout, fmt, ##__VA_ARGS__); \
+} while(0)
+
+#ifdef DEBUG
+#define LOG_DBG(fmt, ...) do { \
+ _LOG(stdout, fmt, ##__VA_ARGS__); \
+} while(0)
+#else
+#define LOG_DBG(fmt, ...)
+#endif
+
+#ifdef VERBOSE
+#define LOG_VER(fmt, ...) do { \
+ _LOG(stdout, fmt, ##__VA_ARGS__); \
+} while(0)
+#else
+#define LOG_VER(fmt, ...)
+#endif
+
+#endif
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh
new file mode 100755
index 0000000..6f445ee
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# Copyright 2014-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
+#
+
+usage() {
+ echo "$0 <connect | disconnect>"
+}
+
+. /usr/local/fbpackages/utils/ast-functions
+
+if [ $# -ne 1 ]; then
+ usage
+ exit 1
+fi
+
+if [ "$1" == "connect" ]; then
+ VALUE=1
+elif [ "$1" == "disconnect" ]; then
+ VALUE=0
+else
+ usage
+ exit 1
+fi
+
+# GPIOE0 (32) controls if uS console connects to UART1 or not.
+# To enable GPIOE0, SCU80[16], SCU8C[12], and SCU70[22] must be 0
+devmem_clear_bit $(scu_addr 80) 16
+devmem_clear_bit $(scu_addr 8C) 12
+devmem_clear_bit $(scu_addr 70) 22
+
+gpio_set 32 $VALUE
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh
new file mode 100755
index 0000000..d04b7cd
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/watch-fc.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+. /usr/local/fbpackages/utils/ast-functions
+
+MAC1LINK=0 # GPIOA0
+FAB0_PRES=20 # GPIOC4
+FAB1_PRES=21 # GPIOC5
+while true; do
+ # fabN_pres: active low.
+ if [ $(gpio_get $FAB0_PRES) = 0 ]; then
+ gpio_set $MAC1LINK 0
+ elif [ $(gpio_get $FAB1_PRES) = 0 ]; then
+ gpio_set $MAC1LINK 1
+ fi
+ sleep 1
+done
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh
new file mode 100644
index 0000000..5ba5311
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh
@@ -0,0 +1,201 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+. /usr/local/fbpackages/utils/ast-functions
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+prog="$0"
+
+usage() {
+ echo "Usage: $prog <command> [command options]"
+ echo
+ echo "Commands:"
+ echo " status: Get the current microserver power status"
+ echo
+ echo " on: Power on microserver if not powered on already"
+ echo " options:"
+ echo " -f: Re-do power on sequence no matter if microserver has "
+ echo " been powered on or not."
+ echo
+ echo " off: Power off microserver ungracefully"
+ echo
+ echo " reset: Power reset microserver ungracefully"
+ echo " options:"
+ echo " -s: Power reset whole wedge system ungracefully"
+ echo
+}
+
+# Because the voltage leak from uS COM pins could cause uS to struck when transitting
+# from S5 to S0, we will need to explicitely pull down uS COM pins before powering off/reset
+# and restoring COM pins after
+
+pull_down_us_com() {
+ # set GPIOL6 and GPIOL7 low
+ devmem_clear_bit $(scu_addr 84) 22
+ devmem_clear_bit $(scu_addr 84) 23
+ gpio_set 94 0
+ gpio_set 95 0
+ # now, connect uart from BMC to the uS
+ gpio_set 32 1
+}
+
+restore_us_com() {
+ devmem_set_bit $(scu_addr 84) 22
+ devmem_set_bit $(scu_addr 84) 23
+ # if sol.sh is running, keep uart from uS connected with BMC
+ if ps | grep sol.sh > /dev/null 2>&1; then
+ gpio_set 32 1
+ else
+ gpio_set 32 0
+ fi
+}
+
+do_status() {
+ echo -n "Microserver power is "
+ if wedge_is_us_on; then
+ echo "on"
+ else
+ echo "off"
+ fi
+ return 0
+}
+
+do_on() {
+ local force opt
+ force=0
+ while getopts "f" opt; do
+ case $opt in
+ f)
+ force=1
+ ;;
+ *)
+ usage
+ exit -1
+ ;;
+
+ esac
+ done
+ echo -n "Power on microserver ..."
+ if [ $force -eq 0 ]; then
+ # need to check if uS is on or not
+ if wedge_is_us_on 10 "."; then
+ echo " Already on. Skip!"
+ return 1
+ fi
+ fi
+ # first make sure, GPIOD1 (25) is high
+ gpio_set 25 1
+ # then, put GPIOP7 (127) to low
+ gpio_set 127 0
+ # generate the power on pulse
+ gpio_set 25 0
+ sleep 1
+ gpio_set 25 1
+ sleep 1
+ restore_us_com
+ # Turn on the power LED (GPIOE5)
+ /usr/local/bin/power_led.sh on
+ echo " Done"
+ return 0
+}
+
+do_off() {
+ echo -n "Power off microserver ..."
+ pull_down_us_com
+ # first make sure, GPIOD1 (25) is high
+ gpio_set 25 1
+ # then, put GPIOP7 (127) to low
+ gpio_set 127 0
+ gpio_set 25 0
+ sleep 5
+ gpio_set 25 1
+ # Turn off the power LED (GPIOE5)
+ /usr/local/bin/power_led.sh off
+ echo " Done"
+ return 0
+}
+
+do_reset() {
+ local system opt
+ system=0
+ while getopts "s" opt; do
+ case $opt in
+ s)
+ system=1
+ ;;
+ *)
+ usage
+ exit -1
+ ;;
+ esac
+ done
+ if [ $system -eq 1 ]; then
+ echo -n "Power reset whole system ..."
+ rmmod adm1275
+ i2cset -y 12 0x10 0xd9 c
+ else
+ if ! wedge_is_us_on; then
+ echo "Power resetting microserver that is powered off has no effect."
+ echo "Use '$prog on' to power the microserver on"
+ return -1
+ fi
+ echo -n "Power reset microserver ..."
+ pull_down_us_com
+ # then, put GPIOP7 (127) to low
+ gpio_set 127 0
+ gpio_set 17 0
+ sleep 1
+ gpio_set 17 1
+ sleep 1
+ restore_us_com
+ fi
+ echo " Done"
+ return 0
+}
+
+if [ $# -lt 1 ]; then
+ usage
+ exit -1
+fi
+
+command="$1"
+shift
+
+case "$command" in
+ status)
+ do_status $@
+ ;;
+ on)
+ do_on $@
+ ;;
+ off)
+ do_off $@
+ ;;
+ reset)
+ do_reset $@
+ ;;
+ *)
+ usage
+ exit -1
+ ;;
+esac
+
+exit $?
diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh
new file mode 100644
index 0000000..34b8e59
--- /dev/null
+++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_us_mac.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+#
+# Copyright 2014-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
+#
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+
+mac=$(i2cdump -y 0x0 0x49 s 0xd4 | grep '^00: d4'| awk '{ print $3":"$4":"$5":"$6":"$7":"$8 }') 2>/dev/null
+
+if [ -n "$mac" ]; then
+ echo $mac
+else
+ echo "Cannot find out the microserver MAC" 1>&2
+fi
OpenPOWER on IntegriCloud