refactoring pin function name generators
[pinmux.git] / src / spec / interfaces.py
1 #!/usr/bin/env python
2
3 from copy import deepcopy
4
5
6 def namesuffix(name, suffix, namelist):
7 names = []
8 for n in namelist:
9 if n:
10 names.append("%s%s_%s" % (name, suffix, n))
11 else:
12 names.append("%s_%s" % (name, suffix))
13 return names
14
15
16 class PinGen(object):
17 def __init__(self, pinouts, fname, pinfn, bankspec):
18 self.pinouts = pinouts
19 self.bankspec = bankspec
20 self.pinfn = pinfn
21 self.fname = fname
22
23 def __call__(self, suffix, offs, bank, mux,
24 spec=None, start=None, limit=None, origsuffix=None):
25 pingroup = self.pinfn(suffix, bank)
26 pingroup = pingroup[start:limit]
27 pins = Pins(self.fname, pingroup, self.bankspec,
28 suffix, offs, bank, mux,
29 spec, origsuffix=suffix)
30 self.pinouts.pinmerge(pins)
31
32
33 # define functions here
34
35 def i2s(suffix, bank):
36 return ['MCK+', 'BCK+', 'LRCK+', 'DI-', 'DO+']
37
38 def emmc(suffix, bank):
39 emmcpins = ['CMD+', 'CLK+']
40 for i in range(8):
41 emmcpins.append("D%d*" % i)
42 return emmcpins
43
44 def sdmmc(suffix, bank):
45 sdmmcpins = ['CMD+', 'CLK+']
46 for i in range(4):
47 sdmmcpins.append("D%d*" % i)
48 return sdmmcpins
49
50 def spi(suffix, bank):
51 return ['CLK*', 'NSS*', 'MOSI*', 'MISO*']
52
53 def quadspi(suffix, bank):
54 return ['CK*', 'NSS*', 'IO0*', 'IO1*', 'IO2*', 'IO3*']
55
56 def i2c(suffix, bank):
57 return ['SDA*', 'SCL*']
58
59 def jtag(suffix, bank):
60 return ['MS+', 'DI-', 'DO+', 'CK+']
61
62 def uart(suffix, bank):
63 return ['TX+', 'RX-']
64
65 def ulpi(suffix, bank):
66 ulpipins = ['CK+', 'DIR+', 'STP+', 'NXT+']
67 for i in range(8):
68 ulpipins.append('D%d*' % i)
69 return ulpipins
70
71 def uartfull(suffix, bank):
72 return ['TX+', 'RX-', 'CTS-', 'RTS+']
73
74 def rgbttl(suffix, bank):
75 ttlpins = ['CK+', 'DE+', 'HS+', 'VS+']
76 for i in range(24):
77 ttlpins.append("D%d+" % i)
78 return ttlpins
79
80 def rgmii(suffix, bank):
81 buspins = []
82 for i in range(4):
83 buspins.append("ERXD%d-" % i)
84 for i in range(4):
85 buspins.append("ETXD%d+" % i)
86 buspins += ['ERXCK-', 'ERXERR-', 'ERXDV-',
87 'EMDC+', 'EMDIO*',
88 'ETXEN+', 'ETXCK+', 'ECRS-',
89 'ECOL+', 'ETXERR+']
90 return buspins
91
92
93 # list functions by name here
94
95 pinspec = {'IIS': i2s,
96 'MMC': emmc,
97 'SD': sdmmc,
98 'SPI': spi,
99 'QSPI': quadspi,
100 'TWI': i2c,
101 'JTAG': jtag,
102 'UART': uart,
103 'UARTQ': uartfull,
104 'LCD': rgbttl,
105 'ULPI': ulpi,
106 'RG': rgmii,
107 }
108
109 # pinouts class
110
111 class Pinouts(object):
112 def __init__(self, bankspec):
113 self.bankspec = bankspec
114 self.pins = {}
115 self.fnspec = {}
116 for fname, pinfn in pinspec.items():
117 if isinstance(pinfn, tuple):
118 name, pinfn = pinfn
119 else:
120 name = pinfn.__name__
121 setattr(self, name, PinGen(self, fname, pinfn, self.bankspec))
122
123 def __contains__(self, k):
124 return k in self.pins
125
126 def has_key(self, k):
127 return k in self.pins
128
129 def add_spec(self, k, v):
130 self.fnspec[k] = v
131
132 def update(self, pinidx, v):
133 if pinidx not in self.pins:
134 self.pins[pinidx] = v
135 else:
136 for k in v:
137 assert k not in self.pins[pinidx], \
138 "pin %d position %d already taken\n%s\n%s" % \
139 (pinidx, k, str(v), self.pins[pinidx])
140 self.pins[pinidx].update(v)
141
142 def keys(self):
143 return self.pins.keys()
144
145 def items(self):
146 return self.pins.items()
147
148 def get(self, k):
149 return self.pins[k]
150
151 def __len__(self):
152 return len(self.pins)
153
154 def __delitem__(self, k):
155 del self.pins[k]
156
157 def __getitem__(self, k):
158 return self.pins[k]
159
160 def flexbus1(self, suffix, offs, bank, mux=1, spec=None, limit=None):
161 buspins = []
162 for i in range(8):
163 buspins.append("AD%d*" % i)
164 for i in range(2):
165 buspins.append("CS%d+" % i)
166 buspins += ['ALE', 'OE', 'RW', 'TA', 'CLK+',
167 'A0', 'A1', 'TS', 'TBST',
168 'TSIZ0', 'TSIZ1']
169 for i in range(4):
170 buspins.append("BWE%d" % i)
171 for i in range(2, 6):
172 buspins.append("CS%d+" % i)
173 pins = Pins('FB', buspins, self.bankspec,
174 suffix, offs, bank, mux,
175 spec, limit, origsuffix=suffix)
176 self.pinmerge(pins)
177
178 def flexbus2(self, suffix, offs, bank, mux=1, spec=None, limit=None):
179 buspins = []
180 for i in range(8, 32):
181 buspins.append("AD%d*" % i)
182 pins = Pins('FB', buspins, self.bankspec,
183 suffix, offs, bank, mux,
184 spec, limit, origsuffix=suffix)
185 self.pinmerge(pins)
186
187 def sdram1(self, suffix, offs, bank, mux=1, spec=None):
188 buspins = []
189 for i in range(16):
190 buspins.append("SDRDQM%d*" % i)
191 for i in range(12):
192 buspins.append("SDRAD%d+" % i)
193 for i in range(8):
194 buspins.append("SDRDQ%d+" % i)
195 for i in range(3):
196 buspins.append("SDRCS%d#+" % i)
197 for i in range(2):
198 buspins.append("SDRDQ%d+" % i)
199 for i in range(2):
200 buspins.append("SDRBA%d+" % i)
201 buspins += ['SDRCKE+', 'SDRRAS#+', 'SDRCAS#+', 'SDRWE#+',
202 'SDRRST+']
203 pins = Pins('SDR', buspins, self.bankspec,
204 suffix, offs, bank, mux,
205 spec, origsuffix=suffix)
206 self.pinmerge(pins)
207
208 def sdram2(self, suffix, offs, bank, mux=1, spec=None, limit=None):
209 buspins = []
210 for i in range(3, 6):
211 buspins.append("SDRCS%d#+" % i)
212 for i in range(8, 32):
213 buspins.append("SDRDQ%d*" % i)
214 pins = Pins('SDR', buspins, self.bankspec,
215 suffix, offs, bank, mux,
216 spec, limit, origsuffix=suffix)
217 self.pinmerge(pins)
218
219 def mcu8080(self, suffix, offs, bank, mux=1, spec=None):
220 buspins = []
221 for i in range(8):
222 buspins.append("MCUD%d*" % i)
223 for i in range(8):
224 buspins.append("MCUAD%d+" % (i + 8))
225 for i in range(6):
226 buspins.append("MCUCS%d+" % i)
227 for i in range(2):
228 buspins.append("MCUNRB%d+" % i)
229 buspins += ['MCUCD+', 'MCURD+', 'MCUWR+', 'MCUCLE+', 'MCUALE+',
230 'MCURST+']
231 pins = Pins('MCU', buspins, self.bankspec,
232 suffix, offs, bank, mux,
233 spec, origsuffix=suffix)
234 self.pinmerge(pins)
235
236 def eint(self, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
237 gpiopins = []
238 for i in range(gpiooffs, gpiooffs + gpionum):
239 gpiopins.append("%d*" % (i))
240 pins = Pins('EINT', gpiopins, self.bankspec,
241 suffix, offs, bank, mux,
242 spec, origsuffix=suffix)
243 self.pinmerge(pins)
244
245 def pwm(self, suffix, offs, bank, pwmoffs, pwmnum=1, mux=1, spec=None):
246 pwmpins = []
247 for i in range(pwmoffs, pwmoffs + pwmnum):
248 pwmpins.append("%d+" % (i))
249 pins = Pins('PWM', pwmpins, self.bankspec,
250 suffix, offs, bank, mux,
251 spec, origsuffix=suffix)
252 self.pinmerge(pins)
253
254 def gpio(self, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
255 prefix = "GPIO%s" % bank
256 gpiopins = []
257 for i in range(gpiooffs, gpiooffs + gpionum):
258 gpiopins.append("%s%d*" % (bank, i))
259 pins = Pins(prefix, gpiopins, self.bankspec,
260 suffix, offs, bank, mux,
261 spec, origsuffix=suffix)
262 self.pinmerge(pins)
263
264 def pinmerge(self, fn):
265 # hack, store the function specs in the pins dict
266 fname = fn.fname
267 suffix = fn.origsuffix
268 bank = fn.bank
269
270 if not hasattr(self, 'fnspec'):
271 self.fnspec = pins
272 if fname == 'GPIO':
273 fname = fname + bank
274 assert 'EINT' not in self
275 if fname not in self.fnspec:
276 self.add_spec(fname, {})
277 if suffix or fname == 'EINT' or fname == 'PWM':
278 specname = fname + suffix
279 else:
280 specname = fname
281 #print "fname bank specname suffix ", fname, bank, specname, repr(
282 # suffix)
283 if specname in self.fnspec[fname]:
284 # ok so some declarations may bring in different
285 # names at different stages (EINT, PWM, flexbus1/2)
286 # so we have to merge the names in. main thing is
287 # the pingroup
288 tomerge = self.fnspec[fname][specname]
289 for p in fn.pingroup:
290 if p not in tomerge.pingroup:
291 tomerge.pingroup.append(p)
292 tomerge.pins.update(fn.pins)
293 tomerge.fntype.update(fn.fntype)
294 else:
295 self.fnspec[fname][specname] = deepcopy(fn)
296
297 # merge actual pins
298 for (pinidx, v) in fn.pins.items():
299 self.update(pinidx, v)
300
301
302 class Pins(object):
303
304 def __init__(self, fname, pingroup, bankspec, suffix, offs, bank, mux,
305 spec=None, limit=None, origsuffix=None):
306
307 # function type can be in, out or inout, represented by - + *
308 # strip function type out of each pin name
309 self.fntype = {}
310 for i in range(len(pingroup)):
311 pname = pingroup[i]
312 if not pname:
313 continue
314 fntype = pname[-1]
315 if fntype not in '+-*':
316 continue
317 pname = pname[:-1]
318 fntype = {'-': 'in', '+': 'out', '*': 'inout'}[fntype]
319 self.fntype[pname] = fntype
320 pingroup[i] = pname
321
322 self.fname = fname
323 self.pingroup = pingroup
324 self.bankspec = bankspec
325 self.suffix = suffix
326 self.origsuffix = origsuffix or suffix
327 self.bank = bank
328 self.mux = mux
329
330 # create consistent name suffixes
331 pingroup = namesuffix(fname, suffix, pingroup)
332 suffix = '' # hack
333
334 res = {}
335 names = {}
336 idx = 0
337 for name in pingroup[:limit]:
338 if suffix and name:
339 name_ = "%s_%s" % (name, suffix)
340 else:
341 name_ = name
342 if spec and name in spec:
343 continue
344 pin = {mux: (name_, bank)}
345 offs_bank, offs_ = offs
346 idx_ = offs_ + idx
347 idx += 1
348 idx_ += bankspec[bank]
349 res[idx_] = pin
350 names[name] = idx_
351 for name in pingroup:
352 if suffix and name:
353 name_ = "%s_%s" % (name, suffix)
354 else:
355 name_ = name
356 if not spec:
357 continue
358 if name not in spec:
359 continue
360 idx_, mux_, bank_ = spec[name]
361 idx_ = names[idx_]
362 pin = {mux_: (name_, bank_)}
363 if idx_ in res:
364 res[idx_].update(pin)
365 else:
366 res[idx_] = pin
367
368 self.pins = res