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