Initial (compilable) version of I2C (no actual logic yet)
This commit is contained in:
parent
d61d86e084
commit
9d2a173b15
58
src/main/scala/devices/i2c/I2C.scala
Normal file
58
src/main/scala/devices/i2c/I2C.scala
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.blocks.devices.i2c
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import config._
|
||||||
|
import regmapper._
|
||||||
|
import uncore.tilelink2._
|
||||||
|
import rocketchip.PeripheryBusConfig
|
||||||
|
import util.AsyncResetRegVec
|
||||||
|
import sifive.blocks.devices.gpio.{GPIOPinCtrl}
|
||||||
|
|
||||||
|
case class I2CConfig(address: BigInt)
|
||||||
|
|
||||||
|
trait HasI2CParameters {
|
||||||
|
implicit val p: Parameters
|
||||||
|
val params: I2CConfig
|
||||||
|
val c = params
|
||||||
|
}
|
||||||
|
|
||||||
|
class I2CPin extends Bundle {
|
||||||
|
val in = Bool(INPUT)
|
||||||
|
val out = Bool(OUTPUT)
|
||||||
|
val oe = Bool(OUTPUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
class I2CPort extends Bundle {
|
||||||
|
val scl = new I2CPin
|
||||||
|
val sda = new I2CPin
|
||||||
|
}
|
||||||
|
|
||||||
|
trait I2CBundle extends Bundle with HasI2CParameters {
|
||||||
|
val port = new I2CPort
|
||||||
|
}
|
||||||
|
|
||||||
|
trait I2CModule extends Module with HasI2CParameters with HasRegMap {
|
||||||
|
val io: I2CBundle
|
||||||
|
|
||||||
|
val prescaler_lo = Reg(UInt(8.W)) // low byte clock prescaler register
|
||||||
|
val prescaler_hi = Reg(UInt(8.W)) // high byte clock prescaler register
|
||||||
|
val control = Reg(UInt(8.W)) // control register
|
||||||
|
val data = Reg(UInt(8.W)) // write: transmit byte, read: receive byte
|
||||||
|
val cmd_status = Reg(UInt(8.W)) // write: command, read: status
|
||||||
|
|
||||||
|
// Note that these are out of order.
|
||||||
|
regmap(
|
||||||
|
I2CCtrlRegs.prescaler_lo -> Seq(RegField(8, prescaler_lo)),
|
||||||
|
I2CCtrlRegs.prescaler_hi -> Seq(RegField(8, prescaler_hi)),
|
||||||
|
I2CCtrlRegs.control -> Seq(RegField(8, control)),
|
||||||
|
I2CCtrlRegs.data -> Seq(RegField(8, data)),
|
||||||
|
I2CCtrlRegs.cmd_status -> Seq(RegField(8, cmd_status))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Magic TL2 Incantation to create a TL2 Slave
|
||||||
|
class TLI2C(c: I2CConfig)(implicit p: Parameters)
|
||||||
|
extends TLRegisterRouter(c.address, interrupts = 1, beatBytes = p(PeripheryBusConfig).beatBytes)(
|
||||||
|
new TLRegBundle(c, _) with I2CBundle)(
|
||||||
|
new TLRegModule(c, _, _) with I2CModule)
|
13
src/main/scala/devices/i2c/I2CCtrlRegs.scala
Normal file
13
src/main/scala/devices/i2c/I2CCtrlRegs.scala
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.blocks.devices.i2c
|
||||||
|
|
||||||
|
// matching Open Cores I2C to re-use Linux driver
|
||||||
|
// http://lxr.free-electrons.com/source/drivers/i2c/busses/i2c-ocores.c?v=4.6
|
||||||
|
|
||||||
|
object I2CCtrlRegs {
|
||||||
|
val prescaler_lo = 0x00 // low byte clock prescaler register
|
||||||
|
val prescaler_hi = 0x01 // high byte clock prescaler register
|
||||||
|
val control = 0x02 // control register
|
||||||
|
val data = 0x03 // write: transmit byte, read: receive byte
|
||||||
|
val cmd_status = 0x04 // write: command, read: status
|
||||||
|
}
|
34
src/main/scala/devices/i2c/I2CPeriphery.scala
Normal file
34
src/main/scala/devices/i2c/I2CPeriphery.scala
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.blocks.devices.i2c
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import diplomacy.LazyModule
|
||||||
|
import rocketchip.{TopNetwork,TopNetworkModule}
|
||||||
|
import uncore.tilelink2.TLFragmenter
|
||||||
|
|
||||||
|
trait PeripheryI2C {
|
||||||
|
this: TopNetwork { val i2cConfigs: Seq[I2CConfig] } =>
|
||||||
|
val i2cDevices = i2cConfigs.zipWithIndex.map { case (c, i) =>
|
||||||
|
val i2c = LazyModule(new TLI2C(c))
|
||||||
|
i2c.suggestName(s"i2c$i")
|
||||||
|
i2c.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
|
||||||
|
intBus.intnode := i2c.intnode
|
||||||
|
i2c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryI2CBundle {
|
||||||
|
this: { val i2cConfigs: Seq[I2CConfig] } =>
|
||||||
|
val i2cs = Vec(i2cConfigs.size, new I2CPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PeripheryI2CModule {
|
||||||
|
this: TopNetworkModule {
|
||||||
|
val i2cConfigs: Seq[I2CConfig]
|
||||||
|
val outer: PeripheryI2C
|
||||||
|
val io: PeripheryI2CBundle
|
||||||
|
} =>
|
||||||
|
(io.i2cs zip outer.i2cDevices).foreach { case (io, device) =>
|
||||||
|
io <> device.module.io.port
|
||||||
|
}
|
||||||
|
}
|
27
src/main/scala/devices/i2c/I2CPins.scala
Normal file
27
src/main/scala/devices/i2c/I2CPins.scala
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.blocks.devices.i2c
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl}
|
||||||
|
import sifive.blocks.util.ShiftRegisterInit
|
||||||
|
|
||||||
|
|
||||||
|
class I2CPinsIO extends Bundle {
|
||||||
|
val scl = new GPIOPin
|
||||||
|
val sda = new GPIOPin
|
||||||
|
}
|
||||||
|
|
||||||
|
class I2CGPIOPort(syncStages: Int = 0) extends Module {
|
||||||
|
val io = new Bundle{
|
||||||
|
val i2c = new I2CPort().flip()
|
||||||
|
val pins = new I2CPinsIO
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user