summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/plankton/board.c17
-rw-r--r--board/plankton/board.h1
-rw-r--r--driver/build.mk3
-rw-r--r--driver/ioexpander_pca9534.c44
-rw-r--r--driver/ioexpander_pca9534.h56
5 files changed, 121 insertions, 0 deletions
diff --git a/board/plankton/board.c b/board/plankton/board.c
index 05fde4bbd9..cb60dcd353 100644
--- a/board/plankton/board.c
+++ b/board/plankton/board.c
@@ -11,6 +11,7 @@
#include "gpio.h"
#include "hooks.h"
#include "i2c.h"
+#include "ioexpander_pca9534.h"
#include "registers.h"
#include "task.h"
#include "timer.h"
@@ -198,3 +199,19 @@ DECLARE_CONSOLE_COMMAND(usbc_action, cmd_usbc_action,
"<5v|12v|20v|dev|usb|dp|flip|pol0|pol1>",
"Set Plankton type-C port state",
NULL);
+
+static int cmd_usb_hub_reset(int argc, char *argv[])
+{
+ int ret;
+
+ ret = pca9534_config_pin(I2C_PORT_MASTER, 0x40, 7, PCA9534_OUTPUT);
+ if (ret)
+ return ret;
+ ret = pca9534_set_level(I2C_PORT_MASTER, 0x40, 7, 0);
+ if (ret)
+ return ret;
+ usleep(100 * MSEC);
+ return pca9534_set_level(I2C_PORT_MASTER, 0x40, 7, 1);
+}
+DECLARE_CONSOLE_COMMAND(hub_reset, cmd_usb_hub_reset,
+ NULL, "Reset USB hub", NULL);
diff --git a/board/plankton/board.h b/board/plankton/board.h
index e5a036e7fe..323143bcd3 100644
--- a/board/plankton/board.h
+++ b/board/plankton/board.h
@@ -24,6 +24,7 @@
#define CONFIG_ADC
#define CONFIG_HW_CRC
#define CONFIG_I2C
+#define CONFIG_IO_EXPANDER_PCA9534
#undef CONFIG_WATCHDOG_HELP
#undef CONFIG_LID_SWITCH
#undef CONFIG_TASK_PROFILING
diff --git a/driver/build.mk b/driver/build.mk
index 1d1cd83f05..409b7f8c6b 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -29,6 +29,9 @@ driver-$(CONFIG_CHARGER_BQ24735)+=charger/bq24735.o
driver-$(CONFIG_CHARGER_BQ24738)+=charger/bq24738.o
driver-$(CONFIG_CHARGER_BQ24773)+=charger/bq24773.o
+# I/O expander
+driver-$(CONFIG_IO_EXPANDER_PCA9534)+=ioexpander_pca9534.o
+
# Current/Power monitor
driver-$(CONFIG_INA231)+=ina231.o
diff --git a/driver/ioexpander_pca9534.c b/driver/ioexpander_pca9534.c
new file mode 100644
index 0000000000..1ac9a5164b
--- /dev/null
+++ b/driver/ioexpander_pca9534.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2014 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.
+ *
+ * NXP PCA9534 I/O expander
+ */
+
+#include "i2c.h"
+#include "ioexpander_pca9534.h"
+
+static int pca9534_pin_read(int port, int addr, int reg, int pin, int *val)
+{
+ int ret;
+ ret = i2c_read8(port, addr, reg, val);
+ *val = (*val & (1 << pin)) ? 1 : 0;
+ return ret;
+}
+
+static int pca9534_pin_write(int port, int addr, int reg, int pin, int val)
+{
+ int ret, v;
+ ret = i2c_read8(port, addr, reg, &v);
+ if (ret != EC_SUCCESS)
+ return ret;
+ v &= ~(1 << pin);
+ if (val)
+ v |= 1 << pin;
+ return i2c_write8(port, addr, reg, v);
+}
+
+int pca9534_get_level(int port, int addr, int pin, int *level)
+{
+ return pca9534_pin_read(port, addr, PCA9534_REG_INPUT, pin, level);
+}
+
+int pca9534_set_level(int port, int addr, int pin, int level)
+{
+ return pca9534_pin_write(port, addr, PCA9534_REG_OUTPUT, pin, level);
+}
+
+int pca9534_config_pin(int port, int addr, int pin, int is_input)
+{
+ return pca9534_pin_write(port, addr, PCA9534_REG_CONFIG, pin, is_input);
+}
diff --git a/driver/ioexpander_pca9534.h b/driver/ioexpander_pca9534.h
new file mode 100644
index 0000000000..70b3e57662
--- /dev/null
+++ b/driver/ioexpander_pca9534.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2014 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.
+ *
+ * NXP PCA9534 I/O expander
+ */
+
+#ifndef PCA9534_H
+#define PCA9534_H
+
+#define PCA9534_REG_INPUT 0x0
+#define PCA9534_REG_OUTPUT 0x1
+#define PCA9534_REG_CONFIG 0x3
+
+#define PCA9534_OUTPUT 0
+#define PCA9534_INPUT 1
+
+/*
+ * Get input level. Note that this reflects the actual level on the
+ * pin, even if the pin is configured as output.
+ *
+ * @param port The I2C port of PCA9534.
+ * @param addr The address of PCA9534.
+ * @param pin The index of the pin to read.
+ * @param level The pointer to where the read level is stored.
+ *
+ * @return EC_SUCCESS, or EC_ERROR_* on error.
+ */
+int pca9534_get_level(int port, int addr, int pin, int *level);
+
+/*
+ * Set output level. This function has no effect if the pin is
+ * configured as input.
+ *
+ * @param port The I2C port of PCA9534.
+ * @param addr The address of PCA9534.
+ * @param pin The index of the pin to set.
+ * @param level The level to set.
+ *
+ * @return EC_SUCCESS, or EC_ERROR_* on error.
+ */
+int pca9534_set_level(int port, int addr, int pin, int level);
+
+/*
+ * Config a pin as input or output.
+ *
+ * @param port The I2C port of PCA9534.
+ * @param addr The address of PCA9534.
+ * @param pin The index of the pin to set.
+ * @param is_input PCA9534_INPUT or PCA9534_OUTPUT.
+ *
+ * @return EC_SUCCESS, or EC_ERROR_* on error.
+ */
+int pca9534_config_pin(int port, int addr, int pin, int is_input);
+
+#endif /* PCA9534_H */