X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fspec%2Finterfaces.py;h=684173edb6a5a7548a1189dca9359a8c63e5ff5b;hb=d19093c4a0e7999c5e8f86bccb90e53e9a48ecb0;hp=864821acd6e823eced948d2be2a3c211a20c7b50;hpb=9afe74c971954cdf71386511c44595231f631c8f;p=pinmux.git diff --git a/src/spec/interfaces.py b/src/spec/interfaces.py index 864821a..684173e 100644 --- a/src/spec/interfaces.py +++ b/src/spec/interfaces.py @@ -1,20 +1,124 @@ #!/usr/bin/env python +from spec.pinfunctions import pinspec +from copy import deepcopy + + +def namesuffix(name, suffix, namelist): + names = [] + for n in namelist: + if n: + names.append("%s%s_%s" % (name, suffix, n)) + else: + names.append("%s_%s" % (name, suffix)) + return names + + +class PinGen(object): + """ a meta-helper which creates pins from the pinspec + and adds them to the pinouts. + + __call__ is used to effectively create a lambda function, which + in combination with setattr (below) gives the function a name + in the Pinouts class, according to the pinspec. + + arguments to __call__ (which ends up as Pinouts.i2s, Pinouts.sdmmc + and so on, according to spec.pinfunctions.pinspec) are: + + suffix: e.g. GPIO or SD or SPI + offs : a tuple of (Bank, Bank offset) as a string, integer + mux : which column in the multiplexer + start : the start of a subset of pins to be inserted + limit : the end of the subset (or the number if start also given) + spec : *EXTRA* pins to be inserted (at different implicit positions) + + the pins are inserted with the suffix, starting from the + offset position using offs as the row and mux as the column, + and working in a constant increment down the rows. + + spec is slightly complicated, basically there's extra + functions that we want to be on the same pin (but a different mux) + because their use is mutually-exclusive. without this spec + argument the extra pins would need to be MANUALLY moved about + during the development of the pinmux, if the "main" pins + were also moved about. this would be a pain. + + so instead, extra pins are given of the form: + { 'EXTRA1' : ('PREEXISTING_NAME', MUX_COLUMN), + ... + } + + where the function EXTRA1 will always be placed on the SAME ROW + as PREEXISTING_NAME, just in MUX_COLUMN. this may be done + several times i.e. multiple new EXTRA functions can be added + on the same row as PRE_EXISTING_NAME, just with different + MUX_COLUMN values. + + Note: spec must implicitly be in the same Bank. + """ + + def __init__(self, pinouts, fname, pinfn, bankspec): + self.pinouts = pinouts + self.bankspec = bankspec + self.pinfn = pinfn + self.fname = fname + + def __call__(self, suffix, offs, mux, + start=None, limit=None, spec=None, origsuffix=None): + bank = offs[0] + pingroup, gangedgroup = self.pinfn(suffix, bank) + if isinstance(pingroup, tuple): + prefix, pingroup = pingroup + else: + prefix = self.fname + if start and limit: # limit turns into an offset from start + limit = start + limit + pingroup = pingroup[start:limit] # see comment in spec.pinfunctions + pins = Pins(prefix, pingroup, self.bankspec, + suffix, offs, bank, mux, + spec, origsuffix=suffix, gangedgrp=gangedgroup) + fname = self.pinouts.pinmerge(pins) + self.pinouts.setganged(fname, gangedgroup) + +# pinouts class + + class Pinouts(object): - def __init__(self): + def __init__(self, bankspec): + self.bankspec = bankspec self.pins = {} self.fnspec = {} + self.ganged = {} + for fname, pinfn in pinspec: + if isinstance(pinfn, tuple): + name, pinfn = pinfn + else: + name = pinfn.__name__ + setattr(self, name, PinGen(self, fname, pinfn, self.bankspec)) + + def setganged(self, fname, grp): + grp = map(lambda x: x[:-1], grp) + if fname not in self.ganged: + self.ganged[fname] = [] + self.ganged[fname] += grp + + def __contains__(self, k): + return k in self.pins def has_key(self, k): - return self.pins.has_key(k) + return k in self.pins def add_spec(self, k, v): self.fnspec[k] = v def update(self, pinidx, v): - if not self.pins.has_key(pinidx): + if pinidx not in self.pins: self.pins[pinidx] = v else: + for k in v: + assert k not in self.pins[pinidx], \ + "pin %d position %d already taken\n%s\n%s" % \ + (pinidx, k, str(v), self.pins[pinidx]) self.pins[pinidx].update(v) def keys(self): @@ -32,11 +136,53 @@ class Pinouts(object): def __delitem__(self, k): del self.pins[k] + def __getitem__(self, k): + return self.pins[k] + + def pinmerge(self, fn): + # hack, store the function specs in the pins dict + fname = fn.fname + suffix = fn.origsuffix + bank = fn.bank + + if not hasattr(self, 'fnspec'): + self.fnspec = pins + if fname == 'GPIO': + fname = fname + bank + assert 'EINT' not in self + if fname not in self.fnspec: + self.add_spec(fname, {}) + if suffix or fname == 'EINT' or fname == 'PWM': + specname = fname + suffix + else: + specname = fname + # print "fname bank specname suffix ", fname, bank, specname, repr( + # suffix) + if specname in self.fnspec[fname]: + # ok so some declarations may bring in different + # names at different stages (EINT, PWM, flexbus1/2) + # so we have to merge the names in. main thing is + # the pingroup + tomerge = self.fnspec[fname][specname] + for p in fn.pingroup: + if p not in tomerge.pingroup: + tomerge.pingroup.append(p) + tomerge.pins.update(fn.pins) + tomerge.fntype.update(fn.fntype) + else: + self.fnspec[fname][specname] = deepcopy(fn) + + # merge actual pins + for (pinidx, v) in fn.pins.items(): + self.update(pinidx, v) + + return fname + class Pins(object): def __init__(self, fname, pingroup, bankspec, suffix, offs, bank, mux, - spec=None, limit=None, origsuffix=None): + spec=None, limit=None, origsuffix=None, gangedgrp=None): # function type can be in, out or inout, represented by - + * # strip function type out of each pin name @@ -55,6 +201,7 @@ class Pins(object): self.fname = fname self.pingroup = pingroup + self.gangedgroup = gangedgrp self.bankspec = bankspec self.suffix = suffix self.origsuffix = origsuffix or suffix @@ -63,7 +210,7 @@ class Pins(object): # create consistent name suffixes pingroup = namesuffix(fname, suffix, pingroup) - suffix = '' # hack + suffix = '' # hack res = {} names = {} @@ -73,7 +220,7 @@ class Pins(object): name_ = "%s_%s" % (name, suffix) else: name_ = name - if spec and spec.has_key(name): + if spec and name in spec: continue pin = {mux: (name_, bank)} offs_bank, offs_ = offs @@ -89,220 +236,14 @@ class Pins(object): name_ = name if not spec: continue - if not spec.has_key(name): + if name not in spec: continue - idx_, mux_, bank_ = spec[name] + idx_, mux_ = spec[name] idx_ = names[idx_] - pin = {mux_: (name_, bank_)} - if res.has_key(idx_): + pin = {mux_: (name_, bank)} + if idx_ in res: res[idx_].update(pin) else: res[idx_] = pin self.pins = res - - -def i2s(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None): - i2spins = ['MCK+', 'BCK+', 'LRCK+', 'DI-', 'DO+'] - #for i in range(4): - # i2spins.append("DO%d+" % i) - return Pins('IIS', i2spins, bankspec, suffix, offs, bank, mux, spec, limit, - origsuffix=suffix) - -def emmc(bankspec, suffix, offs, bank, mux=1, spec=None): - emmcpins = ['CMD+', 'CLK+'] - for i in range(8): - emmcpins.append("D%d*" % i) - return Pins('MMC', emmcpins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def sdmmc(bankspec, suffix, offs, bank, mux=1, spec=None, - start=None, limit=None): - sdmmcpins = ['CMD+', 'CLK+'] - for i in range(4): - sdmmcpins.append("D%d*" % i) - sdmmcpins = sdmmcpins[start:limit] - return Pins('SD', sdmmcpins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def spi(bankspec, suffix, offs, bank, mux=1, spec=None): - spipins = ['CLK*', 'NSS*', 'MOSI*', 'MISO*'] - return Pins('SPI', spipins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def quadspi(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None): - spipins = ['CK*', 'NSS*', 'IO0*', 'IO1*', 'IO2*', 'IO3*'] - return Pins('QSPI', spipins, bankspec, suffix, offs, bank, mux, spec, limit, - origsuffix=suffix) - -def i2c(bankspec, suffix, offs, bank, mux=1, spec=None): - spipins = ['SDA*', 'SCL*'] - return Pins('TWI', spipins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def jtag(bankspec, suffix, offs, bank, mux=1, spec=None): - jtagpins = ['MS+', 'DI-', 'DO+', 'CK+'] - return Pins('JTAG', jtagpins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def uart(bankspec, suffix, offs, bank, mux=1, spec=None): - uartpins = ['TX+', 'RX-'] - return Pins('UART', uartpins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def namesuffix(name, suffix, namelist): - names = [] - for n in namelist: - if n: - names.append("%s%s_%s" % (name, suffix, n)) - else: - names.append("%s_%s" % (name, suffix)) - return names - -def ulpi(bankspec, suffix, offs, bank, mux=1, spec=None): - ulpipins = ['CK+', 'DIR+', 'STP+', 'NXT+'] - for i in range(8): - ulpipins.append('D%d*' % i) - return Pins('ULPI', ulpipins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def uartfull(bankspec, suffix, offs, bank, mux=1, spec=None): - uartpins = ['TX+', 'RX-', 'CTS-', 'RTS+'] - return Pins('UARTQ', uartpins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def rgbttl(bankspec, suffix, offs, bank, mux=1, spec=None): - ttlpins = ['CK+', 'DE+', 'HS+', 'VS+'] - for i in range(24): - ttlpins.append("D%d+" % i) - return Pins('LCD', ttlpins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def rgmii(bankspec, suffix, offs, bank, mux=1, spec=None): - buspins = [] - for i in range(4): - buspins.append("ERXD%d-" % i) - for i in range(4): - buspins.append("ETXD%d+" % i) - buspins += ['ERXCK-', 'ERXERR-', 'ERXDV-', - 'EMDC+', 'EMDIO*', - 'ETXEN+', 'ETXCK+', 'ECRS-', - 'ECOL+', 'ETXERR+'] - return Pins('RG', buspins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def flexbus1(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None): - buspins = [] - for i in range(8): - buspins.append("AD%d*" % i) - for i in range(2): - buspins.append("CS%d+" % i) - buspins += ['ALE', 'OE', 'RW', 'TA', 'CLK+', - 'A0', 'A1', 'TS', 'TBST', - 'TSIZ0', 'TSIZ1'] - for i in range(4): - buspins.append("BWE%d" % i) - for i in range(2,6): - buspins.append("CS%d+" % i) - return Pins('FB', buspins, bankspec, suffix, offs, bank, mux, spec, limit, - origsuffix=suffix) - -def flexbus2(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None): - buspins = [] - for i in range(8,32): - buspins.append("AD%d*" % i) - return Pins('FB', buspins, bankspec, suffix, offs, bank, mux, spec, limit, - origsuffix=suffix) - -def sdram1(bankspec, suffix, offs, bank, mux=1, spec=None): - buspins = [] - for i in range(16): - buspins.append("SDRDQM%d*" % i) - for i in range(12): - buspins.append("SDRAD%d+" % i) - for i in range(8): - buspins.append("SDRDQ%d+" % i) - for i in range(3): - buspins.append("SDRCS%d#+" % i) - for i in range(2): - buspins.append("SDRDQ%d+" % i) - for i in range(2): - buspins.append("SDRBA%d+" % i) - buspins += ['SDRCKE+', 'SDRRAS#+', 'SDRCAS#+', 'SDRWE#+', - 'SDRRST+'] - return Pins('SDR', buspins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def sdram2(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None): - buspins = [] - for i in range(3,6): - buspins.append("SDRCS%d#+" % i) - for i in range(8,32): - buspins.append("SDRDQ%d*" % i) - return Pins('SDR', buspins, bankspec, suffix, offs, bank, mux, spec, limit, - origsuffix=suffix) - -def mcu8080(bankspec, suffix, offs, bank, mux=1, spec=None): - buspins = [] - for i in range(8): - buspins.append("MCUD%d*" % i) - for i in range(8): - buspins.append("MCUAD%d+" % (i+8)) - for i in range(6): - buspins.append("MCUCS%d+" % i) - for i in range(2): - buspins.append("MCUNRB%d+" % i) - buspins += ['MCUCD+', 'MCURD+', 'MCUWR+', 'MCUCLE+', 'MCUALE+', - 'MCURST+'] - return Pins('MCU', buspins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def _pinbank(bankspec, prefix, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, - spec=None): - gpiopins = [] - for i in range(gpiooffs, gpiooffs+gpionum): - gpiopins.append("%s%d*" % (bank, i)) - return Pins('GPIO', gpiopins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def eint(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None): - gpiopins = [] - for i in range(gpiooffs, gpiooffs+gpionum): - gpiopins.append("%d*" % (i)) - return Pins('EINT', gpiopins, bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def pwm(bankspec, suffix, offs, bank, mux=1, spec=None): - return Pins('PWM', ['+', ], bankspec, suffix, offs, bank, mux, spec, - origsuffix=suffix) - -def gpio(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None): - return _pinbank(bankspec, "GPIO", suffix, offs, bank, gpiooffs, - gpionum, mux=0, spec=None) - -def pinmerge(pins, fn): - # hack, store the function specs in the pins dict - fname = fn.fname - suffix = fn.origsuffix - bank = fn.bank - - if not hasattr(pins, 'fnspec'): - pins.fnspec = pins - if fname == 'GPIO': - fname = fname + bank - assert not pins.has_key('EINT') - if not pins.fnspec.has_key(fname): - pins.add_spec(fname, {}) - print "fname bank suffix", fname, bank, suffix - if suffix or fname == 'EINT' or fname == 'PWM': - specname = fname + suffix - else: - specname = fname + bank - pins.fnspec[fname][specname] = fn - - - # merge actual pins - for (pinidx, v) in fn.pins.items(): - print "pinidx", pinidx - pins.update(pinidx, v) -