From nobody Wed May 8 11:08:50 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487954984311517.039773804198; Fri, 24 Feb 2017 08:49:44 -0800 (PST) Received: from localhost ([::1]:38466 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chJ3t-00041N-UB for importer@patchew.org; Fri, 24 Feb 2017 11:49:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50451) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chIuz-0003QC-R9 for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1chIux-0001Cr-Sl for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:29 -0500 Received: from bee.antfield.fr ([188.165.75.195]:53522) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1chIus-0001A1-Vd; Fri, 24 Feb 2017 11:40:23 -0500 From: Clement Deschamps DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=antfield.fr; s=mail; t=1487954421; bh=PG9U60+vUsyUKgbjnnwYBCri9Nf4z/odJSdlEgQjtfU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lMaTJTDDoex/9XmHXL625U4Pzc0uJCRPdtRa/pW9+p3iWMaBiu3et5aX6fuaEU93l ukvA55SaH5rAHSmtV13MWVsd5pglPAVmFwkE/u3nZjJXde6tH5eWy9zUrmTpLpRq4I 1WhLvW+8GzlB6yJ5/SBq9yA6InAi9jOaIT4+scbk= To: qemu-devel@nongnu.org Date: Fri, 24 Feb 2017 17:40:18 +0100 Message-Id: <20170224164021.9066-2-clement.deschamps@antfield.fr> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170224164021.9066-1-clement.deschamps@antfield.fr> References: <20170224164021.9066-1-clement.deschamps@antfield.fr> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 188.165.75.195 Subject: [Qemu-devel] [PATCH v3 1/4] bcm2835_sdhost: add bcm2835 sdhost controller X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, qemu-arm@nongnu.org, Clement Deschamps , andrew.baumann@microsoft.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This adds the BCM2835 SDHost controller from Arasan. Signed-off-by: Clement Deschamps --- hw/sd/Makefile.objs | 1 + hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++++++++++++++++++++++= ++++ include/hw/sd/bcm2835_sdhost.h | 48 +++++ 3 files changed, 478 insertions(+) create mode 100644 hw/sd/bcm2835_sdhost.c create mode 100644 include/hw/sd/bcm2835_sdhost.h diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs index 31c83308f2..c2b7664264 100644 --- a/hw/sd/Makefile.objs +++ b/hw/sd/Makefile.objs @@ -6,3 +6,4 @@ common-obj-$(CONFIG_SDHCI) +=3D sdhci.o obj-$(CONFIG_MILKYMIST) +=3D milkymist-memcard.o obj-$(CONFIG_OMAP) +=3D omap_mmc.o obj-$(CONFIG_PXA2XX) +=3D pxa2xx_mmci.o +obj-$(CONFIG_RASPI) +=3D bcm2835_sdhost.o diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c new file mode 100644 index 0000000000..f7f4e656df --- /dev/null +++ b/hw/sd/bcm2835_sdhost.c @@ -0,0 +1,429 @@ +/* + * Raspberry Pi (BCM2835) SD Host Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "sysemu/blockdev.h" +#include "hw/sd/bcm2835_sdhost.h" + +#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus" +#define BCM2835_SDHOST_BUS(obj) \ + OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS) + +#define SDCMD 0x00 /* Command to SD card - 16 R/W */ +#define SDARG 0x04 /* Argument to SD card - 32 R/W */ +#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ +#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ +#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */ +#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */ +#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */ +#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */ +#define SDHSTS 0x20 /* SD host status - 11 R */ +#define SDVDD 0x30 /* SD card power control - 1 R/W */ +#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ +#define SDHCFG 0x38 /* Host configuration - 2 R/W */ +#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ +#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ +#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ + +#define SDCMD_NEW_FLAG 0x8000 +#define SDCMD_FAIL_FLAG 0x4000 +#define SDCMD_BUSYWAIT 0x800 +#define SDCMD_NO_RESPONSE 0x400 +#define SDCMD_LONG_RESPONSE 0x200 +#define SDCMD_WRITE_CMD 0x80 +#define SDCMD_READ_CMD 0x40 +#define SDCMD_CMD_MASK 0x3f + +#define SDCDIV_MAX_CDIV 0x7ff + +#define SDHSTS_BUSY_IRPT 0x400 +#define SDHSTS_BLOCK_IRPT 0x200 +#define SDHSTS_SDIO_IRPT 0x100 +#define SDHSTS_REW_TIME_OUT 0x80 +#define SDHSTS_CMD_TIME_OUT 0x40 +#define SDHSTS_CRC16_ERROR 0x20 +#define SDHSTS_CRC7_ERROR 0x10 +#define SDHSTS_FIFO_ERROR 0x08 +/* Reserved */ +/* Reserved */ +#define SDHSTS_DATA_FLAG 0x01 + +#define SDHCFG_BUSY_IRPT_EN (1 << 10) +#define SDHCFG_BLOCK_IRPT_EN (1 << 8) +#define SDHCFG_SDIO_IRPT_EN (1 << 5) +#define SDHCFG_DATA_IRPT_EN (1 << 4) +#define SDHCFG_SLOW_CARD (1 << 3) +#define SDHCFG_WIDE_EXT_BUS (1 << 2) +#define SDHCFG_WIDE_INT_BUS (1 << 1) +#define SDHCFG_REL_CMD_LINE (1 << 0) + +#define SDEDM_FORCE_DATA_MODE (1 << 19) +#define SDEDM_CLOCK_PULSE (1 << 20) +#define SDEDM_BYPASS (1 << 21) + +#define SDEDM_WRITE_THRESHOLD_SHIFT 9 +#define SDEDM_READ_THRESHOLD_SHIFT 14 +#define SDEDM_THRESHOLD_MASK 0x1f + +#define SDEDM_FSM_MASK 0xf +#define SDEDM_FSM_IDENTMODE 0x0 +#define SDEDM_FSM_DATAMODE 0x1 +#define SDEDM_FSM_READDATA 0x2 +#define SDEDM_FSM_WRITEDATA 0x3 +#define SDEDM_FSM_READWAIT 0x4 +#define SDEDM_FSM_READCRC 0x5 +#define SDEDM_FSM_WRITECRC 0x6 +#define SDEDM_FSM_WRITEWAIT1 0x7 +#define SDEDM_FSM_POWERDOWN 0x8 +#define SDEDM_FSM_POWERUP 0x9 +#define SDEDM_FSM_WRITESTART1 0xa +#define SDEDM_FSM_WRITESTART2 0xb +#define SDEDM_FSM_GENPULSES 0xc +#define SDEDM_FSM_WRITEWAIT2 0xd +#define SDEDM_FSM_STARTPOWDOWN 0xf + +#define SDDATA_FIFO_WORDS 16 + +static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s) +{ + uint32_t irq =3D s->status & + (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT); + qemu_set_irq(s->irq, !!irq); +} + +static void bcm2835_sdhost_send_command(BCM2835SDHostState *s) +{ + SDRequest request; + uint8_t rsp[16]; + int rlen; + + request.cmd =3D s->cmd & SDCMD_CMD_MASK; + request.arg =3D s->cmdarg; + + rlen =3D sdbus_do_command(&s->sdbus, &request, rsp); + if (rlen < 0) { + goto error; + } + if (!(s->cmd & SDCMD_NO_RESPONSE)) { +#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \ + | (rsp[n + 2] << 8) | rsp[n + 3]) + if (rlen =3D=3D 0 || (rlen =3D=3D 4 && (s->cmd & SDCMD_LONG_RESPON= SE))) { + goto error; + } + if (rlen !=3D 4 && rlen !=3D 16) { + goto error; + } + if (rlen =3D=3D 4) { + s->rsp[0] =3D RWORD(0); + s->rsp[1] =3D s->rsp[2] =3D s->rsp[3] =3D 0; + } else { + s->rsp[0] =3D RWORD(12); + s->rsp[1] =3D RWORD(8); + s->rsp[2] =3D RWORD(4); + s->rsp[3] =3D RWORD(0); + } +#undef RWORD + } + return; + +error: + s->cmd |=3D SDCMD_FAIL_FLAG; + s->status |=3D SDHSTS_CMD_TIME_OUT; +} + +static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value) +{ + int n; + + if (s->fifo_len =3D=3D BCM2835_SDHOST_FIFO_LEN) { + /* FIFO overflow */ + return; + } + n =3D (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1); + s->fifo_len++; + s->fifo[n] =3D value; +} + +static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s) +{ + uint32_t value; + + if (s->fifo_len =3D=3D 0) { + /* FIFO underflow */ + return 0; + } + value =3D s->fifo[s->fifo_pos]; + s->fifo_len--; + s->fifo_pos =3D (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1); + return value; +} + +static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) +{ + uint32_t value =3D 0; + int n; + int is_read; + + is_read =3D (s->cmd & SDCMD_READ_CMD) !=3D 0; + if (s->datacnt !=3D 0 && (!is_read || sdbus_data_ready(&s->sdbus))) { + if (is_read) { + n =3D 0; + while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) { + value |=3D (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8); + s->datacnt--; + n++; + if (n =3D=3D 4) { + bcm2835_sdhost_fifo_push(s, value); + n =3D 0; + value =3D 0; + } + } + if (n !=3D 0) { + bcm2835_sdhost_fifo_push(s, value); + } + } else { /* write */ + n =3D 0; + while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) { + if (n =3D=3D 0) { + value =3D bcm2835_sdhost_fifo_pop(s); + n =3D 4; + } + n--; + s->datacnt--; + sdbus_write_data(&s->sdbus, value & 0xff); + value >>=3D 8; + } + } + } + if (s->datacnt =3D=3D 0) { + s->status |=3D SDHSTS_DATA_FLAG; + + s->edm &=3D ~0xf; + s->edm |=3D SDEDM_FSM_DATAMODE; + + if (s->config & SDHCFG_DATA_IRPT_EN) { + s->status |=3D SDHSTS_SDIO_IRPT; + } + + if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)= ) { + s->status |=3D SDHSTS_BUSY_IRPT; + } + + if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_E= N)) { + s->status |=3D SDHSTS_BLOCK_IRPT; + } + + bcm2835_sdhost_update_irq(s); + } + + s->edm &=3D ~(0x1f << 4); + s->edm |=3D ((s->fifo_len & 0x1f) << 4); +} + +static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset, + unsigned size) +{ + BCM2835SDHostState *s =3D (BCM2835SDHostState *)opaque; + uint32_t res =3D 0; + + switch (offset) { + case SDCMD: + res =3D s->cmd; + break; + case SDHSTS: + res =3D s->status; + break; + case SDRSP0: + res =3D s->rsp[0]; + break; + case SDRSP1: + res =3D s->rsp[1]; + break; + case SDRSP2: + res =3D s->rsp[2]; + break; + case SDRSP3: + res =3D s->rsp[3]; + break; + case SDEDM: + res =3D s->edm; + break; + case SDVDD: + res =3D s->vdd; + break; + case SDDATA: + res =3D bcm2835_sdhost_fifo_pop(s); + bcm2835_sdhost_fifo_run(s); + break; + case SDHBCT: + res =3D s->hbct; + break; + case SDHBLC: + res =3D s->hblc; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); + res =3D 0; + break; + } + + return res; +} + +static void bcm2835_sdhost_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + BCM2835SDHostState *s =3D (BCM2835SDHostState *)opaque; + + switch (offset) { + case SDCMD: + s->cmd =3D value; + if (value & SDCMD_NEW_FLAG) { + bcm2835_sdhost_send_command(s); + bcm2835_sdhost_fifo_run(s); + s->cmd &=3D ~SDCMD_NEW_FLAG; + } + break; + case SDTOUT: + break; + case SDCDIV: + break; + case SDHSTS: + s->status &=3D ~value; + bcm2835_sdhost_update_irq(s); + break; + case SDARG: + s->cmdarg =3D value; + break; + case SDEDM: + if ((value & 0xf) =3D=3D 0xf) { + /* power down */ + value &=3D ~0xf; + } + s->edm =3D value; + break; + case SDHCFG: + s->config =3D value; + bcm2835_sdhost_fifo_run(s); + break; + case SDVDD: + s->vdd =3D value; + break; + case SDDATA: + bcm2835_sdhost_fifo_push(s, value); + bcm2835_sdhost_fifo_run(s); + break; + case SDHBCT: + s->hbct =3D value; + break; + case SDHBLC: + s->hblc =3D value; + s->datacnt =3D s->hblc * s->hbct; + bcm2835_sdhost_fifo_run(s); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); + break; + } +} + +static const MemoryRegionOps bcm2835_sdhost_ops =3D { + .read =3D bcm2835_sdhost_read, + .write =3D bcm2835_sdhost_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_bcm2835_sdhost =3D { + .name =3D TYPE_BCM2835_SDHOST, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(cmd, BCM2835SDHostState), + VMSTATE_UINT32(cmdarg, BCM2835SDHostState), + VMSTATE_UINT32(status, BCM2835SDHostState), + VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4), + VMSTATE_UINT32(config, BCM2835SDHostState), + VMSTATE_UINT32(edm, BCM2835SDHostState), + VMSTATE_UINT32(vdd, BCM2835SDHostState), + VMSTATE_UINT32(hbct, BCM2835SDHostState), + VMSTATE_UINT32(hblc, BCM2835SDHostState), + VMSTATE_INT32(fifo_pos, BCM2835SDHostState), + VMSTATE_INT32(fifo_len, BCM2835SDHostState), + VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO= _LEN), + VMSTATE_UINT32(datacnt, BCM2835SDHostState), + VMSTATE_END_OF_LIST() + } +}; + +static void bcm2835_sdhost_init(Object *obj) +{ + BCM2835SDHostState *s =3D BCM2835_SDHOST(obj); + + qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), + TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus"); + + memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s, + TYPE_BCM2835_SDHOST, 0x1000); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); +} + +static void bcm2835_sdhost_reset(DeviceState *dev) +{ + BCM2835SDHostState *s =3D BCM2835_SDHOST(dev); + + s->cmd =3D 0; + s->cmdarg =3D 0; + s->edm =3D 0x0000c60f; + s->config =3D 0; + s->hbct =3D 0; + s->hblc =3D 0; + s->datacnt =3D 0; + s->fifo_pos =3D 0; + s->fifo_len =3D 0; +} + +static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D bcm2835_sdhost_reset; + dc->vmsd =3D &vmstate_bcm2835_sdhost; +} + +static TypeInfo bcm2835_sdhost_info =3D { + .name =3D TYPE_BCM2835_SDHOST, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BCM2835SDHostState), + .class_init =3D bcm2835_sdhost_class_init, + .instance_init =3D bcm2835_sdhost_init, +}; + +static const TypeInfo bcm2835_sdhost_bus_info =3D { + .name =3D TYPE_BCM2835_SDHOST_BUS, + .parent =3D TYPE_SD_BUS, + .instance_size =3D sizeof(SDBus), +}; + +static void bcm2835_sdhost_register_types(void) +{ + type_register_static(&bcm2835_sdhost_info); + type_register_static(&bcm2835_sdhost_bus_info); +} + +type_init(bcm2835_sdhost_register_types) diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h new file mode 100644 index 0000000000..7520dd6507 --- /dev/null +++ b/include/hw/sd/bcm2835_sdhost.h @@ -0,0 +1,48 @@ +/* + * Raspberry Pi (BCM2835) SD Host Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef BCM2835_SDHOST_H +#define BCM2835_SDHOST_H + +#include "hw/sysbus.h" +#include "hw/sd/sd.h" + +#define TYPE_BCM2835_SDHOST "bcm2835-sdhost" +#define BCM2835_SDHOST(obj) \ + OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST) + +#define BCM2835_SDHOST_FIFO_LEN 16 + +typedef struct { + SysBusDevice busdev; + SDBus sdbus; + MemoryRegion iomem; + + uint32_t cmd; + uint32_t cmdarg; + uint32_t status; + uint32_t rsp[4]; + uint32_t config; + uint32_t edm; + uint32_t vdd; + uint32_t hbct; + uint32_t hblc; + int32_t fifo_pos; + int32_t fifo_len; + uint32_t fifo[BCM2835_SDHOST_FIFO_LEN]; + uint32_t datacnt; + + qemu_irq irq; +} BCM2835SDHostState; + +#endif --=20 2.11.1 From nobody Wed May 8 11:08:50 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487954543830818.019758185102; Fri, 24 Feb 2017 08:42:23 -0800 (PST) Received: from localhost ([::1]:38424 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chIwm-0004lD-BC for importer@patchew.org; Fri, 24 Feb 2017 11:42:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50419) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chIux-0003OA-QE for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1chIuw-0001CK-Mq for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:27 -0500 Received: from bee.antfield.fr ([188.165.75.195]:53530) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1chIut-0001AP-WF; Fri, 24 Feb 2017 11:40:24 -0500 From: Clement Deschamps DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=antfield.fr; s=mail; t=1487954422; bh=tb157WVU0QAJ6b7YN1lvjS5m5CpCvxeLmj7cgDk2yVY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=anvkM6WLh+0deJQeBsqy+6mr0UEQOuIk1Hc2O6SaTui8cFKbh43zPxf5H4QCZQT0D tmj/s+aM4pAhctZ1CitqZlH0byJU/31h+Z5yeO8H3WdZSC1qoP8odp+cdHfY6nSbx8 5t8NPpk68vweAT8+QdBUG+Uarg117fbnI524qBo8= To: qemu-devel@nongnu.org Date: Fri, 24 Feb 2017 17:40:19 +0100 Message-Id: <20170224164021.9066-3-clement.deschamps@antfield.fr> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170224164021.9066-1-clement.deschamps@antfield.fr> References: <20170224164021.9066-1-clement.deschamps@antfield.fr> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 188.165.75.195 Subject: [Qemu-devel] [PATCH v3 2/4] hw/sd: add card-reparenting function X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, qemu-arm@nongnu.org, Clement Deschamps , andrew.baumann@microsoft.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Provide a new function sdbus_reparent_card() in sd core for reparenting a card from a SDBus to another one. This function is required by the raspi platform, where the two SD controllers can be dynamically switched. Signed-off-by: Clement Deschamps --- hw/sd/core.c | 30 ++++++++++++++++++++++++++++++ include/hw/sd/sd.h | 1 + 2 files changed, 31 insertions(+) diff --git a/hw/sd/core.c b/hw/sd/core.c index 14c2bdf27b..a8f24f505f 100644 --- a/hw/sd/core.c +++ b/hw/sd/core.c @@ -131,6 +131,36 @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly) } } =20 +void sdbus_reparent_card(SDBus *from, SDBus *to) +{ + BusChild *kid =3D QTAILQ_FIRST(&from->qbus.children); + SDState *card; + SDCardClass *sc; + bool readonly; + + /* We directly reparent the card object rather than implementing this + * as a hotpluggable connection because we don't want to expose SD car= ds + * to users as being hotpluggable, and we can get away with it in this + * limited use case. This could perhaps be implemented more cleanly in + * future by adding support to the hotplug infrastructure for "device + * can be hotplugged only via code, not by user". + */ + + if (!kid) { + return; + } + + card =3D SD_CARD(kid->child); + sc =3D SD_CARD_GET_CLASS(card); + readonly =3D sc->get_readonly(card); + + sdbus_set_inserted(from, false); + object_unparent(OBJECT(kid)); + qdev_set_parent_bus(DEVICE(card), &to->qbus); + sdbus_set_inserted(to, true); + sdbus_set_readonly(to, readonly); +} + static const TypeInfo sd_bus_info =3D { .name =3D TYPE_SD_BUS, .parent =3D TYPE_BUS, diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index 79909b2478..54eaf9b554 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -140,6 +140,7 @@ uint8_t sdbus_read_data(SDBus *sd); bool sdbus_data_ready(SDBus *sd); bool sdbus_get_inserted(SDBus *sd); bool sdbus_get_readonly(SDBus *sd); +void sdbus_reparent_card(SDBus *from, SDBus *to); =20 /* Functions to be used by SD devices to report back to qdevified controll= ers */ void sdbus_set_inserted(SDBus *sd, bool inserted); --=20 2.11.1 From nobody Wed May 8 11:08:50 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487954563971703.1038051832772; Fri, 24 Feb 2017 08:42:43 -0800 (PST) Received: from localhost ([::1]:38427 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chIx8-0005MO-Kq for importer@patchew.org; Fri, 24 Feb 2017 11:42:42 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50455) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chIv0-0003QR-3F for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1chIuy-0001DH-Cl for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:30 -0500 Received: from bee.antfield.fr ([188.165.75.195]:53534) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1chIuu-0001Aq-Mp; Fri, 24 Feb 2017 11:40:24 -0500 From: Clement Deschamps DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=antfield.fr; s=mail; t=1487954423; bh=Z2JKHKQ9WEOVzcD22zFBPsWIXu/uMW0r9IXocOJ8NTI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eEe0M/L//9RD+PjHQ9G0Y5iaoABLsNPaNkVXvXQG8FxqVNRO7/l0ECuCN4NBaS0RF Fvc+SoPxwQJu5uPHNkDVnb+HrQhND+vWAoC87WNsDBXjhOevM+iYb86Gur62OH3sWY 55WoZ6uNQR1t14TV4ltBCwkdGXq+yx4qbqS52gEE= To: qemu-devel@nongnu.org Date: Fri, 24 Feb 2017 17:40:20 +0100 Message-Id: <20170224164021.9066-4-clement.deschamps@antfield.fr> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170224164021.9066-1-clement.deschamps@antfield.fr> References: <20170224164021.9066-1-clement.deschamps@antfield.fr> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 188.165.75.195 Subject: [Qemu-devel] [PATCH v3 3/4] bcm2835_gpio: add bcm2835 gpio controller X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, qemu-arm@nongnu.org, Clement Deschamps , andrew.baumann@microsoft.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This adds the BCM2835 GPIO controller. It currently implements: - The 54 GPIOs as outputs (qemu_irq) - The SD controller selection via alternate function of GPIOs 48-53 Signed-off-by: Clement Deschamps --- hw/gpio/Makefile.objs | 1 + hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++= ++++ include/hw/gpio/bcm2835_gpio.h | 39 +++++ 3 files changed, 393 insertions(+) create mode 100644 hw/gpio/bcm2835_gpio.c create mode 100644 include/hw/gpio/bcm2835_gpio.h diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs index a43c7cf442..fa0a72e6d0 100644 --- a/hw/gpio/Makefile.objs +++ b/hw/gpio/Makefile.objs @@ -7,3 +7,4 @@ common-obj-$(CONFIG_GPIO_KEY) +=3D gpio_key.o =20 obj-$(CONFIG_OMAP) +=3D omap_gpio.o obj-$(CONFIG_IMX) +=3D imx_gpio.o +obj-$(CONFIG_RASPI) +=3D bcm2835_gpio.o diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c new file mode 100644 index 0000000000..acc2e3cf9e --- /dev/null +++ b/hw/gpio/bcm2835_gpio.c @@ -0,0 +1,353 @@ +/* + * Raspberry Pi (BCM2835) GPIO Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/timer.h" +#include "qapi/error.h" +#include "hw/sysbus.h" +#include "hw/sd/sd.h" +#include "hw/gpio/bcm2835_gpio.h" + +#define GPFSEL0 0x00 +#define GPFSEL1 0x04 +#define GPFSEL2 0x08 +#define GPFSEL3 0x0C +#define GPFSEL4 0x10 +#define GPFSEL5 0x14 +#define GPSET0 0x1C +#define GPSET1 0x20 +#define GPCLR0 0x28 +#define GPCLR1 0x2C +#define GPLEV0 0x34 +#define GPLEV1 0x38 +#define GPEDS0 0x40 +#define GPEDS1 0x44 +#define GPREN0 0x4C +#define GPREN1 0x50 +#define GPFEN0 0x58 +#define GPFEN1 0x5C +#define GPHEN0 0x64 +#define GPHEN1 0x68 +#define GPLEN0 0x70 +#define GPLEN1 0x74 +#define GPAREN0 0x7C +#define GPAREN1 0x80 +#define GPAFEN0 0x88 +#define GPAFEN1 0x8C +#define GPPUD 0x94 +#define GPPUDCLK0 0x98 +#define GPPUDCLK1 0x9C + +static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg) +{ + int i; + uint32_t value =3D 0; + for (i =3D 0; i < 10; i++) { + uint32_t index =3D 10 * reg + i; + if (index < sizeof(s->fsel)) { + value |=3D (s->fsel[index] & 0x7) << (3 * i); + } + } + return value; +} + +static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value) +{ + int i; + for (i =3D 0; i < 10; i++) { + uint32_t index =3D 10 * reg + i; + if (index < sizeof(s->fsel)) { + int fsel =3D (value >> (3 * i)) & 0x7; + s->fsel[index] =3D fsel; + } + } + + /* SD controller selection (48-53) */ + if (s->sd_fsel !=3D 0 + && (s->fsel[48] =3D=3D 0) /* SD_CLK_R */ + && (s->fsel[49] =3D=3D 0) /* SD_CMD_R */ + && (s->fsel[50] =3D=3D 0) /* SD_DATA0_R */ + && (s->fsel[51] =3D=3D 0) /* SD_DATA1_R */ + && (s->fsel[52] =3D=3D 0) /* SD_DATA2_R */ + && (s->fsel[53] =3D=3D 0) /* SD_DATA3_R */ + ) { + /* SDHCI controller selected */ + sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci); + s->sd_fsel =3D 0; + } else if (s->sd_fsel !=3D 4 + && (s->fsel[48] =3D=3D 4) /* SD_CLK_R */ + && (s->fsel[49] =3D=3D 4) /* SD_CMD_R */ + && (s->fsel[50] =3D=3D 4) /* SD_DATA0_R */ + && (s->fsel[51] =3D=3D 4) /* SD_DATA1_R */ + && (s->fsel[52] =3D=3D 4) /* SD_DATA2_R */ + && (s->fsel[53] =3D=3D 4) /* SD_DATA3_R */ + ) { + /* SDHost controller selected */ + sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost); + s->sd_fsel =3D 4; + } +} + +static int gpfsel_is_out(BCM2835GpioState *s, int index) +{ + if (index >=3D 0 && index < 54) { + return s->fsel[index] =3D=3D 1; + } + return 0; +} + +static void gpset(BCM2835GpioState *s, + uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) +{ + uint32_t changes =3D val & ~*lev; + uint32_t cur =3D 1; + + int i; + for (i =3D 0; i < count; i++) { + if ((changes & cur) && (gpfsel_is_out(s, start + i))) { + qemu_set_irq(s->out[start + i], 1); + } + cur <<=3D 1; + } + + *lev |=3D val; +} + +static void gpclr(BCM2835GpioState *s, + uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) +{ + uint32_t changes =3D val & *lev; + uint32_t cur =3D 1; + + int i; + for (i =3D 0; i < count; i++) { + if ((changes & cur) && (gpfsel_is_out(s, start + i))) { + qemu_set_irq(s->out[start + i], 0); + } + cur <<=3D 1; + } + + *lev &=3D ~val; +} + +static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset, + unsigned size) +{ + BCM2835GpioState *s =3D (BCM2835GpioState *)opaque; + + switch (offset) { + case GPFSEL0: + case GPFSEL1: + case GPFSEL2: + case GPFSEL3: + case GPFSEL4: + case GPFSEL5: + return gpfsel_get(s, offset / 4); + case GPSET0: + case GPSET1: + /* Write Only */ + return 0; + case GPCLR0: + case GPCLR1: + /* Write Only */ + return 0; + case GPLEV0: + return s->lev0; + case GPLEV1: + return s->lev1; + case GPEDS0: + case GPEDS1: + case GPREN0: + case GPREN1: + case GPFEN0: + case GPFEN1: + case GPHEN0: + case GPHEN1: + case GPLEN0: + case GPLEN1: + case GPAREN0: + case GPAREN1: + case GPAFEN0: + case GPAFEN1: + case GPPUD: + case GPPUDCLK0: + case GPPUDCLK1: + /* Not implemented */ + return 0; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); + break; + } + + return 0; +} + +static void bcm2835_gpio_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + BCM2835GpioState *s =3D (BCM2835GpioState *)opaque; + + switch (offset) { + case GPFSEL0: + case GPFSEL1: + case GPFSEL2: + case GPFSEL3: + case GPFSEL4: + case GPFSEL5: + gpfsel_set(s, offset / 4, value); + break; + case GPSET0: + gpset(s, value, 0, 32, &s->lev0); + break; + case GPSET1: + gpset(s, value, 32, 22, &s->lev1); + break; + case GPCLR0: + gpclr(s, value, 0, 32, &s->lev0); + break; + case GPCLR1: + gpclr(s, value, 32, 22, &s->lev1); + break; + case GPLEV0: + case GPLEV1: + /* Read Only */ + break; + case GPEDS0: + case GPEDS1: + case GPREN0: + case GPREN1: + case GPFEN0: + case GPFEN1: + case GPHEN0: + case GPHEN1: + case GPLEN0: + case GPLEN1: + case GPAREN0: + case GPAREN1: + case GPAFEN0: + case GPAFEN1: + case GPPUD: + case GPPUDCLK0: + case GPPUDCLK1: + /* Not implemented */ + break; + default: + goto err_out; + } + return; + +err_out: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); +} + +static void bcm2835_gpio_reset(DeviceState *dev) +{ + BCM2835GpioState *s =3D BCM2835_GPIO(dev); + + int i; + for (i =3D 0; i < 6; i++) { + gpfsel_set(s, i, 0); + } + + s->sd_fsel =3D 0; + + /* SDHCI is selected by default */ + sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci); + + s->lev0 =3D 0; + s->lev1 =3D 0; +} + +static const MemoryRegionOps bcm2835_gpio_ops =3D { + .read =3D bcm2835_gpio_read, + .write =3D bcm2835_gpio_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_bcm2835_gpio =3D { + .name =3D "bcm2835_gpio", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54), + VMSTATE_UINT32(lev0, BCM2835GpioState), + VMSTATE_UINT32(lev1, BCM2835GpioState), + VMSTATE_UINT8(sd_fsel, BCM2835GpioState), + VMSTATE_END_OF_LIST() + } +}; + +static void bcm2835_gpio_init(Object *obj) +{ + BCM2835GpioState *s =3D BCM2835_GPIO(obj); + DeviceState *dev =3D DEVICE(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), + TYPE_SD_BUS, DEVICE(s), "sd-bus"); + + memory_region_init_io(&s->iomem, obj, + &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + qdev_init_gpio_out(dev, s->out, 54); +} + +static void bcm2835_gpio_realize(DeviceState *dev, Error **errp) +{ + BCM2835GpioState *s =3D BCM2835_GPIO(dev); + Object *obj; + Error *err =3D NULL; + + obj =3D object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err); + if (obj =3D=3D NULL) { + error_setg(errp, "%s: required sdhci link not found: %s", + __func__, error_get_pretty(err)); + return; + } + s->sdbus_sdhci =3D SD_BUS(obj); + + obj =3D object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err); + if (obj =3D=3D NULL) { + error_setg(errp, "%s: required sdhost link not found: %s", + __func__, error_get_pretty(err)); + return; + } + s->sdbus_sdhost =3D SD_BUS(obj); +} + +static void bcm2835_gpio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D &vmstate_bcm2835_gpio; + dc->realize =3D &bcm2835_gpio_realize; + dc->reset =3D &bcm2835_gpio_reset; +} + +static const TypeInfo bcm2835_gpio_info =3D { + .name =3D TYPE_BCM2835_GPIO, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BCM2835GpioState), + .instance_init =3D bcm2835_gpio_init, + .class_init =3D bcm2835_gpio_class_init, +}; + +static void bcm2835_gpio_register_types(void) +{ + type_register_static(&bcm2835_gpio_info); +} + +type_init(bcm2835_gpio_register_types) diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h new file mode 100644 index 0000000000..9f8e0c720c --- /dev/null +++ b/include/hw/gpio/bcm2835_gpio.h @@ -0,0 +1,39 @@ +/* + * Raspberry Pi (BCM2835) GPIO Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef BCM2835_GPIO_H +#define BCM2835_GPIO_H + +#include "hw/sd/sd.h" + +typedef struct BCM2835GpioState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + + /* SDBus selector */ + SDBus sdbus; + SDBus *sdbus_sdhci; + SDBus *sdbus_sdhost; + + uint8_t fsel[54]; + uint32_t lev0, lev1; + uint8_t sd_fsel; + qemu_irq out[54]; +} BCM2835GpioState; + +#define TYPE_BCM2835_GPIO "bcm2835_gpio" +#define BCM2835_GPIO(obj) \ + OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO) + +#endif --=20 2.11.1 From nobody Wed May 8 11:08:50 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1487954556364777.1707128826018; Fri, 24 Feb 2017 08:42:36 -0800 (PST) Received: from localhost ([::1]:38425 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chIx1-0005G1-1U for importer@patchew.org; Fri, 24 Feb 2017 11:42:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50442) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1chIuz-0003Pj-E1 for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1chIuy-0001DM-EY for qemu-devel@nongnu.org; Fri, 24 Feb 2017 11:40:29 -0500 Received: from bee.antfield.fr ([188.165.75.195]:53544) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1chIuv-0001BG-JH; Fri, 24 Feb 2017 11:40:25 -0500 From: Clement Deschamps DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=antfield.fr; s=mail; t=1487954424; bh=gzw5WfhNkMnGyOJYHheNsdRSN/zO9n6T7QV0JKSxLfY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WkL50tgcvVwHn6roEq3yE+tshmrrnnAy8DplZgH25AVMkAByn792vmtY8GIzbQLMO leZXrayQ+wvZBVFHiV4tauUwjaVPMJsF6qbDBpYrnjLbJ2PeGGphM7Wg0zL5+3d7ZS L+6lnn4EGhVP5HkmeqxYtgonGD2RDAuvL5fZagRM= To: qemu-devel@nongnu.org Date: Fri, 24 Feb 2017 17:40:21 +0100 Message-Id: <20170224164021.9066-5-clement.deschamps@antfield.fr> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170224164021.9066-1-clement.deschamps@antfield.fr> References: <20170224164021.9066-1-clement.deschamps@antfield.fr> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 188.165.75.195 Subject: [Qemu-devel] [PATCH v3 4/4] bcm2835: add sdhost and gpio controllers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, qemu-arm@nongnu.org, Clement Deschamps , andrew.baumann@microsoft.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform. For supporting the SD controller selection (alternate function of GPIOs 48-53), the bcm2835_gpio now exposes an sdbus. It also has a link to both the sdbus of sdhci and sdhost controllers, and the card is reparented from one bus to another when the alternate function of GPIOs 48-53 is modified. Signed-off-by: Clement Deschamps --- hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++= ++-- include/hw/arm/bcm2835_peripherals.h | 4 ++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index 2e641a3989..33398b04db 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -91,6 +91,11 @@ static void bcm2835_peripherals_init(Object *obj) object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL); qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default()); =20 + /* SDHOST */ + object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST); + object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL); + qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default()); + /* DMA Channels */ object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA); object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL); @@ -98,6 +103,16 @@ static void bcm2835_peripherals_init(Object *obj) =20 object_property_add_const_link(OBJECT(&s->dma), "dma-mr", OBJECT(&s->gpu_bus_mr), &error_abort); + + /* GPIO */ + object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO); + object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL); + qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default()); + + object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci", + OBJECT(&s->sdhci.sdbus), &error_abort); + object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost", + OBJECT(&s->sdhost.sdbus), &error_abort); } =20 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) @@ -252,13 +267,20 @@ static void bcm2835_peripherals_realize(DeviceState *= dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_ARASANSDIO)); - object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-= bus", - &err); + + /* SDHOST */ + object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err); if (err) { error_propagate(errp, err); return; } =20 + memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0, + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_SDIO)); + /* DMA Channels */ object_property_set_bool(OBJECT(&s->dma), true, "realized", &err); if (err) { @@ -277,6 +299,23 @@ static void bcm2835_peripherals_realize(DeviceState *d= ev, Error **errp) BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0 + n)); } + + /* GPIO */ + object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); + + object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-b= us", + &err); + if (err) { + error_propagate(errp, err); + return; + } } =20 static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_= peripherals.h index e12ae3721a..4c87859e31 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -21,6 +21,8 @@ #include "hw/misc/bcm2835_property.h" #include "hw/misc/bcm2835_mbox.h" #include "hw/sd/sdhci.h" +#include "hw/sd/bcm2835_sdhost.h" +#include "hw/gpio/bcm2835_gpio.h" =20 #define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals" #define BCM2835_PERIPHERALS(obj) \ @@ -43,6 +45,8 @@ typedef struct BCM2835PeripheralState { BCM2835PropertyState property; BCM2835MboxState mboxes; SDHCIState sdhci; + BCM2835SDHostState sdhost; + BCM2835GpioState gpio; } BCM2835PeripheralState; =20 #endif /* BCM2835_PERIPHERALS_H */ --=20 2.11.1