package sifive.blocks.devices.gpio
import Chisel._
+import sifive.blocks.devices.pinctrl.{PinCtrl, Pin, BasePin, EnhancedPin, EnhancedPinCtrl}
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink._
case class GPIOParams(address: BigInt, width: Int, includeIOF: Boolean = false)
-// 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()
-}
-
-// 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)
}
}
-// 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 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 = {
+ 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
// outside of RocketChipTop.
class GPIOPortIO(c: GPIOParams) extends GenericParameterizedBundle(c) {
- val pins = Vec(c.width, new GPIOPin)
- val iof_0 = if (c.includeIOF) Some(Vec(c.width, new GPIOPinIOF).flip) else None
- val iof_1 = if (c.includeIOF) Some(Vec(c.width, new GPIOPinIOF).flip) else None
+ 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
// 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) {
swPinCtrl(pin).ds := dsReg(pin)
swPinCtrl(pin).ie := ieReg.io.q(pin)
- val pre_xor = Wire(new GPIOPinCtrl())
+ val pre_xor = Wire(new EnhancedPinCtrl())
if (c.includeIOF) {
// Allow SW Override for invalid inputs.
}
}
-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)
- }
- }
-
- 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
class TLGPIO(w: Int, c: GPIOParams)(implicit p: Parameters)
extends TLRegisterRouter(c.address, "gpio", Seq("sifive,gpio0"), interrupts = c.width, beatBytes = w)(
import freechips.rocketchip.config._
import freechips.rocketchip.jtag.{JTAGIO}
+import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
-class JTAGPinsIO(hasTRSTn: Boolean = true) extends Bundle {
+class JTAGPins[T <: Pin](pingen: () => T, hasTRSTn: Boolean = true) extends Bundle {
- val TCK = new GPIOPin()
- val TMS = new GPIOPin()
- val TDI = new GPIOPin()
- val TDO = new GPIOPin()
- val TRSTn = if (hasTRSTn) Option(new GPIOPin()) else None
+ val TCK = pingen()
+ val TMS = pingen()
+ val TDI = pingen()
+ val TDO = pingen()
+ val TRSTn = if (hasTRSTn) Option(pingen()) else None
-}
-
-class JTAGGPIOPort(hasTRSTn: Boolean = true)(implicit p: Parameters) extends Module {
+ def fromJTAGPort(jtag: JTAGIO): Unit = {
+ jtag.TCK := TCK.inputPin (pue = Bool(true)).asClock
+ jtag.TMS := TMS.inputPin (pue = Bool(true))
+ jtag.TDI := TDI.inputPin(pue = Bool(true))
+ jtag.TRSTn.foreach{t => t := TRSTn.get.inputPin(pue = Bool(true))}
- val io = new Bundle {
- // TODO: make this not hard-coded true.
- val jtag = new JTAGIO(hasTRSTn)
- val pins = new JTAGPinsIO(hasTRSTn)
+ TDO.outputPin(jtag.TDO.data)
+ TDO.o.oe := jtag.TDO.driven
}
-
- io.jtag.TCK := GPIOInputPinCtrl(io.pins.TCK, pue = Bool(true)).asClock
- io.jtag.TMS := GPIOInputPinCtrl(io.pins.TMS, pue = Bool(true))
- io.jtag.TDI := GPIOInputPinCtrl(io.pins.TDI, pue = Bool(true))
- io.jtag.TRSTn.foreach{t => t := GPIOInputPinCtrl(io.pins.TRSTn.get, pue = Bool(true))}
-
- GPIOOutputPinCtrl(io.pins.TDO, io.jtag.TDO.data)
- io.pins.TDO.o.oe := io.jtag.TDO.driven
}
import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.{AsyncResetRegVec, Majority}
-import sifive.blocks.devices.gpio.{GPIOPinCtrl}
case class I2CParams(address: BigInt)
trait HasPeripheryI2CBundle {
val i2cs: Vec[I2CPort]
-
- def I2CtoGPIOPins(syncStages: Int = 0): Seq[I2CPinsIO] = i2cs.map { i =>
- val pins = Module(new I2CGPIOPort(syncStages))
- pins.io.i2c <> i
- pins.io.pins
- }
}
trait HasPeripheryI2CModuleImp extends LazyMultiIOModuleImp with HasPeripheryI2CBundle {
package sifive.blocks.devices.i2c
import Chisel._
-import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl}
+import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
import sifive.blocks.util.ShiftRegisterInit
-class I2CPinsIO extends Bundle {
- val scl = new GPIOPin
- val sda = new GPIOPin
-}
+class I2CPins[T <: Pin](pingen: () => T) extends Bundle {
-class I2CGPIOPort(syncStages: Int = 0) extends Module {
- val io = new Bundle{
- val i2c = new I2CPort().flip()
- val pins = new I2CPinsIO
- }
+ val scl: T = pingen()
+ val sda: T = pingen()
- GPIOOutputPinCtrl(io.pins.scl, io.i2c.scl.out, pue=true.B, ie = true.B)
- io.pins.scl.o.oe := io.i2c.scl.oe
- io.i2c.scl.in := ShiftRegisterInit(io.pins.scl.i.ival, syncStages, Bool(true))
+ def fromI2CPort(i2c: I2CPort, syncStages: Int = 0) = {
+ scl.outputPin(i2c.scl.out, pue=true.B, ie = true.B)
+ scl.o.oe := i2c.scl.oe
+ i2c.scl.in := ShiftRegisterInit(scl.i.ival, syncStages, Bool(true))
- GPIOOutputPinCtrl(io.pins.sda, io.i2c.sda.out, pue=true.B, ie = true.B)
- io.pins.sda.o.oe := io.i2c.sda.oe
- io.i2c.sda.in := ShiftRegisterInit(io.pins.sda.i.ival, syncStages, Bool(true))
+ sda.outputPin(i2c.sda.out, pue=true.B, ie = true.B)
+ sda.o.oe := i2c.sda.oe
+ i2c.sda.in := ShiftRegisterInit(sda.i.ival, syncStages, Bool(true))
+ }
}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._
-import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
+import sifive.blocks.devices.pinctrl.{EnhancedPin}
import sifive.blocks.util.{DeglitchShiftRegister, ResetCatchAndSync}
/* The wrapper handles the Clock and Reset Generation for The AON block itself,
and instantiates real pad controls (aka pull-ups)*/
class MockAONWrapperPMUIO extends Bundle {
- val dwakeup_n = new GPIOPin()
- val vddpaden = new GPIOPin()
+ val dwakeup_n = new EnhancedPin()
+ val vddpaden = new EnhancedPin()
}
class MockAONWrapperPadsIO extends Bundle {
- val erst_n = new GPIOPin()
- val lfextclk = new GPIOPin()
+ val erst_n = new EnhancedPin()
+ val lfextclk = new EnhancedPin()
val pmu = new MockAONWrapperPMUIO()
}
// -----------------------------------------------
// ERST
- val erst = ~ GPIOInputPinCtrl(pads.erst_n, pue = Bool(true))
+ val erst = ~pads.erst_n.inputPin(pue = Bool(true))
aon_io.resetCauses.erst := erst
aon_io.resetCauses.wdogrst := aon_io.wdog_rst
// Note that the actual mux lives inside AON itself.
// Therefore, the lfclk which comes out of AON is the
// true clock that AON and AONWrapper are running off of.
- val lfextclk = GPIOInputPinCtrl(pads.lfextclk, pue=Bool(true))
+ val lfextclk = pads.lfextclk.inputPin(pue=Bool(true))
aon_io.lfextclk := lfextclk.asClock
// Drive AON's clock and Reset
// PMU <--> pads Interface
//--------------------------------------------------
- val dwakeup_n_async = GPIOInputPinCtrl(pads.pmu.dwakeup_n, pue=Bool(true))
+ val dwakeup_n_async = pads.pmu.dwakeup_n.inputPin(pue=Bool(true))
val dwakeup_deglitch = Module (new DeglitchShiftRegister(3))
dwakeup_deglitch.clock := lfclk
dwakeup_deglitch.io.d := ~dwakeup_n_async
aon.module.io.pmu.dwakeup := dwakeup_deglitch.io.q
- GPIOOutputPinCtrl(pads.pmu.vddpaden, aon.module.io.pmu.vddpaden)
+ pads.pmu.vddpaden.outputPin(aon.module.io.pmu.vddpaden)
//--------------------------------------------------
// Connect signals to MOFF
--- /dev/null
+//See LICENSE for license details
+
+package sifive.blocks.devices.pinctrl
+
+import Chisel._
+
+// This is the base class of things you "always"
+// want to control from a HW block.
+class PinCtrl extends Bundle {
+ val oval = Bool()
+ val oe = Bool()
+ val ie = Bool()
+}
+
+// Package up the inputs and outputs
+// for the Pin
+abstract class Pin extends Bundle {
+ val i = new Bundle {
+ val ival = Bool(INPUT)
+ }
+ val o: PinCtrl
+
+ // Must be defined by the subclasses
+ def inputPin(pue: Bool = Bool(false)): Bool
+ def outputPin(signal: Bool,
+ pue: Bool = Bool(false),
+ ds: Bool = Bool(false),
+ ie: Bool = Bool(false)
+ ): Unit
+
+ def inputPin(pins: Vec[this.type], pue: Bool): Vec[Bool] = {
+ val signals = Wire(Vec(pins.length, new Bool()))
+ for ((signal, pin) <- (signals zip pins)) {
+ signal := pin.inputPin(pue)
+ }
+ signals
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////
+
+class BasePin extends Pin() {
+ val o = new PinCtrl().asOutput
+
+ 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
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////////////
+class EnhancedPinCtrl extends PinCtrl {
+ val pue = Bool()
+ val ds = Bool()
+}
+
+class EnhancedPin extends Pin() {
+
+ val o = new EnhancedPinCtrl().asOutput
+
+ def inputPin(pue: Bool = Bool(false)): Bool = {
+ this.o.oval := Bool(false)
+ this.o.oe := Bool(false)
+ this.o.pue := pue
+ this.o.ds := Bool(false)
+ this.o.ie := Bool(true)
+
+ this.i.ival
+ }
+
+ def outputPin(signal: Bool,
+ pue: Bool = Bool(false),
+ ds: Bool = Bool(false),
+ ie: Bool = Bool(false)
+ ): Unit = {
+ this.o.oval := signal
+ this.o.oe := Bool(true)
+ this.o.pue := pue
+ this.o.ds := ds
+ this.o.ie := ie
+ }
+}
import freechips.rocketchip.chip.HasSystemNetworks
import freechips.rocketchip.tilelink.TLFragmenter
import freechips.rocketchip.util.HeterogeneousBag
-
-import sifive.blocks.devices.gpio._
+import sifive.blocks.devices.pinctrl.{PinCtrl, Pin}
class PWMPortIO(val c: PWMParams) extends Bundle {
val port = Vec(c.ncmp, Bool()).asOutput
override def cloneType: this.type = new PWMPortIO(c).asInstanceOf[this.type]
}
-class PWMPinsIO(val c: PWMParams) extends Bundle {
- val pwm = Vec(c.ncmp, new GPIOPin)
-}
+class PWMPins[T <: Pin] (pingen: ()=> T, val c: PWMParams) extends Bundle {
-class PWMGPIOPort(val c: PWMParams) extends Module {
- val io = new Bundle {
- val pwm = new PWMPortIO(c).flip()
- val pins = new PWMPinsIO(c)
- }
+ val pwm: Vec[T] = Vec(c.ncmp, pingen())
- GPIOOutputPinCtrl(io.pins.pwm, io.pwm.port.asUInt)
+ def fromPWMPort(port: PWMPortIO) {
+ (pwm zip port.port) foreach {case (pin, port) =>
+ pin.outputPin(port)
+ }
+ }
}
case object PeripheryPWMKey extends Field[Seq[PWMParams]]
trait HasPeripheryPWMBundle {
val pwms: HeterogeneousBag[PWMPortIO]
- def PWMtoGPIOPins(dummy: Int = 1): Seq[PWMPinsIO] = pwms.map { p =>
- val pins = Module(new PWMGPIOPort(p.c))
- pins.io.pwm <> p
- pins.io.pins
- }
}
trait HasPeripheryPWMModuleImp extends LazyMultiIOModuleImp with HasPeripheryPWMBundle {
trait HasPeripherySPIBundle {
val spis: HeterogeneousBag[SPIPortIO]
- def SPItoGPIOPins(syncStages: Int = 0): Seq[SPIPinsIO] = spis.map { s =>
- val pins = Module(new SPIGPIOPort(s.c, syncStages))
- pins.io.spi <> s
- pins.io.pins
- }
}
trait HasPeripherySPIModuleImp extends LazyMultiIOModuleImp with HasPeripherySPIBundle {
trait HasPeripherySPIFlashBundle {
val qspi: HeterogeneousBag[SPIPortIO]
- // It is important for SPIFlash that the syncStages is agreed upon, because
- // internally it needs to realign the input data to the output SCK.
- // Therefore, we rely on the syncStages parameter.
- def SPIFlashtoGPIOPins(syncStages: Int = 0): Seq[SPIPinsIO] = qspi.map { s =>
- val pins = Module(new SPIGPIOPort(s.c, syncStages))
- pins.io.spi <> s
- pins.io.pins
- }
}
trait HasPeripherySPIFlashModuleImp extends LazyMultiIOModuleImp with HasPeripherySPIFlashBundle {
package sifive.blocks.devices.spi
import Chisel._
-import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
+import sifive.blocks.devices.pinctrl.{PinCtrl, Pin}
-class SPIPinsIO(c: SPIParamsBase) extends SPIBundle(c) {
- val sck = new GPIOPin
- val dq = Vec(4, new GPIOPin)
- val cs = Vec(c.csWidth, new GPIOPin)
-}
+class SPIPins[T <: Pin] (pingen: ()=> T, c: SPIParamsBase) extends SPIBundle(c) {
-class SPIGPIOPort(c: SPIParamsBase, syncStages: Int = 0, driveStrength: Bool = Bool(false)) extends Module {
- val io = new SPIBundle(c) {
- val spi = new SPIPortIO(c).flip
- val pins = new SPIPinsIO(c)
- }
+ val sck: T = pingen()
+ val dq: Vec[T] = Vec(4, pingen())
+ val cs: Vec[T] = Vec(c.csWidth, pingen())
- GPIOOutputPinCtrl(io.pins.sck, io.spi.sck, ds = driveStrength)
+ def fromSPIPort(spi: SPIPortIO, syncStages: Int = 0, driveStrength: Bool = Bool(false)) {
+
+ sck.outputPin(spi.sck, ds = driveStrength)
- GPIOOutputPinCtrl(io.pins.dq, Bits(0, io.spi.dq.size))
- (io.pins.dq zip io.spi.dq).foreach {
- case (p, s) =>
- p.o.oval := s.o
- p.o.oe := s.oe
- p.o.ie := ~s.oe
- p.o.pue := Bool(true)
- p.o.ds := driveStrength
+ (dq zip spi.dq).foreach {case (p, s) =>
+ p.outputPin(s.o, pue = Bool(true), ds = driveStrength)
+ p.o.oe := s.oe
+ p.o.ie := ~s.oe
s.i := ShiftRegister(p.i.ival, syncStages)
- }
+ }
- GPIOOutputPinCtrl(io.pins.cs, io.spi.cs.asUInt)
- io.pins.cs.foreach(_.o.ds := driveStrength)
+ (cs zip spi.cs) foreach { case (c, s) =>
+ c.outputPin(s, ds = driveStrength)
+ }
+ }
}
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
import freechips.rocketchip.chip.HasSystemNetworks
import freechips.rocketchip.tilelink.TLFragmenter
-import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
+import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
import sifive.blocks.util.ShiftRegisterInit
case object PeripheryUARTKey extends Field[Seq[UARTParams]]
uarts.foreach { _.rxd := UInt(1) }
}
- def UARTtoGPIOPins(syncStages: Int = 0): Seq[UARTPinsIO] = uarts.map { u =>
- val pins = Module(new UARTGPIOPort(syncStages))
- pins.io.uart <> u
- pins.io.pins
- }
}
trait HasPeripheryUARTModuleImp extends LazyMultiIOModuleImp with HasPeripheryUARTBundle {
}
}
-class UARTPinsIO extends Bundle {
- val rxd = new GPIOPin
- val txd = new GPIOPin
-}
+class UARTPins(pingen: () => Pin) extends Bundle {
+ val rxd = pingen()
+ val txd = pingen()
-class UARTGPIOPort(syncStages: Int = 0) extends Module {
- val io = new Bundle{
- val uart = new UARTPortIO().flip()
- val pins = new UARTPinsIO
+ def fromUARTPort(uart: UARTPortIO, syncStages: Int = 0) {
+ txd.outputPin(uart.txd)
+ val rxd_t = rxd.inputPin()
+ uart.rxd := ShiftRegisterInit(rxd_t, syncStages, Bool(true))
}
-
- GPIOOutputPinCtrl(io.pins.txd, io.uart.txd)
- val rxd = GPIOInputPinCtrl(io.pins.rxd)
- io.uart.rxd := ShiftRegisterInit(rxd, syncStages, Bool(true))
}
+