diff options
author | Victor Liu <victorliu@google.com> | 2024-03-13 19:57:59 +0000 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2024-03-13 19:57:59 +0000 |
commit | 9bdbec4725f4fdfd6c36d3292db778ba249d3fca (patch) | |
tree | 0e931433b7d4f8d384439fd69de31e6512765f6f | |
parent | d28772fb6f9a4bc2932238c3d0710002b4a9f690 (diff) | |
parent | 491a32b27dcad89bbf92dc15a67741a48c4c74fc (diff) | |
download | qm35-android-gs-shusky-5.15-android15-dp.tar.gz |
Merge "[R-7.2.9] uwb: update qm35 driver" into android14-gs-pixel-5.15-24Q3android-15-beta-2_r0.8android-15-beta-2_r0.7android-15-beta-1_r0.8android-15-beta-1_r0.7android-gs-shusky-5.15-android15-dpandroid-gs-shusky-5.15-android15-betaandroid-gs-akita-5.15-android15-beta
-rw-r--r-- | qm35s/hsspi.c | 41 | ||||
-rw-r--r-- | qm35s/hsspi.h | 13 | ||||
-rw-r--r-- | qm35s/qm35-spi.c | 19 | ||||
-rw-r--r-- | qm35s/qm35.h | 2 | ||||
-rw-r--r-- | qm35s/qmrom_spi.c | 12 |
5 files changed, 73 insertions, 14 deletions
diff --git a/qm35s/hsspi.c b/qm35s/hsspi.c index 44589fd..52c6908 100644 --- a/qm35s/hsspi.c +++ b/qm35s/hsspi.c @@ -141,9 +141,27 @@ static bool is_txrx_waiting(struct hsspi *hsspi) static int hsspi_wait_ss_ready(struct hsspi *hsspi) { int ret; + unsigned long flags; hsspi->waiting_ss_rdy = true; + /** + * The following block allows to handle the case where + * the HSSPI_FLAGS_SS_READY is set but the SOC went into + * sleep (S3 or S4) and the exton interrupt has not been + * caught yet. + * + * In that case, the SOC is not ready and this function + * would return 0 immediately leading to a potential + * comms issue if we initiate the transfer when the SOC + * is preparing its SPI xfer. + * + * So, if this happens, HSSPI_FLAGS_SS_BUSY will be low + * and depending on the ss-rdy gpio state, we know if + * the SOC is ready. If not, we'll wait for the timeout + * (and wake the SOC if necessary before waiting). + */ + spin_lock_irqsave(&hsspi->flags_lock, flags); if (!test_bit(HSSPI_FLAGS_SS_BUSY, hsspi->flags)) { /* The ss_ready went low, so the fw is not busy anymore, * if the ss_ready is high, we can proceed, else, @@ -151,9 +169,12 @@ static int hsspi_wait_ss_ready(struct hsspi *hsspi) * we need to wait for it to be ready again. */ clear_bit(HSSPI_FLAGS_SS_READY, hsspi->flags); + spin_unlock_irqrestore(&hsspi->flags_lock, flags); if (gpiod_get_value(hsspi->gpio_ss_rdy)) { return 0; } + } else { + spin_unlock_irqrestore(&hsspi->flags_lock, flags); } /* Check if the QM went to sleep and wake it up if it did */ @@ -507,6 +528,7 @@ int hsspi_init(struct hsspi *hsspi, struct spi_device *spi) memset(hsspi, 0, sizeof(*hsspi)); spin_lock_init(&hsspi->lock); + spin_lock_init(&hsspi->flags_lock); INIT_LIST_HEAD(&hsspi->work_list); hsspi->state = HSSPI_STOPPED; @@ -636,11 +658,6 @@ int hsspi_unregister(struct hsspi *hsspi, struct hsspi_layer *layer) return 0; } -void hsspi_clear_spi_slave_busy(struct hsspi *hsspi) -{ - clear_bit(HSSPI_FLAGS_SS_BUSY, hsspi->flags); -} - void hsspi_set_spi_slave_busy(struct hsspi *hsspi) { set_bit(HSSPI_FLAGS_SS_BUSY, hsspi->flags); @@ -648,7 +665,21 @@ void hsspi_set_spi_slave_busy(struct hsspi *hsspi) void hsspi_set_spi_slave_ready(struct hsspi *hsspi) { + unsigned long flags; + spin_lock_irqsave(&hsspi->flags_lock, flags); + clear_bit(HSSPI_FLAGS_SS_BUSY, hsspi->flags); + set_bit(HSSPI_FLAGS_SS_READY, hsspi->flags); + spin_unlock_irqrestore(&hsspi->flags_lock, flags); + + wake_up_interruptible(&hsspi->wq_ready); +} + +void hsspi_set_spi_slave_ready_irq(struct hsspi *hsspi) +{ + spin_lock(&hsspi->flags_lock); + clear_bit(HSSPI_FLAGS_SS_BUSY, hsspi->flags); set_bit(HSSPI_FLAGS_SS_READY, hsspi->flags); + spin_unlock(&hsspi->flags_lock); wake_up_interruptible(&hsspi->wq_ready); } diff --git a/qm35s/hsspi.h b/qm35s/hsspi.h index 9cb62cc..4919e01 100644 --- a/qm35s/hsspi.h +++ b/qm35s/hsspi.h @@ -147,6 +147,7 @@ enum hsspi_state { */ struct hsspi { spinlock_t lock; /* protect work_list, layers and state */ + spinlock_t flags_lock; /* protect flags */ struct list_head work_list; struct hsspi_layer *layers[UL_MAX_IDX]; enum hsspi_state state; @@ -229,12 +230,22 @@ int hsspi_unregister(struct hsspi *hsspi, struct hsspi_layer *layer); * hsspi_set_spi_slave_ready() - tell the hsspi that the ss_ready is active * @hsspi: pointer to a &struct hsspi * - * This function is called in the ss_ready irq handler. It notices the + * This function is called in the driver's init. It notices the * HSSPI driver that the QM is ready for transfer. */ void hsspi_set_spi_slave_ready(struct hsspi *hsspi); /** + * hsspi_set_spi_slave_ready_irq() - tell the hsspi that the ss_ready is active + * in irq context, + * @hsspi: pointer to a &struct hsspi + * + * This function is called in the ss_ready irq handler. It notices the + * HSSPI driver that the QM is ready for transfer. + */ +void hsspi_set_spi_slave_ready_irq(struct hsspi *hsspi); + +/** * hsspi_clear_spi_slave_ready() - tell the hsspi that the ss_ready has * been lowered meaning that the fw is busy or asleep, * @hsspi: pointer to a &struct hsspi diff --git a/qm35s/qm35-spi.c b/qm35s/qm35-spi.c index 49063f1..ca0a533 100644 --- a/qm35s/qm35-spi.c +++ b/qm35s/qm35-spi.c @@ -215,6 +215,13 @@ static long uci_ioctl(struct file *filp, unsigned int cmd, unsigned long args) qm35_hsspi_stop(qm35_hdl); + if (NO_UWB_HAL) { + on = true; + dev_warn( + &qm35_hdl->spi->dev, + "qm35_regulators_set always ON due to NO_UWB_HAL"); + } + if (REGULATORS_ENABLED(qm35_hdl)) qm35_regulators_set(qm35_hdl, on); @@ -384,10 +391,11 @@ static irqreturn_t qm35_ss_rdy_handler(int irq, void *data) gpiod_set_value(qm35_hdl->gpio_wakeup, 0); if (!qm35_hdl->flashing) { - hsspi_clear_spi_slave_busy(&qm35_hdl->hsspi); - hsspi_set_spi_slave_ready(&qm35_hdl->hsspi); + hsspi_set_spi_slave_ready_irq(&qm35_hdl->hsspi); } else { + spin_lock(&qm35_hdl->lock); qm35_hdl->qmrom_qm_ready = true; + spin_unlock(&qm35_hdl->lock); wake_up_interruptible(&qm35_hdl->qmrom_wq_ready); } @@ -834,11 +842,6 @@ static void qm35_regulators_set(struct qm35_ctx *qm35_hdl, bool on) bool is_enabled; int ret; - if (NO_UWB_HAL) { - on = true; - on_str = "enable"; - } - spin_lock(&qm35_hdl->lock); is_enabled = qm35_hdl->regulators_enabled; @@ -1013,6 +1016,8 @@ static int qm35_probe(struct spi_device *spi) } else { qm35_regulators_set(qm35_ctx, true); usleep_range(100000, 100000); + qm35_reset(qm35_ctx, QM_RESET_LOW_MS, true); + msleep(QM_BOOT_MS); qm35_hsspi_start(qm35_ctx); } diff --git a/qm35s/qm35.h b/qm35s/qm35.h index 128da99..22be3d9 100644 --- a/qm35s/qm35.h +++ b/qm35s/qm35.h @@ -28,7 +28,7 @@ #define QM_BOOT_MS 450 #define QM_BEFORE_RESET_MS 450 -#define DRV_VERSION "7.2.7-rc3" +#define DRV_VERSION "7.2.9-rc1" struct regulator; diff --git a/qm35s/qmrom_spi.c b/qm35s/qmrom_spi.c index 99d2584..babf7e2 100644 --- a/qm35s/qmrom_spi.c +++ b/qm35s/qmrom_spi.c @@ -167,6 +167,18 @@ void qmrom_spi_release_firmware(const struct firmware *fw) int qmrom_spi_wait_for_ready_line(void *handle, unsigned int timeout_ms) { struct qm35_ctx *qm35_ctx = (struct qm35_ctx *)handle; + unsigned long flags; + spin_lock_irqsave(&qm35_ctx->lock, flags); + if (gpiod_get_value(qm35_ctx->gpio_ss_rdy) == 0 && + qm35_ctx->qmrom_qm_ready) { + /* + * qmrom_qm_ready should be cleared if ready line is low + * did we run into a glitch on ss-rdy? or did the soc + * crash? + */ + qm35_ctx->qmrom_qm_ready = false; + } + spin_unlock_irqrestore(&qm35_ctx->lock, flags); wait_event_interruptible_timeout(qm35_ctx->qmrom_wq_ready, qm35_ctx->qmrom_qm_ready, |