summaryrefslogtreecommitdiff
path: root/driver/usb_mux/amd_fp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/usb_mux/amd_fp6.c')
-rw-r--r--driver/usb_mux/amd_fp6.c233
1 files changed, 0 insertions, 233 deletions
diff --git a/driver/usb_mux/amd_fp6.c b/driver/usb_mux/amd_fp6.c
deleted file mode 100644
index b2d5ae1fb4..0000000000
--- a/driver/usb_mux/amd_fp6.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/* Copyright 2021 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.
- *
- * AMD FP6 USB/DP Mux.
- */
-
-#include "amd_fp6.h"
-#include "chipset.h"
-#include "common.h"
-#include "hooks.h"
-#include "i2c.h"
-#include "queue.h"
-#include "timer.h"
-#include "usb_mux.h"
-
-#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args)
-#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args)
-
-/*
- * The recommendation from "3.3.2 Command Timeout" is 250ms,
- * however empirical testing found that a 100ms timeout is sufficient.
- */
-#define WRITE_CMD_TIMEOUT_MS 100
-
-/* Command retry interval */
-#define CMD_RETRY_INTERVAL_MS 1000
-
-/*
- * Local data structure for saving mux state so it can be restored after
- * an AP reset.
- */
-static struct {
- const struct usb_mux *mux;
- uint8_t val;
- bool write_pending;
-} saved_mux_state[USBC_PORT_COUNT];
-
-static int amd_fp6_mux_port0_read(const struct usb_mux *me, uint8_t *val)
-{
- uint8_t payload[3] = { 0 };
- bool mux_ready;
-
- RETURN_ERROR(i2c_xfer(me->i2c_port, me->i2c_addr_flags, NULL, 0,
- payload, 3));
-
- /*
- * payload[0]: Status/ID
- * payload[1]: Port 0 Control/Status
- * payload[2]: Port 1 Control/Status (unused on FP6)
- */
- mux_ready = !!((payload[0] >> AMD_FP6_MUX_PD_STATUS_OFFSET)
- & AMD_FP6_MUX_PD_STATUS_READY);
-
- if (!mux_ready)
- return EC_ERROR_BUSY;
- *val = payload[1];
-
- return EC_SUCCESS;
-}
-
-static int amd_fp6_mux_port0_write(const struct usb_mux *me, uint8_t write_val)
-{
- uint8_t read_val;
- uint8_t port_status;
- timestamp_t start;
-
- /* Check if mux is ready */
- RETURN_ERROR(amd_fp6_mux_port0_read(me, &read_val));
-
- /* Write control register */
- RETURN_ERROR(
- i2c_write8(me->i2c_port, me->i2c_addr_flags, 0, write_val));
-
- /*
- * Read status until write command finishes or times out.
- * The mux has an internal opaque timeout, which we wrap with our own
- * timeout to be safe.
- */
- start = get_time();
- while (time_since32(start) < WRITE_CMD_TIMEOUT_MS * MSEC) {
-
- RETURN_ERROR(amd_fp6_mux_port0_read(me, &read_val));
- port_status = read_val >> AMD_FP6_MUX_PORT_STATUS_OFFSET;
-
- if (port_status == AMD_FP6_MUX_PORT_CMD_COMPLETE)
- return EC_SUCCESS;
- else if (port_status == AMD_FP6_MUX_PORT_CMD_TIMEOUT)
- return EC_ERROR_TIMEOUT;
- else if (port_status == AMD_FP6_MUX_PORT_CMD_BUSY)
- msleep(5);
- else
- return EC_ERROR_UNKNOWN;
- }
-
- return EC_ERROR_TIMEOUT;
-}
-
-/*
- * Keep trying to write the saved mux state until successful or SOC leaves
- * S0 power state.
- */
-static void amd_fp6_set_mux_retry(void);
-DECLARE_DEFERRED(amd_fp6_set_mux_retry);
-static void amd_fp6_set_mux_retry(void)
-{
- int rv;
- bool try_again = false;
-
- /*
- * Mux can only be written in S0, stop trying.
- * Will try again on chipset_resume.
- */
- if (!chipset_in_state(CHIPSET_STATE_ON))
- return;
-
- for (int i = 0; i < ARRAY_SIZE(saved_mux_state); i++) {
- /* Make sure mux_state is initialized */
- if (saved_mux_state[i].mux == NULL ||
- !saved_mux_state[i].write_pending)
- continue;
-
- rv = amd_fp6_mux_port0_write(saved_mux_state[i].mux,
- saved_mux_state[i].val);
-
- if (rv)
- try_again = true;
- else
- saved_mux_state[i].write_pending = false;
- }
- if (try_again)
- hook_call_deferred(&amd_fp6_set_mux_retry_data,
- CMD_RETRY_INTERVAL_MS * MSEC);
-}
-
-
-static int amd_fp6_set_mux(const struct usb_mux *me, mux_state_t mux_state,
- bool *ack_required)
-{
- uint8_t val;
-
- /* This driver does not use host command ACKs */
- *ack_required = false;
-
- if (mux_state == USB_PD_MUX_NONE)
- /*
- * LOW_POWER must be set when connection mode is
- * set to 00b (safe state)
- */
- val = AMD_FP6_MUX_MODE_SAFE | AMD_FP6_MUX_LOW_POWER;
- else if ((mux_state & USB_PD_MUX_USB_ENABLED) &&
- (mux_state & USB_PD_MUX_DP_ENABLED))
- val = AMD_FP6_MUX_MODE_DOCK;
- else if (mux_state & USB_PD_MUX_USB_ENABLED)
- val = AMD_FP6_MUX_MODE_USB;
- else if (mux_state & USB_PD_MUX_DP_ENABLED)
- val = AMD_FP6_MUX_MODE_DP;
- else {
- CPRINTSUSB("C%d: unhandled mux_state %x\n", me->usb_port,
- mux_state);
- return EC_ERROR_INVAL;
- }
-
- if (mux_state & USB_PD_MUX_POLARITY_INVERTED)
- val |= AMD_FP6_MUX_ORIENTATION;
-
- saved_mux_state[me->usb_port].mux = me;
- saved_mux_state[me->usb_port].val = val;
-
- /* Mux is not powered in Z1 */
- if (chipset_in_state(CHIPSET_STATE_HARD_OFF))
- return (mux_state == USB_PD_MUX_NONE) ? EC_SUCCESS
- : EC_ERROR_NOT_POWERED;
-
- saved_mux_state[me->usb_port].write_pending = true;
- amd_fp6_set_mux_retry();
-
- return EC_SUCCESS;
-}
-
-static int amd_fp6_get_mux(const struct usb_mux *me, mux_state_t *mux_state)
-{
- uint8_t val;
- bool inverted;
- uint8_t mode;
-
- /* Mux is not powered in Z1 */
- if (chipset_in_state(CHIPSET_STATE_HARD_OFF))
- return USB_PD_MUX_NONE;
-
- RETURN_ERROR(amd_fp6_mux_port0_read(me, &val));
-
- mode = (val & AMD_FP6_MUX_MODE_MASK);
- inverted = !!(val & AMD_FP6_MUX_ORIENTATION);
-
- if (mode == AMD_FP6_MUX_MODE_USB)
- *mux_state = USB_PD_MUX_USB_ENABLED;
- else if (mode == AMD_FP6_MUX_MODE_DP)
- *mux_state = USB_PD_MUX_DP_ENABLED;
- else if (mode == AMD_FP6_MUX_MODE_DOCK)
- *mux_state = USB_PD_MUX_USB_ENABLED | USB_PD_MUX_DP_ENABLED;
- else /* AMD_FP6_MUX_MODE_SAFE */
- *mux_state = USB_PD_MUX_NONE;
-
- if (inverted)
- *mux_state |= USB_PD_MUX_POLARITY_INVERTED;
-
- return EC_SUCCESS;
-}
-
-/*
- * The FP6 USB Mux will not be ready for writing until *sometime* after S0.
- */
-static void amd_fp6_chipset_resume(void)
-{
- for (int i = 0; i < ARRAY_SIZE(saved_mux_state); i++)
- saved_mux_state[i].write_pending = true;
- hook_call_deferred(&amd_fp6_set_mux_retry_data,
- CMD_RETRY_INTERVAL_MS * MSEC);
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, amd_fp6_chipset_resume, HOOK_PRIO_DEFAULT);
-
-static int amd_fp6_chipset_reset(const struct usb_mux *me)
-{
- amd_fp6_chipset_resume();
- return EC_SUCCESS;
-}
-
-const struct usb_mux_driver amd_fp6_usb_mux_driver = {
- .set = &amd_fp6_set_mux,
- .get = &amd_fp6_get_mux,
- .chipset_reset = &amd_fp6_chipset_reset
-};