diff options
Diffstat (limited to 'firmware/target/arm/imx31/i2c-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/i2c-imx31.c | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/firmware/target/arm/imx31/i2c-imx31.c b/firmware/target/arm/imx31/i2c-imx31.c index 1ffdce38ea..4e810c588f 100644 --- a/firmware/target/arm/imx31/i2c-imx31.c +++ b/firmware/target/arm/imx31/i2c-imx31.c | |||
@@ -37,25 +37,31 @@ static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void); | |||
37 | static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void); | 37 | static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void); |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #define IADR (0x00 / sizeof (unsigned short)) /* 00h */ | ||
41 | #define IFDR (0x04 / sizeof (unsigned short)) /* 04h */ | ||
42 | #define I2CR (0x08 / sizeof (unsigned short)) /* 08h */ | ||
43 | #define I2SR (0x0c / sizeof (unsigned short)) /* 0ch */ | ||
44 | #define I2DR (0x10 / sizeof (unsigned short)) /* 10h */ | ||
45 | |||
40 | static struct i2c_module_descriptor | 46 | static struct i2c_module_descriptor |
41 | { | 47 | { |
42 | struct i2c_map *base; /* Module base address */ | 48 | volatile unsigned short * const base; /* Module base address */ |
43 | enum IMX31_CG_LIST cg; /* Clock gating index */ | 49 | void (* const handler)(void); /* Module interrupt handler */ |
44 | enum IMX31_INT_LIST ints; /* Module interrupt number */ | 50 | struct mutex m; /* Node mutual-exclusion */ |
45 | int enable; /* Enable count */ | 51 | struct wakeup w; /* I2C done signal */ |
46 | void (*handler)(void); /* Module interrupt handler */ | 52 | unsigned char *addr_data; /* Additional addressing data */ |
47 | struct mutex m; /* Node mutual-exclusion */ | 53 | int addr_count; /* Addressing byte count */ |
48 | struct wakeup w; /* I2C done signal */ | 54 | unsigned char *data; /* TX/RX buffer (actual data) */ |
49 | unsigned char *addr_data; /* Additional addressing data */ | 55 | int data_count; /* TX/RX byte count */ |
50 | int addr_count; /* Addressing byte count */ | 56 | unsigned char addr; /* Address + r/w bit */ |
51 | unsigned char *data; /* TX/RX buffer (actual data) */ | 57 | uint8_t enable; /* Enable count */ |
52 | int data_count; /* TX/RX byte count */ | 58 | const uint8_t cg; /* Clock gating index */ |
53 | unsigned char addr; /* Address + r/w bit */ | 59 | const uint8_t ints; /* Module interrupt number */ |
54 | } i2c_descs[I2C_NUM_I2C] = | 60 | } i2c_descs[I2C_NUM_I2C] = |
55 | { | 61 | { |
56 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) | 62 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) |
57 | { | 63 | { |
58 | .base = (struct i2c_map *)I2C1_BASE_ADDR, | 64 | .base = (unsigned short *)I2C1_BASE_ADDR, |
59 | .cg = CG_I2C1, | 65 | .cg = CG_I2C1, |
60 | .ints = INT_I2C1, | 66 | .ints = INT_I2C1, |
61 | .handler = I2C1_HANDLER, | 67 | .handler = I2C1_HANDLER, |
@@ -63,7 +69,7 @@ static struct i2c_module_descriptor | |||
63 | #endif | 69 | #endif |
64 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | 70 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) |
65 | { | 71 | { |
66 | .base = (struct i2c_map *)I2C2_BASE_ADDR, | 72 | .base = (unsigned short *)I2C2_BASE_ADDR, |
67 | .cg = CG_I2C2, | 73 | .cg = CG_I2C2, |
68 | .ints = INT_I2C2, | 74 | .ints = INT_I2C2, |
69 | .handler = I2C2_HANDLER, | 75 | .handler = I2C2_HANDLER, |
@@ -71,7 +77,7 @@ static struct i2c_module_descriptor | |||
71 | #endif | 77 | #endif |
72 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | 78 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) |
73 | { | 79 | { |
74 | .base = (struct i2c_map *)I2C3_BASE_ADDR, | 80 | .base = (unsigned short *)I2C3_BASE_ADDR, |
75 | .cg = CG_I2C3, | 81 | .cg = CG_I2C3, |
76 | .ints = INT_I2C3, | 82 | .ints = INT_I2C3, |
77 | .handler = I2C3_HANDLER, | 83 | .handler = I2C3_HANDLER, |
@@ -81,11 +87,11 @@ static struct i2c_module_descriptor | |||
81 | 87 | ||
82 | static void i2c_interrupt(enum i2c_module_number i2c) | 88 | static void i2c_interrupt(enum i2c_module_number i2c) |
83 | { | 89 | { |
84 | struct i2c_module_descriptor *const desc = &i2c_descs[i2c]; | 90 | struct i2c_module_descriptor * const desc = &i2c_descs[i2c]; |
85 | struct i2c_map * const base = desc->base; | 91 | volatile unsigned short * const base = desc->base; |
86 | uint16_t i2sr = base->i2sr; | 92 | unsigned short i2sr = base[I2SR]; |
87 | 93 | ||
88 | base->i2sr = 0; /* Clear IIF */ | 94 | base[I2SR] = 0; /* Clear IIF */ |
89 | 95 | ||
90 | if (desc->addr_count >= 0) | 96 | if (desc->addr_count >= 0) |
91 | { | 97 | { |
@@ -100,8 +106,8 @@ static void i2c_interrupt(enum i2c_module_number i2c) | |||
100 | /* Switching to data cycle */ | 106 | /* Switching to data cycle */ |
101 | if (desc->addr & 0x1) | 107 | if (desc->addr & 0x1) |
102 | { | 108 | { |
103 | base->i2cr &= ~I2C_I2CR_MTX; /* Switch to RX mode */ | 109 | base[I2CR] &= ~I2C_I2CR_MTX; /* Switch to RX mode */ |
104 | base->i2dr; /* Dummy read */ | 110 | base[I2DR]; /* Dummy read */ |
105 | return; | 111 | return; |
106 | } | 112 | } |
107 | /* else remaining data is TX - handle below */ | 113 | /* else remaining data is TX - handle below */ |
@@ -109,12 +115,12 @@ static void i2c_interrupt(enum i2c_module_number i2c) | |||
109 | } | 115 | } |
110 | else | 116 | else |
111 | { | 117 | { |
112 | base->i2dr = *desc->addr_data++; /* Send next addressing byte */ | 118 | base[I2DR] = *desc->addr_data++; /* Send next addressing byte */ |
113 | return; | 119 | return; |
114 | } | 120 | } |
115 | } | 121 | } |
116 | 122 | ||
117 | if (base->i2cr & I2C_I2CR_MTX) | 123 | if (base[I2CR] & I2C_I2CR_MTX) |
118 | { | 124 | { |
119 | /* Transmitting data */ | 125 | /* Transmitting data */ |
120 | if ((i2sr & I2C_I2SR_RXAK) == 0) | 126 | if ((i2sr & I2C_I2SR_RXAK) == 0) |
@@ -123,7 +129,7 @@ i2c_transmit: | |||
123 | if (desc->data_count > 0) | 129 | if (desc->data_count > 0) |
124 | { | 130 | { |
125 | /* More bytes to send, got ACK from previous byte */ | 131 | /* More bytes to send, got ACK from previous byte */ |
126 | base->i2dr = *desc->data++; | 132 | base[I2DR] = *desc->data++; |
127 | desc->data_count--; | 133 | desc->data_count--; |
128 | return; | 134 | return; |
129 | } | 135 | } |
@@ -138,24 +144,24 @@ i2c_transmit: | |||
138 | if (desc->data_count == 1) | 144 | if (desc->data_count == 1) |
139 | { | 145 | { |
140 | /* 2nd to Last byte - NACK */ | 146 | /* 2nd to Last byte - NACK */ |
141 | base->i2cr |= I2C_I2CR_TXAK; | 147 | base[I2CR] |= I2C_I2CR_TXAK; |
142 | } | 148 | } |
143 | 149 | ||
144 | *desc->data++ = base->i2dr; /* Read data from I2DR and store */ | 150 | *desc->data++ = base[I2DR]; /* Read data from I2DR and store */ |
145 | return; | 151 | return; |
146 | } | 152 | } |
147 | else | 153 | else |
148 | { | 154 | { |
149 | /* Generate STOP signal before reading data */ | 155 | /* Generate STOP signal before reading data */ |
150 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | 156 | base[I2CR] &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); |
151 | *desc->data++ = base->i2dr; /* Read data from I2DR and store */ | 157 | *desc->data++ = base[I2DR]; /* Read data from I2DR and store */ |
152 | goto i2c_done; | 158 | goto i2c_done; |
153 | } | 159 | } |
154 | } | 160 | } |
155 | 161 | ||
156 | i2c_stop: | 162 | i2c_stop: |
157 | /* Generate STOP signal */ | 163 | /* Generate STOP signal */ |
158 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | 164 | base[I2CR] &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); |
159 | i2c_done: | 165 | i2c_done: |
160 | /* Signal thread we're done */ | 166 | /* Signal thread we're done */ |
161 | wakeup_signal(&desc->w); | 167 | wakeup_signal(&desc->w); |
@@ -183,18 +189,18 @@ static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void) | |||
183 | static int i2c_transfer(struct i2c_node * const node, | 189 | static int i2c_transfer(struct i2c_node * const node, |
184 | struct i2c_module_descriptor *const desc) | 190 | struct i2c_module_descriptor *const desc) |
185 | { | 191 | { |
186 | struct i2c_map * const base = desc->base; | 192 | volatile unsigned short * const base = desc->base; |
187 | int count = desc->data_count; | 193 | int count = desc->data_count; |
188 | uint16_t i2cr; | 194 | uint16_t i2cr; |
189 | 195 | ||
190 | /* Make sure bus is idle. */ | 196 | /* Make sure bus is idle. */ |
191 | while (base->i2sr & I2C_I2SR_IBB); | 197 | while (base[I2SR] & I2C_I2SR_IBB); |
192 | 198 | ||
193 | /* Set speed */ | 199 | /* Set speed */ |
194 | base->ifdr = node->ifdr; | 200 | base[IFDR] = node->ifdr; |
195 | 201 | ||
196 | /* Enable module */ | 202 | /* Enable module */ |
197 | base->i2cr = I2C_I2CR_IEN; | 203 | base[I2CR] = I2C_I2CR_IEN; |
198 | 204 | ||
199 | /* Enable Interrupt, Master */ | 205 | /* Enable Interrupt, Master */ |
200 | i2cr = I2C_I2CR_IEN | I2C_I2CR_IIEN | I2C_I2CR_MTX; | 206 | i2cr = I2C_I2CR_IEN | I2C_I2CR_IIEN | I2C_I2CR_MTX; |
@@ -206,13 +212,13 @@ static int i2c_transfer(struct i2c_node * const node, | |||
206 | } | 212 | } |
207 | 213 | ||
208 | /* Set config */ | 214 | /* Set config */ |
209 | base->i2cr = i2cr; | 215 | base[I2CR] = i2cr; |
210 | 216 | ||
211 | /* Generate START */ | 217 | /* Generate START */ |
212 | base->i2cr = i2cr | I2C_I2CR_MSTA; | 218 | base[I2CR] = i2cr | I2C_I2CR_MSTA; |
213 | 219 | ||
214 | /* Address slave (first byte sent) and begin session. */ | 220 | /* Address slave (first byte sent) and begin session. */ |
215 | base->i2dr = desc->addr; | 221 | base[I2DR] = desc->addr; |
216 | 222 | ||
217 | /* Wait for transfer to complete */ | 223 | /* Wait for transfer to complete */ |
218 | if (wakeup_wait(&desc->w, HZ) == OBJ_WAIT_SUCCEEDED) | 224 | if (wakeup_wait(&desc->w, HZ) == OBJ_WAIT_SUCCEEDED) |
@@ -222,7 +228,7 @@ static int i2c_transfer(struct i2c_node * const node, | |||
222 | else | 228 | else |
223 | { | 229 | { |
224 | /* Generate STOP if timeout */ | 230 | /* Generate STOP if timeout */ |
225 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | 231 | base[I2CR] &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); |
226 | count = -1; | 232 | count = -1; |
227 | } | 233 | } |
228 | 234 | ||
@@ -289,7 +295,7 @@ void i2c_init(void) | |||
289 | ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT); | 295 | ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT); |
290 | mutex_init(&desc->m); | 296 | mutex_init(&desc->m); |
291 | wakeup_init(&desc->w); | 297 | wakeup_init(&desc->w); |
292 | desc->base->i2cr = 0; | 298 | desc->base[I2CR] = 0; |
293 | ccm_module_clock_gating(desc->cg, CGM_OFF); | 299 | ccm_module_clock_gating(desc->cg, CGM_OFF); |
294 | } | 300 | } |
295 | } | 301 | } |
@@ -315,8 +321,8 @@ void i2c_enable_node(struct i2c_node *node, bool enable) | |||
315 | if (desc->enable > 0 && --desc->enable == 0) | 321 | if (desc->enable > 0 && --desc->enable == 0) |
316 | { | 322 | { |
317 | /* Last enable */ | 323 | /* Last enable */ |
318 | while (desc->base->i2sr & I2C_I2SR_IBB); /* Wait for STOP */ | 324 | while (desc->base[I2SR] & I2C_I2SR_IBB); /* Wait for STOP */ |
319 | desc->base->i2cr &= ~I2C_I2CR_IEN; | 325 | desc->base[I2CR] &= ~I2C_I2CR_IEN; |
320 | avic_disable_int(desc->ints); | 326 | avic_disable_int(desc->ints); |
321 | ccm_module_clock_gating(desc->cg, CGM_OFF); | 327 | ccm_module_clock_gating(desc->cg, CGM_OFF); |
322 | } | 328 | } |