88#include <stdbool.h>
99#include <stdint.h>
1010
11+ #include "hw/top/dt/dt_i2c.h"
12+ #include "hw/top/dt/dt_pinmux.h"
1113#include "sw/device/lib/base/mmio.h"
1214#include "sw/device/lib/dif/dif_i2c.h"
1315#include "sw/device/lib/dif/dif_pinmux.h"
1820#include "sw/device/lib/testing/test_framework/check.h"
1921
2022#include "hw/top/i2c_regs.h" // Generated.
21- #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
2223
2324#define MODULE_ID MAKE_MODULE_ID('i', 'i', 't')
2425
@@ -35,126 +36,78 @@ static const dif_i2c_fmt_flags_t kDefaultFlags = {.start = false,
3536 .suppress_nak_irq = false};
3637
3738/**
38- * Define an i2c pinmux configuration.
39+ * Get the I2C instance from index.
40+ *
41+ * @param i2c_idx I2C index (0-based).
42+ * @return I2C DT instance, or kDtI2cCount if invalid.
3943 */
40- typedef struct i2c_pinmux_pins {
41- pinmux_testutils_peripheral_pin_t sda ;
42- pinmux_testutils_peripheral_pin_t scl ;
43- } i2c_pinmux_pins_t ;
44-
45- /**
46- * Define an i2c pinmux configuration.
47- */
48- typedef struct i2c_platform_pins {
49- pinmux_testutils_mio_pin_t sda ;
50- pinmux_testutils_mio_pin_t scl ;
51- } i2c_platform_pins_t ;
52-
53- /**
54- * This table store the pins of all i2c instances of Earlgrey.
55- * This is used to connect i2c instances to mio pins based on the platform.
56- */
57- static const i2c_pinmux_pins_t kI2cPinmuxPins [] = {
58- // I2C0.
59- {.sda =
60- {
61- .peripheral_in = kTopEarlgreyPinmuxPeripheralInI2c0Sda ,
62- .outsel = kTopEarlgreyPinmuxOutselI2c0Sda ,
63- },
64- .scl =
65- {
66- .peripheral_in = kTopEarlgreyPinmuxPeripheralInI2c0Scl ,
67- .outsel = kTopEarlgreyPinmuxOutselI2c0Scl ,
68- }},
69- // I2C1.
70- {.sda =
71- {
72- .peripheral_in = kTopEarlgreyPinmuxPeripheralInI2c1Sda ,
73- .outsel = kTopEarlgreyPinmuxOutselI2c1Sda ,
74- },
75- .scl =
76- {
77- .peripheral_in = kTopEarlgreyPinmuxPeripheralInI2c1Scl ,
78- .outsel = kTopEarlgreyPinmuxOutselI2c1Scl ,
79- }},
80- // I2C2.
81- {.sda =
82- {
83- .peripheral_in = kTopEarlgreyPinmuxPeripheralInI2c2Sda ,
84- .outsel = kTopEarlgreyPinmuxOutselI2c2Sda ,
85- },
86- .scl =
87- {
88- .peripheral_in = kTopEarlgreyPinmuxPeripheralInI2c2Scl ,
89- .outsel = kTopEarlgreyPinmuxOutselI2c2Scl ,
90- }},
91- };
44+ static dt_i2c_t get_i2c_instance (uint8_t i2c_idx ) {
45+ if (i2c_idx >= kDtI2cCount ) {
46+ return kDtI2cCount ;
47+ }
48+ return (dt_i2c_t )i2c_idx ;
49+ }
9250
9351/**
94- * Map the combination of platform and I2C ID to pins for SCL and SDA.
52+ * Get the appropriate pads for an I2C instance and platform based on the
53+ * platform. This replicates the original behavior with different mappings for
54+ * different platforms.
55+ *
56+ * @param i2c_dt I2C DT instance.
57+ * @param platform The platform to connect the I2C to.
58+ * @param sda_pad Output parameter for SDA pad.
59+ * @param scl_pad Output parameter for SCL pad.
60+ * @return OK_STATUS if successful, error status otherwise.
9561 */
96- static status_t map_platform_to_pins (i2c_pinmux_platform_id_t platform ,
97- uint8_t i2c_id ,
98- i2c_platform_pins_t * pins ) {
99- TRY_CHECK (pins != NULL );
62+ static status_t get_i2c_pads_for_platform (dt_i2c_t i2c_dt ,
63+ i2c_pinmux_platform_id_t platform ,
64+ dt_pad_t * sda_pad ,
65+ dt_pad_t * scl_pad ) {
66+ #if defined(OPENTITAN_IS_DARJEELING )
67+ // Darjeeling only has I2C0 and uses dedicated pads
68+ if (i2c_dt != kDtI2c0 ) {
69+ return INVALID_ARGUMENT ();
70+ }
71+ * sda_pad = kDtPadI2c0Sda ;
72+ * scl_pad = kDtPadI2c0Scl ;
73+ #elif defined(OPENTITAN_IS_EARLGREY ) || defined(OPENTITAN_IS_ENGLISHBREAKFAST )
74+ // For Earlgrey and EnglishBreakfast platforms
10075 switch (platform ) {
10176 case I2cPinmuxPlatformIdHyper310 : // CW310 HyperDebug
102- * pins =
103- (i2c_platform_pins_t ){.sda =
104- {
105- .mio_out = kTopEarlgreyPinmuxMioOutIoa7 ,
106- .insel = kTopEarlgreyPinmuxInselIoa7 ,
107- },
108- .scl = {
109- .mio_out = kTopEarlgreyPinmuxMioOutIoa8 ,
110- .insel = kTopEarlgreyPinmuxInselIoa8 ,
111- }};
77+ * sda_pad = kDtPadIoa7 ;
78+ * scl_pad = kDtPadIoa8 ;
11279 break ;
11380 case I2cPinmuxPlatformIdDvsim : // DV
11481 // In DV, there's one agent for each I2C instance, with a fixed set of
11582 // muxed pins.
116- switch (i2c_id ) {
117- case 0 : // I2C0 uses the same pins as CW310 HyperDebug
118- TRY (map_platform_to_pins (I2cPinmuxPlatformIdHyper310 , i2c_id , pins ));
83+ switch (i2c_dt ) {
84+ case kDtI2c0 : // I2C0 uses the same pins as CW310 HyperDebug
85+ * sda_pad = kDtPadIoa7 ;
86+ * scl_pad = kDtPadIoa8 ;
11987 break ;
120- case 1 :
121- * pins = (i2c_platform_pins_t ){
122- .sda =
123- {
124- .mio_out = kTopEarlgreyPinmuxMioOutIob10 ,
125- .insel = kTopEarlgreyPinmuxInselIob10 ,
126- },
127- .scl =
128- {
129- .mio_out = kTopEarlgreyPinmuxMioOutIob9 ,
130- .insel = kTopEarlgreyPinmuxInselIob9 ,
131- },
132- };
88+ case kDtI2c1 :
89+ * sda_pad = kDtPadIob10 ;
90+ * scl_pad = kDtPadIob9 ;
13391 break ;
134- case 2 : // I2C2 uses the same pins as CW310 PMOD
135- TRY (map_platform_to_pins (I2cPinmuxPlatformIdCw310Pmod , i2c_id , pins ));
92+ case kDtI2c2 : // I2C2 uses the same pins as CW310 PMOD
93+ * sda_pad = kDtPadIob12 ;
94+ * scl_pad = kDtPadIob11 ;
13695 break ;
13796 default :
138- TRY_CHECK (false, "invalid i2c_id: %0d" , i2c_id );
139- break ;
97+ return INVALID_ARGUMENT ();
14098 }
14199 break ;
142100 case I2cPinmuxPlatformIdCw310Pmod : // CW310 PMOD
143- * pins = (i2c_platform_pins_t ){
144- .sda =
145- {
146- .mio_out = kTopEarlgreyPinmuxMioOutIob12 ,
147- .insel = kTopEarlgreyPinmuxInselIob12 ,
148- },
149- .scl = {
150- .mio_out = kTopEarlgreyPinmuxMioOutIob11 ,
151- .insel = kTopEarlgreyPinmuxInselIob11 ,
152- }};
101+ * sda_pad = kDtPadIob12 ;
102+ * scl_pad = kDtPadIob11 ;
153103 break ;
154104 default :
155- TRY_CHECK (false, "invalid platform: %0d" , platform );
156- break ;
105+ return INVALID_ARGUMENT ();
157106 }
107+ #else
108+ return UNIMPLEMENTED ();
109+ #endif
110+
158111 return OK_STATUS ();
159112}
160113
@@ -344,34 +297,43 @@ status_t i2c_testutils_target_check_write(const dif_i2c_t *i2c,
344297
345298status_t i2c_testutils_select_pinmux (const dif_pinmux_t * pinmux , uint8_t i2c_id ,
346299 i2c_pinmux_platform_id_t platform ) {
347- TRY_CHECK (
348- platform < I2cPinmuxPlatformIdCount && i2c_id < ARRAYSIZE (kI2cPinmuxPins ),
349- "Index out of bounds" );
350- i2c_platform_pins_t platform_pins ;
351- TRY (map_platform_to_pins (platform , i2c_id , & platform_pins ));
352- // Configure sda pin.
353- TRY (dif_pinmux_input_select (pinmux , kI2cPinmuxPins [i2c_id ].sda .peripheral_in ,
354- platform_pins .sda .insel ));
355- TRY (dif_pinmux_output_select (pinmux , platform_pins .sda .mio_out ,
356- kI2cPinmuxPins [i2c_id ].sda .outsel ));
357-
358- // Configure scl pin.
359- TRY (dif_pinmux_input_select (pinmux , kI2cPinmuxPins [i2c_id ].scl .peripheral_in ,
360- platform_pins .scl .insel ));
361- TRY (dif_pinmux_output_select (pinmux , platform_pins .scl .mio_out ,
362- kI2cPinmuxPins [i2c_id ].scl .outsel ));
300+ TRY_CHECK (platform < I2cPinmuxPlatformIdCount , "Platform out of bounds" );
301+
302+ dt_i2c_t i2c_dt = get_i2c_instance (i2c_id );
303+ TRY_CHECK (i2c_dt < kDtI2cCount , "I2C index out of bounds" );
304+
305+ // Get peripheral I/O descriptions for SDA and SCL
306+ dt_periph_io_t sda_periph_io = dt_i2c_periph_io (i2c_dt , kDtI2cPeriphIoSda );
307+ dt_periph_io_t scl_periph_io = dt_i2c_periph_io (i2c_dt , kDtI2cPeriphIoScl );
308+
309+ // Get the appropriate pads for this I2C instance and platform
310+ dt_pad_t sda_pad , scl_pad ;
311+ TRY (get_i2c_pads_for_platform (i2c_dt , platform , & sda_pad , & scl_pad ));
312+
313+ // Connect SDA and SCL using pinmux testutils
314+ TRY (pinmux_testutils_connect (pinmux , sda_periph_io , kDtPeriphIoDirInout ,
315+ sda_pad ));
316+ TRY (pinmux_testutils_connect (pinmux , scl_periph_io , kDtPeriphIoDirInout ,
317+ scl_pad ));
318+
363319 return OK_STATUS ();
364320}
365321
366322status_t i2c_testutils_detach_pinmux (const dif_pinmux_t * pinmux ,
367323 uint8_t i2c_id ) {
368- // Configure sda pin.
369- TRY (dif_pinmux_input_select (pinmux , kI2cPinmuxPins [i2c_id ].sda .peripheral_in ,
370- kTopEarlgreyPinmuxInselConstantZero ));
324+ dt_i2c_t i2c_dt = get_i2c_instance (i2c_id );
325+ TRY_CHECK (i2c_dt < kDtI2cCount , "I2C index out of bounds" );
326+
327+ // Get peripheral I/O descriptions for SDA and SCL
328+ dt_periph_io_t sda_periph_io = dt_i2c_periph_io (i2c_dt , kDtI2cPeriphIoSda );
329+ dt_periph_io_t scl_periph_io = dt_i2c_periph_io (i2c_dt , kDtI2cPeriphIoScl );
330+
331+ // Disconnect SDA and SCL inputs by connecting to constant zero
332+ TRY (pinmux_testutils_connect (pinmux , sda_periph_io , kDtPeriphIoDirIn ,
333+ kDtPadConstantZero ));
334+ TRY (pinmux_testutils_connect (pinmux , scl_periph_io , kDtPeriphIoDirIn ,
335+ kDtPadConstantZero ));
371336
372- // Configure scl pin.
373- TRY (dif_pinmux_input_select (pinmux , kI2cPinmuxPins [i2c_id ].scl .peripheral_in ,
374- kTopEarlgreyPinmuxInselConstantZero ));
375337 return OK_STATUS ();
376338}
377339
0 commit comments