add domains and clocks to be able to create different VDD/VSS IO
[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 'TWI': '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("", ('N', 0), 0, 0, 1)
63 ps.vdd("", ('N', 1), 0, 0, 1)
64 ps.sdram1("", ('N', 2), 0, 0, 30)
65 ps.vss("", ('N', 30), 0, 1, 1)
66 ps.vdd("", ('N', 31), 0, 1, 1)
67
68 ps.vss("", ('E', 0), 0, 2, 1)
69 ps.sdram2("", ('E', 1), 0, 0, 12)
70 ps.vdd("", ('E', 13), 0, 2, 1)
71 ps.gpio("", ('E', 14), 0, 8, 8)
72 ps.vss("", ('E', 23), 0, 3, 1)
73 ps.jtag("", ('E', 24), 0, 0, 4)
74 ps.vdd("", ('E', 31), 0, 3, 1)
75
76 ps.vss("", ('S', 0), 0, 4, 1)
77 ps.sys("", ('S', 1), 0, 0, 7)
78 ps.vdd("", ('S', 8), 0, 4, 1)
79 ps.i2c("", ('S', 9), 0, 0, 2)
80 ps.mspi("0", ('S', 15), 0)
81 ps.uart("0", ('S', 20), 0)
82 ps.vss("", ('S', 22), 0, 5, 1)
83 ps.gpio("", ('S', 23), 0, 0, 8)
84 ps.vdd("", ('S', 31), 0, 5, 1)
85
86 ps.vss("", ('W', 0), 0, 6, 1)
87 ps.pwm("", ('W', 1), 0, 0, 2)
88 ps.eint("", ('W', 3), 0, 0, 3)
89 ps.mspi("1", ('W', 6), 0)
90 ps.vdd("", ('W', 10), 0, 6, 1)
91 ps.sdmmc("0", ('W', 11), 0)
92 ps.vss("", ('W', 17), 0, 7, 1)
93 ps.vdd("", ('W', 31), 0, 7, 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 'TWI', '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 'TWI': '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 def pinparse(psp, pinspec):
137 p = Parse(pinspec, verify=False)
138
139 print p.muxed_cells
140 print p.muxed_cells_bank
141
142 ps = [''] * 32
143 pn = [''] * 32
144 pe = [''] * 32
145 pw = [''] * 32
146 pads = {'N': pn, 'S': ps, 'E': pe, 'W': pw}
147
148 iopads = []
149 domains = {}
150 clocks = {}
151
152 for (padnum, name, _), bank in zip(p.muxed_cells, p.muxed_cells_bank):
153 orig_name = name
154 domain = None # TODO, get this from the PinSpec. sigh
155 padnum = int(padnum)
156 start = p.bankstart[bank]
157 banknum = padnum - start
158 print banknum, name, bank
159 padbank = pads[bank]
160 # VSS
161 if name.startswith('vss'):
162 #name = 'p_vssick_' + name[-1]
163 #name = 'p_vsseck_0'
164 #name = 'vss'
165 name = ''
166 # VDD
167 elif name.startswith('vdd'):
168 #name = 'p_vddick_' + name[-1]
169 #name = 'p_vddeck_0'
170 #name = 'vdd'
171 name = ''
172 # SYS
173 elif name.startswith('sys'):
174 domain = 'SYS'
175 if name == 'sys_clk':
176 name = 'p_sys_clk_0'
177 elif name == 'sys_rst':
178 #name = 'p_sys_rst_1'
179 iopads.append([name, name, name])
180 padbank[banknum] = name
181 print "sys_rst add", bank, banknum, name
182 name = None
183 elif name == 'sys_pllclk':
184 name = None # ignore
185 elif name == 'sys_pllout':
186 name = 'sys_pll_48_o'
187 iopads.append(['p_' + name, name, name])
188 elif name.startswith('sys_csel'):
189 i = name[-1]
190 name2 = 'sys_clksel_i(%s)' % i
191 name = 'p_sys_clksel_' + i
192 iopads.append([name, name2, name2])
193 #if name:
194 # iopads.append([pname, name, name])
195 print "sys pad", name
196 # SPI Card
197 elif name.startswith('mspi0') or name.startswith('mspi1'):
198 domain = 'MSPI'
199 suffix = name[6:]
200 if suffix == 'ck':
201 suffix = 'clk'
202 elif suffix == 'nss':
203 suffix = 'cs_n'
204 if name.startswith('mspi1'):
205 prefix = 'spi_master_'
206 else:
207 prefix = 'spisdcard_'
208 name = prefix + suffix
209 iopads.append(['p_' + name, name, name])
210 # SD/MMC
211 elif name.startswith('sd0'):
212 domain = 'SD'
213 if name.startswith('sd0_d'):
214 i = name[5:]
215 name = 'sdcard_data' + i
216 name2 = 'sdcard_data_%%s(%s)' % i
217 pad = ['p_' + name, name, name2 % 'o', name2 % 'i',
218 'sdcard_data_oe']
219 iopads.append(pad)
220 elif name.startswith('sd0_cmd'):
221 name = 'sdcard_cmd'
222 name2 = 'sdcard_cmd_%s'
223 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
224 iopads.append(pad)
225 else:
226 name = 'sdcard_' + name[4:]
227 iopads.append(['p_' + name, name, name])
228 # SDRAM
229 elif name.startswith('sdr'):
230 domain = 'SDR'
231 if name == 'sdr_clk':
232 name = 'sdram_clock'
233 iopads.append(['p_' + name, name, name])
234 elif name.startswith('sdr_ad'):
235 i = name[6:]
236 name = 'sdram_a_' + i
237 name2 = 'sdram_a(%s)' % i
238 iopads.append(['p_' + name, name2, name2])
239 elif name.startswith('sdr_ba'):
240 i = name[-1]
241 name = 'sdram_ba_' + i
242 name2 = 'sdram_ba(%s)' % i
243 iopads.append(['p_' + name, name2, name2])
244 elif name.startswith('sdr_dqm'):
245 i = name[-1]
246 name = 'sdram_dm_' + i
247 name2 = 'sdram_dm(%s)' % i
248 iopads.append(['p_' + name, name2, name2])
249 elif name.startswith('sdr_d'):
250 i = name[5:]
251 name = 'sdram_dq_' + i
252 name2 = 'sdram_dq_%%s(%s)' % i
253 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', 'sdram_dq_oe']
254 iopads.append(pad)
255 elif name == 'sdr_csn0':
256 name = 'sdram_cs_n'
257 iopads.append(['p_' + name, name, name])
258 elif name[-1] == 'n':
259 name = 'sdram_' + name[4:-1] + '_n'
260 iopads.append(['p_' + name, name, name])
261 else:
262 name = 'sdram_' + name[4:]
263 iopads.append(['p_' + name, name, name])
264 # UART
265 elif name.startswith('uart'):
266 domain = 'UART'
267 name = 'uart_' + name[6:]
268 iopads.append(['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 iopads.append(pad)
278 # I2C
279 elif name.startswith('twi'):
280 domain = 'TWI'
281 name = 'i2c' + name[3:]
282 if name.startswith('i2c_sda'):
283 name2 = 'i2c_sda_%s'
284 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
285 print ("I2C pad", name, pad)
286 iopads.append(pad)
287 else:
288 iopads.append(['p_' + name, name, name])
289 # EINT
290 elif name.startswith('eint'):
291 i = name[-1]
292 name = 'eint_%s' % i
293 name2 = 'eint(%s)' % i
294 pad = ['p_' + name, name2, name2]
295 iopads.append(pad)
296 # PWM
297 elif name.startswith('pwm'):
298 name = name[:-4]
299 pad = ['p_' + name, name, name]
300 iopads.append(pad)
301 else:
302 pad = ['p_' + name, name, name]
303 iopads.append(pad)
304 print ("GPIO pad", name, pad)
305
306 # JTAG domain
307 if name and name.startswith('jtag'):
308 domain = 'JTAG'
309
310 if name and not name.startswith('p_'):
311 name = 'p_' + name
312 if name is not None:
313 padbank[banknum] = name
314 # create domains
315 if domain is not None:
316 if domain not in domains:
317 domains[domain] = []
318 domains[domain].append(name)
319 dl = domain.lower()
320 if domain in psp.clocks and orig_name.startswith(dl):
321 clk = psp.clocks[domain]
322 if clk.lower() in orig_name: # TODO, might over-match
323 clocks[domain] = name
324
325 # HACK!
326 pe[13] = 'p_vddeck_0'
327 pe[23] = 'p_vsseck_0'
328 pw[10] = 'p_vddick_0'
329 pw[17] = 'p_vssick_0'
330
331 # not connected
332 nc_idx = 0
333 for pl in [pe, pw, pn, ps]:
334 for i in range(len(pl)):
335 if pl[i] == '':
336 pl[i] = 'nc_%d' % nc_idx
337 nc_idx += 1
338
339 print p.bankstart
340 pprint(psp.clocks)
341
342 print
343 print "N pads", pn
344 print "S pads", ps
345 print "E pads", pe
346 print "W pads", pw
347
348 # do not want these
349 del clocks['SYS']
350 del domains['SYS']
351
352 print "chip domains (excluding sys-default)"
353 pprint(domains)
354 print "chip clocks (excluding sys-default)"
355 pprint(clocks)
356
357 chip = {
358 'pads.south' : ps,
359 'pads.east' : pe,
360 'pads.north' : pn,
361 'pads.west' : pw,
362 'pads.instances' : iopads,
363 'chip.domains' : domains,
364 'chip.clocks' : clocks,
365 }
366
367 chip = json.dumps(chip)
368 with open("ls180/litex_pinpads.json", "w") as f:
369 f.write(chip)
370