@@ -163,31 +163,36 @@ def __init__(self, pin, peripheral_map):
163163 """
164164 self ._name = pin .attrib ['name' ]
165165 self ._properties = self ._get_pin_properties (pin .find ('functional_properties' ))
166- cfg_assign_xml = pin .find ('functional_properties/functional_property/'
167- 'state/configuration/assign' )
166+ functional_prop = pin .find ('functional_properties/functional_property' )
167+ cfg_assign_xml = functional_prop . find ( 'state/configuration/assign' )
168168 self ._iomuxc_options = {}
169169 if cfg_assign_xml is None :
170170 # Not a configurable register. Skip.
171171 return
172172 match = re .match (r'init_([\w_]+)' , cfg_assign_xml .attrib ['configuration_step' ])
173173 periph_name = match .group (1 )
174- match = re .match (re .escape (periph_name ) + r'_(\w+)' , cfg_assign_xml .attrib ['register' ])
175- reg_name = match .group (1 )
176- cfg_addr = peripheral_map [periph_name ].get_reg_addr (reg_name )
174+ if functional_prop .attrib .get ('id' ) != 'software_input_on' :
175+ match = re .match (re .escape (periph_name ) + r'_(\w+)' , cfg_assign_xml .attrib ['register' ])
176+ reg_name = match .group (1 )
177+ match = re .match (r'SW_PAD_CTL_PAD_(\w+)' , reg_name )
178+ pad_name = match .group (1 )
179+ cfg_addr = peripheral_map [periph_name ].get_reg_addr (reg_name )
180+ else :
181+ # This pad has mux options, but no configuration settings.
182+ cfg_addr = 0x0
183+ pad_name = self ._name
177184 for connections in pin .findall ('connections' ):
185+ name_part = connections .attrib .get ('name_part' )
178186 connection = connections .find ('connection' )
179- iomux_opt = IOMUXOption (connection , peripheral_map , cfg_addr )
187+ name = f"{ periph_name } _{ pad_name } _{ name_part } "
188+ iomux_opt = IOMUXOption (connection , peripheral_map , cfg_addr , name )
180189 peripheral = connection .find ('peripheral_signal_ref' ).attrib ['peripheral' ]
181190 signal = connection .find ('peripheral_signal_ref' ).attrib ['signal' ]
182191 channel = connection .find ('peripheral_signal_ref' ).attrib .get ('channel' )
183192 if channel is not None :
184193 mux_name = f"{ peripheral } _{ signal } , { channel } "
185194 else :
186195 mux_name = f"{ peripheral } _{ signal } "
187- if iomux_opt .get_name () == '' :
188- # Use the default name of {peripheral_name}_{pin_name}
189- iomux_opt = IOMUXOption (connection ,
190- peripheral_map , cfg_addr , name = f"{ periph_name } _{ self ._name } " )
191196 self ._iomuxc_options [mux_name ] = iomux_opt
192197
193198 def __repr__ (self ):
@@ -289,11 +294,14 @@ def _get_pin_properties(self, props):
289294 return prop_mapping
290295
291296
297+ # named tuple for GPIO port/pin
298+ GPIO = collections .namedtuple ('GPIO' , 'port pin' )
299+
292300class IOMUXOption :
293301 """
294302 Internal class representing an IOMUXC option
295303 """
296- def __init__ (self , connection , peripheral_map , cfg_reg , name = '' ):
304+ def __init__ (self , connection , peripheral_map , cfg_reg , name ):
297305 """
298306 Initializes an IOMUXC option object
299307 @param connection: connection XML object from signal_configuration.xml
@@ -309,8 +317,20 @@ def __init__(self, connection, peripheral_map, cfg_reg, name = ''):
309317 self ._daisy_val = 0
310318 self ._cfg_reg = cfg_reg
311319 self ._has_extended_config = False
320+ self ._has_gpr = False
312321 self ._extended_config = []
313322 self ._name = name
323+ # Check if this connection controls a GPIO
324+ peripheral = connection .find ('peripheral_signal_ref' ).attrib .get ('peripheral' )
325+ channel = connection .find ('peripheral_signal_ref' ).attrib .get ('channel' )
326+ if 'GPIO' in peripheral and channel is not None :
327+ match = re .search (r'GPIO(\d+)' , peripheral )
328+ gpio_port = match .group (1 )
329+ self ._is_gpio = True
330+ self ._gpio = GPIO (int (gpio_port ), int (channel ))
331+ else :
332+ self ._is_gpio = False
333+ self ._gpio = (0 , 0 )
314334 # Get connection register names
315335 for assignment in connection .findall ('configuration/assign' ):
316336 match = re .match (r'init_([\w_]+)' , assignment .attrib ['configuration_step' ])
@@ -321,22 +341,21 @@ def __init__(self, connection, peripheral_map, cfg_reg, name = ''):
321341 periph = peripheral_map [periph_name ]
322342 addr = periph .get_reg_addr (reg_name )
323343 value = int (assignment .attrib ['bit_field_value' ], 0 )
324- if not 'bit_field' in assignment .attrib :
325- # Add register name and bit field value to extra configuration
326- self ._has_extended_config = True
327- config = {full_name : assignment .attrib ['bit_field_value' ]}
328- self ._extended_config .append (config )
329- continue
330- if assignment .attrib ['bit_field' ] == 'DAISY' :
344+ if assignment .attrib .get ('bit_field' ) == 'DAISY' :
331345 self ._daisy = addr
332346 self ._daisy_val = value
333- elif assignment .attrib [ 'bit_field' ] == 'MUX_MODE' :
347+ elif assignment .attrib . get ( 'bit_field' ) == 'MUX_MODE' :
334348 self ._mux = addr
335349 self ._mux_val = value
336- register = periph .get_register (reg_name )
337- # Create IOMUXC name for this connection
338- if self ._name == '' :
339- self ._name = self ._generate_iomuxc_name (periph , register , value )
350+ elif periph_name == 'IOMUXC_GPR' :
351+ # GPR register can be used as a secondary pinmux selection,
352+ # record this setting
353+ self ._has_gpr = True
354+ self ._gpr_reg = addr
355+ gpr_mask = int (assignment .attrib .get ('bit_field_mask' ), 0 )
356+ # Calculate gpr bit shift
357+ self ._gpr_shift = ((gpr_mask ) & - (gpr_mask )).bit_length () - 1
358+ self ._gpr_val = int (assignment .attrib .get ('bit_field_value' ), 0 )
340359 else :
341360 # Add register name and bit field value to extra configuration
342361 self ._has_extended_config = True
@@ -349,6 +368,8 @@ def __repr__(self):
349368 """
350369 if self ._has_extended_config :
351370 return "IOMUXOpt(%s, 0x%X = %d, ExtCfg)" % (self ._name , self ._mux , self ._mux_val )
371+ elif self ._has_gpr :
372+ return "IOMUXOpt(%s, 0x%X = %d, GPR)" % (self ._name , self ._mux , self ._mux_val )
352373 return "IOMUXOpt(%s, 0x%X = %d)" % (self ._name , self ._mux , self ._mux_val )
353374
354375 def __hash__ (self ):
@@ -387,7 +408,20 @@ def get_mux_reg(self):
387408 Get the mux reg for this iomux option
388409 """
389410 return self ._mux
390-
411+
412+ def is_gpio (self ):
413+ """
414+ return True if this iomux option is for a GPIO
415+ """
416+ return self ._is_gpio
417+
418+ def gpio (self ):
419+ """
420+ Get iomux gpio port and pin as a tuple of (port,pin)
421+ only valid if is_gpio is True
422+ """
423+ return self ._gpio
424+
391425 def get_mux_val (self ):
392426 """
393427 Get the mux value for this iomux option
@@ -412,6 +446,30 @@ def get_cfg_reg(self):
412446 """
413447 return self ._cfg_reg
414448
449+ def has_gpr (self ):
450+ """
451+ Return true if iomux option has associated GPR configuration requirement
452+ """
453+ return self ._has_gpr
454+
455+ def gpr_reg (self ):
456+ """
457+ If has_gpr() is true, return GPR register address
458+ """
459+ return self ._gpr_reg
460+
461+ def gpr_shift (self ):
462+ """
463+ If has_gpr() is true, return shift on GPR register value
464+ """
465+ return self ._gpr_shift
466+
467+ def gpr_val (self ):
468+ """
469+ If has_gpr() is true, return GPR register value
470+ """
471+ return self ._gpr_val
472+
415473 def has_extended_config (self ):
416474 """
417475 Return true if the iomux option requires extended register configuration
@@ -424,21 +482,6 @@ def get_extended_config(self):
424482 """
425483 return self ._extended_config
426484
427- def _generate_iomuxc_name (self , periph , reg , mux_val ):
428- """
429- Extracts the iomuxc name for a connection from the SW_MUX_CTL_PAD
430- register that is being set. The register description is used to generate
431- the final iomuxc name, like in MCUXpresso config tools
432- @param periph: peripheral object with the SW_MUX_CTL_PAD register
433- @param reg: register object holding the SW_MUX_CTL_PAD register object
434- @param mux_val: mux value being selected in register
435- """
436- pad_name = re .match (r'SW_MUX_CTL_PAD_(\w+)' , reg .get_name ()).group (1 )
437- description = reg .get_bit_field_value_description ('MUX_MODE' , mux_val )
438- mux_name = re .search (r': (\w+) of instance' , description ).group (1 )
439- return f"{ periph .get_name ()} _{ pad_name } _{ mux_name } "
440-
441-
442485class PinGroup :
443486 """
444487 Internal class representing pin group
@@ -680,6 +723,54 @@ def get_part_num(self):
680723 """
681724 return self ._soc_sku
682725
726+ def write_gpio_mux (self , outputfile ):
727+ """
728+ Write pinctrl defintions for GPIO mux. These defintions map GPIO port
729+ and pin combinations to iomuxc options. Note that these defintions are
730+ not indended to be used directly, and will likely need to be hand edited.
731+ @param outputfile file to write gpio dtsi file to
732+ """
733+ # Layered dictionary of gpio mux options. The root keys
734+ # are the port names, and those port names map to
735+ # dictionaries of pin->iomux option mappings
736+ gpio_map = collections .defaultdict (lambda : {})
737+ with open (outputfile , "w" , encoding = 'utf8' ) as gpio_dsti :
738+ # Write header
739+ gpio_dsti .write (f"/*\n "
740+ f" * File created by { os .path .basename (__file__ )} \n "
741+ " * not intended for direct usage. Hand edit these DTS\n "
742+ " * nodes as needed to integrate them into Zephyr.\n "
743+ " */\n \n " )
744+ for pin in sorted (self ._signal_map .values ()):
745+ for iomux_opt in sorted (pin .get_mux_options ()):
746+ if iomux_opt .is_gpio ():
747+ gpio = iomux_opt .gpio ()
748+ if 'CM7' in iomux_opt .get_name ():
749+ gpio_map [f"{ gpio .port } _CM7" ][gpio .pin ] = iomux_opt
750+ else :
751+ gpio_map [str (gpio .port )][gpio .pin ] = iomux_opt
752+ # Now write SOC level GPIO pinmux definitions. These are required
753+ # so that gpio driver is capable of selecting pinmux options when
754+ # a gpio pin is configured.
755+ gpio_dsti .write ("/*\n "
756+ " * GPIO pinmux options. These options define the pinmux settings\n "
757+ " * for GPIO ports on the package, so that the GPIO driver can\n "
758+ " * select GPIO mux options during GPIO configuration.\n "
759+ " */\n \n " )
760+ for port in sorted (gpio_map ):
761+ dts_node = (f"&gpio{ port } {{\n "
762+ "\t pinmux = " )
763+ for pin in sorted (gpio_map [port ]):
764+ iomux_opt = gpio_map [port ][pin ]
765+ dts_node += f"<&{ iomux_opt .get_name ().lower ()} >,\n \t \t "
766+ dts_node = re .sub (r',\n\t\t$' , ";\n " , dts_node )
767+ # end group
768+ dts_node += "};\n \n "
769+ gpio_dsti .write (dts_node )
770+ gpio_dsti .close ()
771+
772+
773+
683774 def write_pinctrl_defs (self , outputfile ):
684775 """
685776 Writes a pinctrl dtsi file that defines all pinmux options. The board
@@ -743,11 +834,16 @@ def write_pinctrl_defs(self, outputfile):
743834 print (f"Warning: unmatched signal pin name { iomuxc_name } " )
744835 reg_type = ''
745836 dts_node += f"\t \t { reg_type } ;\n "
837+ if iomux_opt .has_gpr ():
838+ gpr_reg = iomux_opt .gpr_reg ()
839+ gpr_shift = iomux_opt .gpr_shift ()
840+ gpr_val = iomux_opt .gpr_val ()
841+ # Add GPR configuration
842+ dts_node += f"\t \t gpr = <0x{ gpr_reg :x} 0x{ gpr_shift :x} 0x{ gpr_val :x} >;\n "
746843 dts_node += "\t };\n "
747844 # Write iomuxc dts node to file
748845 soc_dtsi .write (dts_node )
749- soc_dtsi .write ("};\n \n " )
750- soc_dtsi .close ()
846+ soc_dtsi .write ("};\n \n " )
751847
752848 def write_pinctrl_groups (self , mexfile , outputfile ):
753849 """
@@ -876,10 +972,9 @@ def _load_signal_map(self, xml):
876972 iomuxc_options = {}
877973 for pad in pads :
878974 pad_name = pad .attrib ['name' ]
879- if len (pad .findall ('functional_properties/functional_property' )) == 0 :
880- # Not a configurable pad. Continue
881- continue
882- iomuxc_options [pad_name ] = SignalPin (pad , self ._peripheral_map )
975+ # Verify signal pad is configurable
976+ if len (pad .findall ('functional_properties/functional_property' )) != 0 :
977+ iomuxc_options [pad_name ] = SignalPin (pad , self ._peripheral_map )
883978 return iomuxc_options
884979
885980
0 commit comments