763621f4d6f5cf58af21408cd14bb4016d72dab2
[pinmux.git] / src / spec / ls180.py
1 #!/usr/bin/env python
2 # see https://bugs.libre-soc.org/show_bug.cgi?id=304
3
4 from spec.base import PinSpec
5 from parse import Parse
6 import json
7
8 from pprint import pprint
9 from spec.ifaceprint import display, display_fns, check_functions
10 from spec.ifaceprint import display_fixed
11 from collections import OrderedDict
12
13 def pinspec():
14 pinbanks = OrderedDict((
15 ('N', (32, 2)),
16 ('E', (32, 2)),
17 ('S', (32, 2)),
18 ('W', (32, 2)),
19 ))
20 fixedpins = {
21 'CTRL_SYS': [
22 'TEST',
23 'JTAG_SEL',
24 'UBOOT_SEL',
25 'NMI#',
26 'RESET#',
27 'CLK24M_IN',
28 'CLK24M_OUT',
29 'PLLTEST',
30 'PLLREGIO',
31 'PLLVP25',
32 'PLLDV',
33 'PLLVREG',
34 'PLLGND',
35 ],
36 'POWER_GPIO': [
37 'VDD_GPIOB',
38 'GND_GPIOB',
39 ]}
40 fixedpins = {}
41 function_names = {
42 'PWM': 'PWM (pulse-width modulation)',
43 'MSPI0': 'SPI Master 1 (general)',
44 'MSPI1': 'SPI Master 2 (SDCard)',
45 'UART0': 'UART (TX/RX) 1',
46 'SYS': 'System Control',
47 'GPIO': 'GPIO',
48 'EINT': 'External Interrupt',
49 'PWM': 'PWM',
50 'JTAG': 'JTAG',
51 'MTWI': 'I2C Master 1',
52 'SD0': 'SD/MMC 1',
53 'SDR': 'SDRAM',
54 'VDD': 'Power',
55 'VSS': 'GND',
56 #'LPC1': 'Low Pincount Interface 1',
57 #'LPC2': 'Low Pincount Interface 2',
58 }
59
60 ps = PinSpec(pinbanks, fixedpins, function_names)
61
62 ps.vdd("E", ('S', 0), 0, 0, 1)
63 ps.vss("E", ('S', 1), 0, 0, 1)
64 ps.vdd("I", ('S', 2), 0, 0, 1)
65 ps.vss("I", ('S', 3), 0, 0, 1)
66 ps.sdram1("", ('S', 4), 0, 0, 21)
67 ps.mi2c("", ('S', 26), 0, 0, 2)
68 ps.vss("I", ('S', 28), 0, 1, 1)
69 ps.vdd("I", ('S', 29), 0, 1, 1)
70 ps.vss("E", ('S', 30), 0, 1, 1)
71 ps.vdd("E", ('S', 31), 0, 1, 1)
72
73 ps.vdd("E", ('W', 0), 0, 2, 1)
74 ps.vss("E", ('W', 1), 0, 2, 1)
75 ps.vdd("I", ('W', 2), 0, 2, 1)
76 ps.vss("I", ('W', 3), 0, 2, 1)
77 ps.sdram2("", ('W', 4), 0, 0, 12)
78 ps.sdram1("", ('W', 16), 0, 21, 9)
79 ps.uart("0", ('W', 22), 0)
80 ps.mspi("0", ('W', 24), 0)
81 ps.vss("I", ('W', 28), 0, 3, 1)
82 ps.vdd("I", ('W', 29), 0, 3, 1)
83 ps.vss("E", ('W', 30), 0, 3, 1)
84 ps.vdd("E", ('W', 31), 0, 3, 1)
85
86 ps.vss("I", ('E', 0), 0, 4, 1)
87 ps.vdd("I", ('E', 1), 0, 4, 1)
88 ps.vdd("I", ('E', 2), 0, 4, 1)
89 ps.vss("I", ('E', 3), 0, 4, 1)
90 ps.sys("", ('E', 4), 0, 5, 1) # analog VCO out in right top
91 ps.gpio("", ('E', 5), 0, 0, 8) # split GPIO 8-8
92 ps.jtag("", ('E', 13), 0, 0, 4)
93 ps.gpio("", ('E', 17), 0, 8, 8) # the other 8 GPIO
94 ps.eint("", ('E', 25), 0, 0, 3)
95 ps.vss("I", ('E', 28), 0, 5, 1)
96 ps.vdd("I", ('E', 29), 0, 5, 1)
97 ps.vss("I", ('E', 30), 0, 5, 1)
98 ps.vdd("I", ('E', 31), 0, 5, 1)
99
100 ps.vss("E", ('N', 6), 0, 6, 1)
101 ps.vdd("E", ('N', 7), 0, 6, 1)
102 ps.vdd("I", ('N', 8), 0, 6, 1)
103 ps.vss("I", ('N', 9), 0, 6, 1)
104 #ps.pwm("", ('N', 2), 0, 0, 2) comment out (litex problem 25mar2021)
105 #ps.mspi("1", ('N', 7), 0) comment out (litex problem 25mar2021)
106 #ps.sdmmc("0", ('N', 11), 0) # comment out (litex problem 25mar2021)
107 ps.sys("", ('N', 27), 0, 0, 5) # all but analog out in top right
108 ps.vss("I", ('N', 22), 0, 7, 1)
109 ps.vdd("I", ('N', 23), 0, 7, 1)
110 ps.vss("I", ('N', 24), 0, 7, 1)
111 ps.vdd("I", ('N', 25), 0, 7, 1)
112
113 #ps.mquadspi("1", ('S', 0), 0)
114
115 print "ps clocks", ps.clocks
116
117 # Scenarios below can be spec'd out as either "find first interface"
118 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
119 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
120 # EINT and PWM are grouped together, specially, but may still be spec'd
121 # using "BM:Name". Pins are removed in-order as listed from
122 # lists (interfaces, EINTs, PWMs) from available pins.
123
124 ls180 = [
125 # 'SD0', litex problem 25mar2021
126 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
127 'VDD', 'VSS', 'SYS',
128 'MTWI', 'MSPI0',
129 # 'MSPI1', litex problem 25mar2021
130 'SDR']
131 ls180_eint = []
132 ls180_pwm = []#['B0:PWM_0']
133 descriptions = {
134 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
135 'and UART2, for debug purposes',
136 'MTWI': 'I2C.\n',
137 'E2:SD1': '',
138 'MSPI1': '',
139 'UART0': '',
140 'LPC1': '',
141 'SYS': '',
142 'LPC2': '',
143 'SDR': '',
144 'B1:LCD/22': '18-bit RGB/TTL LCD',
145 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
146 'ULPI1': 'dual USB2 Host ULPI PHY'
147 }
148
149 ps.add_scenario("Libre-SOC 180nm", ls180, ls180_eint, ls180_pwm,
150 descriptions)
151
152 return ps
153
154
155 # map pins to litex name conventions, primarily for use in coriolis2
156 # yes this is a mess. it'll do the job though. improvements later
157 def pinparse(psp, pinspec):
158 p = Parse(pinspec, verify=False)
159 pinmap = {}
160 litexmap = {}
161
162 print p.muxed_cells
163 print p.muxed_cells_bank
164
165 ps = [''] * 32
166 pn = [''] * 32
167 pe = [''] * 32
168 pw = [''] * 32
169 pads = {'N': pn, 'S': ps, 'E': pe, 'W': pw}
170
171 iopads = []
172 domains = {}
173 clocks = {}
174
175 n_intpower = 0
176 n_extpower = 0
177 for (padnum, name, x), bank in zip(p.muxed_cells, p.muxed_cells_bank):
178 orig_name = name
179 litex_name = None
180 domain = None # TODO, get this from the PinSpec. sigh
181 padnum = int(padnum)
182 start = p.bankstart[bank]
183 banknum = padnum - start
184 print "bank", bank, banknum, "padname", name, padnum, x
185 padbank = pads[bank]
186 pad = None
187 # VSS
188 if name.startswith('vss'):
189 name = 'p_%s_' % name[:-2] + name[-1]
190 if 'i' in name:
191 name = 'ground_' + name[-1]
192 name2 = 'vss'
193 else:
194 name = 'ioground_' + name[-1]
195 name2 = 'iovss'
196 pad = [name, name2]
197 # VDD
198 elif name.startswith('vdd'):
199 if 'i' in name:
200 n_intpower += 1
201 name = 'power_' + name[-1]
202 name2 = 'vdd'
203 else:
204 n_extpower += 1
205 name = 'iopower_' + name[-1]
206 name2 = 'iovdd'
207 pad = [name, name2]
208 # SYS
209 elif name.startswith('sys'):
210 domain = 'SYS'
211 if name == 'sys_pllclk':
212 pad = ["p_"+name, name, name]
213 elif name == 'sys_rst':
214 #name = 'p_sys_rst_1'
215 pad = [name, name, name]
216 padbank[banknum] = name
217 print "sys_rst add", bank, banknum, name
218 name = None
219 elif name == 'sys_pllclk':
220 name = None # ignore
221 elif name == 'sys_pllvcout':
222 name = 'sys_pll_vco_o'
223 pad = ['p_' + name, name, name, "A"] # A for Analog
224 elif name == 'sys_plltestout':
225 name = 'sys_pll_testout_o'
226 pad = ['p_' + name, name, name]
227 elif name.startswith('sys_pllsel'):
228 i = name[-1]
229 name2 = 'sys_clksel_i(%s)' % i
230 name = 'p_sys_clksel_' + i
231 pad = [name, name2, name2]
232 #if name:
233 # iopads.append([pname, name, name])
234 print "sys pad", name
235 # SPI Card
236 elif name.startswith('mspi0') or name.startswith('mspi1'):
237 domain = 'MSPI'
238 suffix = name[6:]
239 if suffix == 'ck':
240 suffix = 'clk'
241 elif suffix == 'nss':
242 suffix = 'cs_n'
243 if name.startswith('mspi0'):
244 prefix = 'spimaster_'
245 else:
246 prefix = 'spisdcard_'
247 litex_name = name[:6] + suffix
248 name = prefix + suffix
249 pad = ['p_' + name, name, name]
250 # SD/MMC
251 elif name.startswith('sd0'):
252 domain = 'SD'
253 if name.startswith('sd0_d'):
254 i = name[5:]
255 name = 'sdcard_data' + i
256 name2 = 'sdcard_data_%%s(%s)' % i
257 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
258 elif name.startswith('sd0_cmd'):
259 name = 'sdcard_cmd'
260 name2 = 'sdcard_cmd_%s'
261 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
262 else:
263 name = 'sdcard_' + name[4:]
264 pad = ['p_' + name, name, name]
265 litex_name = orig_name[:4] + "_".join(name.split("_")[1:])
266 # SDRAM
267 elif name.startswith('sdr'):
268 domain = 'SDR'
269 if name == 'sdr_clk':
270 name = 'sdram_clock'
271 pad = ['p_' + name, name, name]
272 elif name.startswith('sdr_ad'):
273 i = name[6:]
274 name = 'sdram_a_' + i
275 name2 = 'sdram_a(%s)' % i
276 pad = ['p_' + name, name2, name2]
277 elif name.startswith('sdr_ba'):
278 i = name[-1]
279 name = 'sdram_ba_' + i
280 name2 = 'sdram_ba(%s)' % i
281 pad = ['p_' + name, name2, name2]
282 elif name.startswith('sdr_dqm'):
283 i = name[-1]
284 name = 'sdram_dm_' + i
285 name2 = 'sdram_dm(%s)' % i
286 pad = ['p_' + name, name2, name2]
287 elif name.startswith('sdr_d'):
288 i = name[5:]
289 name = 'sdram_dq_' + i
290 name2 = 'sdram_dq_%%s(%s)' % i
291 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
292 elif name == 'sdr_csn0':
293 name = 'sdram_cs_n'
294 pad = ['p_' + name, name, name]
295 elif name[-1] == 'n':
296 name = 'sdram_' + name[4:-1] + '_n'
297 pad = ['p_' + name, name, name]
298 else:
299 name = 'sdram_' + name[4:]
300 pad = ['p_' + name, name, name]
301 litex_name = orig_name[:4] + "_".join(name.split("_")[1:])
302 # UART
303 elif name.startswith('uart'):
304 domain = 'UART'
305 name = 'uart_' + name[6:]
306 pad = ['p_' + name, name, name]
307 # GPIO
308 elif name.startswith('gpio'):
309 gbank = name[4]
310 domain = 'GPIO'
311 i = name[7:]
312 name = 'gpio_' + i
313 name2 = 'gpio_%%s(%s)' % i
314 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
315 print ("GPIO pad", name, pad)
316 litex_name = "gpio_%s" % gbank + "_".join(name.split("_")[1:])
317 # I2C master-only
318 elif name.startswith('mtwi'):
319 domain = 'MTWI'
320 suffix = name[4:]
321 litex_name = 'mtwi' + suffix
322 name = 'i2c' + suffix
323 if name.startswith('i2c_sda'):
324 name2 = 'i2c_sda_%s'
325 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
326 print ("I2C pad", name, pad)
327 else:
328 pad = ['p_' + name, name, name]
329 # I2C bi-directional
330 elif name.startswith('twi'):
331 domain = 'TWI'
332 name = 'i2c' + name[3:]
333 name2 = name + '_%s'
334 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
335 print ("I2C pad", name, pad)
336 # EINT
337 elif name.startswith('eint'):
338 domain = 'EINT'
339 i = name[-1]
340 name = 'eint_%s' % i
341 name2 = 'eint_%s' % i
342 pad = ['p_' + name, name2, name2]
343 # PWM
344 elif name.startswith('pwm'):
345 domain = 'PWM'
346 name = name[:-4]
347 i = name[3:]
348 name2 = 'pwm(%s)' % i
349 pad = ['p_' + name, name2, name2]
350 else:
351 pad = ['p_' + name, name, name]
352 print ("GPIO pad", name, pad)
353
354 if litex_name is None:
355 litex_name = name
356
357 # JTAG domain
358 if name and name.startswith('jtag'):
359 domain = 'JTAG'
360
361 if name and not name.startswith('p_'):
362 if 'power' not in name and 'ground' not in name:
363 name = 'p_' + name
364 if name is not None:
365 padbank[banknum] = name
366 # create domains
367 if domain is not None:
368 if domain not in domains:
369 domains[domain] = []
370 domains[domain].append(name)
371 dl = domain.lower()
372 if domain in psp.clocks and orig_name.startswith(dl):
373 clk = psp.clocks[domain]
374 if clk.lower() in orig_name: # TODO, might over-match
375 clocks[domain] = name
376 # record remap
377 pinmap[orig_name] = name
378 litexmap[litex_name] = name
379
380 # add pad to iopads
381 if domain and pad is not None:
382 # append direction from spec/domain. damn awkward processing
383 # to find it.
384 fn, name = orig_name.split("_")
385 if domain == 'PWM':
386 name = fn[3:]
387 print psp.byspec
388 spec = None
389 for k in psp.byspec.keys():
390 if k.startswith(domain):
391 spec = psp.byspec[k]
392 print "spec found", domain, spec
393 assert spec is not None
394 found = None
395 for pname in spec:
396 if pname.lower().startswith(name):
397 found = pname
398 print "found spec", found
399 assert found is not None
400 # whewwww. add the direction onto the pad spec list
401 dirn = found[-1]
402 if pad[-1] == 'A':
403 pad[-1] += dirn
404 else:
405 pad.append(dirn)
406 iopads.append(pad)
407 elif pad is not None:
408 iopads.append(pad)
409
410 # not connected
411 nc_idx = 0
412 for pl in [pe, pw, pn, ps]:
413 for i in range(len(pl)):
414 if pl[i] == '':
415 name = 'nc_%d' % nc_idx
416 name2 = 'nc(%d)' % nc_idx
417 pl[i] = name
418 pinmap[name] = name
419 iopads.append([name, name2, name2, "-"])
420 nc_idx += 1
421
422 print p.bankstart
423 pprint(psp.clocks)
424
425 print
426 print "N pads", pn
427 print "S pads", ps
428 print "E pads", pe
429 print "W pads", pw
430
431 # do not want these
432 del clocks['SYS']
433 del domains['SYS']
434
435 print "chip domains (excluding sys-default)"
436 pprint(domains)
437 print "chip clocks (excluding sys-default)"
438 pprint(clocks)
439 print "pin spec"
440 pprint(psp.byspec)
441
442 chip = {
443 'pads.south' : ps,
444 'pads.east' : pe,
445 'pads.north' : pn,
446 'pads.west' : pw,
447 'pads.instances' : iopads,
448 'pins.specs' : psp.byspec,
449 'pins.map' : pinmap,
450 'litex.map' : litexmap,
451 'chip.domains' : domains,
452 'chip.clocks' : clocks,
453 'chip.n_intpower': n_intpower,
454 'chip.n_extpower': n_extpower,
455 }
456
457 return pinmap, chip