atsamd: Add support for programming SERCOM pins
Signed-off-by: Florian Heilmann <Florian.Heilmann@gmx.net> Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// i2c support on samd
|
||||
//
|
||||
// Copyright (C) 2019 Florian Heilmann <Florian.Heilmann@gmx.net>
|
||||
// Copyright (C) 2018-2019 Kevin O'Connor <kevin@koconnor.net>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
@@ -13,22 +14,14 @@
|
||||
#define I2C_FREQ 100000
|
||||
|
||||
static void
|
||||
i2c_init(void)
|
||||
i2c_init(uint32_t bus, SercomI2cm *si)
|
||||
{
|
||||
static int have_run_init;
|
||||
if (have_run_init)
|
||||
static int have_run_init[8];
|
||||
if (have_run_init[bus])
|
||||
return;
|
||||
have_run_init = 1;
|
||||
|
||||
// Setup clock
|
||||
enable_pclock(SERCOM3_GCLK_ID_CORE, ID_SERCOM3);
|
||||
|
||||
// Configure SDA, SCL pins
|
||||
gpio_peripheral(GPIO('A', 22), 'C', 0);
|
||||
gpio_peripheral(GPIO('A', 23), 'C', 0);
|
||||
have_run_init[bus] = 1;
|
||||
|
||||
// Configure i2c
|
||||
SercomI2cm *si = &SERCOM3->I2CM;
|
||||
si->CTRLA.reg = 0;
|
||||
uint32_t areg = (SERCOM_I2CM_CTRLA_LOWTOUTEN
|
||||
| SERCOM_I2CM_CTRLA_INACTOUT(3)
|
||||
@@ -36,7 +29,7 @@ i2c_init(void)
|
||||
| SERCOM_I2CM_STATUS_MEXTTOUT
|
||||
| SERCOM_I2CM_CTRLA_MODE(5));
|
||||
si->CTRLA.reg = areg;
|
||||
uint32_t freq = get_pclock_frequency(SERCOM3_GCLK_ID_CORE);
|
||||
uint32_t freq = sercom_get_pclock_frequency(bus);
|
||||
uint32_t baud = (freq/I2C_FREQ - 10 - freq*TIME_RISE/1000000000) / 2;
|
||||
si->BAUD.reg = baud;
|
||||
si->CTRLA.reg = areg | SERCOM_I2CM_CTRLA_ENABLE;
|
||||
@@ -52,10 +45,17 @@ i2c_init(void)
|
||||
struct i2c_config
|
||||
i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
|
||||
{
|
||||
if (bus)
|
||||
#ifdef SERCOM7
|
||||
if (bus > 7)
|
||||
#else
|
||||
if (bus > 5)
|
||||
#endif
|
||||
shutdown("Unsupported i2c bus");
|
||||
i2c_init();
|
||||
return (struct i2c_config){ .addr=addr<<1 };
|
||||
Sercom *sercom = sercom_enable_pclock(bus);
|
||||
sercom_i2c_pins(bus);
|
||||
SercomI2cm *si = &sercom->I2CM;
|
||||
i2c_init(bus, si);
|
||||
return (struct i2c_config){ .si=si, .addr=addr<<1 };
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -97,7 +97,7 @@ i2c_stop(SercomI2cm *si)
|
||||
void
|
||||
i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write)
|
||||
{
|
||||
SercomI2cm *si = &SERCOM3->I2CM;
|
||||
SercomI2cm *si = (SercomI2cm *)config.si;
|
||||
i2c_start(si, config.addr);
|
||||
while (write_len--)
|
||||
i2c_send_byte(si, *write++);
|
||||
|
||||
Reference in New Issue
Block a user