rename ls180 pllock signal
[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_pll_lck_o'
201 pad = ['p_' + name, name, name]
202 elif name == 'sys_pllout':
203 name = 'sys_pll_18_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 psp.byspec
356 spec = None
357 for k in psp.byspec.keys():
358 if k.startswith(domain):
359 spec = psp.byspec[k]
360 print "spec found", domain, spec
361 assert spec is not None
362 found = None
363 for pname in spec:
364 if pname.lower().startswith(name):
365 found = pname
366 print "found spec", found
367 assert found is not None
368 # whewwww. add the direction onto the pad spec list
369 pad.append(found[-1])
370 iopads.append(pad)
371 elif pad is not None:
372 iopads.append(pad)
373
374 # not connected
375 nc_idx = 0
376 for pl in [pe, pw, pn, ps]:
377 for i in range(len(pl)):
378 if pl[i] == '':
379 name = 'nc_%d' % nc_idx
380 name2 = 'nc(%d)' % nc_idx
381 pl[i] = name
382 pinmap[name] = name
383 iopads.append([name, name2, name2, "-"])
384 nc_idx += 1
385
386 print p.bankstart
387 pprint(psp.clocks)
388
389 print
390 print "N pads", pn
391 print "S pads", ps
392 print "E pads", pe
393 print "W pads", pw
394
395 # do not want these
396 del clocks['SYS']
397 del domains['SYS']
398
399 print "chip domains (excluding sys-default)"
400 pprint(domains)
401 print "chip clocks (excluding sys-default)"
402 pprint(clocks)
403 print "pin spec"
404 pprint(psp.byspec)
405
406 chip = {
407 'pads.south' : ps,
408 'pads.east' : pe,
409 'pads.north' : pn,
410 'pads.west' : pw,
411 'pads.instances' : iopads,
412 'pins.specs' : psp.byspec,
413 'pins.map' : pinmap,
414 'chip.domains' : domains,
415 'chip.clocks' : clocks,
416 'chip.n_intpower': n_intpower,
417 'chip.n_extpower': n_extpower,
418 }
419
420 chip = json.dumps(chip)
421 with open("ls180/litex_pinpads.json", "w") as f:
422 f.write(chip)
423
424 return pinmap