Configure servo for A-A mode when programming ARM targets

For proper USB port power distribution when connecting DUT to the host in USB
A-A mode (required for firmware programming), the servo 'dut_hub_sel' control
needs to be set to 'dut_sees_servo'.

Without this state modification programming through servo is not possible, a
separate specially made A-A USB cable is required to connect DUT directly to
the host.

With this change the control's state before programming is retrieved,
then it is modified if necessary, and then restored after programming
is done.

BUG=chromium-os:22475
TEST=manual
  . run the following commands

   $ dut-control dut_hub_sel:dut_sees_servo
   $ cros_write_firmware -b daisy -w usb -d exynos5250-snow -F spi -i /build/daisy/firmware/image-snow.bin -V
   $ dut-control dut_hub_sel
   dut_hub_sel:dut_sees_servo
   $ dut-control dut_hub_sel:dut_sees_hub
   $ cros_write_firmware -b daisy -w usb -d exynos5250-snow -F spi -i /build/daisy/firmware/image-snow.bin -V
   $ dut-control dut_hub_sel
   dut_hub_sel:dut_sees_hub

  observe both programming attempts succeed and the dut_hub_sel control state preserved.

Change-Id: Ib5a2dba1536378b634a24c477a92e06378d35cb4
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/42013
diff --git a/host/lib/write_firmware.py b/host/lib/write_firmware.py
index 5d3631d..391266a 100644
--- a/host/lib/write_firmware.py
+++ b/host/lib/write_firmware.py
@@ -360,6 +360,8 @@
     Args:
       args: List of arguments to dut-control.
 
+    Retruns:
+      a string, stdout generated by running the command
     Raises:
       IOError if no servo access is permitted.
     """
@@ -367,7 +369,7 @@
       raise IOError('No servo access available, please use --servo')
     if self._servo_port:
       args.extend(['-p', '%s' % self._servo_port])
-    self._tools.Run('dut-control', args)
+    return self._tools.Run('dut-control', args)
 
   def _ExtractPayloadParts(self, payload):
     """Extract the BL1, BL2 and U-Boot parts from a payload.
@@ -449,13 +451,20 @@
     vendor_id = 0x04e8
     product_id = 0x1234
 
-    self._out.Progress('Reseting board via servo')
+    # Preserve dut_hub_sel state.
+    preserved_dut_hub_sel = self._DutControl(['dut_hub_sel',]
+                                             ).strip().split(':')[-1]
+    required_dut_hub_sel = 'dut_sees_servo'
     args = ['warm_reset:on', 'fw_up:on', 'pwr_button:press', 'sleep:.1',
         'warm_reset:off']
+    if preserved_dut_hub_sel != required_dut_hub_sel:
+      # Need to set it to get the port properly powered up.
+      args += ['dut_hub_sel:%s' % required_dut_hub_sel]
     # TODO(sjg) If the board is bricked a reset does not seem to bring it
     # back to life.
     # BUG=chromium-os:28229
     args = ['cold_reset:on', 'sleep:.2', 'cold_reset:off'] + args
+    self._out.Progress('Reseting board via servo')
     self._DutControl(args)
 
     # If we have a kernel to write, create a new image with that added.
@@ -500,8 +509,11 @@
           self._DutControl(args)
 
     finally:
-      # Make sure that the power button is released, whatever happens
+      # Make sure that the power button is released and dut_sel_hub state is
+      # restored, whatever happens
       args = ['fw_up:off', 'pwr_button:release']
+      if preserved_dut_hub_sel != required_dut_hub_sel:
+        args += ['dut_hub_sel:%s' % preserved_dut_hub_sel]
       self._DutControl(args)
 
     self._out.Notice('Image downloaded - please see serial output '