Skip to content

Commit fe10336

Browse files
committed
Add complete bank support for CMIS transceivers
This PR extends the bank parameter support introduced in PR #632 to fully enable multi-bank CMIS transceiver support throughout the stack. Changes include: 1. **Memory Map Bank Awareness**: - Updated CmisFlatMemMap, CmisMemMap, and CCmisMemMap to accept bank parameter - Implemented bank-aware getaddr() method in CmisFlatMemMap that correctly calculates linear offsets using the formula from sonic-linux-kernel PR #473 - Added bank property to CmisFlatMemMap for read-only access - Added constants: CMIS_EEPROM_PAGE_SIZE, CMIS_NUM_NON_BANKED_PAGES, CMIS_NUM_BANKED_PAGES, CMIS_ARCH_PAGES - Uses unified formula: linear_offset = (bank * CMIS_ARCH_PAGES + page) * page_size + offset - Each bank is treated as a full 256-page (32KB) architectural block for proper alignment 2. **API Factory Updates**: - Added bank parameter to create_xcvr_api() and _create_cmis_api() - Updated CMIS API instantiation to pass bank parameter to memory maps - Modified id_mapping to pass bank parameter for all CMIS module types (0x18, 0x19, 0x1b, 0x1e) 3. **SfpBase Integration**: - Updated refresh_xcvr_api() to pass bank parameter when creating xcvr_api 4. **Field Definitions**: - Added BANKS_SUPPORTED_FIELD constant to consts.py - Added BanksSupported field to MODULE_CHAR_ADVT in CmisMemMap This enables proper support for CMIS modules with multiple memory banks, allowing correct EEPROM access across all banks as defined in the CMIS specification. The offset calculation formula matches the optoe kernel driver implementation in sonic-linux-kernel PR #473. Signed-off-by: Bobby McGonigle <bobby@nexthop.ai>
1 parent be9ef4d commit fe10336

5 files changed

Lines changed: 55 additions & 18 deletions

File tree

sonic_platform_base/sfp_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ def refresh_xcvr_api(self):
473473
"""
474474
Updates the XcvrApi associated with this SFP
475475
"""
476-
self._xcvr_api = self._xcvr_api_factory.create_xcvr_api()
476+
self._xcvr_api = self._xcvr_api_factory.create_xcvr_api(bank=self.bank)
477477

478478
def get_xcvr_api(self):
479479
"""

sonic_platform_base/sonic_xcvr/fields/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@
182182
MODULE_PWRDN_DURATION = "ModulePowerDownDuration"
183183
DP_TX_TURNON_DURATION = "DPTxTurnOnDuration"
184184
DP_TX_TURNOFF_DURATION = "DPTxTurnOffDuration"
185+
BANKS_SUPPORTED_FIELD = "BanksSupported"
185186

186187
# DOM
187188
TRANS_DOM_FIELD = "TransceiverDom"

sonic_platform_base/sonic_xcvr/mem_maps/public/c_cmis.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from .cmis import CmisMemMap
1313

1414
class CCmisMemMap(CmisMemMap):
15-
def __init__(self, codes):
16-
super(CCmisMemMap, self).__init__(codes)
15+
def __init__(self, codes, bank=0):
16+
super(CCmisMemMap, self).__init__(codes, bank=bank)
1717

1818
self.MODULE_CONFIG_SUPPORT = RegGroupField(consts.MODULE_CONFIG_SUPPORT_FIELD,
1919
NumberRegField(consts.SUPPORT_GRID, self.getaddr(0x4, 128)),

sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@
1919
from ...fields.consts import *
2020
from ...fields.public.cmis import CableLenField
2121

22+
# Constants matching optoe driver
23+
CMIS_EEPROM_PAGE_SIZE = 128
24+
CMIS_NUM_NON_BANKED_PAGES = 16 # pages 00h-0Fh
25+
CMIS_NUM_BANKED_PAGES = 240 # pages 10h-FFh
26+
CMIS_ARCH_PAGES = 256 # architectural pages per bank (matches OPTOE_ARCH_PAGES)
27+
2228
class CmisFlatMemMap(XcvrMemMap):
2329
"""
2430
Memory map for CMIS flat memory (Lower page and Upper page 0h ONLY)
2531
"""
26-
def __init__(self, codes):
32+
def __init__(self, codes, bank=0):
33+
self._bank = bank
2734
super(CmisFlatMemMap, self).__init__(codes)
2835

2936
self.MGMT_CHARACTERISTICS = RegGroupField(consts.MGMT_CHAR_FIELD,
@@ -138,12 +145,41 @@ def __init__(self, codes):
138145
NumberRegField(consts.MODULE_LEVEL_CONTROL, self.getaddr(0x0, 26), size=1, ro=False),
139146
)
140147

148+
@property
149+
def bank(self):
150+
"""Returns the bank number (read-only)."""
151+
return self._bank
152+
141153
def getaddr(self, page, offset, page_size=128):
142-
return page * page_size + offset
154+
"""
155+
Calculate linear offset for optoe driver using instance's bank.
156+
157+
For lower memory (page 0, offset < 128):
158+
linear_offset = offset
159+
160+
For paged memory:
161+
offset_in_paged_area = (page * page_size + offset) - 128
162+
bytes_per_bank = CMIS_ARCH_PAGES * page_size (256 * 128 = 32KB)
163+
linear_offset = 128 + (bank * bytes_per_bank) + offset_in_paged_area
164+
165+
Simplified:
166+
linear_offset = (bank * CMIS_ARCH_PAGES + page) * page_size + offset
167+
168+
Note: Each bank is treated as a full 256-page (32KB) architectural block,
169+
even though only pages 10h-FFh (240 pages) are actually banked. This ensures
170+
proper alignment and matches the kernel driver behavior.
171+
"""
172+
if page == 0 and offset < 128:
173+
# Lower memory - not affected by banking
174+
return offset
175+
176+
# For all paged memory (including bank 0), use the unified formula
177+
# that treats each bank as a 256-page (32KB) block
178+
return (self.bank * CMIS_ARCH_PAGES + page) * page_size + offset
143179

144180
class CmisMemMap(CmisFlatMemMap):
145-
def __init__(self, codes):
146-
super(CmisMemMap, self).__init__(codes)
181+
def __init__(self, codes, bank=0):
182+
super(CmisMemMap, self).__init__(codes, bank=bank)
147183

148184
# This memmap should contain ONLY upper page >= 01h fields
149185
self.ADVERTISING = RegGroupField(consts.ADVERTISING_FIELD,
@@ -227,6 +263,9 @@ def __init__(self, codes):
227263
RegBitField(consts.VDM_SUPPORTED, 6),
228264
RegBitField(consts.DIAG_PAGE_SUPPORT_ADVT_FIELD, 5),
229265
),
266+
NumberRegField(consts.BANKS_SUPPORTED_FIELD, self.getaddr(0x1, 142),
267+
*(RegBitField("Bit%d" % bit, bit) for bit in range(0, 2))
268+
),
230269
NumberRegField(consts.TX_INPUT_EQ_MAX, self.getaddr(0x1, 153),
231270
*(RegBitField("Bit%d" % (bit), bit) for bit in range (0 , 4))
232271
),
@@ -702,6 +741,3 @@ def __init__(self, codes):
702741
)
703742

704743
# TODO: add remaining fields
705-
706-
def getaddr(self, page, offset, page_size=128):
707-
return page * page_size + offset

sonic_platform_base/sonic_xcvr/xcvr_api_factory.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def _get_vendor_part_num(self):
7575
vendor_pn = part_num.decode('utf-8', errors='ignore')
7676
return vendor_pn.strip()
7777

78-
def _create_cmis_api(self):
78+
def _create_cmis_api(self, bank=0):
7979
api = None
8080
vendor_name = self._get_vendor_name()
8181
vendor_pn = self._get_vendor_part_num()
@@ -86,10 +86,10 @@ def _create_cmis_api(self):
8686
('EOPTOLINK' in vendor_name and vendor_pn in EOP_800G_VENDOR_PN_LIST):
8787
api = self._create_api(CmisCodes, CmisMemMap, CmisFr800gApi)
8888
else:
89-
xcvr_eeprom = XcvrEeprom(self.reader, self.writer, CmisMemMap(CmisCodes))
89+
xcvr_eeprom = XcvrEeprom(self.reader, self.writer, CmisMemMap(CmisCodes, bank=bank))
9090
api = CmisApi(xcvr_eeprom, init_cdb_fw_handler=True)
9191
if api.is_coherent_module():
92-
xcvr_eeprom = XcvrEeprom(self.reader, self.writer, CCmisMemMap(CmisCodes))
92+
xcvr_eeprom = XcvrEeprom(self.reader, self.writer, CCmisMemMap(CmisCodes, bank=bank))
9393
api = CCmisApi(xcvr_eeprom, init_cdb_fw_handler=True)
9494
return api
9595

@@ -109,18 +109,18 @@ def _create_api(self, codes_class, mem_map_class, api_class):
109109
xcvr_eeprom = XcvrEeprom(self.reader, self.writer, mem_map)
110110
return api_class(xcvr_eeprom)
111111

112-
def create_xcvr_api(self):
112+
def create_xcvr_api(self, bank=0):
113113
id = self._get_id()
114114

115115
# Instantiate various Optics implementation based upon their respective ID as per SFF8024
116116
id_mapping = {
117117
0x03: (self._create_api, (Sff8472Codes, Sff8472MemMap, Sff8472Api)),
118118
0x0D: (self._create_qsfp_api, ()),
119119
0x11: (self._create_api, (Sff8636Codes, Sff8636MemMap, Sff8636Api)),
120-
0x18: (self._create_cmis_api, ()),
121-
0x19: (self._create_cmis_api, ()),
122-
0x1b: (self._create_cmis_api, ()),
123-
0x1e: (self._create_cmis_api, ()),
120+
0x18: (self._create_cmis_api, (bank,)),
121+
0x19: (self._create_cmis_api, (bank,)),
122+
0x1b: (self._create_cmis_api, (bank,)),
123+
0x1e: (self._create_cmis_api, (bank,)),
124124
0x7e: (self._create_api, (AmphBackplaneCodes,
125125
AmphBackplaneMemMap, AmphBackplaneImpl)),
126126
}

0 commit comments

Comments
 (0)