Skip to content

Commit

Permalink
Kind of working litex_i2c
Browse files Browse the repository at this point in the history
  • Loading branch information
mithro committed Mar 21, 2017
1 parent 7acadcc commit cc20ffb
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 1 deletion.
3 changes: 2 additions & 1 deletion hw/i2c/Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ common-obj-$(CONFIG_DDC) += i2c-ddc.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
common-obj-$(CONFIG_APM) += pm_smbus.o
common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
common-obj-y += bitbang_i2c.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
common-obj-y += litex_i2c.o
obj-$(CONFIG_OMAP) += omap_i2c.o
129 changes: 129 additions & 0 deletions hw/i2c/litex_i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* LiteX Bit-Banging I2C controller
*
* Copyright (c) 2006-2007 CodeSourcery.
* Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
*
* This file is derived from hw/realview.c by Paul Brook
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/

#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "bitbang_i2c.h"
#include "qemu/log.h"

#define TYPE_LITEX_I2C "litex_i2c"
#define LITEX_I2C(obj) \
OBJECT_CHECK(LiteXI2CState, (obj), TYPE_LITEX_I2C)

enum {
R_OPSIS_I2C_MASTER_W,
R_OPSIS_I2C_MASTER_R,
R_MAX,
};

#define I2C_SCL 0x01
#define I2C_SDAOE 0x02
#define I2C_SDAOUT 0x04

#define I2C_SDAIN 0x01

typedef struct LiteXI2CState {
SysBusDevice parent_obj;

MemoryRegion iomem;
bitbang_i2c_interface *bitbang;
uint32_t regs[R_MAX];

} LiteXI2CState;

static uint64_t litex_i2c_read(void *opaque, hwaddr addr, unsigned size)
{
LiteXI2CState *s = (LiteXI2CState *)opaque;
addr >>= 2;
if (addr >= R_MAX) {
printf("Tried to access invalid address %08x\n", (unsigned int)addr);
return 0;
}

uint64_t r = s->regs[addr];
return r;
}

static void litex_i2c_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
{
int scl, sda_oe, sda_out, sda_in;
LiteXI2CState *s = (LiteXI2CState *)opaque;
addr >>= 2;

if (addr >= R_MAX) {
printf("Tried to access invalid address %08x\n", (unsigned int)addr);
return;
}

s->regs[addr] = value & 0xff;
switch(addr)
{
case R_OPSIS_I2C_MASTER_W:
scl = (value & I2C_SCL) ? 1 : 0;
sda_oe = (s->regs[addr] & I2C_SDAOE) ? 1 : 0;
sda_out = (s->regs[addr] & I2C_SDAOUT) ? 1 : 0;

bitbang_i2c_set(s->bitbang, BITBANG_I2C_SCL, scl);
sda_in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, sda_oe ? sda_out : 1);
if (!sda_oe) {
s->regs[R_OPSIS_I2C_MASTER_R] = sda_in; // FIXME: Shift?
}
}
}

static const MemoryRegionOps litex_i2c_ops = {
.read = litex_i2c_read,
.write = litex_i2c_write,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
.endianness = DEVICE_NATIVE_ENDIAN,
};

static void litex_i2c_init(Object *obj)
{
DeviceState *dev = DEVICE(obj);
LiteXI2CState *s = LITEX_I2C(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
I2CBus *bus;

bus = i2c_init_bus(dev, "i2c");
s->bitbang = bitbang_i2c_init(bus);
memory_region_init_io(&s->iomem, OBJECT(dev), &litex_i2c_ops, s, "litex_i2c", R_MAX * 4);
sysbus_init_mmio(sbd, &s->iomem);
}

static const TypeInfo litex_i2c_info = {
.name = TYPE_LITEX_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LiteXI2CState),
.instance_init = litex_i2c_init,
};

static void litex_i2c_register_types(void)
{
type_register_static(&litex_i2c_info);
}

type_init(litex_i2c_register_types)
40 changes: 40 additions & 0 deletions hw/lm32/litex-hw.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef QEMU_HW_LITEX_HW_H
#define QEMU_HW_LITEX_HW_H

#include "hw/i2c/smbus.h"
#include "hw/qdev.h"
#include "net/net.h"

Expand Down Expand Up @@ -51,6 +52,45 @@ static inline DeviceState *litex_liteeth_create(hwaddr reg_base, hwaddr phy_bas
return dev;
}

uint8_t eeprom_contents[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
250, 251, 252, 253, 254, 255};

static inline DeviceState *litex_i2c_create(hwaddr reg_base)
{
DeviceState *dev;
I2CBus *i2c;

dev = sysbus_create_simple("litex_i2c", reg_base, NULL);
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");

smbus_eeprom_init(i2c, 1, eeprom_contents, 256);
return dev;
}

/*
static inline DeviceState *litex_qspi_create(hwaddr base, qemu_irq qspi_irq)
Expand Down
2 changes: 2 additions & 0 deletions hw/lm32/litex.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ litex_init(MachineState *machine)
litex_liteeth_create(CSR_ETHMAC_BASE & 0x7FFFFFFF, CSR_ETHPHY_BASE & 0x7FFFFFFF, ETHMAC_BASE & 0x7FFFFFFF, irq[ETHMAC_INTERRUPT]);
#endif

litex_i2c_create(CSR_OPSIS_I2C_BASE & 0x7FFFFFFF);

/* make sure juart isn't the first chardev */
env->juart_state = lm32_juart_init(serial_hds[1]);

Expand Down

0 comments on commit cc20ffb

Please sign in to comment.