diff options
author | Andrew Chant <achant@google.com> | 2022-12-16 00:19:43 +0000 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2022-12-16 00:19:43 +0000 |
commit | 2f7d8b7fd5a922910a921a33c7c7c1a3d7483504 (patch) | |
tree | 746d2b15520acc93079ed42a68320612ea94ea20 | |
parent | ddd8bb16843f05c54ee7736a02527ede95aaad60 (diff) | |
download | uwb-2f7d8b7fd5a922910a921a33c7c7c1a3d7483504.tar.gz |
Revert "[R-5.2.2] uwb: update qm35 driver to release R5.2.2"
This reverts commit ddd8bb16843f05c54ee7736a02527ede95aaad60.
Reason for revert: getting back to prior state before mem error
Bug: 262719612
Change-Id: Ibae11e7dc6467978e1e276e8e569008846d7d750
-rw-r--r-- | hsspi.c | 118 | ||||
-rw-r--r-- | hsspi.h | 45 | ||||
-rw-r--r-- | qm35-spi.c | 26 |
3 files changed, 78 insertions, 111 deletions
@@ -44,8 +44,7 @@ #define STC_SOC_ERR BIT(4) #define SS_READY_TIMEOUT_MS (250) - -#define MAX_SUCCESSIVE_ERRORS (5) +#define INTER_CS_ACTIVE_TIME_US (10) struct hsspi_work { struct list_head list; @@ -134,26 +133,13 @@ static int hsspi_wait_ss_ready(struct hsspi *hsspi) { int ret; - 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, - * either the fw went to sleep or crashed, in any case - * we need to wait for it to be ready again. - */ - clear_bit(HSSPI_FLAGS_SS_READY, hsspi->flags); - if (gpiod_get_value(hsspi->gpio_ss_rdy)) { - return 0; - } - } - ret = wait_event_interruptible_timeout( hsspi->wq_ready, test_and_clear_bit(HSSPI_FLAGS_SS_READY, hsspi->flags), msecs_to_jiffies(SS_READY_TIMEOUT_MS)); if (ret == 0) { - dev_warn(&hsspi->spi->dev, - "timed out waiting for ss_ready(%d)\n", - test_bit(HSSPI_FLAGS_SS_READY, hsspi->flags)); + dev_err(&hsspi->spi->dev, "timed out waiting for ss_ready(%d)\n", + test_bit(HSSPI_FLAGS_SS_READY, hsspi->flags)); return -EAGAIN; } if (ret < 0) { @@ -164,6 +150,35 @@ static int hsspi_wait_ss_ready(struct hsspi *hsspi) } /** + * wait_cs_active_min_interval() - waits the time necessary to respect the + * minimium interval between two chip selects active. + * + * @hsspi: &struct hsspi + */ +static void wait_cs_active_min_interval(struct hsspi *hsspi) +{ + /* The HSSPI chip select shall not be activated too early after + * it was deselected. + */ + ktime_t delta = hsspi->next_cs_active_time - ktime_get(); + if (delta > 0) { + delta = ktime_to_us(delta); + usleep_range(delta, delta); + } +} + +/** + * update_next_cs_interval() - update the next time the chip select + * can be activated. + * + * @hsspi: &struct hsspi + */ +static void update_next_cs_interval(struct hsspi *hsspi) +{ + hsspi->next_cs_active_time = ktime_add(ktime_get(), INTER_CS_ACTIVE_TIME_US); +} + +/** * spi_xfer() - Single SPI transfer * * @hsspi: &struct hsspi @@ -186,26 +201,34 @@ static int spi_xfer(struct hsspi *hsspi, const void *tx, void *rx, .len = length, }, }; - int ret, retry = 2; + int ret, retry = 20; hsspi->soc->flags = 0; hsspi->soc->ul = 0; hsspi->soc->length = 0; + if (hsspi->spi_error) + return hsspi->spi_error; + do { + /* The HSSPI chip select shall not be activated too early after + * it was deselected. + */ + wait_cs_active_min_interval(hsspi); hsspi->wakeup_enter(hsspi); ret = hsspi_wait_ss_ready(hsspi); if (ret < 0) { hsspi->wakeup_release(hsspi); + update_next_cs_interval(hsspi); continue; } if (test_sleep_after_ss_ready_us > 0) usleep_range(test_sleep_after_ss_ready_us, test_sleep_after_ss_ready_us+1); - hsspi_set_spi_slave_busy(hsspi); ret = spi_sync_transfer(hsspi->spi, xfers, length ? 2 : 1); hsspi->wakeup_release(hsspi); + update_next_cs_interval(hsspi); trace_hsspi_spi_xfer(&hsspi->spi->dev, hsspi->host, hsspi->soc, ret); @@ -215,9 +238,7 @@ static int spi_xfer(struct hsspi *hsspi, const void *tx, void *rx, } if (!(hsspi->soc->flags & STC_SOC_RDY)) { - dev_err(&hsspi->spi->dev, - "FW not ready (flags %#02x)\n", - hsspi->soc->flags); + dev_err(&hsspi->spi->dev, "FW not ready (flags 0x%02x)\n", hsspi->soc->flags); ret = -EAGAIN; continue; } @@ -236,10 +257,8 @@ static void check_soc_flag(const struct device *dev, const char *func_name, expected = is_tx ? 0x0 : STC_SOC_OA; - if ((soc_flags & (STC_SOC_ERR | STC_SOC_OA)) != expected) { - dev_warn(dev, "%s: bad soc flags %#hhx, expected %#hhx\n", - func_name, soc_flags, expected); - } + if ((soc_flags & (STC_SOC_ERR|STC_SOC_OA)) != expected) + dev_warn(dev, "%s: bad soc flags 0x%hhx\n", func_name, soc_flags); } /** @@ -363,9 +382,7 @@ static int hsspi_pre_read(struct hsspi *hsspi) static int hsspi_thread_fn(void *data) { struct hsspi *hsspi = data; - static int successive_errors; - successive_errors = 0; while (1) { struct hsspi_work *hw; int ret; @@ -391,7 +408,7 @@ static int hsspi_thread_fn(void *data) } else { dev_err(&hsspi->spi->dev, "unknown hsspi_work type: %d\n", hw->type); - continue; + ret = -EINVAL; } } else /* If there is no work, we are here because @@ -400,24 +417,11 @@ static int hsspi_thread_fn(void *data) ret = hsspi_pre_read(hsspi); if (ret) { - successive_errors++; + spin_lock(&hsspi->lock); + hsspi->state = HSSPI_ERROR; + spin_unlock(&hsspi->lock); - if (successive_errors > MAX_SUCCESSIVE_ERRORS) { - dev_err(&hsspi->spi->dev, - "Max successive errors %d reached, likely entered ROM code...\n", - successive_errors); - - /* When the device reboots, the ROM code might raise - * ss_ready; if a SPI transfer is requested, the AP - * will initiate the SPI xfer and the ROM code will - * enter its command mode infinite loop... - * No choice but rebooting the device. - */ - hsspi->reset_qm35(hsspi); - successive_errors = 0; - } - } else { - successive_errors = 0; + hsspi->spi_error = ret; } } return 0; @@ -432,6 +436,7 @@ int hsspi_init(struct hsspi *hsspi, struct spi_device *spi) hsspi->state = HSSPI_STOPPED; hsspi->spi = spi; + hsspi->spi_error = -EAGAIN; init_waitqueue_head(&hsspi->wq); init_waitqueue_head(&hsspi->wq_ready); @@ -449,12 +454,6 @@ int hsspi_init(struct hsspi *hsspi, struct spi_device *spi) return 0; } -void hsspi_set_gpios(struct hsspi *hsspi, struct gpio_desc *gpio_ss_rdy, struct gpio_desc *gpio_exton) -{ - hsspi->gpio_ss_rdy = gpio_ss_rdy; - hsspi->gpio_exton = gpio_exton; -} - int hsspi_deinit(struct hsspi *hsspi) { int i; @@ -556,26 +555,18 @@ 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); -} - void hsspi_set_spi_slave_ready(struct hsspi *hsspi) { + clear_bit(HSSPI_FLAGS_OFF, hsspi->flags); set_bit(HSSPI_FLAGS_SS_READY, hsspi->flags); wake_up_interruptible(&hsspi->wq_ready); } -void hsspi_clear_spi_slave_ready(struct hsspi *hsspi) +void hsspi_set_spi_slave_off(struct hsspi *hsspi) { clear_bit(HSSPI_FLAGS_SS_READY, hsspi->flags); + set_bit(HSSPI_FLAGS_OFF, hsspi->flags); } void hsspi_set_output_data_waiting(struct hsspi *hsspi) @@ -656,6 +647,7 @@ void hsspi_start(struct hsspi *hsspi) spin_lock(&hsspi->lock); hsspi->state = HSSPI_RUNNING; + hsspi->spi_error = 0; spin_unlock(&hsspi->lock); @@ -127,7 +127,7 @@ struct hsspi_layer { enum hsspi_flags { HSSPI_FLAGS_SS_IRQ = 0, HSSPI_FLAGS_SS_READY = 1, - HSSPI_FLAGS_SS_BUSY = 2, + HSSPI_FLAGS_OFF = 2, HSSPI_FLAGS_MAX = 3, }; @@ -165,16 +165,11 @@ struct hsspi { void (*wakeup_enter)(struct hsspi *hsspi); void (*wakeup_release)(struct hsspi *hsspi); - // reset QM35 - void (*reset_qm35)(struct hsspi *hsspi); - struct spi_device *spi; + int spi_error; struct stc_header *host, *soc; ktime_t next_cs_active_time; - - struct gpio_desc *gpio_ss_rdy; - struct gpio_desc *gpio_exton; }; /** @@ -189,8 +184,6 @@ struct hsspi { * */ int hsspi_init(struct hsspi *hsspi, struct spi_device *spi); -void hsspi_set_gpios(struct hsspi *hsspi, struct gpio_desc *gpio_ss_rdy, - struct gpio_desc *gpio_exton); /** * hsspi_deinit() - Initialiaze the HSSPI @@ -232,32 +225,28 @@ int hsspi_unregister(struct hsspi *hsspi, struct hsspi_layer *layer); * * This function is called in the ss_ready irq handler. It notices the * HSSPI driver that the QM is ready for transfer. + * + * The HSSPI must work with or without the ss_rdy gpio. The current + * implementation is far from ideal regarding this requirement. + * + * W/o the gpio we should send SPI transfer right away and retry it if + * the RDY bit was not present in the SOC STC header. */ void hsspi_set_spi_slave_ready(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 - */ -void hsspi_clear_spi_slave_ready(struct hsspi *hsspi); - -/** - * hsspi_set_spi_slave_busy() - tell the hsspi that the ss_ready has - * not been lowered and raised again meaning that the fw is busy, - * @hsspi: pointer to a &struct hsspi - */ -void hsspi_set_spi_slave_busy(struct hsspi *hsspi); - -/** - * hsspi_clear_spi_slave_busy() - tell the hsspi that the ss_ready has - * been lowered and raised again meaning that the fw is not busy anymore, + * hsspi_set_spi_slave_off() - tell the hsspi that qm35 went asleep * @hsspi: pointer to a &struct hsspi * - * This function is called in the ss_ready irq handler. It notices the - * HSSPI driver that the QM has acknowledged the last SPI xfer. + * This function is called in the exton irq handler. It notices the + * HSSPI driver that the QM went asleep. + * + * The HSSPI must work with or without the exton gpio but the sleep + * states on the qm35 would be affected. + * + * W/o the gpio we will ignore the fact that qm35 might have gone asleep. */ -void hsspi_clear_spi_slave_busy(struct hsspi *hsspi); +void hsspi_set_spi_slave_off(struct hsspi *hsspi); /** * hsspi_set_output_data_waiting() - tell the hsspi that the ss_irq is active @@ -97,10 +97,6 @@ int qmrom_retries = QMROM_RETRIES; module_param(qmrom_retries, int, 0444); MODULE_PARM_DESC(qmrom_retries, "QMROM retries"); -int reset_on_error = 1; -module_param(reset_on_error, int, 0444); -MODULE_PARM_DESC(reset_on_error, "Reset the QM35 on successive errors"); - static uint8_t qm_soc_id[ROM_SOC_ID_LEN]; static uint16_t qm_dev_id; @@ -332,7 +328,6 @@ static irqreturn_t qm35_ss_rdy_handler(int irq, void *data) old_time = current_time; #endif - hsspi_clear_spi_slave_busy(&qm35_hdl->hsspi); hsspi_set_spi_slave_ready(&qm35_hdl->hsspi); return IRQ_HANDLED; @@ -360,21 +355,11 @@ static void qm35_wakeup_release(struct hsspi *hsspi) gpiod_set_value(qm35_hdl->gpio_wakeup, 0); } -static void qm35_reset_hook(struct hsspi *hsspi) -{ - struct qm35_ctx *qm35_hdl = - container_of(hsspi, struct qm35_ctx, hsspi); - - if (reset_on_error) - qm35_reset(qm35_hdl, QM_RESET_LOW_MS); - usleep_range(QM_BEFORE_RESET_MS * 1000, QM_BEFORE_RESET_MS * 1000); -} - static irqreturn_t qm35_exton_handler(int irq, void *data) { struct qm35_ctx *qm35_hdl = data; - hsspi_clear_spi_slave_ready(&qm35_hdl->hsspi); + hsspi_set_spi_slave_off(&qm35_hdl->hsspi); return IRQ_HANDLED; } @@ -540,7 +525,6 @@ static int hsspi_irqs_setup(struct qm35_ctx *qm35_ctx) qm35_ctx->hsspi.odw_cleared = reenable_ss_irq; qm35_ctx->hsspi.wakeup_enter = qm35_wakeup_enter; qm35_ctx->hsspi.wakeup_release = qm35_wakeup_release; - qm35_ctx->hsspi.reset_qm35 = qm35_reset_hook; ret = devm_request_irq(&qm35_ctx->spi->dev, qm35_ctx->spi->irq, &qm35_irq_handler, ss_irqflags, @@ -564,7 +548,7 @@ static int hsspi_irqs_setup(struct qm35_ctx *qm35_ctx) return ret; if (!gpiod_get_value(qm35_ctx->gpio_exton)) - hsspi_clear_spi_slave_ready(&qm35_ctx->hsspi); + hsspi_set_spi_slave_off(&qm35_ctx->hsspi); } /* Get spi csn */ @@ -758,10 +742,12 @@ static int qm35_probe(struct spi_device *spi) goto log_layer_unregister; } - hsspi_set_gpios(&qm35_ctx->hsspi, qm35_ctx->gpio_ss_rdy, - qm35_ctx->gpio_exton); hsspi_start(&qm35_ctx->hsspi); + /* we can have missed an edge */ + if (gpiod_get_value(qm35_ctx->gpio_ss_rdy)) + hsspi_set_spi_slave_ready(&qm35_ctx->hsspi); + ret = misc_register(&qm35_ctx->uci_dev); if (ret) { dev_err(&spi->dev, "Failed to register uci device\n"); |