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