X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmain%2Fscala%2Fdevices%2Fgpio%2FGPIO.scala;h=e7a48299d132df91965224608386f61812b810f4;hb=ef4f2ed888cd614858c6b2647c1eb6f988ff3973;hp=9dd8d87ba58ef8d6da8da59263fa5fd771641a14;hpb=64bff444622bf7a61a84ed6cdda8aa6ddd5119cf;p=sifive-blocks.git diff --git a/src/main/scala/devices/gpio/GPIO.scala b/src/main/scala/devices/gpio/GPIO.scala index 9dd8d87..e7a4829 100644 --- a/src/main/scala/devices/gpio/GPIO.scala +++ b/src/main/scala/devices/gpio/GPIO.scala @@ -2,35 +2,26 @@ package sifive.blocks.devices.gpio import Chisel._ -import config.Parameters -import regmapper._ -import uncore.tilelink2._ -import util.AsyncResetRegVec - -case class GPIOParams(address: BigInt, width: Int) - -// YAGNI: Make the PUE, DS, and -// these also optionally HW controllable. -// This is the base class of things you "always" -// want to control from a HW block. -class GPIOCtrl extends Bundle { - val oval = Bool() - val oe = Bool() - val ie = Bool() -} +import sifive.blocks.devices.pinctrl.{PinCtrl, Pin, BasePin, EnhancedPin, EnhancedPinCtrl} +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.regmapper._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.{AsyncResetRegVec, GenericParameterizedBundle} + +case class GPIOParams(address: BigInt, width: Int, includeIOF: Boolean = false) -// This is the actual IOF interface. +// This is the actual IOF interface.pa // Add a valid bit to indicate whether // there is something actually connected // to this. -class GPIOPinIOFCtrl extends GPIOCtrl { +class IOFCtrl extends PinCtrl { val valid = Bool() } // By default, -object GPIOPinIOFCtrl { - def apply(): GPIOPinIOFCtrl = { - val iof = Wire(new GPIOPinIOFCtrl()) +object IOFCtrl { + def apply(): IOFCtrl = { + val iof = Wire(new IOFCtrl()) iof.valid := Bool(false) iof.oval := Bool(false) iof.oe := Bool(false) @@ -39,53 +30,42 @@ object GPIOPinIOFCtrl { } } -// This is the control for a physical -// Pad. - -class GPIOPinCtrl extends GPIOCtrl { - val pue = Bool() // Pull-up Enable - val ds = Bool() // Drive Strength -} - -object GPIOPinCtrl { - def apply(): GPIOPinCtrl = { - val pin = Wire(new GPIOPinCtrl()) - pin.oval := Bool(false) - pin.oe := Bool(false) - pin.pue := Bool(false) - pin.ds := Bool(false) - pin.ie := Bool(false) - pin - } -} - // Package up the inputs and outputs // for the IOF -class GPIOPinIOF extends Bundle { - val i = new Bundle { - val ival = Bool(INPUT) +class IOFPin extends Pin { + val o = new IOFCtrl().asOutput + + def default(): Unit = { + this.o.oval := Bool(false) + this.o.oe := Bool(false) + this.o.ie := Bool(false) + this.o.valid := Bool(false) + } + + def inputPin(pue: Bool = Bool(false) /*ignored*/): Bool = { + this.o.oval := Bool(false) + this.o.oe := Bool(false) + this.o.ie := Bool(true) + this.i.ival + } + def outputPin(signal: Bool, + pue: Bool = Bool(false), /*ignored*/ + ds: Bool = Bool(false), /*ignored*/ + ie: Bool = Bool(false) + ): Unit = { + this.o.oval := signal + this.o.oe := Bool(true) + this.o.ie := ie } - val o = new GPIOPinIOFCtrl().asOutput } // Connect both the i and o side of the pin, // and drive the valid signal for the IOF. -object GPIOPinToIOF { - - def apply (pin: GPIOPin, iof: GPIOPinIOF): Unit = { +object BasePinToIOF { + def apply(pin: BasePin, iof: IOFPin): Unit = { iof <> pin iof.o.valid := Bool(true) } - -} - -// Package up the inputs and outputs -// for the Pin -class GPIOPin extends Bundle { - val i = new Bundle { - val ival = Bool(INPUT) - } - val o = new GPIOPinCtrl().asOutput } // This is sort of weird because @@ -93,10 +73,10 @@ class GPIOPin extends Bundle { // level, and we have to do the pinmux // outside of RocketChipTop. -class GPIOPortIO(c: GPIOParams) extends Bundle { - val pins = Vec(c.width, new GPIOPin) - val iof_0 = Vec(c.width, new GPIOPinIOF).flip - val iof_1 = Vec(c.width, new GPIOPinIOF).flip +class GPIOPortIO(c: GPIOParams) extends GenericParameterizedBundle(c) { + val pins = Vec(c.width, new EnhancedPin()) + val iof_0 = if (c.includeIOF) Some(Vec(c.width, new IOFPin).flip) else None + val iof_1 = if (c.includeIOF) Some(Vec(c.width, new IOFPin).flip) else None } // It would be better if the IOF were here and @@ -142,7 +122,7 @@ trait HasGPIOModuleContents extends Module with HasRegMap { // HW IO Function val iofEnReg = Module(new AsyncResetRegVec(c.width, 0)) val iofSelReg = Reg(init = UInt(0, c.width)) - + // Invert Output val xorReg = Reg(init = UInt(0, c.width)) @@ -153,6 +133,10 @@ trait HasGPIOModuleContents extends Module with HasRegMap { val rise = ~valueReg & inSyncReg; val fall = valueReg & ~inSyncReg; + val iofEnFields = if (c.includeIOF) (Seq(RegField.rwReg(c.width, iofEnReg.io))) else (Seq(RegField(c.width))) + val iofSelFields = if (c.includeIOF) (Seq(RegField(c.width, iofSelReg))) else (Seq(RegField(c.width))) + + // Note that these are out of order. regmap( GPIOCtrlRegs.value -> Seq(RegField.r(c.width, valueReg)), @@ -167,8 +151,8 @@ trait HasGPIOModuleContents extends Module with HasRegMap { GPIOCtrlRegs.low_ip -> Seq(RegField.w1ToClear(c.width,lowIpReg, ~valueReg)), GPIOCtrlRegs.port -> Seq(RegField(c.width, portReg)), GPIOCtrlRegs.pullup_en -> Seq(RegField.rwReg(c.width, pueReg.io)), - GPIOCtrlRegs.iof_en -> Seq(RegField.rwReg(c.width, iofEnReg.io)), - GPIOCtrlRegs.iof_sel -> Seq(RegField(c.width, iofSelReg)), + GPIOCtrlRegs.iof_en -> iofEnFields, + GPIOCtrlRegs.iof_sel -> iofSelFields, GPIOCtrlRegs.drive -> Seq(RegField(c.width, dsReg)), GPIOCtrlRegs.input_en -> Seq(RegField.rwReg(c.width, ieReg.io)), GPIOCtrlRegs.out_xor -> Seq(RegField(c.width, xorReg)) @@ -179,15 +163,14 @@ trait HasGPIOModuleContents extends Module with HasRegMap { // Actual Pinmux // ------------------------------------------------- - val swPinCtrl = Wire(Vec(c.width, new GPIOPinCtrl())) + val swPinCtrl = Wire(Vec(c.width, new EnhancedPinCtrl())) // This strips off the valid. - val iof0Ctrl = Wire(Vec(c.width, new GPIOCtrl())) - val iof1Ctrl = Wire(Vec(c.width, new GPIOCtrl())) - - val iofCtrl = Wire(Vec(c.width, new GPIOCtrl())) - val iofPlusSwPinCtrl = Wire(Vec(c.width, new GPIOPinCtrl())) + val iof0Ctrl = Wire(Vec(c.width, new EnhancedPinCtrl())) + val iof1Ctrl = Wire(Vec(c.width, new EnhancedPinCtrl())) + val iofCtrl = Wire(Vec(c.width, new EnhancedPinCtrl())) + val iofPlusSwPinCtrl = Wire(Vec(c.width, new EnhancedPinCtrl())) for (pin <- 0 until c.width) { @@ -198,26 +181,33 @@ trait HasGPIOModuleContents extends Module with HasRegMap { swPinCtrl(pin).ds := dsReg(pin) swPinCtrl(pin).ie := ieReg.io.q(pin) - // Allow SW Override for invalid inputs. - iof0Ctrl(pin) <> swPinCtrl(pin) - when (io.port.iof_0(pin).o.valid) { - iof0Ctrl(pin) <> io.port.iof_0(pin).o - } - - iof1Ctrl(pin) <> swPinCtrl(pin) - when (io.port.iof_1(pin).o.valid) { - iof1Ctrl(pin) <> io.port.iof_1(pin).o + val pre_xor = Wire(new EnhancedPinCtrl()) + + if (c.includeIOF) { + // Allow SW Override for invalid inputs. + iof0Ctrl(pin) <> swPinCtrl(pin) + when (io.port.iof_0.get(pin).o.valid) { + iof0Ctrl(pin) <> io.port.iof_0.get(pin).o + } + + iof1Ctrl(pin) <> swPinCtrl(pin) + when (io.port.iof_1.get(pin).o.valid) { + iof1Ctrl(pin) <> io.port.iof_1.get(pin).o + } + + // Select IOF 0 vs. IOF 1. + iofCtrl(pin) <> Mux(iofSelReg(pin), iof1Ctrl(pin), iof0Ctrl(pin)) + + // Allow SW Override for things IOF doesn't control. + iofPlusSwPinCtrl(pin) <> swPinCtrl(pin) + iofPlusSwPinCtrl(pin) <> iofCtrl(pin) + + // Final XOR & Pin Control + pre_xor := Mux(iofEnReg.io.q(pin), iofPlusSwPinCtrl(pin), swPinCtrl(pin)) + } else { + pre_xor := swPinCtrl(pin) } - // Select IOF 0 vs. IOF 1. - iofCtrl(pin) <> Mux(iofSelReg(pin), iof1Ctrl(pin), iof0Ctrl(pin)) - - // Allow SW Override for things IOF doesn't control. - iofPlusSwPinCtrl(pin) <> swPinCtrl(pin) - iofPlusSwPinCtrl(pin) <> iofCtrl(pin) - - // Final XOR & Pin Control - val pre_xor: GPIOPinCtrl = Mux(iofEnReg.io.q(pin), iofPlusSwPinCtrl(pin), swPinCtrl(pin)) io.port.pins(pin).o := pre_xor io.port.pins(pin).o.oval := pre_xor.oval ^ xorReg(pin) @@ -227,61 +217,12 @@ trait HasGPIOModuleContents extends Module with HasRegMap { (highIpReg(pin) & highIeReg(pin)) | (lowIpReg(pin) & lowIeReg(pin)) - // Send Value to all consumers - io.port.iof_0(pin).i.ival := inSyncReg(pin) - io.port.iof_1(pin).i.ival := inSyncReg(pin) - } -} - -object GPIOOutputPinCtrl { - - def apply( pin: GPIOPin, signal: Bool, - pue: Bool = Bool(false), - ds: Bool = Bool(false), - ie: Bool = Bool(false) - ): Unit = { - pin.o.oval := signal - pin.o.oe := Bool(true) - pin.o.pue := pue - pin.o.ds := ds - pin.o.ie := ie - } - - def apply(pins: Vec[GPIOPin], signals: Bits, - pue: Bool, ds: Bool, ie: Bool - ): Unit = { - for ((signal, pin) <- (signals.toBools zip pins)) { - apply(pin, signal, pue, ds, ie) + if (c.includeIOF) { + // Send Value to all consumers + io.port.iof_0.get(pin).i.ival := inSyncReg(pin) + io.port.iof_1.get(pin).i.ival := inSyncReg(pin) } } - - def apply(pins: Vec[GPIOPin], signals: Bits): Unit = apply(pins, signals, - Bool(false), Bool(false), Bool(false)) - -} - -object GPIOInputPinCtrl { - - def apply (pin: GPIOPin, pue: Bool = Bool(false)): Bool = { - pin.o.oval := Bool(false) - pin.o.oe := Bool(false) - pin.o.pue := pue - pin.o.ds := Bool(false) - pin.o.ie := Bool(true) - - pin.i.ival - } - - def apply (pins: Vec[GPIOPin], pue: Bool): Vec[Bool] = { - val signals = Wire(Vec.fill(pins.size)(Bool(false))) - for ((signal, pin) <- (signals zip pins)) { - signal := GPIOInputPinCtrl(pin, pue) - } - signals - } - - def apply (pins: Vec[GPIOPin]): Vec[Bool] = apply(pins, Bool(false)) - } // Magic TL2 Incantation to create a TL2 Slave