extend sys_clk pad name
[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 name = 'power_' + name[-1]
170 name2 = 'vss'
171 else:
172 name = 'iopower_' + name[-1]
173 name2 = 'iovss'
174 pad = [name, name2]
175 # VDD
176 elif name.startswith('vdd'):
177 if 'i' in name:
178 n_intpower += 1
179 name = 'ground_' + name[-1]
180 name2 = 'vdd'
181 else:
182 n_extpower += 1
183 name = 'ioground_' + name[-1]
184 name2 = 'iovdd'
185 pad = [name, name2]
186 # SYS
187 elif name.startswith('sys'):
188 domain = 'SYS'
189 if name == 'sys_clk':
190 pad = ["p_"+name, name, name]
191 elif name == 'sys_rst':
192 #name = 'p_sys_rst_1'
193 pad = [name, name, name]
194 padbank[banknum] = name
195 print "sys_rst add", bank, banknum, name
196 name = None
197 elif name == 'sys_pllclk':
198 name = None # ignore
199 elif name == 'sys_pllock':
200 name = 'sys_pllock'
201 pad = ['p_' + name, name, name]
202 elif name == 'sys_pllout':
203 name = 'sys_pll_48_o'
204 pad = ['p_' + name, name, name]
205 elif name.startswith('sys_csel'):
206 i = name[-1]
207 name2 = 'sys_clksel_i(%s)' % i
208 name = 'p_sys_clksel_' + i
209 pad = [name, name2, name2]
210 #if name:
211 # iopads.append([pname, name, name])
212 print "sys pad", name
213 # SPI Card
214 elif name.startswith('mspi0') or name.startswith('mspi1'):
215 domain = 'MSPI'
216 suffix = name[6:]
217 if suffix == 'ck':
218 suffix = 'clk'
219 elif suffix == 'nss':
220 suffix = 'cs_n'
221 if name.startswith('mspi1'):
222 prefix = 'spimaster_'
223 else:
224 prefix = 'spisdcard_'
225 name = prefix + suffix
226 pad = ['p_' + name, name, name]
227 # SD/MMC
228 elif name.startswith('sd0'):
229 domain = 'SD'
230 if name.startswith('sd0_d'):
231 i = name[5:]
232 name = 'sdcard_data' + i
233 name2 = 'sdcard_data_%%s(%s)' % i
234 pad = ['p_' + name, name, name2 % 'o', name2 % 'i',
235 'sdcard_data_oe']
236 elif name.startswith('sd0_cmd'):
237 name = 'sdcard_cmd'
238 name2 = 'sdcard_cmd_%s'
239 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
240 else:
241 name = 'sdcard_' + name[4:]
242 pad = ['p_' + name, name, name]
243 # SDRAM
244 elif name.startswith('sdr'):
245 domain = 'SDR'
246 if name == 'sdr_clk':
247 name = 'sdram_clock'
248 pad = ['p_' + name, name, name]
249 elif name.startswith('sdr_ad'):
250 i = name[6:]
251 name = 'sdram_a_' + i
252 name2 = 'sdram_a(%s)' % i
253 pad = ['p_' + name, name2, name2]
254 elif name.startswith('sdr_ba'):
255 i = name[-1]
256 name = 'sdram_ba_' + i
257 name2 = 'sdram_ba(%s)' % i
258 pad = ['p_' + name, name2, name2]
259 elif name.startswith('sdr_dqm'):
260 i = name[-1]
261 name = 'sdram_dm_' + i
262 name2 = 'sdram_dm(%s)' % i
263 pad = ['p_' + name, name2, name2]
264 elif name.startswith('sdr_d'):
265 i = name[5:]
266 name = 'sdram_dq_' + i
267 name2 = 'sdram_dq_%%s(%s)' % i
268 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', 'sdram_dq_oe']
269 elif name == 'sdr_csn0':
270 name = 'sdram_cs_n'
271 pad = ['p_' + name, name, name]
272 elif name[-1] == 'n':
273 name = 'sdram_' + name[4:-1] + '_n'
274 pad = ['p_' + name, name, name]
275 else:
276 name = 'sdram_' + name[4:]
277 pad = ['p_' + name, name, name]
278 # UART
279 elif name.startswith('uart'):
280 domain = 'UART'
281 name = 'uart_' + name[6:]
282 pad = ['p_' + name, name, name]
283 # GPIO
284 elif name.startswith('gpio'):
285 domain = 'GPIO'
286 i = name[7:]
287 name = 'gpio_' + i
288 name2 = 'gpio_%%s(%s)' % i
289 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
290 print ("GPIO pad", name, pad)
291 # I2C master-only
292 elif name.startswith('mtwi'):
293 domain = 'MTWI'
294 name = 'i2c' + name[4:]
295 if name.startswith('i2c_sda'):
296 name2 = 'i2c_sda_%s'
297 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
298 print ("I2C pad", name, pad)
299 else:
300 pad = ['p_' + name, name, name]
301 # I2C bi-directional
302 elif name.startswith('twi'):
303 domain = 'TWI'
304 name = 'i2c' + name[3:]
305 name2 = name + '_%s'
306 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
307 print ("I2C pad", name, pad)
308 # EINT
309 elif name.startswith('eint'):
310 domain = 'EINT'
311 i = name[-1]
312 name = 'eint_%s' % i
313 name2 = 'eint(%s)' % i
314 pad = ['p_' + name, name2, name2]
315 # PWM
316 elif name.startswith('pwm'):
317 domain = 'PWM'
318 name = name[:-4]
319 i = name[3:]
320 name2 = 'pwm(%s)' % i
321 pad = ['p_' + name, name2, name2]
322 else:
323 pad = ['p_' + name, name, name]
324 print ("GPIO pad", name, pad)
325
326 # JTAG domain
327 if name and name.startswith('jtag'):
328 domain = 'JTAG'
329
330 if name and not name.startswith('p_'):
331 if 'power' not in name and 'ground' not in name:
332 name = 'p_' + name
333 if name is not None:
334 padbank[banknum] = name
335 # create domains
336 if domain is not None:
337 if domain not in domains:
338 domains[domain] = []
339 domains[domain].append(name)
340 dl = domain.lower()
341 if domain in psp.clocks and orig_name.startswith(dl):
342 clk = psp.clocks[domain]
343 if clk.lower() in orig_name: # TODO, might over-match
344 clocks[domain] = name
345 # record remap
346 pinmap[orig_name] = name
347
348 # add pad to iopads
349 if domain and pad is not None:
350 # append direction from spec/domain. damn awkward processing
351 # to find it.
352 fn, name = orig_name.split("_")
353 if domain == 'PWM':
354 name = fn[3:]
355 print dir(psp)
356 print dir(p)
357 print psp.byspec
358 spec = None
359 for k in psp.byspec.keys():
360 if k.startswith(domain):
361 spec = psp.byspec[k]
362 print "spec found", domain, spec
363 assert spec is not None
364 found = None
365 for pname in spec:
366 if pname.lower().startswith(name):
367 found = pname
368 print "found spec", found
369 assert found is not None
370 # whewwww. add the direction onto the pad spec list
371 pad.append(found[-1])
372 iopads.append(pad)
373 elif pad is not None:
374 iopads.append(pad)
375
376 # not connected
377 nc_idx = 0
378 for pl in [pe, pw, pn, ps]:
379 for i in range(len(pl)):
380 if pl[i] == '':
381 name = 'nc_%d' % nc_idx
382 name2 = 'nc(%d)' % nc_idx
383 pl[i] = name
384 pinmap[name] = name
385 iopads.append([name, name2, name2, "-"])
386 nc_idx += 1
387
388 print p.bankstart
389 pprint(psp.clocks)
390
391 print
392 print "N pads", pn
393 print "S pads", ps
394 print "E pads", pe
395 print "W pads", pw
396
397 # do not want these
398 del clocks['SYS']
399 del domains['SYS']
400
401 print "chip domains (excluding sys-default)"
402 pprint(domains)
403 print "chip clocks (excluding sys-default)"
404 pprint(clocks)
405 print "pin spec"
406 pprint(psp.byspec)
407
408 chip = {
409 'pads.south' : ps,
410 'pads.east' : pe,
411 'pads.north' : pn,
412 'pads.west' : pw,
413 'pads.instances' : iopads,
414 'pins.specs' : psp.byspec,
415 'pins.map' : pinmap,
416 'chip.domains' : domains,
417 'chip.clocks' : clocks,
418 'chip.n_intpower': n_intpower,
419 'chip.n_extpower': n_extpower,
420 }
421
422 chip = json.dumps(chip)
423 with open("ls180/litex_pinpads.json", "w") as f:
424 f.write(chip)
425
426 return pinmap