1
0

Initial (compilable) version of I2C (no actual logic yet)

This commit is contained in:
Alex Solomatnikov 2017-01-24 14:58:01 -08:00
parent d61d86e084
commit 9d2a173b15
4 changed files with 132 additions and 0 deletions

View 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)

View 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
}

View 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
}
}

View 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))
}