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