diff options
Diffstat (limited to 'src/samd21/i2c.c')
-rw-r--r-- | src/samd21/i2c.c | 114 |
1 files changed, 0 insertions, 114 deletions
diff --git a/src/samd21/i2c.c b/src/samd21/i2c.c deleted file mode 100644 index 801c0e32..00000000 --- a/src/samd21/i2c.c +++ /dev/null @@ -1,114 +0,0 @@ -// i2c support on samd21 -// -// Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net> -// -// This file may be distributed under the terms of the GNU GPLv3 license. - -#include "autoconf.h" // CONFIG_CLOCK_FREQ -#include "internal.h" // enable_pclock -#include "command.h" // shutdown -#include "gpio.h" // i2c_setup -#include "samd21.h" // SERCOM3 -#include "sched.h" // sched_shutdown - -#define TIME_RISE 125ULL // 125 nanoseconds -#define I2C_FREQ 100000 - -static void -i2c_init(void) -{ - static int have_run_init; - if (have_run_init) - return; - have_run_init = 1; - - // Setup clock - enable_pclock(SERCOM3_GCLK_ID_CORE, PM_APBCMASK_SERCOM3); - - // Configure SDA, SCL pins - gpio_peripheral(GPIO('A', 22), 'C', 0); - gpio_peripheral(GPIO('A', 23), 'C', 0); - - // Configure i2c - SercomI2cm *si = &SERCOM3->I2CM; - si->CTRLA.reg = 0; - uint32_t areg = (SERCOM_I2CM_CTRLA_LOWTOUTEN - | SERCOM_I2CM_CTRLA_INACTOUT(3) - | SERCOM_I2CM_STATUS_SEXTTOUT - | SERCOM_I2CM_STATUS_MEXTTOUT - | SERCOM_I2CM_CTRLA_MODE_I2C_MASTER); - si->CTRLA.reg = areg; - uint32_t baud = (CONFIG_CLOCK_FREQ / I2C_FREQ - - 10 - CONFIG_CLOCK_FREQ*TIME_RISE/1000000000) / 2; - si->BAUD.reg = baud; - si->CTRLA.reg = areg | SERCOM_I2CM_CTRLA_ENABLE; - while (si->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_ENABLE) - ; - - // Go into idle mode - si->STATUS.reg = SERCOM_I2CM_STATUS_BUSSTATE(1); - while (si->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_SYSOP) - ; -} - -struct i2c_config -i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr) -{ - if (bus) - shutdown("Unsupported i2c bus"); - i2c_init(); - return (struct i2c_config){ .addr=addr<<1 }; -} - -static void -i2c_wait(SercomI2cm *si) -{ - for (;;) { - uint32_t intflag = si->INTFLAG.reg; - if (!(intflag & SERCOM_I2CM_INTFLAG_MB)) { - if (si->STATUS.reg & SERCOM_I2CM_STATUS_BUSERR) - shutdown("i2c buserror"); - continue; - } - if (intflag & SERCOM_I2CM_INTFLAG_ERROR) - shutdown("i2c error"); - break; - } -} - -static void -i2c_start(SercomI2cm *si, uint8_t addr) -{ - si->ADDR.reg = addr; - i2c_wait(si); -} - -static void -i2c_send_byte(SercomI2cm *si, uint8_t b) -{ - si->DATA.reg = b; - i2c_wait(si); -} - -static void -i2c_stop(SercomI2cm *si) -{ - si->CTRLB.reg = SERCOM_I2CM_CTRLB_CMD(3); -} - -void -i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write) -{ - SercomI2cm *si = &SERCOM3->I2CM; - i2c_start(si, config.addr); - while (write_len--) - i2c_send_byte(si, *write++); - i2c_stop(si); -} - -void -i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg - , uint8_t read_len, uint8_t *read) -{ - shutdown("i2c_read not supported on samd21"); -} |