summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
Diffstat (limited to 'driver')
-rw-r--r--driver/build.mk1
-rw-r--r--driver/pi3usb30532.h78
-rw-r--r--driver/usb_switch_pi3usb30532.c85
3 files changed, 164 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk
index f45b293dc7..997726fe24 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -56,6 +56,7 @@ driver-$(CONFIG_TEMP_SENSOR_TMP432)+=temp_sensor/tmp432.o
# USB switches
driver-$(CONFIG_USB_SWITCH_PI3USB9281)+=usb_switch_pi3usb9281.o
+driver-$(CONFIG_USB_SWITCH_PI3USB30532)+=usb_switch_pi3usb30532.o
driver-$(CONFIG_USB_SWITCH_TSU6721)+=usb_switch_tsu6721.o
# Firmware Update
diff --git a/driver/pi3usb30532.h b/driver/pi3usb30532.h
new file mode 100644
index 0000000000..f99c9561bb
--- /dev/null
+++ b/driver/pi3usb30532.h
@@ -0,0 +1,78 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Pericom PI3USB30532 USB port switch driver.
+ */
+
+#ifndef PI3USB30532_H
+#define PI3USB30532_H
+
+#include <inttypes.h>
+
+/* USB switch registers */
+#define PI3USB30532_REG_ADDR 0x00
+#define PI3USB30532_REG_VENDOR 0x01
+#define PI3USB30532_REG_CONTROL 0x02
+/* Control register field */
+#define PI3USB30532_CTRL_MASK 0x7
+#define PI3USB30532_CTRL_RSVD 0
+/* Switch vendor ID */
+#define PI3USB30532_VENDOR_ID 0
+
+/* PI3USB30532 control flags */
+#define PI3USB30532_BIT_SWAP (1 << 0)
+#define PI3USB30532_BIT_DP (1 << 1)
+#define PI3USB30532_BIT_USB (1 << 2)
+
+/* PI3USB30532 modes */
+/* Power down, switch open */
+#define PI3USB30532_MODE_POWERDOWN 0
+/* Keep power on, switch open */
+#define PI3USB30532_MODE_POWERON 1
+/* 4-lane DP 1.2
+ * dp0~3 : rx2, tx2, tx1, rx1
+ * hpd+/-: rfu1, rfu2
+ */
+#define PI3USB30532_MODE_DP PI3USB30532_BIT_DP
+/* 4-lane DP 1.2 swap
+ * dp0~3 : rx1, tx1, tx2, rx2
+ * hpd+/-: rfu2, rfu1
+ */
+#define PI3USB30532_MODE_DP_SWAP (PI3USB30532_MODE_DP | PI3USB30532_BIT_SWAP)
+/* USB3
+ * tx/rx : tx1, rx1
+ */
+#define PI3USB30532_MODE_USB PI3USB30532_BIT_USB
+/* USB3 swap
+ * tx/rx : tx2, rx2
+ */
+#define PI3USB30532_MODE_USB_SWAP (PI3USB30532_MODE_USB | PI3USB30532_BIT_SWAP)
+/* 2-lane DP 1.2 + USB3
+ * tx/rx : tx1, rx1
+ * dp0~1 : rx2, tx2
+ * hpd+/-: rfu1, rfu2
+ */
+#define PI3USB30532_MODE_DP_USB (PI3USB30532_BIT_DP | PI3USB30532_BIT_USB)
+/* 2-lane DP 1.2 + USB3, swap
+ * tx/rx : tx2, rx2
+ * dp0-1 : rx1, tx1
+ * hpd+/-: rfu2, rfu1
+ */
+#define PI3USB30532_MODE_DP_USB_SWAP (PI3USB30532_MODE_DP_USB | \
+ PI3USB30532_BIT_SWAP)
+
+
+/* Reads PI3USB30532 register */
+int pi3usb30532_read(uint8_t chip_idx, uint8_t reg);
+
+/* Writes PI3USB30532 register */
+int pi3usb30532_write(uint8_t chip_idx, uint8_t reg, uint8_t val);
+
+/* Writes PI3USB30532 control register */
+int pi3usb30532_set_switch(uint8_t chip_idx, uint8_t mode);
+
+/* Resets PI3USB30532 to power on default value */
+int pi3usb30532_reset(uint8_t chip_idx);
+
+#endif /* PI3USB30532_H */
diff --git a/driver/usb_switch_pi3usb30532.c b/driver/usb_switch_pi3usb30532.c
new file mode 100644
index 0000000000..1688278ae6
--- /dev/null
+++ b/driver/usb_switch_pi3usb30532.c
@@ -0,0 +1,85 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Pericom PI3USB30532 USB port switch driver.
+ */
+
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "task.h"
+#include "timer.h"
+#include "pi3usb30532.h"
+#include "util.h"
+
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr)
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
+
+#define INTERNAL_READ_ERROR(code) (EC_ERROR_INTERNAL_FIRST + code)
+#define IS_READ_ERROR(code) ((code) > EC_ERROR_INTERNAL_FIRST)
+
+/* 8-bit I2C address */
+static const int pi3usb30532_addrs[] = CONFIG_USB_SWITCH_I2C_ADDRS;
+
+int pi3usb30532_read(uint8_t chip_idx, uint8_t reg)
+{
+ int res, val;
+ int addr = pi3usb30532_addrs[chip_idx];
+
+ res = i2c_read8(I2C_PORT_USB_SWITCH, addr, reg, &val);
+ if (res)
+ return INTERNAL_READ_ERROR(res);
+
+ return val;
+}
+
+int pi3usb30532_write(uint8_t chip_idx, uint8_t reg, uint8_t val)
+{
+ int res;
+ int addr = pi3usb30532_addrs[chip_idx];
+
+ res = i2c_write8(I2C_PORT_USB_SWITCH, addr, reg, val);
+ if (res)
+ CPUTS("PI3USB30532 I2C write failed");
+
+ return res;
+}
+
+/* Writes control register to set switch mode */
+int pi3usb30532_set_switch(uint8_t chip_idx, uint8_t mode)
+{
+ return pi3usb30532_write(chip_idx, PI3USB30532_REG_CONTROL,
+ (mode & PI3USB30532_CTRL_MASK) |
+ PI3USB30532_CTRL_RSVD);
+}
+
+int pi3usb30532_reset(uint8_t chip_idx)
+{
+ return pi3usb30532_set_switch(chip_idx, PI3USB30532_MODE_POWERDOWN);
+}
+
+static void pi3usb30532_init(void)
+{
+ int i, res, val;
+
+ for (i = 0; i < ARRAY_SIZE(pi3usb30532_addrs); i++) {
+ res = pi3usb30532_reset(i);
+ if (res)
+ CPRINTS("PI3USB30532 [%d] init failed", i);
+
+ val = pi3usb30532_read(i, PI3USB30532_REG_VENDOR);
+ if (IS_READ_ERROR(val)) {
+ CPRINTS("PI3USB30532 [%d] read failed", i);
+ continue;
+ }
+
+ if (val != PI3USB30532_VENDOR_ID)
+ CPRINTS("PI3USB30532 [%d] invalid ID 0x%02x", i, val);
+
+ }
+}
+DECLARE_HOOK(HOOK_INIT, pi3usb30532_init, HOOK_PRIO_LAST);