hw/gpio: Connect SD controller to BCM2838 GPIO
Signed-off-by: Sergey Kambalin <sergey.kambalin@auriga.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20240226000259.2752893-9-sergey.kambalin@auriga.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
0c8b40db67
commit
b54a9a5679
@ -17,6 +17,7 @@
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
|
#include "hw/sd/sd.h"
|
||||||
#include "hw/gpio/bcm2838_gpio.h"
|
#include "hw/gpio/bcm2838_gpio.h"
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
|
|
||||||
@ -63,6 +64,16 @@
|
|||||||
|
|
||||||
#define BYTES_IN_WORD 4
|
#define BYTES_IN_WORD 4
|
||||||
|
|
||||||
|
/* bcm,function property */
|
||||||
|
#define BCM2838_FSEL_GPIO_IN 0
|
||||||
|
#define BCM2838_FSEL_GPIO_OUT 1
|
||||||
|
#define BCM2838_FSEL_ALT5 2
|
||||||
|
#define BCM2838_FSEL_ALT4 3
|
||||||
|
#define BCM2838_FSEL_ALT0 4
|
||||||
|
#define BCM2838_FSEL_ALT1 5
|
||||||
|
#define BCM2838_FSEL_ALT2 6
|
||||||
|
#define BCM2838_FSEL_ALT3 7
|
||||||
|
|
||||||
static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
|
static uint32_t gpfsel_get(BCM2838GpioState *s, uint8_t reg)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -86,6 +97,31 @@ static void gpfsel_set(BCM2838GpioState *s, uint8_t reg, uint32_t value)
|
|||||||
s->fsel[index] = fsel;
|
s->fsel[index] = fsel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SD controller selection (48-53) */
|
||||||
|
if (s->sd_fsel != BCM2838_FSEL_GPIO_IN
|
||||||
|
&& (s->fsel[48] == BCM2838_FSEL_GPIO_IN)
|
||||||
|
&& (s->fsel[49] == BCM2838_FSEL_GPIO_IN)
|
||||||
|
&& (s->fsel[50] == BCM2838_FSEL_GPIO_IN)
|
||||||
|
&& (s->fsel[51] == BCM2838_FSEL_GPIO_IN)
|
||||||
|
&& (s->fsel[52] == BCM2838_FSEL_GPIO_IN)
|
||||||
|
&& (s->fsel[53] == BCM2838_FSEL_GPIO_IN)
|
||||||
|
) {
|
||||||
|
/* SDHCI controller selected */
|
||||||
|
sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci);
|
||||||
|
s->sd_fsel = BCM2838_FSEL_GPIO_IN;
|
||||||
|
} else if (s->sd_fsel != BCM2838_FSEL_ALT0
|
||||||
|
&& (s->fsel[48] == BCM2838_FSEL_ALT0) /* SD_CLK_R */
|
||||||
|
&& (s->fsel[49] == BCM2838_FSEL_ALT0) /* SD_CMD_R */
|
||||||
|
&& (s->fsel[50] == BCM2838_FSEL_ALT0) /* SD_DATA0_R */
|
||||||
|
&& (s->fsel[51] == BCM2838_FSEL_ALT0) /* SD_DATA1_R */
|
||||||
|
&& (s->fsel[52] == BCM2838_FSEL_ALT0) /* SD_DATA2_R */
|
||||||
|
&& (s->fsel[53] == BCM2838_FSEL_ALT0) /* SD_DATA3_R */
|
||||||
|
) {
|
||||||
|
/* SDHost controller selected */
|
||||||
|
sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost);
|
||||||
|
s->sd_fsel = BCM2838_FSEL_ALT0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gpfsel_is_out(BCM2838GpioState *s, int index)
|
static int gpfsel_is_out(BCM2838GpioState *s, int index)
|
||||||
@ -266,6 +302,11 @@ static void bcm2838_gpio_reset(DeviceState *dev)
|
|||||||
|
|
||||||
memset(s->fsel, 0, sizeof(s->fsel));
|
memset(s->fsel, 0, sizeof(s->fsel));
|
||||||
|
|
||||||
|
s->sd_fsel = 0;
|
||||||
|
|
||||||
|
/* SDHCI is selected by default */
|
||||||
|
sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci);
|
||||||
|
|
||||||
s->lev0 = 0;
|
s->lev0 = 0;
|
||||||
s->lev1 = 0;
|
s->lev1 = 0;
|
||||||
|
|
||||||
@ -304,6 +345,8 @@ static void bcm2838_gpio_init(Object *obj)
|
|||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
|
|
||||||
|
qbus_init(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(s), "sd-bus");
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, obj, &bcm2838_gpio_ops, s,
|
memory_region_init_io(&s->iomem, obj, &bcm2838_gpio_ops, s,
|
||||||
"bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
|
"bcm2838_gpio", BCM2838_GPIO_REGS_SIZE);
|
||||||
sysbus_init_mmio(sbd, &s->iomem);
|
sysbus_init_mmio(sbd, &s->iomem);
|
||||||
@ -312,7 +355,14 @@ static void bcm2838_gpio_init(Object *obj)
|
|||||||
|
|
||||||
static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
|
static void bcm2838_gpio_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
/* Temporary stub. Do nothing */
|
BCM2838GpioState *s = BCM2838_GPIO(dev);
|
||||||
|
Object *obj;
|
||||||
|
|
||||||
|
obj = object_property_get_link(OBJECT(dev), "sdbus-sdhci", &error_abort);
|
||||||
|
s->sdbus_sdhci = SD_BUS(obj);
|
||||||
|
|
||||||
|
obj = object_property_get_link(OBJECT(dev), "sdbus-sdhost", &error_abort);
|
||||||
|
s->sdbus_sdhost = SD_BUS(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
|
static void bcm2838_gpio_class_init(ObjectClass *klass, void *data)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#ifndef BCM2838_GPIO_H
|
#ifndef BCM2838_GPIO_H
|
||||||
#define BCM2838_GPIO_H
|
#define BCM2838_GPIO_H
|
||||||
|
|
||||||
|
#include "hw/sd/sd.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
|
||||||
@ -29,6 +30,10 @@ struct BCM2838GpioState {
|
|||||||
|
|
||||||
MemoryRegion iomem;
|
MemoryRegion iomem;
|
||||||
|
|
||||||
|
/* SDBus selector */
|
||||||
|
SDBus sdbus;
|
||||||
|
SDBus *sdbus_sdhci;
|
||||||
|
SDBus *sdbus_sdhost;
|
||||||
|
|
||||||
uint8_t fsel[BCM2838_GPIO_NUM];
|
uint8_t fsel[BCM2838_GPIO_NUM];
|
||||||
uint32_t lev0, lev1;
|
uint32_t lev0, lev1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user