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