git: 3c0867343819 - main - spibus: extend API: add cs_delay ivar, KEEP_CS and NO_SLEEP flags

From: Vladimir Kondratyev <wulf_at_FreeBSD.org>
Date: Mon, 24 Apr 2023 09:43:06 UTC
The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=3c086734381945f6d779a98582d8eae3edca0b68

commit 3c086734381945f6d779a98582d8eae3edca0b68
Author:     Val Packett <val@packett.cool>
AuthorDate: 2023-04-24 09:41:52 +0000
Commit:     Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2023-04-24 09:41:52 +0000

    spibus: extend API: add cs_delay ivar, KEEP_CS and NO_SLEEP flags
    
    These feature are required for an upcoming Apple MacBook topcase
    (HID over SPI) driver:
    
    A delay after toggling CS is required to avoid anomalies like an extra
    junk byte in front of the message. Keeping CS asserted is required to
    be able to read a status report after writing a command. (The device
    won't return the status if CS was deasserted.)
    
    Sleep is not allowed in the interrupt context where the Apple input
    driver runs its transactions. Use a flag to tell the SPI driver to
    avoid mtx_sleep.
    
    Reviewed by:    manu (ok to SPI part of larger patch)
    MFC afret:      1 month
    Differential revision:  https://reviews.freebsd.org/D29534
---
 sys/dev/spibus/spi.h       | 4 ++++
 sys/dev/spibus/spibus.c    | 6 ++++++
 sys/dev/spibus/spibusvar.h | 3 +++
 3 files changed, 13 insertions(+)

diff --git a/sys/dev/spibus/spi.h b/sys/dev/spibus/spi.h
index 4cb5c8905b61..fc5b4ab2c148 100644
--- a/sys/dev/spibus/spi.h
+++ b/sys/dev/spibus/spi.h
@@ -34,9 +34,13 @@ struct spi_command {
 	uint32_t tx_data_sz;
 	void	*rx_data;
 	uint32_t rx_data_sz;
+	uint32_t flags;
 };
 #define	SPI_COMMAND_INITIALIZER	{ 0 }
 
+#define	SPI_FLAG_KEEP_CS	0x1		/* Keep chip select asserted */
+#define	SPI_FLAG_NO_SLEEP	0x2		/* Prevent driver from sleeping (use polling) */
+
 #define	SPI_CHIP_SELECT_HIGH	0x1		/* Chip select high (else low) */
 
 #ifdef FDT
diff --git a/sys/dev/spibus/spibus.c b/sys/dev/spibus/spibus.c
index b0b2b5eb73ad..40ebb916a649 100644
--- a/sys/dev/spibus/spibus.c
+++ b/sys/dev/spibus/spibus.c
@@ -146,6 +146,9 @@ spibus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
 	case SPIBUS_IVAR_CLOCK:
 		*(uint32_t *)result = devi->clock;
 		break;
+	case SPIBUS_IVAR_CS_DELAY:
+		*(uint32_t *)result = devi->cs_delay;
+		break;
 	}
 	return (0);
 }
@@ -174,6 +177,9 @@ spibus_write_ivar(device_t bus, device_t child, int which, uintptr_t value)
 			return (EINVAL);
 		devi->mode = (uint32_t)value;
 		break;
+	case SPIBUS_IVAR_CS_DELAY:
+		devi->cs_delay = (uint32_t)value;
+		break;
 	default:
 		return (EINVAL);
 	}
diff --git a/sys/dev/spibus/spibusvar.h b/sys/dev/spibus/spibusvar.h
index 58a7bf784787..db94d30831e6 100644
--- a/sys/dev/spibus/spibusvar.h
+++ b/sys/dev/spibus/spibusvar.h
@@ -43,6 +43,7 @@ struct spibus_ivar
 	uint32_t	cs;
 	uint32_t	mode;
 	uint32_t	clock;
+	uint32_t	cs_delay;
 	struct resource_list	rl;
 };
 
@@ -52,6 +53,7 @@ enum {
 	SPIBUS_IVAR_CS,		/* chip select that we're on */
 	SPIBUS_IVAR_MODE,	/* SPI mode (0-3) */
 	SPIBUS_IVAR_CLOCK,	/* maximum clock freq for device */
+	SPIBUS_IVAR_CS_DELAY,	/* delay in microseconds after toggling chip select */
 };
 
 #define SPIBUS_ACCESSOR(A, B, T)					\
@@ -71,6 +73,7 @@ spibus_set_ ## A(device_t dev, T t)					\
 SPIBUS_ACCESSOR(cs,		CS,		uint32_t)
 SPIBUS_ACCESSOR(mode,		MODE,		uint32_t)
 SPIBUS_ACCESSOR(clock,		CLOCK,		uint32_t)
+SPIBUS_ACCESSOR(cs_delay,		CS_DELAY,		uint32_t)
 
 extern driver_t spibus_driver;
 extern driver_t ofw_spibus_driver;