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