1## 2## This file is part of the libsigrokdecode project. 3## 4## Copyright (C) 2012-2013 Uwe Hermann <uwe@hermann-uwe.de> 5## 6## This program is free software; you can redistribute it and/or modify 7## it under the terms of the GNU General Public License as published by 8## the Free Software Foundation; either version 2 of the License, or 9## (at your option) any later version. 10## 11## This program is distributed in the hope that it will be useful, 12## but WITHOUT ANY WARRANTY; without even the implied warranty of 13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14## GNU General Public License for more details. 15## 16## You should have received a copy of the GNU General Public License 17## along with this program; if not, see <http://www.gnu.org/licenses/>. 18## 19 20import sigrokdecode as srd 21 22# ... 23fields = { 24 # START field (indicates start or stop of a transaction) 25 'START': { 26 0b0000: 'Start of cycle for a target', 27 0b0001: 'Reserved', 28 0b0010: 'Grant for bus master 0', 29 0b0011: 'Grant for bus master 1', 30 0b0100: 'Reserved', 31 0b0101: 'Reserved', 32 0b0110: 'Reserved', 33 0b0111: 'Reserved', 34 0b1000: 'Reserved', 35 0b1001: 'Reserved', 36 0b1010: 'Reserved', 37 0b1011: 'Reserved', 38 0b1100: 'Reserved', 39 0b1101: 'Start of cycle for a Firmware Memory Read cycle', 40 0b1110: 'Start of cycle for a Firmware Memory Write cycle', 41 0b1111: 'Stop/abort (end of a cycle for a target)', 42 }, 43 # Cycle type / direction field 44 # Bit 0 (LAD[0]) is unused, should always be 0. 45 # Neither host nor peripheral are allowed to drive 0b11x0. 46 'CT_DR': { 47 0b0000: 'I/O read', 48 0b0010: 'I/O write', 49 0b0100: 'Memory read', 50 0b0110: 'Memory write', 51 0b1000: 'DMA read', 52 0b1010: 'DMA write', 53 0b1100: 'Reserved / not allowed', 54 0b1110: 'Reserved / not allowed', 55 }, 56 # SIZE field (determines how many bytes are to be transferred) 57 # Bits[3:2] are reserved, must be driven to 0b00. 58 # Neither host nor peripheral are allowed to drive 0b0010. 59 'SIZE': { 60 0b0000: '8 bits (1 byte)', 61 0b0001: '16 bits (2 bytes)', 62 0b0010: 'Reserved / not allowed', 63 0b0011: '32 bits (4 bytes)', 64 }, 65 # CHANNEL field (bits[2:0] contain the DMA channel number) 66 'CHANNEL': { 67 0b0000: '0', 68 0b0001: '1', 69 0b0010: '2', 70 0b0011: '3', 71 0b0100: '4', 72 0b0101: '5', 73 0b0110: '6', 74 0b0111: '7', 75 }, 76 # SYNC field (used to add wait states) 77 'SYNC': { 78 0b0000: 'Ready', 79 0b0001: 'Reserved', 80 0b0010: 'Reserved', 81 0b0011: 'Reserved', 82 0b0100: 'Reserved', 83 0b0101: 'Short wait', 84 0b0110: 'Long wait', 85 0b0111: 'Reserved', 86 0b1000: 'Reserved', 87 0b1001: 'Ready more (DMA only)', 88 0b1010: 'Error', 89 0b1011: 'Reserved', 90 0b1100: 'Reserved', 91 0b1101: 'Reserved', 92 0b1110: 'Reserved', 93 0b1111: 'Reserved', 94 }, 95} 96 97class Decoder(srd.Decoder): 98 api_version = 3 99 id = 'lpc' 100 name = 'LPC' 101 longname = 'Low Pin Count' 102 desc = 'Protocol for low-bandwidth devices on PC mainboards.' 103 license = 'gplv2+' 104 inputs = ['logic'] 105 outputs = [] 106 tags = ['PC'] 107 channels = ( 108 {'id': 'lframe', 'name': 'LFRAME#', 'desc': 'Frame'}, 109 {'id': 'lclk', 'name': 'LCLK', 'desc': 'Clock'}, 110 {'id': 'lad0', 'name': 'LAD[0]', 'desc': 'Addr/control/data 0'}, 111 {'id': 'lad1', 'name': 'LAD[1]', 'desc': 'Addr/control/data 1'}, 112 {'id': 'lad2', 'name': 'LAD[2]', 'desc': 'Addr/control/data 2'}, 113 {'id': 'lad3', 'name': 'LAD[3]', 'desc': 'Addr/control/data 3'}, 114 ) 115 optional_channels = ( 116 {'id': 'lreset', 'name': 'LRESET#', 'desc': 'Reset'}, 117 {'id': 'ldrq', 'name': 'LDRQ#', 'desc': 'Encoded DMA / bus master request'}, 118 {'id': 'serirq', 'name': 'SERIRQ', 'desc': 'Serialized IRQ'}, 119 {'id': 'clkrun', 'name': 'CLKRUN#', 'desc': 'Clock run'}, 120 {'id': 'lpme', 'name': 'LPME#', 'desc': 'LPC power management event'}, 121 {'id': 'lpcpd', 'name': 'LPCPD#', 'desc': 'Power down'}, 122 {'id': 'lsmi', 'name': 'LSMI#', 'desc': 'System Management Interrupt'}, 123 ) 124 annotations = ( 125 ('warnings', 'Warnings'), 126 ('start', 'Start'), 127 ('cycle-type', 'Cycle-type/direction'), 128 ('addr', 'Address'), 129 ('tar1', 'Turn-around cycle 1'), 130 ('sync', 'Sync'), 131 ('data', 'Data'), 132 ('tar2', 'Turn-around cycle 2'), 133 ) 134 annotation_rows = ( 135 ('data', 'Data', (1, 2, 3, 4, 5, 6, 7)), 136 ('warnings', 'Warnings', (0,)), 137 ) 138 139 def __init__(self): 140 self.reset() 141 142 def reset(self): 143 self.state = 'IDLE' 144 self.oldlclk = -1 145 self.lad = -1 146 self.addr = 0 147 self.cur_nibble = 0 148 self.cycle_type = -1 149 self.databyte = 0 150 self.tarcount = 0 151 self.synccount = 0 152 self.oldpins = None 153 self.ss_block = self.es_block = None 154 155 def start(self): 156 self.out_ann = self.register(srd.OUTPUT_ANN) 157 158 def putb(self, data): 159 self.put(self.ss_block, self.es_block, self.out_ann, data) 160 161 def handle_get_start(self, lad, lad_bits, lframe): 162 # LAD[3:0]: START field (1 clock cycle). 163 164 # The last value of LAD[3:0] before LFRAME# gets de-asserted is what 165 # the peripherals must use. However, the host can keep LFRAME# asserted 166 # multiple clocks, and we output all START fields that occur, even 167 # though the peripherals are supposed to ignore all but the last one. 168 self.es_block = self.samplenum 169 self.putb([1, [fields['START'][lad], 'START', 'St', 'S']]) 170 self.ss_block = self.samplenum 171 172 # Output a warning if LAD[3:0] changes while LFRAME# is low. 173 # TODO 174 if (self.lad != -1 and self.lad != lad): 175 self.putb([0, ['LAD[3:0] changed while LFRAME# was asserted']]) 176 177 # LFRAME# is asserted (low). Wait until it gets de-asserted again 178 # (the host is allowed to keep it asserted multiple clocks). 179 if lframe != 1: 180 return 181 182 self.start_field = self.lad 183 self.state = 'GET CT/DR' 184 185 def handle_get_ct_dr(self, lad, lad_bits): 186 # LAD[3:0]: Cycle type / direction field (1 clock cycle). 187 188 self.cycle_type = fields['CT_DR'].get(lad, 'Reserved / unknown') 189 190 # TODO: Warning/error on invalid cycle types. 191 if 'Reserved' in self.cycle_type: 192 self.putb([0, ['Invalid cycle type (%s)' % lad_bits]]) 193 194 self.es_block = self.samplenum 195 self.putb([2, ['Cycle type: %s' % self.cycle_type]]) 196 self.ss_block = self.samplenum 197 198 self.state = 'GET ADDR' 199 self.addr = 0 200 self.cur_nibble = 0 201 202 def handle_get_addr(self, lad, lad_bits): 203 # LAD[3:0]: ADDR field (4/8/0 clock cycles). 204 205 # I/O cycles: 4 ADDR clocks. Memory cycles: 8 ADDR clocks. 206 # DMA cycles: no ADDR clocks at all. 207 if self.cycle_type in ('I/O read', 'I/O write'): 208 addr_nibbles = 4 # Address is 16bits. 209 elif self.cycle_type in ('Memory read', 'Memory write'): 210 addr_nibbles = 8 # Address is 32bits. 211 else: 212 addr_nibbles = 0 # TODO: How to handle later on? 213 214 # Addresses are driven MSN-first. 215 offset = ((addr_nibbles - 1) - self.cur_nibble) * 4 216 self.addr |= (lad << offset) 217 218 # Continue if we haven't seen all ADDR cycles, yet. 219 if (self.cur_nibble < addr_nibbles - 1): 220 self.cur_nibble += 1 221 return 222 223 self.es_block = self.samplenum 224 s = 'Address: 0x%%0%dx' % addr_nibbles 225 self.putb([3, [s % self.addr]]) 226 self.ss_block = self.samplenum 227 228 self.state = 'GET TAR' 229 self.tar_count = 0 230 231 def handle_get_tar(self, lad, lad_bits): 232 # LAD[3:0]: First TAR (turn-around) field (2 clock cycles). 233 234 self.es_block = self.samplenum 235 self.putb([4, ['TAR, cycle %d: %s' % (self.tarcount, lad_bits)]]) 236 self.ss_block = self.samplenum 237 238 # On the first TAR clock cycle LAD[3:0] is driven to 1111 by 239 # either the host or peripheral. On the second clock cycle, 240 # the host or peripheral tri-states LAD[3:0], but its value 241 # should still be 1111, due to pull-ups on the LAD lines. 242 if lad_bits != '1111': 243 self.putb([0, ['TAR, cycle %d: %s (expected 1111)' % \ 244 (self.tarcount, lad_bits)]]) 245 246 if (self.tarcount != 1): 247 self.tarcount += 1 248 return 249 250 self.tarcount = 0 251 self.state = 'GET SYNC' 252 253 def handle_get_sync(self, lad, lad_bits): 254 # LAD[3:0]: SYNC field (1-n clock cycles). 255 256 self.sync_val = lad_bits 257 self.cycle_type = fields['SYNC'].get(lad, 'Reserved / unknown') 258 259 # TODO: Warnings if reserved value are seen? 260 if 'Reserved' in self.cycle_type: 261 self.putb([0, ['SYNC, cycle %d: %s (reserved value)' % \ 262 (self.synccount, self.sync_val)]]) 263 264 self.es_block = self.samplenum 265 self.putb([5, ['SYNC, cycle %d: %s' % (self.synccount, self.sync_val)]]) 266 self.ss_block = self.samplenum 267 268 # TODO 269 270 self.cycle_count = 0 271 self.state = 'GET DATA' 272 273 def handle_get_data(self, lad, lad_bits): 274 # LAD[3:0]: DATA field (2 clock cycles). 275 276 # Data is driven LSN-first. 277 if (self.cycle_count == 0): 278 self.databyte = lad 279 elif (self.cycle_count == 1): 280 self.databyte |= (lad << 4) 281 else: 282 raise Exception('Invalid cycle_count: %d' % self.cycle_count) 283 284 if (self.cycle_count != 1): 285 self.cycle_count += 1 286 return 287 288 self.es_block = self.samplenum 289 self.putb([6, ['DATA: 0x%02x' % self.databyte]]) 290 self.ss_block = self.samplenum 291 292 self.cycle_count = 0 293 self.state = 'GET TAR2' 294 295 def handle_get_tar2(self, lad, lad_bits): 296 # LAD[3:0]: Second TAR field (2 clock cycles). 297 298 self.es_block = self.samplenum 299 self.putb([7, ['TAR, cycle %d: %s' % (self.tarcount, lad_bits)]]) 300 self.ss_block = self.samplenum 301 302 # On the first TAR clock cycle LAD[3:0] is driven to 1111 by 303 # either the host or peripheral. On the second clock cycle, 304 # the host or peripheral tri-states LAD[3:0], but its value 305 # should still be 1111, due to pull-ups on the LAD lines. 306 if lad_bits != '1111': 307 self.putb([0, ['Warning: TAR, cycle %d: %s (expected 1111)' 308 % (self.tarcount, lad_bits)]]) 309 310 if (self.tarcount != 1): 311 self.tarcount += 1 312 return 313 314 self.tarcount = 0 315 self.state = 'IDLE' 316 317 def decode(self): 318 while True: 319 # TODO: Come up with more appropriate self.wait() conditions. 320 pins = self.wait() 321 322 # If none of the pins changed, there's nothing to do. 323 if self.oldpins == pins: 324 continue 325 326 # Store current pin values for the next round. 327 self.oldpins = pins 328 329 # Get individual pin values into local variables. 330 (lframe, lclk, lad0, lad1, lad2, lad3) = pins[:6] 331 (lreset, ldrq, serirq, clkrun, lpme, lpcpd, lsmi) = pins[6:] 332 333 # Only look at the signals upon rising LCLK edges. The LPC clock 334 # is the same as the PCI clock (which is sampled at rising edges). 335 if not (self.oldlclk == 0 and lclk == 1): 336 self.oldlclk = lclk 337 continue 338 339 # Store LAD[3:0] bit values (one nibble) in local variables. 340 # Most (but not all) states need this. 341 if self.state != 'IDLE': 342 lad = (lad3 << 3) | (lad2 << 2) | (lad1 << 1) | lad0 343 lad_bits = '{:04b}'.format(lad) 344 # self.putb([0, ['LAD: %s' % lad_bits]]) 345 346 # TODO: Only memory read/write is currently supported/tested. 347 348 # State machine 349 if self.state == 'IDLE': 350 # A valid LPC cycle starts with LFRAME# being asserted (low). 351 if lframe != 0: 352 continue 353 self.ss_block = self.samplenum 354 self.state = 'GET START' 355 self.lad = -1 356 elif self.state == 'GET START': 357 self.handle_get_start(lad, lad_bits, lframe) 358 elif self.state == 'GET CT/DR': 359 self.handle_get_ct_dr(lad, lad_bits) 360 elif self.state == 'GET ADDR': 361 self.handle_get_addr(lad, lad_bits) 362 elif self.state == 'GET TAR': 363 self.handle_get_tar(lad, lad_bits) 364 elif self.state == 'GET SYNC': 365 self.handle_get_sync(lad, lad_bits) 366 elif self.state == 'GET DATA': 367 self.handle_get_data(lad, lad_bits) 368 elif self.state == 'GET TAR2': 369 self.handle_get_tar2(lad, lad_bits) 370