1 /**
2 * \file j7200/I2C_soc.c
3 *
4 * \brief J7200 SoC specific I2C hardware attributes.
5 *
6 * This file contains the hardware attributes of I2C peripheral like
7 * base address, interrupt number etc.
8 */
10 /*
11 * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the
23 * distribution.
24 *
25 * Neither the name of Texas Instruments Incorporated nor the names of
26 * its contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 */
43 #include <string.h>
44 #include <ti/csl/arch/r5/csl_arm_r5.h>
45 #include <ti/csl/soc.h>
46 #include <ti/csl/csl_clec.h>
47 #include <ti/drv/i2c/I2C.h>
48 #include <ti/drv/i2c/soc/I2C_soc.h>
49 #include <ti/drv/sciclient/sciclient.h>
51 #define I2C_INPUT_CLK (96000000U)
53 /* DMSC SYSFW invalid I2C device ID */
54 #define I2C_TISCI_INVALID_DEV_ID ((uint16_t)0xFFFFU)
56 /* CLEC input event # offset for GIC SPI */
57 #define I2C_CLEC_GIC_SPI_IN_EVT_OFFSET (1024U - 32U)
59 /* DMSC SYSFW C66x destination host int # for I2C0 */
60 #define I2C_TISCI_C66X_DST_HOST_IRQ0 (60U)
62 /* C7x INTC int # for I2C0 */
63 #define I2C_C7X_IRQ0 (30U)
65 static int32_t I2C_configSocIntrPath(const void *pHwAttrs, bool setIntrPath);
67 /* I2C configuration structure */
68 I2C_HwAttrs i2cInitCfg[I2C_HWIP_MAX_CNT] =
69 {
70 {
71 #if defined (BUILD_MPU)
72 /* default configuration for I2C instance and MPU core on Main domain*/
73 (uint32_t)CSL_I2C0_CFG_BASE, /* baseAddr */
74 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C0_POINTRPEND_0, /* intNum */
75 0, /* eventId */
76 #endif
77 #if defined (BUILD_MCU)
78 /*
79 * default configuration for I2C instances and R5 cores on MCU domain
80 * I2C_socInit() is called during initialization to change the default
81 * configurations to use Main Domain's I2C instances if R5 is running
82 * on Main domain
83 */
84 (uint32_t)CSL_MCU_I2C0_CFG_BASE, /* baseAddr */
85 CSLR_MCU_R5FSS0_CORE0_INTR_MCU_I2C0_POINTRPEND_0,
86 0, /* eventId */
87 #endif
88 #if defined (BUILD_C7X_1)
89 /* default configuration for I2C instance and DSP core on Main domain*/
90 (uint32_t)CSL_I2C0_CFG_BASE, /* baseAddr */
91 I2C_C7X_IRQ0, /* intNum */
92 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C0_POINTRPEND_0 + I2C_CLEC_GIC_SPI_IN_EVT_OFFSET, /* eventId, input event # to CLEC */
93 #endif
94 I2C_INPUT_CLK,
95 (bool)true,
96 {
97 /* default own slave addresses */
98 0x70, 0x0, 0x0, 0x0
99 },
100 I2C_configSocIntrPath
101 },
102 {
103 #if defined (BUILD_MPU)
104 (uint32_t)CSL_I2C1_CFG_BASE,
105 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C1_POINTRPEND_0,
106 0,
107 #endif
108 #if defined (BUILD_MCU)
109 (uint32_t)CSL_MCU_I2C1_CFG_BASE,
110 CSLR_MCU_R5FSS0_CORE0_INTR_MCU_I2C1_POINTRPEND_0,
111 0,
112 #endif
113 #if defined (BUILD_C7X_1)
114 /* default configuration for I2C instance and DSP core on Main domain*/
115 (uint32_t)CSL_I2C1_CFG_BASE, /* baseAddr */
116 I2C_C7X_IRQ0 + 1, /* intNum */
117 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C1_POINTRPEND_0 + I2C_CLEC_GIC_SPI_IN_EVT_OFFSET, /* eventId, input event # to CLEC */
118 #endif
119 I2C_INPUT_CLK,
120 (bool)true,
121 {
122 0x71, 0x0, 0x0, 0x0
123 },
124 I2C_configSocIntrPath
125 },
126 {
127 #if defined (BUILD_MPU)
128 (uint32_t)CSL_I2C2_CFG_BASE,
129 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C2_POINTRPEND_0,
130 0,
131 #endif
132 #if defined (BUILD_MCU)
133 0,
134 0,
135 0,
136 #endif
137 #if defined (BUILD_C7X_1)
138 /* default configuration for I2C instance and DSP core on Main domain*/
139 (uint32_t)CSL_I2C2_CFG_BASE, /* baseAddr */
140 I2C_C7X_IRQ0 + 2, /* intNum */
141 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C2_POINTRPEND_0 + I2C_CLEC_GIC_SPI_IN_EVT_OFFSET, /* eventId, input event # to CLEC */
142 #endif
143 I2C_INPUT_CLK,
144 (bool)true,
145 {
146 0x72, 0x0, 0x0, 0x0
147 },
148 I2C_configSocIntrPath
149 },
150 {
151 #if defined (BUILD_MPU)
152 (uint32_t)CSL_I2C3_CFG_BASE,
153 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C3_POINTRPEND_0,
154 0,
155 #endif
156 #if defined (BUILD_MCU)
157 0,
158 0,
159 0,
160 #endif
161 #if defined (BUILD_C7X_1)
162 /* default configuration for I2C instance and DSP core on Main domain*/
163 (uint32_t)CSL_I2C3_CFG_BASE, /* baseAddr */
164 I2C_C7X_IRQ0 + 3, /* intNum */
165 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C3_POINTRPEND_0 + I2C_CLEC_GIC_SPI_IN_EVT_OFFSET, /* eventId, input event # to CLEC */
166 #endif
167 I2C_INPUT_CLK,
168 (bool)true,
169 {
170 0x73, 0x0, 0x0, 0x0
171 },
172 I2C_configSocIntrPath
173 },
174 {
175 #if defined (BUILD_MPU)
176 (uint32_t)CSL_I2C4_CFG_BASE,
177 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C4_POINTRPEND_0,
178 0,
179 #endif
180 #if defined (BUILD_MCU)
181 0,
182 0,
183 0,
184 #endif
185 #if defined (BUILD_C7X_1)
186 /* default configuration for I2C instance and DSP core on Main domain*/
187 (uint32_t)CSL_I2C4_CFG_BASE, /* baseAddr */
188 I2C_C7X_IRQ0 + 4, /* intNum */
189 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C4_POINTRPEND_0 + I2C_CLEC_GIC_SPI_IN_EVT_OFFSET, /* eventId, input event # to CLEC */
190 #endif
191 I2C_INPUT_CLK,
192 (bool)true,
193 {
194 0x74, 0x0, 0x0, 0x0
195 },
196 I2C_configSocIntrPath
197 },
198 {
199 #if defined (BUILD_MPU)
200 (uint32_t)CSL_I2C5_CFG_BASE,
201 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C5_POINTRPEND_0,
202 0,
203 #endif
204 #if defined (BUILD_MCU)
205 0,
206 0,
207 0,
208 #endif
209 #if defined (BUILD_C7X_1)
210 /* default configuration for I2C instance and DSP core on Main domain*/
211 (uint32_t)CSL_I2C5_CFG_BASE, /* baseAddr */
212 I2C_C7X_IRQ0 + 5, /* intNum */
213 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C5_POINTRPEND_0 + I2C_CLEC_GIC_SPI_IN_EVT_OFFSET, /* eventId, input event # to CLEC */
214 #endif
215 I2C_INPUT_CLK,
216 (bool)true,
217 {
218 0x75, 0x0, 0x0, 0x0
219 },
220 I2C_configSocIntrPath
221 },
222 {
223 #if defined (BUILD_MPU)
224 (uint32_t)CSL_I2C6_CFG_BASE,
225 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C6_POINTRPEND_0,
226 0,
227 #endif
228 #if defined (BUILD_MCU)
229 0,
230 0,
231 0,
232 #endif
233 #if defined (BUILD_C7X_1)
234 /* default configuration for I2C instance and DSP core on Main domain*/
235 (uint32_t)CSL_I2C6_CFG_BASE, /* baseAddr */
236 I2C_C7X_IRQ0 + 6, /* intNum */
237 CSLR_COMPUTE_CLUSTER0_MSMC_1MB_GIC_SPI_I2C6_POINTRPEND_0 + I2C_CLEC_GIC_SPI_IN_EVT_OFFSET, /* eventId, input event # to CLEC */
238 #endif
239 I2C_INPUT_CLK,
240 (bool)true,
241 {
242 0x76, 0x0, 0x0, 0x0
243 },
244 I2C_configSocIntrPath
245 },
246 };
249 /* I2C objects */
250 I2C_v1_Object I2cObjects[I2C_HWIP_MAX_CNT];
253 /* I2C configuration structure */
254 CSL_PUBLIC_CONST I2C_config_list I2C_config = {
255 {
256 &I2C_v1_FxnTable,
257 &I2cObjects[0],
258 &i2cInitCfg[0]
259 },
261 {
262 &I2C_v1_FxnTable,
263 &I2cObjects[1],
264 &i2cInitCfg[1]
265 },
267 {
268 &I2C_v1_FxnTable,
269 &I2cObjects[2],
270 &i2cInitCfg[2]
271 },
273 {
274 &I2C_v1_FxnTable,
275 &I2cObjects[3],
276 &i2cInitCfg[3]
277 },
279 {
280 &I2C_v1_FxnTable,
281 &I2cObjects[4],
282 &i2cInitCfg[4]
283 },
285 {
286 &I2C_v1_FxnTable,
287 &I2cObjects[5],
288 &i2cInitCfg[5]
289 },
291 {
292 &I2C_v1_FxnTable,
293 &I2cObjects[6],
294 &i2cInitCfg[6]
295 },
296 {NULL, NULL, NULL},
297 {NULL, NULL, NULL},
298 {NULL, NULL, NULL},
299 {NULL, NULL, NULL},
300 {NULL, NULL, NULL},
301 {NULL, NULL, NULL},
302 {NULL, NULL, NULL}
303 };
305 /**
306 * \brief This API gets the SoC level of I2C intial configuration
307 *
308 * \param index I2C instance index.
309 * \param cfg Pointer to I2C SOC initial config.
310 *
311 * \return 0 success: -1: error
312 *
313 */
314 int32_t I2C_socGetInitCfg(uint32_t index, I2C_HwAttrs *cfg)
315 {
316 int32_t ret = 0;
318 if (index < I2C_HWIP_MAX_CNT)
319 {
320 *cfg = i2cInitCfg[index];
321 }
322 else
323 {
324 ret = (int32_t)(-1);
325 }
327 return ret;
328 }
330 /**
331 * \brief This API sets the SoC level of I2C intial configuration
332 *
333 * \param index I2C instance index.
334 * \param cfg Pointer to I2C SOC initial config.
335 *
336 * \return 0 success: -1: error
337 *
338 */
339 int32_t I2C_socSetInitCfg(uint32_t index, const I2C_HwAttrs *cfg)
340 {
341 int32_t ret = 0;
343 if (index < I2C_HWIP_MAX_CNT)
344 {
345 i2cInitCfg[index] = *cfg;
346 }
347 else
348 {
349 ret = (int32_t)(-1);
350 }
352 return ret;
353 }
355 #if defined (BUILD_MCU)
356 /**
357 * \brief This API update the default SoC level of configurations
358 * based on the core and domain
359 *
360 * i2cInitCfg table configures MCU domain's I2C instances by
361 * default for R5, I2C_socInit() is called in I2C_init() to
362 * overwrite the defaut configurations with the configurations
363 * of Main domain's UART instances if R5 is on the Main domain
364 *
365 * \param none
366 *
367 * \return none
368 *
369 */
370 void I2C_socInit(void);
371 void I2C_socInit(void)
372 {
373 uint32_t i;
374 CSL_ArmR5CPUInfo info;
376 CSL_armR5GetCpuID(&info);
377 if (info.grpId != (uint32_t)CSL_ARM_R5_CLUSTER_GROUP_ID_0)
378 {
379 /* Pulsar R5 core is on the Main domain */
380 for (i = 0; i < I2C_HWIP_MAX_CNT; i++)
381 {
382 /* Configure the Main SS UART instances for Main SS Pulsar R5 */
383 i2cInitCfg[i].baseAddr = (uint32_t)CSL_I2C0_CFG_BASE + (0x10000U * i);
385 if (i < 2U)
386 {
387 /* Main domain's I2C0-1 are directly connected to the MAIN Pulsar VIMs */
388 i2cInitCfg[i].intNum = CSLR_R5FSS0_CORE0_INTR_I2C0_POINTRPEND_0 + i;
389 }
390 }
391 }
392 }
393 #endif
395 static int32_t I2C_configSocIntrPath(const void *pHwAttrs, bool setIntrPath)
396 {
397 int32_t ret = I2C_STATUS_SUCCESS;
399 #if defined(BUILD_MCU)
400 struct tisci_msg_rm_irq_set_req rmIrqReq;
401 struct tisci_msg_rm_irq_set_resp rmIrqResp;
402 struct tisci_msg_rm_irq_release_req rmIrqRelease;
403 uint16_t src_id;
404 uint16_t src_index;
405 uint16_t dst_id;
406 CSL_ArmR5CPUInfo r5CpuInfo;
407 int32_t retVal;
408 I2C_HwAttrs const *hwAttrs = (I2C_HwAttrs const *)(pHwAttrs);
410 if (hwAttrs->baseAddr == CSL_WKUP_I2C0_CFG_BASE)
411 {
412 /*
413 * The interrupt path is established using the DMSC firmware
414 * for I2C instance 0 on wakeup domin
415 */
416 src_id = TISCI_DEV_WKUP_I2C0;
417 src_index = (uint16_t)hwAttrs->eventId; /* set to 0 for non-event based interrupt */
419 CSL_armR5GetCpuID(&r5CpuInfo);
420 if (r5CpuInfo.grpId == (uint32_t)CSL_ARM_R5_CLUSTER_GROUP_ID_1)
421 {
422 if(r5CpuInfo.cpuID == 0U)
423 {
424 dst_id = TISCI_DEV_R5FSS0_CORE0;
425 }
426 else
427 {
428 dst_id = TISCI_DEV_R5FSS0_CORE1;
429 }
430 }
431 else if (r5CpuInfo.grpId == (uint32_t)CSL_ARM_R5_CLUSTER_GROUP_ID_2)
432 {
433 if(r5CpuInfo.cpuID == 0U)
434 {
435 dst_id = TISCI_DEV_R5FSS1_CORE0;
436 }
437 else
438 {
439 dst_id = TISCI_DEV_R5FSS1_CORE1;
440 }
441 }
442 else
443 {
444 ret = I2C_STATUS_ERROR;
445 }
447 if (ret == I2C_STATUS_SUCCESS)
448 {
449 if(setIntrPath)
450 {
451 (void)memset (&rmIrqReq, 0, sizeof(rmIrqReq));
452 rmIrqReq.secondary_host = TISCI_MSG_VALUE_RM_UNUSED_SECONDARY_HOST;
453 rmIrqReq.src_id = src_id;
454 rmIrqReq.src_index = src_index;
456 /* Set the destination interrupt */
457 rmIrqReq.valid_params |= TISCI_MSG_VALUE_RM_DST_ID_VALID;
458 rmIrqReq.valid_params |= TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
460 /* Set the destination based on the core */
461 rmIrqReq.dst_id = dst_id;
462 rmIrqReq.dst_host_irq = (uint16_t)hwAttrs->intNum;
463 }
464 else
465 {
466 (void)memset (&rmIrqRelease,0,sizeof(rmIrqRelease));
467 rmIrqRelease.secondary_host = TISCI_MSG_VALUE_RM_UNUSED_SECONDARY_HOST;
468 rmIrqRelease.src_id = src_id;
469 rmIrqRelease.src_index = src_index;
471 /* Set the destination interrupt */
472 rmIrqRelease.valid_params |= TISCI_MSG_VALUE_RM_DST_ID_VALID;
473 rmIrqRelease.valid_params |= TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID;
475 /* Set the destination based on the core */
476 rmIrqRelease.dst_id = dst_id;
477 rmIrqRelease.dst_host_irq = (uint16_t)hwAttrs->intNum;
478 }
480 /* Config event */
481 if(setIntrPath)
482 {
483 retVal = Sciclient_rmIrqSet(
484 (const struct tisci_msg_rm_irq_set_req *)&rmIrqReq,
485 &rmIrqResp,
486 SCICLIENT_SERVICE_WAIT_FOREVER);
487 }
488 else
489 {
490 retVal = Sciclient_rmIrqRelease(
491 (const struct tisci_msg_rm_irq_release_req *)&rmIrqRelease,
492 SCICLIENT_SERVICE_WAIT_FOREVER);
493 }
494 if ((int32_t)0 != retVal)
495 {
496 ret = I2C_STATUS_ERROR;
497 }
498 }
499 }
500 #elif defined (BUILD_C7X_1)
501 int32_t retVal;
502 I2C_HwAttrs const *hwAttrs = (I2C_HwAttrs const *)(pHwAttrs);
503 CSL_ClecEventConfig cfgClec;
504 CSL_CLEC_EVTRegs *clecBaseAddr = (CSL_CLEC_EVTRegs *)CSL_COMPUTE_CLUSTER0_CLEC_REGS_BASE;
506 /* Configure CLEC for I2C0 */
507 cfgClec.secureClaimEnable = FALSE;
508 cfgClec.evtSendEnable = TRUE;
509 cfgClec.rtMap = CSL_CLEC_RTMAP_CPU_ALL;
510 cfgClec.extEvtNum = 0;
511 cfgClec.c7xEvtNum = hwAttrs->intNum;
512 retVal = CSL_clecConfigEvent(clecBaseAddr, hwAttrs->eventId, &cfgClec);
513 if (retVal != CSL_PASS)
514 {
515 ret = I2C_STATUS_ERROR;
516 }
517 #else
518 pHwAttrs = pHwAttrs;
519 setIntrPath = setIntrPath;
520 #endif
522 return(ret);
523 }