2 * I2C multiplexer for PCA954x series of I2C multiplexer/switch chips.
4 * Copyright 2021 Google LLC
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "qemu/osdep.h"
18 #include "qapi/error.h"
19 #include "hw/i2c/i2c.h"
20 #include "hw/i2c/i2c_mux_pca954x.h"
21 #include "hw/i2c/smbus_slave.h"
22 #include "hw/qdev-core.h"
23 #include "hw/qdev-properties.h"
24 #include "hw/sysbus.h"
26 #include "qemu/module.h"
27 #include "qemu/queue.h"
28 #include "qom/object.h"
31 #define PCA9548_CHANNEL_COUNT 8
32 #define PCA9546_CHANNEL_COUNT 4
35 * struct Pca954xState - The pca954x state object.
36 * @control: The value written to the mux control.
37 * @channel: The set of i2c channel buses that act as channels which own the
40 typedef struct Pca954xState
{
45 bool enabled
[PCA9548_CHANNEL_COUNT
];
46 I2CBus
*bus
[PCA9548_CHANNEL_COUNT
];
52 * struct Pca954xClass - The pca954x class object.
53 * @nchans: The number of i2c channels this device has.
55 typedef struct Pca954xClass
{
56 SMBusDeviceClass parent
;
61 #define TYPE_PCA954X "pca954x"
62 OBJECT_DECLARE_TYPE(Pca954xState
, Pca954xClass
, PCA954X
)
65 * For each channel, if it's enabled, recursively call match on those children.
67 static bool pca954x_match(I2CSlave
*candidate
, uint8_t address
,
69 I2CNodeList
*current_devs
)
71 Pca954xState
*mux
= PCA954X(candidate
);
72 Pca954xClass
*mc
= PCA954X_GET_CLASS(mux
);
75 /* They are talking to the mux itself (or all devices enabled). */
76 if ((candidate
->address
== address
) || broadcast
) {
77 I2CNode
*node
= g_new(struct I2CNode
, 1);
78 node
->elt
= candidate
;
79 QLIST_INSERT_HEAD(current_devs
, node
, next
);
85 for (i
= 0; i
< mc
->nchans
; i
++) {
86 if (!mux
->enabled
[i
]) {
90 if (i2c_scan_bus(mux
->bus
[i
], address
, broadcast
,
98 /* If we arrived here we didn't find a match, return broadcast. */
102 static void pca954x_enable_channel(Pca954xState
*s
, uint8_t enable_mask
)
104 Pca954xClass
*mc
= PCA954X_GET_CLASS(s
);
108 * For each channel, check if their bit is set in enable_mask and if yes,
109 * enable it, otherwise disable, hide it.
111 for (i
= 0; i
< mc
->nchans
; i
++) {
112 if (enable_mask
& (1 << i
)) {
113 s
->enabled
[i
] = true;
115 s
->enabled
[i
] = false;
120 static void pca954x_write(Pca954xState
*s
, uint8_t data
)
123 pca954x_enable_channel(s
, data
);
125 trace_pca954x_write_bytes(data
);
128 static int pca954x_write_data(SMBusDevice
*d
, uint8_t *buf
, uint8_t len
)
130 Pca954xState
*s
= PCA954X(d
);
133 qemu_log_mask(LOG_GUEST_ERROR
, "%s: writing empty data\n", __func__
);
138 * len should be 1, because they write one byte to enable/disable channels.
141 qemu_log_mask(LOG_GUEST_ERROR
,
142 "%s: extra data after channel selection mask\n",
147 pca954x_write(s
, buf
[0]);
151 static uint8_t pca954x_read_byte(SMBusDevice
*d
)
153 Pca954xState
*s
= PCA954X(d
);
154 uint8_t data
= s
->control
;
155 trace_pca954x_read_data(data
);
159 static void pca954x_enter_reset(Object
*obj
, ResetType type
)
161 Pca954xState
*s
= PCA954X(obj
);
162 /* Reset will disable all channels. */
166 I2CBus
*pca954x_i2c_get_bus(I2CSlave
*mux
, uint8_t channel
)
168 Pca954xClass
*pc
= PCA954X_GET_CLASS(mux
);
169 Pca954xState
*pca954x
= PCA954X(mux
);
171 g_assert(channel
< pc
->nchans
);
172 return pca954x
->bus
[channel
];
175 static void pca9546_class_init(ObjectClass
*klass
, void *data
)
177 Pca954xClass
*s
= PCA954X_CLASS(klass
);
178 s
->nchans
= PCA9546_CHANNEL_COUNT
;
181 static void pca9548_class_init(ObjectClass
*klass
, void *data
)
183 Pca954xClass
*s
= PCA954X_CLASS(klass
);
184 s
->nchans
= PCA9548_CHANNEL_COUNT
;
187 static void pca954x_realize(DeviceState
*dev
, Error
**errp
)
189 Pca954xState
*s
= PCA954X(dev
);
190 DeviceState
*d
= DEVICE(s
);
192 d
->id
= g_strdup(s
->name
);
194 d
->id
= g_strdup_printf("pca954x[%x]", s
->parent
.i2c
.address
);
198 static void pca954x_init(Object
*obj
)
200 Pca954xState
*s
= PCA954X(obj
);
201 Pca954xClass
*c
= PCA954X_GET_CLASS(obj
);
204 /* SMBus modules. Cannot fail. */
205 for (i
= 0; i
< c
->nchans
; i
++) {
206 g_autofree gchar
*bus_name
= g_strdup_printf("i2c.%d", i
);
208 /* start all channels as disabled. */
209 s
->enabled
[i
] = false;
210 s
->bus
[i
] = i2c_init_bus(DEVICE(s
), bus_name
);
214 static Property pca954x_props
[] = {
215 DEFINE_PROP_STRING("name", Pca954xState
, name
),
216 DEFINE_PROP_END_OF_LIST()
219 static void pca954x_class_init(ObjectClass
*klass
, void *data
)
221 I2CSlaveClass
*sc
= I2C_SLAVE_CLASS(klass
);
222 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
223 DeviceClass
*dc
= DEVICE_CLASS(klass
);
224 SMBusDeviceClass
*k
= SMBUS_DEVICE_CLASS(klass
);
226 sc
->match_and_add
= pca954x_match
;
228 rc
->phases
.enter
= pca954x_enter_reset
;
230 dc
->desc
= "Pca954x i2c-mux";
231 dc
->realize
= pca954x_realize
;
233 k
->write_data
= pca954x_write_data
;
234 k
->receive_byte
= pca954x_read_byte
;
236 device_class_set_props(dc
, pca954x_props
);
239 static const TypeInfo pca954x_info
[] = {
241 .name
= TYPE_PCA954X
,
242 .parent
= TYPE_SMBUS_DEVICE
,
243 .instance_size
= sizeof(Pca954xState
),
244 .instance_init
= pca954x_init
,
245 .class_size
= sizeof(Pca954xClass
),
246 .class_init
= pca954x_class_init
,
250 .name
= TYPE_PCA9546
,
251 .parent
= TYPE_PCA954X
,
252 .class_init
= pca9546_class_init
,
255 .name
= TYPE_PCA9548
,
256 .parent
= TYPE_PCA954X
,
257 .class_init
= pca9548_class_init
,
261 DEFINE_TYPES(pca954x_info
)