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