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 
75 #define MEC_I2C_SMB0_ECIA_INFO MEC5_ECIA_INFO(13, 0, 5, 20)
76 #define MEC_I2C_SMB1_ECIA_INFO MEC5_ECIA_INFO(13, 1, 5, 21)
77 #define MEC_I2C_SMB2_ECIA_INFO MEC5_ECIA_INFO(13, 2, 5, 22)
78 #define MEC_I2C_SMB3_ECIA_INFO MEC5_ECIA_INFO(13, 3, 5, 23)
79 #define MEC_I2C_SMB4_ECIA_INFO MEC5_ECIA_INFO(13, 4, 5, 158)
80 
81 /* #define MEC_I2C_NL_DEBUG_SAVE_CM_CMD */
82 
83 struct mec_i2c_info {
84     uintptr_t base_addr;
85     uint32_t devi;
86     uint16_t pcr_id;
87 };
88 
89 static const struct mec_i2c_freq_cfg freq_cfg_dflt[MEC_I2C_STD_FREQ_MAX] = {
90     [MEC_I2C_STD_FREQ_100K] = {
91         .freqhz = 100000u,
92         .idle_scaling = 0x01fc01edu,
93         .timeout_scaling = 0x4b9cc2c7u,
94         .data_timing = 0x0c4d5006u,
95         .bus_clk = 0x4f4fu,
96         .rpt_start_hold_time = 0x4du,
97     },
98     [MEC_I2C_STD_FREQ_400K] = {
99         .freqhz = 400000u,
100         .idle_scaling = 0x01000050u,
101         .timeout_scaling = 0x159cc2c7u,
102         .data_timing = 0x040a0a06u,
103         .bus_clk = 0xf17u,
104         .rpt_start_hold_time = 0x0au,
105     },
106     [MEC_I2C_STD_FREQ_1M] = {
107         .freqhz = 1000000u,
108         .idle_scaling = 0x10000050u,
109         .timeout_scaling = 0x089cc2c7u,
110         .data_timing = 0x04060601u,
111         .bus_clk = 0x509u,
112         .rpt_start_hold_time = 0x06u,
113     },
114 };
115 
116 static const struct mec_i2c_info i2c_instances[MEC5_I2C_SMB_INSTANCES] = {
117     {MEC_I2C_SMB0_BASE, MEC_I2C_SMB0_ECIA_INFO, MEC_PCR_I2C_SMB0 },
118     {MEC_I2C_SMB1_BASE, MEC_I2C_SMB1_ECIA_INFO, MEC_PCR_I2C_SMB1 },
119     {MEC_I2C_SMB2_BASE, MEC_I2C_SMB2_ECIA_INFO, MEC_PCR_I2C_SMB2 },
120     {MEC_I2C_SMB3_BASE, MEC_I2C_SMB3_ECIA_INFO, MEC_PCR_I2C_SMB3 },
121     {MEC_I2C_SMB4_BASE, MEC_I2C_SMB4_ECIA_INFO, MEC_PCR_I2C_SMB4 },
122 };
123 
get_i2c_smb_info(struct mec_i2c_smb_regs * base)124 static struct mec_i2c_info const *get_i2c_smb_info(struct mec_i2c_smb_regs *base)
125 {
126     for (int i = 0; i < MEC5_I2C_SMB_INSTANCES; i++) {
127         const struct mec_i2c_info *p = &i2c_instances[i];
128 
129         if (p->base_addr == (uintptr_t)base) {
130             return p;
131         }
132     }
133 
134     return NULL;
135 }
136 
mec_hal_i2c_smb_reset(struct mec_i2c_smb_ctx * ctx)137 int mec_hal_i2c_smb_reset(struct mec_i2c_smb_ctx *ctx)
138 {
139     if (!ctx) {
140         return MEC_RET_ERR_INVAL;
141     }
142 
143     const struct mec_i2c_info *info = get_i2c_smb_info(ctx->base);
144 
145     if (!info) {
146         return MEC_RET_ERR_INVAL;
147     }
148 
149     mec_hal_pcr_blk_reset(info->pcr_id);
150 
151     return MEC_RET_OK;
152 }
153 
i2c_timing(struct mec_i2c_smb_regs * base,const struct mec_i2c_freq_cfg * freq_cfg)154 static void i2c_timing(struct mec_i2c_smb_regs *base, const struct mec_i2c_freq_cfg *freq_cfg)
155 {
156     base->BUSCLK = freq_cfg->bus_clk;
157     base->RSHT = freq_cfg->rpt_start_hold_time;
158     base->DATATM = freq_cfg->data_timing;
159     base->IDLESC = freq_cfg->idle_scaling;
160     base->TMOUTSC = freq_cfg->timeout_scaling;
161 }
162 
i2c_config(struct mec_i2c_smb_ctx * ctx,struct mec_i2c_smb_cfg * config,struct mec_i2c_freq_cfg * custom_freq_cfg)163 static void i2c_config(struct mec_i2c_smb_ctx *ctx, struct mec_i2c_smb_cfg *config,
164                        struct mec_i2c_freq_cfg *custom_freq_cfg)
165 {
166     struct mec_i2c_smb_regs *base = ctx->base;
167     uint8_t control = MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos); /* clear low level HW status */
168 
169     /* disable and set port MUX */
170     base->CONFIG = (((uint32_t)config->port << MEC_I2C_SMB_CONFIG_PORT_SEL_Pos)
171                     & MEC_I2C_SMB_CONFIG_PORT_SEL_Msk);
172     base->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_FEN_Pos); /* enable digital filter */
173 
174     base->CTRL = control;
175     ctx->i2c_ctrl_cached = control;
176 
177     /* GCC 12 is generating a 16-bit load from an odd aligned address!
178      * base->OWN_ADDR = (uint32_t)config->target_addr1 | ((uint32_t)config->target_addr2 << 8);
179      * Try forcing it not to do that.
180      */
181     base->OWN_ADDR = config->target_addr2;
182     base->OWN_ADDR = (base->OWN_ADDR << 8) | config->target_addr1;
183 
184     if (config->cfg_flags & MEC_I2C_SMB_CFG_CUST_FREQ) {
185         i2c_timing(base, custom_freq_cfg);
186     } else {
187         i2c_timing(base, &freq_cfg_dflt[config->std_freq]);
188     }
189 
190     base->COMPL = MEC_I2C_SMB_COMPL_STS_RW1C_MSK;
191 
192     /* Enable output drive and HW ACK generation */
193     control = (MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos)
194                | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos));
195     ctx->i2c_ctrl_cached = control;
196     base->CTRL = control;
197 
198     base->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos);
199     for (int i = 0; i < 8; i++) {
200         base->EXTLEN = 0;
201     }
202     base->COMPL |= MEC_I2C_SMB_COMPL_STS_RW1C_MSK;
203 }
204 
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)205 int mec_hal_i2c_smb_init(struct mec_i2c_smb_ctx *ctx, struct mec_i2c_smb_cfg *config,
206                          struct mec_i2c_freq_cfg *custom_freq_cfg)
207 {
208     if (!ctx) {
209         return MEC_RET_ERR_INVAL;
210     }
211 
212     const struct mec_i2c_info *info = get_i2c_smb_info(ctx->base);
213 
214     if (!info || !config) {
215         return MEC_RET_ERR_INVAL;
216     }
217 
218     ctx->devi = info->devi;
219 
220     mec_hal_pcr_clr_blk_slp_en(info->pcr_id);
221     mec_hal_pcr_blk_reset(info->pcr_id);
222 
223     if (!(MEC_BIT(config->port) & MEC5_I2C_SMB_PORT_MAP)) {
224         return MEC_RET_ERR_INVAL;
225     }
226 
227     if ((config->cfg_flags & MEC_I2C_SMB_CFG_CUST_FREQ) && !custom_freq_cfg) {
228         return MEC_RET_ERR_INVAL;
229     } else if (config->std_freq >= MEC_I2C_STD_FREQ_MAX) {
230         return MEC_RET_ERR_INVAL;
231     }
232 
233     /* configure controller and cache last value written to write-only control register */
234     i2c_config(ctx, config, custom_freq_cfg);
235 
236     /* clear GIRQ latched status */
237     mec_hal_girq_clr_src(ctx->devi);
238 
239     return MEC_RET_OK;
240 }
241 
mec_hal_i2c_smb_girq_status_clr(struct mec_i2c_smb_ctx * ctx)242 int mec_hal_i2c_smb_girq_status_clr(struct mec_i2c_smb_ctx *ctx)
243 {
244     if (!ctx) {
245         return MEC_RET_ERR_INVAL;
246     }
247 
248     mec_hal_girq_clr_src(ctx->devi);
249 
250     return MEC_RET_OK;
251 }
252 
253 /* Enable/disable I2C controller interrupt signal from propagating to NVIC */
mec_hal_i2c_smb_girq_ctrl(struct mec_i2c_smb_ctx * ctx,int flags)254 int mec_hal_i2c_smb_girq_ctrl(struct mec_i2c_smb_ctx *ctx, int flags)
255 {
256     if (!ctx) {
257         return MEC_RET_ERR_INVAL;
258     }
259 
260     if (flags & MEC_I2C_SMB_GIRQ_DIS) {
261         mec_hal_girq_ctrl(ctx->devi, 0);
262     }
263 
264     if (flags & MEC_I2C_SMB_GIRQ_CLR_STS) {
265         mec_hal_girq_clr_src(ctx->devi);
266     }
267 
268     if (flags & MEC_I2C_SMB_GIRQ_EN) {
269         mec_hal_girq_ctrl(ctx->devi, 1);
270     }
271 
272     return MEC_RET_OK;
273 }
274 
mec_hal_i2c_smb_girq_status(struct mec_i2c_smb_ctx * ctx)275 int mec_hal_i2c_smb_girq_status(struct mec_i2c_smb_ctx *ctx)
276 {
277     if (!ctx) {
278         return 0;
279     }
280 
281     return (int)mec_hal_girq_src(ctx->devi);
282 }
283 
mec_hal_i2c_smb_girq_result(struct mec_i2c_smb_ctx * ctx)284 int mec_hal_i2c_smb_girq_result(struct mec_i2c_smb_ctx *ctx)
285 {
286     if (!ctx) {
287         return 0;
288     }
289 
290     return (int)mec_hal_girq_result(ctx->devi);
291 }
292 
293 /* check I2C.Status Not Busy bit. If set the bus is NOT owned by this controller.
294  * Returns 0 if not owned or the parameter check fails.
295  *         1 if bus is owned by this controller.
296  */
mec_hal_i2c_smb_is_bus_owned(struct mec_i2c_smb_ctx * ctx)297 int mec_hal_i2c_smb_is_bus_owned(struct mec_i2c_smb_ctx *ctx)
298 {
299 #ifdef MEC_I2C_BASE_CHECK
300     if (!ctx || !ctx->base) {
301         return 0;
302     }
303 #endif
304     struct mec_i2c_smb_regs *base = ctx->base;
305 
306     if (base->STATUS & MEC_BIT(MEC_I2C_SMB_STATUS_NBB_Pos)) {
307         return 0;
308     }
309 
310     return 1;
311 }
312 
mec_hal_i2c_smb_ctrl_set(struct mec_i2c_smb_ctx * ctx,uint8_t ctrl)313 int mec_hal_i2c_smb_ctrl_set(struct mec_i2c_smb_ctx * ctx, uint8_t ctrl)
314 {
315 #ifdef MEC_I2C_BASE_CHECK
316     if (!ctx || !ctx->base) {
317         return MEC_RET_ERR_INVAL;
318     }
319 #endif
320     struct mec_i2c_smb_regs *base = ctx->base;
321 
322     ctx->i2c_ctrl_cached = ctrl;
323     base->CTRL = ctrl;
324 
325     return MEC_RET_OK;
326 }
327 
mec_hal_i2c_smb_ctrl_get(struct mec_i2c_smb_ctx * ctx)328 uint8_t mec_hal_i2c_smb_ctrl_get(struct mec_i2c_smb_ctx *ctx)
329 {
330     if (!ctx) {
331         return 0u;
332     }
333 
334     return ctx->i2c_ctrl_cached;
335 }
336 
337 /* Re-arm Target mode receive after an external STOP.  */
mec_hal_i2c_smb_rearm_target_rx(struct mec_i2c_smb_ctx * ctx)338 int mec_hal_i2c_smb_rearm_target_rx(struct mec_i2c_smb_ctx *ctx)
339 {
340     uint8_t ctr = (MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos)
341                    | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos));
342 
343     return mec_hal_i2c_smb_ctrl_set(ctx, ctr);
344 }
345 
mec_hal_i2c_smb_auto_ack_enable(struct mec_i2c_smb_ctx * ctx,uint8_t ien)346 int mec_hal_i2c_smb_auto_ack_enable(struct mec_i2c_smb_ctx *ctx, uint8_t ien)
347 {
348 #ifdef MEC_I2C_BASE_CHECK
349     if (!ctx || !ctx->base) {
350         return MEC_RET_ERR_INVAL;
351     }
352 #endif
353     struct mec_i2c_smb_regs *base = ctx->base;
354     uint8_t ctr = MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos);
355 
356     if (ien) {
357         ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
358     }
359 
360     ctx->i2c_ctrl_cached = ctr;
361     base->CTRL = ctr;
362     return MEC_RET_OK;
363 }
364 
mec_hal_i2c_smb_auto_ack_disable(struct mec_i2c_smb_ctx * ctx,uint8_t ien)365 int mec_hal_i2c_smb_auto_ack_disable(struct mec_i2c_smb_ctx *ctx, uint8_t ien)
366 {
367 #ifdef MEC_I2C_BASE_CHECK
368     if (!ctx || !ctx->base) {
369         return MEC_RET_ERR_INVAL;
370     }
371 #endif
372     struct mec_i2c_smb_regs *base = ctx->base;
373     uint8_t ctr = MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos);
374 
375     if (ien) {
376         ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
377     }
378 
379     ctx->i2c_ctrl_cached = ctr;
380     base->CTRL = ctr;
381     return MEC_RET_OK;
382 }
383 
mec_hal_i2c_smb_idle_intr_enable(struct mec_i2c_smb_ctx * ctx,uint8_t enable)384 int mec_hal_i2c_smb_idle_intr_enable(struct mec_i2c_smb_ctx *ctx, uint8_t enable)
385 {
386 #ifdef MEC_I2C_BASE_CHECK
387     if (!ctx || !ctx->base) {
388         return MEC_RET_ERR_INVAL;
389     }
390 #endif
391 
392     struct mec_i2c_smb_regs *base = ctx->base;
393 
394     if (enable) {
395         base->CONFIG |= MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
396     } else {
397         base->CONFIG &= (uint32_t)~MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
398     }
399 
400     return MEC_RET_OK;
401 }
402 
mec_hal_i2c_smb_intr_ctrl(struct mec_i2c_smb_ctx * ctx,uint32_t mask,uint8_t enable)403 int mec_hal_i2c_smb_intr_ctrl(struct mec_i2c_smb_ctx *ctx, uint32_t mask, uint8_t enable)
404 {
405     uint32_t cfg = 0;
406 
407 #ifdef MEC_I2C_BASE_CHECK
408     if (!ctx || !ctx->base) {
409         return MEC_RET_ERR_INVAL;
410     }
411 #endif
412 
413     struct mec_i2c_smb_regs *regs = ctx->base;
414 
415     if (mask & MEC_BIT(MEC_I2C_IEN_BYTE_MODE_POS)) {
416         if (enable) {
417             ctx->i2c_ctrl_cached |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
418         } else {
419             ctx->i2c_ctrl_cached &= (uint8_t)~MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
420         }
421         regs->CTRL = ctx->i2c_ctrl_cached;
422     }
423 
424     if (mask & MEC_BIT(MEC_I2C_IEN_IDLE_POS)) {
425         cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos);
426     }
427     if (mask & MEC_BIT(MEC_I2C_NL_IEN_CM_DONE_POS)) {
428         cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENMI_Pos);
429     }
430     if (mask & MEC_BIT(MEC_I2C_NL_IEN_TM_DONE_POS)) {
431         cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENSI_Pos);
432     }
433     if (mask & MEC_BIT(MEC_I2C_NL_IEN_AAT_POS)) {
434         cfg |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_AAS_Pos);
435     }
436 
437     if (enable) {
438         regs->CONFIG |= cfg;
439     } else {
440         regs->CONFIG &= ~cfg;
441     }
442 
443     return MEC_RET_OK;
444 }
445 
446 /* Returns 32-bit unsigned containing combined I2C status
447  * b[7:0] = I2C.Status read-only register (byte status)
448  * b[31:8] = I2C.Completion status bits.
449  * We lose I2C.Completion bit[6] = TIMERR but this bit is
450  * a logical OR of bits[12:8].
451  * If parameter clear != 0 this routine will clear the R/W1C
452  * bits in I2C.Completion after reading them.
453  */
mec_hal_i2c_smb_status(struct mec_i2c_smb_ctx * ctx,uint8_t clear)454 uint32_t mec_hal_i2c_smb_status(struct mec_i2c_smb_ctx *ctx, uint8_t clear)
455 {
456 #ifdef MEC_I2C_BASE_CHECK
457     if (!ctx || !ctx->base) {
458         return 0;
459     }
460 #endif
461     struct mec_i2c_smb_regs *base = ctx->base;
462     uint32_t status = base->STATUS;
463     uint32_t compl = base->COMPL;
464 
465     if (clear) {
466         base->COMPL = compl;
467     }
468 
469     return (status | (compl & 0xffffff00u));
470 }
471 
mec_hal_i2c_smb_wake_status(struct mec_i2c_smb_ctx * ctx)472 uint32_t mec_hal_i2c_smb_wake_status(struct mec_i2c_smb_ctx *ctx)
473 {
474     if (!ctx) {
475         return 0;
476     }
477 
478     struct mec_i2c_smb_regs *base = ctx->base;
479 
480     return base->WAKE_STS;
481 }
482 
mec_hal_i2c_smb_wake_status_clr(struct mec_i2c_smb_ctx * ctx)483 void mec_hal_i2c_smb_wake_status_clr(struct mec_i2c_smb_ctx *ctx)
484 {
485 #ifdef MEC_I2C_BASE_CHECK
486     if (!ctx || !ctx->base) {
487         return;
488     }
489 #endif
490 
491     struct mec_i2c_smb_regs *base = ctx->base;
492 
493     base->WAKE_STS = MEC_BIT(MEC_I2C_SMB_WAKE_STS_START_DET_Pos);
494 }
495 
mec_hal_i2c_smb_is_idle_intr(struct mec_i2c_smb_ctx * ctx)496 int mec_hal_i2c_smb_is_idle_intr(struct mec_i2c_smb_ctx *ctx)
497 {
498 #ifdef MEC_I2C_BASE_CHECK
499     if (!ctx || !ctx->base) {
500         return 0;
501     }
502 #endif
503     struct mec_i2c_smb_regs *base = ctx->base;
504     uint32_t cfg = base->CONFIG & MEC_BIT(MEC_I2C_SMB_CONFIG_ENI_IDLE_Pos);
505     uint32_t compl = base->COMPL & MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
506 
507     if (cfg && compl) {
508         return 1;
509     }
510 
511     return 0;
512 }
513 
mec_hal_i2c_smb_idle_status_clr(struct mec_i2c_smb_ctx * ctx)514 int mec_hal_i2c_smb_idle_status_clr(struct mec_i2c_smb_ctx *ctx)
515 {
516 #ifdef MEC_I2C_BASE_CHECK
517     if (!ctx || !ctx->base) {
518         return 0;
519     }
520 #endif
521     struct mec_i2c_smb_regs *base = ctx->base;
522 
523     base->COMPL |= MEC_BIT(MEC_I2C_SMB_COMPL_IDLE_Pos);
524 
525     return 0;
526 }
527 
528 /* Controller specification sequence:
529  * START + addr. Bus is idle (I2C.STATUS.NBB == 1)
530  *    write addr to I2C.Data
531  *    write 0xC5 to I2C.Control or 0xCb if interrupts are enabled
532  * RPT-START + addr. Bus must we owned by this controller (I2C.STATUS.NBB == 0)
533  *    write 0x45 or 0x4b to I2C.Control
534  *    write addr I2C.Data
535  */
mec_hal_i2c_smb_start_gen(struct mec_i2c_smb_ctx * ctx,uint8_t target_addr,int flags)536 int mec_hal_i2c_smb_start_gen(struct mec_i2c_smb_ctx *ctx, uint8_t target_addr, int flags)
537 {
538 #ifdef MEC_I2C_BASE_CHECK
539     if (!ctx || !ctx->base) {
540         return MEC_RET_ERR_INVAL;
541     }
542 #endif
543     struct mec_i2c_smb_regs *base = ctx->base;
544     uint8_t ctr = (MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_STA_Pos)
545                    | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos));
546 
547     if (flags & MEC_I2C_SMB_BYTE_ENI) {
548         ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_ENI_Pos);
549     }
550 
551     if (base->STATUS & MEC_BIT(MEC_I2C_SMB_STATUS_NBB_Pos)) {
552         ctr |= MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos);
553         ctx->i2c_ctrl_cached = ctr;
554         base->DATA = target_addr;
555         base->CTRL = ctr;
556     } else {
557         ctx->i2c_ctrl_cached = ctr;
558         base->CTRL = ctr;
559         base->DATA = target_addr;
560     }
561 
562     return MEC_RET_OK;
563 }
564 
mec_hal_i2c_smb_stop_gen(struct mec_i2c_smb_ctx * ctx)565 int mec_hal_i2c_smb_stop_gen(struct mec_i2c_smb_ctx *ctx)
566 {
567 #ifdef MEC_I2C_BASE_CHECK
568     if (!ctx || !ctx->base) {
569         return MEC_RET_ERR_INVAL;
570     }
571 #endif
572     struct mec_i2c_smb_regs *base = ctx->base;
573     uint8_t control = (MEC_BIT(MEC_I2C_SMB_CTRL_PIN_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_ESO_Pos)
574                        | MEC_BIT(MEC_I2C_SMB_CTRL_ACK_Pos) | MEC_BIT(MEC_I2C_SMB_CTRL_STO_Pos));
575 
576     /* Nothing to do. Controller does not own the bus at this time */
577     if (base->STATUS & MEC_BIT(MEC_I2C_SMB_STATUS_NBB_Pos)) {
578         return MEC_RET_ERR_NOP;
579     }
580 
581     ctx->i2c_ctrl_cached = control;
582     base->CTRL = control;
583 
584     return MEC_RET_OK;
585 }
586 
587 /* Write byte to I2C.DATA for transmit
588  * Prerequisites: Bus is owned by this controller and a START or Rpt-START plus
589  * target write address has been sent by the controller.
590  * If byte mode interrupts are required they should be enabled in the (Rpt)START
591  * generation API.
592  */
mec_hal_i2c_smb_xmit_byte(struct mec_i2c_smb_ctx * ctx,uint8_t msg_byte)593 int mec_hal_i2c_smb_xmit_byte(struct mec_i2c_smb_ctx *ctx, uint8_t msg_byte)
594 {
595 #ifdef MEC_I2C_BASE_CHECK
596     if (!ctx || !ctx->base) {
597         return MEC_RET_ERR_INVAL;
598     }
599 #endif
600     struct mec_i2c_smb_regs *base = ctx->base;
601 
602     /* TODO should we check for NBB==1 and return error?
603      * Only for data bytes. In the case of START we write target
604      * address to I2C.DATA before writing I2C.Control.
605      * If this function is only used for data then we can add the
606      * check of NBB.
607      */
608 
609     base->DATA = msg_byte;
610 
611     return MEC_RET_OK;
612 }
613 
614 /* Read byte currently in receive buffer and generate clocks for next
615  * byte if CTRL.STO == 0.
616  */
mec_hal_i2c_smb_read_byte(struct mec_i2c_smb_ctx * ctx,uint8_t * msg_byte)617 int mec_hal_i2c_smb_read_byte(struct mec_i2c_smb_ctx *ctx, uint8_t *msg_byte)
618 {
619 #ifdef MEC_I2C_BASE_CHECK
620     if (!ctx || !ctx->base) {
621         return MEC_RET_ERR_INVAL;
622     }
623 #endif
624     struct mec_i2c_smb_regs *base = ctx->base;
625     uint8_t b = base->DATA;
626 
627     if (msg_byte) {
628         *msg_byte = b;
629     }
630 
631     return MEC_RET_OK;
632 }
633 
mec_hal_i2c_smb_bbctrl(struct mec_i2c_smb_ctx * ctx,uint8_t enable,uint8_t pin_drive)634 int mec_hal_i2c_smb_bbctrl(struct mec_i2c_smb_ctx *ctx, uint8_t enable, uint8_t pin_drive)
635 {
636 #ifdef MEC_I2C_BASE_CHECK
637     if (!ctx || !ctx->base) {
638         return MEC_RET_ERR_INVAL;
639     }
640 #endif
641     struct mec_i2c_smb_regs *base = ctx->base;
642     uint8_t bbctr = 0u;
643 
644     if (enable) {
645         bbctr |= MEC_BIT(MEC_I2C_SMB_BBCTRL_BBEN_Pos);
646         if (!(pin_drive & MEC_BIT(MEC_I2C_BB_SCL_POS))) { /* drive low? */
647             bbctr |= MEC_BIT(MEC_I2C_SMB_BBCTRL_CLDIR_Pos);
648         }
649         if (!(pin_drive & MEC_BIT(MEC_I2C_BB_SDA_POS))) { /* drive low? */
650             bbctr |= MEC_BIT(MEC_I2C_SMB_BBCTRL_DADIR_Pos);
651         }
652     }
653 
654     base->BBCTRL = bbctr;
655 
656     return MEC_RET_OK;
657 }
658 
659 /* Read SCL and SDA pin states using bit-bang control register.
660  * NOTE 1: Bit-bang mode must be enabled otherwise HW will return
661  * both pin states as high.
662  * NOTE 2: Enabling bit-bang switches the SCL and SDA lines away from
663  * I2C logic to BB logic. When bit-bang is is disabled one must allow
664  * time for I2C logic to resync to pins.
665  */
mec_hal_i2c_smb_bbctrl_pin_states(struct mec_i2c_smb_ctx * ctx)666 uint8_t mec_hal_i2c_smb_bbctrl_pin_states(struct mec_i2c_smb_ctx *ctx)
667 {
668 #ifdef MEC_I2C_BASE_CHECK
669     if (!ctx || !ctx->base) {
670         return 0x3u;
671     }
672 #endif
673     struct mec_i2c_smb_regs *base = ctx->base;
674 
675     return (base->BBCTRL >> MEC_I2C_SMB_BBCTRL_BBCLKI_Pos) & 0x3u;
676 }
677 
678 /* -------- I2C-NL -------- */
679 
680 #ifdef MEC_I2C_NL_DEBUG_SAVE_CM_CMD
681 static volatile uint32_t mec_i2c_nl_dbg_save[4];
682 #endif
683 
mec_hal_i2c_nl_cm_cfg_start(struct mec_i2c_smb_ctx * ctx,uint16_t ntx,uint16_t nrx,uint32_t flags)684 int mec_hal_i2c_nl_cm_cfg_start(struct mec_i2c_smb_ctx *ctx, uint16_t ntx, uint16_t nrx,
685                                 uint32_t flags)
686 {
687 #ifdef MEC_I2C_BASE_CHECK
688     if (!ctx || !ctx->base) {
689         return MEC_RET_ERR_INVAL;
690     }
691 #endif
692     struct mec_i2c_smb_regs *regs = ctx->base;
693     uint32_t cmd = 0;
694 
695     if (!ntx) { /* Any I2C transaction requires transmit of target address! */
696         return MEC_RET_ERR_INVAL;
697     }
698 
699     regs->CONFIG &= (uint32_t)~MEC_BIT(MEC_I2C_SMB_CONFIG_ENMI_Pos);
700     regs->CONFIG |= (MEC_BIT(MEC_I2C_SMB_CONFIG_FLUSH_CTXB_Pos)
701                      | MEC_BIT(MEC_I2C_SMB_CONFIG_FLUSH_CRXB_Pos));
702     regs->COMPL |= MEC_BIT(MEC_I2C_SMB_COMPL_MDONE_Pos);
703 
704     regs->EXTLEN = ((ntx >> 8) & 0xffu) | (nrx & 0xff00u);
705 
706     cmd = (uint32_t)(ntx & 0xffu) << MEC_I2C_SMB_CM_CMD_WRCNT_LSB_Pos;
707     cmd |= ((uint32_t)(nrx & 0xffu) << MEC_I2C_SMB_CM_CMD_RDCNT_LSB_Pos);
708     cmd |= (MEC_BIT(MEC_I2C_SMB_CM_CMD_MRUN_Pos) | MEC_BIT(MEC_I2C_SMB_CM_CMD_MPROCEED_Pos));
709 
710     if (flags & MEC_I2C_NL_FLAG_START) {
711         cmd |= MEC_BIT(MEC_I2C_SMB_CM_CMD_START0_Pos);
712     }
713 
714     if (flags & MEC_I2C_NL_FLAG_RPT_START) {
715         cmd |= MEC_BIT(MEC_I2C_SMB_CM_CMD_STARTN_Pos);
716     }
717 
718     if (flags & MEC_I2C_NL_FLAG_STOP) {
719         cmd |= MEC_BIT(MEC_I2C_SMB_CM_CMD_STOP_Pos);
720     }
721 
722     if (flags & MEC_I2C_NL_FLAG_CM_DONE_IEN) {
723         regs->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENMI_Pos);
724     }
725 
726 #ifdef MEC_I2C_NL_DEBUG_SAVE_CM_CMD
727     mec_i2c_nl_dbg_save[0] = cmd;
728     mec_i2c_nl_dbg_save[1] = regs->CONFIG;
729     mec_i2c_nl_dbg_save[2] = regs->COMPL;
730     mec_i2c_nl_dbg_save[3] = regs->EXTLEN;
731 #endif
732 
733     regs->CM_CMD = cmd;
734 
735     return MEC_RET_OK;
736 }
737 
738 /* I2C-NL FSM clears MRUN and MPROCEED when both wrCnt and rdCnt transition to 0.
739  * MRUN==1 and MPROCEED is cleared to 0 when FSM requires software to reconfigure
740  * DMA for the direction change from write to read. After the Rpt-Start and rdAddr
741  * are transmitted and (n)ACK'd the FSM clears MPROCEED only.
742  * NOTE: any error should clear MRUN and MPROCEED.
743  */
mec_hal_i2c_nl_cm_event(struct mec_i2c_smb_regs * regs)744 uint32_t mec_hal_i2c_nl_cm_event(struct mec_i2c_smb_regs *regs)
745 {
746 #ifdef MEC_I2C_BASE_CHECK
747     if (!regs) {
748         return MEC_I2C_NL_CM_EVENT_NONE;
749     }
750 #endif
751 
752     uint32_t cm_cmd = regs->CM_CMD & 0x03u;
753 
754     if (cm_cmd == 0) {
755         return MEC_I2C_NL_CM_EVENT_ALL_DONE;
756     } else if (cm_cmd == 0x01) {
757         return MEC_I2C_NL_CM_EVENT_W2R;
758     } else {
759         return MEC_I2C_NL_CM_EVENT_NONE;
760     }
761 }
762 
763 /* ---- Power Management ----
764  * Each controller has a wake enable interrupt on detection of an
765  * external I2C START. This is only required if the controller is
766  * being used in target mode.
767  */
768 
769 static uint8_t i2c_pm_save_buf[MEC5_I2C_SMB_INSTANCES];
770 
771 /* Save and disable the controller */
mec_hal_i2c_pm_save_disable(void)772 void mec_hal_i2c_pm_save_disable(void)
773 {
774     for (int i = 0; i < MEC5_I2C_SMB_INSTANCES; i++) {
775         struct mec_i2c_smb_regs *regs = (struct mec_i2c_smb_regs *)i2c_instances[i].base_addr;
776 
777         if (regs->CONFIG & MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos)) {
778             regs->CONFIG &= (uint32_t)~MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos);
779             i2c_pm_save_buf[i] = 1;
780         } else {
781             i2c_pm_save_buf[i] = 0;
782         }
783     }
784 }
785 
mec_hal_i2c_pm_restore(void)786 void mec_hal_i2c_pm_restore(void)
787 {
788     for (int i = 0; i < MEC5_I2C_SMB_INSTANCES; i++) {
789         struct mec_i2c_smb_regs *regs = (struct mec_i2c_smb_regs *)i2c_instances[i].base_addr;
790 
791         if (i2c_pm_save_buf[i]) {
792             regs->CONFIG |= MEC_BIT(MEC_I2C_SMB_CONFIG_ENAB_Pos);
793         }
794     }
795 }
796 
797 /* end mec_i2c.c */
798