i2c.c revision 342c37806ad0ac7d1e5d3f5dff74065d28e5ec3f
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> 11ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema#include <platform.h> 120840b67ad4db1415094691100441dffe913f76abGreg Hackmann 130840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <plat/inc/cmsis.h> 141a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann#include <plat/inc/dma.h> 150840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <plat/inc/gpio.h> 16de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann#include <plat/inc/i2c.h> 170840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <plat/inc/pwr.h> 18ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema#include <plat/inc/plat.h> 190840b67ad4db1415094691100441dffe913f76abGreg Hackmann 2081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#include <cpu/inc/barrier.h> 2181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 2281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#define I2C_VERBOSE_DEBUG 0 2381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#define I2C_MAX_QUEUE_DEPTH 5 240840b67ad4db1415094691100441dffe913f76abGreg Hackmann 250840b67ad4db1415094691100441dffe913f76abGreg Hackmann#if I2C_VERBOSE_DEBUG 269ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann#define i2c_log_debug(x) osLog(LOG_DEBUG, x "\n") 270840b67ad4db1415094691100441dffe913f76abGreg Hackmann#else 280840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define i2c_log_debug(x) do {} while(0) 290840b67ad4db1415094691100441dffe913f76abGreg Hackmann#endif 300840b67ad4db1415094691100441dffe913f76abGreg Hackmann 310840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_PE (1 << 0) 320840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SMBUS (1 << 1) 330840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SMBTYPE (1 << 3) 340840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENARP (1 << 4) 350840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENPEC (1 << 5) 360840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENGC (1 << 6) 370840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_NOSTRETCH (1 << 7) 380840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_START (1 << 8) 390840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_STOP (1 << 9) 400840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ACK (1 << 10) 410840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_POS (1 << 11) 420840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_PEC (1 << 12) 430840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ALERT (1 << 13) 440840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SWRST (1 << 15) 450840b67ad4db1415094691100441dffe913f76abGreg Hackmann 46c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CR2_FREQ(x) ((x) & I2C_CR2_FREQ_MASK) 470840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_FREQ_MASK 0x3F 480840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITERREN (1 << 8) 490840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITEVTEN (1 << 9) 500840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITBUFEN (1 << 10) 510840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_DMAEN (1 << 11) 520840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_LAST (1 << 12) 530840b67ad4db1415094691100441dffe913f76abGreg Hackmann 54c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD7(x) (((x) & I2C_OAR1_ADD7_MASK) << 1) 55c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD7_MASK 0x7F 56c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD10(x) ((x) & I2C_OAR1_ADD10_MASK) 57c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD10_MASK 0x3FF 580840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_OAR1_ADDMODE (1 << 15) 590840b67ad4db1415094691100441dffe913f76abGreg Hackmann 600840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_SB (1 << 0) 610840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ADDR (1 << 1) 620840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_BTF (1 << 2) 630840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ADD10 (1 << 3) 640840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_STOPF (1 << 4) 650840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_RXNE (1 << 6) 660840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_TXE (1 << 7) 670840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_BERR (1 << 8) 680840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ARLO (1 << 9) 690840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_AF (1 << 10) 700840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_OVR (1 << 11) 710840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_PECERR (1 << 12) 720840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_TIMEOUT (1 << 14) 730840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_SMBALERT (1 << 15) 740840b67ad4db1415094691100441dffe913f76abGreg Hackmann 750840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_MSL (1 << 0) 760840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_BUSY (1 << 1) 770840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_TRA (1 << 2) 780840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_GENCALL (1 << 4) 790840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_SMBDEFAULT (1 << 5) 800840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_SMBHOST (1 << 6) 810840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_DUALF (1 << 7) 820840b67ad4db1415094691100441dffe913f76abGreg Hackmann 83c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR(x) ((x) & I2C_CCR_MASK) 84c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_MASK 0xFFF 85c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_DUTY_16_9 (1 << 14) 86c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_FM (1 << 15) 87c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 88c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_TRISE(x) ((x) & I2C_TRISE_MASK) 89c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_TRISE_MASK 0x3F 90c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 91a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2c { 920840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CR1; 930840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CR2; 940840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t OAR1; 950840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t OAR2; 960840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t DR; 970840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t SR1; 980840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t SR2; 990840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CCR; 1000840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t TRISE; 1010840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t FLTR; 1020840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1030840b67ad4db1415094691100441dffe913f76abGreg Hackmann 10481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemaenum StmI2cSpiMasterState 10581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 10681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_IDLE, 10781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_START, 10881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_TX_ADDR, 10981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_TX_DATA, 11081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_RX_ADDR, 11181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_RX_DATA, 11281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 11381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 114a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct I2cStmState { 1150840b67ad4db1415094691100441dffe913f76abGreg Hackmann struct { 1160840b67ad4db1415094691100441dffe913f76abGreg Hackmann union { 1170840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint8_t *buf; 1180840b67ad4db1415094691100441dffe913f76abGreg Hackmann const uint8_t *cbuf; 1199ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann uint8_t byte; 1200840b67ad4db1415094691100441dffe913f76abGreg Hackmann }; 1210840b67ad4db1415094691100441dffe913f76abGreg Hackmann size_t size; 1220840b67ad4db1415094691100441dffe913f76abGreg Hackmann size_t offset; 1239ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann bool preamble; 1240840b67ad4db1415094691100441dffe913f76abGreg Hackmann 125a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg I2cCallbackF callback; 1260840b67ad4db1415094691100441dffe913f76abGreg Hackmann void *cookie; 1270840b67ad4db1415094691100441dffe913f76abGreg Hackmann } rx, tx; 1280840b67ad4db1415094691100441dffe913f76abGreg Hackmann 1290840b67ad4db1415094691100441dffe913f76abGreg Hackmann enum { 130c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_DISABLED, 131c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_SLAVE, 132c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_MASTER, 133c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } mode; 134c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 135c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema enum { 136c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_SLAVE_IDLE, 1370840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_RX_ARMED, 1380840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_RX, 1390840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_TX_ARMED, 1400840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_TX, 141a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg } slaveState; 142c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 14381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // StmI2cSpiMasterState 14481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState; 1450840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1460840b67ad4db1415094691100441dffe913f76abGreg Hackmann 147a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2cCfg { 148a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct StmI2c *regs; 1490840b67ad4db1415094691100441dffe913f76abGreg Hackmann 1500840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t clock; 1510840b67ad4db1415094691100441dffe913f76abGreg Hackmann 152895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema IRQn_Type irqEv; 153895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema IRQn_Type irqEr; 1540840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1550840b67ad4db1415094691100441dffe913f76abGreg Hackmann 156a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2cDev { 157895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg; 158de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board; 159a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState state; 1600840b67ad4db1415094691100441dffe913f76abGreg Hackmann 16181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t next; 16281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t last; 16381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 164366407f628e806b2b48ccc36e5a2ac5df914f9cbDmitry Grinberg struct Gpio scl; 165366407f628e806b2b48ccc36e5a2ac5df914f9cbDmitry Grinberg struct Gpio sda; 166342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg 167342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg uint8_t addr; 1680840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1690840b67ad4db1415094691100441dffe913f76abGreg Hackmann 17081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic const struct StmI2cCfg mStmI2cCfgs[] = { 17181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [0] = { 17281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C1_BASE, 17381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 17481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C1, 17581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 17681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C1_EV_IRQn, 17781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C1_ER_IRQn, 17881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 17981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [1] = { 18081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C2_BASE, 18181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 18281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C2, 18381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 18481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C2_EV_IRQn, 18581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C2_ER_IRQn, 18681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 18781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [2] = { 18881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C3_BASE, 18981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C3, 19181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C3_EV_IRQn, 19381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C3_ER_IRQn, 19481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 19581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 19681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic struct StmI2cDev mStmI2cDevs[ARRAY_SIZE(mStmI2cCfgs)]; 19881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastruct StmI2cXfer 20081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 20181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t id; 20281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema const void *txBuf; 20381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema size_t txSize; 20481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema void *rxBuf; 20581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema size_t rxSize; 20681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema I2cCallbackF callback; 20781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema void *cookie; 208342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg uint8_t busId; /* for us these are both fine in a uint 8 */ 209342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg uint8_t addr; 21081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 21181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21281be7381e3399a0ff4c54222987ab7bd0b1169dfBen FennemaATOMIC_BITSET_DECL(mXfersValid, I2C_MAX_QUEUE_DEPTH, static); 21381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic struct StmI2cXfer mXfers[I2C_MAX_QUEUE_DEPTH] = { }; 21481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic inline struct StmI2cXfer *stmI2cGetXfer(void) 21681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 21781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema int32_t idx = atomicBitsetFindClearAndSet(mXfersValid); 21881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (idx < 0) 22081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return NULL; 22181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema else 22281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return mXfers + idx; 22381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema} 22481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 22581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic inline void stmI2cPutXfer(struct StmI2cXfer *xfer) 22681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 22781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (xfer) 22881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicBitsetClearBit(mXfersValid, xfer - mXfers); 22981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema} 23081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 231b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cAckEnable(struct StmI2cDev *pdev) 2320840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 233895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 |= I2C_CR1_ACK; 2340840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2350840b67ad4db1415094691100441dffe913f76abGreg Hackmann 236b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cAckDisable(struct StmI2cDev *pdev) 2370840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 238895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 &= ~I2C_CR1_ACK; 2390840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2400840b67ad4db1415094691100441dffe913f76abGreg Hackmann 2411a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cDmaEnable(struct StmI2cDev *pdev) 2421a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 2431a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->cfg->regs->CR2 |= I2C_CR2_DMAEN; 2441a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 2451a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 2461a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cDmaDisable(struct StmI2cDev *pdev) 2471a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 2481a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->cfg->regs->CR2 &= ~I2C_CR2_DMAEN; 2491a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 2501a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 251b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cStopEnable(struct StmI2cDev *pdev) 252c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 2536b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 2546b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2556b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann while (regs->CR1 & (I2C_CR1_STOP | I2C_CR1_START)) 2566b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann ; 2576b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann regs->CR1 |= I2C_CR1_STOP; 2586b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann} 2596b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2606b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmannstatic inline void stmI2cStartEnable(struct StmI2cDev *pdev) 2616b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann{ 2626b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 2636b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2646b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann while (regs->CR1 & (I2C_CR1_STOP | I2C_CR1_START)) 2656b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann ; 2666b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann regs->CR1 |= I2C_CR1_START; 267c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 268c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 269b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cIrqEnable(struct StmI2cDev *pdev, 2700840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t mask) 2710840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 272895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR2 |= mask; 2730840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2740840b67ad4db1415094691100441dffe913f76abGreg Hackmann 275b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cIrqDisable(struct StmI2cDev *pdev, 2760840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t mask) 2770840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 278895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR2 &= ~mask; 2790840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2800840b67ad4db1415094691100441dffe913f76abGreg Hackmann 281a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cEnable(struct StmI2cDev *pdev) 2820840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 283895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 |= I2C_CR1_PE; 2840840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2850840b67ad4db1415094691100441dffe913f76abGreg Hackmann 286a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cDisable(struct StmI2cDev *pdev) 2870840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 288895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 &= ~I2C_CR1_PE; 2890840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2900840b67ad4db1415094691100441dffe913f76abGreg Hackmann 291a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cSpeedSet(struct StmI2cDev *pdev, 292342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg const uint32_t speed) 293c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 294895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 295c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema int ccr, ccr_1, ccr_2; 296c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema int apb1_clk; 297c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 298c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema apb1_clk = pwrGetBusSpeed(PERIPH_BUS_APB1); 299c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 300c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CR2 = (regs->CR2 & ~I2C_CR2_FREQ_MASK) | 301c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema I2C_CR2_FREQ(apb1_clk / 1000000); 302c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 303c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (speed <= 100000) { 304c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr = apb1_clk / (speed * 2); 305c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr < 4) 306c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr = 4; 307c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR(ccr); 308c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 309c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->TRISE = I2C_TRISE((apb1_clk / 1000000) + 1); 310c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (speed <= 400000) { 311c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_1 = apb1_clk / (speed * 3); 312c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr_1 == 0 || apb1_clk / (ccr_1 * 3) > speed) 313c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_1 ++; 314c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_2 = apb1_clk / (speed * 25); 315c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr_2 == 0 || apb1_clk / (ccr_2 * 25) > speed) 316c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_2 ++; 317c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 318c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if ((apb1_clk / (ccr_1 * 3)) > (apb1_clk / (ccr_2 * 25))) 319c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR_FM | I2C_CCR(ccr_1); 320c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else 321c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR_FM | I2C_CCR_DUTY_16_9 | I2C_CCR(ccr_2); 322c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 323c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->TRISE = I2C_TRISE(((3*apb1_clk)/10000000) + 1); 324c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 325c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 326c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 327a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cSlaveIdle(struct StmI2cDev *pdev) 3280840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 329a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 3300840b67ad4db1415094691100441dffe913f76abGreg Hackmann 331a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX_ARMED; 332b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 333b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 3340840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3350840b67ad4db1415094691100441dffe913f76abGreg Hackmann 336b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveRxDone(struct StmI2cDev *pdev) 3370840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 338a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 339a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg size_t rxOffst = state->rx.offset; 3400840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3410840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.offset = 0; 34262a051ff2d95252651580d9653b391bf94e756fbGreg Hackmann state->rx.callback(state->rx.cookie, 0, rxOffst, 0); 3430840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3440840b67ad4db1415094691100441dffe913f76abGreg Hackmann 345b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveTxDone(struct StmI2cDev *pdev) 3460840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 347a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 348a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg size_t txOffst = state->tx.offset; 3490840b67ad4db1415094691100441dffe913f76abGreg Hackmann 350a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSlaveIdle(pdev); 35162a051ff2d95252651580d9653b391bf94e756fbGreg Hackmann state->tx.callback(state->tx.cookie, txOffst, 0, 0); 352c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 353c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 354b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveTxNextByte(struct StmI2cDev *pdev) 3550840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 356a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 357895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 3580840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3599ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (state->tx.preamble) { 3609ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann regs->DR = state->tx.byte; 3619ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.offset++; 3629ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } else if (state->tx.offset < state->tx.size) { 3630840b67ad4db1415094691100441dffe913f76abGreg Hackmann regs->DR = state->tx.cbuf[state->tx.offset]; 3640840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->tx.offset++; 3650840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 3669ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->slaveState = STM_I2C_SLAVE_TX_ARMED; 367b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN); 3689ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.callback(state->tx.cookie, state->tx.offset, 0, 0); 3690840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 3700840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3710840b67ad4db1415094691100441dffe913f76abGreg Hackmann 372b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveAddrMatched(struct StmI2cDev *pdev) 3730840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 374a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 375895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 3760840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3770840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("addr"); 3780840b67ad4db1415094691100441dffe913f76abGreg Hackmann 379a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_RX_ARMED) { 380a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX; 381b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 382d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else if (state->slaveState == STM_I2C_SLAVE_TX) { 383b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 3840840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 385c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* clear ADDR by doing a dummy reads from SR1 (already read) then SR2 */ 3860840b67ad4db1415094691100441dffe913f76abGreg Hackmann (void)regs->SR2; 3870840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3880840b67ad4db1415094691100441dffe913f76abGreg Hackmann 389b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveStopRxed(struct StmI2cDev *pdev) 3900840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 391895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 3920840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3930840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("stopf"); 3940840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3950840b67ad4db1415094691100441dffe913f76abGreg Hackmann (void)regs->SR1; 396a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 3970840b67ad4db1415094691100441dffe913f76abGreg Hackmann /* clear STOPF by doing a dummy read from SR1 and strobing the PE bit */ 3980840b67ad4db1415094691100441dffe913f76abGreg Hackmann 399a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSlaveIdle(pdev); 400b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxDone(pdev); 4010840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4020840b67ad4db1415094691100441dffe913f76abGreg Hackmann 403b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveRxBufNotEmpty(struct StmI2cDev *pdev) 4040840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 405a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 406895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4070840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint8_t data = regs->DR; 4080840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4090840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("rxne"); 4100840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4110840b67ad4db1415094691100441dffe913f76abGreg Hackmann if (state->rx.offset < state->rx.size) { 4120840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.buf[state->rx.offset] = data; 4130840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.offset++; 4140840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 415b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 4160840b67ad4db1415094691100441dffe913f76abGreg Hackmann /* TODO: error on overflow */ 4170840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4180840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4190840b67ad4db1415094691100441dffe913f76abGreg Hackmann 420b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveTxBufEmpty(struct StmI2cDev *pdev) 4210840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 422a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 4230840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4240840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("txe"); 4250840b67ad4db1415094691100441dffe913f76abGreg Hackmann 426a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_RX) { 427a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_TX_ARMED; 428b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN); 429b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 430b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxDone(pdev); 431b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann /* stmI2cTxNextByte() will happen when the task provides a 4320840b67ad4db1415094691100441dffe913f76abGreg Hackmann TX buffer; the I2C controller will stretch the clock until then */ 4330840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 434b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxNextByte(pdev); 4350840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4360840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4370840b67ad4db1415094691100441dffe913f76abGreg Hackmann 438b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveNakRxed(struct StmI2cDev *pdev) 4390840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 440a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 441895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4420840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4430840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("af"); 4440840b67ad4db1415094691100441dffe913f76abGreg Hackmann 445a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_TX) { 446d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann state->tx.offset--; 447d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann /* NACKs seem to be preceded by a spurious TXNE, so adjust the offset to 448d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann compensate (the corresponding byte written to DR was never actually 449d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann transmitted) */ 450b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxDone(pdev); 4510840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4520840b67ad4db1415094691100441dffe913f76abGreg Hackmann regs->SR1 &= ~I2C_SR1_AF; 4530840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4540840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4551a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cMasterTxRxDone(struct StmI2cDev *pdev, int err) 456b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann{ 457b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann struct I2cStmState *state = &pdev->state; 458b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann size_t txOffst = state->tx.offset; 459b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann size_t rxOffst = state->rx.offset; 460b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann uint32_t id; 461b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann int i; 462b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann struct StmI2cXfer *xfer; 463b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 464287671677bb946b266dc4c8fc39582533272363cBen Fennema if (pdev->board->sleepDev >= 0) 465287671677bb946b266dc4c8fc39582533272363cBen Fennema platReleaseDevInSleepMode(pdev->board->sleepDev); 466ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema 467b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.offset = 0; 468b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.offset = 0; 4691a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.callback(state->tx.cookie, txOffst, rxOffst, err); 470b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 471b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann do { 472b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann id = atomicAdd(&pdev->next, 1); 473b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } while (!id); 474b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 475b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann for (i=0; i<I2C_MAX_QUEUE_DEPTH; i++) { 476b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann xfer = &mXfers[i]; 477b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 478b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann if (xfer->busId == (pdev - mStmI2cDevs) && 479b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicCmpXchg32bits(&xfer->id, id, 0)) { 480b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann pdev->addr = xfer->addr; 481b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.cbuf = xfer->txBuf; 482b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.offset = 0; 483b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.size = xfer->txSize; 484b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.callback = xfer->callback; 485b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.cookie = xfer->cookie; 486b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.buf = xfer->rxBuf; 487b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.offset = 0; 488b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.size = xfer->rxSize; 489b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.callback = NULL; 490b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.cookie = NULL; 491b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_START); 492287671677bb946b266dc4c8fc39582533272363cBen Fennema if (pdev->board->sleepDev >= 0) 493287671677bb946b266dc4c8fc39582533272363cBen Fennema platRequestDevInSleepMode(pdev->board->sleepDev, 12); 494b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cPutXfer(xfer); 4956b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann stmI2cStartEnable(pdev); 496b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann return; 497b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } 498b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } 499b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 500b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_IDLE); 501b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann} 502b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 5031a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic void stmI2cMasterDmaTxDone(void *cookie, uint16_t bytesLeft, int err) 5041a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5051a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2cDev *pdev = cookie; 5061a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct I2cStmState *state = &pdev->state; 5071a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 5081a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5091a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.offset = state->tx.size - bytesLeft; 5101a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.size = 0; 5111a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaDisable(pdev); 5121a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann if (err == 0 && state->rx.size > 0) { 5131a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_START); 5141a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStartEnable(pdev); 5151a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann } else { 5161a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann while (!(regs->SR1 & I2C_SR1_BTF)) 5171a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann ; 5181a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5191a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStopEnable(pdev); 5201a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, err); 5211a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann } 5221a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5231a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5241a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic void stmI2cMasterDmaRxDone(void *cookie, uint16_t bytesLeft, int err) 5251a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5261a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2cDev *pdev = cookie; 5271a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct I2cStmState *state = &pdev->state; 5281a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5291a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.offset = state->rx.size - bytesLeft; 5301a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size = 0; 5311a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5321a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaDisable(pdev); 5331a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStopEnable(pdev); 5341a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, err); 5351a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5361a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 537102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic inline void stmI2cMasterDmaCancel(struct StmI2cDev *pdev) 538102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 539102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct I2cStmState *state = &pdev->state; 540102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 541102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann dmaStop(I2C_DMA_BUS, pdev->board->dmaRx.stream); 542102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann state->rx.offset = state->rx.size - dmaBytesLeft(I2C_DMA_BUS, 543102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann pdev->board->dmaRx.stream); 544102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann dmaStop(I2C_DMA_BUS, pdev->board->dmaTx.stream); 545102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann state->tx.offset = state->tx.size - dmaBytesLeft(I2C_DMA_BUS, 546102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann pdev->board->dmaTx.stream); 547102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 548102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cDmaDisable(pdev); 549102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 550102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 5511a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cMasterStartDma(struct StmI2cDev *pdev, 5521a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann const struct StmI2cDmaCfg *dmaCfg, const void *buf, 5531a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann size_t size, DmaCallbackF callback, bool rx, bool last) 5541a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5551a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 5561a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct dmaMode mode; 5571a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5581a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann memset(&mode, 0, sizeof(mode)); 5591a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.priority = DMA_PRIORITY_HIGH; 5601a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.direction = rx ? DMA_DIRECTION_PERIPH_TO_MEM : 5611a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann DMA_DIRECTION_MEM_TO_PERIPH; 5621a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.periphAddr = (uintptr_t)®s->DR; 5631a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.minc = true; 5641a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.channel = dmaCfg->channel; 5651a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5661a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann dmaStart(I2C_DMA_BUS, dmaCfg->stream, buf, size, &mode, callback, pdev); 5671a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann if (last) 5681a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_LAST); 5691a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann else 5701a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_LAST); 5711a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaEnable(pdev); 5721a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5731a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 574b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterSentStart(struct StmI2cDev *pdev) 5750840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 576a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 577895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 5780840b67ad4db1415094691100441dffe913f76abGreg Hackmann 57981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicReadByte(&state->masterState) == STM_I2C_MASTER_START) { 580c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (state->tx.size > 0) { 58181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_TX_ADDR); 582c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->DR = pdev->addr << 1; 583c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 58481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_RX_ADDR); 585b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 586c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->DR = (pdev->addr << 1) | 0x01; 587c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 588c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 5890840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 5900840b67ad4db1415094691100441dffe913f76abGreg Hackmann 591b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterSentAddr(struct StmI2cDev *pdev) 5920840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 593a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 594895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 59581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState = atomicReadByte(&state->masterState); 5960840b67ad4db1415094691100441dffe913f76abGreg Hackmann 59781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (masterState == STM_I2C_MASTER_TX_ADDR) { 5981a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterStartDma(pdev, &pdev->board->dmaTx, state->tx.cbuf, 5991a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.size, stmI2cMasterDmaTxDone, false, !!state->rx.size); 600c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR2; // Clear ADDR 60181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_TX_DATA); 60281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } else if (masterState == STM_I2C_MASTER_RX_ADDR) { 603c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (state->rx.size == 1) // Generate NACK here for 1 byte transfers 604b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 6051a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 6061a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterStartDma(pdev, &pdev->board->dmaRx, state->rx.buf, 6071a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size, stmI2cMasterDmaRxDone, true, 6081a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size > 1); 609c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR2; // Clear ADDR 61081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_RX_DATA); 611c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 612c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 613c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 614b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterNakRxed(struct StmI2cDev *pdev) 615c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 616a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 617895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 61881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState = atomicReadByte(&state->masterState); 619c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 62081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (masterState == STM_I2C_MASTER_TX_ADDR || 62181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema masterState == STM_I2C_MASTER_TX_DATA || 62281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema masterState == STM_I2C_MASTER_RX_ADDR || 62381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema masterState == STM_I2C_MASTER_RX_DATA) { 624102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 6251a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 626c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR1 &= ~I2C_SR1_AF; 627b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cStopEnable(pdev); 6281a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, 0); 629c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 630c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 631c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 632102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic void stmI2cMasterBusError(struct StmI2cDev *pdev) 633102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 634102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 635102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 636102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 637102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1 &= ~I2C_SR1_BERR; 638102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterTxRxDone(pdev, EIO); 639102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 640102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 641102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic void stmI2cMasterArbitrationLoss(struct StmI2cDev *pdev) 642102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 643102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 644102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 645102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 646102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1 &= ~I2C_SR1_ARLO; 647102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterTxRxDone(pdev, EBUSY); 648102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 649102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 650102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic void stmI2cMasterUnexpectedError(struct StmI2cDev *pdev) 651102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 652102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 653102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 654102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann osLog(LOG_ERROR, "Unexpected I2C ERR interrupt: SR1 = %04lX, SR2 = %04lX\n", 655102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1, regs->SR2); 656102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 657102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 658102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1 = 0; 659102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterTxRxDone(pdev, EIO); 660102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 661102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 662a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic void stmI2cIsrEvent(struct StmI2cDev *pdev) 663c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 664895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 665c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema uint16_t sr1 = regs->SR1; 666c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 667c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 668c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_ADDR) { 669b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveAddrMatched(pdev); 670c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_RXNE) { 671b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxBufNotEmpty(pdev); 672c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_TXE) { 673b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxBufEmpty(pdev); 674c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_BTF) { 675c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (regs->SR2 & I2C_SR2_TRA) 676b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxBufEmpty(pdev); 677c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else 678b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxBufNotEmpty(pdev); 679d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else if (sr1 & I2C_SR1_STOPF) { 680b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveStopRxed(pdev); 681c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 682c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* TODO: other flags */ 683c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (pdev->state.mode == STM_I2C_MASTER) { 684c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_SB) 685b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterSentStart(pdev); 686c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else if (sr1 & I2C_SR1_ADDR) 687b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterSentAddr(pdev); 688c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 689c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 690c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 691a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic void stmI2cIsrError(struct StmI2cDev *pdev) 692c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 693895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 694c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema uint16_t sr1 = regs->SR1; 695c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 696c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 697c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_AF) 698b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveNakRxed(pdev); 699c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* TODO: other flags */ 700c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (pdev->state.mode == STM_I2C_MASTER) { 701c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_AF) 702b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterNakRxed(pdev); 703102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann else if (sr1 & I2C_SR1_BERR) 704102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterBusError(pdev); 705102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann else if (sr1 & I2C_SR1_ARLO) 706102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterArbitrationLoss(pdev); 707102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann else 708102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterUnexpectedError(pdev); 709c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 7100840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 7110840b67ad4db1415094691100441dffe913f76abGreg Hackmann 7120840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define DECLARE_IRQ_HANDLERS(_n) \ 7130840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_EV_IRQHandler(); \ 7140840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_ER_IRQHandler(); \ 7150840b67ad4db1415094691100441dffe913f76abGreg Hackmann \ 7160840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_EV_IRQHandler() \ 7170840b67ad4db1415094691100441dffe913f76abGreg Hackmann { \ 718895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cIsrEvent(&mStmI2cDevs[_n - 1]); \ 7190840b67ad4db1415094691100441dffe913f76abGreg Hackmann } \ 7200840b67ad4db1415094691100441dffe913f76abGreg Hackmann \ 7210840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_ER_IRQHandler() \ 7220840b67ad4db1415094691100441dffe913f76abGreg Hackmann { \ 723895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cIsrError(&mStmI2cDevs[_n - 1]); \ 7240840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 7250840b67ad4db1415094691100441dffe913f76abGreg Hackmann 726895ed4022a50ee173631b04b791fe13114bcdd55Ben FennemaDECLARE_IRQ_HANDLERS(1); 727e0771b85c97ed0a90ff0824530a98f4f69e9b1a9Ben FennemaDECLARE_IRQ_HANDLERS(3); 728895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 729de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmannstatic inline void stmI2cGpioInit(struct Gpio *gpio, 730de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board, const struct StmI2cGpioCfg *cfg) 7310840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 732de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann gpioRequest(gpio, cfg->num); 733de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann gpioConfigAlt(gpio, board->gpioSpeed, board->gpioPull, GPIO_OUT_OPEN_DRAIN, 734de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann cfg->func); 7350840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 7360840b67ad4db1415094691100441dffe913f76abGreg Hackmann 737342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cMasterRequest(uint32_t busId, uint32_t speed) 7380840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 739895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 7400840b67ad4db1415094691100441dffe913f76abGreg Hackmann return -EINVAL; 7410840b67ad4db1415094691100441dffe913f76abGreg Hackmann 742de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board = boardStmI2cCfg(busId); 743de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann if (!board) 744de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann return -EINVAL; 745de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann 746895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 74781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct I2cStmState *state = &pdev->state; 748895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = &mStmI2cCfgs[busId]; 7490840b67ad4db1415094691100441dffe913f76abGreg Hackmann 75081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode == STM_I2C_DISABLED) { 75181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->mode = STM_I2C_MASTER; 752895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 753895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg = cfg; 754de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann pdev->board = board; 75581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->next = 2; 75681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->last = 1; 75781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicBitsetInit(mXfersValid, I2C_MAX_QUEUE_DEPTH); 758895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 759de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->scl, board, &board->gpioScl); 760de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->sda, board, &board->gpioSda); 761c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 762c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, true); 763c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 764a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cDisable(pdev); 765c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 766c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, true); 767c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, false); 7680840b67ad4db1415094691100441dffe913f76abGreg Hackmann 7691a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITEVTEN | I2C_CR2_ITERREN); 770a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSpeedSet(pdev, speed); 77181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_IDLE); 772c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 773895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEr); 774895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEv); 775c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 776a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 777c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 778c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 779c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 780c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 7810840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 7820840b67ad4db1415094691100441dffe913f76abGreg Hackmann 783342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cMasterRelease(uint32_t busId) 7840840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 785895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 786c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 787c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 788895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 78981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct I2cStmState *state = &pdev->state; 790895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 7910840b67ad4db1415094691100441dffe913f76abGreg Hackmann 79281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode == STM_I2C_MASTER) { 793ddcba9d9835dc96c06488f56f55e5835a46eaff3Ben Fennema if (atomicReadByte(&state->masterState) == STM_I2C_MASTER_IDLE) { 794ddcba9d9835dc96c06488f56f55e5835a46eaff3Ben Fennema state->mode = STM_I2C_DISABLED; 7951a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 79681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema stmI2cDisable(pdev); 79781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, false); 79881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return 0; 79981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } else { 80081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EBUSY; 80181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 802c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 80381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EINVAL; 804c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 805c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 8060840b67ad4db1415094691100441dffe913f76abGreg Hackmann 80781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 808342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cMasterTxRx(uint32_t busId, uint32_t addr, 809895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const void *txBuf, size_t txSize, void *rxBuf, size_t rxSize, 810895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema I2cCallbackF callback, void *cookie) 811c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 81281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t id; 81381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 814895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 815c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 816c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else if (addr & 0x80) 817c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -ENXIO; 8180840b67ad4db1415094691100441dffe913f76abGreg Hackmann 819895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 820a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 8210840b67ad4db1415094691100441dffe913f76abGreg Hackmann 82281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode != STM_I2C_MASTER) 82381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EINVAL; 824c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 82581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct StmI2cXfer *xfer = stmI2cGetXfer(); 82681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 82781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (xfer) { 82881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->busId = busId; 82981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->addr = addr; 83081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->txBuf = txBuf; 83181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->txSize = txSize; 83281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->rxBuf = rxBuf; 83381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->rxSize = rxSize; 83481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->callback = callback; 83581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->cookie = cookie; 83681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 83781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema do { 83881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema id = atomicAdd(&pdev->last, 1); 83981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } while (!id); 84081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 84181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // after this point the transfer can be picked up by the transfer 84281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // complete interrupt 84381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWrite32bits(&xfer->id, id); 84481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 84581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // only initiate transfer here if we are in IDLE. Otherwise the transfer 84681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // completion interrupt will start the next transfer (not necessarily 84781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // this one) 84881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicCmpXchgByte((uint8_t *)&state->masterState, 84981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_IDLE, STM_I2C_MASTER_START)) { 85081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // it is possible for this transfer to already be complete by the 85181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // time we get here. if so, transfer->id will have been set to 0. 85281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicCmpXchg32bits(&xfer->id, id, 0)) { 85381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->addr = xfer->addr; 85481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.cbuf = xfer->txBuf; 85581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.offset = 0; 85681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.size = xfer->txSize; 85781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.callback = xfer->callback; 85881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.cookie = xfer->cookie; 85981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.buf = xfer->rxBuf; 86081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.offset = 0; 86181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.size = xfer->rxSize; 86281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.callback = NULL; 86381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.cookie = NULL; 864287671677bb946b266dc4c8fc39582533272363cBen Fennema if (pdev->board->sleepDev >= 0) 865287671677bb946b266dc4c8fc39582533272363cBen Fennema platRequestDevInSleepMode(pdev->board->sleepDev, 12); 86681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema stmI2cPutXfer(xfer); 8676b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann stmI2cStartEnable(pdev); 86881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 86981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 870c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 871c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 872c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 873c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 8740840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 8750840b67ad4db1415094691100441dffe913f76abGreg Hackmann 876342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveRequest(uint32_t busId, uint32_t addr) 8770840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 878895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 879c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 880c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 881de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board = boardStmI2cCfg(busId); 882de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann if (!board) 883de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann return -EINVAL; 884de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann 885895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 886895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = &mStmI2cCfgs[busId]; 887c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 888c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_DISABLED) { 889c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->state.mode = STM_I2C_SLAVE; 890c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 891c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->addr = addr; 892895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg = cfg; 893de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann pdev->board = board; 8940840b67ad4db1415094691100441dffe913f76abGreg Hackmann 895de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->scl, board, &board->gpioScl); 896de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann stmI2cGpioInit(&pdev->sda, board, &board->gpioSda); 897c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 898c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 899c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 9000840b67ad4db1415094691100441dffe913f76abGreg Hackmann return -EBUSY; 901c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 902c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 9030840b67ad4db1415094691100441dffe913f76abGreg Hackmann 904342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveRelease(uint32_t busId) 905c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 906895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 907c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 9080840b67ad4db1415094691100441dffe913f76abGreg Hackmann 909895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 910895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 911a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 912c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 913c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->state.mode = STM_I2C_DISABLED; 9141a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 915b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 916895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cDisable(pdev); 917895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, false); 918c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 919c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 920c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 921c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 9220840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 923a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 924342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergvoid i2cSlaveEnableRx(uint32_t busId, void *rxBuf, size_t rxSize, 925a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg I2cCallbackF callback, void *cookie) 9260840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 927895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 928895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 929a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 930a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 931c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 932366407f628e806b2b48ccc36e5a2ac5df914f9cbDmitry Grinberg state->rx.buf = rxBuf; 933c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.offset = 0; 934895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema state->rx.size = rxSize; 935c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.callback = callback; 936c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.cookie = cookie; 937a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX_ARMED; 938c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 939c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, true); 940c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, true); 941c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, false); 942c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 943895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEr); 944895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEv); 945c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 946a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 947c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema cfg->regs->OAR1 = I2C_OAR1_ADD7(pdev->addr); 948b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 949b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 950c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 9510840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 952a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 953342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergstatic int i2cSlaveTx(uint32_t busId, const void *txBuf, uint8_t byte, 9549ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann size_t txSize, I2cCallbackF callback, void *cookie) 955c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 956895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 957a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 958c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 959c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 960d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann if (state->slaveState == STM_I2C_SLAVE_RX) 961c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 962a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 9639ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (txBuf) { 9649ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.cbuf = txBuf; 9659ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.preamble = false; 9669ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } else { 9679ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.byte = byte; 9689ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.preamble = true; 9699ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } 970c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.offset = 0; 971895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema state->tx.size = txSize; 972c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.callback = callback; 973c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.cookie = cookie; 974a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 9759ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (state->slaveState == STM_I2C_SLAVE_TX_ARMED) { 9769ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->slaveState = STM_I2C_SLAVE_TX; 977b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxNextByte(pdev); 978b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN); 979d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else { 980d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann state->slaveState = STM_I2C_SLAVE_TX; 9819ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } 982c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 983c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 984c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 985c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 986c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 987c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 9889ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann 989342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveTxPreamble(uint32_t busId, uint8_t byte, I2cCallbackF callback, 9909ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann void *cookie) 9919ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann{ 9929ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann return i2cSlaveTx(busId, NULL, byte, 0, callback, cookie); 9939ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann} 9949ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann 995342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveTxPacket(uint32_t busId, const void *txBuf, size_t txSize, 9969ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann I2cCallbackF callback, void *cookie) 9979ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann{ 9989ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann return i2cSlaveTx(busId, txBuf, 0, txSize, callback, cookie); 9999ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann} 1000