xref: /qemu/hw/i2c/arm_sbcon_i2c.c (revision 550da1cc22c49f0df427232be29484230d15029b)
1d1157ca4SOskar Andero /*
2f61c3fb5SPhilippe Mathieu-Daudé  * ARM SBCon two-wire serial bus interface (I2C bitbang)
3f61c3fb5SPhilippe Mathieu-Daudé  * a.k.a. ARM Versatile I2C controller
4d1157ca4SOskar Andero  *
5d1157ca4SOskar Andero  * Copyright (c) 2006-2007 CodeSourcery.
6d1157ca4SOskar Andero  * Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
7d1157ca4SOskar Andero  *
8d1157ca4SOskar Andero  * This file is derived from hw/realview.c by Paul Brook
9d1157ca4SOskar Andero  *
10d1157ca4SOskar Andero  * This program is free software; you can redistribute it and/or
11d1157ca4SOskar Andero  * modify it under the terms of the GNU General Public License
12d1157ca4SOskar Andero  * as published by the Free Software Foundation; either version 2
13d1157ca4SOskar Andero  * of the License, or (at your option) any later version.
14d1157ca4SOskar Andero  *
15d1157ca4SOskar Andero  * This program is distributed in the hope that it will be useful,
16d1157ca4SOskar Andero  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17d1157ca4SOskar Andero  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18d1157ca4SOskar Andero  * GNU General Public License for more details.
19d1157ca4SOskar Andero  *
20d1157ca4SOskar Andero  * You should have received a copy of the GNU General Public License
21d1157ca4SOskar Andero  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22d1157ca4SOskar Andero  *
23d1157ca4SOskar Andero  */
24d1157ca4SOskar Andero 
258ef94f0bSPeter Maydell #include "qemu/osdep.h"
26f61c3fb5SPhilippe Mathieu-Daudé #include "hw/i2c/arm_sbcon_i2c.h"
27faa1bdfaSPhilippe Mathieu-Daudé #include "hw/registerfields.h"
2803dd024fSPaolo Bonzini #include "qemu/log.h"
290b8fa32fSMarkus Armbruster #include "qemu/module.h"
30db1015e9SEduardo Habkost #include "qom/object.h"
31d1157ca4SOskar Andero 
32db1015e9SEduardo Habkost typedef ArmSbconI2CState VersatileI2CState;
3392518611SPhilippe Mathieu-Daudé DECLARE_INSTANCE_CHECKER(ArmSbconI2CState, VERSATILE_I2C,
34*550da1ccSPhilippe Mathieu-Daudé                          TYPE_ARM_SBCON_I2C)
3593e7f5f4SAndreas Färber 
3693e7f5f4SAndreas Färber 
37d1157ca4SOskar Andero 
38faa1bdfaSPhilippe Mathieu-Daudé REG32(CONTROL_GET, 0)
39faa1bdfaSPhilippe Mathieu-Daudé REG32(CONTROL_SET, 0)
40faa1bdfaSPhilippe Mathieu-Daudé REG32(CONTROL_CLR, 4)
41faa1bdfaSPhilippe Mathieu-Daudé 
42cfcfbae0SPhilippe Mathieu-Daudé #define SCL BIT(0)
43cfcfbae0SPhilippe Mathieu-Daudé #define SDA BIT(1)
44cfcfbae0SPhilippe Mathieu-Daudé 
45a8170e5eSAvi Kivity static uint64_t versatile_i2c_read(void *opaque, hwaddr offset,
46d1157ca4SOskar Andero                                    unsigned size)
47d1157ca4SOskar Andero {
4892518611SPhilippe Mathieu-Daudé     ArmSbconI2CState *s = opaque;
49d1157ca4SOskar Andero 
50faa1bdfaSPhilippe Mathieu-Daudé     switch (offset) {
51faa1bdfaSPhilippe Mathieu-Daudé     case A_CONTROL_SET:
52d1157ca4SOskar Andero         return (s->out & 1) | (s->in << 1);
53faa1bdfaSPhilippe Mathieu-Daudé     default:
545170d661SPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
555170d661SPeter Maydell                       "%s: Bad offset 0x%x\n", __func__, (int)offset);
56d1157ca4SOskar Andero         return -1;
57d1157ca4SOskar Andero     }
58d1157ca4SOskar Andero }
59d1157ca4SOskar Andero 
60a8170e5eSAvi Kivity static void versatile_i2c_write(void *opaque, hwaddr offset,
61d1157ca4SOskar Andero                                 uint64_t value, unsigned size)
62d1157ca4SOskar Andero {
6392518611SPhilippe Mathieu-Daudé     ArmSbconI2CState *s = opaque;
64d1157ca4SOskar Andero 
65d1157ca4SOskar Andero     switch (offset) {
66faa1bdfaSPhilippe Mathieu-Daudé     case A_CONTROL_SET:
67d1157ca4SOskar Andero         s->out |= value & 3;
68d1157ca4SOskar Andero         break;
69faa1bdfaSPhilippe Mathieu-Daudé     case A_CONTROL_CLR:
70d1157ca4SOskar Andero         s->out &= ~value;
71d1157ca4SOskar Andero         break;
72d1157ca4SOskar Andero     default:
735170d661SPeter Maydell         qemu_log_mask(LOG_GUEST_ERROR,
745170d661SPeter Maydell                       "%s: Bad offset 0x%x\n", __func__, (int)offset);
75d1157ca4SOskar Andero     }
76cfcfbae0SPhilippe Mathieu-Daudé     bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & SCL) != 0);
77cfcfbae0SPhilippe Mathieu-Daudé     s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0);
78d1157ca4SOskar Andero }
79d1157ca4SOskar Andero 
80d1157ca4SOskar Andero static const MemoryRegionOps versatile_i2c_ops = {
81d1157ca4SOskar Andero     .read = versatile_i2c_read,
82d1157ca4SOskar Andero     .write = versatile_i2c_write,
83d1157ca4SOskar Andero     .endianness = DEVICE_NATIVE_ENDIAN,
84d1157ca4SOskar Andero };
85d1157ca4SOskar Andero 
868ce26fcdSxiaoqiang zhao static void versatile_i2c_init(Object *obj)
87d1157ca4SOskar Andero {
888ce26fcdSxiaoqiang zhao     DeviceState *dev = DEVICE(obj);
8992518611SPhilippe Mathieu-Daudé     ArmSbconI2CState *s = VERSATILE_I2C(obj);
908ce26fcdSxiaoqiang zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
91a5c82852SAndreas Färber     I2CBus *bus;
92d1157ca4SOskar Andero 
9393e7f5f4SAndreas Färber     bus = i2c_init_bus(dev, "i2c");
9441742927SPeter Maydell     bitbang_i2c_init(&s->bitbang, bus);
958ce26fcdSxiaoqiang zhao     memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
96f61c3fb5SPhilippe Mathieu-Daudé                           "arm_sbcon_i2c", 0x1000);
9793e7f5f4SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
98d1157ca4SOskar Andero }
99d1157ca4SOskar Andero 
100d1157ca4SOskar Andero static const TypeInfo versatile_i2c_info = {
101*550da1ccSPhilippe Mathieu-Daudé     .name          = TYPE_ARM_SBCON_I2C,
102d1157ca4SOskar Andero     .parent        = TYPE_SYS_BUS_DEVICE,
10392518611SPhilippe Mathieu-Daudé     .instance_size = sizeof(ArmSbconI2CState),
1048ce26fcdSxiaoqiang zhao     .instance_init = versatile_i2c_init,
105d1157ca4SOskar Andero };
106d1157ca4SOskar Andero 
107d1157ca4SOskar Andero static void versatile_i2c_register_types(void)
108d1157ca4SOskar Andero {
109d1157ca4SOskar Andero     type_register_static(&versatile_i2c_info);
110d1157ca4SOskar Andero }
111d1157ca4SOskar Andero 
112d1157ca4SOskar Andero type_init(versatile_i2c_register_types)
113