114986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi/* 214986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Copyright (C) 2016 The Android Open Source Project 314986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 414986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Licensed under the Apache License, Version 2.0 (the "License"); 514986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * you may not use this file except in compliance with the License. 614986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * You may obtain a copy of the License at 714986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 814986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * http://www.apache.org/licenses/LICENSE-2.0 914986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 1014986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Unless required by applicable law or agreed to in writing, software 1114986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * distributed under the License is distributed on an "AS IS" BASIS, 1214986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1314986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * See the License for the specific language governing permissions and 1414986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * limitations under the License. 1514986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi */ 1614986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi 170840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <errno.h> 180840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <stdint.h> 191a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann#include <string.h> 200840b67ad4db1415094691100441dffe913f76abGreg Hackmann 210840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <gpio.h> 22a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg#include <i2c.h> 230840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <seos.h> 240840b67ad4db1415094691100441dffe913f76abGreg Hackmann#include <util.h> 2571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg#include <gpio.h> 2681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#include <atomicBitset.h> 2781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#include <atomic.h> 28ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema#include <platform.h> 290840b67ad4db1415094691100441dffe913f76abGreg Hackmann 30f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/cmsis.h> 31f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/dma.h> 32f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/gpio.h> 33f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/i2c.h> 34f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/pwr.h> 35f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/plat.h> 360840b67ad4db1415094691100441dffe913f76abGreg Hackmann 37f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <cpu/barrier.h> 3881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 3981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#define I2C_VERBOSE_DEBUG 0 4081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema#define I2C_MAX_QUEUE_DEPTH 5 410840b67ad4db1415094691100441dffe913f76abGreg Hackmann 420840b67ad4db1415094691100441dffe913f76abGreg Hackmann#if I2C_VERBOSE_DEBUG 439ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann#define i2c_log_debug(x) osLog(LOG_DEBUG, x "\n") 440840b67ad4db1415094691100441dffe913f76abGreg Hackmann#else 450840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define i2c_log_debug(x) do {} while(0) 460840b67ad4db1415094691100441dffe913f76abGreg Hackmann#endif 470840b67ad4db1415094691100441dffe913f76abGreg Hackmann 480840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_PE (1 << 0) 490840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SMBUS (1 << 1) 500840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SMBTYPE (1 << 3) 510840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENARP (1 << 4) 520840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENPEC (1 << 5) 530840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ENGC (1 << 6) 540840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_NOSTRETCH (1 << 7) 550840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_START (1 << 8) 560840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_STOP (1 << 9) 570840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ACK (1 << 10) 580840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_POS (1 << 11) 590840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_PEC (1 << 12) 600840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_ALERT (1 << 13) 610840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR1_SWRST (1 << 15) 620840b67ad4db1415094691100441dffe913f76abGreg Hackmann 63c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CR2_FREQ(x) ((x) & I2C_CR2_FREQ_MASK) 640840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_FREQ_MASK 0x3F 650840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITERREN (1 << 8) 660840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITEVTEN (1 << 9) 670840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_ITBUFEN (1 << 10) 680840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_DMAEN (1 << 11) 690840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_CR2_LAST (1 << 12) 700840b67ad4db1415094691100441dffe913f76abGreg Hackmann 71c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD7(x) (((x) & I2C_OAR1_ADD7_MASK) << 1) 72c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD7_MASK 0x7F 73c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD10(x) ((x) & I2C_OAR1_ADD10_MASK) 74c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_OAR1_ADD10_MASK 0x3FF 750840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_OAR1_ADDMODE (1 << 15) 760840b67ad4db1415094691100441dffe913f76abGreg Hackmann 770840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_SB (1 << 0) 780840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ADDR (1 << 1) 790840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_BTF (1 << 2) 800840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ADD10 (1 << 3) 810840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_STOPF (1 << 4) 820840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_RXNE (1 << 6) 830840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_TXE (1 << 7) 840840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_BERR (1 << 8) 850840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_ARLO (1 << 9) 860840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_AF (1 << 10) 870840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_OVR (1 << 11) 880840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_PECERR (1 << 12) 890840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_TIMEOUT (1 << 14) 900840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR1_SMBALERT (1 << 15) 910840b67ad4db1415094691100441dffe913f76abGreg Hackmann 920840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_MSL (1 << 0) 930840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_BUSY (1 << 1) 940840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_TRA (1 << 2) 950840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_GENCALL (1 << 4) 960840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_SMBDEFAULT (1 << 5) 970840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_SMBHOST (1 << 6) 980840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define I2C_SR2_DUALF (1 << 7) 990840b67ad4db1415094691100441dffe913f76abGreg Hackmann 100c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR(x) ((x) & I2C_CCR_MASK) 101c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_MASK 0xFFF 102c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_DUTY_16_9 (1 << 14) 103c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_CCR_FM (1 << 15) 104c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 105c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_TRISE(x) ((x) & I2C_TRISE_MASK) 106c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema#define I2C_TRISE_MASK 0x3F 107c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 108a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2c { 1090840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CR1; 1100840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CR2; 1110840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t OAR1; 1120840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t OAR2; 1130840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t DR; 1140840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t SR1; 1150840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t SR2; 1160840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t CCR; 1170840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t TRISE; 1180840b67ad4db1415094691100441dffe913f76abGreg Hackmann volatile uint32_t FLTR; 1190840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1200840b67ad4db1415094691100441dffe913f76abGreg Hackmann 12181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemaenum StmI2cSpiMasterState 12281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 12381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_IDLE, 12481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_START, 12581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_TX_ADDR, 12681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_TX_DATA, 12781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_RX_ADDR, 12881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_RX_DATA, 12981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 13081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 131a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct I2cStmState { 1320840b67ad4db1415094691100441dffe913f76abGreg Hackmann struct { 1330840b67ad4db1415094691100441dffe913f76abGreg Hackmann union { 1340840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint8_t *buf; 1350840b67ad4db1415094691100441dffe913f76abGreg Hackmann const uint8_t *cbuf; 1369ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann uint8_t byte; 1370840b67ad4db1415094691100441dffe913f76abGreg Hackmann }; 1380840b67ad4db1415094691100441dffe913f76abGreg Hackmann size_t size; 1390840b67ad4db1415094691100441dffe913f76abGreg Hackmann size_t offset; 1409ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann bool preamble; 1410840b67ad4db1415094691100441dffe913f76abGreg Hackmann 142a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg I2cCallbackF callback; 1430840b67ad4db1415094691100441dffe913f76abGreg Hackmann void *cookie; 1440840b67ad4db1415094691100441dffe913f76abGreg Hackmann } rx, tx; 1450840b67ad4db1415094691100441dffe913f76abGreg Hackmann 1460840b67ad4db1415094691100441dffe913f76abGreg Hackmann enum { 147c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_DISABLED, 148c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_SLAVE, 149c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_MASTER, 150c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } mode; 151c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 152c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema enum { 153c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema STM_I2C_SLAVE_IDLE, 1540840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_RX_ARMED, 1550840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_RX, 1560840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_TX_ARMED, 1570840b67ad4db1415094691100441dffe913f76abGreg Hackmann STM_I2C_SLAVE_TX, 158a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg } slaveState; 159c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 16081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // StmI2cSpiMasterState 16181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState; 162c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov uint16_t tid; 1630840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1640840b67ad4db1415094691100441dffe913f76abGreg Hackmann 165a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2cCfg { 166a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct StmI2c *regs; 1670840b67ad4db1415094691100441dffe913f76abGreg Hackmann 1680840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t clock; 1690840b67ad4db1415094691100441dffe913f76abGreg Hackmann 170895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema IRQn_Type irqEv; 171895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema IRQn_Type irqEr; 1720840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1730840b67ad4db1415094691100441dffe913f76abGreg Hackmann 174a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstruct StmI2cDev { 175895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg; 176de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board; 177a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState state; 1780840b67ad4db1415094691100441dffe913f76abGreg Hackmann 17981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t next; 18081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t last; 18181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 18271b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct Gpio *scl; 18371b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct Gpio *sda; 184342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg 185342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg uint8_t addr; 1860840b67ad4db1415094691100441dffe913f76abGreg Hackmann}; 1870840b67ad4db1415094691100441dffe913f76abGreg Hackmann 18881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic const struct StmI2cCfg mStmI2cCfgs[] = { 18981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [0] = { 19081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C1_BASE, 19181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C1, 19381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 19481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C1_EV_IRQn, 19581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C1_ER_IRQn, 19681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 19781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [1] = { 19881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C2_BASE, 19981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 20081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C2, 20181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 20281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C2_EV_IRQn, 20381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C2_ER_IRQn, 20481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 20581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema [2] = { 20681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .regs = (struct StmI2c *)I2C3_BASE, 20781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 20881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .clock = PERIPH_APB1_I2C3, 20981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEv = I2C3_EV_IRQn, 21181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema .irqEr = I2C3_ER_IRQn, 21281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema }, 21381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 21481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic struct StmI2cDev mStmI2cDevs[ARRAY_SIZE(mStmI2cCfgs)]; 21681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 21781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastruct StmI2cXfer 21881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 21981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t id; 22081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema const void *txBuf; 22181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema size_t txSize; 22281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema void *rxBuf; 22381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema size_t rxSize; 22481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema I2cCallbackF callback; 22581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema void *cookie; 226342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg uint8_t busId; /* for us these are both fine in a uint 8 */ 227342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg uint8_t addr; 228f62fa5ad2731c3f0711eacc4a623ed6cfd3e05beBen Fennema uint16_t tid; 22981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema}; 23081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 23181be7381e3399a0ff4c54222987ab7bd0b1169dfBen FennemaATOMIC_BITSET_DECL(mXfersValid, I2C_MAX_QUEUE_DEPTH, static); 23281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic struct StmI2cXfer mXfers[I2C_MAX_QUEUE_DEPTH] = { }; 23381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 23481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic inline struct StmI2cXfer *stmI2cGetXfer(void) 23581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 23681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema int32_t idx = atomicBitsetFindClearAndSet(mXfersValid); 23781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 23881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (idx < 0) 23981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return NULL; 24081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema else 24181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return mXfers + idx; 24281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema} 24381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 24481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennemastatic inline void stmI2cPutXfer(struct StmI2cXfer *xfer) 24581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema{ 24681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (xfer) 24781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicBitsetClearBit(mXfersValid, xfer - mXfers); 24881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema} 24981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 250b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cAckEnable(struct StmI2cDev *pdev) 2510840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 252895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 |= I2C_CR1_ACK; 2530840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2540840b67ad4db1415094691100441dffe913f76abGreg Hackmann 255b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cAckDisable(struct StmI2cDev *pdev) 2560840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 257895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 &= ~I2C_CR1_ACK; 2580840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2590840b67ad4db1415094691100441dffe913f76abGreg Hackmann 2601a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cDmaEnable(struct StmI2cDev *pdev) 2611a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 2621a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->cfg->regs->CR2 |= I2C_CR2_DMAEN; 2631a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 2641a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 2651a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cDmaDisable(struct StmI2cDev *pdev) 2661a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 2671a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann pdev->cfg->regs->CR2 &= ~I2C_CR2_DMAEN; 2681a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 2691a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 270b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cStopEnable(struct StmI2cDev *pdev) 271c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 2726b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 2736b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2746b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann while (regs->CR1 & (I2C_CR1_STOP | I2C_CR1_START)) 2756b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann ; 2766b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann regs->CR1 |= I2C_CR1_STOP; 2776b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann} 2786b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2796b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmannstatic inline void stmI2cStartEnable(struct StmI2cDev *pdev) 2806b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann{ 2816b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 2826b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann 2836b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann while (regs->CR1 & (I2C_CR1_STOP | I2C_CR1_START)) 2846b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann ; 2856b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann regs->CR1 |= I2C_CR1_START; 286c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 287c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 288b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cIrqEnable(struct StmI2cDev *pdev, 2890840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t mask) 2900840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 291895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR2 |= mask; 2920840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2930840b67ad4db1415094691100441dffe913f76abGreg Hackmann 294b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cIrqDisable(struct StmI2cDev *pdev, 2950840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint32_t mask) 2960840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 297895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR2 &= ~mask; 2980840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 2990840b67ad4db1415094691100441dffe913f76abGreg Hackmann 300a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cEnable(struct StmI2cDev *pdev) 3010840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 302895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 |= I2C_CR1_PE; 3030840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3040840b67ad4db1415094691100441dffe913f76abGreg Hackmann 305a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cDisable(struct StmI2cDev *pdev) 3060840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 307895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg->regs->CR1 &= ~I2C_CR1_PE; 3080840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3090840b67ad4db1415094691100441dffe913f76abGreg Hackmann 310a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cSpeedSet(struct StmI2cDev *pdev, 311342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinberg const uint32_t speed) 312c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 313895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 314c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema int ccr, ccr_1, ccr_2; 315c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema int apb1_clk; 316c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 317c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema apb1_clk = pwrGetBusSpeed(PERIPH_BUS_APB1); 318c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 319c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CR2 = (regs->CR2 & ~I2C_CR2_FREQ_MASK) | 320c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema I2C_CR2_FREQ(apb1_clk / 1000000); 321c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 322c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (speed <= 100000) { 323c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr = apb1_clk / (speed * 2); 324c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr < 4) 325c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr = 4; 326c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR(ccr); 327c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 328c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->TRISE = I2C_TRISE((apb1_clk / 1000000) + 1); 329c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (speed <= 400000) { 330c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_1 = apb1_clk / (speed * 3); 331c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr_1 == 0 || apb1_clk / (ccr_1 * 3) > speed) 332c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_1 ++; 333c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_2 = apb1_clk / (speed * 25); 334c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (ccr_2 == 0 || apb1_clk / (ccr_2 * 25) > speed) 335c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema ccr_2 ++; 336c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 337c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if ((apb1_clk / (ccr_1 * 3)) > (apb1_clk / (ccr_2 * 25))) 338c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR_FM | I2C_CCR(ccr_1); 339c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else 340c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->CCR = I2C_CCR_FM | I2C_CCR_DUTY_16_9 | I2C_CCR(ccr_2); 341c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 342c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->TRISE = I2C_TRISE(((3*apb1_clk)/10000000) + 1); 343c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 344c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 345c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 346a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic inline void stmI2cSlaveIdle(struct StmI2cDev *pdev) 3470840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 348a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 3490840b67ad4db1415094691100441dffe913f76abGreg Hackmann 350a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX_ARMED; 351b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 352b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 3530840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3540840b67ad4db1415094691100441dffe913f76abGreg Hackmann 355c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudovstatic inline void stmI2cInvokeRxCallback(struct I2cStmState *state, size_t tx, size_t rx, int err) 356c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov{ 357c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov uint16_t oldTid = osSetCurrentTid(state->tid); 358c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov state->rx.callback(state->rx.cookie, tx, rx, err); 359c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov osSetCurrentTid(oldTid); 360c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov} 361c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov 362c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudovstatic inline void stmI2cInvokeTxCallback(struct I2cStmState *state, size_t tx, size_t rx, int err) 363c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov{ 364c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov uint16_t oldTid = osSetCurrentTid(state->tid); 365c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov state->tx.callback(state->tx.cookie, tx, rx, err); 366c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov osSetCurrentTid(oldTid); 367c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov} 368c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov 369b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveRxDone(struct StmI2cDev *pdev) 3700840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 371a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 372a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg size_t rxOffst = state->rx.offset; 3730840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3740840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.offset = 0; 375c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov stmI2cInvokeRxCallback(state, 0, rxOffst, 0); 3760840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 3770840b67ad4db1415094691100441dffe913f76abGreg Hackmann 378b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveTxDone(struct StmI2cDev *pdev) 3790840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 380a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 381a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg size_t txOffst = state->tx.offset; 3820840b67ad4db1415094691100441dffe913f76abGreg Hackmann 383a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSlaveIdle(pdev); 384c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov stmI2cInvokeTxCallback(state, txOffst, 0, 0); 385c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 386c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 387b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveTxNextByte(struct StmI2cDev *pdev) 3880840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 389a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 390895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 3910840b67ad4db1415094691100441dffe913f76abGreg Hackmann 3929ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (state->tx.preamble) { 3939ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann regs->DR = state->tx.byte; 3949ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.offset++; 3959ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } else if (state->tx.offset < state->tx.size) { 3960840b67ad4db1415094691100441dffe913f76abGreg Hackmann regs->DR = state->tx.cbuf[state->tx.offset]; 3970840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->tx.offset++; 3980840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 3999ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->slaveState = STM_I2C_SLAVE_TX_ARMED; 400b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN); 401c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov stmI2cInvokeTxCallback(state, state->tx.offset, 0, 0); 4020840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4030840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4040840b67ad4db1415094691100441dffe913f76abGreg Hackmann 405b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveAddrMatched(struct StmI2cDev *pdev) 4060840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 407a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 408895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4090840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4100840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("addr"); 4110840b67ad4db1415094691100441dffe913f76abGreg Hackmann 412a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_RX_ARMED) { 413a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX; 414b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 415d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else if (state->slaveState == STM_I2C_SLAVE_TX) { 416b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); 4170840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 418c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* clear ADDR by doing a dummy reads from SR1 (already read) then SR2 */ 4190840b67ad4db1415094691100441dffe913f76abGreg Hackmann (void)regs->SR2; 4200840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4210840b67ad4db1415094691100441dffe913f76abGreg Hackmann 422b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveStopRxed(struct StmI2cDev *pdev) 4230840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 424895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4250840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4260840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("stopf"); 4270840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4280840b67ad4db1415094691100441dffe913f76abGreg Hackmann (void)regs->SR1; 429a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 4300840b67ad4db1415094691100441dffe913f76abGreg Hackmann /* clear STOPF by doing a dummy read from SR1 and strobing the PE bit */ 4310840b67ad4db1415094691100441dffe913f76abGreg Hackmann 432a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSlaveIdle(pdev); 433b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxDone(pdev); 4340840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4350840b67ad4db1415094691100441dffe913f76abGreg Hackmann 436b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic inline void stmI2cSlaveRxBufNotEmpty(struct StmI2cDev *pdev) 4370840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 438a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 439895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4400840b67ad4db1415094691100441dffe913f76abGreg Hackmann uint8_t data = regs->DR; 4410840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4420840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("rxne"); 4430840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4440840b67ad4db1415094691100441dffe913f76abGreg Hackmann if (state->rx.offset < state->rx.size) { 4450840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.buf[state->rx.offset] = data; 4460840b67ad4db1415094691100441dffe913f76abGreg Hackmann state->rx.offset++; 4470840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 448b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 4490840b67ad4db1415094691100441dffe913f76abGreg Hackmann /* TODO: error on overflow */ 4500840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4510840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4520840b67ad4db1415094691100441dffe913f76abGreg Hackmann 453b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveTxBufEmpty(struct StmI2cDev *pdev) 4540840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 455a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 4560840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4570840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("txe"); 4580840b67ad4db1415094691100441dffe913f76abGreg Hackmann 459a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_RX) { 460a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_TX_ARMED; 461b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITBUFEN); 462b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 463b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxDone(pdev); 464b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann /* stmI2cTxNextByte() will happen when the task provides a 4650840b67ad4db1415094691100441dffe913f76abGreg Hackmann TX buffer; the I2C controller will stretch the clock until then */ 4660840b67ad4db1415094691100441dffe913f76abGreg Hackmann } else { 467b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxNextByte(pdev); 4680840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4690840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4700840b67ad4db1415094691100441dffe913f76abGreg Hackmann 471b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cSlaveNakRxed(struct StmI2cDev *pdev) 4720840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 473a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 474895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 4750840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4760840b67ad4db1415094691100441dffe913f76abGreg Hackmann i2c_log_debug("af"); 4770840b67ad4db1415094691100441dffe913f76abGreg Hackmann 478a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg if (state->slaveState == STM_I2C_SLAVE_TX) { 479d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann state->tx.offset--; 480d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann /* NACKs seem to be preceded by a spurious TXNE, so adjust the offset to 481d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann compensate (the corresponding byte written to DR was never actually 482d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann transmitted) */ 483b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxDone(pdev); 4840840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 4850840b67ad4db1415094691100441dffe913f76abGreg Hackmann regs->SR1 &= ~I2C_SR1_AF; 4860840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 4870840b67ad4db1415094691100441dffe913f76abGreg Hackmann 4881a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cMasterTxRxDone(struct StmI2cDev *pdev, int err) 489b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann{ 490b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann struct I2cStmState *state = &pdev->state; 491b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann size_t txOffst = state->tx.offset; 492b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann size_t rxOffst = state->rx.offset; 493b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann uint32_t id; 494b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann int i; 495b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann struct StmI2cXfer *xfer; 496b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 497287671677bb946b266dc4c8fc39582533272363cBen Fennema if (pdev->board->sleepDev >= 0) 498287671677bb946b266dc4c8fc39582533272363cBen Fennema platReleaseDevInSleepMode(pdev->board->sleepDev); 499ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema 500b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.offset = 0; 501b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.offset = 0; 50272638ba906c8825313090d4d4aac66b809659e85Ben Fennema stmI2cInvokeTxCallback(state, txOffst, rxOffst, err); 503b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 504b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann do { 5058cf410ff3b2d8a09f3aa2b5ca10253732e8e6f78Alexey Polyudov id = atomicAdd32bits(&pdev->next, 1); 506b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } while (!id); 507b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 508b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann for (i=0; i<I2C_MAX_QUEUE_DEPTH; i++) { 509b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann xfer = &mXfers[i]; 510b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 511b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann if (xfer->busId == (pdev - mStmI2cDevs) && 512b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicCmpXchg32bits(&xfer->id, id, 0)) { 513b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann pdev->addr = xfer->addr; 514b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.cbuf = xfer->txBuf; 515b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.offset = 0; 516b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.size = xfer->txSize; 517b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.callback = xfer->callback; 518b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->tx.cookie = xfer->cookie; 519b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.buf = xfer->rxBuf; 520b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.offset = 0; 521b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.size = xfer->rxSize; 522b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.callback = NULL; 523b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann state->rx.cookie = NULL; 524f62fa5ad2731c3f0711eacc4a623ed6cfd3e05beBen Fennema state->tid = xfer->tid; 525b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_START); 526287671677bb946b266dc4c8fc39582533272363cBen Fennema if (pdev->board->sleepDev >= 0) 527287671677bb946b266dc4c8fc39582533272363cBen Fennema platRequestDevInSleepMode(pdev->board->sleepDev, 12); 528b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cPutXfer(xfer); 5296b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann stmI2cStartEnable(pdev); 530b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann return; 531b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } 532b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann } 533b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 534b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_IDLE); 535b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann} 536b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann 5371a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic void stmI2cMasterDmaTxDone(void *cookie, uint16_t bytesLeft, int err) 5381a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5391a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2cDev *pdev = cookie; 5401a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct I2cStmState *state = &pdev->state; 5411a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 5421a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5431a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.offset = state->tx.size - bytesLeft; 5441a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.size = 0; 5451a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaDisable(pdev); 5461a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann if (err == 0 && state->rx.size > 0) { 5471a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann atomicWriteByte(&state->masterState, STM_I2C_MASTER_START); 5481a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStartEnable(pdev); 5491a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann } else { 5501a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann while (!(regs->SR1 & I2C_SR1_BTF)) 5511a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann ; 5521a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5531a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStopEnable(pdev); 5541a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, err); 5551a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann } 5561a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5571a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5581a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic void stmI2cMasterDmaRxDone(void *cookie, uint16_t bytesLeft, int err) 5591a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5601a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2cDev *pdev = cookie; 5611a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct I2cStmState *state = &pdev->state; 5621a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5631a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.offset = state->rx.size - bytesLeft; 5641a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size = 0; 5651a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5661a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaDisable(pdev); 5671a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cStopEnable(pdev); 5681a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterTxRxDone(pdev, err); 5691a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 5701a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 571102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic inline void stmI2cMasterDmaCancel(struct StmI2cDev *pdev) 572102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 573102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct I2cStmState *state = &pdev->state; 574102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 575102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann dmaStop(I2C_DMA_BUS, pdev->board->dmaRx.stream); 576102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann state->rx.offset = state->rx.size - dmaBytesLeft(I2C_DMA_BUS, 577102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann pdev->board->dmaRx.stream); 578102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann dmaStop(I2C_DMA_BUS, pdev->board->dmaTx.stream); 579102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann state->tx.offset = state->tx.size - dmaBytesLeft(I2C_DMA_BUS, 580102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann pdev->board->dmaTx.stream); 581102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 582102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cDmaDisable(pdev); 583102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 584102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 5851a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmannstatic inline void stmI2cMasterStartDma(struct StmI2cDev *pdev, 5861a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann const struct StmI2cDmaCfg *dmaCfg, const void *buf, 5871a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann size_t size, DmaCallbackF callback, bool rx, bool last) 5881a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann{ 5891a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 5901a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann struct dmaMode mode; 5911a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 5921a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann memset(&mode, 0, sizeof(mode)); 5931a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.priority = DMA_PRIORITY_HIGH; 5941a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.direction = rx ? DMA_DIRECTION_PERIPH_TO_MEM : 5951a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann DMA_DIRECTION_MEM_TO_PERIPH; 5961a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.periphAddr = (uintptr_t)®s->DR; 5971a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.minc = true; 5981a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann mode.channel = dmaCfg->channel; 5991a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 6001a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann dmaStart(I2C_DMA_BUS, dmaCfg->stream, buf, size, &mode, callback, pdev); 6011a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann if (last) 6021a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_LAST); 6031a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann else 6041a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_LAST); 6051a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cDmaEnable(pdev); 6061a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann} 6071a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 608b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterSentStart(struct StmI2cDev *pdev) 6090840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 610a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 611895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 6120840b67ad4db1415094691100441dffe913f76abGreg Hackmann 61381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicReadByte(&state->masterState) == STM_I2C_MASTER_START) { 614c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (state->tx.size > 0) { 61581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_TX_ADDR); 616c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->DR = pdev->addr << 1; 617c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 61881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_RX_ADDR); 619b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 620c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->DR = (pdev->addr << 1) | 0x01; 621c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 622c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 6230840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 6240840b67ad4db1415094691100441dffe913f76abGreg Hackmann 625b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterSentAddr(struct StmI2cDev *pdev) 6260840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 627a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 628895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 62981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState = atomicReadByte(&state->masterState); 6300840b67ad4db1415094691100441dffe913f76abGreg Hackmann 63181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (masterState == STM_I2C_MASTER_TX_ADDR) { 6321a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterStartDma(pdev, &pdev->board->dmaTx, state->tx.cbuf, 6331a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->tx.size, stmI2cMasterDmaTxDone, false, !!state->rx.size); 634c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR2; // Clear ADDR 63581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_TX_DATA); 63681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } else if (masterState == STM_I2C_MASTER_RX_ADDR) { 637c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (state->rx.size == 1) // Generate NACK here for 1 byte transfers 638b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 6391a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 6401a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cMasterStartDma(pdev, &pdev->board->dmaRx, state->rx.buf, 6411a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size, stmI2cMasterDmaRxDone, true, 6421a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann state->rx.size > 1); 643c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR2; // Clear ADDR 64481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_RX_DATA); 645c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 646c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 647c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 648b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmannstatic void stmI2cMasterNakRxed(struct StmI2cDev *pdev) 649c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 650a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 651895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 65281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint8_t masterState = atomicReadByte(&state->masterState); 65372638ba906c8825313090d4d4aac66b809659e85Ben Fennema int err = 0; 654c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 65581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (masterState == STM_I2C_MASTER_TX_ADDR || 65672638ba906c8825313090d4d4aac66b809659e85Ben Fennema masterState == STM_I2C_MASTER_RX_ADDR) { 65772638ba906c8825313090d4d4aac66b809659e85Ben Fennema err = -ENXIO; 65872638ba906c8825313090d4d4aac66b809659e85Ben Fennema } else if (masterState == STM_I2C_MASTER_TX_DATA || 65981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema masterState == STM_I2C_MASTER_RX_DATA) { 660102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 66172638ba906c8825313090d4d4aac66b809659e85Ben Fennema err = -EIO; 66272638ba906c8825313090d4d4aac66b809659e85Ben Fennema } 6631a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann 66472638ba906c8825313090d4d4aac66b809659e85Ben Fennema if (err) { 665c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema regs->SR1 &= ~I2C_SR1_AF; 666b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cStopEnable(pdev); 66772638ba906c8825313090d4d4aac66b809659e85Ben Fennema stmI2cMasterTxRxDone(pdev, err); 668c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 669c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 670c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 671102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic void stmI2cMasterBusError(struct StmI2cDev *pdev) 672102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 673102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 674102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 675102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 676102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1 &= ~I2C_SR1_BERR; 67755783a2db53152e98b17ea3252eb814d97b9b9c7Zhengyin Qian stmI2cMasterTxRxDone(pdev, -EIO); 678102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 679102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 680102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic void stmI2cMasterArbitrationLoss(struct StmI2cDev *pdev) 681102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 682102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 683102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 684102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 685102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1 &= ~I2C_SR1_ARLO; 68655783a2db53152e98b17ea3252eb814d97b9b9c7Zhengyin Qian stmI2cMasterTxRxDone(pdev, -EBUSY); 687102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 688102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 689102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmannstatic void stmI2cMasterUnexpectedError(struct StmI2cDev *pdev) 690102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann{ 691102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann struct StmI2c *regs = pdev->cfg->regs; 692102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 693102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann osLog(LOG_ERROR, "Unexpected I2C ERR interrupt: SR1 = %04lX, SR2 = %04lX\n", 694102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1, regs->SR2); 695102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 696102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterDmaCancel(pdev); 697102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann regs->SR1 = 0; 69855783a2db53152e98b17ea3252eb814d97b9b9c7Zhengyin Qian stmI2cMasterTxRxDone(pdev, -EIO); 699102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann} 700102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann 701a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic void stmI2cIsrEvent(struct StmI2cDev *pdev) 702c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 703895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 704c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema uint16_t sr1 = regs->SR1; 705c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 706c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 707c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_ADDR) { 708b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveAddrMatched(pdev); 709c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_RXNE) { 710b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxBufNotEmpty(pdev); 711c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_TXE) { 712b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxBufEmpty(pdev); 713c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (sr1 & I2C_SR1_BTF) { 714c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (regs->SR2 & I2C_SR2_TRA) 715b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxBufEmpty(pdev); 716c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else 717b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveRxBufNotEmpty(pdev); 718d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else if (sr1 & I2C_SR1_STOPF) { 719b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveStopRxed(pdev); 720c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 721c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* TODO: other flags */ 722c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (pdev->state.mode == STM_I2C_MASTER) { 723c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_SB) 724b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterSentStart(pdev); 725c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else if (sr1 & I2C_SR1_ADDR) 726b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterSentAddr(pdev); 727c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 728c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 729c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 730a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinbergstatic void stmI2cIsrError(struct StmI2cDev *pdev) 731c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 732895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2c *regs = pdev->cfg->regs; 733c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema uint16_t sr1 = regs->SR1; 734c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 735c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 736c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_AF) 737b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveNakRxed(pdev); 738c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema /* TODO: other flags */ 739c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else if (pdev->state.mode == STM_I2C_MASTER) { 740c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (sr1 & I2C_SR1_AF) 741b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cMasterNakRxed(pdev); 742102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann else if (sr1 & I2C_SR1_BERR) 743102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterBusError(pdev); 744102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann else if (sr1 & I2C_SR1_ARLO) 745102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterArbitrationLoss(pdev); 746102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann else 747102610d413fb2a73ed2dd0b8a059117190fd2de0Greg Hackmann stmI2cMasterUnexpectedError(pdev); 748c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 7490840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 7500840b67ad4db1415094691100441dffe913f76abGreg Hackmann 7510840b67ad4db1415094691100441dffe913f76abGreg Hackmann#define DECLARE_IRQ_HANDLERS(_n) \ 7520840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_EV_IRQHandler(); \ 7530840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_ER_IRQHandler(); \ 7540840b67ad4db1415094691100441dffe913f76abGreg Hackmann \ 7550840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_EV_IRQHandler() \ 7560840b67ad4db1415094691100441dffe913f76abGreg Hackmann { \ 757895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cIsrEvent(&mStmI2cDevs[_n - 1]); \ 7580840b67ad4db1415094691100441dffe913f76abGreg Hackmann } \ 7590840b67ad4db1415094691100441dffe913f76abGreg Hackmann \ 7600840b67ad4db1415094691100441dffe913f76abGreg Hackmann extern void I2C##_n##_ER_IRQHandler() \ 7610840b67ad4db1415094691100441dffe913f76abGreg Hackmann { \ 762895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cIsrError(&mStmI2cDevs[_n - 1]); \ 7630840b67ad4db1415094691100441dffe913f76abGreg Hackmann } 7640840b67ad4db1415094691100441dffe913f76abGreg Hackmann 765895ed4022a50ee173631b04b791fe13114bcdd55Ben FennemaDECLARE_IRQ_HANDLERS(1); 766f6063e913e1882f4d8767c93b168a7c201ae8b76Antonio BorneoDECLARE_IRQ_HANDLERS(2); 767e0771b85c97ed0a90ff0824530a98f4f69e9b1a9Ben FennemaDECLARE_IRQ_HANDLERS(3); 768895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 76971b642d969783c6514970587e30502db3ba112c3Dmitry Grinbergstatic inline struct Gpio* stmI2cGpioInit(const struct StmI2cBoardCfg *board, const struct StmI2cGpioCfg *cfg) 7700840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 7713568682fec0484260cfe2b9ba0d1540f956c21cbDmitry Grinberg struct Gpio* gpio = gpioRequest(cfg->gpioNum); 772de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann gpioConfigAlt(gpio, board->gpioSpeed, board->gpioPull, GPIO_OUT_OPEN_DRAIN, 773de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann cfg->func); 77471b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 77571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg return gpio; 7760840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 7770840b67ad4db1415094691100441dffe913f76abGreg Hackmann 778342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cMasterRequest(uint32_t busId, uint32_t speed) 7790840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 780895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 7810840b67ad4db1415094691100441dffe913f76abGreg Hackmann return -EINVAL; 7820840b67ad4db1415094691100441dffe913f76abGreg Hackmann 783de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board = boardStmI2cCfg(busId); 784de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann if (!board) 785de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann return -EINVAL; 786de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann 787895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 78881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct I2cStmState *state = &pdev->state; 789895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = &mStmI2cCfgs[busId]; 7900840b67ad4db1415094691100441dffe913f76abGreg Hackmann 79181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode == STM_I2C_DISABLED) { 79281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->mode = STM_I2C_MASTER; 793895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 794895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg = cfg; 795de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann pdev->board = board; 79681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->next = 2; 79781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->last = 1; 79881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicBitsetInit(mXfersValid, I2C_MAX_QUEUE_DEPTH); 799895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema 80071b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->scl = stmI2cGpioInit(board, &board->gpioScl); 80171b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->sda = stmI2cGpioInit(board, &board->gpioSda); 802c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 803c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, true); 804c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 805a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cDisable(pdev); 806c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 807c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, true); 808c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, false); 8090840b67ad4db1415094691100441dffe913f76abGreg Hackmann 8101a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITEVTEN | I2C_CR2_ITERREN); 811a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cSpeedSet(pdev, speed); 81281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWriteByte(&state->masterState, STM_I2C_MASTER_IDLE); 813c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 814895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEr); 815895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEv); 816c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 817a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 818c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 819c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 820c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 821c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 8220840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 8230840b67ad4db1415094691100441dffe913f76abGreg Hackmann 824342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cMasterRelease(uint32_t busId) 8250840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 826895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 827c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 828c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 829895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 83081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct I2cStmState *state = &pdev->state; 831895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 8320840b67ad4db1415094691100441dffe913f76abGreg Hackmann 83381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode == STM_I2C_MASTER) { 834ddcba9d9835dc96c06488f56f55e5835a46eaff3Ben Fennema if (atomicReadByte(&state->masterState) == STM_I2C_MASTER_IDLE) { 835ddcba9d9835dc96c06488f56f55e5835a46eaff3Ben Fennema state->mode = STM_I2C_DISABLED; 8361a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 83781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema stmI2cDisable(pdev); 83881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, false); 83971b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 84071b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioRelease(pdev->scl); 84171b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioRelease(pdev->sda); 84271b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 84381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return 0; 84481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } else { 84581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EBUSY; 84681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 847c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 84881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EINVAL; 849c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 850c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 8510840b67ad4db1415094691100441dffe913f76abGreg Hackmann 85281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 853342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cMasterTxRx(uint32_t busId, uint32_t addr, 854895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const void *txBuf, size_t txSize, void *rxBuf, size_t rxSize, 855895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema I2cCallbackF callback, void *cookie) 856c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 85781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema uint32_t id; 85881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 859895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 860c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 861c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema else if (addr & 0x80) 862c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -ENXIO; 8630840b67ad4db1415094691100441dffe913f76abGreg Hackmann 864895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 865a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 8660840b67ad4db1415094691100441dffe913f76abGreg Hackmann 86781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (state->mode != STM_I2C_MASTER) 86881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema return -EINVAL; 869c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 87081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema struct StmI2cXfer *xfer = stmI2cGetXfer(); 87181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 87281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (xfer) { 87381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->busId = busId; 87481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->addr = addr; 87581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->txBuf = txBuf; 87681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->txSize = txSize; 87781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->rxBuf = rxBuf; 87881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->rxSize = rxSize; 87981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->callback = callback; 88081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema xfer->cookie = cookie; 881f62fa5ad2731c3f0711eacc4a623ed6cfd3e05beBen Fennema xfer->tid = osGetCurrentTid(); 88281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 88381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema do { 8848cf410ff3b2d8a09f3aa2b5ca10253732e8e6f78Alexey Polyudov id = atomicAdd32bits(&pdev->last, 1); 88581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } while (!id); 88681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 88781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // after this point the transfer can be picked up by the transfer 88881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // complete interrupt 88981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema atomicWrite32bits(&xfer->id, id); 89081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema 89181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // only initiate transfer here if we are in IDLE. Otherwise the transfer 89281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // completion interrupt will start the next transfer (not necessarily 89381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // this one) 89481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicCmpXchgByte((uint8_t *)&state->masterState, 89581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema STM_I2C_MASTER_IDLE, STM_I2C_MASTER_START)) { 89681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // it is possible for this transfer to already be complete by the 89781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema // time we get here. if so, transfer->id will have been set to 0. 89881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema if (atomicCmpXchg32bits(&xfer->id, id, 0)) { 89981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema pdev->addr = xfer->addr; 90081be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.cbuf = xfer->txBuf; 90181be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.offset = 0; 90281be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.size = xfer->txSize; 90381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.callback = xfer->callback; 90481be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->tx.cookie = xfer->cookie; 90581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.buf = xfer->rxBuf; 90681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.offset = 0; 90781be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.size = xfer->rxSize; 90881be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.callback = NULL; 90981be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema state->rx.cookie = NULL; 910f62fa5ad2731c3f0711eacc4a623ed6cfd3e05beBen Fennema state->tid = xfer->tid; 911287671677bb946b266dc4c8fc39582533272363cBen Fennema if (pdev->board->sleepDev >= 0) 912287671677bb946b266dc4c8fc39582533272363cBen Fennema platRequestDevInSleepMode(pdev->board->sleepDev, 12); 91381be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema stmI2cPutXfer(xfer); 9146b8a5ad6a9b658df8ed5ea52fcc5df53d6c41fd6Greg Hackmann stmI2cStartEnable(pdev); 91581be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 91681be7381e3399a0ff4c54222987ab7bd0b1169dfBen Fennema } 917c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 918c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 919c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 920c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 9210840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 9220840b67ad4db1415094691100441dffe913f76abGreg Hackmann 923342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveRequest(uint32_t busId, uint32_t addr) 9240840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 925895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 926c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 927c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 928de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann const struct StmI2cBoardCfg *board = boardStmI2cCfg(busId); 929de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann if (!board) 930de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann return -EINVAL; 931de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann 932895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 933895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = &mStmI2cCfgs[busId]; 934c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 935c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_DISABLED) { 936c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->state.mode = STM_I2C_SLAVE; 937c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 938c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->addr = addr; 939895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pdev->cfg = cfg; 940de3e8ff2e1ff562311016c30c4c93d9acf95442fGreg Hackmann pdev->board = board; 9410840b67ad4db1415094691100441dffe913f76abGreg Hackmann 94271b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->scl = stmI2cGpioInit(board, &board->gpioScl); 94371b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->sda = stmI2cGpioInit(board, &board->gpioSda); 944c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 945c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 946c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 9470840b67ad4db1415094691100441dffe913f76abGreg Hackmann return -EBUSY; 948c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 949c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 9500840b67ad4db1415094691100441dffe913f76abGreg Hackmann 951342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveRelease(uint32_t busId) 952c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 953895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema if (busId >= ARRAY_SIZE(mStmI2cDevs)) 954c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EINVAL; 9550840b67ad4db1415094691100441dffe913f76abGreg Hackmann 956895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 957895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 958a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 959c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 960c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pdev->state.mode = STM_I2C_DISABLED; 9611a56d7dbff3c06f7b55084aa5ec9f75e1f061ac1Greg Hackmann stmI2cIrqDisable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 962b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckDisable(pdev); 963895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema stmI2cDisable(pdev); 964895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, false); 96571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 96671b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioRelease(pdev->scl); 96771b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioRelease(pdev->sda); 96871b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 969c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 970c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 971c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 972c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 9730840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 974a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 975342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergvoid i2cSlaveEnableRx(uint32_t busId, void *rxBuf, size_t rxSize, 976a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg I2cCallbackF callback, void *cookie) 9770840b67ad4db1415094691100441dffe913f76abGreg Hackmann{ 978895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 979895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema const struct StmI2cCfg *cfg = pdev->cfg; 980a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 981a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 982c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 983366407f628e806b2b48ccc36e5a2ac5df914f9cbDmitry Grinberg state->rx.buf = rxBuf; 984c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.offset = 0; 985895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema state->rx.size = rxSize; 986c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.callback = callback; 987c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->rx.cookie = cookie; 988a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg state->slaveState = STM_I2C_SLAVE_RX_ARMED; 989c36763df4fb478679f842e9dd9bb7a1ae314a60aAlexey Polyudov state->tid = osGetCurrentTid(); 990c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 991c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitClock(PERIPH_BUS_APB1, cfg->clock, true); 992c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, true); 993c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema pwrUnitReset(PERIPH_BUS_APB1, cfg->clock, false); 994c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 995895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEr); 996895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema NVIC_EnableIRQ(cfg->irqEv); 997c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 998a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg stmI2cEnable(pdev); 999c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema cfg->regs->OAR1 = I2C_OAR1_ADD7(pdev->addr); 1000b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITERREN | I2C_CR2_ITEVTEN); 1001b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cAckEnable(pdev); 1002c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 10030840b67ad4db1415094691100441dffe913f76abGreg Hackmann} 1004a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 1005342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergstatic int i2cSlaveTx(uint32_t busId, const void *txBuf, uint8_t byte, 10069ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann size_t txSize, I2cCallbackF callback, void *cookie) 1007c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema{ 1008895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema struct StmI2cDev *pdev = &mStmI2cDevs[busId]; 1009a1acd43d08d2fe165f43ad3630974fe5a9d00977Dmitry Grinberg struct I2cStmState *state = &pdev->state; 1010c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 1011c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema if (pdev->state.mode == STM_I2C_SLAVE) { 1012d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann if (state->slaveState == STM_I2C_SLAVE_RX) 1013c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 1014a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 10159ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (txBuf) { 10169ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.cbuf = txBuf; 10179ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.preamble = false; 10189ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } else { 10199ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.byte = byte; 10209ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->tx.preamble = true; 10219ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } 1022c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.offset = 0; 1023895ed4022a50ee173631b04b791fe13114bcdd55Ben Fennema state->tx.size = txSize; 1024c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.callback = callback; 1025c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema state->tx.cookie = cookie; 1026a443864c8bd6dd2d8d6f9e018d058081e597986fDmitry Grinberg 10279ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann if (state->slaveState == STM_I2C_SLAVE_TX_ARMED) { 10289ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann state->slaveState = STM_I2C_SLAVE_TX; 1029b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cSlaveTxNextByte(pdev); 1030b1a01e920afed810350a633ee48112b75b9a3041Greg Hackmann stmI2cIrqEnable(pdev, I2C_CR2_ITBUFEN); 1031d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann } else { 1032d9b4be2f9f66404fa14bd43ad76ab852eb7690d5Greg Hackmann state->slaveState = STM_I2C_SLAVE_TX; 10339ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann } 1034c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema 1035c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return 0; 1036c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } else { 1037c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema return -EBUSY; 1038c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema } 1039c39f6795e17ef975d6a1e8912f4ff878b3dc4ba5Ben Fennema} 10409ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann 1041342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveTxPreamble(uint32_t busId, uint8_t byte, I2cCallbackF callback, 10429ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann void *cookie) 10439ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann{ 10449ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann return i2cSlaveTx(busId, NULL, byte, 0, callback, cookie); 10459ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann} 10469ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann 1047342c37806ad0ac7d1e5d3f5dff74065d28e5ec3fDmitry Grinbergint i2cSlaveTxPacket(uint32_t busId, const void *txBuf, size_t txSize, 10489ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann I2cCallbackF callback, void *cookie) 10499ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann{ 10509ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann return i2cSlaveTx(busId, txBuf, 0, txSize, callback, cookie); 10519ec8fea4cc8e5357e2e08d761b82d4379e9626caGreg Hackmann} 1052