1 /*
2 * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stddef.h>
7 #include <stdint.h>
8
9 #include <device_mec5.h>
10 #include "mec_pcfg.h"
11 #include "mec_defs.h"
12 #include "mec_ecia_api.h"
13 #include "mec_i2c_api.h"
14 #include "mec_pcr_api.h"
15 #include "mec_retval.h"
16
17 /* MEC5 I2C controller notes:
18 * The I2C byte mode Control(WO) and Status(RO) register are both located at offset 0.
19 * I2C.STATUS register is an 8-bit read-only status register:
20 * bit[0] = Not Bus Busy(NBB) 0 indicates the bus is owned by this controller.
21 * bit[1] = Lost Arbitration(LAB) 1 indicates controller lost arbitration to another
22 * controller on the bus. LAB detection is performed during data transfer,
23 * ackowledgement, START, and Repeated-START phases of the transfer. LAB
24 * is not checked during a STOP phase. If LAB occurs this controller will tri-state
25 * its pins and continue to clock in the address/data from the external controller.
26 * On the 9th clock NIPEND and LAB will both assert.
27 * I2C-NL CM FSM will transition to IDLE state after 9th clock (n)ACK bit and
28 * clear the PIN bit to 1(de-asserted).
29 * bit[2] = AAS = 1 indicates an external Controller issued (RPT)-START + target address
30 * the target address matches one of the two target addresses in this controller's
31 * own address register or the I2C generate call address(0x00). NOTE: general
32 * call address detction can be enabled/disabled in the Configuration register.
33 * bit[3] = LRB_AD0 value interpretation depends upon the AAS status bit.
34 * AAS==0: LRB is the last received bit on the bus. Usually this is the value
35 * of SDA on the 9th I2C clock (0=ACK, 1=NACK).
36 * AAS==1: AD0=1 if received target address was the I2C GC(0x00) address else
37 * 0 if the target address matched one of the controller's own addresses.
38 * bit[4] = BER 1 = Controller detected a bus error. Assertion of BER cause the controller
39 * to de-assert NBB and NPIPEND: NBB=1 and NIPEND=1.
40 * bit[5] = STS 1 = externally generated STOP was detected. BROKEN in MEC520x. A HW fix
41 * implemented in MEC540x.
42 * bit[6] = SAD 1 = SMBus address decode asserted if enabled in the Configuration register.
43 * bit[7] = NIPEND 1 = No Interrupt Pending(de-asserted). 1 = Interrupt is Pending(asserted).
44 * NIPEND is asserted(0) after the 9th I2C clock or on detection of a bus error.
45 * TX direction: NIPEND de-asserted when I2C.Data register is written.
46 * RX direction: NIPEND de-asserted when I2C.Data is read.
47 * NOTE: In Controller Mode reading I2C.Data when direction is RX and I2C.CTRL.STO=0
48 * returns current data byte and generates clocks for the next byte (read-ahead).
49 * HW determines direction based on the W/nR bit which is bit[0] of the I2C target
50 * address.
51 *
52 * I2C.CTRL register is an 8-bit write-only control register:
53 * bit[0] = ACK = 1 HW will generate an ACK on the 9th after receiving a
54 * data byte from an external Controller.
55 * bit[1] = STO = 1 generate a STOP
56 * bit[2] = STA = 1 generate a START and transmit the address in the I2C.DATA register.
57 * bit[3] = ENI = 1 Assert the I2C controller's interrupt active signal to the corresponding
58 * GIRQ Source bit. Interrupt signal asserted when I2C.STATUS.NIPEND -> 0.
59 * bits[5:4] = reserved
60 * bit[6] = ESO = 1 Enable SDA outout. 0 = SDA disabled.
61 * bit[7] = NIPEND_RST = Not Pending Interrupt. A software reset de-asserting all status
62 * except the Not Bus Busy status bit. WARNING: Behaviour of this bit
63 * depends upon the I2C FSM state.
64 *
65 * Controller clears I2C.CTRL.STA write-only bit after 7th clock of I2C address.
66 * Controller clears I2C.CTRL.STO write-only bit when it drives SDA low at
67 * the beginning of generating the STOP sequence on the bus. This occurs
68 * a minimum 1/2 I2C clock period after the 9th clock pulse of the previous
69 * data on the bus.
70 */
71 #define MEC_I2C_SMB_COMPL_STS_RW1C_MSK 0xe1397f00u
72 #define MEC_I2C_SMB_COMPL_STS_RO_MSK 0x02020040u
73 #define MEC_I2C_SMB_COMPL_EN_RW_MSK 0x3cu
74 #define MEC_I2C_SMB_COMPL_TM_STS_RW1C_MSK 0x80390000u
75 #define MEC_I2C_SMB_COMPL_TM_STS_ALL_MSK 0x803b0000u
76
77 #define MEC_I2C_SMB0_ECIA_INFO MEC5_ECIA_INFO(13, 0, 5, 20)
78 #define MEC_I2C_SMB1_ECIA_INFO MEC5_ECIA_INFO(13, 1, 5, 21)
79 #define MEC_I2C_SMB2_ECIA_INFO MEC5_ECIA_INFO(13, 2, 5, 22)
80 #define MEC_I2C_SMB3_ECIA_INFO MEC5_ECIA_INFO(13, 3, 5, 23)
81 #define MEC_I2C_SMB4_ECIA_INFO MEC5_ECIA_INFO(13, 4, 5, 158)
82
83 /* #define MEC_I2C_NL_DEBUG_SAVE_CM_CMD */
84
85 struct mec_i2c_info {
86 uintptr_t base_addr;
87 uint32_t devi;
88 uint16_t pcr_id;
89 };
90
91 static const struct mec_i2c_freq_cfg freq_cfg_dflt[MEC_I2C_STD_FREQ_MAX] = {
92 [MEC_I2C_STD_FREQ_100K] = {
93 .freqhz = 100000u,
94 .idle_scaling = 0x01fc01edu,
95 .timeout_scaling = 0x4b9cc2c7u,
96 .data_timing = 0x0c4d5006u,
97 .bus_clk = 0x4f4fu,
98 .rpt_start_hold_time = 0x4du,
99 },
100 [MEC_I2C_STD_FREQ_400K] = {
101 .freqhz = 400000u,
102 .idle_scaling = 0x01000050u,
103 .timeout_scaling = 0x159cc2c7u,
104 .data_timing = 0x040a0a06u,
105 .bus_clk = 0xf17u,
106 .rpt_start_hold_time = 0x0au,
107 },
108 [MEC_I2C_STD_FREQ_1M] = {
109 .freqhz = 1000000u,
110 .idle_scaling = 0x10000050u,
111 .timeout_scaling = 0x089cc2c7u,
112 .data_timing = 0x04060601u,
113 .bus_clk = 0x509u,
114 .rpt_start_hold_time = 0x06u,
115 },
116 };
117
118 static const struct mec_i2c_info i2c_instances[MEC5_I2C_SMB_INSTANCES] = {
119 {MEC_I2C_SMB0_BASE, MEC_I2C_SMB0_ECIA_INFO, MEC_PCR_I2C_SMB0 },
120 {MEC_I2C_SMB1_BASE, MEC_I2C_SMB1_ECIA_INFO, MEC_PCR_I2C_SMB1 },
121 {MEC_I2C_SMB2_BASE, MEC_I2C_SMB2_ECIA_INFO, MEC_PCR_I2C_SMB2 },
122 {MEC_I2C_SMB3_BASE, MEC_I2C_SMB3_ECIA_INFO, MEC_PCR_I2C_SMB3 },
123 {MEC_I2C_SMB4_BASE, MEC_I2C_SMB4_ECIA_INFO, MEC_PCR_I2C_SMB4 },
124 };
125
get_i2c_smb_info(struct mec_i2c_smb_regs * base)126 static struct mec_i2c_info const *get_i2c_smb_info(struct mec_i2c_smb_regs *base)
127 {
128 for (int i = 0; i < MEC5_I2C_SMB_INSTANCES; i++) {
129 const struct mec_i2c_info *p = &i2c_instances[i];
130
131 if (p->base_addr == (uintptr_t)base) {
132 return p;
133 }
134 }
135
136 return NULL;
137 }
138
mec_hal_i2c_smb_reset(struct mec_i2c_smb_ctx * ctx)139 int mec_hal_i2c_smb_reset(struct mec_i2c_smb_ctx *ctx)
140 {
141 if (!ctx) {
142 return MEC_RET_ERR_INVAL;
143 }
144
145 const struct mec_i2c_info *info = get_i2c_smb_info(ctx->base);
146
147 if (!info) {
148 return MEC_RET_ERR_INVAL;
149 }
150
151 mec_hal_pcr_blk_reset(info->pcr_id);
152
153 return MEC_RET_OK;
154 }
155
i2c_timing(struct mec_i2c_smb_regs * base,const struct mec_i2c_freq_cfg * freq_cfg)156 static void i2c_timing(struct mec_i2c_smb_regs *base, const struct mec_i2c_freq_cfg *freq_cfg)
157 {
158 base->BUSCLK = freq_cfg->bus_clk;
159 base->RSHT = freq_cfg->rpt_start_hold_time;
160 base->DATATM = freq_cfg->data_timing;
161 base->IDLESC = freq_cfg->idle_scaling;
162 base->TMOUTSC = freq_cfg->timeout_scaling;
163 }
164
i2c_config(struct mec_i2c_smb_ctx * ctx,struct mec_i2c_smb_cfg * config,struct mec_i2c_freq_cfg * custom_freq_cfg)165 static void i2c_config(struct mec_i2c_smb_ctx *ctx, struct mec_i2c_smb_cfg *config,
166 struct mec_i2c_freq_cfg *custom_freq_cfg)
167 {
168 struct mec_i2c_smb_regs *base = ctx->base;
169 uint8_t control = MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos); /* clear low level HW status */
170
171 /* disable and set port MUX */
172 base->CONFIG = (((uint32_t)config->port << MEC_I2C_SMB_CONFIG_PORT_SEL_Pos)
173 & MEC_I2C_SMB_CONFIG_PORT_SEL_Msk);
174 base->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_FEN_Pos); /* enable digital filter */
175
176 base->CTRL = control;
177 ctx->i2c_ctrl_cached = control;
178
179 /* GCC 12 is generating a 16-bit load from an odd aligned address!
180 * base->OWN_ADDR = (uint32_t)config->target_addr1 | ((uint32_t)config->target_addr2 << 8);
181 * Try forcing it not to do that.
182 */
183 base->OWN_ADDR = config->target_addr2;
184 base->OWN_ADDR = (base->OWN_ADDR << 8) | config->target_addr1;
185
186 if (config->cfg_flags & MEC_I2C_SMB_CFG_CUST_FREQ) {
187 i2c_timing(base, custom_freq_cfg);
188 } else {
189 i2c_timing(base, &freq_cfg_dflt[config->std_freq]);
190 }
191
192 base->COMPL = MEC_I2C_SMB_COMPL_STS_RW1C_MSK;
193
194 /* Enable output drive and HW ACK generation */
195 control = (MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos)
196 | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos));
197 ctx->i2c_ctrl_cached = control;
198 base->CTRL = control;
199
200 base->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos);
201 for (int i = 0; i < 8; i++) {
202 base->EXTLEN = 0;
203 }
204 base->COMPL |= MEC_I2C_SMB_COMPL_STS_RW1C_MSK;
205 }
206
207 /* I2C-SMB bus clock frequency =
208 * Fixed HW BAUD clock freq / ((low_period+1) + (high_period+1))
209 */
mec_hal_i2c_smb_bus_freq_get(struct mec_i2c_smb_ctx * ctx,uint32_t * bus_freq_hz)210 int mec_hal_i2c_smb_bus_freq_get(struct mec_i2c_smb_ctx *ctx, uint32_t *bus_freq_hz)
211 {
212 if (!ctx || !ctx->base || !bus_freq_hz) {
213 return MEC_RET_ERR_INVAL;
214 }
215
216 struct mec_i2c_smb_regs *regs = ctx->base;
217 uint32_t busclk = regs->BUSCLK;
218 uint32_t lcnt = busclk & 0xffu;
219 uint32_t hcnt = (busclk >> 8) & 0xffu;
220
221 *bus_freq_hz = MEC_I2C_SMB_BAUD_CLK_FREQ_HZ / ((lcnt + 1u) + (hcnt + 1));
222
223 return MEC_RET_OK;
224 }
225
mec_hal_i2c_smb_init(struct mec_i2c_smb_ctx * ctx,struct mec_i2c_smb_cfg * config,struct mec_i2c_freq_cfg * custom_freq_cfg)226 int mec_hal_i2c_smb_init(struct mec_i2c_smb_ctx *ctx, struct mec_i2c_smb_cfg *config,
227 struct mec_i2c_freq_cfg *custom_freq_cfg)
228 {
229 uint32_t own_addrs = 0;
230
231 if (!ctx) {
232 return MEC_RET_ERR_INVAL;
233 }
234
235 const struct mec_i2c_info *info = get_i2c_smb_info(ctx->base);
236
237 if (!info || !config) {
238 return MEC_RET_ERR_INVAL;
239 }
240
241 ctx->devi = info->devi;
242
243 if (config->cfg_flags & MEC_I2C_SMB_CFG_PRESERVE_TARGET_ADDRS) {
244 own_addrs = ctx->base->OWN_ADDR;
245 config->target_addr1 = (uint8_t)(own_addrs & 0x7fu);
246 config->target_addr2 = (uint8_t)((own_addrs >> 8) & 0x7fu);
247 }
248
249 mec_hal_pcr_clr_blk_slp_en(info->pcr_id);
250 mec_hal_pcr_blk_reset(info->pcr_id);
251
252 if (!(MEC_BIT(config->port) & MEC5_I2C_SMB_PORT_MAP)) {
253 return MEC_RET_ERR_INVAL;
254 }
255
256 if ((config->cfg_flags & MEC_I2C_SMB_CFG_CUST_FREQ) && !custom_freq_cfg) {
257 return MEC_RET_ERR_INVAL;
258 } else if (config->std_freq >= MEC_I2C_STD_FREQ_MAX) {
259 return MEC_RET_ERR_INVAL;
260 }
261
262 /* configure controller and cache last value written to write-only control register */
263 i2c_config(ctx, config, custom_freq_cfg);
264
265 /* clear GIRQ latched status */
266 mec_hal_girq_clr_src(ctx->devi);
267
268 return MEC_RET_OK;
269 }
270
271 /* Helper to set/get specified own (target mode) I2C 7-bit address.
272 * If curr_addr pointer is non-NULL then we get the current value else
273 * set own address to new_addr.
274 */
mec_hal_i2c_smb_own_addr(struct mec_i2c_smb_ctx * ctx,uint8_t tid,uint16_t new_addr,uint16_t * curr_addr)275 static int mec_hal_i2c_smb_own_addr(struct mec_i2c_smb_ctx *ctx, uint8_t tid,
276 uint16_t new_addr, uint16_t *curr_addr)
277 {
278 uint32_t msk = 0;
279 uint8_t pos = 0;
280
281 if (!ctx) {
282 return MEC_RET_ERR_INVAL;
283 }
284
285 const struct mec_i2c_info *info = get_i2c_smb_info(ctx->base);
286
287 if (!info) {
288 return MEC_RET_ERR_INVAL;
289 }
290
291 switch (tid) {
292 case MEC_I2C_TARGET_ADDR_0:
293 msk = MEC_I2C_SMB_OWN_ADDR_OAD0_Msk;
294 pos = MEC_I2C_SMB_OWN_ADDR_OAD0_Pos;
295 break;
296 case MEC_I2C_TARGET_ADDR_1:
297 msk = MEC_I2C_SMB_OWN_ADDR_OAD1_Msk;
298 pos = MEC_I2C_SMB_OWN_ADDR_OAD1_Pos;
299 break;
300 default:
301 return MEC_RET_ERR_INVAL;
302 }
303
304 struct mec_i2c_smb_regs *regs = ctx->base;
305
306 if (curr_addr) {
307 *curr_addr = (uint16_t)((regs->OWN_ADDR & msk) >> pos);
308 } else {
309 regs->OWN_ADDR = ((regs->OWN_ADDR & (uint32_t)~msk)
310 | (((uint32_t)new_addr << pos) & msk));
311 }
312
313 return MEC_RET_OK;
314 }
315
mec_hal_i2c_smb_get_target_addr(struct mec_i2c_smb_ctx * ctx,uint8_t target_id,uint16_t * target_addr)316 int mec_hal_i2c_smb_get_target_addr(struct mec_i2c_smb_ctx *ctx, uint8_t target_id,
317 uint16_t *target_addr)
318 {
319 if (!target_addr) {
320 return MEC_RET_ERR_INVAL;
321 }
322
323 return mec_hal_i2c_smb_own_addr(ctx, target_id, 0u, target_addr);
324 }
325
mec_hal_i2c_smb_set_target_addr(struct mec_i2c_smb_ctx * ctx,uint8_t target_id,uint16_t target_addr)326 int mec_hal_i2c_smb_set_target_addr(struct mec_i2c_smb_ctx *ctx, uint8_t target_id,
327 uint16_t target_addr)
328 {
329 return mec_hal_i2c_smb_own_addr(ctx, target_id, target_addr, NULL);
330 }
331
mec_hal_i2c_smb_clr_target_addr(struct mec_i2c_smb_ctx * ctx,uint16_t target_addr)332 int mec_hal_i2c_smb_clr_target_addr(struct mec_i2c_smb_ctx *ctx, uint16_t target_addr)
333 {
334 if (!ctx) {
335 return MEC_RET_ERR_INVAL;
336 }
337
338 struct mec_i2c_smb_regs *regs = ctx->base;
339 uint32_t oaddr = regs->OWN_ADDR;
340 uint32_t taddr = (oaddr & MEC_I2C_SMB_OWN_ADDR_OAD0_Msk) >> MEC_I2C_SMB_OWN_ADDR_OAD0_Pos;
341
342 if (taddr == (uint32_t)target_addr) {
343 regs->OWN_ADDR &= (uint32_t)~MEC_I2C_SMB_OWN_ADDR_OAD0_Msk;
344 } else {
345 taddr = (oaddr & MEC_I2C_SMB_OWN_ADDR_OAD1_Msk) >> MEC_I2C_SMB_OWN_ADDR_OAD1_Pos;
346 if (taddr == (uint32_t)target_addr) {
347 regs->OWN_ADDR &= (uint32_t)~MEC_I2C_SMB_OWN_ADDR_OAD1_Msk;
348 }
349 }
350
351 return MEC_RET_OK;
352 }
353
mec_hal_i2c_smb_girq_status_clr(struct mec_i2c_smb_ctx * ctx)354 int mec_hal_i2c_smb_girq_status_clr(struct mec_i2c_smb_ctx *ctx)
355 {
356 if (!ctx) {
357 return MEC_RET_ERR_INVAL;
358 }
359
360 mec_hal_girq_clr_src(ctx->devi);
361
362 return MEC_RET_OK;
363 }
364
365 /* Enable/disable I2C controller interrupt signal from propagating to NVIC */
mec_hal_i2c_smb_girq_ctrl(struct mec_i2c_smb_ctx * ctx,int flags)366 int mec_hal_i2c_smb_girq_ctrl(struct mec_i2c_smb_ctx *ctx, int flags)
367 {
368 if (!ctx) {
369 return MEC_RET_ERR_INVAL;
370 }
371
372 if (flags & MEC_I2C_SMB_GIRQ_DIS) {
373 mec_hal_girq_ctrl(ctx->devi, 0);
374 }
375
376 if (flags & MEC_I2C_SMB_GIRQ_CLR_STS) {
377 mec_hal_girq_clr_src(ctx->devi);
378 }
379
380 if (flags & MEC_I2C_SMB_GIRQ_EN) {
381 mec_hal_girq_ctrl(ctx->devi, 1);
382 }
383
384 return MEC_RET_OK;
385 }
386
mec_hal_i2c_smb_girq_status(struct mec_i2c_smb_ctx * ctx)387 int mec_hal_i2c_smb_girq_status(struct mec_i2c_smb_ctx *ctx)
388 {
389 if (!ctx) {
390 return 0;
391 }
392
393 return (int)mec_hal_girq_src(ctx->devi);
394 }
395
mec_hal_i2c_smb_girq_result(struct mec_i2c_smb_ctx * ctx)396 int mec_hal_i2c_smb_girq_result(struct mec_i2c_smb_ctx *ctx)
397 {
398 if (!ctx) {
399 return 0;
400 }
401
402 return (int)mec_hal_girq_result(ctx->devi);
403 }
404
405 /* check I2C.Status Not Busy bit. If set the bus is NOT owned by this controller.
406 * Returns 0 if not owned or the parameter check fails.
407 * 1 if bus is owned by this controller.
408 */
mec_hal_i2c_smb_is_bus_owned(struct mec_i2c_smb_ctx * ctx)409 int mec_hal_i2c_smb_is_bus_owned(struct mec_i2c_smb_ctx *ctx)
410 {
411 #ifdef MEC_I2C_BASE_CHECK
412 if (!ctx || !ctx->base) {
413 return 0;
414 }
415 #endif
416 struct mec_i2c_smb_regs *base = ctx->base;
417
418 if (base->STATUS & MEC_BIT(MEC_I2C_SMB_STATUS_NBB_Pos)) {
419 return 0;
420 }
421
422 return 1;
423 }
424
mec_hal_i2c_smb_ctrl_set(struct mec_i2c_smb_ctx * ctx,uint8_t ctrl)425 int mec_hal_i2c_smb_ctrl_set(struct mec_i2c_smb_ctx *ctx, uint8_t ctrl)
426 {
427 #ifdef MEC_I2C_BASE_CHECK
428 if (!ctx || !ctx->base) {
429 return MEC_RET_ERR_INVAL;
430 }
431 #endif
432 struct mec_i2c_smb_regs *base = ctx->base;
433
434 ctx->i2c_ctrl_cached = ctrl;
435 base->CTRL = ctrl;
436
437 return MEC_RET_OK;
438 }
439
mec_hal_i2c_smb_ctrl_get(struct mec_i2c_smb_ctx * ctx)440 uint8_t mec_hal_i2c_smb_ctrl_get(struct mec_i2c_smb_ctx *ctx)
441 {
442 if (!ctx) {
443 return 0u;
444 }
445
446 return ctx->i2c_ctrl_cached;
447 }
448
mec_hal_i2c_cmd_ack_ctrl(struct mec_i2c_smb_ctx * ctx,uint8_t ack_en)449 int mec_hal_i2c_cmd_ack_ctrl(struct mec_i2c_smb_ctx *ctx, uint8_t ack_en)
450 {
451 #ifdef MEC_I2C_BASE_CHECK
452 if (!ctx || !ctx->base) {
453 return MEC_RET_ERR_INVAL;
454 }
455 #endif
456 struct mec_i2c_smb_regs *base = ctx->base;
457 uint8_t ctrl = ctx->i2c_ctrl_cached;
458
459 if (ack_en) {
460 ctrl |= MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos);
461 } else {
462 ctrl &= (uint8_t)~MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos);
463 }
464
465 ctx->i2c_ctrl_cached = ctrl;
466 base->CTRL = ctrl;
467
468 return MEC_RET_OK;
469 }
470
471 /* Re-arm Target mode receive after an external STOP. */
mec_hal_i2c_smb_rearm_target_rx(struct mec_i2c_smb_ctx * ctx)472 int mec_hal_i2c_smb_rearm_target_rx(struct mec_i2c_smb_ctx *ctx)
473 {
474 uint8_t ctr = (MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos)
475 | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos));
476
477 return mec_hal_i2c_smb_ctrl_set(ctx, ctr);
478 }
479
mec_hal_i2c_smb_auto_ack_enable(struct mec_i2c_smb_ctx * ctx,uint8_t ien)480 int mec_hal_i2c_smb_auto_ack_enable(struct mec_i2c_smb_ctx *ctx, uint8_t ien)
481 {
482 #ifdef MEC_I2C_BASE_CHECK
483 if (!ctx || !ctx->base) {
484 return MEC_RET_ERR_INVAL;
485 }
486 #endif
487 struct mec_i2c_smb_regs *base = ctx->base;
488 uint8_t ctr = MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos);
489
490 if (ien) {
491 ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
492 }
493
494 ctx->i2c_ctrl_cached = ctr;
495 base->CTRL = ctr;
496 return MEC_RET_OK;
497 }
498
mec_hal_i2c_smb_auto_ack_disable(struct mec_i2c_smb_ctx * ctx,uint8_t ien)499 int mec_hal_i2c_smb_auto_ack_disable(struct mec_i2c_smb_ctx *ctx, uint8_t ien)
500 {
501 #ifdef MEC_I2C_BASE_CHECK
502 if (!ctx || !ctx->base) {
503 return MEC_RET_ERR_INVAL;
504 }
505 #endif
506 struct mec_i2c_smb_regs *base = ctx->base;
507 uint8_t ctr = MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos);
508
509 if (ien) {
510 ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
511 }
512
513 ctx->i2c_ctrl_cached = ctr;
514 base->CTRL = ctr;
515 return MEC_RET_OK;
516 }
517
mec_hal_i2c_smb_idle_intr_enable(struct mec_i2c_smb_ctx * ctx,uint8_t enable)518 int mec_hal_i2c_smb_idle_intr_enable(struct mec_i2c_smb_ctx *ctx, uint8_t enable)
519 {
520 #ifdef MEC_I2C_BASE_CHECK
521 if (!ctx || !ctx->base) {
522 return MEC_RET_ERR_INVAL;
523 }
524 #endif
525
526 struct mec_i2c_smb_regs *base = ctx->base;
527
528 if (enable) {
529 base->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos);
530 } else {
531 base->CONFIG &= (uint32_t)~MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos);
532 }
533
534 return MEC_RET_OK;
535 }
536
mec_hal_i2c_smb_intr_ctrl(struct mec_i2c_smb_ctx * ctx,uint32_t mask,uint8_t enable)537 int mec_hal_i2c_smb_intr_ctrl(struct mec_i2c_smb_ctx *ctx, uint32_t mask, uint8_t enable)
538 {
539 uint32_t cfg = 0;
540
541 #ifdef MEC_I2C_BASE_CHECK
542 if (!ctx || !ctx->base) {
543 return MEC_RET_ERR_INVAL;
544 }
545 #endif
546
547 struct mec_i2c_smb_regs *regs = ctx->base;
548
549 if (mask & MEC_BIT(MEC_I2C_IEN_BYTE_MODE_POS)) {
550 if (enable) {
551 ctx->i2c_ctrl_cached |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
552 } else {
553 ctx->i2c_ctrl_cached &= (uint8_t)~MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
554 }
555 regs->CTRL = ctx->i2c_ctrl_cached;
556 }
557
558 if (mask & MEC_BIT(MEC_I2C_IEN_IDLE_POS)) {
559 cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos);
560 }
561 if (mask & MEC_BIT(MEC_I2C_NL_IEN_CM_DONE_POS)) {
562 cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENMI_Pos);
563 }
564 if (mask & MEC_BIT(MEC_I2C_NL_IEN_TM_DONE_POS)) {
565 cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENSI_Pos);
566 }
567 if (mask & MEC_BIT(MEC_I2C_NL_IEN_AAT_POS)) {
568 cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_AAT_Pos);
569 }
570
571 if (enable) {
572 regs->CONFIG |= cfg;
573 } else {
574 regs->CONFIG &= (uint32_t)~cfg;
575 }
576
577 return MEC_RET_OK;
578 }
579
580 /* Returns 32-bit unsigned containing combined I2C status
581 * b[7:0] = I2C.Status read-only register (byte status)
582 * b[31:8] = I2C.Completion status bits.
583 * We lose I2C.Completion bit[6] = TIMERR but this bit is
584 * a logical OR of bits[12:8].
585 * If parameter clear != 0 this routine will clear the R/W1C
586 * bits in I2C.Completion after reading them.
587 */
mec_hal_i2c_smb_status(struct mec_i2c_smb_ctx * ctx,uint8_t clear)588 uint32_t mec_hal_i2c_smb_status(struct mec_i2c_smb_ctx *ctx, uint8_t clear)
589 {
590 #ifdef MEC_I2C_BASE_CHECK
591 if (!ctx || !ctx->base) {
592 return 0;
593 }
594 #endif
595 struct mec_i2c_smb_regs *base = ctx->base;
596 uint32_t status = base->STATUS;
597 uint32_t compl = base->COMPL;
598
599 if (clear) {
600 base->COMPL = compl;
601 }
602
603 return (status | (compl & 0xffffff00u));
604 }
605
mec_hal_i2c_smb_wake_status(struct mec_i2c_smb_ctx * ctx)606 uint32_t mec_hal_i2c_smb_wake_status(struct mec_i2c_smb_ctx *ctx)
607 {
608 if (!ctx) {
609 return 0;
610 }
611
612 struct mec_i2c_smb_regs *base = ctx->base;
613
614 return base->WAKE_STS;
615 }
616
mec_hal_i2c_smb_wake_status_clr(struct mec_i2c_smb_ctx * ctx)617 void mec_hal_i2c_smb_wake_status_clr(struct mec_i2c_smb_ctx *ctx)
618 {
619 #ifdef MEC_I2C_BASE_CHECK
620 if (!ctx || !ctx->base) {
621 return;
622 }
623 #endif
624
625 struct mec_i2c_smb_regs *base = ctx->base;
626
627 base->WAKE_STS = MEC_BIT(MEC_I2C_SMB_WAKE_STS_START_DET_Pos);
628 }
629
mec_hal_i2c_smb_is_idle_ien(struct mec_i2c_smb_ctx * ctx)630 int mec_hal_i2c_smb_is_idle_ien(struct mec_i2c_smb_ctx *ctx)
631 {
632 #ifdef MEC_I2C_BASE_CHECK
633 if (!ctx || !ctx->base) {
634 return 0;
635 }
636 #endif
637 struct mec_i2c_smb_regs *regs = ctx->base;
638
639 if (regs->CONFIG & MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos)) {
640 return 1;
641 }
642
643 return 0;
644 }
645
mec_hal_i2c_smb_is_idle_intr(struct mec_i2c_smb_ctx * ctx)646 int mec_hal_i2c_smb_is_idle_intr(struct mec_i2c_smb_ctx *ctx)
647 {
648 #ifdef MEC_I2C_BASE_CHECK
649 if (!ctx || !ctx->base) {
650 return 0;
651 }
652 #endif
653 struct mec_i2c_smb_regs *base = ctx->base;
654 uint32_t cfg = base->CONFIG & MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos);
655 uint32_t compl = base->COMPL & MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
656
657 if (cfg && compl) {
658 return 1;
659 }
660
661 return 0;
662 }
663
664 /* Return 1 if AAT interrupt is enabled else 0.
665 * NOTE we can't condition this with AAT read-only status from the
666 * I2C.Status register because that value is dynamic, it can change
667 * due to Network layer causing the status to be cleared.
668 */
mec_hal_i2c_smb_is_aat_ien(struct mec_i2c_smb_ctx * ctx)669 bool mec_hal_i2c_smb_is_aat_ien(struct mec_i2c_smb_ctx *ctx)
670 {
671 #ifdef MEC_I2C_BASE_CHECK
672 if (!ctx || !ctx->base) {
673 return false;
674 }
675 #endif
676 struct mec_i2c_smb_regs *base = ctx->base;
677 uint32_t cfg = base->CONFIG & MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_AAT_Pos);
678
679 if (cfg) {
680 return true;
681 }
682
683 return false;
684 }
685
mec_hal_i2c_smb_idle_status_clr(struct mec_i2c_smb_ctx * ctx)686 int mec_hal_i2c_smb_idle_status_clr(struct mec_i2c_smb_ctx *ctx)
687 {
688 #ifdef MEC_I2C_BASE_CHECK
689 if (!ctx || !ctx->base) {
690 return 0;
691 }
692 #endif
693 struct mec_i2c_smb_regs *base = ctx->base;
694
695 base->COMPL |= MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
696
697 return 0;
698 }
699
700 /* Controller specification sequence:
701 * START + addr. Bus is idle (I2C.STATUS.NBB == 1)
702 * write addr to I2C.Data
703 * write 0xC5 to I2C.Control or 0xCb if interrupts are enabled
704 * RPT-START + addr. Bus must we owned by this controller (I2C.STATUS.NBB == 0)
705 * write 0x45 or 0x4b to I2C.Control
706 * write addr I2C.Data
707 */
mec_hal_i2c_smb_start_gen(struct mec_i2c_smb_ctx * ctx,uint8_t target_addr,int flags)708 int mec_hal_i2c_smb_start_gen(struct mec_i2c_smb_ctx *ctx, uint8_t target_addr, int flags)
709 {
710 #ifdef MEC_I2C_BASE_CHECK
711 if (!ctx || !ctx->base) {
712 return MEC_RET_ERR_INVAL;
713 }
714 #endif
715 struct mec_i2c_smb_regs *base = ctx->base;
716 uint8_t ctr = (MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_STA_Pos)
717 | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos));
718
719 if (flags & MEC_I2C_SMB_BYTE_ENI) {
720 ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
721 }
722
723 if (base->STATUS & MEC_BIT(MEC_I2C_SMB_STATUS_NBB_Pos)) {
724 ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos);
725 ctx->i2c_ctrl_cached = ctr;
726 base->DATA = target_addr;
727 base->CTRL = ctr;
728 } else {
729 ctx->i2c_ctrl_cached = ctr;
730 base->CTRL = ctr;
731 base->DATA = target_addr;
732 }
733
734 return MEC_RET_OK;
735 }
736
mec_hal_i2c_smb_stop_gen(struct mec_i2c_smb_ctx * ctx)737 int mec_hal_i2c_smb_stop_gen(struct mec_i2c_smb_ctx *ctx)
738 {
739 #ifdef MEC_I2C_BASE_CHECK
740 if (!ctx || !ctx->base) {
741 return MEC_RET_ERR_INVAL;
742 }
743 #endif
744 struct mec_i2c_smb_regs *base = ctx->base;
745 uint8_t control = (MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos)
746 | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_STO_Pos));
747
748 /* Nothing to do. Controller does not own the bus at this time */
749 if (base->STATUS & MEC_BIT(MEC_I2C_SMB_STATUS_NBB_Pos)) {
750 return MEC_RET_ERR_NOP;
751 }
752
753 ctx->i2c_ctrl_cached = control;
754 base->CTRL = control;
755
756 return MEC_RET_OK;
757 }
758
759 /* Write byte to I2C.DATA for transmit
760 * Prerequisites: Bus is owned by this controller and a START or Rpt-START plus
761 * target write address has been sent by the controller.
762 * If byte mode interrupts are required they should be enabled in the (Rpt)START
763 * generation API.
764 */
mec_hal_i2c_smb_xmit_byte(struct mec_i2c_smb_ctx * ctx,uint8_t msg_byte)765 int mec_hal_i2c_smb_xmit_byte(struct mec_i2c_smb_ctx *ctx, uint8_t msg_byte)
766 {
767 #ifdef MEC_I2C_BASE_CHECK
768 if (!ctx || !ctx->base) {
769 return MEC_RET_ERR_INVAL;
770 }
771 #endif
772 struct mec_i2c_smb_regs *base = ctx->base;
773
774 /* TODO should we check for NBB==1 and return error?
775 * Only for data bytes. In the case of START we write target
776 * address to I2C.DATA before writing I2C.Control.
777 * If this function is only used for data then we can add the
778 * check of NBB.
779 */
780
781 base->DATA = msg_byte;
782
783 return MEC_RET_OK;
784 }
785
786 /* Read byte currently in receive buffer and generate clocks for next
787 * byte if CTRL.STO == 0.
788 */
mec_hal_i2c_smb_read_byte(struct mec_i2c_smb_ctx * ctx,uint8_t * msg_byte)789 int mec_hal_i2c_smb_read_byte(struct mec_i2c_smb_ctx *ctx, uint8_t *msg_byte)
790 {
791 #ifdef MEC_I2C_BASE_CHECK
792 if (!ctx || !ctx->base) {
793 return MEC_RET_ERR_INVAL;
794 }
795 #endif
796 struct mec_i2c_smb_regs *base = ctx->base;
797 uint8_t b = base->DATA;
798
799 if (msg_byte) {
800 *msg_byte = b;
801 }
802
803 return MEC_RET_OK;
804 }
805
mec_hal_i2c_smb_bbctrl(struct mec_i2c_smb_ctx * ctx,uint8_t enable,uint8_t pin_drive)806 int mec_hal_i2c_smb_bbctrl(struct mec_i2c_smb_ctx *ctx, uint8_t enable, uint8_t pin_drive)
807 {
808 #ifdef MEC_I2C_BASE_CHECK
809 if (!ctx || !ctx->base) {
810 return MEC_RET_ERR_INVAL;
811 }
812 #endif
813 struct mec_i2c_smb_regs *base = ctx->base;
814 uint8_t bbctr = 0u;
815
816 if (enable) {
817 bbctr |= MEC_BIT(MEC_I2C_SMB_BBCTRL_BBEN_Pos);
818 if (!(pin_drive & MEC_BIT(MEC_I2C_BB_SCL_POS))) { /* drive low? */
819 bbctr |= MEC_BIT(MEC_I2C_SMB_BBCTRL_CLDIR_Pos);
820 }
821 if (!(pin_drive & MEC_BIT(MEC_I2C_BB_SDA_POS))) { /* drive low? */
822 bbctr |= MEC_BIT(MEC_I2C_SMB_BBCTRL_DADIR_Pos);
823 }
824 }
825
826 base->BBCTRL = bbctr;
827
828 return MEC_RET_OK;
829 }
830
831 /* Read SCL and SDA pin states using bit-bang control register.
832 * NOTE 1: Bit-bang mode must be enabled otherwise HW will return
833 * both pin states as high.
834 * NOTE 2: Enabling bit-bang switches the SCL and SDA lines away from
835 * I2C logic to BB logic. When bit-bang is is disabled one must allow
836 * time for I2C logic to resync to pins.
837 */
mec_hal_i2c_smb_bbctrl_pin_states(struct mec_i2c_smb_ctx * ctx)838 uint8_t mec_hal_i2c_smb_bbctrl_pin_states(struct mec_i2c_smb_ctx *ctx)
839 {
840 #ifdef MEC_I2C_BASE_CHECK
841 if (!ctx || !ctx->base) {
842 return 0x3u;
843 }
844 #endif
845 struct mec_i2c_smb_regs *base = ctx->base;
846
847 return (base->BBCTRL >> MEC_I2C_SMB_BBCTRL_BBCLKI_Pos) & 0x3u;
848 }
849
850 /* -------- I2C-NL -------- */
851
852 #ifdef MEC_I2C_NL_DEBUG_SAVE_CM_CMD
853 static volatile uint32_t mec_i2c_nl_dbg_save[4];
854 #endif
855
mec_hal_i2c_nl_cm_cfg_start(struct mec_i2c_smb_ctx * ctx,uint16_t ntx,uint16_t nrx,uint32_t flags)856 int mec_hal_i2c_nl_cm_cfg_start(struct mec_i2c_smb_ctx *ctx, uint16_t ntx, uint16_t nrx,
857 uint32_t flags)
858 {
859 #ifdef MEC_I2C_BASE_CHECK
860 if (!ctx || !ctx->base) {
861 return MEC_RET_ERR_INVAL;
862 }
863 #endif
864 struct mec_i2c_smb_regs *regs = ctx->base;
865 uint32_t cmd = 0, primask = 0;
866
867 if (!ntx) { /* Any I2C transaction requires transmit of target address! */
868 return MEC_RET_ERR_INVAL;
869 }
870
871 ctx->wrcnt = ntx;
872 ctx->rdcnt = nrx;
873
874 regs->CONFIG &= (uint32_t)~MEC_BIT(MEC_I2C_SMB_CONFIG_ENMI_Pos);
875 regs->CONFIG |= (MEC_BIT(MEC_I2C_SMB_CONFIG_FLUSH_CTXB_Pos)
876 | MEC_BIT(MEC_I2C_SMB_CONFIG_FLUSH_CRXB_Pos));
877 regs->COMPL |= MEC_BIT(MEC_I2C_SMB_COMPL_CM_DONE_Pos);
878
879 regs->EXTLEN = ((ntx >> 8) & 0xffu) | (nrx & 0xff00u);
880
881 cmd = (uint32_t)(ntx & 0xffu) << MEC_I2C_SMB_CM_CMD_WRCNT_LSB_Pos;
882 cmd |= ((uint32_t)(nrx & 0xffu) << MEC_I2C_SMB_CM_CMD_RDCNT_LSB_Pos);
883 cmd |= (MEC_BIT(MEC_I2C_SMB_CM_CMD_RUN_Pos) | MEC_BIT(MEC_I2C_SMB_CM_CMD_PROCEED_Pos));
884
885 if (flags & MEC_I2C_NL_FLAG_START) {
886 cmd |= MEC_BIT(MEC_I2C_SMB_CM_CMD_START0_Pos);
887 }
888
889 if (flags & MEC_I2C_NL_FLAG_RPT_START) {
890 cmd |= MEC_BIT(MEC_I2C_SMB_CM_CMD_STARTN_Pos);
891 }
892
893 if (flags & MEC_I2C_NL_FLAG_STOP) {
894 cmd |= MEC_BIT(MEC_I2C_SMB_CM_CMD_STOP_Pos);
895 }
896
897 if (flags & MEC_I2C_NL_FLAG_CM_DONE_IEN) {
898 regs->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENMI_Pos);
899 }
900
901 #ifdef MEC_I2C_NL_DEBUG_SAVE_CM_CMD
902 mec_i2c_nl_dbg_save[0] = cmd;
903 mec_i2c_nl_dbg_save[1] = regs->CONFIG;
904 mec_i2c_nl_dbg_save[2] = regs->COMPL;
905 mec_i2c_nl_dbg_save[3] = regs->EXTLEN;
906 #endif
907
908 /* save CM_CMD in context */
909 ctx->cmdctrl = (uint16_t)(cmd & 0xffffu);
910
911 /* clear IDLE status just before starting HW
912 * It may be futile because the bus is idle before starting and the status
913 * bit may immediately be set by HW again.
914 */
915 regs->COMPL |= MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
916 if (flags & MEC_I2C_NL_FLAG_IDLE_IEN) {
917 primask = __get_PRIMASK();
918 __disable_irq();
919 regs->CM_CMD = cmd;
920 MEC_CPU_STALL->STALL = 1u; /* 2 us = 32 16 MHz I2C BAUD clocks */
921 regs->COMPL |= MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
922 regs->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos);
923 if (!primask) {
924 __enable_irq();
925 }
926 } else {
927 regs->CM_CMD = cmd;
928 }
929
930 return MEC_RET_OK;
931 }
932
933 /* I2C-NL FSM clears MRUN and MPROCEED when both wrCnt and rdCnt transition to 0.
934 * MRUN==1 and MPROCEED is cleared to 0 when FSM requires software to reconfigure
935 * DMA for the direction change from write to read. After the Rpt-Start and rdAddr
936 * are transmitted and (n)ACK'd the FSM clears MPROCEED only.
937 * NOTE: any error should clear MRUN and MPROCEED.
938 */
mec_hal_i2c_nl_cm_event(struct mec_i2c_smb_ctx * ctx)939 uint32_t mec_hal_i2c_nl_cm_event(struct mec_i2c_smb_ctx *ctx)
940 {
941 #ifdef MEC_I2C_BASE_CHECK
942 if (!ctx || !ctx->base) {
943 return MEC_I2C_NL_CM_EVENT_NONE;
944 }
945 #endif
946 struct mec_i2c_smb_regs *regs = ctx->base;
947 uint32_t cm_cmd = regs->CM_CMD;
948 uint16_t wrcnt = (uint16_t)((regs->EXTLEN & 0xffu) << 8);
949 uint16_t rdcnt = (uint16_t)(regs->EXTLEN & 0xff00u);
950
951 wrcnt |= (uint16_t)((cm_cmd >> 16) & 0xffu);
952 rdcnt |= (uint16_t)((cm_cmd >> 24) & 0xffu);
953
954 if (!cm_cmd && !(ctx->wrcnt || ctx->rdcnt)) {
955 return MEC_I2C_NL_CM_EVENT_ALL_DONE;
956 } else if (rdcnt && !wrcnt && ((cm_cmd & 0x03u) == 0x01)) {
957 return MEC_I2C_NL_CM_EVENT_W2R;
958 } else {
959 return MEC_I2C_NL_CM_EVENT_NONE;
960 }
961 }
962
mec_hal_i2c_nl_cmd_clear(struct mec_i2c_smb_ctx * ctx,uint8_t is_tm)963 int mec_hal_i2c_nl_cmd_clear(struct mec_i2c_smb_ctx *ctx, uint8_t is_tm)
964 {
965 #ifdef MEC_I2C_BASE_CHECK
966 if (!ctx || !ctx->base) {
967 return MEC_RET_ERR_INVAL;
968 }
969 #endif
970 if (is_tm) {
971 ctx->base->TM_CMD = 0;
972 } else {
973 ctx->base->CM_CMD = 0;
974 }
975 ctx->base->EXTLEN = 0;
976
977 return MEC_RET_OK;
978 }
979
mec_hal_i2c_nl_cm_proceed(struct mec_i2c_smb_ctx * ctx)980 int mec_hal_i2c_nl_cm_proceed(struct mec_i2c_smb_ctx *ctx)
981 {
982 #ifdef MEC_I2C_BASE_CHECK
983 if (!ctx || !ctx->base) {
984 return MEC_RET_ERR_INVAL;
985 }
986 #endif
987 ctx->base->CM_CMD |= (MEC_BIT(MEC_I2C_SMB_CM_CMD_RUN_Pos)
988 | MEC_BIT(MEC_I2C_SMB_CM_CMD_PROCEED_Pos));
989 return MEC_RET_OK;
990 }
991
mec_hal_i2c_nl_tm_proceed(struct mec_i2c_smb_ctx * ctx)992 int mec_hal_i2c_nl_tm_proceed(struct mec_i2c_smb_ctx *ctx)
993 {
994 #ifdef MEC_I2C_BASE_CHECK
995 if (!ctx || !ctx->base) {
996 return MEC_RET_ERR_INVAL;
997 }
998 #endif
999 ctx->base->TM_CMD |= (MEC_BIT(MEC_I2C_SMB_TM_CMD_RUN_Pos)
1000 | MEC_BIT(MEC_I2C_SMB_TM_CMD_PROCEED_Pos));
1001 return MEC_RET_OK;
1002 }
1003
mec_hal_i2c_nl_state_get(struct mec_i2c_smb_regs * regs,struct mec_i2c_smb_nl_state * state,uint8_t is_tm)1004 int mec_hal_i2c_nl_state_get(struct mec_i2c_smb_regs *regs, struct mec_i2c_smb_nl_state *state,
1005 uint8_t is_tm)
1006 {
1007 uint32_t elen = 0, r = 0;
1008
1009 #ifdef MEC_I2C_BASE_CHECK
1010 if (!regs) {
1011 return MEC_RET_ERR_INVAL;
1012 }
1013 #endif
1014 if (!state) {
1015 return MEC_RET_ERR_INVAL;
1016 }
1017
1018 elen = regs->EXTLEN;
1019
1020 if (is_tm) {
1021 elen >>= 16; /* TM wrCnt_MSB shifted to b[7:0] and TM rdCnt_MSB to b[15:0] */
1022 r = regs->TM_CMD;
1023 state->wrcnt = (uint16_t)((r >> 8) & 0xffu);
1024 state->rdcnt = (uint16_t)((r >> 16) & 0xffu);
1025 state->ctrl = (uint16_t)(r & 0xffu);
1026 } else {
1027 r = regs->CM_CMD;
1028 state->wrcnt = (uint16_t)((r >> 16) & 0xffu);
1029 state->rdcnt = (uint16_t)((r >> 24) & 0xffu);
1030 state->ctrl = (uint16_t)(r & 0xffffu);
1031 }
1032
1033 state->wrcnt |= (uint16_t)((elen & 0xffu) << 8);
1034 state->rdcnt |= (uint16_t)((elen & 0xff00u));
1035
1036 return MEC_RET_OK;
1037 }
1038
mec_hal_i2c_nl_cm_xfr_count_get(struct mec_i2c_smb_regs * regs,uint8_t is_read)1039 uint32_t mec_hal_i2c_nl_cm_xfr_count_get(struct mec_i2c_smb_regs *regs, uint8_t is_read)
1040 {
1041 uint32_t cnt = 0;
1042
1043 #ifdef MEC_I2C_BASE_CHECK
1044 if (!regs) {
1045 return cnt;
1046 }
1047 #endif
1048
1049 cnt = regs->EXTLEN;
1050 if (is_read) {
1051 cnt = (cnt & MEC_I2C_SMB_ELEN_CM_RDCNT_MSB_Msk) >> MEC_I2C_SMB_ELEN_CM_RDCNT_MSB_Pos;
1052 cnt <<= 8;
1053 cnt |= ((regs->CM_CMD & MEC_I2C_SMB_CM_CMD_RDCNT_LSB_Msk)
1054 >> MEC_I2C_SMB_CM_CMD_RDCNT_LSB_Pos);
1055 } else {
1056 cnt = (cnt & MEC_I2C_SMB_ELEN_CM_WRCNT_MSB_Msk) >> MEC_I2C_SMB_ELEN_CM_WRCNT_MSB_Pos;
1057 cnt <<= 8;
1058 cnt |= ((regs->CM_CMD & MEC_I2C_SMB_CM_CMD_WRCNT_LSB_Msk)
1059 >> MEC_I2C_SMB_CM_CMD_WRCNT_LSB_Pos);
1060 }
1061
1062 return cnt;
1063 }
1064
1065 /* Modify CM write or read byte count.
1066 * LSB's of the 16-bit counts are located in the CM_CMD register.
1067 * Bit[1:0] of this register should not be written with 0.
1068 * We access count LSB's using byte access.
1069 * write count LSB is in bits[15:8], read count LSB is in bits[32:26].
1070 */
mec_hal_i2c_nl_cm_xfr_count_set(struct mec_i2c_smb_regs * regs,uint8_t is_read,uint32_t cnt)1071 int mec_hal_i2c_nl_cm_xfr_count_set(struct mec_i2c_smb_regs *regs, uint8_t is_read, uint32_t cnt)
1072 {
1073 uint32_t cnt_lsb = 0, cnt_msb = 0;
1074 uint32_t cmsk = MEC_I2C_SMB_CM_CMD_WRCNT_LSB_Msk;
1075 uint32_t emsk = MEC_I2C_SMB_ELEN_CM_WRCNT_MSB_Msk;
1076 uint8_t cpos = MEC_I2C_SMB_CM_CMD_WRCNT_LSB_Pos;
1077 uint8_t epos = MEC_I2C_SMB_ELEN_CM_WRCNT_MSB_Pos;
1078
1079 #ifdef MEC_I2C_BASE_CHECK
1080 if (!regs) {
1081 return MEC_RET_ERR_INVAL;
1082 }
1083 #endif
1084
1085 if (cnt > MEC_I2C_SMB_NL_MAX_XFR_COUNT) {
1086 return MEC_RET_ERR_INVAL;
1087 }
1088
1089 /* Set MSB first in case LSB is 0 */
1090 if (is_read) {
1091 cmsk = MEC_I2C_SMB_CM_CMD_RDCNT_LSB_Msk;
1092 emsk = MEC_I2C_SMB_ELEN_CM_RDCNT_MSB_Msk;
1093 cpos = MEC_I2C_SMB_CM_CMD_RDCNT_LSB_Pos;
1094 epos = MEC_I2C_SMB_ELEN_CM_RDCNT_MSB_Pos;
1095 }
1096
1097 cnt_lsb = cnt & 0xffu;
1098 cnt_msb = (cnt >> 8) & 0xffu;
1099
1100 regs->EXTLEN = (regs->EXTLEN & (uint32_t)~emsk) | ((cnt_msb << epos) & emsk);
1101 regs->CM_CMD = (regs->CM_CMD & (uint32_t)~cmsk) | ((cnt_lsb << cpos) & cmsk);
1102
1103 return MEC_RET_OK;
1104 }
1105
mec_hal_i2c_nl_cmd_get(struct mec_i2c_smb_ctx * ctx,uint8_t is_tm)1106 uint32_t mec_hal_i2c_nl_cmd_get(struct mec_i2c_smb_ctx *ctx, uint8_t is_tm)
1107 {
1108 if (!ctx || !ctx->base) {
1109 return 0;
1110 }
1111
1112 if (!is_tm) {
1113 return ctx->base->CM_CMD;
1114 }
1115
1116 return ctx->base->TM_CMD;
1117 }
1118
1119
1120 /* ---- Target Mode Network Layer ---- */
1121
1122 /* Configure I2C controller's target command register
1123 * b[23:16] = Read count. This reflects the number of bytes we are receiving from
1124 * the external I2C Controller. This value is decremented by 1 for each by the
1125 * Central DMA channel reads from the TM Receive Buffer register.
1126 * Read count represents the buffer size the driver implements. The buffer should
1127 * be large enought to receive the message data plus possible Rpt-START address byte.
1128 * Read Count MSB is located in b[31:24] of the EXTLEN register.
1129 *
1130 * b[15:8] = Write count. The number of bytes this target will send to the external
1131 * I2C Controller. If this field and TM_PEC are 0 when the External controller requests
1132 * data then the current contents of the TM Transmit Buffer are used and the SPROT
1133 * status bit is set in the Completion register.
1134 * Write count MSB is located in b[23:16] of the EXTLEN register.
1135 *
1136 * b[2] = TM_PEC. If this bit is 1 when Write count is decrement to 0 then HW FSM will
1137 * copy contents of the PEC register to the I2C.Data register. HW FSM then clears the PEC
1138 * register and this bit.
1139 *
1140 * b[1] = TM_PROCEED
1141 * b[0] = TM_RUN
1142 *
1143 */
1144 /* Flags used by CM cfg_start
1145 * #define MEC_I2C_NL_FLAG_START 0x01
1146 * #define MEC_I2C_NL_FLAG_RPT_START 0x02
1147 * #define MEC_I2C_NL_FLAG_STOP 0x04
1148 * #define MEC_I2C_NL_FLAG_CM_DONE_IEN 0x100u
1149 *
1150 * New flags for TM config?
1151 * TM_CMD has no start, rpt-start, or stop flags.
1152 * TM_MODE has
1153 * Completion register status bits
1154 * TM_DONE
1155 * Rpt-START on matching target write address
1156 * Rpt-START on matching target read address
1157 * TM_PROTOCOL_WR_CNT_ERROR
1158 * TM_TR(RO) = 0 TM finished rx phase, 1 = finished tx phase
1159 * TM_NAKR TM sent a NAK while it was receiving data
1160 *
1161 * Configuration register
1162 * TM_DONE interrupt enable
1163 * AAT interrupt enable
1164 */
mec_hal_i2c_nl_tm_config(struct mec_i2c_smb_ctx * ctx,uint16_t ntx,uint16_t nrx,uint32_t flags)1165 int mec_hal_i2c_nl_tm_config(struct mec_i2c_smb_ctx *ctx, uint16_t ntx, uint16_t nrx,
1166 uint32_t flags)
1167 {
1168 uint32_t tm_cmd = 0;
1169 uint32_t tm_ien = 0;
1170 uint32_t elen = 0;
1171 uint32_t tm_ien_msk = (MEC_BIT(MEC_I2C_SMB_CONFIG_ENSI_Pos)
1172 | MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_AAT_Pos));
1173
1174 if (!ctx) {
1175 return MEC_RET_ERR_INVAL;
1176 }
1177
1178 struct mec_i2c_smb_regs *regs = ctx->base;
1179
1180 ctx->wrcnt = ntx;
1181 ctx->rdcnt = nrx;
1182
1183 regs->CONFIG &= (uint32_t)~tm_ien_msk;
1184 regs->COMPL |= (uint32_t)MEC_I2C_SMB_COMPL_TM_STS_ALL_MSK;
1185
1186 if (flags & MEC_I2C_NL_TM_FLAG_DONE_IEN) {
1187 tm_ien |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENSI_Pos);
1188 }
1189
1190 if (flags & MEC_I2C_NL_TM_FLAG_AAT_IEN) {
1191 tm_ien |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_AAT_Pos);
1192 }
1193
1194 #ifdef MEC5_I2C_SMB_HAS_STOP_DETECT_IRQ
1195 if (flags & MEC_I2C_NL_TM_FLAG_STOP_IEN) {
1196 tm_ien |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_NL_STS_Pos);
1197 }
1198 #endif
1199
1200 tm_cmd = (((uint32_t)nrx << MEC_I2C_SMB_TM_CMD_RDCNT_LSB_Pos)
1201 & MEC_I2C_SMB_TM_CMD_RDCNT_LSB_Msk);
1202 tm_cmd |= (((uint32_t)ntx << MEC_I2C_SMB_TM_CMD_WRCNT_LSB_Pos)
1203 & MEC_I2C_SMB_TM_CMD_WRCNT_LSB_Msk);
1204
1205 if (flags & MEC_I2C_NL_TM_FLAG_RUN) {
1206 tm_cmd |= (MEC_BIT(MEC_I2C_SMB_TM_CMD_RUN_Pos)
1207 | MEC_BIT(MEC_I2C_SMB_TM_CMD_PROCEED_Pos));
1208 }
1209
1210 /* save TM_CMD in context */
1211 ctx->cmdctrl = (uint16_t)(tm_cmd & 0xffu);
1212
1213 /* b[23:16] = TM wrCnt MSB, b[31:24] = TM rdCnt MSB */
1214 elen = (ntx & 0xff00u) >> 8;
1215 elen |= nrx & 0xff00u;
1216 elen <<= 16;
1217 regs->EXTLEN = (regs->EXTLEN & 0xffffu) | elen;
1218 regs->TM_CMD = tm_cmd;
1219 regs->CONFIG |= tm_ien;
1220
1221 return MEC_RET_OK;
1222 }
1223
mec_hal_i2c_nl_tm_event(struct mec_i2c_smb_ctx * ctx)1224 uint32_t mec_hal_i2c_nl_tm_event(struct mec_i2c_smb_ctx *ctx)
1225 {
1226 #ifdef MEC_I2C_BASE_CHECK
1227 if (!ctx || !ctx->base) {
1228 return MEC_I2C_NL_TM_EVENT_NONE;
1229 }
1230 #endif
1231 struct mec_i2c_smb_regs *regs = ctx->base;
1232 uint32_t tm_cmd = regs->TM_CMD;
1233 uint32_t elen = regs->EXTLEN;
1234 uint16_t wrcnt = (uint16_t)((elen >> 8) & 0xff00u);
1235 uint16_t rdcnt = (uint16_t)((elen >> 16) & 0xff00u);
1236
1237 wrcnt |= (uint16_t)((tm_cmd >> 8) & 0xffu);
1238 rdcnt |= (uint16_t)((tm_cmd >> 16) & 0xffu);
1239
1240 if (!tm_cmd && (ctx->wrcnt || ctx->rdcnt)) {
1241 return MEC_I2C_NL_TM_EVENT_ALL_DONE;
1242 } else if (rdcnt && !wrcnt && ((tm_cmd & 0x03u) == 0x01)) {
1243 return MEC_I2C_NL_TM_EVENT_W2R;
1244 } else {
1245 return MEC_I2C_NL_TM_EVENT_NONE;
1246 }
1247 }
1248
mec_hal_i2c_nl_tm_xfr_count_get(struct mec_i2c_smb_ctx * ctx,uint8_t is_rx)1249 uint32_t mec_hal_i2c_nl_tm_xfr_count_get(struct mec_i2c_smb_ctx *ctx, uint8_t is_rx)
1250 {
1251 uint32_t cnt = 0;
1252
1253 #ifdef MEC_I2C_BASE_CHECK
1254 if (!ctx || !ctx->base) {
1255 return MEC_I2C_NL_TM_EVENT_NONE;
1256 }
1257 #endif
1258 struct mec_i2c_smb_regs *regs = ctx->base;
1259
1260 cnt = regs->EXTLEN;
1261 if (is_rx) { /* External Controller transmits clocks and data. We capture(receive) data */
1262 cnt = (cnt & MEC_I2C_SMB_ELEN_TM_RDCNT_MSB_Msk) >> MEC_I2C_SMB_ELEN_TM_RDCNT_MSB_Pos;
1263 cnt <<= 8;
1264 cnt |= ((regs->TM_CMD & MEC_I2C_SMB_TM_CMD_RDCNT_LSB_Msk)
1265 >> MEC_I2C_SMB_TM_CMD_RDCNT_LSB_Pos);
1266 } else { /* External Controller generates clocks and we supply(transmit) data */
1267 cnt = (cnt & MEC_I2C_SMB_ELEN_TM_WRCNT_MSB_Msk) >> MEC_I2C_SMB_ELEN_TM_WRCNT_MSB_Pos;
1268 cnt <<= 8;
1269 cnt |= ((regs->TM_CMD & MEC_I2C_SMB_TM_CMD_WRCNT_LSB_Msk)
1270 >> MEC_I2C_SMB_TM_CMD_WRCNT_LSB_Pos);
1271 }
1272
1273 return cnt;
1274 }
1275
mec_hal_i2c_nl_tm_xfr_count_set(struct mec_i2c_smb_regs * regs,uint8_t is_read,uint32_t cnt)1276 int mec_hal_i2c_nl_tm_xfr_count_set(struct mec_i2c_smb_regs *regs, uint8_t is_read, uint32_t cnt)
1277 {
1278 uint32_t cnt_lsb = 0, cnt_msb = 0;
1279 uint32_t cmsk = MEC_I2C_SMB_TM_CMD_WRCNT_LSB_Msk;
1280 uint32_t emsk = MEC_I2C_SMB_ELEN_TM_WRCNT_MSB_Msk;
1281 uint8_t cpos = MEC_I2C_SMB_TM_CMD_WRCNT_LSB_Pos;
1282 uint8_t epos = MEC_I2C_SMB_ELEN_TM_WRCNT_MSB_Pos;
1283
1284 #ifdef MEC_I2C_BASE_CHECK
1285 if (!regs) {
1286 return MEC_RET_ERR_INVAL;
1287 }
1288 #endif
1289
1290 if (cnt > MEC_I2C_SMB_NL_MAX_XFR_COUNT) {
1291 return MEC_RET_ERR_INVAL;
1292 }
1293
1294 /* Set MSB first in case LSB is 0 */
1295 if (is_read) {
1296 cmsk = MEC_I2C_SMB_TM_CMD_RDCNT_LSB_Msk;
1297 emsk = MEC_I2C_SMB_ELEN_TM_RDCNT_MSB_Msk;
1298 cpos = MEC_I2C_SMB_TM_CMD_RDCNT_LSB_Pos;
1299 epos = MEC_I2C_SMB_ELEN_TM_RDCNT_MSB_Pos;
1300 }
1301
1302 cnt_lsb = cnt & 0xffu;
1303 cnt_msb = (cnt >> 8) & 0xffu;
1304
1305 regs->EXTLEN = (regs->EXTLEN & (uint32_t)~emsk) | ((cnt_msb << epos) & emsk);
1306 regs->TM_CMD = (regs->TM_CMD & (uint32_t)~cmsk) | ((cnt_lsb << cpos) & cmsk);
1307
1308 return MEC_RET_OK;
1309 }
1310
mec_hal_i2c_nl_tm_transfered(struct mec_i2c_smb_ctx * ctx,uint8_t is_rx)1311 uint32_t mec_hal_i2c_nl_tm_transfered(struct mec_i2c_smb_ctx *ctx, uint8_t is_rx)
1312 {
1313 uint32_t nxfr = 0, hwcnt = 0;
1314
1315 #ifdef MEC_I2C_BASE_CHECK
1316 if (!ctx || !ctx->base) {
1317 return MEC_I2C_NL_TM_EVENT_NONE;
1318 }
1319 #endif
1320
1321 hwcnt = mec_hal_i2c_nl_tm_xfr_count_get(ctx, is_rx);
1322
1323 if (is_rx) {
1324 if (ctx->rdcnt >= hwcnt) {
1325 nxfr = ctx->rdcnt - hwcnt;
1326 }
1327 } else {
1328 if (ctx->wrcnt >= hwcnt) {
1329 nxfr = ctx->wrcnt - hwcnt;
1330 }
1331 }
1332
1333 return nxfr;
1334 }
1335
1336
1337 /* ---- Power Management ----
1338 * Each controller has a wake enable interrupt on detection of an
1339 * external I2C START. This is only required if the controller is
1340 * being used in target mode.
1341 */
1342
1343 static uint8_t i2c_pm_save_buf[MEC5_I2C_SMB_INSTANCES];
1344
1345 /* Save and disable the controller */
mec_hal_i2c_pm_save_disable(void)1346 void mec_hal_i2c_pm_save_disable(void)
1347 {
1348 for (int i = 0; i < MEC5_I2C_SMB_INSTANCES; i++) {
1349 struct mec_i2c_smb_regs *regs = (struct mec_i2c_smb_regs *)i2c_instances[i].base_addr;
1350
1351 if (regs->CONFIG & MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos)) {
1352 regs->CONFIG &= (uint32_t)~MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos);
1353 i2c_pm_save_buf[i] = 1;
1354 } else {
1355 i2c_pm_save_buf[i] = 0;
1356 }
1357 }
1358 }
1359
mec_hal_i2c_pm_restore(void)1360 void mec_hal_i2c_pm_restore(void)
1361 {
1362 for (int i = 0; i < MEC5_I2C_SMB_INSTANCES; i++) {
1363 struct mec_i2c_smb_regs *regs = (struct mec_i2c_smb_regs *)i2c_instances[i].base_addr;
1364
1365 if (i2c_pm_save_buf[i]) {
1366 regs->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos);
1367 }
1368 }
1369 }
1370
1371 /* end mec_i2c.c */
1372