diff options
Diffstat (limited to 'c/src/lib/libcpu/m68k/mcf5206/mbus/mcfmbus.c')
-rw-r--r-- | c/src/lib/libcpu/m68k/mcf5206/mbus/mcfmbus.c | 860 |
1 files changed, 407 insertions, 453 deletions
diff --git a/c/src/lib/libcpu/m68k/mcf5206/mbus/mcfmbus.c b/c/src/lib/libcpu/m68k/mcf5206/mbus/mcfmbus.c index 1df8d95f5d..d9e70089f2 100644 --- a/c/src/lib/libcpu/m68k/mcf5206/mbus/mcfmbus.c +++ b/c/src/lib/libcpu/m68k/mcf5206/mbus/mcfmbus.c @@ -1,6 +1,8 @@ /* * MCF5206e MBUS module (I2C bus) driver - * + */ + +/* * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia * Author: Victor V. Vengerov <vvv@oktet.ru> * @@ -15,15 +17,15 @@ /* Events of I2C machine */ typedef enum i2c_event { - EVENT_NONE, /* Spurious event */ - EVENT_TRANSFER, /* Start new transfer */ - EVENT_NEXTMSG, /* Start processing of next message in transfer */ - EVENT_ACK, /* Sending finished with ACK */ - EVENT_NACK, /* Sending finished with NACK */ - EVENT_TIMEOUT, /* Timeout occured */ - EVENT_DATA_RECV, /* Data received */ - EVENT_ARB_LOST, /* Arbitration lost */ - EVENT_SLAVE /* Addressed as a slave */ + EVENT_NONE, /* Spurious event */ + EVENT_TRANSFER, /* Start new transfer */ + EVENT_NEXTMSG, /* Start processing of next message in transfer */ + EVENT_ACK, /* Sending finished with ACK */ + EVENT_NACK, /* Sending finished with NACK */ + EVENT_TIMEOUT, /* Timeout occured */ + EVENT_DATA_RECV, /* Data received */ + EVENT_ARB_LOST, /* Arbitration lost */ + EVENT_SLAVE /* Addressed as a slave */ } i2c_event; static mcfmbus *mbus; @@ -109,52 +111,42 @@ static mcfmbus *mbus; static i2c_event mcfmbus_get_event(mcfmbus *bus) { - i2c_event event; - uint8_t status, control; - rtems_interrupt_level level; - rtems_interrupt_disable(level); - status = *MCF5206E_MBSR(bus->base); - control = *MCF5206E_MBCR(bus->base); - if (status & MCF5206E_MBSR_MIF) /* Interrupt occured */ - { - if (status & MCF5206E_MBSR_MAAS) - { - event = EVENT_SLAVE; - *MCF5206E_MBCR(bus->base) = control; /* To clear Addressed As Slave - condition */ - } - else if (status & MCF5206E_MBSR_MAL) /* Arbitration lost */ - { - *MCF5206E_MBSR(bus->base) = status & ~MCF5206E_MBSR_MAL; - event = EVENT_ARB_LOST; - } - else if (control & MCF5206E_MBCR_MTX) /* Trasmit mode */ - { - if (status & MCF5206E_MBSR_RXAK) - event = EVENT_NACK; - else - event = EVENT_ACK; - } - else /* Received */ - { - event = EVENT_DATA_RECV; - } - - /* Clear interrupt condition */ - *MCF5206E_MBSR(bus->base) &= ~MCF5206E_MBSR_MIF; + i2c_event event; + uint8_t status, control; + rtems_interrupt_level level; + rtems_interrupt_disable(level); + status = *MCF5206E_MBSR(bus->base); + control = *MCF5206E_MBCR(bus->base); + + if (status & MCF5206E_MBSR_MIF) { /* Interrupt occured */ + if (status & MCF5206E_MBSR_MAAS) { + event = EVENT_SLAVE; + *MCF5206E_MBCR(bus->base) = control; /* To clear Addressed As Slave + condition */ + } else if (status & MCF5206E_MBSR_MAL) { /* Arbitration lost */ + *MCF5206E_MBSR(bus->base) = status & ~MCF5206E_MBSR_MAL; + event = EVENT_ARB_LOST; } - else - { - event = EVENT_NONE; + else if (control & MCF5206E_MBCR_MTX) { /* Trasmit mode */ + if (status & MCF5206E_MBSR_RXAK) + event = EVENT_NACK; + else + event = EVENT_ACK; + } else { /* Received */ + event = EVENT_DATA_RECV; } - rtems_interrupt_enable(level); - return event; + + /* Clear interrupt condition */ + *MCF5206E_MBSR(bus->base) &= ~MCF5206E_MBSR_MIF; + } else { + event = EVENT_NONE; + } + rtems_interrupt_enable(level); + return event; } -static void -mcfmbus_machine_error(mcfmbus *bus, i2c_event event) +static void mcfmbus_machine_error(mcfmbus *bus, i2c_event event) { - return; } /* mcfmbus_machine -- @@ -167,445 +159,407 @@ mcfmbus_machine_error(mcfmbus *bus, i2c_event event) * RETURNS: * none */ -static void -mcfmbus_machine(mcfmbus *bus, i2c_event event) +static void mcfmbus_machine(mcfmbus *bus, i2c_event event) { - uint8_t b; - switch (bus->state) - { - case STATE_IDLE: - switch (event) - { - case EVENT_NEXTMSG: /* Start new message processing */ - bus->cmsg++; - /* FALLTHRU */ - - case EVENT_TRANSFER: /* Initiate new transfer */ - if (bus->cmsg - bus->msg >= bus->nmsg) - { - mcfmbus_stop(bus); - next_state(bus, STATE_IDLE); - bus->msg = bus->cmsg = NULL; - bus->nmsg = bus->byte = 0; - bus->done(bus->done_arg_ptr); - break; - } - - /* Initiate START or REPEATED START condition on the bus */ - if (event == EVENT_TRANSFER) - { - mcfmbus_start(bus); - } - else /* (event == EVENT_NEXTMSG) */ - { - mcfmbus_rstart(bus); - } - - bus->byte = 0; - mcfmbus_tx_mode(bus); - - /* Initiate slave address sending */ - if (bus->cmsg->flags & I2C_MSG_ADDR_10) - { - i2c_address a = bus->cmsg->addr; - b = 0xf0 | (((a >> 8) & 0x03) << 1); - if (bus->cmsg->flags & I2C_MSG_WR) - { - mcfmbus_send(bus, b); - next_state(bus, STATE_ADDR_1_W); - } - else - { - mcfmbus_send(bus, b | 1); - next_state(bus, STATE_ADDR_1_R); - } - } - else - { - b = (bus->cmsg->addr & ~0x01); - - if (bus->cmsg->flags & I2C_MSG_WR) - { - next_state(bus, STATE_SENDING); - } - else - { - next_state(bus, STATE_ADDR_7); - b |= 1; - } - - mcfmbus_send(bus, b); - } - break; - - default: - mcfmbus_machine_error(bus, event); - break; - } + uint8_t b; + + switch (bus->state) { + case STATE_IDLE: + switch (event) { + case EVENT_NEXTMSG: /* Start new message processing */ + bus->cmsg++; + /* FALLTHRU */ + + case EVENT_TRANSFER: /* Initiate new transfer */ + if (bus->cmsg - bus->msg >= bus->nmsg) { + mcfmbus_stop(bus); + next_state(bus, STATE_IDLE); + bus->msg = bus->cmsg = NULL; + bus->nmsg = bus->byte = 0; + bus->done((void *)bus->done_arg_ptr); break; - - case STATE_ADDR_7: - switch (event) - { - case EVENT_ACK: - mcfmbus_rx_mode(bus); - if (bus->cmsg->len <= 1) - mcfmbus_send_nack(bus); - else - mcfmbus_send_ack(bus); - next_state(bus, STATE_RECEIVING); - break; - - case EVENT_NACK: - mcfmbus_error(bus, I2C_NO_DEVICE); - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - break; - - case EVENT_ARB_LOST: - mcfmbus_error(bus, I2C_ARBITRATION_LOST); - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - break; - - default: - mcfmbus_machine_error(bus, event); - break; + } + + /* Initiate START or REPEATED START condition on the bus */ + if (event == EVENT_TRANSFER) { + mcfmbus_start(bus); + } else { /* (event == EVENT_NEXTMSG) */ + mcfmbus_rstart(bus); + } + + bus->byte = 0; + mcfmbus_tx_mode(bus); + + /* Initiate slave address sending */ + if (bus->cmsg->flags & I2C_MSG_ADDR_10) { + i2c_address a = bus->cmsg->addr; + b = 0xf0 | (((a >> 8) & 0x03) << 1); + if (bus->cmsg->flags & I2C_MSG_WR) { + mcfmbus_send(bus, b); + next_state(bus, STATE_ADDR_1_W); + } else { + mcfmbus_send(bus, b | 1); + next_state(bus, STATE_ADDR_1_R); } - break; - - case STATE_ADDR_1_R: - case STATE_ADDR_1_W: - switch (event) - { - case EVENT_ACK: - { - uint8_t b = (bus->cmsg->addr & 0xff); - mcfmbus_send(bus, b); - if (bus->state == STATE_ADDR_1_W) - { - next_state(bus, STATE_SENDING); - } - else - { - i2c_address a; - mcfmbus_rstart(bus); - mcfmbus_tx_mode(bus); - a = bus->cmsg->addr; - b = 0xf0 | (((a >> 8) & 0x03) << 1) | 1; - mcfmbus_send(bus, b); - next_state(bus, STATE_ADDR_7); - } - break; - } - - case EVENT_NACK: - mcfmbus_error(bus, I2C_NO_DEVICE); - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - break; - - case EVENT_ARB_LOST: - mcfmbus_error(bus, I2C_ARBITRATION_LOST); - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - break; - - default: - mcfmbus_machine_error(bus, event); - break; + } else { + b = (bus->cmsg->addr & ~0x01); + + if (bus->cmsg->flags & I2C_MSG_WR) { + next_state(bus, STATE_SENDING); + } else { + next_state(bus, STATE_ADDR_7); + b |= 1; } - break; - case STATE_SENDING: - switch (event) - { - case EVENT_ACK: - if (bus->byte == bus->cmsg->len) - { - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - } - else - { - mcfmbus_send(bus, bus->cmsg->buf[bus->byte++]); - next_state(bus, STATE_SENDING); - } - break; - - case EVENT_NACK: - if (bus->byte == 0) - { - mcfmbus_error(bus, I2C_NO_DEVICE); - } - else - { - mcfmbus_error(bus, I2C_NO_ACKNOWLEDGE); - } - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - break; - - case EVENT_ARB_LOST: - mcfmbus_error(bus, I2C_ARBITRATION_LOST); - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - break; - - default: - mcfmbus_machine_error(bus, event); - break; + mcfmbus_send(bus, b); + } + break; - } + default: + mcfmbus_machine_error(bus, event); break; + } + break; + + case STATE_ADDR_7: + switch (event) { + case EVENT_ACK: + mcfmbus_rx_mode(bus); + if (bus->cmsg->len <= 1) + mcfmbus_send_nack(bus); + else + mcfmbus_send_ack(bus); + next_state(bus, STATE_RECEIVING); + break; + + case EVENT_NACK: + mcfmbus_error(bus, I2C_NO_DEVICE); + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + break; + + case EVENT_ARB_LOST: + mcfmbus_error(bus, I2C_ARBITRATION_LOST); + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + break; + + default: + mcfmbus_machine_error(bus, event); + break; + } + break; + + case STATE_ADDR_1_R: + case STATE_ADDR_1_W: + switch (event) { + case EVENT_ACK: { + uint8_t b = (bus->cmsg->addr & 0xff); + mcfmbus_send(bus, b); + if (bus->state == STATE_ADDR_1_W) { + next_state(bus, STATE_SENDING); + } else { + i2c_address a; + mcfmbus_rstart(bus); + mcfmbus_tx_mode(bus); + a = bus->cmsg->addr; + b = 0xf0 | (((a >> 8) & 0x03) << 1) | 1; + mcfmbus_send(bus, b); + next_state(bus, STATE_ADDR_7); + } + break; + } - case STATE_RECEIVING: - switch (event) - { - case EVENT_DATA_RECV: - if (bus->cmsg->len - bus->byte <= 2) - { - mcfmbus_send_nack(bus); - if (bus->cmsg->len - bus->byte <= 1) - { - if (bus->cmsg - bus->msg + 1 == bus->nmsg) - mcfmbus_stop(bus); - else - mcfmbus_rstart(bus); - } - } - else - { - mcfmbus_send_ack(bus); - } - bus->cmsg->buf[bus->byte++] = *MCF5206E_MBDR(bus->base); - if (bus->cmsg->len == bus->byte) - { - next_state(bus,STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - } - else - { - next_state(bus,STATE_RECEIVING); - } - break; - - case EVENT_ARB_LOST: - mcfmbus_error(bus, I2C_ARBITRATION_LOST); - next_state(bus, STATE_IDLE); - mcfmbus_machine(bus, EVENT_NEXTMSG); - break; - - default: - mcfmbus_machine_error(bus, event); - break; - } - break; + case EVENT_NACK: + mcfmbus_error(bus, I2C_NO_DEVICE); + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + break; + + case EVENT_ARB_LOST: + mcfmbus_error(bus, I2C_ARBITRATION_LOST); + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + break; + + default: + mcfmbus_machine_error(bus, event); + break; } + break; + + case STATE_SENDING: + switch (event) { + case EVENT_ACK: + if (bus->byte == bus->cmsg->len) { + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + } else { + mcfmbus_send(bus, bus->cmsg->buf[bus->byte++]); + next_state(bus, STATE_SENDING); + } + break; + + case EVENT_NACK: + if (bus->byte == 0) { + mcfmbus_error(bus, I2C_NO_DEVICE); + } else { + mcfmbus_error(bus, I2C_NO_ACKNOWLEDGE); + } + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + break; + + case EVENT_ARB_LOST: + mcfmbus_error(bus, I2C_ARBITRATION_LOST); + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + break; + + default: + mcfmbus_machine_error(bus, event); + break; + } + break; + + case STATE_RECEIVING: + switch (event) { + case EVENT_DATA_RECV: + if (bus->cmsg->len - bus->byte <= 2) { + mcfmbus_send_nack(bus); + if (bus->cmsg->len - bus->byte <= 1) { + if (bus->cmsg - bus->msg + 1 == bus->nmsg) + mcfmbus_stop(bus); + else + mcfmbus_rstart(bus); + } + } else { + mcfmbus_send_ack(bus); + } + bus->cmsg->buf[bus->byte++] = *MCF5206E_MBDR(bus->base); + if (bus->cmsg->len == bus->byte) { + next_state(bus,STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + } else { + next_state(bus,STATE_RECEIVING); + } + break; + + case EVENT_ARB_LOST: + mcfmbus_error(bus, I2C_ARBITRATION_LOST); + next_state(bus, STATE_IDLE); + mcfmbus_machine(bus, EVENT_NEXTMSG); + break; + + default: + mcfmbus_machine_error(bus, event); + break; + } + break; + } } /* mcfmbus_interrupt_handler -- - * MBUS module interrupt handler routine - * - * PARAMETERS: - * vector - interrupt vector number (not used) - * - * RETURNS: - * none - */ -rtems_isr -mcfmbus_interrupt_handler(rtems_vector_number vector) +* MBUS module interrupt handler routine +* +* PARAMETERS: +* vector - interrupt vector number (not used) +* +* RETURNS: +* none +*/ +static rtems_isr mcfmbus_interrupt_handler(rtems_vector_number vector) { - i2c_event event; - event = mcfmbus_get_event(mbus); - mcfmbus_machine(mbus, event); + i2c_event event; + event = mcfmbus_get_event(mbus); + mcfmbus_machine(mbus, event); } /* mcfmbus_poll -- - * MBUS module poll routine; used to poll events when I2C driver - * operates in poll-driven mode. - * - * PARAMETERS: - * none - * - * RETURNS: - * none - */ +* MBUS module poll routine; used to poll events when I2C driver +* operates in poll-driven mode. +* +* PARAMETERS: +* none +* +* RETURNS: +* none +*/ void mcfmbus_poll(mcfmbus *bus) { - i2c_event event; - event = mcfmbus_get_event(bus); - if (event != EVENT_NONE) - mcfmbus_machine(bus, event); + i2c_event event; + event = mcfmbus_get_event(bus); + if (event != EVENT_NONE) + mcfmbus_machine(bus, event); } /* mcfmbus_select_clock_divider -- - * Select divider for system clock which is used for I2C bus clock - * generation. Not each divider can be selected for I2C bus; this - * function select nearest larger or equal divider. - * - * PARAMETERS: - * i2c_bus - pointer to the bus descriptor structure - * divider - system frequency divider for I2C serial clock. - * RETURNS: - * RTEMS_SUCCESSFUL, if operation performed successfully, or - * RTEMS error code when failed. - */ +* Select divider for system clock which is used for I2C bus clock +* generation. Not each divider can be selected for I2C bus; this +* function select nearest larger or equal divider. +* +* PARAMETERS: +* i2c_bus - pointer to the bus descriptor structure +* divider - system frequency divider for I2C serial clock. +* RETURNS: +* RTEMS_SUCCESSFUL, if operation performed successfully, or +* RTEMS error code when failed. +*/ rtems_status_code mcfmbus_select_clock_divider(mcfmbus *i2c_bus, int divider) { - int i; - int mbc; - struct { - int divider; - int mbc; - } dividers[] ={ - { 20, 0x20 }, { 22, 0x21 }, { 24, 0x22 }, { 26, 0x23 }, - { 28, 0x00 }, { 30, 0x01 }, { 32, 0x25 }, { 34, 0x02 }, - { 36, 0x26 }, { 40, 0x03 }, { 44, 0x04 }, { 48, 0x05 }, - { 56, 0x06 }, { 64, 0x2a }, { 68, 0x07 }, { 72, 0x2B }, - { 80, 0x08 }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, - { 112, 0x2E }, { 128, 0x0B }, { 144, 0x0C }, { 160, 0x0D }, - { 192, 0x0E }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, - { 288, 0x10 }, { 320, 0x11 }, { 384, 0x12 }, { 448, 0x36 }, - { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x15 }, - { 768, 0x16 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, - { 1152, 0x18 }, { 1280, 0x19 }, { 1536, 0x1A }, { 1792, 0x3E }, - { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, - { 3072, 0x1E }, { 3840, 0x1F } - }; - - if (i2c_bus == NULL) - return RTEMS_INVALID_ADDRESS; - - for (i = 0, mbc = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++) - { - mbc = dividers[i].mbc; - if (dividers[i].divider >= divider) - { - break; - } + int i; + int mbc; + struct { + int divider; + int mbc; + } dividers[] ={ + { 20, 0x20 }, { 22, 0x21 }, { 24, 0x22 }, { 26, 0x23 }, + { 28, 0x00 }, { 30, 0x01 }, { 32, 0x25 }, { 34, 0x02 }, + { 36, 0x26 }, { 40, 0x03 }, { 44, 0x04 }, { 48, 0x05 }, + { 56, 0x06 }, { 64, 0x2a }, { 68, 0x07 }, { 72, 0x2B }, + { 80, 0x08 }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, + { 112, 0x2E }, { 128, 0x0B }, { 144, 0x0C }, { 160, 0x0D }, + { 192, 0x0E }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, + { 288, 0x10 }, { 320, 0x11 }, { 384, 0x12 }, { 448, 0x36 }, + { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x15 }, + { 768, 0x16 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, + { 1152, 0x18 }, { 1280, 0x19 }, { 1536, 0x1A }, { 1792, 0x3E }, + { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, + { 3072, 0x1E }, { 3840, 0x1F } + }; + + if (i2c_bus == NULL) + return RTEMS_INVALID_ADDRESS; + + for (i = 0, mbc = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++) { + mbc = dividers[i].mbc; + if (dividers[i].divider >= divider) { + break; } - *MCF5206E_MFDR(i2c_bus->base) = mbc; - return RTEMS_SUCCESSFUL; + } + *MCF5206E_MFDR(i2c_bus->base) = mbc; + return RTEMS_SUCCESSFUL; } /* mcfmbus_initialize -- - * Initialize ColdFire MBUS I2C bus controller. - * - * PARAMETERS: - * i2c_bus - pointer to the bus descriptor structure - * base - ColdFire internal peripherial base address - * - * RETURNS: - * RTEMS_SUCCESSFUL, or RTEMS error code when initialization failed. - */ -rtems_status_code -mcfmbus_initialize(mcfmbus *i2c_bus, uint32_t base) +* Initialize ColdFire MBUS I2C bus controller. +* +* PARAMETERS: +* i2c_bus - pointer to the bus descriptor structure +* base - ColdFire internal peripherial base address +* +* RETURNS: +* RTEMS_SUCCESSFUL, or RTEMS error code when initialization failed. +*/ +rtems_status_code mcfmbus_initialize(mcfmbus *i2c_bus, uint32_t base) { - rtems_interrupt_level level; - rtems_status_code sc; - - if (mbus != NULL) /* Check if already initialized */ - return RTEMS_RESOURCE_IN_USE; - - if (i2c_bus == NULL) - return RTEMS_INVALID_ADDRESS; - - - i2c_bus->base = base; - i2c_bus->state = STATE_IDLE; - i2c_bus->msg = NULL; - i2c_bus->cmsg = NULL; - i2c_bus->nmsg = 0; - i2c_bus->byte = 0; - - sc = rtems_interrupt_catch( - mcfmbus_interrupt_handler, - 24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >> - MCF5206E_ICR_IL_S), - &i2c_bus->oldisr - ); - if (sc != RTEMS_SUCCESSFUL) - return sc; - - mbus = i2c_bus; - rtems_interrupt_disable(level); - *MCF5206E_IMR(base) &= ~MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS); - *MCF5206E_MBCR(base) = 0; - *MCF5206E_MBSR(base) = 0; - *MCF5206E_MBDR(base) = 0x1F; /* Maximum possible divider is 3840 */ - *MCF5206E_MBCR(base) = MCF5206E_MBCR_MEN | MCF5206E_MBCR_MIEN; - rtems_interrupt_enable(level); - - return RTEMS_SUCCESSFUL; + rtems_interrupt_level level; + rtems_status_code sc; + + if (mbus != NULL) /* Check if already initialized */ + return RTEMS_RESOURCE_IN_USE; + + if (i2c_bus == NULL) + return RTEMS_INVALID_ADDRESS; + + + i2c_bus->base = base; + i2c_bus->state = STATE_IDLE; + i2c_bus->msg = NULL; + i2c_bus->cmsg = NULL; + i2c_bus->nmsg = 0; + i2c_bus->byte = 0; + + sc = rtems_interrupt_catch( + mcfmbus_interrupt_handler, + 24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >> + MCF5206E_ICR_IL_S), + &i2c_bus->oldisr + ); + if (sc != RTEMS_SUCCESSFUL) + return sc; + + mbus = i2c_bus; + rtems_interrupt_disable(level); + *MCF5206E_IMR(base) &= ~MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS); + *MCF5206E_MBCR(base) = 0; + *MCF5206E_MBSR(base) = 0; + *MCF5206E_MBDR(base) = 0x1F; /* Maximum possible divider is 3840 */ + *MCF5206E_MBCR(base) = MCF5206E_MBCR_MEN | MCF5206E_MBCR_MIEN; + rtems_interrupt_enable(level); + + return RTEMS_SUCCESSFUL; } /* mcfmbus_i2c_transfer -- - * Initiate multiple-messages transfer over I2C bus via ColdFire MBUS - * controller. - * - * PARAMETERS: - * bus - pointer to MBUS controller descriptor - * nmsg - number of messages - * msg - pointer to messages array - * done - function which is called when transfer is finished - * done_arg_ptr - arbitrary argument ptr passed to done funciton - * - * RETURNS: - * RTEMS_SUCCESSFUL if transfer initiated successfully, or error - * code when failed. - */ -rtems_status_code -mcfmbus_i2c_transfer(mcfmbus *bus, int nmsg, i2c_message *msg, - i2c_transfer_done done, void *done_arg_ptr) +* Initiate multiple-messages transfer over I2C bus via ColdFire MBUS +* controller. +* +* PARAMETERS: +* bus - pointer to MBUS controller descriptor +* nmsg - number of messages +* msg - pointer to messages array +* done - function which is called when transfer is finished +* done_arg_ptr - arbitrary argument ptr passed to done funciton +* +* RETURNS: +* RTEMS_SUCCESSFUL if transfer initiated successfully, or error +* code when failed. +*/ +rtems_status_code mcfmbus_i2c_transfer( + mcfmbus *bus, + int nmsg, + i2c_message *msg, + i2c_transfer_done done, + void *done_arg_ptr +) { - if (bus != mbus) - return RTEMS_NOT_CONFIGURED; - - bus->done = done; - bus->done_arg_ptr = done_arg_ptr; - bus->cmsg = bus->msg = msg; - bus->nmsg = nmsg; - bus->byte = 0; - bus->state = STATE_IDLE; - mcfmbus_machine(bus, EVENT_TRANSFER); - return RTEMS_SUCCESSFUL; + if (bus != mbus) + return RTEMS_NOT_CONFIGURED; + + bus->done = done; + bus->done_arg_ptr = (uintptr_t) done_arg_ptr; + bus->cmsg = bus->msg = msg; + bus->nmsg = nmsg; + bus->byte = 0; + bus->state = STATE_IDLE; + mcfmbus_machine(bus, EVENT_TRANSFER); + return RTEMS_SUCCESSFUL; } /* mcfmbus_i2c_done -- - * Close ColdFire MBUS I2C bus controller and release all resources. - * - * PARAMETERS: - * bus - pointer to MBUS controller descriptor - * - * RETURNS: - * RTEMS_SUCCESSFUL, if transfer initiated successfully, or error - * code when failed. - */ -rtems_status_code -mcfmbus_i2c_done(mcfmbus *i2c_bus) +* Close ColdFire MBUS I2C bus controller and release all resources. +* +* PARAMETERS: +* bus - pointer to MBUS controller descriptor +* +* RETURNS: +* RTEMS_SUCCESSFUL, if transfer initiated successfully, or error +* code when failed. +*/ +rtems_status_code mcfmbus_i2c_done(mcfmbus *i2c_bus) { - rtems_status_code sc; - uint32_t base; - if (mbus == NULL) - return RTEMS_NOT_CONFIGURED; - - if (mbus != i2c_bus) - return RTEMS_INVALID_ADDRESS; - - base = i2c_bus->base; - - *MCF5206E_IMR(base) |= MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS); - *MCF5206E_MBCR(base) = 0; - - sc = rtems_interrupt_catch( - i2c_bus->oldisr, - 24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >> - MCF5206E_ICR_IL_S), - NULL - ); - return sc; + rtems_status_code sc; + uint32_t base; + if (mbus == NULL) + return RTEMS_NOT_CONFIGURED; + + if (mbus != i2c_bus) + return RTEMS_INVALID_ADDRESS; + + base = i2c_bus->base; + + *MCF5206E_IMR(base) |= MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS); + *MCF5206E_MBCR(base) = 0; + + sc = rtems_interrupt_catch( + i2c_bus->oldisr, + 24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >> + MCF5206E_ICR_IL_S), + NULL + ); + return sc; } |