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