git: 3c0867343819 - main - spibus: extend API: add cs_delay ivar, KEEP_CS and NO_SLEEP flags
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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;