i2c.c revision 1a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1
10840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <errno.h> 20840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <stdint.h> 31a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann#include <string.h> 40840b67ad4db1415094691100441dffe913f76abGreg Hackmann 50840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <gpio.h> 6a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg#include <i2c.h> 70840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <seos.h> 80840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <util.h> 981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#include <atomicBitset.h> 1081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#include <atomic.h> 110840b67ad4db1415094691100441dffe913f76abGreg Hackmann 120840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <plat/inc/cmsis.h> 131a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann#include <plat/inc/dma.h> 140840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <plat/inc/gpio.h> 15de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann#include <plat/inc/i2c.h> 160840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <plat/inc/pwr.h> 170840b67ad4db1415094691100441dffe913f76abGreg Hackmann 1881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#include <cpu/inc/barrier.h> 1981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 2081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#define I2C_VERBOSE_DEBUG 0 2181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#define I2C_MAX_QUEUE_DEPTH 5 220840b67ad4db1415094691100441dffe913f76abGreg Hackmann 230840b67ad4db1415094691100441dffe913f76abGreg Hackmann#if I2C_VERBOSE_DEBUG 249ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann#define i2c_log_debug(x) osLog(LOG_DEBUG, x "\n") 250840b67ad4db1415094691100441dffe913f76abGreg Hackmann#else 260840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define i2c_log_debug(x) do {} while(0) 270840b67ad4db1415094691100441dffe913f76abGreg Hackmann#endif 280840b67ad4db1415094691100441dffe913f76abGreg Hackmann 290840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_PE (1 << 0) 300840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SMBUS (1 << 1) 310840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SMBTYPE (1 << 3) 320840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENARP (1 << 4) 330840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENPEC (1 << 5) 340840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENGC (1 << 6) 350840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_NOSTRETCH (1 << 7) 360840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_START (1 << 8) 370840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_STOP (1 << 9) 380840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ACK (1 << 10) 390840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_POS (1 << 11) 400840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_PEC (1 << 12) 410840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ALERT (1 << 13) 420840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SWRST (1 << 15) 430840b67ad4db1415094691100441dffe913f76abGreg Hackmann 44c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CR2_FREQ(x) ((x) & I2C_CR2_FREQ_MASK) 450840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_FREQ_MASK 0x3F 460840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITERREN (1 << 8) 470840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITEVTEN (1 << 9) 480840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITBUFEN (1 << 10) 490840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_DMAEN (1 << 11) 500840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_LAST (1 << 12) 510840b67ad4db1415094691100441dffe913f76abGreg Hackmann 52c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD7(x) (((x) & I2C_OAR1_ADD7_MASK) << 1) 53c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD7_MASK 0x7F 54c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD10(x) ((x) & I2C_OAR1_ADD10_MASK) 55c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD10_MASK 0x3FF 560840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_OAR1_ADDMODE (1 << 15) 570840b67ad4db1415094691100441dffe913f76abGreg Hackmann 580840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_SB (1 << 0) 590840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ADDR (1 << 1) 600840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_BTF (1 << 2) 610840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ADD10 (1 << 3) 620840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_STOPF (1 << 4) 630840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_RXNE (1 << 6) 640840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_TXE (1 << 7) 650840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_BERR (1 << 8) 660840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ARLO (1 << 9) 670840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_AF (1 << 10) 680840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_OVR (1 << 11) 690840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_PECERR (1 << 12) 700840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_TIMEOUT (1 << 14) 710840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_SMBALERT (1 << 15) 720840b67ad4db1415094691100441dffe913f76abGreg Hackmann 730840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_MSL (1 << 0) 740840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_BUSY (1 << 1) 750840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_TRA (1 << 2) 760840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_GENCALL (1 << 4) 770840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_SMBDEFAULT (1 << 5) 780840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_SMBHOST (1 << 6) 790840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_DUALF (1 << 7) 800840b67ad4db1415094691100441dffe913f76abGreg Hackmann 81c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR(x) ((x) & I2C_CCR_MASK) 82c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_MASK 0xFFF 83c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_DUTY_16_9 (1 << 14) 84c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_FM (1 << 15) 85c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 86c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_TRISE(x) ((x) & I2C_TRISE_MASK) 87c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_TRISE_MASK 0x3F 88c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 89a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2c { 900840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CR1; 910840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CR2; 920840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t OAR1; 930840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t OAR2; 940840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t DR; 950840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t SR1; 960840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t SR2; 970840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CCR; 980840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t TRISE; 990840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t FLTR; 1000840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1010840b67ad4db1415094691100441dffe913f76abGreg Hackmann 10281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemaenum StmI2cSpiMasterState 10381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 10481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_IDLE, 10581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_START, 10681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_TX_ADDR, 10781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_TX_DATA, 10881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_RX_ADDR, 10981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_RX_DATA, 11081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 11181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 112a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct I2cStmState { 1130840b67ad4db1415094691100441dffe913f76abGreg Hackmann struct { 1140840b67ad4db1415094691100441dffe913f76abGreg Hackmann union { 1150840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint8_t *buf; 1160840b67ad4db1415094691100441dffe913f76abGreg Hackmann const uint8_t *cbuf; 1179ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann uint8_t byte; 1180840b67ad4db1415094691100441dffe913f76abGreg Hackmann }; 1190840b67ad4db1415094691100441dffe913f76abGreg Hackmann size_t size; 1200840b67ad4db1415094691100441dffe913f76abGreg Hackmann size_t offset; 1219ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann bool preamble; 1220840b67ad4db1415094691100441dffe913f76abGreg Hackmann 123a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg I2cCallbackF callback; 1240840b67ad4db1415094691100441dffe913f76abGreg Hackmann void *cookie; 1250840b67ad4db1415094691100441dffe913f76abGreg Hackmann } rx, tx; 1260840b67ad4db1415094691100441dffe913f76abGreg Hackmann 1270840b67ad4db1415094691100441dffe913f76abGreg Hackmann enum { 128c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_DISABLED, 129c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_SLAVE, 130c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_MASTER, 131c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } mode; 132c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 133c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema enum { 134c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_SLAVE_IDLE, 1350840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_RX_ARMED, 1360840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_RX, 1370840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_TX_ARMED, 1380840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_TX, 139a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg } slaveState; 140c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 14181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // StmI2cSpiMasterState 14281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState; 1430840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1440840b67ad4db1415094691100441dffe913f76abGreg Hackmann 145a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2cCfg { 146a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct StmI2c *regs; 1470840b67ad4db1415094691100441dffe913f76abGreg Hackmann 1480840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t clock; 1490840b67ad4db1415094691100441dffe913f76abGreg Hackmann 150895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema IRQn_Type irqEv; 151895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema IRQn_Type irqEr; 1520840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1530840b67ad4db1415094691100441dffe913f76abGreg Hackmann 154a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2cDev { 155895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg; 156de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board; 157a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState state; 1580840b67ad4db1415094691100441dffe913f76abGreg Hackmann 15981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t next; 16081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t last; 16181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 162a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg I2cAddr addr; 1630840b67ad4db1415094691100441dffe913f76abGreg Hackmann 164366407f628e806b2b48ccc36e5a2ac5df914f9cbDmitry Grinberg struct Gpio scl; 165366407f628e806b2b48ccc36e5a2ac5df914f9cbDmitry Grinberg struct Gpio sda; 1660840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1670840b67ad4db1415094691100441dffe913f76abGreg Hackmann 16881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic const struct StmI2cCfg mStmI2cCfgs[] = { 16981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [0] = { 17081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C1_BASE, 17181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 17281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C1, 17381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 17481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C1_EV_IRQn, 17581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C1_ER_IRQn, 17681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 17781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [1] = { 17881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C2_BASE, 17981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 18081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C2, 18181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 18281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C2_EV_IRQn, 18381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C2_ER_IRQn, 18481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 18581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [2] = { 18681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C3_BASE, 18781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 18881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C3, 18981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C3_EV_IRQn, 19181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C3_ER_IRQn, 19281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 19381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 19481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic struct StmI2cDev mStmI2cDevs[ARRAY_SIZE(mStmI2cCfgs)]; 19681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastruct StmI2cXfer 19881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 19981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t id; 20081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema const void *txBuf; 20181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema size_t txSize; 20281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema void *rxBuf; 20381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema size_t rxSize; 20481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema I2cCallbackF callback; 20581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema void *cookie; 20681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema I2cBus busId; 20781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema I2cAddr addr; 20881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 20981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21081be7381e3399a0ff4c54222987ab7bd0b1169dfBen FennemaATOMIC_BITSET_DECL(mXfersValid, I2C_MAX_QUEUE_DEPTH, static); 21181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic struct StmI2cXfer mXfers[I2C_MAX_QUEUE_DEPTH] = { }; 21281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic inline struct StmI2cXfer *stmI2cGetXfer(void) 21481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 21581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema int32_t idx = atomicBitsetFindClearAndSet(mXfersValid); 21681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (idx < 0) 21881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return NULL; 21981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema else 22081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return mXfers + idx; 22181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema} 22281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 22381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic inline void stmI2cPutXfer(struct StmI2cXfer *xfer) 22481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 22581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (xfer) 22681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicBitsetClearBit(mXfersValid, xfer - mXfers); 22781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema} 22881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 229b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cAckEnable(struct StmI2cDev *pdev) 2300840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 231895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 |= I2C_CR1_ACK; 2320840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2330840b67ad4db1415094691100441dffe913f76abGreg Hackmann 234b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cAckDisable(struct StmI2cDev *pdev) 2350840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 236895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 &= ~I2C_CR1_ACK; 2370840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2380840b67ad4db1415094691100441dffe913f76abGreg Hackmann 2391a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cDmaEnable(struct StmI2cDev *pdev) 2401a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 2411a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->cfg->regs->CR2 |= I2C_CR2_DMAEN; 2421a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 2431a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 2441a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cDmaDisable(struct StmI2cDev *pdev) 2451a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 2461a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->cfg->regs->CR2 &= ~I2C_CR2_DMAEN; 2471a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 2481a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 249b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cStopEnable(struct StmI2cDev *pdev) 250c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 2516b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 2526b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2536b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann while (regs->CR1 & (I2C_CR1_STOP | I2C_CR1_START)) 2546b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann ; 2556b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann regs->CR1 |= I2C_CR1_STOP; 2566b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann} 2576b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2586b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmannstatic inline void stmI2cStartEnable(struct StmI2cDev *pdev) 2596b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann{ 2606b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 2616b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2626b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann while (regs->CR1 & (I2C_CR1_STOP | I2C_CR1_START)) 2636b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann ; 2646b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann regs->CR1 |= I2C_CR1_START; 265c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 266c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 267b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cIrqEnable(struct StmI2cDev *pdev, 2680840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t mask) 2690840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 270895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR2 |= mask; 2710840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2720840b67ad4db1415094691100441dffe913f76abGreg Hackmann 273b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cIrqDisable(struct StmI2cDev *pdev, 2740840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t mask) 2750840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 276895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR2 &= ~mask; 2770840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2780840b67ad4db1415094691100441dffe913f76abGreg Hackmann 279a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cEnable(struct StmI2cDev *pdev) 2800840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 281895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 |= I2C_CR1_PE; 2820840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2830840b67ad4db1415094691100441dffe913f76abGreg Hackmann 284a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cDisable(struct StmI2cDev *pdev) 2850840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 286895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 &= ~I2C_CR1_PE; 2870840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2880840b67ad4db1415094691100441dffe913f76abGreg Hackmann 289a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cSpeedSet(struct StmI2cDev *pdev, 290a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg const I2cSpeed speed) 291c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 292895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 293c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema int ccr, ccr_1, ccr_2; 294c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema int apb1_clk; 295c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 296c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema apb1_clk = pwrGetBusSpeed(PERIPH_BUS_APB1); 297c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 298c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CR2 = (regs->CR2 & ~I2C_CR2_FREQ_MASK) | 299c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema I2C_CR2_FREQ(apb1_clk / 1000000); 300c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 301c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (speed <= 100000) { 302c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr = apb1_clk / (speed * 2); 303c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr < 4) 304c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr = 4; 305c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR(ccr); 306c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 307c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->TRISE = I2C_TRISE((apb1_clk / 1000000) + 1); 308c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (speed <= 400000) { 309c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_1 = apb1_clk / (speed * 3); 310c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr_1 == 0 || apb1_clk / (ccr_1 * 3) > speed) 311c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_1 ++; 312c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_2 = apb1_clk / (speed * 25); 313c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr_2 == 0 || apb1_clk / (ccr_2 * 25) > speed) 314c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_2 ++; 315c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 316c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if ((apb1_clk / (ccr_1 * 3)) > (apb1_clk / (ccr_2 * 25))) 317c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR_FM | I2C_CCR(ccr_1); 318c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else 319c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR_FM | I2C_CCR_DUTY_16_9 | I2C_CCR(ccr_2); 320c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 321c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->TRISE = I2C_TRISE(((3*apb1_clk)/10000000) + 1); 322c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 323c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 324c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 325a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cSlaveIdle(struct StmI2cDev *pdev) 3260840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 327a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 3280840b67ad4db1415094691100441dffe913f76abGreg Hackmann 329a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX_ARMED; 330b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 331b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 3320840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3330840b67ad4db1415094691100441dffe913f76abGreg Hackmann 334b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveRxDone(struct StmI2cDev *pdev) 3350840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 336a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 337a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg size_t rxOffst = state->rx.offset; 3380840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3390840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.offset = 0; 34062a051ff2d95252651580d9653b391bf94e756fbGreg Hackmann state->rx.callback(state->rx.cookie, 0, rxOffst, 0); 3410840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3420840b67ad4db1415094691100441dffe913f76abGreg Hackmann 343b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveTxDone(struct StmI2cDev *pdev) 3440840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 345a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 346a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg size_t txOffst = state->tx.offset; 3470840b67ad4db1415094691100441dffe913f76abGreg Hackmann 348a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSlaveIdle(pdev); 34962a051ff2d95252651580d9653b391bf94e756fbGreg Hackmann state->tx.callback(state->tx.cookie, txOffst, 0, 0); 350c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 351c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 352b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveTxNextByte(struct StmI2cDev *pdev) 3530840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 354a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 355895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 3560840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3579ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (state->tx.preamble) { 3589ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann regs->DR = state->tx.byte; 3599ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.offset++; 3609ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } else if (state->tx.offset < state->tx.size) { 3610840b67ad4db1415094691100441dffe913f76abGreg Hackmann regs->DR = state->tx.cbuf[state->tx.offset]; 3620840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->tx.offset++; 3630840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 3649ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->slaveState = STM_I2C_SLAVE_TX_ARMED; 365b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN); 3669ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.callback(state->tx.cookie, state->tx.offset, 0, 0); 3670840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 3680840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3690840b67ad4db1415094691100441dffe913f76abGreg Hackmann 370b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveAddrMatched(struct StmI2cDev *pdev) 3710840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 372a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 373895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 3740840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3750840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("addr"); 3760840b67ad4db1415094691100441dffe913f76abGreg Hackmann 377a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_RX_ARMED) { 378a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX; 379b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 380d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else if (state->slaveState == STM_I2C_SLAVE_TX) { 381b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 3820840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 383c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* clear ADDR by doing a dummy reads from SR1 (already read) then SR2 */ 3840840b67ad4db1415094691100441dffe913f76abGreg Hackmann (void)regs->SR2; 3850840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3860840b67ad4db1415094691100441dffe913f76abGreg Hackmann 387b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveStopRxed(struct StmI2cDev *pdev) 3880840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 389895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 3900840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3910840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("stopf"); 3920840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3930840b67ad4db1415094691100441dffe913f76abGreg Hackmann (void)regs->SR1; 394a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 3950840b67ad4db1415094691100441dffe913f76abGreg Hackmann /* clear STOPF by doing a dummy read from SR1 and strobing the PE bit */ 3960840b67ad4db1415094691100441dffe913f76abGreg Hackmann 397a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSlaveIdle(pdev); 398b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxDone(pdev); 3990840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4000840b67ad4db1415094691100441dffe913f76abGreg Hackmann 401b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveRxBufNotEmpty(struct StmI2cDev *pdev) 4020840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 403a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 404895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4050840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint8_t data = regs->DR; 4060840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4070840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("rxne"); 4080840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4090840b67ad4db1415094691100441dffe913f76abGreg Hackmann if (state->rx.offset < state->rx.size) { 4100840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.buf[state->rx.offset] = data; 4110840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.offset++; 4120840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 413b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 4140840b67ad4db1415094691100441dffe913f76abGreg Hackmann /* TODO: error on overflow */ 4150840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4160840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4170840b67ad4db1415094691100441dffe913f76abGreg Hackmann 418b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveTxBufEmpty(struct StmI2cDev *pdev) 4190840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 420a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 4210840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4220840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("txe"); 4230840b67ad4db1415094691100441dffe913f76abGreg Hackmann 424a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_RX) { 425a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_TX_ARMED; 426b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN); 427b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 428b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxDone(pdev); 429b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann /* stmI2cTxNextByte() will happen when the task provides a 4300840b67ad4db1415094691100441dffe913f76abGreg Hackmann TX buffer; the I2C controller will stretch the clock until then */ 4310840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 432b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxNextByte(pdev); 4330840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4340840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4350840b67ad4db1415094691100441dffe913f76abGreg Hackmann 436b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveNakRxed(struct StmI2cDev *pdev) 4370840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 438a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 439895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4400840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4410840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("af"); 4420840b67ad4db1415094691100441dffe913f76abGreg Hackmann 443a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_TX) { 444d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann state->tx.offset--; 445d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann /* NACKs seem to be preceded by a spurious TXNE, so adjust the offset to 446d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann compensate (the corresponding byte written to DR was never actually 447d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann transmitted) */ 448b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxDone(pdev); 4490840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4500840b67ad4db1415094691100441dffe913f76abGreg Hackmann regs->SR1 &= ~I2C_SR1_AF; 4510840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4520840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4531a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cMasterTxRxDone(struct StmI2cDev *pdev, int err) 454b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann{ 455b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann struct I2cStmState *state = &pdev->state; 456b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann size_t txOffst = state->tx.offset; 457b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann size_t rxOffst = state->rx.offset; 458b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann uint32_t id; 459b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann int i; 460b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann struct StmI2cXfer *xfer; 461b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 462b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.offset = 0; 463b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.offset = 0; 4641a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.callback(state->tx.cookie, txOffst, rxOffst, err); 465b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 466b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann do { 467b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann id = atomicAdd(&pdev->next, 1); 468b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } while (!id); 469b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 470b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann for (i=0; i<I2C_MAX_QUEUE_DEPTH; i++) { 471b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann xfer = &mXfers[i]; 472b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 473b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann if (xfer->busId == (pdev - mStmI2cDevs) && 474b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicCmpXchg32bits(&xfer->id, id, 0)) { 475b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann pdev->addr = xfer->addr; 476b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.cbuf = xfer->txBuf; 477b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.offset = 0; 478b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.size = xfer->txSize; 479b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.callback = xfer->callback; 480b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.cookie = xfer->cookie; 481b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.buf = xfer->rxBuf; 482b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.offset = 0; 483b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.size = xfer->rxSize; 484b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.callback = NULL; 485b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.cookie = NULL; 486b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_START); 487b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cPutXfer(xfer); 4886b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann stmI2cStartEnable(pdev); 489b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann return; 490b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } 491b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } 492b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 493b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_IDLE); 494b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann} 495b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 4961a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic void stmI2cMasterDmaTxDone(void *cookie, uint16_t bytesLeft, int err) 4971a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 4981a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2cDev *pdev = cookie; 4991a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct I2cStmState *state = &pdev->state; 5001a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 5011a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5021a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.offset = state->tx.size - bytesLeft; 5031a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.size = 0; 5041a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaDisable(pdev); 5051a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann if (err == 0 && state->rx.size > 0) { 5061a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_START); 5071a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStartEnable(pdev); 5081a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann } else { 5091a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann while (!(regs->SR1 & I2C_SR1_BTF)) 5101a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann ; 5111a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5121a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStopEnable(pdev); 5131a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, err); 5141a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann } 5151a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5161a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5171a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic void stmI2cMasterDmaRxDone(void *cookie, uint16_t bytesLeft, int err) 5181a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5191a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2cDev *pdev = cookie; 5201a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct I2cStmState *state = &pdev->state; 5211a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5221a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.offset = state->rx.size - bytesLeft; 5231a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size = 0; 5241a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5251a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaDisable(pdev); 5261a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStopEnable(pdev); 5271a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, err); 5281a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5291a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5301a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cMasterStartDma(struct StmI2cDev *pdev, 5311a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann const struct StmI2cDmaCfg *dmaCfg, const void *buf, 5321a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann size_t size, DmaCallbackF callback, bool rx, bool last) 5331a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5341a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 5351a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct dmaMode mode; 5361a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5371a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann memset(&mode, 0, sizeof(mode)); 5381a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.priority = DMA_PRIORITY_HIGH; 5391a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.direction = rx ? DMA_DIRECTION_PERIPH_TO_MEM : 5401a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann DMA_DIRECTION_MEM_TO_PERIPH; 5411a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.periphAddr = (uintptr_t)®s->DR; 5421a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.minc = true; 5431a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.channel = dmaCfg->channel; 5441a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5451a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann dmaStart(I2C_DMA_BUS, dmaCfg->stream, buf, size, &mode, callback, pdev); 5461a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann if (last) 5471a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_LAST); 5481a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann else 5491a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_LAST); 5501a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaEnable(pdev); 5511a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5521a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 553b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterSentStart(struct StmI2cDev *pdev) 5540840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 555a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 556895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 5570840b67ad4db1415094691100441dffe913f76abGreg Hackmann 55881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicReadByte(&state->masterState) == STM_I2C_MASTER_START) { 559c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (state->tx.size > 0) { 56081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_TX_ADDR); 561c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->DR = pdev->addr << 1; 562c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 56381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_RX_ADDR); 564b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 565c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->DR = (pdev->addr << 1) | 0x01; 566c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 567c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 5680840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 5690840b67ad4db1415094691100441dffe913f76abGreg Hackmann 570b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterSentAddr(struct StmI2cDev *pdev) 5710840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 572a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 573895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 57481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState = atomicReadByte(&state->masterState); 5750840b67ad4db1415094691100441dffe913f76abGreg Hackmann 57681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (masterState == STM_I2C_MASTER_TX_ADDR) { 5771a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterStartDma(pdev, &pdev->board->dmaTx, state->tx.cbuf, 5781a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.size, stmI2cMasterDmaTxDone, false, !!state->rx.size); 579c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR2; // Clear ADDR 58081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_TX_DATA); 58181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } else if (masterState == STM_I2C_MASTER_RX_ADDR) { 582c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (state->rx.size == 1) // Generate NACK here for 1 byte transfers 583b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 5841a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5851a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterStartDma(pdev, &pdev->board->dmaRx, state->rx.buf, 5861a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size, stmI2cMasterDmaRxDone, true, 5871a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size > 1); 588c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR2; // Clear ADDR 58981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_RX_DATA); 590c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 591c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 592c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 593b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterNakRxed(struct StmI2cDev *pdev) 594c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 595a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 596895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 59781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState = atomicReadByte(&state->masterState); 598c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 59981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (masterState == STM_I2C_MASTER_TX_ADDR || 60081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema masterState == STM_I2C_MASTER_TX_DATA || 60181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema masterState == STM_I2C_MASTER_RX_ADDR || 60281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema masterState == STM_I2C_MASTER_RX_DATA) { 6031a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann dmaStop(I2C_DMA_BUS, pdev->board->dmaRx.stream); 6041a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.offset = state->rx.size - dmaBytesLeft(I2C_DMA_BUS, 6051a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->board->dmaRx.stream); 6061a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann dmaStop(I2C_DMA_BUS, pdev->board->dmaTx.stream); 6071a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.offset = state->tx.size - dmaBytesLeft(I2C_DMA_BUS, 6081a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->board->dmaTx.stream); 6091a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaDisable(pdev); 6101a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 611c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR1 &= ~I2C_SR1_AF; 612b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cStopEnable(pdev); 6131a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, 0); 614c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 615c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 616c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 617a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic void stmI2cIsrEvent(struct StmI2cDev *pdev) 618c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 619895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 620c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema uint16_t sr1 = regs->SR1; 621c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 622c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 623c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_ADDR) { 624b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveAddrMatched(pdev); 625c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_RXNE) { 626b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxBufNotEmpty(pdev); 627c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_TXE) { 628b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxBufEmpty(pdev); 629c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_BTF) { 630c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (regs->SR2 & I2C_SR2_TRA) 631b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxBufEmpty(pdev); 632c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else 633b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxBufNotEmpty(pdev); 634d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else if (sr1 & I2C_SR1_STOPF) { 635b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveStopRxed(pdev); 636c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 637c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* TODO: other flags */ 638c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (pdev->state.mode == STM_I2C_MASTER) { 639c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_SB) 640b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterSentStart(pdev); 641c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else if (sr1 & I2C_SR1_ADDR) 642b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterSentAddr(pdev); 643c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 644c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 645c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 646a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic void stmI2cIsrError(struct StmI2cDev *pdev) 647c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 648895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 649c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema uint16_t sr1 = regs->SR1; 650c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 651c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 652c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_AF) 653b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveNakRxed(pdev); 654c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* TODO: other flags */ 655c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (pdev->state.mode == STM_I2C_MASTER) { 656c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_AF) 657b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterNakRxed(pdev); 658c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 6590840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 6600840b67ad4db1415094691100441dffe913f76abGreg Hackmann 6610840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define DECLARE_IRQ_HANDLERS(_n) \ 6620840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_EV_IRQHandler(); \ 6630840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_ER_IRQHandler(); \ 6640840b67ad4db1415094691100441dffe913f76abGreg Hackmann \ 6650840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_EV_IRQHandler() \ 6660840b67ad4db1415094691100441dffe913f76abGreg Hackmann { \ 667895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cIsrEvent(&mStmI2cDevs[_n - 1]); \ 6680840b67ad4db1415094691100441dffe913f76abGreg Hackmann } \ 6690840b67ad4db1415094691100441dffe913f76abGreg Hackmann \ 6700840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_ER_IRQHandler() \ 6710840b67ad4db1415094691100441dffe913f76abGreg Hackmann { \ 672895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cIsrError(&mStmI2cDevs[_n - 1]); \ 6730840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 6740840b67ad4db1415094691100441dffe913f76abGreg Hackmann 675895ed4022a50ee173631b04b791fe13114bcdd55Ben FennemaDECLARE_IRQ_HANDLERS(1); 676e0771b85c97ed0a90ff0824530a98f4f69e9b1a9Ben FennemaDECLARE_IRQ_HANDLERS(3); 677895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 678de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmannstatic inline void stmI2cGpioInit(struct Gpio *gpio, 679de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board, const struct StmI2cGpioCfg *cfg) 6800840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 681de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann gpioRequest(gpio, cfg->num); 682de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann gpioConfigAlt(gpio, board->gpioSpeed, board->gpioPull, GPIO_OUT_OPEN_DRAIN, 683de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann cfg->func); 6840840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 6850840b67ad4db1415094691100441dffe913f76abGreg Hackmann 686895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennemaint i2cMasterRequest(I2cBus busId, I2cSpeed speed) 6870840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 688895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 6890840b67ad4db1415094691100441dffe913f76abGreg Hackmann return -EINVAL; 6900840b67ad4db1415094691100441dffe913f76abGreg Hackmann 691de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board = boardStmI2cCfg(busId); 692de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann if (!board) 693de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann return -EINVAL; 694de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann 695895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 69681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct I2cStmState *state = &pdev->state; 697895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = &mStmI2cCfgs[busId]; 6980840b67ad4db1415094691100441dffe913f76abGreg Hackmann 69981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode == STM_I2C_DISABLED) { 70081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->mode = STM_I2C_MASTER; 701895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 702895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg = cfg; 703de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann pdev->board = board; 70481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->next = 2; 70581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->last = 1; 70681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicBitsetInit(mXfersValid, I2C_MAX_QUEUE_DEPTH); 707895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 708de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->scl, board, &board->gpioScl); 709de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->sda, board, &board->gpioSda); 710c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 711c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, true); 712c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 713a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cDisable(pdev); 714c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 715c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, true); 716c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, false); 7170840b67ad4db1415094691100441dffe913f76abGreg Hackmann 7181a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITEVTEN | I2C_CR2_ITERREN); 719a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSpeedSet(pdev, speed); 72081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_IDLE); 721c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 722895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEr); 723895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEv); 724c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 725a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 726c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 727c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 728c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 729c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 7300840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 7310840b67ad4db1415094691100441dffe913f76abGreg Hackmann 732895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennemaint i2cMasterRelease(I2cBus busId) 7330840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 734895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 735c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 736c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 737895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 73881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct I2cStmState *state = &pdev->state; 739895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 7400840b67ad4db1415094691100441dffe913f76abGreg Hackmann 74181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode == STM_I2C_MASTER) { 742ddcba9d9835dc96c06488f56f55e5835a46eaff3Ben Fennema if (atomicReadByte(&state->masterState) == STM_I2C_MASTER_IDLE) { 743ddcba9d9835dc96c06488f56f55e5835a46eaff3Ben Fennema state->mode = STM_I2C_DISABLED; 7441a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 74581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema stmI2cDisable(pdev); 74681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, false); 74781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return 0; 74881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } else { 74981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EBUSY; 75081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 751c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 75281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EINVAL; 753c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 754c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 7550840b67ad4db1415094691100441dffe913f76abGreg Hackmann 75681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 757895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennemaint i2cMasterTxRx(I2cBus busId, I2cAddr addr, 758895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const void *txBuf, size_t txSize, void *rxBuf, size_t rxSize, 759895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema I2cCallbackF callback, void *cookie) 760c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 76181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t id; 76281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 763895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 764c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 765c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else if (addr & 0x80) 766c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -ENXIO; 7670840b67ad4db1415094691100441dffe913f76abGreg Hackmann 768895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 769a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 7700840b67ad4db1415094691100441dffe913f76abGreg Hackmann 77181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode != STM_I2C_MASTER) 77281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EINVAL; 773c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 77481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct StmI2cXfer *xfer = stmI2cGetXfer(); 77581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 77681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (xfer) { 77781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->busId = busId; 77881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->addr = addr; 77981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->txBuf = txBuf; 78081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->txSize = txSize; 78181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->rxBuf = rxBuf; 78281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->rxSize = rxSize; 78381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->callback = callback; 78481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->cookie = cookie; 78581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 78681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema do { 78781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema id = atomicAdd(&pdev->last, 1); 78881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } while (!id); 78981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 79081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // after this point the transfer can be picked up by the transfer 79181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // complete interrupt 79281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWrite32bits(&xfer->id, id); 79381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 79481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // only initiate transfer here if we are in IDLE. Otherwise the transfer 79581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // completion interrupt will start the next transfer (not necessarily 79681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // this one) 79781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicCmpXchgByte((uint8_t *)&state->masterState, 79881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_IDLE, STM_I2C_MASTER_START)) { 79981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // it is possible for this transfer to already be complete by the 80081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // time we get here. if so, transfer->id will have been set to 0. 80181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicCmpXchg32bits(&xfer->id, id, 0)) { 80281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->addr = xfer->addr; 80381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.cbuf = xfer->txBuf; 80481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.offset = 0; 80581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.size = xfer->txSize; 80681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.callback = xfer->callback; 80781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.cookie = xfer->cookie; 80881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.buf = xfer->rxBuf; 80981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.offset = 0; 81081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.size = xfer->rxSize; 81181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.callback = NULL; 81281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.cookie = NULL; 81381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema stmI2cPutXfer(xfer); 8146b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann stmI2cStartEnable(pdev); 81581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 81681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 817c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 818c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 819c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 820c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 8210840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 8220840b67ad4db1415094691100441dffe913f76abGreg Hackmann 823895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennemaint i2cSlaveRequest(I2cBus busId, I2cAddr addr) 8240840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 825895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 826c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 827c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 828de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board = boardStmI2cCfg(busId); 829de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann if (!board) 830de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann return -EINVAL; 831de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann 832895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 833895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = &mStmI2cCfgs[busId]; 834c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 835c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_DISABLED) { 836c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->state.mode = STM_I2C_SLAVE; 837c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 838c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->addr = addr; 839895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg = cfg; 840de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann pdev->board = board; 8410840b67ad4db1415094691100441dffe913f76abGreg Hackmann 842de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->scl, board, &board->gpioScl); 843de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->sda, board, &board->gpioSda); 844c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 845c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 846c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 8470840b67ad4db1415094691100441dffe913f76abGreg Hackmann return -EBUSY; 848c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 849c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 8500840b67ad4db1415094691100441dffe913f76abGreg Hackmann 851895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennemaint i2cSlaveRelease(I2cBus busId) 852c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 853895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 854c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 8550840b67ad4db1415094691100441dffe913f76abGreg Hackmann 856895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 857895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 858a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 859c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 860c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->state.mode = STM_I2C_DISABLED; 8611a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 862b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 863895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cDisable(pdev); 864895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, false); 865c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 866c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 867c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 868c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 8690840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 870a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 871895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennemavoid i2cSlaveEnableRx(I2cBus busId, void *rxBuf, size_t rxSize, 872a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg I2cCallbackF callback, void *cookie) 8730840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 874895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 875895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 876a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 877a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 878c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 879366407f628e806b2b48ccc36e5a2ac5df914f9cbDmitry Grinberg state->rx.buf = rxBuf; 880c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.offset = 0; 881895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema state->rx.size = rxSize; 882c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.callback = callback; 883c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.cookie = cookie; 884a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX_ARMED; 885c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 886c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, true); 887c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, true); 888c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, false); 889c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 890895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEr); 891895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEv); 892c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 893a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 894c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema cfg->regs->OAR1 = I2C_OAR1_ADD7(pdev->addr); 895b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 896b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 897c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 8980840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 899a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 9009ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmannstatic int i2cSlaveTx(I2cBus busId, const void *txBuf, uint8_t byte, 9019ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann size_t txSize, I2cCallbackF callback, void *cookie) 902c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 903895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 904a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 905c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 906c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 907d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann if (state->slaveState == STM_I2C_SLAVE_RX) 908c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 909a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 9109ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (txBuf) { 9119ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.cbuf = txBuf; 9129ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.preamble = false; 9139ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } else { 9149ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.byte = byte; 9159ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.preamble = true; 9169ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } 917c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.offset = 0; 918895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema state->tx.size = txSize; 919c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.callback = callback; 920c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.cookie = cookie; 921a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 9229ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (state->slaveState == STM_I2C_SLAVE_TX_ARMED) { 9239ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->slaveState = STM_I2C_SLAVE_TX; 924b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxNextByte(pdev); 925b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN); 926d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else { 927d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann state->slaveState = STM_I2C_SLAVE_TX; 9289ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } 929c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 930c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 931c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 932c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 933c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 934c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 9359ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann 9369ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmannint i2cSlaveTxPreamble(I2cBus busId, uint8_t byte, I2cCallbackF callback, 9379ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann void *cookie) 9389ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann{ 9399ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann return i2cSlaveTx(busId, NULL, byte, 0, callback, cookie); 9409ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann} 9419ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann 9429ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmannint i2cSlaveTxPacket(I2cBus busId, const void *txBuf, size_t txSize, 9439ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann I2cCallbackF callback, void *cookie) 9449ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann{ 9459ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann return i2cSlaveTx(busId, txBuf, 0, txSize, callback, cookie); 9469ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann} 947