Unverified Commit 7c1bda09 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'samsung-fixes-6.15' of...

Merge tag 'samsung-fixes-6.15' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into arm/fixes

Samsung SoC driver fixes for v6.15

1. Exynos ACPM driver (used on Google GS101): Fix timeout due to missing
   responses from the firmware part.

2. Samsung USI (serial engines) driver: Correct ineffective
   unconfiguring of the interface during probe removal.

* tag 'samsung-fixes-6.15' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
  soc: samsung: usi: prevent wrong bits inversion during unconfiguring
  firmware: exynos-acpm: check saved RX before bailing out on empty RX queue

Link: https://lore.kernel.org/r/20250513101023.21552-5-krzysztof.kozlowski@linaro.org


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 15eaaa71 dd303e02
Loading
Loading
Loading
Loading
+30 −14
Original line number Diff line number Diff line
@@ -184,6 +184,29 @@ struct acpm_match_data {
#define client_to_acpm_chan(c) container_of(c, struct acpm_chan, cl)
#define handle_to_acpm_info(h) container_of(h, struct acpm_info, handle)

/**
 * acpm_get_saved_rx() - get the response if it was already saved.
 * @achan:	ACPM channel info.
 * @xfer:	reference to the transfer to get response for.
 * @tx_seqnum:	xfer TX sequence number.
 */
static void acpm_get_saved_rx(struct acpm_chan *achan,
			      const struct acpm_xfer *xfer, u32 tx_seqnum)
{
	const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1];
	u32 rx_seqnum;

	if (!rx_data->response)
		return;

	rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);

	if (rx_seqnum == tx_seqnum) {
		memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
		clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
	}
}

/**
 * acpm_get_rx() - get response from RX queue.
 * @achan:	ACPM channel info.
@@ -204,15 +227,16 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
	rx_front = readl(achan->rx.front);
	i = readl(achan->rx.rear);

	/* Bail out if RX is empty. */
	if (i == rx_front)
	tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);

	if (i == rx_front) {
		acpm_get_saved_rx(achan, xfer, tx_seqnum);
		return 0;
	}

	base = achan->rx.base;
	mlen = achan->mlen;

	tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);

	/* Drain RX queue. */
	do {
		/* Read RX seqnum. */
@@ -259,16 +283,8 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
	 * If the response was not in this iteration of the queue, check if the
	 * RX data was previously saved.
	 */
	rx_data = &achan->rx_data[tx_seqnum - 1];
	if (!rx_set && rx_data->response) {
		rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM,
				      rx_data->cmd[0]);

		if (rx_seqnum == tx_seqnum) {
			memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
			clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
		}
	}
	if (!rx_set)
		acpm_get_saved_rx(achan, xfer, tx_seqnum);

	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ static void exynos_usi_unconfigure(void *data)
	/* Make sure that we've stopped providing the clock to USI IP */
	val = readl(usi->regs + USI_OPTION);
	val &= ~USI_OPTION_CLKREQ_ON;
	val |= ~USI_OPTION_CLKSTOP_ON;
	val |= USI_OPTION_CLKSTOP_ON;
	writel(val, usi->regs + USI_OPTION);

	/* Set USI block state to reset */