disable PLL temporarily
[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_pllock':
202 name = 'sys_pll_lck_o'
203 pad = ['p_' + name, name, name]
204 elif name == 'sys_pllout':
205 name = 'sys_pll_18_o'
206 pad = ['p_' + name, name, name]
207 elif name.startswith('sys_csel'):
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',
237 'sdcard_data_oe']
238 elif name.startswith('sd0_cmd'):
239 name = 'sdcard_cmd'
240 name2 = 'sdcard_cmd_%s'
241 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
242 else:
243 name = 'sdcard_' + name[4:]
244 pad = ['p_' + name, name, name]
245 # SDRAM
246 elif name.startswith('sdr'):
247 domain = 'SDR'
248 if name == 'sdr_clk':
249 name = 'sdram_clock'
250 pad = ['p_' + name, name, name]
251 elif name.startswith('sdr_ad'):
252 i = name[6:]
253 name = 'sdram_a_' + i
254 name2 = 'sdram_a(%s)' % i
255 pad = ['p_' + name, name2, name2]
256 elif name.startswith('sdr_ba'):
257 i = name[-1]
258 name = 'sdram_ba_' + i
259 name2 = 'sdram_ba(%s)' % i
260 pad = ['p_' + name, name2, name2]
261 elif name.startswith('sdr_dqm'):
262 i = name[-1]
263 name = 'sdram_dm_' + i
264 name2 = 'sdram_dm(%s)' % i
265 pad = ['p_' + name, name2, name2]
266 elif name.startswith('sdr_d'):
267 i = name[5:]
268 name = 'sdram_dq_' + i
269 name2 = 'sdram_dq_%%s(%s)' % i
270 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', 'sdram_dq_oe']
271 elif name == 'sdr_csn0':
272 name = 'sdram_cs_n'
273 pad = ['p_' + name, name, name]
274 elif name[-1] == 'n':
275 name = 'sdram_' + name[4:-1] + '_n'
276 pad = ['p_' + name, name, name]
277 else:
278 name = 'sdram_' + name[4:]
279 pad = ['p_' + name, name, name]
280 # UART
281 elif name.startswith('uart'):
282 domain = 'UART'
283 name = 'uart_' + name[6:]
284 pad = ['p_' + name, name, name]
285 # GPIO
286 elif name.startswith('gpio'):
287 domain = 'GPIO'
288 i = name[7:]
289 name = 'gpio_' + i
290 name2 = 'gpio_%%s(%s)' % i
291 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
292 print ("GPIO pad", name, pad)
293 # I2C master-only
294 elif name.startswith('mtwi'):
295 domain = 'MTWI'
296 name = 'i2c' + name[4:]
297 if name.startswith('i2c_sda'):
298 name2 = 'i2c_sda_%s'
299 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
300 print ("I2C pad", name, pad)
301 else:
302 pad = ['p_' + name, name, name]
303 # I2C bi-directional
304 elif name.startswith('twi'):
305 domain = 'TWI'
306 name = 'i2c' + name[3:]
307 name2 = name + '_%s'
308 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
309 print ("I2C pad", name, pad)
310 # EINT
311 elif name.startswith('eint'):
312 domain = 'EINT'
313 i = name[-1]
314 name = 'eint_%s' % i
315 name2 = 'eint_%s' % i
316 pad = ['p_' + name, name2, name2]
317 # PWM
318 elif name.startswith('pwm'):
319 domain = 'PWM'
320 name = name[:-4]
321 i = name[3:]
322 name2 = 'pwm(%s)' % i
323 pad = ['p_' + name, name2, name2]
324 else:
325 pad = ['p_' + name, name, name]
326 print ("GPIO pad", name, pad)
327
328 # JTAG domain
329 if name and name.startswith('jtag'):
330 domain = 'JTAG'
331
332 if name and not name.startswith('p_'):
333 if 'power' not in name and 'ground' not in name:
334 name = 'p_' + name
335 if name is not None:
336 padbank[banknum] = name
337 # create domains
338 if domain is not None:
339 if domain not in domains:
340 domains[domain] = []
341 domains[domain].append(name)
342 dl = domain.lower()
343 if domain in psp.clocks and orig_name.startswith(dl):
344 clk = psp.clocks[domain]
345 if clk.lower() in orig_name: # TODO, might over-match
346 clocks[domain] = name
347 # record remap
348 pinmap[orig_name] = name
349
350 # add pad to iopads
351 if domain and pad is not None:
352 # append direction from spec/domain. damn awkward processing
353 # to find it.
354 fn, name = orig_name.split("_")
355 if domain == 'PWM':
356 name = fn[3:]
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