mirror of
https://github.com/qemu/qemu.git
synced 2024-12-14 15:03:33 +08:00
machine: Move gpio code to hw/core/gpio.c
Only softmmu code uses gpio, so move gpio code from qdev.c to gpio.c and compile it only on softmmu mode. Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-Id: <20190425200051.19906-2-ehabkost@redhat.com> [PMD: Rebased] Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
This commit is contained in:
parent
af531756d2
commit
b19a3e2cd9
hw/core
197
hw/core/gpio.c
Normal file
197
hw/core/gpio.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* qdev GPIO helpers
|
||||
*
|
||||
* Copyright (c) 2009 CodeSourcery
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "hw/irq.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
|
||||
const char *name)
|
||||
{
|
||||
NamedGPIOList *ngl;
|
||||
|
||||
QLIST_FOREACH(ngl, &dev->gpios, node) {
|
||||
/* NULL is a valid and matchable name. */
|
||||
if (g_strcmp0(name, ngl->name) == 0) {
|
||||
return ngl;
|
||||
}
|
||||
}
|
||||
|
||||
ngl = g_malloc0(sizeof(*ngl));
|
||||
ngl->name = g_strdup(name);
|
||||
QLIST_INSERT_HEAD(&dev->gpios, ngl, node);
|
||||
return ngl;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
|
||||
qemu_irq_handler handler,
|
||||
void *opaque,
|
||||
const char *name, int n)
|
||||
{
|
||||
int i;
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(gpio_list->num_out == 0 || !name);
|
||||
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
|
||||
opaque, n);
|
||||
|
||||
if (!name) {
|
||||
name = "unnamed-gpio-in";
|
||||
}
|
||||
for (i = gpio_list->num_in; i < gpio_list->num_in + n; i++) {
|
||||
gchar *propname = g_strdup_printf("%s[%u]", name, i);
|
||||
|
||||
object_property_add_child(OBJECT(dev), propname,
|
||||
OBJECT(gpio_list->in[i]));
|
||||
g_free(propname);
|
||||
}
|
||||
|
||||
gpio_list->num_in += n;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
|
||||
{
|
||||
qdev_init_gpio_in_named(dev, handler, NULL, n);
|
||||
}
|
||||
|
||||
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
|
||||
const char *name, int n)
|
||||
{
|
||||
int i;
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(gpio_list->num_in == 0 || !name);
|
||||
|
||||
if (!name) {
|
||||
name = "unnamed-gpio-out";
|
||||
}
|
||||
memset(pins, 0, sizeof(*pins) * n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
gchar *propname = g_strdup_printf("%s[%u]", name,
|
||||
gpio_list->num_out + i);
|
||||
|
||||
object_property_add_link(OBJECT(dev), propname, TYPE_IRQ,
|
||||
(Object **)&pins[i],
|
||||
object_property_allow_set_link,
|
||||
OBJ_PROP_LINK_STRONG);
|
||||
g_free(propname);
|
||||
}
|
||||
gpio_list->num_out += n;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
|
||||
{
|
||||
qdev_init_gpio_out_named(dev, pins, NULL, n);
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n)
|
||||
{
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(n >= 0 && n < gpio_list->num_in);
|
||||
return gpio_list->in[n];
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
|
||||
{
|
||||
return qdev_get_gpio_in_named(dev, NULL, n);
|
||||
}
|
||||
|
||||
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
|
||||
qemu_irq pin)
|
||||
{
|
||||
char *propname = g_strdup_printf("%s[%d]",
|
||||
name ? name : "unnamed-gpio-out", n);
|
||||
if (pin && !OBJECT(pin)->parent) {
|
||||
/* We need a name for object_property_set_link to work */
|
||||
object_property_add_child(container_get(qdev_get_machine(),
|
||||
"/unattached"),
|
||||
"non-qdev-gpio[*]", OBJECT(pin));
|
||||
}
|
||||
object_property_set_link(OBJECT(dev), propname, OBJECT(pin), &error_abort);
|
||||
g_free(propname);
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n)
|
||||
{
|
||||
g_autofree char *propname = g_strdup_printf("%s[%d]",
|
||||
name ? name : "unnamed-gpio-out", n);
|
||||
|
||||
qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
|
||||
NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* disconnect a GPIO output, returning the disconnected input (if any) */
|
||||
|
||||
static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
|
||||
const char *name, int n)
|
||||
{
|
||||
char *propname = g_strdup_printf("%s[%d]",
|
||||
name ? name : "unnamed-gpio-out", n);
|
||||
|
||||
qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
|
||||
NULL);
|
||||
if (ret) {
|
||||
object_property_set_link(OBJECT(dev), propname, NULL, NULL);
|
||||
}
|
||||
g_free(propname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
|
||||
const char *name, int n)
|
||||
{
|
||||
qemu_irq disconnected = qdev_disconnect_gpio_out_named(dev, name, n);
|
||||
qdev_connect_gpio_out_named(dev, name, n, icpt);
|
||||
return disconnected;
|
||||
}
|
||||
|
||||
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin)
|
||||
{
|
||||
qdev_connect_gpio_out_named(dev, NULL, n, pin);
|
||||
}
|
||||
|
||||
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
|
||||
const char *name)
|
||||
{
|
||||
int i;
|
||||
NamedGPIOList *ngl = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
for (i = 0; i < ngl->num_in; i++) {
|
||||
const char *nm = ngl->name ? ngl->name : "unnamed-gpio-in";
|
||||
char *propname = g_strdup_printf("%s[%d]", nm, i);
|
||||
|
||||
object_property_add_alias(OBJECT(container), propname,
|
||||
OBJECT(dev), propname);
|
||||
g_free(propname);
|
||||
}
|
||||
for (i = 0; i < ngl->num_out; i++) {
|
||||
const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out";
|
||||
char *propname = g_strdup_printf("%s[%d]", nm, i);
|
||||
|
||||
object_property_add_alias(OBJECT(container), propname,
|
||||
OBJECT(dev), propname);
|
||||
g_free(propname);
|
||||
}
|
||||
QLIST_REMOVE(ngl, node);
|
||||
QLIST_INSERT_HEAD(&container->gpios, ngl, node);
|
||||
}
|
@ -27,6 +27,7 @@ common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
|
||||
softmmu_ss.add(files(
|
||||
'cpu-sysemu.c',
|
||||
'fw-path-provider.c',
|
||||
'gpio.c',
|
||||
'loader.c',
|
||||
'machine-hmp-cmds.c',
|
||||
'machine.c',
|
||||
|
174
hw/core/qdev.c
174
hw/core/qdev.c
@ -436,180 +436,6 @@ BusState *qdev_get_parent_bus(DeviceState *dev)
|
||||
return dev->parent_bus;
|
||||
}
|
||||
|
||||
static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev,
|
||||
const char *name)
|
||||
{
|
||||
NamedGPIOList *ngl;
|
||||
|
||||
QLIST_FOREACH(ngl, &dev->gpios, node) {
|
||||
/* NULL is a valid and matchable name. */
|
||||
if (g_strcmp0(name, ngl->name) == 0) {
|
||||
return ngl;
|
||||
}
|
||||
}
|
||||
|
||||
ngl = g_malloc0(sizeof(*ngl));
|
||||
ngl->name = g_strdup(name);
|
||||
QLIST_INSERT_HEAD(&dev->gpios, ngl, node);
|
||||
return ngl;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
|
||||
qemu_irq_handler handler,
|
||||
void *opaque,
|
||||
const char *name, int n)
|
||||
{
|
||||
int i;
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(gpio_list->num_out == 0 || !name);
|
||||
gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler,
|
||||
opaque, n);
|
||||
|
||||
if (!name) {
|
||||
name = "unnamed-gpio-in";
|
||||
}
|
||||
for (i = gpio_list->num_in; i < gpio_list->num_in + n; i++) {
|
||||
gchar *propname = g_strdup_printf("%s[%u]", name, i);
|
||||
|
||||
object_property_add_child(OBJECT(dev), propname,
|
||||
OBJECT(gpio_list->in[i]));
|
||||
g_free(propname);
|
||||
}
|
||||
|
||||
gpio_list->num_in += n;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
|
||||
{
|
||||
qdev_init_gpio_in_named(dev, handler, NULL, n);
|
||||
}
|
||||
|
||||
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
|
||||
const char *name, int n)
|
||||
{
|
||||
int i;
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(gpio_list->num_in == 0 || !name);
|
||||
|
||||
if (!name) {
|
||||
name = "unnamed-gpio-out";
|
||||
}
|
||||
memset(pins, 0, sizeof(*pins) * n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
gchar *propname = g_strdup_printf("%s[%u]", name,
|
||||
gpio_list->num_out + i);
|
||||
|
||||
object_property_add_link(OBJECT(dev), propname, TYPE_IRQ,
|
||||
(Object **)&pins[i],
|
||||
object_property_allow_set_link,
|
||||
OBJ_PROP_LINK_STRONG);
|
||||
g_free(propname);
|
||||
}
|
||||
gpio_list->num_out += n;
|
||||
}
|
||||
|
||||
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
|
||||
{
|
||||
qdev_init_gpio_out_named(dev, pins, NULL, n);
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n)
|
||||
{
|
||||
NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
assert(n >= 0 && n < gpio_list->num_in);
|
||||
return gpio_list->in[n];
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
|
||||
{
|
||||
return qdev_get_gpio_in_named(dev, NULL, n);
|
||||
}
|
||||
|
||||
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
|
||||
qemu_irq pin)
|
||||
{
|
||||
char *propname = g_strdup_printf("%s[%d]",
|
||||
name ? name : "unnamed-gpio-out", n);
|
||||
if (pin && !OBJECT(pin)->parent) {
|
||||
/* We need a name for object_property_set_link to work */
|
||||
object_property_add_child(container_get(qdev_get_machine(),
|
||||
"/unattached"),
|
||||
"non-qdev-gpio[*]", OBJECT(pin));
|
||||
}
|
||||
object_property_set_link(OBJECT(dev), propname, OBJECT(pin), &error_abort);
|
||||
g_free(propname);
|
||||
}
|
||||
|
||||
qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n)
|
||||
{
|
||||
g_autofree char *propname = g_strdup_printf("%s[%d]",
|
||||
name ? name : "unnamed-gpio-out", n);
|
||||
|
||||
qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
|
||||
NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* disconnect a GPIO output, returning the disconnected input (if any) */
|
||||
|
||||
static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev,
|
||||
const char *name, int n)
|
||||
{
|
||||
char *propname = g_strdup_printf("%s[%d]",
|
||||
name ? name : "unnamed-gpio-out", n);
|
||||
|
||||
qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname,
|
||||
NULL);
|
||||
if (ret) {
|
||||
object_property_set_link(OBJECT(dev), propname, NULL, NULL);
|
||||
}
|
||||
g_free(propname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
|
||||
const char *name, int n)
|
||||
{
|
||||
qemu_irq disconnected = qdev_disconnect_gpio_out_named(dev, name, n);
|
||||
qdev_connect_gpio_out_named(dev, name, n, icpt);
|
||||
return disconnected;
|
||||
}
|
||||
|
||||
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
|
||||
{
|
||||
qdev_connect_gpio_out_named(dev, NULL, n, pin);
|
||||
}
|
||||
|
||||
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
|
||||
const char *name)
|
||||
{
|
||||
int i;
|
||||
NamedGPIOList *ngl = qdev_get_named_gpio_list(dev, name);
|
||||
|
||||
for (i = 0; i < ngl->num_in; i++) {
|
||||
const char *nm = ngl->name ? ngl->name : "unnamed-gpio-in";
|
||||
char *propname = g_strdup_printf("%s[%d]", nm, i);
|
||||
|
||||
object_property_add_alias(OBJECT(container), propname,
|
||||
OBJECT(dev), propname);
|
||||
g_free(propname);
|
||||
}
|
||||
for (i = 0; i < ngl->num_out; i++) {
|
||||
const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out";
|
||||
char *propname = g_strdup_printf("%s[%d]", nm, i);
|
||||
|
||||
object_property_add_alias(OBJECT(container), propname,
|
||||
OBJECT(dev), propname);
|
||||
g_free(propname);
|
||||
}
|
||||
QLIST_REMOVE(ngl, node);
|
||||
QLIST_INSERT_HEAD(&container->gpios, ngl, node);
|
||||
}
|
||||
|
||||
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
||||
{
|
||||
BusState *bus;
|
||||
|
Loading…
Reference in New Issue
Block a user