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