package common import ( "strconv" "sync" "review.coreboot.org/coreboot.git/util/intelp2m/config" ) type Fields interface { DecodeDW0() DecodeDW1() GenerateString() } const ( PAD_OWN_ACPI = 0 PAD_OWN_DRIVER = 1 ) const ( TxLASTRxE = 0x0 Tx0RxDCRx0 = 0x1 Tx0RxDCRx1 = 0x2 Tx1RxDCRx0 = 0x3 Tx1RxDCRx1 = 0x4 Tx0RxE = 0x5 Tx1RxE = 0x6 HIZCRx0 = 0x7 HIZCRx1 = 0x8 TxDRxE = 0x9 StandbyIgnore = 0xf ) const ( IOSTERM_SAME = 0x0 IOSTERM_DISPUPD = 0x1 IOSTERM_ENPD = 0x2 IOSTERM_ENPU = 0x3 ) const ( TRIG_LEVEL = 0 TRIG_EDGE_SINGLE = 1 TRIG_OFF = 2 TRIG_EDGE_BOTH = 3 ) const ( RST_PWROK = 0 RST_DEEP = 1 RST_PLTRST = 2 RST_RSMRST = 3 ) // PlatformSpecific - platform-specific interface type PlatformSpecific interface { RemmapRstSrc() Pull() GpiMacroAdd() GpoMacroAdd() NativeFunctionMacroAdd() NoConnMacroAdd() } // Macro - contains macro information and methods // Platform : platform-specific interface // padID : pad ID string // str : macro string entirely // Reg : structure of configuration register values and their masks type Macro struct { Platform PlatformSpecific Reg [MAX_DW_NUM]Register padID string str string ownership uint8 Fields } var instanceMacro *Macro var once sync.Once // GetInstance returns singleton func GetInstanceMacro(p PlatformSpecific, f Fields) *Macro { once.Do(func() { instanceMacro = &Macro{ Platform : p, Fields : f } }) return instanceMacro } func GetMacro() *Macro { return GetInstanceMacro(nil, nil) } func (macro *Macro) PadIdGet() string { return macro.padID } func (macro *Macro) PadIdSet(padid string) *Macro { macro.padID = padid return macro } func (macro *Macro) SetPadOwnership(own uint8) *Macro { macro.ownership = own return macro } func (macro *Macro) IsOwnershipDriver() bool { return macro.ownership == PAD_OWN_DRIVER } // returns data configuration structure // number : register number func (macro *Macro) Register(number uint8) *Register { return ¯o.Reg[number] } // add a string to macro func (macro *Macro) Add(str string) *Macro { macro.str += str return macro } // set a string in a macro instead of its previous contents func (macro *Macro) Set(str string) *Macro { macro.str = str return macro } // get macro string func (macro *Macro) Get() string { return macro.str } // set a string in a macro instead of its previous contents func (macro *Macro) Clear() *Macro { macro.Set("") return macro } // Adds PAD Id to the macro as a new argument // return: Macro func (macro *Macro) Id() *Macro { return macro.Add(macro.padID) } // Add Separator to macro if needed func (macro *Macro) Separator() *Macro { str := macro.Get() c := str[len(str)-1] if c != '(' && c != '_' { macro.Add(", ") } return macro } // Adds the PADRSTCFG parameter from DW0 to the macro as a new argument // return: Macro func (macro *Macro) Rstsrc() *Macro { dw0 := macro.Register(PAD_CFG_DW0) var resetsrc = map[uint8]string { 0: "PWROK", 1: "DEEP", 2: "PLTRST", 3: "RSMRST", } return macro.Separator().Add(resetsrc[dw0.GetResetConfig()]) } // Adds The Pad Termination (TERM) parameter from DW1 to the macro as a new argument // return: Macro func (macro *Macro) Pull() *Macro { macro.Platform.Pull() return macro } // Adds Pad GPO value to macro string as a new argument // return: Macro func (macro *Macro) Val() *Macro { dw0 := macro.Register(PAD_CFG_DW0) return macro.Separator().Add(strconv.Itoa(int(dw0.GetGPIOTXState()))) } // Adds Pad GPO value to macro string as a new argument // return: Macro func (macro *Macro) Trig() *Macro { dw0 := macro.Register(PAD_CFG_DW0) var trig = map[uint8]string{ 0x0: "LEVEL", 0x1: "EDGE_SINGLE", 0x2: "OFF", 0x3: "EDGE_BOTH", } return macro.Separator().Add(trig[dw0.GetRXLevelEdgeConfiguration()]) } // Adds Pad Polarity Inversion Stage (RXINV) to macro string as a new argument // return: Macro func (macro *Macro) Invert() *Macro { macro.Separator() if macro.Register(PAD_CFG_DW0).GetRxInvert() !=0 { return macro.Add("INVERT") } return macro.Add("NONE") } // Adds input/output buffer state // return: Macro func (macro *Macro) Bufdis() *Macro { var buffDisStat = map[uint8]string{ 0x0: "NO_DISABLE", // both buffers are enabled 0x1: "TX_DISABLE", // output buffer is disabled 0x2: "RX_DISABLE", // input buffer is disabled 0x3: "TX_RX_DISABLE", // both buffers are disabled } state := macro.Register(PAD_CFG_DW0).GetGPIORxTxDisableStatus() return macro.Separator().Add(buffDisStat[state]) } // Adds macro to set the host software ownership // return: Macro func (macro *Macro) Own() *Macro { if macro.IsOwnershipDriver() { return macro.Separator().Add("DRIVER") } return macro.Separator().Add("ACPI") } //Adds pad native function (PMODE) as a new argument //return: Macro func (macro *Macro) Padfn() *Macro { dw0 := macro.Register(PAD_CFG_DW0) nfnum := int(dw0.GetPadMode()) if nfnum != 0 { return macro.Separator().Add("NF" + strconv.Itoa(nfnum)) } // GPIO used only for PAD_FUNC(x) macro return macro.Add("GPIO") } // Add a line to the macro that defines IO Standby State // return: macro func (macro *Macro) IOSstate() *Macro { var stateMacro = map[uint8]string{ TxLASTRxE: "TxLASTRxE", Tx0RxDCRx0: "Tx0RxDCRx0", Tx0RxDCRx1: "Tx0RxDCRx1", Tx1RxDCRx0: "Tx1RxDCRx0", Tx1RxDCRx1: "Tx1RxDCRx1", Tx0RxE: "Tx0RxE", Tx1RxE: "Tx1RxE", HIZCRx0: "HIZCRx0", HIZCRx1: "HIZCRx1", TxDRxE: "TxDRxE", StandbyIgnore: "IGNORE", } dw1 := macro.Register(PAD_CFG_DW1) str, valid := stateMacro[dw1.GetIOStandbyState()] if !valid { // ignore setting for incorrect value str = "IGNORE" } return macro.Separator().Add(str) } // Add a line to the macro that defines IO Standby Termination // return: macro func (macro *Macro) IOTerm() *Macro { var ioTermMacro = map[uint8]string{ IOSTERM_SAME: "SAME", IOSTERM_DISPUPD: "DISPUPD", IOSTERM_ENPD: "ENPD", IOSTERM_ENPU: "ENPU", } dw1 := macro.Register(PAD_CFG_DW1) return macro.Separator().Add(ioTermMacro[dw1.GetIOStandbyTermination()]) } // Check created macro func (macro *Macro) check() *Macro { if !macro.Register(PAD_CFG_DW0).MaskCheck() { return macro.GenerateFields() } return macro } // or - Set " | " if its needed func (macro *Macro) Or() *Macro { if str := macro.Get(); str[len(str) - 1] == ')' { macro.Add(" | ") } return macro } // DecodeIgnored - Add info about ignored field mask // reg : PAD_CFG_DW0 or PAD_CFG_DW1 register func (macro *Macro) DecodeIgnored(reg uint8) *Macro { var decode = map[uint8]func() { PAD_CFG_DW0: macro.Fields.DecodeDW0, PAD_CFG_DW1: macro.Fields.DecodeDW1, } decodefn, valid := decode[reg] if !valid || config.IsFspStyleMacro() { return macro } dw := macro.Register(reg) ignored := dw.IgnoredFieldsGet() if ignored != 0 { temp := dw.ValueGet() dw.ValueSet(ignored) regnum := strconv.Itoa(int(reg)) macro.Add("/* DW" + regnum + ": ") decodefn() macro.Add(" - IGNORED */\n\t") dw.ValueSet(temp) } return macro } // GenerateFields - generate bitfield macros func (macro *Macro) GenerateFields() *Macro { dw0 := macro.Register(PAD_CFG_DW0) dw1 := macro.Register(PAD_CFG_DW1) // Get mask of ignored bit fields. dw0Ignored := dw0.IgnoredFieldsGet() dw1Ignored := dw1.IgnoredFieldsGet() if config.InfoLevelGet() != 4 { macro.Clear() } if config.InfoLevelGet() >= 3 { // Add string of reference macro as a comment reference := macro.Get() macro.Clear() /* DW0 : PAD_TRIG(OFF) | PAD_BUF(RX_DISABLE) | 1 - IGNORED */ macro.DecodeIgnored(PAD_CFG_DW0).DecodeIgnored(PAD_CFG_DW1) if config.InfoLevelGet() >= 4 { /* PAD_CFG_NF(GPP_B23, 20K_PD, PLTRST, NF2), */ macro.Add("/* ").Add(reference).Add(" */\n\t") } } if config.AreFieldsIgnored() { // Consider bit fields that should be ignored when regenerating // advansed macros var tempVal uint32 = dw0.ValueGet() & ^dw0Ignored dw0.ValueSet(tempVal) tempVal = dw1.ValueGet() & ^dw1Ignored dw1.ValueSet(tempVal) } macro.Fields.GenerateString() return macro } // Generate macro for bi-directional GPIO port func (macro *Macro) Bidirection() { dw1 := macro.Register(PAD_CFG_DW1) ios := dw1.GetIOStandbyState() != 0 || dw1.GetIOStandbyTermination() != 0 macro.Set("PAD_CFG_GPIO_BIDIRECT") if ios { macro.Add("_IOS") } // PAD_CFG_GPIO_BIDIRECT(pad, val, pull, rst, trig, own) macro.Add("(").Id().Val().Pull().Rstsrc().Trig() if ios { // PAD_CFG_GPIO_BIDIRECT_IOS(pad, val, pull, rst, trig, iosstate, iosterm, own) macro.IOSstate().IOTerm() } macro.Own().Add("),") } const ( rxDisable uint8 = 0x2 txDisable uint8 = 0x1 ) // Gets base string of current macro // return: string of macro func (macro *Macro) Generate() string { dw0 := macro.Register(PAD_CFG_DW0) macro.Platform.RemmapRstSrc() macro.Set("PAD_CFG") if dw0.GetPadMode() == 0 { // GPIO switch dw0.GetGPIORxTxDisableStatus() { case txDisable: macro.Platform.GpiMacroAdd() // GPI case rxDisable: macro.Platform.GpoMacroAdd() // GPO case rxDisable | txDisable: macro.Platform.NoConnMacroAdd() // NC default: macro.Bidirection() } } else { macro.Platform.NativeFunctionMacroAdd() } if config.IsFieldsMacroUsed() { // Clear control mask to generate advanced macro only return macro.GenerateFields().Get() } if config.IsNonCheckingFlagUsed() { body := macro.Get() if config.InfoLevelGet() >= 3 { macro.Clear().DecodeIgnored(PAD_CFG_DW0).DecodeIgnored(PAD_CFG_DW1) comment := macro.Get() if config.InfoLevelGet() >= 4 { macro.Clear().Add("/* ") macro.Fields.GenerateString() macro.Add(" */\n\t") comment += macro.Get() } return comment + body } return body } return macro.check().Get() }