File indexing completed on 2025-05-11 08:23:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <rtems.h>
0017 #include <bsp.h>
0018 #include <stdlib.h>
0019 #include <string.h>
0020
0021 #include "i2c.h"
0022 #include "i2cdrv.h"
0023 #include "mcf5206/mcfmbus.h"
0024
0025 #ifndef I2C_NUMBER_OF_BUSES
0026 #define I2C_NUMBER_OF_BUSES (1)
0027 #endif
0028
0029 #ifndef I2C_SELECT_BUS
0030 #define I2C_SELECT_BUS(bus)
0031 #endif
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 typedef struct i2c_qel {
0046 i2c_bus_number bus;
0047 i2c_message *msg;
0048 int nmsg;
0049 i2c_transfer_done done;
0050 void * done_arg_ptr;
0051 } i2c_qel;
0052
0053
0054 static i2c_qel *tqueue;
0055
0056
0057 static int tqueue_size;
0058
0059
0060 static volatile int tqueue_head;
0061
0062
0063 static volatile int tqueue_tail;
0064
0065
0066 static volatile bool mbus_busy;
0067
0068
0069 static mcfmbus mbus;
0070
0071
0072 static int i2cdrv_bus_clock_div[I2C_NUMBER_OF_BUSES];
0073
0074
0075 static int i2cdrv_bus_clock_div_current;
0076
0077
0078 static void i2cdrv_unload(void);
0079
0080
0081
0082
0083
0084 static void
0085 i2cdrv_done(void * arg_ptr)
0086 {
0087 rtems_interrupt_level level;
0088 i2c_qel *qel = tqueue + tqueue_tail;
0089 qel->done(qel->done_arg_ptr);
0090 rtems_interrupt_disable(level);
0091 tqueue_tail = (tqueue_tail + 1) % tqueue_size;
0092 mbus_busy = false;
0093 rtems_interrupt_enable(level);
0094 i2cdrv_unload();
0095 }
0096
0097
0098
0099
0100
0101 static void
0102 i2cdrv_unload(void)
0103 {
0104 rtems_interrupt_level level;
0105 i2c_qel *qel;
0106 rtems_status_code sc;
0107 rtems_interrupt_disable(level);
0108 if (!mbus_busy && (tqueue_head != tqueue_tail))
0109 {
0110 mbus_busy = true;
0111 rtems_interrupt_enable(level);
0112 qel = tqueue + tqueue_tail;
0113
0114 I2C_SELECT_BUS(qel->bus);
0115 if (i2cdrv_bus_clock_div[qel->bus] != i2cdrv_bus_clock_div_current)
0116 {
0117 i2cdrv_bus_clock_div_current = i2cdrv_bus_clock_div[qel->bus];
0118 mcfmbus_select_clock_divider(&mbus, i2cdrv_bus_clock_div_current);
0119 }
0120 sc = mcfmbus_i2c_transfer(&mbus, qel->nmsg, qel->msg,
0121 i2cdrv_done,qel);
0122 if (sc != RTEMS_SUCCESSFUL)
0123 {
0124 int i;
0125 for (i = 0; i < qel->nmsg; i++)
0126 {
0127 qel->msg[i].status = I2C_RESOURCE_NOT_AVAILABLE;
0128 }
0129 i2cdrv_done(qel);
0130 }
0131 }
0132 else
0133 {
0134 rtems_interrupt_enable(level);
0135 }
0136 }
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 rtems_status_code
0155 i2c_transfer(i2c_bus_number bus, int nmsg, i2c_message *msg,
0156 i2c_transfer_done done, void * done_arg_ptr)
0157 {
0158 i2c_qel qel;
0159 rtems_interrupt_level level;
0160
0161 if (bus >= I2C_NUMBER_OF_BUSES)
0162 {
0163 return RTEMS_INVALID_NUMBER;
0164 }
0165
0166 if (msg == NULL)
0167 {
0168 return RTEMS_INVALID_ADDRESS;
0169 }
0170
0171 qel.bus = bus;
0172 qel.msg = msg;
0173 qel.nmsg = nmsg;
0174 qel.done = done;
0175 qel.done_arg_ptr = done_arg_ptr;
0176 rtems_interrupt_disable(level);
0177 if ((tqueue_head + 1) % tqueue_size == tqueue_tail)
0178 {
0179 rtems_interrupt_enable(level);
0180 return RTEMS_TOO_MANY;
0181 }
0182 memcpy(tqueue + tqueue_head, &qel, sizeof(qel));
0183 tqueue_head = (tqueue_head + 1) % tqueue_size;
0184 rtems_interrupt_enable(level);
0185 i2cdrv_unload();
0186 return RTEMS_SUCCESSFUL;
0187 }
0188
0189
0190
0191
0192 rtems_device_driver
0193 i2cdrv_initialize(rtems_device_major_number major,
0194 rtems_device_minor_number minor,
0195 void *arg)
0196 {
0197 int i;
0198 rtems_status_code sc;
0199 mbus_busy = false;
0200 tqueue_tail = tqueue_head = 0;
0201 tqueue_size = 32;
0202 tqueue = calloc(tqueue_size, sizeof(i2c_qel));
0203
0204 sc = mcfmbus_initialize(&mbus, MBAR);
0205 if (sc != RTEMS_SUCCESSFUL)
0206 return sc;
0207
0208 for (i = 0; i < I2C_NUMBER_OF_BUSES; i++)
0209 {
0210 sc = i2c_select_clock_rate(i, 4096);
0211 if (sc != RTEMS_SUCCESSFUL)
0212 return sc;
0213 }
0214 i2cdrv_bus_clock_div_current = -1;
0215 return RTEMS_SUCCESSFUL;
0216 }
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 rtems_status_code
0234 i2c_select_clock_rate(i2c_bus_number bus, int bps)
0235 {
0236 int div;
0237 if (bus >= I2C_NUMBER_OF_BUSES)
0238 return RTEMS_INVALID_NUMBER;
0239
0240 if (bps == 0)
0241 return RTEMS_UNSATISFIED;
0242
0243 div = BSP_SYSTEM_FREQUENCY / bps;
0244 i2cdrv_bus_clock_div[bus] = div;
0245 return RTEMS_SUCCESSFUL;
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258 void
0259 i2c_poll(i2c_bus_number bus)
0260 {
0261 mcfmbus_poll(&mbus);
0262 }