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