From 26ba99e972c952b58a400e67966f87154cda2c48 Mon Sep 17 00:00:00 2001 From: Piotr Mienkowski Date: Sun, 21 May 2017 02:47:32 +0200 Subject: [PATCH] drivers: Add Atmel SAM family I2C (TWI) driver Added I2C bus (TWI) driver for Atmel SAM MCU family. Only I2C Master Mode with 7 bit addressing is currently supported. Tested on Arduino Due board. Origin: Original Signed-off-by: Piotr Mienkowski --- arch/arm/soc/atmel_sam/sam4s/soc_pinmap.h | 12 + boards/arm/arduino_due/Kconfig.defconfig | 7 +- boards/arm/sam4s_xplained/Kconfig.defconfig | 10 + .../arm/sam4s_xplained/doc/sam4s_xplained.rst | 2 + drivers/i2c/Kconfig | 12 +- drivers/i2c/Makefile | 1 + drivers/i2c/i2c_sam_twi.c | 396 ++++++++++++++++++ dts/arm/arduino_due.dts | 10 + dts/arm/arduino_due.fixup | 14 + dts/arm/atmel/sam3x.dtsi | 21 + dts/arm/atmel/sam4s.dtsi | 21 + dts/arm/sam4s_xplained.dts | 9 + dts/arm/sam4s_xplained.fixup | 14 + dts/arm/yaml/atmel,sam-i2c-twi.yaml | 36 ++ 14 files changed, 557 insertions(+), 8 deletions(-) create mode 100644 drivers/i2c/i2c_sam_twi.c create mode 100644 dts/arm/yaml/atmel,sam-i2c-twi.yaml diff --git a/arch/arm/soc/atmel_sam/sam4s/soc_pinmap.h b/arch/arm/soc/atmel_sam/sam4s/soc_pinmap.h index 0fd69435f1a..d847a6eef8e 100644 --- a/arch/arm/soc/atmel_sam/sam4s/soc_pinmap.h +++ b/arch/arm/soc/atmel_sam/sam4s/soc_pinmap.h @@ -27,4 +27,16 @@ #define PINS_UART1 {PIN_UART1_RXD, PIN_UART1_TXD} +/* Two-wire Interface (TWI) */ + +#define PIN_TWI0_TWCK {PIO_PA4A_TWCK0, PIOA, ID_PIOA, SOC_GPIO_FUNC_A} +#define PIN_TWI0_TWD {PIO_PA3A_TWD0, PIOA, ID_PIOA, SOC_GPIO_FUNC_A} + +#define PINS_TWI0 {PIN_TWI0_TWCK, PIN_TWI0_TWD} + +#define PIN_TWI1_TWCK {PIO_PB5A_TWCK1, PIOB, ID_PIOB, SOC_GPIO_FUNC_A} +#define PIN_TWI1_TWD {PIO_PB4A_TWD1, PIOB, ID_PIOB, SOC_GPIO_FUNC_A} + +#define PINS_TWI1 {PIN_TWI1_TWCK, PIN_TWI1_TWD} + #endif /* _ATMEL_SAM4S_SOC_PINMAP_H_ */ diff --git a/boards/arm/arduino_due/Kconfig.defconfig b/boards/arm/arduino_due/Kconfig.defconfig index b5d1d0ebcac..db0ee385789 100644 --- a/boards/arm/arduino_due/Kconfig.defconfig +++ b/boards/arm/arduino_due/Kconfig.defconfig @@ -40,20 +40,15 @@ endif # GPIO if I2C -config I2C_ATMEL_SAM3 +config I2C_SAM_TWI def_bool y config I2C_0 default y -config I2C_0_IRQ_PRI - default 0 config I2C_1 default y -config I2C_1_IRQ_PRI - default 0 - endif # I2C endif # BOARD_ARDUINO_DUE diff --git a/boards/arm/sam4s_xplained/Kconfig.defconfig b/boards/arm/sam4s_xplained/Kconfig.defconfig index 462216b6bb0..a6b711e2ff4 100644 --- a/boards/arm/sam4s_xplained/Kconfig.defconfig +++ b/boards/arm/sam4s_xplained/Kconfig.defconfig @@ -10,4 +10,14 @@ config BOARD string default sam4s_xplained +if I2C + +config I2C_SAM_TWI + default y + +config I2C_0 + default y + +endif # I2C + endif # BOARD_SAM4S_XPLAINED diff --git a/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst b/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst index 358b7e83594..0cee60cd71d 100644 --- a/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst +++ b/boards/arm/sam4s_xplained/doc/sam4s_xplained.rst @@ -43,6 +43,8 @@ features: +-----------+------------+-------------------------------------+ | UART | on-chip | serial port | +-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ Other hardware features are not currently supported by Zephyr. diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 9d5e6a32742..5ed9c67f26c 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -54,11 +54,19 @@ config I2C_ATMEL_SAM3 for individual controllers. config TWIHS_SAM - bool "Atmel SAM I2C driver" + bool "Atmel SAM (TWIHS) I2C driver" depends on SOC_FAMILY_SAM default n help - Enable Atmel SAM MCU Family I2C bus driver. + Enable Atmel SAM MCU Family (TWIHS) I2C bus driver. + +config I2C_SAM_TWI + bool "Atmel SAM (TWI) I2C driver" + depends on SOC_FAMILY_SAM + select HAS_DTS_I2C + default n + help + Enable Atmel SAM MCU Family (TWI) I2C bus driver. config I2C_MCUX bool "MCUX I2C driver" diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index dcbe3ca4d6f..d4c5d484108 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_I2C_NRF5) += i2c_nrf5.o obj-$(CONFIG_I2C_QMSI) += i2c_qmsi.o obj-$(CONFIG_I2C_QMSI_SS) += i2c_qmsi_ss.o obj-$(CONFIG_I2C_SBCON) += i2c_sbcon.o +obj-$(CONFIG_I2C_SAM_TWI) += i2c_sam_twi.o obj-$(CONFIG_I2C_STM32_V1) += i2c_ll_stm32_v1.o i2c_ll_stm32.o obj-$(CONFIG_I2C_STM32_V2) += i2c_ll_stm32_v2.o i2c_ll_stm32.o obj-$(CONFIG_TWIHS_SAM) += twihs_sam.o diff --git a/drivers/i2c/i2c_sam_twi.c b/drivers/i2c/i2c_sam_twi.c new file mode 100644 index 00000000000..c47ece02c4a --- /dev/null +++ b/drivers/i2c/i2c_sam_twi.c @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2017 Piotr Mienkowski + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief I2C bus (TWI) driver for Atmel SAM MCU family. + * + * Limitations: + * - Only I2C Master Mode with 7 bit addressing is currently supported. + * - No reentrancy support. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2c-priv.h" + +#define SYS_LOG_DOMAIN "dev/i2c_sam_twi" +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_I2C_LEVEL +#include + +/** I2C bus speed [Hz] in Standard Mode */ +#define BUS_SPEED_STANDARD_HZ 100000U +/** I2C bus speed [Hz] in Fast Mode */ +#define BUS_SPEED_FAST_HZ 400000U +/* Maximum value of Clock Divider (CKDIV) */ +#define CKDIV_MAX 7 + +/* Device constant configuration parameters */ +struct i2c_sam_twi_dev_cfg { + Twi *regs; + void (*irq_config)(void); + u32_t bitrate; + const struct soc_gpio_pin *pin_list; + u8_t pin_list_size; + u8_t periph_id; + u8_t irq_id; +}; + +struct twi_msg { + /* Buffer containing data to read or write */ + u8_t *buf; + /* Length of the buffer */ + u32_t len; + /* Index of the next byte to be read/written from/to the buffer */ + u32_t idx; + /* Value of TWI_SR at the end of the message */ + u32_t twi_sr; + /* Transfer flags as defined in the i2c.h file */ + u8_t flags; +}; + +/* Device run time data */ +struct i2c_sam_twi_dev_data { + struct k_sem sem; + struct twi_msg msg; +}; + +#define DEV_NAME(dev) ((dev)->config->name) +#define DEV_CFG(dev) \ + ((const struct i2c_sam_twi_dev_cfg *const)(dev)->config->config_info) +#define DEV_DATA(dev) \ + ((struct i2c_sam_twi_dev_data *const)(dev)->driver_data) + +static int i2c_clk_set(Twi *const twi, u32_t speed) +{ + u32_t ck_div = 0; + u32_t cl_div; + bool div_completed = false; + + /* From the datasheet "TWI Clock Waveform Generator Register" + * T_low = ( ( CLDIV × 2^CKDIV ) + 4 ) × T_MCK + */ + while (!div_completed) { + cl_div = ((SOC_ATMEL_SAM_MCK_FREQ_HZ / (2 * speed)) - 4) + / (1 << ck_div); + + if (cl_div <= 255) { + div_completed = true; + } else { + ck_div++; + } + } + + if (ck_div > CKDIV_MAX) { + SYS_LOG_ERR("Failed to configure I2C clock"); + return -EIO; + } + + /* Set TWI clock duty cycle to 50% */ + twi->TWI_CWGR = TWI_CWGR_CLDIV(cl_div) | TWI_CWGR_CHDIV(cl_div) + | TWI_CWGR_CKDIV(ck_div); + + return 0; +} + +static int i2c_sam_twi_configure(struct device *dev, u32_t config) +{ + const struct i2c_sam_twi_dev_cfg *const dev_cfg = DEV_CFG(dev); + Twi *const twi = dev_cfg->regs; + u32_t bitrate; + int ret; + + if (!(config & I2C_MODE_MASTER)) { + SYS_LOG_ERR("Master Mode is not enabled"); + return -EIO; + } + + if (config & I2C_ADDR_10_BITS) { + SYS_LOG_ERR("I2C 10-bit addressing is currently not supported"); + SYS_LOG_ERR("Please submit a patch"); + return -EIO; + } + + /* Configure clock */ + switch (I2C_SPEED_GET(config)) { + case I2C_SPEED_STANDARD: + bitrate = BUS_SPEED_STANDARD_HZ; + break; + case I2C_SPEED_FAST: + bitrate = BUS_SPEED_FAST_HZ; + break; + default: + SYS_LOG_ERR("Unsupported I2C speed value"); + return -EIO; + } + + /* Setup clock waveform */ + ret = i2c_clk_set(twi, bitrate); + if (ret < 0) { + return ret; + } + + /* Disable Slave Mode */ + twi->TWI_CR = TWI_CR_SVDIS; + + /* Enable Master Mode */ + twi->TWI_CR = TWI_CR_MSEN; + + return 0; +} + +static void write_msg_start(Twi *const twi, struct twi_msg *msg, u8_t daddr) +{ + /* Set slave address and number of internal address bytes. */ + twi->TWI_MMR = TWI_MMR_DADR(daddr); + + /* Write first data byte on I2C bus */ + twi->TWI_THR = msg->buf[msg->idx++]; + + /* Enable Transmit Ready and Transmission Completed interrupts */ + twi->TWI_IER = TWI_IER_TXRDY | TWI_IER_TXCOMP | TWI_IER_NACK; +} + +static void read_msg_start(Twi *const twi, struct twi_msg *msg, u8_t daddr) +{ + u32_t twi_cr_stop; + + /* Set slave address and number of internal address bytes */ + twi->TWI_MMR = TWI_MMR_MREAD | TWI_MMR_DADR(daddr); + + /* In single data byte read the START and STOP must both be set */ + twi_cr_stop = (msg->len == 1) ? TWI_CR_STOP : 0; + /* Start the transfer by sending START condition */ + twi->TWI_CR = TWI_CR_START | twi_cr_stop; + + /* Enable Receive Ready and Transmission Completed interrupts */ + twi->TWI_IER = TWI_IER_RXRDY | TWI_IER_TXCOMP | TWI_IER_NACK; +} + +static int i2c_sam_twi_transfer(struct device *dev, struct i2c_msg *msgs, + u8_t num_msgs, u16_t addr) +{ + const struct i2c_sam_twi_dev_cfg *const dev_cfg = DEV_CFG(dev); + struct i2c_sam_twi_dev_data *const dev_data = DEV_DATA(dev); + Twi *const twi = dev_cfg->regs; + + __ASSERT_NO_MSG(msgs); + if (!num_msgs) { + return 0; + } + + /* Clear pending interrupts, such as NACK. */ + (void)twi->TWI_SR; + + /* Set number of internal address bytes to 0, not used. */ + twi->TWI_IADR = 0; + + for (; num_msgs > 0; num_msgs--, msgs++) { + dev_data->msg.buf = msgs->buf; + dev_data->msg.len = msgs->len; + dev_data->msg.idx = 0; + dev_data->msg.twi_sr = 0; + dev_data->msg.flags = msgs->flags; + + /* + * REMARK: Dirty workaround: + * + * The controller does not have a documented, generic way to + * issue RESTART when changing transfer direction as master. + * Send a stop condition in such a case. + */ + if (num_msgs > 1) { + if ((msgs[0].flags & I2C_MSG_RW_MASK) != + (msgs[1].flags & I2C_MSG_RW_MASK)) { + dev_data->msg.flags |= I2C_MSG_STOP; + } + } + + if ((msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { + read_msg_start(twi, &dev_data->msg, addr); + } else { + write_msg_start(twi, &dev_data->msg, addr); + } + /* Wait for the transfer to complete */ + k_sem_take(&dev_data->sem, K_FOREVER); + + if (dev_data->msg.twi_sr > 0) { + /* Something went wrong */ + return -EIO; + } + } + + return 0; +} + +static void i2c_sam_twi_isr(void *arg) +{ + struct device *dev = (struct device *)arg; + const struct i2c_sam_twi_dev_cfg *const dev_cfg = DEV_CFG(dev); + struct i2c_sam_twi_dev_data *const dev_data = DEV_DATA(dev); + Twi *const twi = dev_cfg->regs; + struct twi_msg *msg = &dev_data->msg; + u32_t isr_status; + + /* Retrieve interrupt status */ + isr_status = twi->TWI_SR & twi->TWI_IMR; + + /* Not Acknowledged */ + if (isr_status & TWI_SR_NACK) { + msg->twi_sr = isr_status; + goto tx_comp; + } + + /* Byte received */ + if (isr_status & TWI_SR_RXRDY) { + + msg->buf[msg->idx++] = twi->TWI_RHR; + + if (msg->idx == msg->len - 1) { + /* Send a STOP condition on the TWI */ + twi->TWI_CR = TWI_CR_STOP; + } + } + + /* Byte sent */ + if (isr_status & TWI_SR_TXRDY) { + if (msg->idx == msg->len) { + if (msg->flags & I2C_MSG_STOP) { + /* Send a STOP condition on the TWI */ + twi->TWI_CR = TWI_CR_STOP; + /* Disable Transmit Ready interrupt */ + twi->TWI_IDR = TWI_IDR_TXRDY; + } else { + /* Transmission completed */ + goto tx_comp; + } + } else { + twi->TWI_THR = msg->buf[msg->idx++]; + } + } + + /* Transmission completed */ + if (isr_status & TWI_SR_TXCOMP) { + goto tx_comp; + } + + return; + +tx_comp: + /* Disable all enabled interrupts */ + twi->TWI_IDR = twi->TWI_IMR; + /* We are done */ + k_sem_give(&dev_data->sem); +} + +static int i2c_sam_twi_initialize(struct device *dev) +{ + const struct i2c_sam_twi_dev_cfg *const dev_cfg = DEV_CFG(dev); + struct i2c_sam_twi_dev_data *const dev_data = DEV_DATA(dev); + Twi *const twi = dev_cfg->regs; + u32_t bitrate_cfg; + int ret; + + /* Configure interrupts */ + dev_cfg->irq_config(); + + /* Initialize semaphore */ + k_sem_init(&dev_data->sem, 0, 1); + + /* Connect pins to the peripheral */ + soc_gpio_list_configure(dev_cfg->pin_list, dev_cfg->pin_list_size); + + /* Enable module's clock */ + soc_pmc_peripheral_enable(dev_cfg->periph_id); + + /* Reset TWI module */ + twi->TWI_CR = TWI_CR_SWRST; + + bitrate_cfg = _i2c_map_dt_bitrate(dev_cfg->bitrate); + + ret = i2c_sam_twi_configure(dev, I2C_MODE_MASTER | bitrate_cfg); + if (ret < 0) { + SYS_LOG_ERR("Failed to initialize %s device", DEV_NAME(dev)); + return ret; + } + + /* Enable module's IRQ */ + irq_enable(dev_cfg->irq_id); + + SYS_LOG_INF("Device %s initialized", DEV_NAME(dev)); + + return 0; +} + +static const struct i2c_driver_api i2c_sam_twi_driver_api = { + .configure = i2c_sam_twi_configure, + .transfer = i2c_sam_twi_transfer, +}; + +/* I2C0 */ + +#ifdef CONFIG_I2C_0 +static struct device DEVICE_NAME_GET(i2c0_sam); + +static void i2c0_sam_irq_config(void) +{ + IRQ_CONNECT(CONFIG_I2C_0_IRQ, CONFIG_I2C_0_IRQ_PRI, i2c_sam_twi_isr, + DEVICE_GET(i2c0_sam), 0); +} + +static const struct soc_gpio_pin pins_twi0[] = PINS_TWI0; + +static const struct i2c_sam_twi_dev_cfg i2c0_sam_config = { + .regs = (Twi *)CONFIG_I2C_0_BASE_ADDRESS, + .irq_config = i2c0_sam_irq_config, + .periph_id = CONFIG_I2C_0_PERIPHERAL_ID, + .irq_id = CONFIG_I2C_0_IRQ, + .pin_list = pins_twi0, + .pin_list_size = ARRAY_SIZE(pins_twi0), + .bitrate = CONFIG_I2C_0_BITRATE, +}; + +static struct i2c_sam_twi_dev_data i2c0_sam_data; + +DEVICE_AND_API_INIT(i2c0_sam, CONFIG_I2C_0_NAME, &i2c_sam_twi_initialize, + &i2c0_sam_data, &i2c0_sam_config, POST_KERNEL, + CONFIG_I2C_INIT_PRIORITY, &i2c_sam_twi_driver_api); +#endif + +/* I2C1 */ + +#ifdef CONFIG_I2C_1 +static struct device DEVICE_NAME_GET(i2c1_sam); + +static void i2c1_sam_irq_config(void) +{ + IRQ_CONNECT(CONFIG_I2C_1_IRQ, CONFIG_I2C_1_IRQ_PRI, i2c_sam_twi_isr, + DEVICE_GET(i2c1_sam), 0); +} + +static const struct soc_gpio_pin pins_twi1[] = PINS_TWI1; + +static const struct i2c_sam_twi_dev_cfg i2c1_sam_config = { + .regs = (Twi *)CONFIG_I2C_1_BASE_ADDRESS, + .irq_config = i2c1_sam_irq_config, + .periph_id = CONFIG_I2C_1_PERIPHERAL_ID, + .irq_id = CONFIG_I2C_1_IRQ, + .pin_list = pins_twi1, + .pin_list_size = ARRAY_SIZE(pins_twi1), + .bitrate = CONFIG_I2C_1_BITRATE, +}; + +static struct i2c_sam_twi_dev_data i2c1_sam_data; + +DEVICE_AND_API_INIT(i2c1_sam, CONFIG_I2C_1_NAME, &i2c_sam_twi_initialize, + &i2c1_sam_data, &i2c1_sam_config, POST_KERNEL, + CONFIG_I2C_INIT_PRIORITY, &i2c_sam_twi_driver_api); +#endif diff --git a/dts/arm/arduino_due.dts b/dts/arm/arduino_due.dts index 092a90a72d1..80522300a3c 100644 --- a/dts/arm/arduino_due.dts +++ b/dts/arm/arduino_due.dts @@ -8,6 +8,8 @@ aliases { uart_0 = &uart0; + i2c_0 = &i2c0; + i2c_1 = &i2c1; }; chosen { @@ -17,6 +19,14 @@ }; }; +&i2c0 { + status = "ok"; +}; + +&i2c1 { + status = "ok"; +}; + &uart0 { status = "ok"; current-speed = <115200>; diff --git a/dts/arm/arduino_due.fixup b/dts/arm/arduino_due.fixup index bb2f999f47b..859c62451a1 100644 --- a/dts/arm/arduino_due.fixup +++ b/dts/arm/arduino_due.fixup @@ -5,6 +5,20 @@ */ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS + +#define CONFIG_I2C_0_BASE_ADDRESS ATMEL_SAM_I2C_TWI_4008C000_BASE_ADDRESS +#define CONFIG_I2C_0_NAME ATMEL_SAM_I2C_TWI_4008C000_LABEL +#define CONFIG_I2C_0_BITRATE ATMEL_SAM_I2C_TWI_4008C000_CLOCK_FREQUENCY +#define CONFIG_I2C_0_IRQ ATMEL_SAM_I2C_TWI_4008C000_IRQ_0 +#define CONFIG_I2C_0_IRQ_PRI ATMEL_SAM_I2C_TWI_4008C000_IRQ_0_PRIORITY +#define CONFIG_I2C_0_PERIPHERAL_ID ATMEL_SAM_I2C_TWI_4008C000_PERIPHERAL_ID +#define CONFIG_I2C_1_BASE_ADDRESS ATMEL_SAM_I2C_TWI_40090000_BASE_ADDRESS +#define CONFIG_I2C_1_NAME ATMEL_SAM_I2C_TWI_40090000_LABEL +#define CONFIG_I2C_1_BITRATE ATMEL_SAM_I2C_TWI_40090000_CLOCK_FREQUENCY +#define CONFIG_I2C_1_IRQ ATMEL_SAM_I2C_TWI_40090000_IRQ_0 +#define CONFIG_I2C_1_IRQ_PRI ATMEL_SAM_I2C_TWI_40090000_IRQ_0_PRIORITY +#define CONFIG_I2C_1_PERIPHERAL_ID ATMEL_SAM_I2C_TWI_40090000_PERIPHERAL_ID + #define CONFIG_UART_ATMEL_SAM3_NAME ATMEL_SAM_UART_400E0800_LABEL #define CONFIG_UART_SAM_PORT_0_NAME ATMEL_SAM_UART_400E0800_LABEL #define CONFIG_UART_SAM_PORT_0_BAUD_RATE ATMEL_SAM_UART_400E0800_CURRENT_SPEED diff --git a/dts/arm/atmel/sam3x.dtsi b/dts/arm/atmel/sam3x.dtsi index acb4edec05b..8853911c159 100644 --- a/dts/arm/atmel/sam3x.dtsi +++ b/dts/arm/atmel/sam3x.dtsi @@ -5,6 +5,7 @@ */ #include +#include / { cpus { @@ -29,6 +30,26 @@ }; soc { + i2c0: i2c@4008C000 { + compatible = "atmel,sam-i2c-twi"; + clock-frequency = ; + reg = <0x4008C000 0x128>; + interrupts = <22 0>; + peripheral-id = <22>; + label = "I2C_0"; + status = "disabled"; + }; + + i2c1: i2c@40090000 { + compatible = "atmel,sam-i2c-twi"; + clock-frequency = ; + reg = <0x40090000 0x128>; + interrupts = <23 0>; + peripheral-id = <23>; + label = "I2C_1"; + status = "disabled"; + }; + uart0: uart@400E0800 { compatible = "atmel,sam-uart"; reg = <0x400E0800 0x124>; diff --git a/dts/arm/atmel/sam4s.dtsi b/dts/arm/atmel/sam4s.dtsi index 53af49ed6b8..727c3b77351 100644 --- a/dts/arm/atmel/sam4s.dtsi +++ b/dts/arm/atmel/sam4s.dtsi @@ -5,6 +5,7 @@ */ #include +#include / { cpus { @@ -29,6 +30,26 @@ }; soc { + i2c0: i2c@40018000 { + compatible = "atmel,sam-i2c-twi"; + clock-frequency = ; + reg = <0x40018000 0x128>; + interrupts = <19 0>; + peripheral-id = <19>; + label = "I2C_0"; + status = "disabled"; + }; + + i2c1: i2c@4001C000 { + compatible = "atmel,sam-i2c-twi"; + clock-frequency = ; + reg = <0x4001C000 0x128>; + interrupts = <20 0>; + peripheral-id = <20>; + label = "I2C_1"; + status = "disabled"; + }; + uart0: uart@400E0600 { compatible = "atmel,sam-uart"; reg = <0x400E0600 0x200>; diff --git a/dts/arm/sam4s_xplained.dts b/dts/arm/sam4s_xplained.dts index f65cd52c643..e5e999e9da9 100644 --- a/dts/arm/sam4s_xplained.dts +++ b/dts/arm/sam4s_xplained.dts @@ -11,6 +11,11 @@ model = "Atmel SAM4S Xplained Board with an Atmel SAM4S16C SoC"; compatible = "atmel,sam4s_xplained", "atmel,sam4s16c", "atmel,sam4s"; + aliases { + i2c_0 = &i2c0; + i2c_1 = &i2c1; + }; + chosen { zephyr,console = &uart1; zephyr,sram = &sram0; @@ -18,6 +23,10 @@ }; }; +&i2c0 { + status = "ok"; +}; + &uart1 { current-speed = <115200>; status = "ok"; diff --git a/dts/arm/sam4s_xplained.fixup b/dts/arm/sam4s_xplained.fixup index 053e09d7808..8775d62e8ec 100644 --- a/dts/arm/sam4s_xplained.fixup +++ b/dts/arm/sam4s_xplained.fixup @@ -6,6 +6,20 @@ #define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS + +#define CONFIG_I2C_0_BASE_ADDRESS ATMEL_SAM_I2C_TWI_40018000_BASE_ADDRESS +#define CONFIG_I2C_0_NAME ATMEL_SAM_I2C_TWI_40018000_LABEL +#define CONFIG_I2C_0_BITRATE ATMEL_SAM_I2C_TWI_40018000_CLOCK_FREQUENCY +#define CONFIG_I2C_0_IRQ ATMEL_SAM_I2C_TWI_40018000_IRQ_0 +#define CONFIG_I2C_0_IRQ_PRI ATMEL_SAM_I2C_TWI_40018000_IRQ_0_PRIORITY +#define CONFIG_I2C_0_PERIPHERAL_ID ATMEL_SAM_I2C_TWI_40018000_PERIPHERAL_ID +#define CONFIG_I2C_1_BASE_ADDRESS ATMEL_SAM_I2C_TWI_4001C000_BASE_ADDRESS +#define CONFIG_I2C_1_NAME ATMEL_SAM_I2C_TWI_4001C000_LABEL +#define CONFIG_I2C_1_BITRATE ATMEL_SAM_I2C_TWI_4001C000_CLOCK_FREQUENCY +#define CONFIG_I2C_1_IRQ ATMEL_SAM_I2C_TWI_4001C000_IRQ_0 +#define CONFIG_I2C_1_IRQ_PRI ATMEL_SAM_I2C_TWI_4001C000_IRQ_0_PRIORITY +#define CONFIG_I2C_1_PERIPHERAL_ID ATMEL_SAM_I2C_TWI_4001C000_PERIPHERAL_ID + #define CONFIG_UART_SAM_PORT_0_NAME ATMEL_SAM_UART_400E0600_LABEL #define CONFIG_UART_SAM_PORT_0_BAUD_RATE ATMEL_SAM_UART_400E0600_CURRENT_SPEED #define CONFIG_UART_SAM_PORT_1_NAME ATMEL_SAM_UART_400E0800_LABEL diff --git a/dts/arm/yaml/atmel,sam-i2c-twi.yaml b/dts/arm/yaml/atmel,sam-i2c-twi.yaml new file mode 100644 index 00000000000..5d39436257c --- /dev/null +++ b/dts/arm/yaml/atmel,sam-i2c-twi.yaml @@ -0,0 +1,36 @@ +--- +title: Atmel SAM Family I2C (TWI) node +id: atmel,sam-i2c-twi +version: 0.1 + +description: > + This is a representation of the Atmel SAM Family I2C (TWI) node + +inherits: + - !include i2c.yaml + +properties: + - compatible: + type: string + category: required + description: compatible strings + constraint: "atmel,sam-i2c-twi" + + - reg: + type: array + description: mmio register space + generation: define + category: required + + - interrupts: + type: array + category: required + description: required interrupts + generation: define + + - peripheral-id: + type: int + description: peripheral ID + generation: define + category: required +...