1package common 2 3import ( 4 "strconv" 5 "sync" 6 7 "review.coreboot.org/coreboot.git/util/intelp2m/config" 8) 9 10type Fields interface { 11 DecodeDW0() 12 DecodeDW1() 13 GenerateString() 14} 15 16const ( 17 PAD_OWN_ACPI = 0 18 PAD_OWN_DRIVER = 1 19) 20 21const ( 22 TxLASTRxE = 0x0 23 Tx0RxDCRx0 = 0x1 24 Tx0RxDCRx1 = 0x2 25 Tx1RxDCRx0 = 0x3 26 Tx1RxDCRx1 = 0x4 27 Tx0RxE = 0x5 28 Tx1RxE = 0x6 29 HIZCRx0 = 0x7 30 HIZCRx1 = 0x8 31 TxDRxE = 0x9 32 StandbyIgnore = 0xf 33) 34 35const ( 36 IOSTERM_SAME = 0x0 37 IOSTERM_DISPUPD = 0x1 38 IOSTERM_ENPD = 0x2 39 IOSTERM_ENPU = 0x3 40) 41 42const ( 43 TRIG_LEVEL = 0 44 TRIG_EDGE_SINGLE = 1 45 TRIG_OFF = 2 46 TRIG_EDGE_BOTH = 3 47) 48 49const ( 50 RST_PWROK = 0 51 RST_DEEP = 1 52 RST_PLTRST = 2 53 RST_RSMRST = 3 54) 55 56// PlatformSpecific - platform-specific interface 57type PlatformSpecific interface { 58 RemmapRstSrc() 59 Pull() 60 GpiMacroAdd() 61 GpoMacroAdd() 62 NativeFunctionMacroAdd() 63 NoConnMacroAdd() 64} 65 66// Macro - contains macro information and methods 67// Platform : platform-specific interface 68// padID : pad ID string 69// str : macro string entirely 70// Reg : structure of configuration register values and their masks 71type Macro struct { 72 Platform PlatformSpecific 73 Reg [MAX_DW_NUM]Register 74 padID string 75 str string 76 ownership uint8 77 Fields 78} 79 80var instanceMacro *Macro 81var once sync.Once 82 83// GetInstance returns singleton 84func GetInstanceMacro(p PlatformSpecific, f Fields) *Macro { 85 once.Do(func() { 86 instanceMacro = &Macro{ Platform : p, Fields : f } 87 }) 88 return instanceMacro 89} 90 91func GetMacro() *Macro { 92 return GetInstanceMacro(nil, nil) 93} 94 95func (macro *Macro) PadIdGet() string { 96 return macro.padID 97} 98 99func (macro *Macro) PadIdSet(padid string) *Macro { 100 macro.padID = padid 101 return macro 102} 103 104func (macro *Macro) SetPadOwnership(own uint8) *Macro { 105 macro.ownership = own 106 return macro 107} 108 109func (macro *Macro) IsOwnershipDriver() bool { 110 return macro.ownership == PAD_OWN_DRIVER 111} 112 113// returns <Register> data configuration structure 114// number : register number 115func (macro *Macro) Register(number uint8) *Register { 116 return ¯o.Reg[number] 117} 118 119// add a string to macro 120func (macro *Macro) Add(str string) *Macro { 121 macro.str += str 122 return macro 123} 124 125// set a string in a macro instead of its previous contents 126func (macro *Macro) Set(str string) *Macro { 127 macro.str = str 128 return macro 129} 130 131// get macro string 132func (macro *Macro) Get() string { 133 return macro.str 134} 135 136// set a string in a macro instead of its previous contents 137func (macro *Macro) Clear() *Macro { 138 macro.Set("") 139 return macro 140} 141 142// Adds PAD Id to the macro as a new argument 143// return: Macro 144func (macro *Macro) Id() *Macro { 145 return macro.Add(macro.padID) 146} 147 148// Add Separator to macro if needed 149func (macro *Macro) Separator() *Macro { 150 str := macro.Get() 151 c := str[len(str)-1] 152 if c != '(' && c != '_' { 153 macro.Add(", ") 154 } 155 return macro 156} 157 158// Adds the PADRSTCFG parameter from DW0 to the macro as a new argument 159// return: Macro 160func (macro *Macro) Rstsrc() *Macro { 161 dw0 := macro.Register(PAD_CFG_DW0) 162 var resetsrc = map[uint8]string { 163 0: "PWROK", 164 1: "DEEP", 165 2: "PLTRST", 166 3: "RSMRST", 167 } 168 return macro.Separator().Add(resetsrc[dw0.GetResetConfig()]) 169} 170 171// Adds The Pad Termination (TERM) parameter from DW1 to the macro as a new argument 172// return: Macro 173func (macro *Macro) Pull() *Macro { 174 macro.Platform.Pull() 175 return macro 176} 177 178// Adds Pad GPO value to macro string as a new argument 179// return: Macro 180func (macro *Macro) Val() *Macro { 181 dw0 := macro.Register(PAD_CFG_DW0) 182 return macro.Separator().Add(strconv.Itoa(int(dw0.GetGPIOTXState()))) 183} 184 185// Adds Pad GPO value to macro string as a new argument 186// return: Macro 187func (macro *Macro) Trig() *Macro { 188 dw0 := macro.Register(PAD_CFG_DW0) 189 var trig = map[uint8]string{ 190 0x0: "LEVEL", 191 0x1: "EDGE_SINGLE", 192 0x2: "OFF", 193 0x3: "EDGE_BOTH", 194 } 195 return macro.Separator().Add(trig[dw0.GetRXLevelEdgeConfiguration()]) 196} 197 198// Adds Pad Polarity Inversion Stage (RXINV) to macro string as a new argument 199// return: Macro 200func (macro *Macro) Invert() *Macro { 201 macro.Separator() 202 if macro.Register(PAD_CFG_DW0).GetRxInvert() !=0 { 203 return macro.Add("INVERT") 204 } 205 return macro.Add("NONE") 206} 207 208// Adds input/output buffer state 209// return: Macro 210func (macro *Macro) Bufdis() *Macro { 211 var buffDisStat = map[uint8]string{ 212 0x0: "NO_DISABLE", // both buffers are enabled 213 0x1: "TX_DISABLE", // output buffer is disabled 214 0x2: "RX_DISABLE", // input buffer is disabled 215 0x3: "TX_RX_DISABLE", // both buffers are disabled 216 } 217 state := macro.Register(PAD_CFG_DW0).GetGPIORxTxDisableStatus() 218 return macro.Separator().Add(buffDisStat[state]) 219} 220 221// Adds macro to set the host software ownership 222// return: Macro 223func (macro *Macro) Own() *Macro { 224 if macro.IsOwnershipDriver() { 225 return macro.Separator().Add("DRIVER") 226 } 227 return macro.Separator().Add("ACPI") 228} 229 230//Adds pad native function (PMODE) as a new argument 231//return: Macro 232func (macro *Macro) Padfn() *Macro { 233 dw0 := macro.Register(PAD_CFG_DW0) 234 nfnum := int(dw0.GetPadMode()) 235 if nfnum != 0 { 236 return macro.Separator().Add("NF" + strconv.Itoa(nfnum)) 237 } 238 // GPIO used only for PAD_FUNC(x) macro 239 return macro.Add("GPIO") 240} 241 242// Add a line to the macro that defines IO Standby State 243// return: macro 244func (macro *Macro) IOSstate() *Macro { 245 var stateMacro = map[uint8]string{ 246 TxLASTRxE: "TxLASTRxE", 247 Tx0RxDCRx0: "Tx0RxDCRx0", 248 Tx0RxDCRx1: "Tx0RxDCRx1", 249 Tx1RxDCRx0: "Tx1RxDCRx0", 250 Tx1RxDCRx1: "Tx1RxDCRx1", 251 Tx0RxE: "Tx0RxE", 252 Tx1RxE: "Tx1RxE", 253 HIZCRx0: "HIZCRx0", 254 HIZCRx1: "HIZCRx1", 255 TxDRxE: "TxDRxE", 256 StandbyIgnore: "IGNORE", 257 } 258 dw1 := macro.Register(PAD_CFG_DW1) 259 str, valid := stateMacro[dw1.GetIOStandbyState()] 260 if !valid { 261 // ignore setting for incorrect value 262 str = "IGNORE" 263 } 264 return macro.Separator().Add(str) 265} 266 267// Add a line to the macro that defines IO Standby Termination 268// return: macro 269func (macro *Macro) IOTerm() *Macro { 270 var ioTermMacro = map[uint8]string{ 271 IOSTERM_SAME: "SAME", 272 IOSTERM_DISPUPD: "DISPUPD", 273 IOSTERM_ENPD: "ENPD", 274 IOSTERM_ENPU: "ENPU", 275 } 276 dw1 := macro.Register(PAD_CFG_DW1) 277 return macro.Separator().Add(ioTermMacro[dw1.GetIOStandbyTermination()]) 278} 279 280// Check created macro 281func (macro *Macro) check() *Macro { 282 if !macro.Register(PAD_CFG_DW0).MaskCheck() { 283 return macro.GenerateFields() 284 } 285 return macro 286} 287 288// or - Set " | " if its needed 289func (macro *Macro) Or() *Macro { 290 291 if str := macro.Get(); str[len(str) - 1] == ')' { 292 macro.Add(" | ") 293 } 294 return macro 295} 296 297// DecodeIgnored - Add info about ignored field mask 298// reg : PAD_CFG_DW0 or PAD_CFG_DW1 register 299func (macro *Macro) DecodeIgnored(reg uint8) *Macro { 300 var decode = map[uint8]func() { 301 PAD_CFG_DW0: macro.Fields.DecodeDW0, 302 PAD_CFG_DW1: macro.Fields.DecodeDW1, 303 } 304 decodefn, valid := decode[reg] 305 if !valid || config.IsFspStyleMacro() { 306 return macro 307 } 308 dw := macro.Register(reg) 309 ignored := dw.IgnoredFieldsGet() 310 if ignored != 0 { 311 temp := dw.ValueGet() 312 dw.ValueSet(ignored) 313 regnum := strconv.Itoa(int(reg)) 314 macro.Add("/* DW" + regnum + ": ") 315 decodefn() 316 macro.Add(" - IGNORED */\n\t") 317 dw.ValueSet(temp) 318 } 319 return macro 320} 321 322// GenerateFields - generate bitfield macros 323func (macro *Macro) GenerateFields() *Macro { 324 dw0 := macro.Register(PAD_CFG_DW0) 325 dw1 := macro.Register(PAD_CFG_DW1) 326 327 // Get mask of ignored bit fields. 328 dw0Ignored := dw0.IgnoredFieldsGet() 329 dw1Ignored := dw1.IgnoredFieldsGet() 330 331 if config.InfoLevelGet() != 4 { 332 macro.Clear() 333 } 334 if config.InfoLevelGet() >= 3 { 335 // Add string of reference macro as a comment 336 reference := macro.Get() 337 macro.Clear() 338 /* DW0 : PAD_TRIG(OFF) | PAD_BUF(RX_DISABLE) | 1 - IGNORED */ 339 macro.DecodeIgnored(PAD_CFG_DW0).DecodeIgnored(PAD_CFG_DW1) 340 if config.InfoLevelGet() >= 4 { 341 /* PAD_CFG_NF(GPP_B23, 20K_PD, PLTRST, NF2), */ 342 macro.Add("/* ").Add(reference).Add(" */\n\t") 343 } 344 } 345 if config.AreFieldsIgnored() { 346 // Consider bit fields that should be ignored when regenerating 347 // advansed macros 348 var tempVal uint32 = dw0.ValueGet() & ^dw0Ignored 349 dw0.ValueSet(tempVal) 350 351 tempVal = dw1.ValueGet() & ^dw1Ignored 352 dw1.ValueSet(tempVal) 353 } 354 355 macro.Fields.GenerateString() 356 return macro 357} 358 359// Generate macro for bi-directional GPIO port 360func (macro *Macro) Bidirection() { 361 dw1 := macro.Register(PAD_CFG_DW1) 362 ios := dw1.GetIOStandbyState() != 0 || dw1.GetIOStandbyTermination() != 0 363 macro.Set("PAD_CFG_GPIO_BIDIRECT") 364 if ios { 365 macro.Add("_IOS") 366 } 367 // PAD_CFG_GPIO_BIDIRECT(pad, val, pull, rst, trig, own) 368 macro.Add("(").Id().Val().Pull().Rstsrc().Trig() 369 if ios { 370 // PAD_CFG_GPIO_BIDIRECT_IOS(pad, val, pull, rst, trig, iosstate, iosterm, own) 371 macro.IOSstate().IOTerm() 372 } 373 macro.Own().Add("),") 374} 375 376const ( 377 rxDisable uint8 = 0x2 378 txDisable uint8 = 0x1 379) 380 381// Gets base string of current macro 382// return: string of macro 383func (macro *Macro) Generate() string { 384 dw0 := macro.Register(PAD_CFG_DW0) 385 386 macro.Platform.RemmapRstSrc() 387 macro.Set("PAD_CFG") 388 if dw0.GetPadMode() == 0 { 389 // GPIO 390 switch dw0.GetGPIORxTxDisableStatus() { 391 case txDisable: 392 macro.Platform.GpiMacroAdd() // GPI 393 394 case rxDisable: 395 macro.Platform.GpoMacroAdd() // GPO 396 397 case rxDisable | txDisable: 398 macro.Platform.NoConnMacroAdd() // NC 399 400 default: 401 macro.Bidirection() 402 } 403 } else { 404 macro.Platform.NativeFunctionMacroAdd() 405 } 406 407 if config.IsFieldsMacroUsed() { 408 // Clear control mask to generate advanced macro only 409 return macro.GenerateFields().Get() 410 } 411 412 if config.IsNonCheckingFlagUsed() { 413 body := macro.Get() 414 if config.InfoLevelGet() >= 3 { 415 macro.Clear().DecodeIgnored(PAD_CFG_DW0).DecodeIgnored(PAD_CFG_DW1) 416 comment := macro.Get() 417 if config.InfoLevelGet() >= 4 { 418 macro.Clear().Add("/* ") 419 macro.Fields.GenerateString() 420 macro.Add(" */\n\t") 421 comment += macro.Get() 422 } 423 return comment + body 424 } 425 return body 426 } 427 428 return macro.check().Get() 429} 430