mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-05-12 11:43:16 -04:00
Compare commits
5 commits
c9d468d924
...
bcdec75f94
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcdec75f94 | ||
|
|
922b5e9a4b | ||
|
|
e81dd7c709 | ||
|
|
4af1768795 | ||
|
|
9c5017ea98 |
14 changed files with 583 additions and 19 deletions
|
|
@ -4920,11 +4920,11 @@
|
|||
</source>
|
||||
<dest>
|
||||
*: none
|
||||
recording: "Počet bitov"
|
||||
recording: "Bitová rýchlosť"
|
||||
</dest>
|
||||
<voice>
|
||||
*: none
|
||||
recording: "Počet bitov"
|
||||
recording: "Bitová rýchlosť"
|
||||
</voice>
|
||||
</phrase>
|
||||
<phrase>
|
||||
|
|
|
|||
|
|
@ -1953,6 +1953,7 @@ target/arm/stm32/echoplayer/audiohw-echoplayer.c
|
|||
target/arm/stm32/echoplayer/backlight-echoplayer.c
|
||||
target/arm/stm32/echoplayer/button-echoplayer.c
|
||||
target/arm/stm32/echoplayer/clock-echoplayer.c
|
||||
target/arm/stm32/echoplayer/i2c-echoplayer.c
|
||||
target/arm/stm32/echoplayer/lcd-echoplayer.c
|
||||
target/arm/stm32/echoplayer/power-echoplayer.c
|
||||
target/arm/stm32/echoplayer/sdmmc-echoplayer.c
|
||||
|
|
|
|||
|
|
@ -33,16 +33,19 @@
|
|||
#define MODEL_NUMBER 64
|
||||
|
||||
//#define HAVE_ATA_SD
|
||||
//#define HAVE_HOTSWAP
|
||||
#define HAVE_HOTSWAP
|
||||
#define INCLUDE_TIMEOUT_API
|
||||
|
||||
//#define CONFIG_STORAGE (STORAGE_NAND | STORAGE_SD)
|
||||
#define CONFIG_STORAGE STORAGE_SD /* Multivolume currently handled at firmware/target/ level */
|
||||
#define CONFIG_STORAGE STORAGE_SD
|
||||
|
||||
#define CONFIG_NAND NAND_CC
|
||||
|
||||
#define HAVE_MULTIDRIVE
|
||||
#define NUM_DRIVES 2
|
||||
|
||||
//#define HAVE_MULTIDRIVE
|
||||
//#define NUM_DRIVES 2
|
||||
#define HAVE_HOTSWAP
|
||||
#define HAVE_MULTIVOLUME
|
||||
#define HAVE_HOTSWAP_STORAGE_AS_MAIN
|
||||
|
||||
|
||||
|
||||
|
|
@ -159,6 +162,7 @@
|
|||
#define HAVE_USBSTACK
|
||||
#define USB_VENDOR_ID 0x07C4
|
||||
#define USB_PRODUCT_ID 0xA4A5
|
||||
#define HAVE_BOOTLOADER_USB_MODE
|
||||
|
||||
/* Define this if a programmable hotkey is mapped */
|
||||
//#define HAVE_HOTKEY
|
||||
|
|
|
|||
|
|
@ -192,6 +192,7 @@ No access to the NAND yet..
|
|||
#define USB_STATUS_BY_EVENT
|
||||
#define USB_VENDOR_ID 0x07C4
|
||||
#define USB_PRODUCT_ID 0xA4A5
|
||||
#define HAVE_BOOTLOADER_USB_MODE
|
||||
|
||||
/* Define this if a programmable hotkey is mapped */
|
||||
//#define HAVE_HOTKEY
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@
|
|||
#define CONFIG_STORAGE (STORAGE_SD /* | STORAGE_NAND */)
|
||||
|
||||
#define HAVE_MULTIDRIVE
|
||||
#define CONFIG_STORAGE_MULTI
|
||||
//#define CONFIG_STORAGE_MULTI
|
||||
#define NUM_DRIVES 2
|
||||
|
||||
/* Define this if media can be exchanged on the fly */
|
||||
|
|
|
|||
|
|
@ -1401,3 +1401,111 @@ block DMAMUX {
|
|||
|
||||
DMAMUX1 @ 0x40020800 : DMAMUX
|
||||
DMAMUX2 @ 0x58025800 : DMAMUX
|
||||
|
||||
// I2C controller
|
||||
block I2C {
|
||||
CR1 @ 0x00 : reg {
|
||||
-- 23 PECEN
|
||||
-- 22 ALERTEN
|
||||
-- 21 SMBDEN
|
||||
-- 20 SMBHEN
|
||||
-- 19 GCEN
|
||||
-- 18 WUPEN
|
||||
-- 17 NOSTRETCH
|
||||
-- 16 SBC
|
||||
-- 15 RXDMAEN
|
||||
-- 14 TXDMAEN
|
||||
-- 12 ANFOFF
|
||||
11 08 DNF
|
||||
-- 07 ERRIE
|
||||
-- 06 TCIE
|
||||
-- 05 STOPIE
|
||||
-- 04 NACKIE
|
||||
-- 03 ADDRIE
|
||||
-- 02 RXIE
|
||||
-- 01 TXIE
|
||||
-- 00 PE
|
||||
}
|
||||
|
||||
CR2 @ 0x04 : reg {
|
||||
-- 26 PECBYTE
|
||||
-- 25 AUTOEND
|
||||
-- 24 RELOAD
|
||||
23 16 NBYTES
|
||||
-- 15 NACK
|
||||
-- 14 STOP
|
||||
-- 13 START
|
||||
-- 12 HEAD10R
|
||||
-- 11 ADD10
|
||||
-- 10 RD_WRN
|
||||
09 00 SADD
|
||||
}
|
||||
|
||||
OAR1 @ 0x08 : reg {
|
||||
-- 15 OA1EN
|
||||
-- 10 OA1MODE
|
||||
09 00 OA1
|
||||
}
|
||||
|
||||
OAR2 @ 0x0c : reg {
|
||||
-- 15 OA2EN
|
||||
10 08 OA2MSK
|
||||
07 01 OA2
|
||||
}
|
||||
|
||||
TIMINGR @ 0x10 : reg {
|
||||
31 28 PRESC
|
||||
23 20 SCLDEL
|
||||
19 16 SDADEL
|
||||
15 08 SCLH
|
||||
07 00 SCLL
|
||||
}
|
||||
|
||||
TIMEOUTR @ 0x14 : reg {
|
||||
-- 31 TEXTEN
|
||||
27 16 TIMEOUTB
|
||||
-- 15 TIMOUTEN
|
||||
-- 12 TIDLE
|
||||
11 00 TIMEOUTA
|
||||
}
|
||||
|
||||
ISR @ 0x18 : reg {
|
||||
23 17 ADDCODE
|
||||
-- 16 DIR
|
||||
-- 15 BUSY
|
||||
-- 14 ALERT
|
||||
-- 12 TIMEOUT
|
||||
-- 11 PECERR
|
||||
-- 10 OVR
|
||||
-- 09 ARLO
|
||||
-- 08 BERR
|
||||
-- 07 TCR
|
||||
-- 06 TC
|
||||
-- 05 STOPF
|
||||
-- 04 NACKF
|
||||
-- 03 ADDR
|
||||
-- 02 RXNE
|
||||
-- 01 TXIS
|
||||
-- 00 TXE
|
||||
}
|
||||
|
||||
ICR @ 0x1c : reg {
|
||||
-- 13 ALERTCF
|
||||
-- 12 TIMOUTCF
|
||||
-- 11 PECCF
|
||||
-- 10 OVRCF
|
||||
-- 09 ARLOCF
|
||||
-- 08 BERRCF
|
||||
-- 05 STOPCF
|
||||
-- 04 NACKCF
|
||||
-- 03 ADDRCF
|
||||
}
|
||||
|
||||
RXDR @ 0x24 : reg
|
||||
TXDR @ 0x28 : reg
|
||||
}
|
||||
|
||||
I2C1 @ 0x40005400 : I2C
|
||||
I2C2 @ 0x40005800 : I2C
|
||||
I2C3 @ 0x40005C00 : I2C
|
||||
I2C4 @ 0x58001C00 : I2C
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ INIT_ATTR static void init_periph_clock(void)
|
|||
{
|
||||
reg_writef(RCC_D1CCIPR, SDMMCSEL_V(PLL1Q));
|
||||
reg_writef(RCC_D2CCIP1R, SPI45SEL_V(HSE));
|
||||
reg_writef(RCC_D2CCIP2R, I2C123SEL_V(HSI));
|
||||
|
||||
/* Enable AXI SRAM in sleep mode to allow DMA'ing out of it */
|
||||
reg_writef(RCC_AHB3LPENR, AXISRAMEN(1));
|
||||
|
|
@ -203,3 +204,11 @@ const struct stm32_clock spi5_ker_clock = {
|
|||
.lpen_reg = ITA_RCC_APB2LPENR,
|
||||
.lpen_bit = BM_RCC_APB2ENR_SPI5EN,
|
||||
};
|
||||
|
||||
const struct stm32_clock i2c1_ker_clock = {
|
||||
.frequency = STM32_HSI_FREQ,
|
||||
.en_reg = ITA_RCC_APB1LENR,
|
||||
.en_bit = BM_RCC_APB1LENR_I2C1EN,
|
||||
.lpen_reg = ITA_RCC_APB1LLPENR,
|
||||
.lpen_bit = BM_RCC_APB1LENR_I2C1EN,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,5 +28,6 @@ void echoplayer_clock_init(void) INIT_ATTR;
|
|||
extern struct stm32_clock sdmmc1_ker_clock;
|
||||
extern struct stm32_clock ltdc_ker_clock;
|
||||
extern struct stm32_clock spi5_ker_clock;
|
||||
extern struct stm32_clock i2c1_ker_clock;
|
||||
|
||||
#endif /* __CLOCK_ECHOPLAYER_H__ */
|
||||
|
|
|
|||
50
firmware/target/arm/stm32/echoplayer/i2c-echoplayer.c
Normal file
50
firmware/target/arm/stm32/echoplayer/i2c-echoplayer.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2026 by Aidan MacDonald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "i2c-stm32h7.h"
|
||||
#include "clock-echoplayer.h"
|
||||
#include "nvic-arm.h"
|
||||
#include "regs/stm32h743/i2c.h"
|
||||
|
||||
static const struct stm32_i2c_config i2c1_conf INITDATA_ATTR = {
|
||||
.instance = ITA_I2C1,
|
||||
.ker_clock = &i2c1_ker_clock,
|
||||
.bus_freq_hz = 400000,
|
||||
.scl_low_min_ns = 1300,
|
||||
.scl_high_min_ns = 600,
|
||||
.t_vd_dat_max_ns = 900,
|
||||
.t_su_dat_max_ns = 100,
|
||||
.rise_time_max_ns = 300,
|
||||
.fall_time_max_ns = 300,
|
||||
};
|
||||
|
||||
struct stm32_i2c_controller i2c1_ctl;
|
||||
|
||||
void i2c_init(void)
|
||||
{
|
||||
stm32_i2c_init(&i2c1_ctl, &i2c1_conf);
|
||||
nvic_enable_irq(NVIC_IRQN_I2C1_EV);
|
||||
nvic_enable_irq(NVIC_IRQN_I2C1_ER);
|
||||
}
|
||||
|
||||
void i2c1_irq_handler(void)
|
||||
{
|
||||
stm32_i2c_irq_handler(&i2c1_ctl);
|
||||
}
|
||||
28
firmware/target/arm/stm32/echoplayer/i2c-echoplayer.h
Normal file
28
firmware/target/arm/stm32/echoplayer/i2c-echoplayer.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2026 by Aidan MacDonald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __I2C_ECHOPLAYER_H__
|
||||
#define __I2C_ECHOPLAYER_H__
|
||||
|
||||
#include "i2c-stm32h7.h"
|
||||
|
||||
extern struct stm32_i2c_controller i2c1_ctl;
|
||||
|
||||
#endif /* __I2C_ECHOPLAYER_H__ */
|
||||
|
|
@ -18,8 +18,291 @@
|
|||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "i2c.h"
|
||||
#include "i2c-stm32h7.h"
|
||||
#include "kernel.h"
|
||||
#include "panic.h"
|
||||
#include "regs/stm32h743/rcc.h"
|
||||
#include "regs/stm32h743/i2c.h"
|
||||
|
||||
void i2c_init(void)
|
||||
#define FLAG_WRITE_REG_ADDR 0x01
|
||||
#define FLAG_WAIT_REG_ADDR 0x02
|
||||
#define FLAG_READ_DATA 0x04
|
||||
#define FLAG_WRITE_DATA 0x08
|
||||
|
||||
static uint32_t stm32_i2c_get_timingr(const struct stm32_i2c_config *cfg)
|
||||
{
|
||||
/* Kernel clock period and target I2C bus clock period */
|
||||
int t_ker = 1000000 / (stm32_clock_get_frequency(cfg->ker_clock) / 1000);
|
||||
int t_scl = 1000000 / (cfg->bus_freq_hz / 1000);
|
||||
|
||||
/* Analog filter delays */
|
||||
int af_min = 50;
|
||||
int af_max = 260;
|
||||
|
||||
/* Digital filter delays */
|
||||
int df = 0;
|
||||
|
||||
/* Synchronization delays excluding rise/fall time */
|
||||
int sync_min = af_min + df + (2 * t_ker);
|
||||
int sync_max = af_max + df + (4 * (t_ker + 1));
|
||||
|
||||
/* Calculate bounds for SCLDEL/SDADEL */
|
||||
int min_scldel_ns = cfg->rise_time_max_ns + cfg->t_su_dat_max_ns;
|
||||
int min_sdadel_ns = cfg->fall_time_max_ns - sync_min;
|
||||
int max_sdadel_ns = cfg->t_vd_dat_max_ns - cfg->rise_time_max_ns - sync_max;
|
||||
|
||||
/* Find prescaler setting which produces the least error */
|
||||
uint32_t best_timingr = 0;
|
||||
int best_error = INT_MAX;
|
||||
|
||||
for (int presc = 16; presc > 0; --presc)
|
||||
{
|
||||
/* Prescaler clock period */
|
||||
int t_presc_min = presc * t_ker;
|
||||
int t_presc_max = presc * (t_ker + 1);
|
||||
int t_presc_avg = (t_presc_min + t_presc_max) / 2;
|
||||
|
||||
/* Compute SCLDEL setting */
|
||||
int scldel = (min_scldel_ns + t_presc_min - 1) / t_presc_min;
|
||||
if (scldel > 16)
|
||||
continue;
|
||||
|
||||
/* Compute SDADEL setting */
|
||||
int min_sdadel = (min_sdadel_ns + t_presc_min - 1) / t_presc_min;
|
||||
int max_sdadel = max_sdadel_ns / t_presc_max;
|
||||
int sdadel = (min_sdadel + max_sdadel) / 2;
|
||||
if (min_sdadel > 15 || max_sdadel == 0 || min_sdadel > max_sdadel)
|
||||
continue;
|
||||
|
||||
/* Find minimum SCLL and SCLH settings */
|
||||
int scll_min = (cfg->scl_low_min_ns + t_presc_min - 1) / t_presc_min;
|
||||
int sclh_min = (cfg->scl_high_min_ns + t_presc_min - 1) / t_presc_min;
|
||||
if (scll_min > 256 || scll_min > 256)
|
||||
continue;
|
||||
|
||||
/* Find slack time to add to SCLL/SCLH to meet target clock */
|
||||
int t_scl_slack = t_scl;
|
||||
t_scl_slack -= sync_min * 2;
|
||||
t_scl_slack -= cfg->rise_time_max_ns + cfg->fall_time_max_ns;
|
||||
t_scl_slack -= (scll_min + sclh_min) * t_presc_min;
|
||||
|
||||
/* Compute real SCLL and SCLH */
|
||||
int scll = scll_min;
|
||||
int sclh = sclh_min;
|
||||
|
||||
/* Divide slack between SCLL/SCLH evenly if possible */
|
||||
if (t_scl_slack >= 2*t_presc_avg)
|
||||
{
|
||||
int add_clocks = t_scl_slack / (2 * t_presc_avg);
|
||||
|
||||
scll += add_clocks;
|
||||
sclh += add_clocks;
|
||||
t_scl_slack -= add_clocks * t_presc_avg;
|
||||
}
|
||||
|
||||
/* Add leftover clock to SCLH if would reduce error */
|
||||
if (t_scl_slack >= t_presc_avg/2)
|
||||
sclh += 1;
|
||||
|
||||
/* Determine SCL clock period from these settings */
|
||||
int approx_scl = (scll + sclh) * t_presc_avg + (2 * sync_min);
|
||||
approx_scl += cfg->rise_time_max_ns + cfg->fall_time_max_ns;
|
||||
|
||||
/* Update best timing value */
|
||||
int err = t_scl - approx_scl;
|
||||
if (err < 0)
|
||||
err = -err;
|
||||
|
||||
if (err < best_error)
|
||||
{
|
||||
best_timingr = __reg_orf(I2C_TIMINGR,
|
||||
PRESC(presc - 1),
|
||||
SDADEL(sdadel - 0),
|
||||
SCLDEL(scldel - 1),
|
||||
SCLL(scll - 1),
|
||||
SCLH(sclh - 1));
|
||||
best_error = err;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_error == INT_MAX)
|
||||
panicf("%s", __func__);
|
||||
|
||||
return best_timingr;
|
||||
}
|
||||
|
||||
static void stm32_i2c_transfer_complete(struct stm32_i2c_controller *ctl, int err)
|
||||
{
|
||||
ctl->error = err;
|
||||
|
||||
reg_writelf(ctl->regs, I2C_CR1, PE(0));
|
||||
semaphore_release(&ctl->bus_sem);
|
||||
}
|
||||
|
||||
void stm32_i2c_init(struct stm32_i2c_controller *ctl,
|
||||
const struct stm32_i2c_config *cfg)
|
||||
{
|
||||
mutex_init(&ctl->bus_lock);
|
||||
semaphore_init(&ctl->bus_sem, 1, 0);
|
||||
|
||||
ctl->regs = cfg->instance;
|
||||
ctl->ker_clock = cfg->ker_clock;
|
||||
|
||||
stm32_clock_enable(ctl->ker_clock);
|
||||
|
||||
reg_writelf(ctl->regs, I2C_CR1,
|
||||
ANFOFF(0),
|
||||
ERRIE(1),
|
||||
TCIE(1),
|
||||
STOPIE(1),
|
||||
NACKIE(1),
|
||||
RXIE(1),
|
||||
TXIE(1));
|
||||
reg_varl(ctl->regs, I2C_TIMINGR) = stm32_i2c_get_timingr(cfg);
|
||||
|
||||
stm32_clock_disable(ctl->ker_clock);
|
||||
}
|
||||
|
||||
int stm32_i2c_read_mem(struct stm32_i2c_controller *ctl,
|
||||
uint8_t dev_addr,
|
||||
uint8_t reg_addr,
|
||||
void *data, size_t count)
|
||||
{
|
||||
if (count > 255)
|
||||
panicf("%s: count>255 unsupported", __func__);
|
||||
|
||||
mutex_lock(&ctl->bus_lock);
|
||||
stm32_clock_enable(ctl->ker_clock);
|
||||
|
||||
ctl->xfer_buf = data;
|
||||
ctl->xfer_count = count;
|
||||
ctl->reg_addr = reg_addr;
|
||||
ctl->flags = FLAG_WRITE_REG_ADDR | FLAG_WAIT_REG_ADDR | FLAG_READ_DATA;
|
||||
arm_dsb();
|
||||
|
||||
/* Start first 1-byte transfer of the register address */
|
||||
reg_writelf(ctl->regs, I2C_CR1, PE(1));
|
||||
reg_writelf(ctl->regs, I2C_CR2,
|
||||
NBYTES(1),
|
||||
RD_WRN(0),
|
||||
AUTOEND(0),
|
||||
START(1),
|
||||
SADD(dev_addr << 1));
|
||||
|
||||
semaphore_wait(&ctl->bus_sem, TIMEOUT_BLOCK);
|
||||
|
||||
stm32_clock_disable(ctl->ker_clock);
|
||||
mutex_unlock(&ctl->bus_lock);
|
||||
return ctl->error;
|
||||
}
|
||||
|
||||
int stm32_i2c_write_mem(struct stm32_i2c_controller *ctl,
|
||||
uint8_t dev_addr,
|
||||
uint8_t reg_addr,
|
||||
const void *data, size_t count)
|
||||
{
|
||||
if (count > 254)
|
||||
panicf("%s: count>254 unsupported", __func__);
|
||||
|
||||
mutex_lock(&ctl->bus_lock);
|
||||
stm32_clock_enable(ctl->ker_clock);
|
||||
|
||||
ctl->xfer_buf = (void *)data;
|
||||
ctl->xfer_count = count;
|
||||
ctl->reg_addr = reg_addr;
|
||||
ctl->flags = FLAG_WRITE_REG_ADDR | FLAG_WRITE_DATA;
|
||||
arm_dsb();
|
||||
|
||||
/* Start transfer of register address + data */
|
||||
reg_writelf(ctl->regs, I2C_CR1, PE(1));
|
||||
reg_writelf(ctl->regs, I2C_CR2,
|
||||
NBYTES(ctl->xfer_count + 1),
|
||||
RD_WRN(0),
|
||||
AUTOEND(1),
|
||||
START(1),
|
||||
SADD(dev_addr << 1));
|
||||
|
||||
semaphore_wait(&ctl->bus_sem, TIMEOUT_BLOCK);
|
||||
|
||||
stm32_clock_disable(ctl->ker_clock);
|
||||
mutex_unlock(&ctl->bus_lock);
|
||||
return ctl->error;
|
||||
}
|
||||
|
||||
void stm32_i2c_irq_handler(struct stm32_i2c_controller *ctl)
|
||||
{
|
||||
uint32_t isr = reg_varl(ctl->regs, I2C_ISR);
|
||||
|
||||
/* Detect errors */
|
||||
if (reg_vreadf(isr, I2C_ISR, ARLO) ||
|
||||
reg_vreadf(isr, I2C_ISR, BERR) ||
|
||||
(reg_vreadf(isr, I2C_ISR, STOPF) && ctl->xfer_count != 0) ||
|
||||
reg_vreadf(isr, I2C_ISR, NACKF))
|
||||
{
|
||||
stm32_i2c_transfer_complete(ctl, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctl->flags & FLAG_WRITE_REG_ADDR)
|
||||
{
|
||||
/* Write the register address */
|
||||
if (reg_vreadf(isr, I2C_ISR, TXIS))
|
||||
{
|
||||
reg_varl(ctl->regs, I2C_TXDR) = ctl->reg_addr;
|
||||
ctl->flags &= ~FLAG_WRITE_REG_ADDR;
|
||||
}
|
||||
}
|
||||
else if (ctl->flags & FLAG_WAIT_REG_ADDR)
|
||||
{
|
||||
/* Wait for register address write to complete */
|
||||
if (reg_vreadf(isr, I2C_ISR, TC))
|
||||
{
|
||||
ctl->flags &= ~FLAG_WAIT_REG_ADDR;
|
||||
|
||||
if (ctl->flags & FLAG_READ_DATA)
|
||||
{
|
||||
/* Start read portion of the transfer */
|
||||
reg_writelf(ctl->regs, I2C_CR2,
|
||||
NBYTES(ctl->xfer_count),
|
||||
RD_WRN(1),
|
||||
AUTOEND(1),
|
||||
START(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Writes shouldn't get here */
|
||||
panicf("%s", __func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ctl->flags & FLAG_WRITE_DATA)
|
||||
{
|
||||
if (ctl->xfer_count > 0 && reg_vreadf(isr, I2C_ISR, TXIS))
|
||||
{
|
||||
/* Transmit bytes from buffer */
|
||||
reg_varl(ctl->regs, I2C_TXDR) = *ctl->xfer_buf++;
|
||||
ctl->xfer_count--;
|
||||
}
|
||||
else if (ctl->xfer_count == 0 && reg_vreadf(isr, I2C_ISR, STOPF))
|
||||
{
|
||||
/* Transfer complete without error */
|
||||
ctl->flags &= ~FLAG_WRITE_DATA;
|
||||
stm32_i2c_transfer_complete(ctl, 0);
|
||||
}
|
||||
}
|
||||
else if (ctl->flags & FLAG_READ_DATA)
|
||||
{
|
||||
if (ctl->xfer_count > 0 && reg_vreadf(isr, I2C_ISR, RXNE))
|
||||
{
|
||||
/* Read bytes into buffer */
|
||||
*ctl->xfer_buf++ = reg_varl(ctl->regs, I2C_RXDR);
|
||||
ctl->xfer_count--;
|
||||
}
|
||||
else if (ctl->xfer_count == 0 && reg_vreadf(isr, I2C_ISR, STOPF))
|
||||
{
|
||||
/* Transfer complete without error */
|
||||
ctl->flags &= ~FLAG_READ_DATA;
|
||||
stm32_i2c_transfer_complete(ctl, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
76
firmware/target/arm/stm32/i2c-stm32h7.h
Normal file
76
firmware/target/arm/stm32/i2c-stm32h7.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2026 Aidan MacDonald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __I2C_STM32H743_H__
|
||||
#define __I2C_STM32H743_H__
|
||||
|
||||
#include "mutex.h"
|
||||
#include "semaphore.h"
|
||||
#include "clock-stm32h7.h"
|
||||
|
||||
struct stm32_i2c_config
|
||||
{
|
||||
/* I2C instance address */
|
||||
uint32_t instance;
|
||||
|
||||
/* I2C kernel clock */
|
||||
const struct stm32_clock *ker_clock;
|
||||
|
||||
int bus_freq_hz; /* Desired I2C bus frequency */
|
||||
int scl_low_min_ns; /* Minimum SCL low time */
|
||||
int scl_high_min_ns; /* Minimum SCL high time */
|
||||
int t_vd_dat_max_ns; /* Maximum SDA valid time */
|
||||
int t_su_dat_max_ns; /* Minimum SDA setup time */
|
||||
int rise_time_max_ns; /* Worst-case rise time for SCL & SDA */
|
||||
int fall_time_max_ns; /* Worst-case fall time for SCL & SDA */
|
||||
};
|
||||
|
||||
struct stm32_i2c_controller
|
||||
{
|
||||
uint32_t regs;
|
||||
const struct stm32_clock *ker_clock;
|
||||
|
||||
struct mutex bus_lock;
|
||||
struct semaphore bus_sem;
|
||||
|
||||
int error;
|
||||
|
||||
uint8_t *xfer_buf;
|
||||
size_t xfer_count;
|
||||
|
||||
uint8_t reg_addr;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
void stm32_i2c_init(struct stm32_i2c_controller *ctl,
|
||||
const struct stm32_i2c_config *cfg);
|
||||
|
||||
int stm32_i2c_read_mem(struct stm32_i2c_controller *ctl,
|
||||
uint8_t dev_addr,
|
||||
uint8_t reg_addr,
|
||||
void *data, size_t nbytes);
|
||||
int stm32_i2c_write_mem(struct stm32_i2c_controller *ctl,
|
||||
uint8_t dev_addr,
|
||||
uint8_t reg_addr,
|
||||
const void *data, size_t nbytes);
|
||||
|
||||
void stm32_i2c_irq_handler(struct stm32_i2c_controller *ctl);
|
||||
|
||||
#endif /* __I2C_STM32H743_H__ */
|
||||
|
|
@ -51,7 +51,10 @@ void bdma_ch4_irq_handler(void) ATTR_IRQ_HANDLER;
|
|||
void bdma_ch5_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void bdma_ch6_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void bdma_ch7_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void i2c_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void i2c1_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void i2c2_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void i2c3_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void i2c4_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void lcdc_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void otg_hs_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
void sai1_irq_handler(void) ATTR_IRQ_HANDLER;
|
||||
|
|
|
|||
|
|
@ -58,10 +58,10 @@ __vectors_platform:
|
|||
.word UIE /* [ 28] */
|
||||
.word UIE /* [ 29] */
|
||||
.word UIE /* [ 30] */
|
||||
.word i2c_irq_handler /* [ 31] I2C1 event */
|
||||
.word i2c_irq_handler /* [ 32] I2C1 error */
|
||||
.word i2c_irq_handler /* [ 33] I2C2 event */
|
||||
.word i2c_irq_handler /* [ 34] I2C2 error */
|
||||
.word i2c1_irq_handler /* [ 31] I2C1 event */
|
||||
.word i2c1_irq_handler /* [ 32] I2C1 error */
|
||||
.word i2c2_irq_handler /* [ 33] I2C2 event */
|
||||
.word i2c2_irq_handler /* [ 34] I2C2 error */
|
||||
.word spi1_irq_handler /* [ 35] SPI1 */
|
||||
.word spi2_irq_handler /* [ 36] SPI2 */
|
||||
.word UIE /* [ 37] */
|
||||
|
|
@ -99,8 +99,8 @@ __vectors_platform:
|
|||
.word dma2_ch6_irq_handler /* [ 69] DMA2 Stream6 */
|
||||
.word dma2_ch7_irq_handler /* [ 70] DMA2 Stream7 */
|
||||
.word UIE /* [ 71] */
|
||||
.word i2c_irq_handler /* [ 72] I2C3 event */
|
||||
.word i2c_irq_handler /* [ 73] I2C3 error */
|
||||
.word i2c3_irq_handler /* [ 72] I2C3 event */
|
||||
.word i2c3_irq_handler /* [ 73] I2C3 error */
|
||||
.word UIE /* [ 74] */
|
||||
.word UIE /* [ 75] */
|
||||
.word UIE /* [ 76] */
|
||||
|
|
@ -122,8 +122,8 @@ __vectors_platform:
|
|||
.word UIE /* [ 92] */
|
||||
.word UIE /* [ 93] */
|
||||
.word UIE /* [ 94] */
|
||||
.word i2c_irq_handler /* [ 95] I2C4 event */
|
||||
.word i2c_irq_handler /* [ 96] I2C4 error */
|
||||
.word i2c4_irq_handler /* [ 95] I2C4 event */
|
||||
.word i2c4_irq_handler /* [ 96] I2C4 error */
|
||||
.word UIE /* [ 97] */
|
||||
.word UIE /* [ 98] */
|
||||
.word UIE /* [ 99] */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue