From 45a63ee8d635b98be3141c7958590511bc45b901 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 10 Nov 2014 13:46:32 +0100 Subject: bsp/xilinx-zynq: Add Cadence I2C bus driver --- c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am | 6 + c/src/lib/libbsp/arm/xilinx-zynq/i2c/cadence-i2c.c | 469 +++++++++++++++++++++ .../arm/xilinx-zynq/include/cadence-i2c-regs.h | 73 ++++ .../libbsp/arm/xilinx-zynq/include/cadence-i2c.h | 35 ++ c/src/lib/libbsp/arm/xilinx-zynq/include/i2c.h | 50 +++ c/src/lib/libbsp/arm/xilinx-zynq/preinstall.am | 12 + 6 files changed, 645 insertions(+) create mode 100644 c/src/lib/libbsp/arm/xilinx-zynq/i2c/cadence-i2c.c create mode 100644 c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c-regs.h create mode 100644 c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c.h create mode 100644 c/src/lib/libbsp/arm/xilinx-zynq/include/i2c.h diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am index 1bce30a1a1..15f8af4f90 100644 --- a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am +++ b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am @@ -43,6 +43,9 @@ include_bsp_HEADERS += ../shared/include/arm-gic-irq.h include_bsp_HEADERS += ../shared/include/arm-gic-regs.h include_bsp_HEADERS += ../shared/include/arm-gic-tm27.h include_bsp_HEADERS += ../shared/include/arm-release-id.h +include_bsp_HEADERS += include/cadence-i2c.h +include_bsp_HEADERS += include/cadence-i2c-regs.h +include_bsp_HEADERS += include/i2c.h include_bsp_HEADERS += include/irq.h include_bsp_HEADERS += include/zynq-uart.h include_bsp_HEADERS += include/zynq-uart-regs.h @@ -114,6 +117,9 @@ libbsp_a_SOURCES += console/zynq-uart.c libbsp_a_SOURCES += ../../shared/clockdrv_shell.h libbsp_a_SOURCES += ../shared/arm-a9mpcore-clock-config.c +# I2C +libbsp_a_SOURCES += i2c/cadence-i2c.c + # Cache libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c libbsp_a_SOURCES += ../shared/arm-l2c-310/cache_.h diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/i2c/cadence-i2c.c b/c/src/lib/libbsp/arm/xilinx-zynq/i2c/cadence-i2c.c new file mode 100644 index 0000000000..76211da496 --- /dev/null +++ b/c/src/lib/libbsp/arm/xilinx-zynq/i2c/cadence-i2c.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include + +#include +#include + +#include + +#define CADENCE_I2C_DIV_A_MAX 4 + +#define CADENCE_I2C_DIV_B_MAX 64 + +#define CADENCE_I2C_FIFO_DEPTH 16 + +#define CADENCE_I2C_DATA_IRQ_DEPTH (CADENCE_I2C_FIFO_DEPTH - 2) + +#define CADENCE_I2C_TRANSFER_SIZE_MAX 255 + +#define CADENCE_I2C_TRANSFER_SIZE_ONCE_MAX (18 * CADENCE_I2C_DATA_IRQ_DEPTH) + +#define CADENCE_I2C_IRQ_ERROR \ + (CADENCE_I2C_IXR_ARB_LOST \ + | CADENCE_I2C_IXR_RX_UNF \ + | CADENCE_I2C_IXR_TX_OVR \ + | CADENCE_I2C_IXR_RX_OVR \ + | CADENCE_I2C_IXR_NACK) + +#define CADENCE_I2C_IRQ_USED \ + (CADENCE_I2C_IRQ_ERROR \ + | CADENCE_I2C_IXR_DATA \ + | CADENCE_I2C_IXR_COMP) + +typedef struct { + i2c_bus base; + volatile cadence_i2c *regs; + i2c_msg *msgs; + uint32_t msg_todo; + uint32_t current_msg_todo; + uint8_t *current_msg_byte; + uint32_t current_todo; + uint32_t irqstatus; + bool read; + bool hold; + rtems_id task_id; + uint32_t input_clock; + rtems_vector_number irq; +} cadence_i2c_bus; + +static void cadence_i2c_disable_interrupts(volatile cadence_i2c *regs) +{ + regs->irqdisable = 0xffff; +} + +static void cadence_i2c_clear_irq_status(volatile cadence_i2c *regs) +{ + regs->irqstatus = regs->irqstatus; +} + +static void cadence_i2c_reset(cadence_i2c_bus *bus) +{ + volatile cadence_i2c *regs = bus->regs; + uint32_t val; + + cadence_i2c_disable_interrupts(regs); + + val = regs->control; + val &= ~CADENCE_I2C_CONTROL_HOLD; + val |= CADENCE_I2C_CONTROL_ACKEN + | CADENCE_I2C_CONTROL_MS + | CADENCE_I2C_CONTROL_CLR_FIFO; + regs->control = val; + + regs->transfer_size = 0; + regs->status = regs->status; + + cadence_i2c_clear_irq_status(regs); +} + +static uint32_t cadence_i2c_set_address_size( + const i2c_msg *msg, + uint32_t control +) +{ + if ((msg->flags & I2C_M_TEN) == 0) { + control |= CADENCE_I2C_CONTROL_NEA; + } else { + control &= ~CADENCE_I2C_CONTROL_NEA; + } + + return control; +} + +static void cadence_i2c_setup_read_transfer( + cadence_i2c_bus *bus, + volatile cadence_i2c *regs, + uint32_t control +) +{ + control |= CADENCE_I2C_CONTROL_RW; + regs->control = control; + + if (bus->current_todo <= CADENCE_I2C_TRANSFER_SIZE_MAX) { + regs->transfer_size = bus->current_todo; + } else { + regs->transfer_size = CADENCE_I2C_TRANSFER_SIZE_ONCE_MAX; + } +} + +static void cadence_i2c_next_byte(cadence_i2c_bus *bus) +{ + --bus->current_msg_todo; + ++bus->current_msg_byte; + + if (bus->current_msg_todo == 0) { + i2c_msg *msg; + + ++bus->msgs; + --bus->msg_todo; + + msg = &bus->msgs[0]; + + bus->current_msg_todo = msg->len; + bus->current_msg_byte = msg->buf; + } +} + +static void cadence_i2c_write_to_fifo( + cadence_i2c_bus *bus, + volatile cadence_i2c *regs +) +{ + uint32_t space_available; + uint32_t todo_now; + uint32_t i; + + space_available = CADENCE_I2C_FIFO_DEPTH - regs->transfer_size; + + if (bus->current_todo > space_available) { + todo_now = space_available; + } else { + todo_now = bus->current_todo; + } + + bus->current_todo -= todo_now; + + for (i = 0; i < todo_now; ++i) { + regs->data = *bus->current_msg_byte; + + cadence_i2c_next_byte(bus); + } +} + +static void cadence_i2c_setup_write_transfer( + cadence_i2c_bus *bus, + volatile cadence_i2c *regs, + uint32_t control +) +{ + control &= ~CADENCE_I2C_CONTROL_RW; + regs->control = control; + + cadence_i2c_write_to_fifo(bus, regs); +} + +static void cadence_i2c_setup_transfer( + cadence_i2c_bus *bus, + volatile cadence_i2c *regs +) +{ + const i2c_msg *msgs = bus->msgs; + uint32_t msg_todo = bus->msg_todo; + uint32_t i; + uint32_t control; + + bus->current_todo = msgs[0].len; + for (i = 1; i < msg_todo && (msgs[i].flags & I2C_M_NOSTART) != 0; ++i) { + bus->current_todo += msgs[i].len; + } + + regs = bus->regs; + + control = regs->control; + control |= CADENCE_I2C_CONTROL_CLR_FIFO; + + bus->hold = i < msg_todo; + + if (bus->hold || bus->current_todo > CADENCE_I2C_FIFO_DEPTH) { + control |= CADENCE_I2C_CONTROL_HOLD; + } else { + control &= ~CADENCE_I2C_CONTROL_HOLD; + } + + control = cadence_i2c_set_address_size(msgs, control); + + bus->read = (msgs->flags & I2C_M_RD) != 0; + if (bus->read) { + cadence_i2c_setup_read_transfer(bus, regs, control); + } else { + cadence_i2c_setup_write_transfer(bus, regs, control); + } + + cadence_i2c_clear_irq_status(regs); + + regs->address = CADENCE_I2C_ADDRESS(msgs->addr); +} + +static void cadence_i2c_continue_read_transfer( + cadence_i2c_bus *bus, + volatile cadence_i2c *regs +) +{ + uint32_t i; + + bus->current_todo -= CADENCE_I2C_DATA_IRQ_DEPTH; + + /* + * This works since CADENCE_I2C_TRANSFER_SIZE_ONCE_MAX is an integral + * multiple of CADENCE_I2C_DATA_IRQ_DEPTH. + * + * FIXME: Tests with a 1024 byte EEPROM show that this doesn't work. Needs + * further investigations with an I2C analyser or an oscilloscope. + */ + if (regs->transfer_size == 0) { + if (bus->current_todo <= CADENCE_I2C_TRANSFER_SIZE_MAX) { + regs->transfer_size = bus->current_todo; + } else { + regs->transfer_size = CADENCE_I2C_TRANSFER_SIZE_ONCE_MAX; + } + } + + for (i = 0; i < CADENCE_I2C_DATA_IRQ_DEPTH; ++i) { + *bus->current_msg_byte = (uint8_t) regs->data; + + cadence_i2c_next_byte(bus); + } + + if (!bus->hold && bus->current_todo <= CADENCE_I2C_FIFO_DEPTH) { + regs->control &= ~CADENCE_I2C_CONTROL_HOLD; + } +} + +static void cadence_i2c_interrupt(void *arg) +{ + cadence_i2c_bus *bus = arg; + volatile cadence_i2c *regs = bus->regs; + uint32_t irqstatus = regs->irqstatus; + bool done = false; + + /* Clear interrupts */ + regs->irqstatus = irqstatus; + + if ((irqstatus & (CADENCE_I2C_IXR_ARB_LOST | CADENCE_I2C_IXR_NACK)) != 0) { + done = true; + } + + if ( + (irqstatus & CADENCE_I2C_IXR_DATA) != 0 + && bus->read + && bus->current_todo >= CADENCE_I2C_DATA_IRQ_DEPTH + ) { + cadence_i2c_continue_read_transfer(bus, regs); + } + + if ((irqstatus & CADENCE_I2C_IXR_COMP) != 0) { + if (bus->read) { + uint32_t todo_now = bus->current_todo; + uint32_t i; + + for (i = 0; i < todo_now; ++i) { + *bus->current_msg_byte = (uint8_t) regs->data; + + cadence_i2c_next_byte(bus); + } + + bus->current_todo = 0; + + done = true; + } else { + if (bus->current_todo > 0) { + cadence_i2c_write_to_fifo(bus, regs); + } else { + done = true; + } + + if (!bus->hold && bus->current_todo == 0) { + regs->control &= ~CADENCE_I2C_CONTROL_HOLD; + } + } + } + + if (done) { + uint32_t err = irqstatus & CADENCE_I2C_IRQ_ERROR; + + if (bus->msg_todo == 0 || err != 0) { + rtems_status_code sc; + + cadence_i2c_disable_interrupts(regs); + + bus->irqstatus = err; + + sc = rtems_event_transient_send(bus->task_id); + _Assert(sc == RTEMS_SUCCESSFUL); + (void) sc; + } else { + cadence_i2c_setup_transfer(bus, regs); + } + } +} + +static int cadence_i2c_transfer( + i2c_bus *base, + i2c_msg *msgs, + uint32_t msg_count +) +{ + cadence_i2c_bus *bus = (cadence_i2c_bus *) base; + volatile cadence_i2c *regs; + rtems_status_code sc; + uint32_t i; + + _Assert(msg_count > 0); + + for (i = 0; i < msg_count; ++i) { + /* FIXME: Not sure if we can support this. */ + if ((msgs[i].flags & I2C_M_RECV_LEN) != 0) { + return -EINVAL; + } + } + + bus->msgs = &msgs[0]; + bus->msg_todo = msg_count; + bus->current_msg_todo = msgs[0].len; + bus->current_msg_byte = msgs[0].buf; + bus->task_id = rtems_task_self(); + + regs = bus->regs; + cadence_i2c_setup_transfer(bus, regs); + regs->irqenable = CADENCE_I2C_IRQ_USED; + + sc = rtems_event_transient_receive(RTEMS_WAIT, bus->base.timeout); + if (sc != RTEMS_SUCCESSFUL) { + cadence_i2c_reset(bus); + rtems_event_transient_clear(); + + return -ETIMEDOUT; + } + + return bus->irqstatus == 0 ? 0 : -EIO; +} + +static int cadence_i2c_set_clock(i2c_bus *base, unsigned long clock) +{ + cadence_i2c_bus *bus = (cadence_i2c_bus *) base; + volatile cadence_i2c *regs = bus->regs; + uint32_t error = 0xffffffff; + uint32_t best_div_a = CADENCE_I2C_DIV_A_MAX - 1; + uint32_t best_div_b = CADENCE_I2C_DIV_B_MAX - 1; + uint32_t div = bus->input_clock / (22 * clock); + uint32_t div_a; + uint32_t control; + + if (div <= 0 || div > (CADENCE_I2C_DIV_A_MAX * CADENCE_I2C_DIV_B_MAX)) { + return -EIO; + } + + for (div_a = 0; div_a < CADENCE_I2C_DIV_A_MAX; ++div_a) { + uint32_t a = 22 * clock * (div_a + 1); + uint32_t b = (bus->input_clock + a - 1) / a; + + if (b > 0 && b <= CADENCE_I2C_DIV_B_MAX) { + uint32_t actual_clock = bus->input_clock / (22 * (div_a + 1) * b); + uint32_t e = clock < actual_clock ? + actual_clock - clock : clock - actual_clock; + + /* + * Favour greater div_a values according to UG585, Zynq-7000 AP SoC + * Technical Reference Manual, Table 20-1: Calculated Values for Standard + * and High Speed SCL Clock Values". + */ + if (e <= error && actual_clock <= clock) { + error = e; + best_div_a = div_a; + best_div_b = b - 1; + } + } + } + + control = regs->control; + control = CADENCE_I2C_CONTROL_DIV_A_SET(control, best_div_a); + control = CADENCE_I2C_CONTROL_DIV_B_SET(control, best_div_b); + regs->control = control; + + return 0; +} + +static void cadence_i2c_destroy(i2c_bus *base) +{ + cadence_i2c_bus *bus = (cadence_i2c_bus *) base; + rtems_status_code sc; + + sc = rtems_interrupt_handler_remove(bus->irq, cadence_i2c_interrupt, bus); + _Assert(sc == RTEMS_SUCCESSFUL); + (void) sc; + + i2c_bus_destroy_and_free(&bus->base); +} + +int i2c_bus_register_cadence( + const char *bus_path, + uintptr_t register_base, + uint32_t input_clock, + rtems_vector_number irq +) +{ + cadence_i2c_bus *bus; + rtems_status_code sc; + int err; + + bus = (cadence_i2c_bus *) i2c_bus_alloc_and_init(sizeof(*bus)); + if (bus == NULL) { + return -1; + } + + bus->regs = (volatile cadence_i2c *) register_base; + bus->input_clock = input_clock; + bus->irq = irq; + + cadence_i2c_reset(bus); + + err = cadence_i2c_set_clock(&bus->base, I2C_BUS_CLOCK_DEFAULT); + if (err != 0) { + (*bus->base.destroy)(&bus->base); + + rtems_set_errno_and_return_minus_one(-err); + } + + sc = rtems_interrupt_handler_install( + irq, + "Cadence I2C", + RTEMS_INTERRUPT_UNIQUE, + cadence_i2c_interrupt, + bus + ); + if (sc != RTEMS_SUCCESSFUL) { + (*bus->base.destroy)(&bus->base); + + rtems_set_errno_and_return_minus_one(EIO); + } + + bus->base.transfer = cadence_i2c_transfer; + bus->base.set_clock = cadence_i2c_set_clock; + bus->base.destroy = cadence_i2c_destroy; + + return i2c_bus_register(&bus->base, bus_path); +} diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c-regs.h b/c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c-regs.h new file mode 100644 index 0000000000..c06a47c7f1 --- /dev/null +++ b/c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c-regs.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_XILINX_ZYNQ_CADENCE_I2C_REGS_H +#define LIBBSP_ARM_XILINX_ZYNQ_CADENCE_I2C_REGS_H + +#include + +typedef struct { + uint32_t control; +#define CADENCE_I2C_CONTROL_DIV_A(val) BSP_FLD32(val, 14, 15) +#define CADENCE_I2C_CONTROL_DIV_A_GET(reg) BSP_FLD32GET(reg, 14, 15) +#define CADENCE_I2C_CONTROL_DIV_A_SET(reg, val) BSP_FLD32SET(reg, val, 14, 15) +#define CADENCE_I2C_CONTROL_DIV_B(val) BSP_FLD32(val, 8, 13) +#define CADENCE_I2C_CONTROL_DIV_B_GET(reg) BSP_FLD32GET(reg, 8, 13) +#define CADENCE_I2C_CONTROL_DIV_B_SET(reg, val) BSP_FLD32SET(reg, val, 8, 13) +#define CADENCE_I2C_CONTROL_CLR_FIFO BSP_BIT32(6) +#define CADENCE_I2C_CONTROL_SLVMON BSP_BIT32(5) +#define CADENCE_I2C_CONTROL_HOLD BSP_BIT32(4) +#define CADENCE_I2C_CONTROL_ACKEN BSP_BIT32(3) +#define CADENCE_I2C_CONTROL_NEA BSP_BIT32(2) +#define CADENCE_I2C_CONTROL_MS BSP_BIT32(1) +#define CADENCE_I2C_CONTROL_RW BSP_BIT32(0) + uint32_t status; +#define CADENCE_I2C_STATUS_BA BSP_BIT32(8) +#define CADENCE_I2C_STATUS_RXOVF BSP_BIT32(7) +#define CADENCE_I2C_STATUS_TXDV BSP_BIT32(6) +#define CADENCE_I2C_STATUS_RXDV BSP_BIT32(5) +#define CADENCE_I2C_STATUS_RXRW BSP_BIT32(3) + uint32_t address; +#define CADENCE_I2C_ADDRESS(val) BSP_FLD32(val, 0, 9) +#define CADENCE_I2C_ADDRESS_GET(reg) BSP_FLD32GET(reg, 0, 9) +#define CADENCE_I2C_ADDRESS_SET(reg, val) BSP_FLD32SET(reg, val, 0, 9) + uint32_t data; + uint32_t irqstatus; +#define CADENCE_I2C_IXR_ARB_LOST BSP_BIT32(9) +#define CADENCE_I2C_IXR_RX_UNF BSP_BIT32(7) +#define CADENCE_I2C_IXR_TX_OVR BSP_BIT32(6) +#define CADENCE_I2C_IXR_RX_OVR BSP_BIT32(5) +#define CADENCE_I2C_IXR_SLV_RDY BSP_BIT32(4) +#define CADENCE_I2C_IXR_TO BSP_BIT32(3) +#define CADENCE_I2C_IXR_NACK BSP_BIT32(2) +#define CADENCE_I2C_IXR_DATA BSP_BIT32(1) +#define CADENCE_I2C_IXR_COMP BSP_BIT32(0) + uint32_t transfer_size; +#define CADENCE_I2C_TRANSFER_SIZE(val) BSP_FLD32(val, 0, 7) +#define CADENCE_I2C_TRANSFER_SIZE_GET(reg) BSP_FLD32GET(reg, 0, 7) +#define CADENCE_I2C_TRANSFER_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 7) + uint32_t slave_mon_pause; +#define CADENCE_I2C_SLAVE_MON_PAUSE(val) BSP_FLD32(val, 0, 3) +#define CADENCE_I2C_SLAVE_MON_PAUSE_GET(reg) BSP_FLD32GET(reg, 0, 3) +#define CADENCE_I2C_SLAVE_MON_PAUSE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 3) + uint32_t timeout; +#define CADENCE_I2C_TIMEOUT(val) BSP_FLD32(val, 0, 7) +#define CADENCE_I2C_TIMEOUT_GET(reg) BSP_FLD32GET(reg, 0, 7) +#define CADENCE_I2C_TIMEOUT_SET(reg, val) BSP_FLD32SET(reg, val, 0, 7) + uint32_t irqmask; + uint32_t irqenable; + uint32_t irqdisable; +} cadence_i2c; + +#endif /* LIBBSP_ARM_XILINX_ZYNQ_CADENCE_I2C_REGS_H */ diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c.h b/c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c.h new file mode 100644 index 0000000000..9697cf3354 --- /dev/null +++ b/c/src/lib/libbsp/arm/xilinx-zynq/include/cadence-i2c.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_XILINX_ZYNQ_CADENCE_I2C_H +#define LIBBSP_ARM_XILINX_ZYNQ_CADENCE_I2C_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int i2c_bus_register_cadence( + const char *bus_path, + uintptr_t register_base, + uint32_t input_clock, + rtems_vector_number irq +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_ARM_XILINX_ZYNQ_CADENCE_I2C_H */ diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/include/i2c.h b/c/src/lib/libbsp/arm/xilinx-zynq/include/i2c.h new file mode 100644 index 0000000000..709ea0178e --- /dev/null +++ b/c/src/lib/libbsp/arm/xilinx-zynq/include/i2c.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_XILINX_ZYNQ_I2C_H +#define LIBBSP_ARM_XILINX_ZYNQ_I2C_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +static inline int zynq_register_i2c_0(void) +{ + return i2c_bus_register_cadence( + "/dev/i2c-0", + 0xe0004000, + zynq_clock_cpu_1x(), + ZYNQ_IRQ_I2C_0 + ); +} + +static inline int zynq_register_i2c_1(void) +{ + return i2c_bus_register_cadence( + "/dev/i2c-1", + 0xe0005000, + zynq_clock_cpu_1x(), + ZYNQ_IRQ_I2C_1 + ); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_ARM_XILINX_ZYNQ_I2C_H */ diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/preinstall.am b/c/src/lib/libbsp/arm/xilinx-zynq/preinstall.am index 980196df05..a75c344bc5 100644 --- a/c/src/lib/libbsp/arm/xilinx-zynq/preinstall.am +++ b/c/src/lib/libbsp/arm/xilinx-zynq/preinstall.am @@ -126,6 +126,18 @@ $(PROJECT_INCLUDE)/bsp/arm-release-id.h: ../shared/include/arm-release-id.h $(PR $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-release-id.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-release-id.h +$(PROJECT_INCLUDE)/bsp/cadence-i2c.h: include/cadence-i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/cadence-i2c.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/cadence-i2c.h + +$(PROJECT_INCLUDE)/bsp/cadence-i2c-regs.h: include/cadence-i2c-regs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/cadence-i2c-regs.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/cadence-i2c-regs.h + +$(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h + $(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h -- cgit v1.2.3