1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "qemu/osdep.h"
25#include "hw/sysbus.h"
26#include "qemu/log.h"
27#include "qapi/error.h"
28
29#define TYPE_GPIO_MR_MUX "gpio-mr-mux"
30
31#define GPIO_MR_MUX(obj) \
32 OBJECT_CHECK(GpioMrMux, (obj), TYPE_GPIO_MR_MUX)
33
34#ifndef MR_MUX_DEBUG
35#define MR_MUX_DEBUG 0
36#endif
37
38#define MAX_NR_GPIOS (4)
39#define MAX_REGIONS (1 << MAX_NR_GPIOS)
40
41typedef struct GpioMrMux {
42 SysBusDevice parent_obj;
43 MemoryRegion iomem;
44
45 MemoryRegion *mr[MAX_REGIONS];
46 MemoryRegion mr_alias[MAX_REGIONS];
47
48 struct {
49 uint64_t mr_size;
50 } cfg;
51
52 uint32_t state;
53} GpioMrMux;
54
55static void update_regions(GpioMrMux *s)
56{
57 int i;
58
59 for (i = 0; i < MAX_REGIONS; i++) {
60 bool enabled = s->state == i;
61 memory_region_set_enabled(&s->mr_alias[i], enabled);
62 }
63}
64
65static void input_handler(void *opaque, int nr, int level)
66{
67 GpioMrMux *s = GPIO_MR_MUX(opaque);
68
69 s->state = deposit32(s->state, nr, 1, level);
70 update_regions(s);
71}
72
73static void gpio_mr_mux_realize(DeviceState *dev, Error **errp)
74{
75 GpioMrMux *s = GPIO_MR_MUX(dev);
76 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
77 int i;
78
79 memory_region_init(&s->iomem, OBJECT(dev),
80 TYPE_GPIO_MR_MUX, s->cfg.mr_size);
81 sysbus_init_mmio(sbd, &s->iomem);
82
83 for (i = 0; i < MAX_REGIONS; i++) {
84 if (s->mr[i]) {
85 char *name = g_strdup_printf("mr-alias%d", i);
86
87
88 memory_region_init_alias(&s->mr_alias[i], OBJECT(s),
89 name, s->mr[i], 0, memory_region_size(s->mr[i]));
90 memory_region_add_subregion_overlap(&s->iomem, 0,
91 &s->mr_alias[i], 0);
92 g_free(name);
93 }
94 }
95}
96
97static void gpio_mr_mux_init(Object *obj)
98{
99 GpioMrMux *s = GPIO_MR_MUX(obj);
100 int i;
101
102 qdev_init_gpio_in(DEVICE(obj), input_handler, MAX_NR_GPIOS);
103
104 for (i = 0; i < MAX_REGIONS; i++) {
105 char *name = g_strdup_printf("mr%d", i);
106
107 object_property_add_link(obj, name, TYPE_MEMORY_REGION,
108 (Object **)&s->mr[i],
109 qdev_prop_allow_set_link_before_realize,
110 OBJ_PROP_LINK_UNREF_ON_RELEASE,
111 &error_abort);
112 g_free(name);
113 }
114}
115
116static Property gpio_mr_mux_properties[] = {
117 DEFINE_PROP_UINT64("mr-size", GpioMrMux, cfg.mr_size, UINT64_MAX),
118 DEFINE_PROP_END_OF_LIST(),
119};
120
121static void gpio_mr_mux_class_init(ObjectClass *klass, void *data)
122{
123 DeviceClass *dc = DEVICE_CLASS(klass);
124
125 dc->realize = gpio_mr_mux_realize;
126 dc->props = gpio_mr_mux_properties;
127}
128
129static const TypeInfo gpio_mr_mux_info = {
130 .name = TYPE_GPIO_MR_MUX,
131 .parent = TYPE_SYS_BUS_DEVICE,
132 .instance_size = sizeof(GpioMrMux),
133 .class_init = gpio_mr_mux_class_init,
134 .instance_init = gpio_mr_mux_init,
135};
136
137static void gpio_mr_mux_register_types(void)
138{
139 type_register_static(&gpio_mr_mux_info);
140}
141
142type_init(gpio_mr_mux_register_types)
143