icE1usb fw: Import I2C peripheral driver
Signed-off-by: Sylvain Munaut <tnt@246tNt.com> Change-Id: Ib729bb5f4e94eec25c86517042cdfdcb6847ba25
This commit is contained in:
parent
b722de7a2a
commit
652c732ec4
|
@ -55,6 +55,7 @@ HEADERS_app=\
|
|||
gps.h \
|
||||
gpsdo.h \
|
||||
ice1usb_proto.h \
|
||||
i2c.h \
|
||||
misc.h \
|
||||
usb_desc_ids.h \
|
||||
usb_dev.h \
|
||||
|
@ -69,6 +70,7 @@ SOURCES_app=\
|
|||
fw_app.c \
|
||||
gps.c \
|
||||
gpsdo.c \
|
||||
i2c.c \
|
||||
misc.c \
|
||||
usb_desc_app.c \
|
||||
usb_dev.c \
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* i2c.c
|
||||
*
|
||||
* Copyright (C) 2021-2022 Sylvain Munaut <tnt@246tNt.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "console.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
struct i2c {
|
||||
uint32_t csr;
|
||||
} __attribute__((packed,aligned(4)));
|
||||
|
||||
#define I2C_CMD_START (0 << 12)
|
||||
#define I2C_CMD_STOP (1 << 12)
|
||||
#define I2C_CMD_WRITE (2 << 12)
|
||||
#define I2C_CMD_READ (3 << 12)
|
||||
|
||||
#define I2C_GET_RESP (1 << 15)
|
||||
#define I2C_ACK (0 << 8) /* ack bit value = 0 means ACK */
|
||||
#define I2C_NAK (1 << 8) /* ack bit value = 1 means NAK */
|
||||
|
||||
#define I2C_VALID (1 << 31)
|
||||
|
||||
|
||||
static volatile struct i2c * const i2c_regs = (void *)(I2C_BASE);
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
_i2c_wait(void)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
do {
|
||||
v = i2c_regs->csr;
|
||||
} while (!(v & I2C_VALID));
|
||||
|
||||
return v & 0x1ff;
|
||||
}
|
||||
|
||||
bool
|
||||
i2c_ready(void)
|
||||
{
|
||||
return i2c_regs->csr & (1 << 31);
|
||||
}
|
||||
|
||||
void
|
||||
i2c_start(void)
|
||||
{
|
||||
i2c_regs->csr = I2C_CMD_START;
|
||||
}
|
||||
|
||||
void
|
||||
i2c_stop(void)
|
||||
{
|
||||
i2c_regs->csr = I2C_CMD_STOP;
|
||||
}
|
||||
|
||||
bool
|
||||
i2c_write(uint8_t data)
|
||||
{
|
||||
i2c_regs->csr = I2C_CMD_WRITE | data;
|
||||
return (_i2c_wait() & (I2C_ACK | I2C_NAK)) == I2C_ACK;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
i2c_read(bool ack)
|
||||
{
|
||||
i2c_regs->csr = I2C_CMD_READ | I2C_GET_RESP | (ack ? I2C_ACK : I2C_NAK);
|
||||
return _i2c_wait() & 0xff;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
i2c_write_reg(uint8_t dev, uint8_t reg, uint8_t val)
|
||||
{
|
||||
bool rv = true;
|
||||
i2c_start();
|
||||
rv = rv && i2c_write(dev);
|
||||
rv = rv && i2c_write(reg);
|
||||
rv = rv && i2c_write(val);
|
||||
i2c_stop();
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
i2c_read_reg(uint8_t dev, uint8_t reg, uint8_t *val)
|
||||
{
|
||||
bool rv = true;
|
||||
i2c_start();
|
||||
rv = rv && i2c_write(dev);
|
||||
rv = rv && i2c_write(reg);
|
||||
if (rv)
|
||||
i2c_start();
|
||||
rv = rv && i2c_write(dev|1);
|
||||
*val = rv ? i2c_read(false) : 0x00; // NAK
|
||||
i2c_stop();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
i2c_probe(uint8_t dev)
|
||||
{
|
||||
bool rv;
|
||||
i2c_start();
|
||||
rv = i2c_write(dev);
|
||||
i2c_stop();
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
i2c_scan(void)
|
||||
{
|
||||
for (uint8_t addr=0; addr<128; addr++) {
|
||||
if (i2c_probe(addr << 1))
|
||||
printf("I2C @ %08x\n", addr << 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* i2c.h
|
||||
*
|
||||
* Copyright (C) 2021-2022 Sylvain Munaut <tnt@246tNt.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void i2c_start(void);
|
||||
void i2c_stop(void);
|
||||
bool i2c_write(uint8_t data);
|
||||
uint8_t i2c_read(bool ack);
|
||||
|
||||
bool i2c_write_reg(uint8_t dev, uint8_t reg, uint8_t val);
|
||||
bool i2c_read_reg (uint8_t dev, uint8_t reg, uint8_t *val);
|
||||
|
||||
bool i2c_probe(uint8_t dev);
|
||||
void i2c_scan(void);
|
Loading…
Reference in New Issue