From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666700144373.06643551522086; Sun, 13 Aug 2017 16:25:00 -0700 (PDT) Received: from localhost ([::1]:46251 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2Ff-0006ER-3Y for importer@patchew.org; Sun, 13 Aug 2017 19:24:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51888) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh274-0007Rh-2E for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005wN-MT for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:05 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:38236) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005ul-NO; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 23F9D747EE0; Mon, 14 Aug 2017 01:15:59 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 250A8747ED1; Mon, 14 Aug 2017 01:15:49 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 152.66.115.2 Subject: [Qemu-devel] [RFC PATCH 01/12] ppc4xx: Move MAL from ppc405_uc to ppc4xx_devs 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: Francois Revol , Alexander Graf , David Gibson 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 device appears in other SoCs as well not just in 405 ones Signed-off-by: BALATON Zoltan Reviewed-by: David Gibson --- hw/ppc/ppc405_uc.c | 263 --------------------------------------------= --- hw/ppc/ppc4xx_devs.c | 264 ++++++++++++++++++++++++++++++++++++++++++++= ++++ include/hw/ppc/ppc4xx.h | 2 + 3 files changed, 266 insertions(+), 263 deletions(-) diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index f6fe3e6..3c74402 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -42,7 +42,6 @@ //#define DEBUG_OCM //#define DEBUG_I2C //#define DEBUG_GPT -//#define DEBUG_MAL //#define DEBUG_CLOCKS //#define DEBUG_CLOCKS_LL =20 @@ -1513,268 +1512,6 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq i= rqs[5]) } =20 /*************************************************************************= ****/ -/* MAL */ -enum { - MAL0_CFG =3D 0x180, - MAL0_ESR =3D 0x181, - MAL0_IER =3D 0x182, - MAL0_TXCASR =3D 0x184, - MAL0_TXCARR =3D 0x185, - MAL0_TXEOBISR =3D 0x186, - MAL0_TXDEIR =3D 0x187, - MAL0_RXCASR =3D 0x190, - MAL0_RXCARR =3D 0x191, - MAL0_RXEOBISR =3D 0x192, - MAL0_RXDEIR =3D 0x193, - MAL0_TXCTP0R =3D 0x1A0, - MAL0_TXCTP1R =3D 0x1A1, - MAL0_TXCTP2R =3D 0x1A2, - MAL0_TXCTP3R =3D 0x1A3, - MAL0_RXCTP0R =3D 0x1C0, - MAL0_RXCTP1R =3D 0x1C1, - MAL0_RCBS0 =3D 0x1E0, - MAL0_RCBS1 =3D 0x1E1, -}; - -typedef struct ppc40x_mal_t ppc40x_mal_t; -struct ppc40x_mal_t { - qemu_irq irqs[4]; - uint32_t cfg; - uint32_t esr; - uint32_t ier; - uint32_t txcasr; - uint32_t txcarr; - uint32_t txeobisr; - uint32_t txdeir; - uint32_t rxcasr; - uint32_t rxcarr; - uint32_t rxeobisr; - uint32_t rxdeir; - uint32_t txctpr[4]; - uint32_t rxctpr[2]; - uint32_t rcbs[2]; -}; - -static void ppc40x_mal_reset (void *opaque); - -static uint32_t dcr_read_mal (void *opaque, int dcrn) -{ - ppc40x_mal_t *mal; - uint32_t ret; - - mal =3D opaque; - switch (dcrn) { - case MAL0_CFG: - ret =3D mal->cfg; - break; - case MAL0_ESR: - ret =3D mal->esr; - break; - case MAL0_IER: - ret =3D mal->ier; - break; - case MAL0_TXCASR: - ret =3D mal->txcasr; - break; - case MAL0_TXCARR: - ret =3D mal->txcarr; - break; - case MAL0_TXEOBISR: - ret =3D mal->txeobisr; - break; - case MAL0_TXDEIR: - ret =3D mal->txdeir; - break; - case MAL0_RXCASR: - ret =3D mal->rxcasr; - break; - case MAL0_RXCARR: - ret =3D mal->rxcarr; - break; - case MAL0_RXEOBISR: - ret =3D mal->rxeobisr; - break; - case MAL0_RXDEIR: - ret =3D mal->rxdeir; - break; - case MAL0_TXCTP0R: - ret =3D mal->txctpr[0]; - break; - case MAL0_TXCTP1R: - ret =3D mal->txctpr[1]; - break; - case MAL0_TXCTP2R: - ret =3D mal->txctpr[2]; - break; - case MAL0_TXCTP3R: - ret =3D mal->txctpr[3]; - break; - case MAL0_RXCTP0R: - ret =3D mal->rxctpr[0]; - break; - case MAL0_RXCTP1R: - ret =3D mal->rxctpr[1]; - break; - case MAL0_RCBS0: - ret =3D mal->rcbs[0]; - break; - case MAL0_RCBS1: - ret =3D mal->rcbs[1]; - break; - default: - ret =3D 0; - break; - } - - return ret; -} - -static void dcr_write_mal (void *opaque, int dcrn, uint32_t val) -{ - ppc40x_mal_t *mal; - int idx; - - mal =3D opaque; - switch (dcrn) { - case MAL0_CFG: - if (val & 0x80000000) - ppc40x_mal_reset(mal); - mal->cfg =3D val & 0x00FFC087; - break; - case MAL0_ESR: - /* Read/clear */ - mal->esr &=3D ~val; - break; - case MAL0_IER: - mal->ier =3D val & 0x0000001F; - break; - case MAL0_TXCASR: - mal->txcasr =3D val & 0xF0000000; - break; - case MAL0_TXCARR: - mal->txcarr =3D val & 0xF0000000; - break; - case MAL0_TXEOBISR: - /* Read/clear */ - mal->txeobisr &=3D ~val; - break; - case MAL0_TXDEIR: - /* Read/clear */ - mal->txdeir &=3D ~val; - break; - case MAL0_RXCASR: - mal->rxcasr =3D val & 0xC0000000; - break; - case MAL0_RXCARR: - mal->rxcarr =3D val & 0xC0000000; - break; - case MAL0_RXEOBISR: - /* Read/clear */ - mal->rxeobisr &=3D ~val; - break; - case MAL0_RXDEIR: - /* Read/clear */ - mal->rxdeir &=3D ~val; - break; - case MAL0_TXCTP0R: - idx =3D 0; - goto update_tx_ptr; - case MAL0_TXCTP1R: - idx =3D 1; - goto update_tx_ptr; - case MAL0_TXCTP2R: - idx =3D 2; - goto update_tx_ptr; - case MAL0_TXCTP3R: - idx =3D 3; - update_tx_ptr: - mal->txctpr[idx] =3D val; - break; - case MAL0_RXCTP0R: - idx =3D 0; - goto update_rx_ptr; - case MAL0_RXCTP1R: - idx =3D 1; - update_rx_ptr: - mal->rxctpr[idx] =3D val; - break; - case MAL0_RCBS0: - idx =3D 0; - goto update_rx_size; - case MAL0_RCBS1: - idx =3D 1; - update_rx_size: - mal->rcbs[idx] =3D val & 0x000000FF; - break; - } -} - -static void ppc40x_mal_reset (void *opaque) -{ - ppc40x_mal_t *mal; - - mal =3D opaque; - mal->cfg =3D 0x0007C000; - mal->esr =3D 0x00000000; - mal->ier =3D 0x00000000; - mal->rxcasr =3D 0x00000000; - mal->rxdeir =3D 0x00000000; - mal->rxeobisr =3D 0x00000000; - mal->txcasr =3D 0x00000000; - mal->txdeir =3D 0x00000000; - mal->txeobisr =3D 0x00000000; -} - -static void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]) -{ - ppc40x_mal_t *mal; - int i; - - mal =3D g_malloc0(sizeof(ppc40x_mal_t)); - for (i =3D 0; i < 4; i++) - mal->irqs[i] =3D irqs[i]; - qemu_register_reset(&ppc40x_mal_reset, mal); - ppc_dcr_register(env, MAL0_CFG, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_ESR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_IER, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCASR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCARR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXEOBISR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXDEIR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCASR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCARR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXEOBISR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXDEIR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP0R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP1R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP2R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP3R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCTP0R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCTP1R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RCBS0, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RCBS1, - mal, &dcr_read_mal, &dcr_write_mal); -} - -/*************************************************************************= ****/ /* SPR */ void ppc40x_core_reset(PowerPCCPU *cpu) { diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index e7f413e..8e4f78e 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -734,3 +734,267 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, i= nt nr_banks, =20 return ram_size; } + +/*************************************************************************= ****/ +/* MAL */ +enum { + MAL0_CFG =3D 0x180, + MAL0_ESR =3D 0x181, + MAL0_IER =3D 0x182, + MAL0_TXCASR =3D 0x184, + MAL0_TXCARR =3D 0x185, + MAL0_TXEOBISR =3D 0x186, + MAL0_TXDEIR =3D 0x187, + MAL0_RXCASR =3D 0x190, + MAL0_RXCARR =3D 0x191, + MAL0_RXEOBISR =3D 0x192, + MAL0_RXDEIR =3D 0x193, + MAL0_TXCTP0R =3D 0x1A0, + MAL0_TXCTP1R =3D 0x1A1, + MAL0_TXCTP2R =3D 0x1A2, + MAL0_TXCTP3R =3D 0x1A3, + MAL0_RXCTP0R =3D 0x1C0, + MAL0_RXCTP1R =3D 0x1C1, + MAL0_RCBS0 =3D 0x1E0, + MAL0_RCBS1 =3D 0x1E1, +}; + +typedef struct ppc40x_mal_t ppc40x_mal_t; +struct ppc40x_mal_t { + qemu_irq irqs[4]; + uint32_t cfg; + uint32_t esr; + uint32_t ier; + uint32_t txcasr; + uint32_t txcarr; + uint32_t txeobisr; + uint32_t txdeir; + uint32_t rxcasr; + uint32_t rxcarr; + uint32_t rxeobisr; + uint32_t rxdeir; + uint32_t txctpr[4]; + uint32_t rxctpr[2]; + uint32_t rcbs[2]; +}; + +static void ppc40x_mal_reset(void *opaque); + +static uint32_t dcr_read_mal(void *opaque, int dcrn) +{ + ppc40x_mal_t *mal; + uint32_t ret; + + mal =3D opaque; + switch (dcrn) { + case MAL0_CFG: + ret =3D mal->cfg; + break; + case MAL0_ESR: + ret =3D mal->esr; + break; + case MAL0_IER: + ret =3D mal->ier; + break; + case MAL0_TXCASR: + ret =3D mal->txcasr; + break; + case MAL0_TXCARR: + ret =3D mal->txcarr; + break; + case MAL0_TXEOBISR: + ret =3D mal->txeobisr; + break; + case MAL0_TXDEIR: + ret =3D mal->txdeir; + break; + case MAL0_RXCASR: + ret =3D mal->rxcasr; + break; + case MAL0_RXCARR: + ret =3D mal->rxcarr; + break; + case MAL0_RXEOBISR: + ret =3D mal->rxeobisr; + break; + case MAL0_RXDEIR: + ret =3D mal->rxdeir; + break; + case MAL0_TXCTP0R: + ret =3D mal->txctpr[0]; + break; + case MAL0_TXCTP1R: + ret =3D mal->txctpr[1]; + break; + case MAL0_TXCTP2R: + ret =3D mal->txctpr[2]; + break; + case MAL0_TXCTP3R: + ret =3D mal->txctpr[3]; + break; + case MAL0_RXCTP0R: + ret =3D mal->rxctpr[0]; + break; + case MAL0_RXCTP1R: + ret =3D mal->rxctpr[1]; + break; + case MAL0_RCBS0: + ret =3D mal->rcbs[0]; + break; + case MAL0_RCBS1: + ret =3D mal->rcbs[1]; + break; + default: + ret =3D 0; + break; + } + + return ret; +} + +static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) +{ + ppc40x_mal_t *mal; + int idx; + + mal =3D opaque; + switch (dcrn) { + case MAL0_CFG: + if (val & 0x80000000) { + ppc40x_mal_reset(mal); + } + mal->cfg =3D val & 0x00FFC087; + break; + case MAL0_ESR: + /* Read/clear */ + mal->esr &=3D ~val; + break; + case MAL0_IER: + mal->ier =3D val & 0x0000001F; + break; + case MAL0_TXCASR: + mal->txcasr =3D val & 0xF0000000; + break; + case MAL0_TXCARR: + mal->txcarr =3D val & 0xF0000000; + break; + case MAL0_TXEOBISR: + /* Read/clear */ + mal->txeobisr &=3D ~val; + break; + case MAL0_TXDEIR: + /* Read/clear */ + mal->txdeir &=3D ~val; + break; + case MAL0_RXCASR: + mal->rxcasr =3D val & 0xC0000000; + break; + case MAL0_RXCARR: + mal->rxcarr =3D val & 0xC0000000; + break; + case MAL0_RXEOBISR: + /* Read/clear */ + mal->rxeobisr &=3D ~val; + break; + case MAL0_RXDEIR: + /* Read/clear */ + mal->rxdeir &=3D ~val; + break; + case MAL0_TXCTP0R: + idx =3D 0; + goto update_tx_ptr; + case MAL0_TXCTP1R: + idx =3D 1; + goto update_tx_ptr; + case MAL0_TXCTP2R: + idx =3D 2; + goto update_tx_ptr; + case MAL0_TXCTP3R: + idx =3D 3; + update_tx_ptr: + mal->txctpr[idx] =3D val; + break; + case MAL0_RXCTP0R: + idx =3D 0; + goto update_rx_ptr; + case MAL0_RXCTP1R: + idx =3D 1; + update_rx_ptr: + mal->rxctpr[idx] =3D val; + break; + case MAL0_RCBS0: + idx =3D 0; + goto update_rx_size; + case MAL0_RCBS1: + idx =3D 1; + update_rx_size: + mal->rcbs[idx] =3D val & 0x000000FF; + break; + } +} + +static void ppc40x_mal_reset(void *opaque) +{ + ppc40x_mal_t *mal; + + mal =3D opaque; + mal->cfg =3D 0x0007C000; + mal->esr =3D 0x00000000; + mal->ier =3D 0x00000000; + mal->rxcasr =3D 0x00000000; + mal->rxdeir =3D 0x00000000; + mal->rxeobisr =3D 0x00000000; + mal->txcasr =3D 0x00000000; + mal->txdeir =3D 0x00000000; + mal->txeobisr =3D 0x00000000; +} + +void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]) +{ + ppc40x_mal_t *mal; + int i; + + mal =3D g_malloc0(sizeof(ppc40x_mal_t)); + for (i =3D 0; i < 4; i++) { + mal->irqs[i] =3D irqs[i]; + } + qemu_register_reset(&ppc40x_mal_reset, mal); + ppc_dcr_register(env, MAL0_CFG, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_ESR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_IER, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCASR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCARR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXEOBISR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXDEIR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCASR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCARR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXEOBISR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXDEIR, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP0R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP1R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP2R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_TXCTP3R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCTP0R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RXCTP1R, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RCBS0, + mal, &dcr_read_mal, &dcr_write_mal); + ppc_dcr_register(env, MAL0_RCBS1, + mal, &dcr_read_mal, &dcr_write_mal); +} diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index 66e57a5..db50cfa 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -53,6 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, i= nt nbanks, hwaddr *ram_sizes, int do_init); =20 +void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]); + #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" =20 #endif /* PPC4XX_H */ --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 150266667815272.10091241808038; Sun, 13 Aug 2017 16:24:38 -0700 (PDT) Received: from localhost ([::1]:46179 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2FH-0005oY-SA for importer@patchew.org; Sun, 13 Aug 2017 19:24:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51877) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh273-0007RW-VR for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005wM-NB for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:05 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:38237) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005um-N2; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 36AA6747EDA; Mon, 14 Aug 2017 01:15:59 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 406E7747ED8; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: <4282985e208e7c623dcb32e737cd43ab4c2a2716.1502643878.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 152.66.115.2 Subject: [Qemu-devel] [RFC PATCH 02/12] ppc4xx: Make MAL emulation more generic 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: Francois Revol , Alexander Graf , David Gibson 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" Allow MAL with more RX and TX channels as found in newer versions. Signed-off-by: BALATON Zoltan Reviewed-by: David Gibson --- hw/ppc/ppc405_uc.c | 2 +- hw/ppc/ppc4xx_devs.c | 171 +++++++++++++++++++-------------------------= ---- include/hw/ppc/ppc4xx.h | 3 +- 3 files changed, 70 insertions(+), 106 deletions(-) diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 3c74402..03856d5 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -2281,7 +2281,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_spac= e_mem, mal_irqs[1] =3D pic[12]; mal_irqs[2] =3D pic[13]; mal_irqs[3] =3D pic[14]; - ppc405_mal_init(env, mal_irqs); + ppc4xx_mal_init(env, 4, 2, mal_irqs); /* Ethernet */ /* Uses pic[9], pic[15], pic[17] */ /* CPU control */ diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 8e4f78e..6e1cc09 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -737,6 +737,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int= nr_banks, =20 /*************************************************************************= ****/ /* MAL */ + enum { MAL0_CFG =3D 0x180, MAL0_ESR =3D 0x181, @@ -750,17 +751,13 @@ enum { MAL0_RXEOBISR =3D 0x192, MAL0_RXDEIR =3D 0x193, MAL0_TXCTP0R =3D 0x1A0, - MAL0_TXCTP1R =3D 0x1A1, - MAL0_TXCTP2R =3D 0x1A2, - MAL0_TXCTP3R =3D 0x1A3, MAL0_RXCTP0R =3D 0x1C0, - MAL0_RXCTP1R =3D 0x1C1, MAL0_RCBS0 =3D 0x1E0, MAL0_RCBS1 =3D 0x1E1, }; =20 -typedef struct ppc40x_mal_t ppc40x_mal_t; -struct ppc40x_mal_t { +typedef struct ppc4xx_mal_t ppc4xx_mal_t; +struct ppc4xx_mal_t { qemu_irq irqs[4]; uint32_t cfg; uint32_t esr; @@ -773,16 +770,32 @@ struct ppc40x_mal_t { uint32_t rxcarr; uint32_t rxeobisr; uint32_t rxdeir; - uint32_t txctpr[4]; - uint32_t rxctpr[2]; - uint32_t rcbs[2]; + uint32_t *txctpr; + uint32_t *rxctpr; + uint32_t *rcbs; + uint8_t txcnum; + uint8_t rxcnum; }; =20 -static void ppc40x_mal_reset(void *opaque); +static void ppc4xx_mal_reset(void *opaque) +{ + ppc4xx_mal_t *mal; + + mal =3D opaque; + mal->cfg =3D 0x0007C000; + mal->esr =3D 0x00000000; + mal->ier =3D 0x00000000; + mal->rxcasr =3D 0x00000000; + mal->rxdeir =3D 0x00000000; + mal->rxeobisr =3D 0x00000000; + mal->txcasr =3D 0x00000000; + mal->txdeir =3D 0x00000000; + mal->txeobisr =3D 0x00000000; +} =20 static uint32_t dcr_read_mal(void *opaque, int dcrn) { - ppc40x_mal_t *mal; + ppc4xx_mal_t *mal; uint32_t ret; =20 mal =3D opaque; @@ -820,48 +833,32 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn) case MAL0_RXDEIR: ret =3D mal->rxdeir; break; - case MAL0_TXCTP0R: - ret =3D mal->txctpr[0]; - break; - case MAL0_TXCTP1R: - ret =3D mal->txctpr[1]; - break; - case MAL0_TXCTP2R: - ret =3D mal->txctpr[2]; - break; - case MAL0_TXCTP3R: - ret =3D mal->txctpr[3]; - break; - case MAL0_RXCTP0R: - ret =3D mal->rxctpr[0]; - break; - case MAL0_RXCTP1R: - ret =3D mal->rxctpr[1]; - break; - case MAL0_RCBS0: - ret =3D mal->rcbs[0]; - break; - case MAL0_RCBS1: - ret =3D mal->rcbs[1]; - break; default: ret =3D 0; break; } + if (dcrn >=3D MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) { + ret =3D mal->txctpr[dcrn - MAL0_TXCTP0R]; + } + if (dcrn >=3D MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) { + ret =3D mal->rxctpr[dcrn - MAL0_RXCTP0R]; + } + if (dcrn >=3D MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) { + ret =3D mal->rcbs[dcrn - MAL0_RCBS0]; + } =20 return ret; } =20 static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) { - ppc40x_mal_t *mal; - int idx; + ppc4xx_mal_t *mal; =20 mal =3D opaque; switch (dcrn) { case MAL0_CFG: if (val & 0x80000000) { - ppc40x_mal_reset(mal); + ppc4xx_mal_reset(mal); } mal->cfg =3D val & 0x00FFC087; break; @@ -900,65 +897,35 @@ static void dcr_write_mal(void *opaque, int dcrn, uin= t32_t val) /* Read/clear */ mal->rxdeir &=3D ~val; break; - case MAL0_TXCTP0R: - idx =3D 0; - goto update_tx_ptr; - case MAL0_TXCTP1R: - idx =3D 1; - goto update_tx_ptr; - case MAL0_TXCTP2R: - idx =3D 2; - goto update_tx_ptr; - case MAL0_TXCTP3R: - idx =3D 3; - update_tx_ptr: - mal->txctpr[idx] =3D val; - break; - case MAL0_RXCTP0R: - idx =3D 0; - goto update_rx_ptr; - case MAL0_RXCTP1R: - idx =3D 1; - update_rx_ptr: - mal->rxctpr[idx] =3D val; - break; - case MAL0_RCBS0: - idx =3D 0; - goto update_rx_size; - case MAL0_RCBS1: - idx =3D 1; - update_rx_size: - mal->rcbs[idx] =3D val & 0x000000FF; - break; + } + if (dcrn >=3D MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) { + mal->txctpr[dcrn - MAL0_TXCTP0R] =3D val; + } + if (dcrn >=3D MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) { + mal->rxctpr[dcrn - MAL0_RXCTP0R] =3D val; + } + if (dcrn >=3D MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) { + mal->rcbs[dcrn - MAL0_RCBS0] =3D val & 0x000000FF; } } =20 -static void ppc40x_mal_reset(void *opaque) -{ - ppc40x_mal_t *mal; - - mal =3D opaque; - mal->cfg =3D 0x0007C000; - mal->esr =3D 0x00000000; - mal->ier =3D 0x00000000; - mal->rxcasr =3D 0x00000000; - mal->rxdeir =3D 0x00000000; - mal->rxeobisr =3D 0x00000000; - mal->txcasr =3D 0x00000000; - mal->txdeir =3D 0x00000000; - mal->txeobisr =3D 0x00000000; -} - -void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]) +void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, + qemu_irq irqs[4]) { - ppc40x_mal_t *mal; + ppc4xx_mal_t *mal; int i; =20 - mal =3D g_malloc0(sizeof(ppc40x_mal_t)); + assert(txcnum <=3D 32 && rxcnum <=3D 32); + mal =3D g_malloc0(sizeof(*mal)); + mal->txcnum =3D txcnum; + mal->rxcnum =3D rxcnum; + mal->txctpr =3D g_new0(uint32_t, txcnum); + mal->rxctpr =3D g_new0(uint32_t, rxcnum); + mal->rcbs =3D g_new0(uint32_t, rxcnum); for (i =3D 0; i < 4; i++) { mal->irqs[i] =3D irqs[i]; } - qemu_register_reset(&ppc40x_mal_reset, mal); + qemu_register_reset(&ppc4xx_mal_reset, mal); ppc_dcr_register(env, MAL0_CFG, mal, &dcr_read_mal, &dcr_write_mal); ppc_dcr_register(env, MAL0_ESR, @@ -981,20 +948,16 @@ void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[= 4]) mal, &dcr_read_mal, &dcr_write_mal); ppc_dcr_register(env, MAL0_RXDEIR, mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP0R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP1R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP2R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCTP3R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCTP0R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCTP1R, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RCBS0, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RCBS1, - mal, &dcr_read_mal, &dcr_write_mal); + for (i =3D 0; i < txcnum; i++) { + ppc_dcr_register(env, MAL0_TXCTP0R + i, + mal, &dcr_read_mal, &dcr_write_mal); + } + for (i =3D 0; i < rxcnum; i++) { + ppc_dcr_register(env, MAL0_RXCTP0R + i, + mal, &dcr_read_mal, &dcr_write_mal); + } + for (i =3D 0; i < rxcnum; i++) { + ppc_dcr_register(env, MAL0_RCBS0 + i, + mal, &dcr_read_mal, &dcr_write_mal); + } } diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index db50cfa..cb0bb55 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -53,7 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, i= nt nbanks, hwaddr *ram_sizes, int do_init); =20 -void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4]); +void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, + qemu_irq irqs[4]); =20 #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" =20 --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666300053874.624093961214; Sun, 13 Aug 2017 16:18:20 -0700 (PDT) Received: from localhost ([::1]:46142 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh29A-0000SE-99 for importer@patchew.org; Sun, 13 Aug 2017 19:18:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51829) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh272-0007Pp-3q for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005w0-Io for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:04 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:38235) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005ui-Qs; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 52C76747EDF; Mon, 14 Aug 2017 01:15:58 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 58D7B747EDA; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [RFC PATCH 03/12] ohci: Allow sysbus version to be used as a companion 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: Francois Revol , Alexander Graf , David Gibson 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" Signed-off-by: BALATON Zoltan --- hw/usb/hcd-ohci.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 267982e..17beedd 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1999,7 +1999,9 @@ typedef struct { /*< public >*/ =20 OHCIState ohci; + char *masterbus; uint32_t num_ports; + uint32_t firstport; dma_addr_t dma_offset; } OHCISysBusState; =20 @@ -2007,10 +2009,15 @@ static void ohci_realize_pxa(DeviceState *dev, Erro= r **errp) { OHCISysBusState *s =3D SYSBUS_OHCI(dev); SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + Error *err =3D NULL; =20 - /* Cannot fail as we pass NULL for masterbus */ - usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0, - &address_space_memory, &error_abort); + usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, + s->masterbus, s->firstport, + &address_space_memory, &err); + if (err) { + error_propagate(errp, err); + return; + } sysbus_init_irq(sbd, &s->ohci.irq); sysbus_init_mmio(sbd, &s->ohci.mem); } @@ -2142,7 +2149,9 @@ static const TypeInfo ohci_pci_info =3D { }; =20 static Property ohci_sysbus_properties[] =3D { + DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus), DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3), + DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0), DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0), DEFINE_PROP_END_OF_LIST(), }; --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666298536297.5538942528948; Sun, 13 Aug 2017 16:18:18 -0700 (PDT) Received: from localhost ([::1]:46140 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh298-0000Qg-Vf for importer@patchew.org; Sun, 13 Aug 2017 19:18:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51819) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh271-0007Pl-Og for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh26y-0005tt-HR for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:03 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:38182) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26y-0005qA-BI; Sun, 13 Aug 2017 19:16:00 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 02F2B747EE2; Mon, 14 Aug 2017 01:15:51 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 5C2EF747EDC; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [RFC PATCH 04/12] ehci: Add ppc4xx-ehci for the USB 2.0 controller in embedded PPC SoCs 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: Francois Revol , Alexander Graf , David Gibson 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" Signed-off-by: BALATON Zoltan --- hw/usb/hcd-ehci-sysbus.c | 25 +++++++++++++++++++++++++ hw/usb/hcd-ehci.h | 1 + 2 files changed, 26 insertions(+) diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index 6c20604..3b83beb 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -142,6 +142,30 @@ static const TypeInfo ehci_tegra2_type_info =3D { .class_init =3D ehci_tegra2_class_init, }; =20 +static void ehci_ppc4xx_init(Object *o) +{ + EHCISysBusState *s =3D SYS_BUS_EHCI(o); + + s->ehci.companion_enable =3D true; +} + +static void ehci_ppc4xx_class_init(ObjectClass *oc, void *data) +{ + SysBusEHCIClass *sec =3D SYS_BUS_EHCI_CLASS(oc); + DeviceClass *dc =3D DEVICE_CLASS(oc); + + sec->capsbase =3D 0x0; + sec->opregbase =3D 0x10; + set_bit(DEVICE_CATEGORY_USB, dc->categories); +} + +static const TypeInfo ehci_ppc4xx_type_info =3D { + .name =3D TYPE_PPC4xx_EHCI, + .parent =3D TYPE_SYS_BUS_EHCI, + .class_init =3D ehci_ppc4xx_class_init, + .instance_init =3D ehci_ppc4xx_init, +}; + /* * Faraday FUSBH200 USB 2.0 EHCI */ @@ -224,6 +248,7 @@ static void ehci_sysbus_register_types(void) type_register_static(&ehci_xlnx_type_info); type_register_static(&ehci_exynos4210_type_info); type_register_static(&ehci_tegra2_type_info); + type_register_static(&ehci_ppc4xx_type_info); type_register_static(&ehci_fusbh200_type_info); } =20 diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 821f1de..0bc364b 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -344,6 +344,7 @@ typedef struct EHCIPCIState { #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb" #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb" #define TYPE_TEGRA2_EHCI "tegra2-ehci-usb" +#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb" #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb" =20 #define SYS_BUS_EHCI(obj) \ --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666485166489.5836062039764; Sun, 13 Aug 2017 16:21:25 -0700 (PDT) Received: from localhost ([::1]:46156 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2CC-0003Bh-3S for importer@patchew.org; Sun, 13 Aug 2017 19:21:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51818) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh271-0007Pk-OM for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh26y-0005uP-Q0 for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:03 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:38184) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26y-0005qK-BY; Sun, 13 Aug 2017 19:16:00 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 4364B747EE5; Mon, 14 Aug 2017 01:15:51 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 5EE08747ED7; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [RFC PATCH 05/12] ppc4xx: Split off 4xx I2C emulation from ppc405_uc to its own file 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: Francois Revol , Alexander Graf , David Gibson 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" Signed-off-by: BALATON Zoltan --- hw/ppc/Makefile.objs | 2 +- hw/ppc/ppc405.h | 2 + hw/ppc/ppc405_uc.c | 241 --------------------------------------------- hw/ppc/ppc4xx_i2c.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 275 insertions(+), 242 deletions(-) create mode 100644 hw/ppc/ppc4xx_i2c.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 7efc686..2077216 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -13,7 +13,7 @@ endif obj-$(CONFIG_PSERIES) +=3D spapr_rtas_ddw.o # PowerPC 4xx boards obj-y +=3D ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o -obj-y +=3D ppc4xx_pci.o +obj-y +=3D ppc4xx_pci.o ppc4xx_i2c.o # PReP obj-$(CONFIG_PREP) +=3D prep.o obj-$(CONFIG_PREP) +=3D prep_systemio.o diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index a9ffc87..61ec739 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -59,6 +59,8 @@ struct ppc4xx_bd_info_t { ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, uint32_t flags); =20 +void ppc405_i2c_init(hwaddr base, qemu_irq irq); + CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[4], hwaddr ram_bases[4], diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 03856d5..3925e4c 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -40,7 +40,6 @@ //#define DEBUG_GPIO //#define DEBUG_SERIAL //#define DEBUG_OCM -//#define DEBUG_I2C //#define DEBUG_GPT //#define DEBUG_CLOCKS //#define DEBUG_CLOCKS_LL @@ -993,246 +992,6 @@ static void ppc405_ocm_init(CPUPPCState *env) } =20 /*************************************************************************= ****/ -/* I2C controller */ -typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; -struct ppc4xx_i2c_t { - qemu_irq irq; - MemoryRegion iomem; - uint8_t mdata; - uint8_t lmadr; - uint8_t hmadr; - uint8_t cntl; - uint8_t mdcntl; - uint8_t sts; - uint8_t extsts; - uint8_t sdata; - uint8_t lsadr; - uint8_t hsadr; - uint8_t clkdiv; - uint8_t intrmsk; - uint8_t xfrcnt; - uint8_t xtcntlss; - uint8_t directcntl; -}; - -static uint32_t ppc4xx_i2c_readb (void *opaque, hwaddr addr) -{ - ppc4xx_i2c_t *i2c; - uint32_t ret; - -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); -#endif - i2c =3D opaque; - switch (addr) { - case 0x00: - // i2c_readbyte(&i2c->mdata); - ret =3D i2c->mdata; - break; - case 0x02: - ret =3D i2c->sdata; - break; - case 0x04: - ret =3D i2c->lmadr; - break; - case 0x05: - ret =3D i2c->hmadr; - break; - case 0x06: - ret =3D i2c->cntl; - break; - case 0x07: - ret =3D i2c->mdcntl; - break; - case 0x08: - ret =3D i2c->sts; - break; - case 0x09: - ret =3D i2c->extsts; - break; - case 0x0A: - ret =3D i2c->lsadr; - break; - case 0x0B: - ret =3D i2c->hsadr; - break; - case 0x0C: - ret =3D i2c->clkdiv; - break; - case 0x0D: - ret =3D i2c->intrmsk; - break; - case 0x0E: - ret =3D i2c->xfrcnt; - break; - case 0x0F: - ret =3D i2c->xtcntlss; - break; - case 0x10: - ret =3D i2c->directcntl; - break; - default: - ret =3D 0x00; - break; - } -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, = ret); -#endif - - return ret; -} - -static void ppc4xx_i2c_writeb (void *opaque, - hwaddr addr, uint32_t value) -{ - ppc4xx_i2c_t *i2c; - -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, - value); -#endif - i2c =3D opaque; - switch (addr) { - case 0x00: - i2c->mdata =3D value; - // i2c_sendbyte(&i2c->mdata); - break; - case 0x02: - i2c->sdata =3D value; - break; - case 0x04: - i2c->lmadr =3D value; - break; - case 0x05: - i2c->hmadr =3D value; - break; - case 0x06: - i2c->cntl =3D value; - break; - case 0x07: - i2c->mdcntl =3D value & 0xDF; - break; - case 0x08: - i2c->sts &=3D ~(value & 0x0A); - break; - case 0x09: - i2c->extsts &=3D ~(value & 0x8F); - break; - case 0x0A: - i2c->lsadr =3D value; - break; - case 0x0B: - i2c->hsadr =3D value; - break; - case 0x0C: - i2c->clkdiv =3D value; - break; - case 0x0D: - i2c->intrmsk =3D value; - break; - case 0x0E: - i2c->xfrcnt =3D value & 0x77; - break; - case 0x0F: - i2c->xtcntlss =3D value; - break; - case 0x10: - i2c->directcntl =3D value & 0x7; - break; - } -} - -static uint32_t ppc4xx_i2c_readw (void *opaque, hwaddr addr) -{ - uint32_t ret; - -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); -#endif - ret =3D ppc4xx_i2c_readb(opaque, addr) << 8; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 1); - - return ret; -} - -static void ppc4xx_i2c_writew (void *opaque, - hwaddr addr, uint32_t value) -{ -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, - value); -#endif - ppc4xx_i2c_writeb(opaque, addr, value >> 8); - ppc4xx_i2c_writeb(opaque, addr + 1, value); -} - -static uint32_t ppc4xx_i2c_readl (void *opaque, hwaddr addr) -{ - uint32_t ret; - -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); -#endif - ret =3D ppc4xx_i2c_readb(opaque, addr) << 24; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 1) << 16; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 2) << 8; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 3); - - return ret; -} - -static void ppc4xx_i2c_writel (void *opaque, - hwaddr addr, uint32_t value) -{ -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, - value); -#endif - ppc4xx_i2c_writeb(opaque, addr, value >> 24); - ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16); - ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8); - ppc4xx_i2c_writeb(opaque, addr + 3, value); -} - -static const MemoryRegionOps i2c_ops =3D { - .old_mmio =3D { - .read =3D { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, = }, - .write =3D { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writ= el, }, - }, - .endianness =3D DEVICE_NATIVE_ENDIAN, -}; - -static void ppc4xx_i2c_reset (void *opaque) -{ - ppc4xx_i2c_t *i2c; - - i2c =3D opaque; - i2c->mdata =3D 0x00; - i2c->sdata =3D 0x00; - i2c->cntl =3D 0x00; - i2c->mdcntl =3D 0x00; - i2c->sts =3D 0x00; - i2c->extsts =3D 0x00; - i2c->clkdiv =3D 0x00; - i2c->xfrcnt =3D 0x00; - i2c->directcntl =3D 0x0F; -} - -static void ppc405_i2c_init(hwaddr base, qemu_irq irq) -{ - ppc4xx_i2c_t *i2c; - - i2c =3D g_malloc0(sizeof(ppc4xx_i2c_t)); - i2c->irq =3D irq; -#ifdef DEBUG_I2C - printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); -#endif - memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011); - memory_region_add_subregion(get_system_memory(), base, &i2c->iomem); - qemu_register_reset(ppc4xx_i2c_reset, i2c); -} - -/*************************************************************************= ****/ /* General purpose timers */ typedef struct ppc4xx_gpt_t ppc4xx_gpt_t; struct ppc4xx_gpt_t { diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c new file mode 100644 index 0000000..15f2dea --- /dev/null +++ b/hw/ppc/ppc4xx_i2c.c @@ -0,0 +1,272 @@ +/* + * PPC4xx I2C controller emulation + * + * Copyright (c) 2007 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "cpu.h" +#include "hw/hw.h" +#include "exec/address-spaces.h" +#include "hw/ppc/ppc.h" +#include "ppc405.h" + +/*#define DEBUG_I2C*/ + +typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; +struct ppc4xx_i2c_t { + qemu_irq irq; + MemoryRegion iomem; + uint8_t mdata; + uint8_t lmadr; + uint8_t hmadr; + uint8_t cntl; + uint8_t mdcntl; + uint8_t sts; + uint8_t extsts; + uint8_t sdata; + uint8_t lsadr; + uint8_t hsadr; + uint8_t clkdiv; + uint8_t intrmsk; + uint8_t xfrcnt; + uint8_t xtcntlss; + uint8_t directcntl; +}; + +static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr) +{ + ppc4xx_i2c_t *i2c; + uint32_t ret; + +#ifdef DEBUG_I2C + printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); +#endif + i2c =3D opaque; + switch (addr) { + case 0x00: + /*i2c_readbyte(&i2c->mdata);*/ + ret =3D i2c->mdata; + break; + case 0x02: + ret =3D i2c->sdata; + break; + case 0x04: + ret =3D i2c->lmadr; + break; + case 0x05: + ret =3D i2c->hmadr; + break; + case 0x06: + ret =3D i2c->cntl; + break; + case 0x07: + ret =3D i2c->mdcntl; + break; + case 0x08: + ret =3D i2c->sts; + break; + case 0x09: + ret =3D i2c->extsts; + break; + case 0x0A: + ret =3D i2c->lsadr; + break; + case 0x0B: + ret =3D i2c->hsadr; + break; + case 0x0C: + ret =3D i2c->clkdiv; + break; + case 0x0D: + ret =3D i2c->intrmsk; + break; + case 0x0E: + ret =3D i2c->xfrcnt; + break; + case 0x0F: + ret =3D i2c->xtcntlss; + break; + case 0x10: + ret =3D i2c->directcntl; + break; + default: + ret =3D 0x00; + break; + } +#ifdef DEBUG_I2C + printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, = ret); +#endif + + return ret; +} + +static void ppc4xx_i2c_writeb(void *opaque, + hwaddr addr, uint32_t value) +{ + ppc4xx_i2c_t *i2c; + +#ifdef DEBUG_I2C + printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, + value); +#endif + i2c =3D opaque; + switch (addr) { + case 0x00: + i2c->mdata =3D value; + /*i2c_sendbyte(&i2c->mdata);*/ + break; + case 0x02: + i2c->sdata =3D value; + break; + case 0x04: + i2c->lmadr =3D value; + break; + case 0x05: + i2c->hmadr =3D value; + break; + case 0x06: + i2c->cntl =3D value; + break; + case 0x07: + i2c->mdcntl =3D value & 0xDF; + break; + case 0x08: + i2c->sts &=3D ~(value & 0x0A); + break; + case 0x09: + i2c->extsts &=3D ~(value & 0x8F); + break; + case 0x0A: + i2c->lsadr =3D value; + break; + case 0x0B: + i2c->hsadr =3D value; + break; + case 0x0C: + i2c->clkdiv =3D value; + break; + case 0x0D: + i2c->intrmsk =3D value; + break; + case 0x0E: + i2c->xfrcnt =3D value & 0x77; + break; + case 0x0F: + i2c->xtcntlss =3D value; + break; + case 0x10: + i2c->directcntl =3D value & 0x7; + break; + } +} + +static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr) +{ + uint32_t ret; + +#ifdef DEBUG_I2C + printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); +#endif + ret =3D ppc4xx_i2c_readb(opaque, addr) << 8; + ret |=3D ppc4xx_i2c_readb(opaque, addr + 1); + + return ret; +} + +static void ppc4xx_i2c_writew(void *opaque, + hwaddr addr, uint32_t value) +{ +#ifdef DEBUG_I2C + printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, + value); +#endif + ppc4xx_i2c_writeb(opaque, addr, value >> 8); + ppc4xx_i2c_writeb(opaque, addr + 1, value); +} + +static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr) +{ + uint32_t ret; + +#ifdef DEBUG_I2C + printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); +#endif + ret =3D ppc4xx_i2c_readb(opaque, addr) << 24; + ret |=3D ppc4xx_i2c_readb(opaque, addr + 1) << 16; + ret |=3D ppc4xx_i2c_readb(opaque, addr + 2) << 8; + ret |=3D ppc4xx_i2c_readb(opaque, addr + 3); + + return ret; +} + +static void ppc4xx_i2c_writel(void *opaque, + hwaddr addr, uint32_t value) +{ +#ifdef DEBUG_I2C + printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, + value); +#endif + ppc4xx_i2c_writeb(opaque, addr, value >> 24); + ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16); + ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8); + ppc4xx_i2c_writeb(opaque, addr + 3, value); +} + +static const MemoryRegionOps i2c_ops =3D { + .old_mmio =3D { + .read =3D { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, = }, + .write =3D { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writ= el, }, + }, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static void ppc4xx_i2c_reset(void *opaque) +{ + ppc4xx_i2c_t *i2c; + + i2c =3D opaque; + i2c->mdata =3D 0x00; + i2c->sdata =3D 0x00; + i2c->cntl =3D 0x00; + i2c->mdcntl =3D 0x00; + i2c->sts =3D 0x00; + i2c->extsts =3D 0x00; + i2c->clkdiv =3D 0x00; + i2c->xfrcnt =3D 0x00; + i2c->directcntl =3D 0x0F; +} + +void ppc405_i2c_init(hwaddr base, qemu_irq irq) +{ + ppc4xx_i2c_t *i2c; + + i2c =3D g_malloc0(sizeof(ppc4xx_i2c_t)); + i2c->irq =3D irq; +#ifdef DEBUG_I2C + printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); +#endif + memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011); + memory_region_add_subregion(get_system_memory(), base, &i2c->iomem); + qemu_register_reset(ppc4xx_i2c_reset, i2c); +} --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666482971825.3985391651921; Sun, 13 Aug 2017 16:21:22 -0700 (PDT) Received: from localhost ([::1]:46154 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2C9-00039B-R9 for importer@patchew.org; Sun, 13 Aug 2017 19:21:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51817) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh271-0007Pi-O0 for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh26y-0005u7-OC for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:03 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:38193) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26y-0005qP-BC; Sun, 13 Aug 2017 19:16:00 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 9230B747EE6; Mon, 14 Aug 2017 01:15:51 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 61DA9747EDB; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [RFC PATCH 06/12] ppc4xx_i2c: QOMify 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: Francois Revol , Alexander Graf , David Gibson 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" Signed-off-by: BALATON Zoltan --- hw/ppc/ppc405.h | 2 - hw/ppc/ppc405_uc.c | 5 +- hw/ppc/ppc4xx_i2c.c | 153 +++++++++++++++++-----------------------= ---- include/hw/i2c/ppc4xx_i2c.h | 59 +++++++++++++++++ 4 files changed, 121 insertions(+), 98 deletions(-) create mode 100644 include/hw/i2c/ppc4xx_i2c.h diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 61ec739..a9ffc87 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -59,8 +59,6 @@ struct ppc4xx_bd_info_t { ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, uint32_t flags); =20 -void ppc405_i2c_init(hwaddr base, qemu_irq irq); - CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[4], hwaddr ram_bases[4], diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 3925e4c..8f44cb4 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -28,6 +28,7 @@ #include "hw/hw.h" #include "hw/ppc/ppc.h" #include "hw/boards.h" +#include "hw/i2c/ppc4xx_i2c.h" #include "ppc405.h" #include "hw/char/serial.h" #include "qemu/timer.h" @@ -1663,7 +1664,7 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_spac= e_mem, DEVICE_BIG_ENDIAN); } /* IIC controller */ - ppc405_i2c_init(0xef600500, pic[2]); + sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]); /* GPIO */ ppc405_gpio_init(0xef600700); /* CPU control */ @@ -2010,7 +2011,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_spac= e_mem, dma_irqs[3] =3D pic[8]; ppc405_dma_init(env, dma_irqs); /* IIC controller */ - ppc405_i2c_init(0xef600500, pic[2]); + sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, pic[2]); /* GPIO */ ppc405_gpio_init(0xef600700); /* Serial ports */ diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c index 15f2dea..fafbb34 100644 --- a/hw/ppc/ppc4xx_i2c.c +++ b/hw/ppc/ppc4xx_i2c.c @@ -27,42 +27,19 @@ #include "qemu-common.h" #include "cpu.h" #include "hw/hw.h" -#include "exec/address-spaces.h" -#include "hw/ppc/ppc.h" -#include "ppc405.h" +#include "hw/i2c/ppc4xx_i2c.h" =20 /*#define DEBUG_I2C*/ =20 -typedef struct ppc4xx_i2c_t ppc4xx_i2c_t; -struct ppc4xx_i2c_t { - qemu_irq irq; - MemoryRegion iomem; - uint8_t mdata; - uint8_t lmadr; - uint8_t hmadr; - uint8_t cntl; - uint8_t mdcntl; - uint8_t sts; - uint8_t extsts; - uint8_t sdata; - uint8_t lsadr; - uint8_t hsadr; - uint8_t clkdiv; - uint8_t intrmsk; - uint8_t xfrcnt; - uint8_t xtcntlss; - uint8_t directcntl; -}; +#define PPC4xx_I2C_MEM_SIZE 0x11 =20 -static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr addr) +static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr) { - ppc4xx_i2c_t *i2c; - uint32_t ret; + uint8_t ret; =20 #ifdef DEBUG_I2C printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); #endif - i2c =3D opaque; switch (addr) { case 0x00: /*i2c_readbyte(&i2c->mdata);*/ @@ -121,16 +98,12 @@ static uint32_t ppc4xx_i2c_readb(void *opaque, hwaddr = addr) return ret; } =20 -static void ppc4xx_i2c_writeb(void *opaque, - hwaddr addr, uint32_t value) +static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t va= lue) { - ppc4xx_i2c_t *i2c; - #ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, - value); + printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", + __func__, addr, value); #endif - i2c =3D opaque; switch (addr) { case 0x00: i2c->mdata =3D value; @@ -181,71 +154,44 @@ static void ppc4xx_i2c_writeb(void *opaque, } } =20 -static uint32_t ppc4xx_i2c_readw(void *opaque, hwaddr addr) +static uint64_t ppc4xx_i2c_read(void *opaque, hwaddr addr, unsigned int si= ze) { - uint32_t ret; + PPC4xxI2CState *s =3D PPC4xx_I2C(opaque); + int i; + uint64_t ret =3D 0; =20 -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); -#endif - ret =3D ppc4xx_i2c_readb(opaque, addr) << 8; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 1); + for (i =3D 0; i < size; i++) { + ret <<=3D 8; + ret |=3D ppc4xx_i2c_readb(s, addr + i); + } =20 return ret; } =20 -static void ppc4xx_i2c_writew(void *opaque, - hwaddr addr, uint32_t value) +static void ppc4xx_i2c_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) { -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, - value); -#endif - ppc4xx_i2c_writeb(opaque, addr, value >> 8); - ppc4xx_i2c_writeb(opaque, addr + 1, value); -} - -static uint32_t ppc4xx_i2c_readl(void *opaque, hwaddr addr) -{ - uint32_t ret; - -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); -#endif - ret =3D ppc4xx_i2c_readb(opaque, addr) << 24; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 1) << 16; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 2) << 8; - ret |=3D ppc4xx_i2c_readb(opaque, addr + 3); - - return ret; -} + PPC4xxI2CState *s =3D PPC4xx_I2C(opaque); + int i; =20 -static void ppc4xx_i2c_writel(void *opaque, - hwaddr addr, uint32_t value) -{ -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, ad= dr, - value); -#endif - ppc4xx_i2c_writeb(opaque, addr, value >> 24); - ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16); - ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8); - ppc4xx_i2c_writeb(opaque, addr + 3, value); + for (i =3D 0; i < size; i++) { + ppc4xx_i2c_writeb(s, addr + i, value & 0xff); + value >>=3D 8; + } } =20 -static const MemoryRegionOps i2c_ops =3D { - .old_mmio =3D { - .read =3D { ppc4xx_i2c_readb, ppc4xx_i2c_readw, ppc4xx_i2c_readl, = }, - .write =3D { ppc4xx_i2c_writeb, ppc4xx_i2c_writew, ppc4xx_i2c_writ= el, }, - }, +static const MemoryRegionOps ppc4xx_i2c_ops =3D { + .read =3D ppc4xx_i2c_read, + .write =3D ppc4xx_i2c_write, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 4, .endianness =3D DEVICE_NATIVE_ENDIAN, }; =20 -static void ppc4xx_i2c_reset(void *opaque) +static void ppc4xx_i2c_reset(DeviceState *s) { - ppc4xx_i2c_t *i2c; + PPC4xxI2CState *i2c =3D PPC4xx_I2C(s); =20 - i2c =3D opaque; i2c->mdata =3D 0x00; i2c->sdata =3D 0x00; i2c->cntl =3D 0x00; @@ -257,16 +203,35 @@ static void ppc4xx_i2c_reset(void *opaque) i2c->directcntl =3D 0x0F; } =20 -void ppc405_i2c_init(hwaddr base, qemu_irq irq) +static void ppc4xx_i2c_init(Object *o) { - ppc4xx_i2c_t *i2c; + PPC4xxI2CState *s =3D PPC4xx_I2C(o); =20 - i2c =3D g_malloc0(sizeof(ppc4xx_i2c_t)); - i2c->irq =3D irq; -#ifdef DEBUG_I2C - printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); -#endif - memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011); - memory_region_add_subregion(get_system_memory(), base, &i2c->iomem); - qemu_register_reset(ppc4xx_i2c_reset, i2c); + memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s, + TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); + s->bus =3D i2c_init_bus(DEVICE(s), "i2c"); } + +static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D ppc4xx_i2c_reset; +} + +static const TypeInfo ppc4xx_i2c_type_info =3D { + .name =3D TYPE_PPC4xx_I2C, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(PPC4xxI2CState), + .instance_init =3D ppc4xx_i2c_init, + .class_init =3D ppc4xx_i2c_class_init, +}; + +static void ppc4xx_i2c_register_types(void) +{ + type_register_static(&ppc4xx_i2c_type_info); +} + +type_init(ppc4xx_i2c_register_types) diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h new file mode 100644 index 0000000..7f1e6be --- /dev/null +++ b/include/hw/i2c/ppc4xx_i2c.h @@ -0,0 +1,59 @@ +/* + * PPC4xx I2C controller emulation + * + * Copyright (c) 2007 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#ifndef PPC4XX_I2C_H +#define PPC4XX_I2C_H + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/sysbus.h" + +#define TYPE_PPC4xx_I2C "ppc4xx-i2c" +#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2= C) + +typedef struct PPC4xxI2CState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + qemu_irq irq; + MemoryRegion iomem; + uint8_t mdata; + uint8_t lmadr; + uint8_t hmadr; + uint8_t cntl; + uint8_t mdcntl; + uint8_t sts; + uint8_t extsts; + uint8_t sdata; + uint8_t lsadr; + uint8_t hsadr; + uint8_t clkdiv; + uint8_t intrmsk; + uint8_t xfrcnt; + uint8_t xtcntlss; + uint8_t directcntl; +} PPC4xxI2CState; + +#endif /* PPC4XX_I2C_H */ --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666486014801.3821552560656; Sun, 13 Aug 2017 16:21:26 -0700 (PDT) Received: from localhost ([::1]:46157 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2CC-0003CY-Va for importer@patchew.org; Sun, 13 Aug 2017 19:21:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51824) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh271-0007Pm-Qj for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh26y-0005uF-PY for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:03 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:38197) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26y-0005qU-BS; Sun, 13 Aug 2017 19:16:00 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id DE630747EDC; Mon, 14 Aug 2017 01:15:51 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 6509D747EDD; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan MIME-Version: 1.0 Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [RFC PATCH 07/12] ppc4xx_i2c: Implement basic I2C functions 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: Francois Revol , Alexander Graf , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Enough to please U-Boot and make it able to detect SDRAM SPD EEPROMs Signed-off-by: Fran=C3=A7ois Revol Signed-off-by: BALATON Zoltan Reviewed-by: David Gibson --- hw/ppc/ppc4xx_i2c.c | 214 +++++++++++++++++++++++++++++++++++++---= ---- include/hw/i2c/ppc4xx_i2c.h | 5 ++ 2 files changed, 189 insertions(+), 30 deletions(-) diff --git a/hw/ppc/ppc4xx_i2c.c b/hw/ppc/ppc4xx_i2c.c index fafbb34..0b088e6 100644 --- a/hw/ppc/ppc4xx_i2c.c +++ b/hw/ppc/ppc4xx_i2c.c @@ -2,6 +2,8 @@ * PPC4xx I2C controller emulation * * Copyright (c) 2007 Jocelyn Mayer + * Copyright (c) 2012 Fran=C3=A7ois Revol + * Copyright (c) 2016 BALATON Zoltan * * Permission is hereby granted, free of charge, to any person obtaining a= copy * of this software and associated documentation files (the "Software"), t= o deal @@ -25,25 +27,126 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/log.h" #include "cpu.h" #include "hw/hw.h" #include "hw/i2c/ppc4xx_i2c.h" =20 /*#define DEBUG_I2C*/ =20 -#define PPC4xx_I2C_MEM_SIZE 0x11 +#ifdef DEBUG_I2C +#define DPRINTF(fmt, args...) printf("[%s]%s: " fmt, TYPE_PPC4xx_I2C, \ + __func__, ##args); +#else +#define DPRINTF(fmt, args...) +#endif + +#define PPC4xx_I2C_MEM_SIZE 0x12 + +#define IIC_CNTL_PT (1 << 0) +#define IIC_CNTL_READ (1 << 1) +#define IIC_CNTL_CHT (1 << 2) +#define IIC_CNTL_RPST (1 << 3) + +#define IIC_STS_PT (1 << 0) +#define IIC_STS_ERR (1 << 2) +#define IIC_STS_MDBS (1 << 5) + +#define IIC_EXTSTS_XFRA (1 << 0) + +#define IIC_XTCNTLSS_SRST (1 << 0) + +static void ppc4xx_i2c_reset(DeviceState *s) +{ + PPC4xxI2CState *i2c =3D PPC4xx_I2C(s); + + /* FIXME: Should also reset bus? + *if (s->address !=3D ADDR_RESET) { + * i2c_end_transfer(s->bus); + *} + */ + + i2c->mdata =3D 0; + i2c->lmadr =3D 0; + i2c->hmadr =3D 0; + i2c->cntl =3D 0; + i2c->mdcntl =3D 0; + i2c->sts =3D 0; + i2c->extsts =3D 0x8f; + i2c->sdata =3D 0; + i2c->lsadr =3D 0; + i2c->hsadr =3D 0; + i2c->clkdiv =3D 0; + i2c->intrmsk =3D 0; + i2c->xfrcnt =3D 0; + i2c->xtcntlss =3D 0; + i2c->directcntl =3D 0x0f; + i2c->intr =3D 0; +} + +static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c) +{ + return true; +} =20 static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, hwaddr addr) { - uint8_t ret; + int ret; =20 -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr); -#endif switch (addr) { case 0x00: - /*i2c_readbyte(&i2c->mdata);*/ ret =3D i2c->mdata; + if (ppc4xx_i2c_is_master(i2c)) { + ret =3D 0xff; + + if (!(i2c->sts & IIC_STS_MDBS)) { + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read " + "without starting transfer\n", + TYPE_PPC4xx_I2C, __func__); + } else { + int pending =3D (i2c->cntl >> 4) & 3; + + /* get the next byte */ + ret =3D i2c_recv(i2c->bus); + DPRINTF("received byte %04x\n", ret); + + if (ret < 0) { + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed " + "for device 0x%02x\n", TYPE_PPC4xx_I2C, + __func__, i2c->lmadr); + ret =3D 0xff; + } else { + /* Raise interrupt if enabled */ + /*ppc4xx_i2c_raise_interrupt(i2c)*/; + } + + if (!pending) { + i2c->sts &=3D ~IIC_STS_MDBS; + /*i2c_end_transfer(i2c->bus);*/ + /*} else if (i2c->cntl & (IIC_CNTL_RPST | IIC_CNTL_CHT)) {= */ + } else if (pending) { + /* current smbus implementation doesn't like + multibyte xfer repeated start */ + i2c_end_transfer(i2c->bus); + if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) { + /* if non zero is returned, the adress is not vali= d */ + i2c->sts &=3D ~IIC_STS_PT; + i2c->sts |=3D IIC_STS_ERR; + i2c->extsts |=3D IIC_EXTSTS_XFRA; + } else { + /*i2c->sts |=3D IIC_STS_PT;*/ + i2c->sts |=3D IIC_STS_MDBS; + i2c->sts &=3D ~IIC_STS_ERR; + i2c->extsts =3D 0; + } + } + pending--; + i2c->cntl =3D (i2c->cntl & 0xcf) | (pending << 4); + } + } else { + qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n= ", + TYPE_PPC4xx_I2C, __func__); + } break; case 0x02: ret =3D i2c->sdata; @@ -87,39 +190,88 @@ static uint8_t ppc4xx_i2c_readb(PPC4xxI2CState *i2c, h= waddr addr) case 0x10: ret =3D i2c->directcntl; break; + case 0x11: + ret =3D i2c->intr; + break; default: - ret =3D 0x00; + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%" + HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr); + ret =3D 0; break; } -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__, addr, = ret); -#endif =20 return ret; } =20 static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwaddr addr, uint8_t va= lue) { -#ifdef DEBUG_I2C - printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", - __func__, addr, value); -#endif switch (addr) { case 0x00: i2c->mdata =3D value; - /*i2c_sendbyte(&i2c->mdata);*/ + if (!i2c_bus_busy(i2c->bus)) { + /* assume we start a write transfer */ + if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 0)) { + /* if non zero is returned, the adress is not valid */ + i2c->sts &=3D ~IIC_STS_PT; + i2c->sts |=3D IIC_STS_ERR; + i2c->extsts |=3D IIC_EXTSTS_XFRA; + } else { + i2c->sts |=3D IIC_STS_PT; + i2c->sts &=3D ~IIC_STS_ERR; + i2c->extsts =3D 0; + } + } + if (i2c_bus_busy(i2c->bus)) { + DPRINTF("sending byte %02x\n", i2c->mdata); + if (i2c_send(i2c->bus, i2c->mdata)) { + /* if the target return non zero then end the transfer */ + i2c->sts &=3D ~IIC_STS_PT; + i2c->sts |=3D IIC_STS_ERR; + i2c->extsts |=3D IIC_EXTSTS_XFRA; + i2c_end_transfer(i2c->bus); + } + } break; case 0x02: i2c->sdata =3D value; break; case 0x04: i2c->lmadr =3D value; + if (i2c_bus_busy(i2c->bus)) { + i2c_end_transfer(i2c->bus); + } + DPRINTF("%s: device addr %02x\n", __func__, i2c->lmadr); break; case 0x05: i2c->hmadr =3D value; break; case 0x06: i2c->cntl =3D value; + if (i2c->cntl & IIC_CNTL_PT) { + if (i2c->cntl & IIC_CNTL_READ) { + DPRINTF("read xfer %d\n", ((i2c->cntl >> 4) & 3) + 1); + if (i2c_bus_busy(i2c->bus)) { + /* end previous transfer */ + i2c->sts &=3D ~IIC_STS_PT; + i2c_end_transfer(i2c->bus); + } + if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, 1)) { + /* if non zero is returned, the adress is not valid */ + i2c->sts &=3D ~IIC_STS_PT; + i2c->sts |=3D IIC_STS_ERR; + i2c->extsts |=3D IIC_EXTSTS_XFRA; + } else { + /*i2c->sts |=3D IIC_STS_PT;*/ + i2c->sts |=3D IIC_STS_MDBS; + i2c->sts &=3D ~IIC_STS_ERR; + i2c->extsts =3D 0; + } + } else { + DPRINTF("write xfer %d\n", ((i2c->cntl >> 4) & 3) + 1); + /* we actually already did the write transfer... */ + i2c->sts &=3D ~IIC_STS_PT; + } + } break; case 0x07: i2c->mdcntl =3D value & 0xDF; @@ -132,6 +284,7 @@ static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hwad= dr addr, uint8_t value) break; case 0x0A: i2c->lsadr =3D value; + /*i2c_set_slave_address(i2c->bus, i2c->lsadr);*/ break; case 0x0B: i2c->hsadr =3D value; @@ -146,11 +299,23 @@ static void ppc4xx_i2c_writeb(PPC4xxI2CState *i2c, hw= addr addr, uint8_t value) i2c->xfrcnt =3D value & 0x77; break; case 0x0F: + if (value & IIC_XTCNTLSS_SRST) { + /* Is it actually a full reset? U-Boot sets some regs before */ + ppc4xx_i2c_reset(DEVICE(i2c)); + break; + } i2c->xtcntlss =3D value; break; case 0x10: i2c->directcntl =3D value & 0x7; break; + case 0x11: + i2c->intr =3D value; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%" + HWADDR_PRIx "\n", TYPE_PPC4xx_I2C, __func__, addr); + break; } } =20 @@ -160,10 +325,12 @@ static uint64_t ppc4xx_i2c_read(void *opaque, hwaddr = addr, unsigned int size) int i; uint64_t ret =3D 0; =20 + DPRINTF("read I2C " TARGET_FMT_plx " size %u\n", addr, size); for (i =3D 0; i < size; i++) { ret <<=3D 8; ret |=3D ppc4xx_i2c_readb(s, addr + i); } + DPRINTF("read I2C " TARGET_FMT_plx " %02" PRIx64 "\n", addr, ret); =20 return ret; } @@ -174,6 +341,8 @@ static void ppc4xx_i2c_write(void *opaque, hwaddr addr,= uint64_t value, PPC4xxI2CState *s =3D PPC4xx_I2C(opaque); int i; =20 + DPRINTF("write I2C " TARGET_FMT_plx " size %u val %08" PRIx64 "\n", + addr, size, value); for (i =3D 0; i < size; i++) { ppc4xx_i2c_writeb(s, addr + i, value & 0xff); value >>=3D 8; @@ -188,21 +357,6 @@ static const MemoryRegionOps ppc4xx_i2c_ops =3D { .endianness =3D DEVICE_NATIVE_ENDIAN, }; =20 -static void ppc4xx_i2c_reset(DeviceState *s) -{ - PPC4xxI2CState *i2c =3D PPC4xx_I2C(s); - - i2c->mdata =3D 0x00; - i2c->sdata =3D 0x00; - i2c->cntl =3D 0x00; - i2c->mdcntl =3D 0x00; - i2c->sts =3D 0x00; - i2c->extsts =3D 0x00; - i2c->clkdiv =3D 0x00; - i2c->xfrcnt =3D 0x00; - i2c->directcntl =3D 0x0F; -} - static void ppc4xx_i2c_init(Object *o) { PPC4xxI2CState *s =3D PPC4xx_I2C(o); diff --git a/include/hw/i2c/ppc4xx_i2c.h b/include/hw/i2c/ppc4xx_i2c.h index 7f1e6be..71fb392 100644 --- a/include/hw/i2c/ppc4xx_i2c.h +++ b/include/hw/i2c/ppc4xx_i2c.h @@ -2,6 +2,8 @@ * PPC4xx I2C controller emulation * * Copyright (c) 2007 Jocelyn Mayer + * Copyright (c) 2012 Fran=C3=A7ois Revol + * Copyright (c) 2016 BALATON Zoltan * * Permission is hereby granted, free of charge, to any person obtaining a= copy * of this software and associated documentation files (the "Software"), t= o deal @@ -28,6 +30,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "hw/sysbus.h" +#include "hw/i2c/i2c.h" =20 #define TYPE_PPC4xx_I2C "ppc4xx-i2c" #define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2= C) @@ -37,6 +40,7 @@ typedef struct PPC4xxI2CState { SysBusDevice parent_obj; =20 /*< public >*/ + I2CBus *bus; qemu_irq irq; MemoryRegion iomem; uint8_t mdata; @@ -54,6 +58,7 @@ typedef struct PPC4xxI2CState { uint8_t xfrcnt; uint8_t xtcntlss; uint8_t directcntl; + uint8_t intr; } PPC4xxI2CState; =20 #endif /* PPC4XX_I2C_H */ --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666840966334.161401131592; Sun, 13 Aug 2017 16:27:20 -0700 (PDT) Received: from localhost ([::1]:46395 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2Hv-00007D-MQ for importer@patchew.org; Sun, 13 Aug 2017 19:27:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51879) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh273-0007Rc-VS for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005wc-Md for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:05 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:38229) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005u2-MP; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 218D5747ED7; Mon, 14 Aug 2017 01:15:52 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 67A03747ED9; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: <9a1b25fc97fa35cd8c6294b1014931d832ef8240.1502643878.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 152.66.115.2 Subject: [Qemu-devel] [RFC PATCH 08/12] hw/ide: Emulate SiI3112 SATA 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: Francois Revol , Alexander Graf , David Gibson 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" Signed-off-by: BALATON Zoltan --- hw/ide/Makefile.objs | 1 + hw/ide/sii3112.c | 365 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 366 insertions(+) create mode 100644 hw/ide/sii3112.c diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs index 729e9bd..76f3d6d 100644 --- a/hw/ide/Makefile.objs +++ b/hw/ide/Makefile.objs @@ -10,3 +10,4 @@ common-obj-$(CONFIG_IDE_VIA) +=3D via.o common-obj-$(CONFIG_MICRODRIVE) +=3D microdrive.o common-obj-$(CONFIG_AHCI) +=3D ahci.o common-obj-$(CONFIG_AHCI) +=3D ich.o +common-obj-$(CONFIG_IDE_SII3112) +=3D sii3112.o diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c new file mode 100644 index 0000000..d3f34b5 --- /dev/null +++ b/hw/ide/sii3112.c @@ -0,0 +1,365 @@ +/* + * QEMU SiI3112A PCI to Serial ATA Controller Emulation + * + * Copyright (C) 2017 BALATON Zoltan + * + * 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 +#include + +#ifdef DEBUG_IDE +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__); +#else +#define DPRINTF(fmt, ...) +#endif /* DEBUG */ + +#define TYPE_SII3112_PCI "sii3112" +#define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \ + TYPE_SII3112_PCI) + +typedef struct SiI3112Regs { + uint32_t confstat; + uint32_t scontrol; + uint16_t sien; + uint8_t swdata; +} SiI3112Regs; + +typedef struct SiI3112PCIState { + PCIIDEState i; + MemoryRegion mmio; + SiI3112Regs regs[2]; +} SiI3112PCIState; + +static uint64_t sii3112_reg_read(void *opaque, hwaddr addr, + unsigned int size) +{ + SiI3112PCIState *d =3D opaque; + uint64_t val =3D 0; + + switch (addr) { + case 0x00: + val =3D d->i.bmdma[0].cmd; + break; + case 0x01: + val =3D d->regs[0].swdata; + break; + case 0x02: + val =3D d->i.bmdma[0].status; + break; + case 0x03: + val =3D 0; + break; + case 0x04 ... 0x07: + val =3D bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size); + break; + case 0x08: + val =3D d->i.bmdma[1].cmd; + break; + case 0x09: + val =3D d->regs[1].swdata; + break; + case 0x0a: + val =3D d->i.bmdma[1].status; + break; + case 0x0b: + val =3D 0; + break; + case 0x0c ... 0x0f: + val =3D bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size= ); + break; + case 0x10: + val =3D d->i.bmdma[0].cmd; + val |=3D (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SAT= AINT0*/ + val |=3D (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SAT= AINT1*/ + val |=3D (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0); + val |=3D d->i.bmdma[0].status << 16; + val |=3D d->i.bmdma[1].status << 24; + break; + case 0x18: + val =3D d->i.bmdma[1].cmd; + val |=3D (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0); + val |=3D d->i.bmdma[1].status << 16; + break; + case 0x80 ... 0x87: + if (size =3D=3D 1) { + val =3D ide_ioport_read(&d->i.bus[0], addr - 0x80); + } else if (addr =3D=3D 0x80) { + val =3D (size =3D=3D 2) ? ide_data_readw(&d->i.bus[0], 0) : + ide_data_readl(&d->i.bus[0], 0); + } else { + val =3D (1ULL << (size * 8)) - 1; + } + break; + case 0x8a: + val =3D (size =3D=3D 1) ? ide_status_read(&d->i.bus[0], 4) : + (1ULL << (size * 8)) - 1; + break; + case 0xa0: + val =3D d->regs[0].confstat; + break; + case 0xc0 ... 0xc7: + if (size =3D=3D 1) { + val =3D ide_ioport_read(&d->i.bus[1], addr - 0xc0); + } else if (addr =3D=3D 0xc0) { + val =3D (size =3D=3D 2) ? ide_data_readw(&d->i.bus[1], 0) : + ide_data_readl(&d->i.bus[1], 0); + } else { + val =3D (1ULL << (size * 8)) - 1; + } + break; + case 0xca: + val =3D (size =3D=3D 1) ? ide_status_read(&d->i.bus[0], 4) : + (1ULL << (size * 8)) - 1; + break; + case 0xe0: + val =3D d->regs[1].confstat; + break; + case 0x100: + val =3D d->regs[0].scontrol; + break; + case 0x104: + val =3D (d->i.bus[0].ifs[0].blk) ? 0x113 : 0; + break; + case 0x148: + val =3D d->regs[0].sien << 16; + break; + case 0x180: + val =3D d->regs[1].scontrol; + break; + case 0x184: + val =3D (d->i.bus[1].ifs[0].blk) ? 0x113 : 0; + break; + case 0x1c8: + val =3D d->regs[1].sien << 16; + break; + default: + val =3D 0; + } + DPRINTF("%s: addr 0x%"PRIx64 " size %d =3D %"PRIx64 "\n", + __func__, addr, size, val); + return val; +} + +static void sii3112_reg_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int size) +{ + SiI3112PCIState *d =3D opaque; + + DPRINTF("%s: addr 0x%"PRIx64 " size %d =3D %"PRIx64 "\n", + __func__, addr, size, val); + switch (addr) { + case 0x00: + case 0x10: + bmdma_cmd_writeb(&d->i.bmdma[0], val); + break; + case 0x01: + case 0x11: + d->regs[0].swdata =3D val & 0x3f; + break; + case 0x02: + case 0x12: + d->i.bmdma[0].status =3D (val & 0x60) | (d->i.bmdma[0].status & 1)= | + (d->i.bmdma[0].status & ~val & 6); + break; + case 0x04 ... 0x07: + bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size); + break; + case 0x08: + case 0x18: + bmdma_cmd_writeb(&d->i.bmdma[1], val); + break; + case 0x09: + case 0x19: + d->regs[1].swdata =3D val & 0x3f; + break; + case 0x0a: + case 0x1a: + d->i.bmdma[1].status =3D (val & 0x60) | (d->i.bmdma[1].status & 1)= | + (d->i.bmdma[1].status & ~val & 6); + break; + case 0x0c ... 0x0f: + bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size); + break; + case 0x80 ... 0x87: + if (size =3D=3D 1) { + ide_ioport_write(&d->i.bus[0], addr - 0x80, val); + } else if (addr =3D=3D 0x80) { + if (size =3D=3D 2) { + ide_data_writew(&d->i.bus[0], 0, val); + } else { + ide_data_writel(&d->i.bus[0], 0, val); + } + } + break; + case 0x8a: + if (size =3D=3D 1) { + ide_cmd_write(&d->i.bus[0], 4, val); + } + break; + case 0xc0 ... 0xc7: + if (size =3D=3D 1) { + ide_ioport_write(&d->i.bus[1], addr - 0xc0, val); + } else if (addr =3D=3D 0xc0) { + if (size =3D=3D 2) { + ide_data_writew(&d->i.bus[1], 0, val); + } else { + ide_data_writel(&d->i.bus[1], 0, val); + } + } + break; + case 0xca: + if (size =3D=3D 1) { + ide_cmd_write(&d->i.bus[1], 4, val); + } + break; + case 0x100: + d->regs[0].scontrol =3D val & 0xfff; + if (val & 1) { + ide_bus_reset(&d->i.bus[0]); + } + break; + case 0x148: + d->regs[0].sien =3D (val >> 16) & 0x3eed; + break; + case 0x180: + d->regs[1].scontrol =3D val & 0xfff; + if (val & 1) { + ide_bus_reset(&d->i.bus[1]); + } + break; + case 0x1c8: + d->regs[1].sien =3D (val >> 16) & 0x3eed; + break; + default: + val =3D 0; + } +} + +static const MemoryRegionOps sii3112_reg_ops =3D { + .read =3D sii3112_reg_read, + .write =3D sii3112_reg_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +/* the PCI irq level is the logical OR of the two channels */ +static void sii3112_update_irq(SiI3112PCIState *s) +{ + int i, set =3D 0; + + for (i =3D 0; i < 2; i++) { + set |=3D s->regs[i].confstat & (1UL << 11); + } + pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0)); +} + +static void sii3112_set_irq(void *opaque, int channel, int level) +{ + SiI3112PCIState *s =3D opaque; + + DPRINTF("%s: channel %d level %d\n", __func__, channel, level); + if (level) { + s->regs[channel].confstat |=3D (1UL << 11); + } else { + s->regs[channel].confstat &=3D ~(1UL << 11); + } + + sii3112_update_irq(s); +} + +static void sii3112_reset(void *opaque) +{ + SiI3112PCIState *s =3D opaque; + int i; + + for (i =3D 0; i < 2; i++) { + s->regs[i].confstat =3D 0x6515 << 16; + ide_bus_reset(&s->i.bus[i]); + } +} + +static void sii3112_pci_realize(PCIDevice *dev, Error **errp) +{ + SiI3112PCIState *d =3D SII3112_PCI(dev); + PCIIDEState *s =3D PCI_IDE(dev); + MemoryRegion *mr; + qemu_irq *irq; + int i; + + pci_config_set_interrupt_pin(dev->config, 1); + pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8); + + memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d, + "sii3112.bar5", 0x200); + pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); + + mr =3D g_new(MemoryRegion, 1); + memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80= , 8); + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr); + mr =3D g_new(MemoryRegion, 1); + memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88= , 4); + pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr); + mr =3D g_new(MemoryRegion, 1); + memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0= , 8); + pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr); + mr =3D g_new(MemoryRegion, 1); + memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8= , 4); + pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr); + mr =3D g_new(MemoryRegion, 1); + memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 1= 6); + pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr); + + irq =3D qemu_allocate_irqs(sii3112_set_irq, d, 2); + for (i =3D 0; i < 2; i++) { + ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1); + ide_init2(&s->bus[i], irq[i]); + + bmdma_init(&s->bus[i], &s->bmdma[i], s); + s->bmdma[i].bus =3D &s->bus[i]; + ide_register_restart_cb(&s->bus[i]); + } + qemu_register_reset(sii3112_reset, s); +} + +static void sii3112_pci_exitfn(PCIDevice *dev) +{ + PCIIDEState *d =3D PCI_IDE(dev); + int i; + + for (i =3D 0; i < 2; ++i) { + memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io); + memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_iopor= t); + } +} + +static void sii3112_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *pd =3D PCI_DEVICE_CLASS(klass); + + pd->vendor_id =3D 0x1095; + pd->device_id =3D 0x3112; + pd->class_id =3D PCI_CLASS_STORAGE_RAID; + pd->revision =3D 1; + pd->realize =3D sii3112_pci_realize; + pd->exit =3D sii3112_pci_exitfn; + dc->desc =3D "SiI3112A SATA controller"; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +} + +static const TypeInfo sii3112_pci_info =3D { + .name =3D TYPE_SII3112_PCI, + .parent =3D TYPE_PCI_IDE, + .instance_size =3D sizeof(SiI3112PCIState), + .class_init =3D sii3112_pci_class_init, +}; + +static void sii3112_register_types(void) +{ + type_register_static(&sii3112_pci_info); +} + +type_init(sii3112_register_types) --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 1502666701234443.48111638277487; Sun, 13 Aug 2017 16:25:01 -0700 (PDT) Received: from localhost ([::1]:46266 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2Fg-0006Hx-32 for importer@patchew.org; Sun, 13 Aug 2017 19:25:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51909) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh274-0007Ro-Hs for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005wo-NW for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:06 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:38230) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005u3-NW; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 5DB19747EDB; Mon, 14 Aug 2017 01:15:52 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 6A56F747EDE; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: <0362ffdbfb08b46edef0e2180387078299a9b721.1502643878.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 152.66.115.2 Subject: [Qemu-devel] [RFC PATCH 09/12] ppc440: Add emulation of plb-pcix controller found in some 440 SoCs 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: Francois Revol , Alexander Graf , David Gibson 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" Signed-off-by: BALATON Zoltan --- hw/ppc/Makefile.objs | 2 +- hw/ppc/ppc440_pcix.c | 506 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 507 insertions(+), 1 deletion(-) create mode 100644 hw/ppc/ppc440_pcix.c diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 2077216..9c5d58a 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -13,7 +13,7 @@ endif obj-$(CONFIG_PSERIES) +=3D spapr_rtas_ddw.o # PowerPC 4xx boards obj-y +=3D ppc405_boards.o ppc4xx_devs.o ppc405_uc.o ppc440_bamboo.o -obj-y +=3D ppc4xx_pci.o ppc4xx_i2c.o +obj-y +=3D ppc4xx_pci.o ppc440_pcix.o ppc4xx_i2c.o # PReP obj-$(CONFIG_PREP) +=3D prep.o obj-$(CONFIG_PREP) +=3D prep_systemio.o diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c new file mode 100644 index 0000000..3abd0d0 --- /dev/null +++ b/hw/ppc/ppc440_pcix.c @@ -0,0 +1,506 @@ +/* + * Emulation of the ibm,plb-pcix PCI controller + * This is found in some 440 SoCs e.g. the 460EX. + * + * Copyright (c) 2016 BALATON Zoltan + * + * Derived from ppc4xx_pci.c and pci-host/ppce500.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/ppc/ppc.h" +#include "hw/ppc/ppc4xx.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "exec/address-spaces.h" + +/*#define DEBUG_PCI*/ + +#ifdef DEBUG_PCI +#define DPRINTF(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__); +#else +#define DPRINTF(fmt, ...) +#endif /* DEBUG */ + +struct PLBOutMap { + uint64_t la; + uint64_t pcia; + uint32_t sa; + MemoryRegion mr; +}; + +struct PLBInMap { + uint64_t sa; + uint64_t la; + MemoryRegion mr; +}; + +#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" +#define PPC440_PCIX_HOST_BRIDGE(obj) \ + OBJECT_CHECK(PPC440PCIXState, (obj), TYPE_PPC440_PCIX_HOST_BRIDGE) + +#define PPC440_PCIX_NR_POMS 3 +#define PPC440_PCIX_NR_PIMS 3 + +typedef struct PPC440PCIXState { + PCIHostState parent_obj; + + PCIDevice *dev; + struct PLBOutMap pom[PPC440_PCIX_NR_POMS]; + struct PLBInMap pim[PPC440_PCIX_NR_PIMS]; + uint32_t sts; + qemu_irq irq[PCI_NUM_PINS]; + AddressSpace bm_as; + MemoryRegion bm; + + MemoryRegion container; + MemoryRegion iomem; + MemoryRegion busmem; +} PPC440PCIXState; + +#define PPC440_REG_BASE 0x80000 +#define PPC440_REG_SIZE 0xff + +#define PCIC0_CFGADDR 0x0 +#define PCIC0_CFGDATA 0x4 + +#define PCIX0_POM0LAL 0x68 +#define PCIX0_POM0LAH 0x6c +#define PCIX0_POM0SA 0x70 +#define PCIX0_POM0PCIAL 0x74 +#define PCIX0_POM0PCIAH 0x78 +#define PCIX0_POM1LAL 0x7c +#define PCIX0_POM1LAH 0x80 +#define PCIX0_POM1SA 0x84 +#define PCIX0_POM1PCIAL 0x88 +#define PCIX0_POM1PCIAH 0x8c +#define PCIX0_POM2SA 0x90 + +#define PCIX0_PIM0SAL 0x98 +#define PCIX0_PIM0LAL 0x9c +#define PCIX0_PIM0LAH 0xa0 +#define PCIX0_PIM1SA 0xa4 +#define PCIX0_PIM1LAL 0xa8 +#define PCIX0_PIM1LAH 0xac +#define PCIX0_PIM2SAL 0xb0 +#define PCIX0_PIM2LAL 0xb4 +#define PCIX0_PIM2LAH 0xb8 +#define PCIX0_PIM0SAH 0xf8 +#define PCIX0_PIM2SAH 0xfc + +#define PCIX0_STS 0xe0 + +#define PCI_ALL_SIZE (PPC440_REG_BASE + PPC440_REG_SIZE) + +/* DMA mapping */ +static void ppc440_pcix_update_pim(PPC440PCIXState *s, int idx) +{ + MemoryRegion *mem =3D &s->pim[idx].mr; + char *name; + uint64_t size; + + if (memory_region_is_mapped(mem)) { + /* Before we modify anything, unmap and destroy the region */ + memory_region_del_subregion(&s->bm, mem); + object_unparent(OBJECT(mem)); + } + + if (!(s->pim[idx].sa & 1)) { + /* Not enabled, nothing to do */ + return; + } + + name =3D g_strdup_printf("PCI Inbound Window %d", idx); + size =3D ~(s->pim[idx].sa & ~7ULL) + 1; + memory_region_init_alias(mem, OBJECT(s), name, get_system_memory(), + s->pim[idx].la, size); + memory_region_add_subregion_overlap(&s->bm, 0, mem, -1); + g_free(name); + + DPRINTF("%s: Added window %d of size=3D%#"PRIx64" to CPU=3D%#"PRIx64"\= n", + __func__, idx, size, s->pim[idx].la); +} + +/* BAR mapping */ +static void ppc440_pcix_update_pom(PPC440PCIXState *s, int idx) +{ + MemoryRegion *mem =3D &s->pom[idx].mr; + MemoryRegion *address_space_mem =3D get_system_memory(); + char *name; + uint32_t size; + + if (memory_region_is_mapped(mem)) { + /* Before we modify anything, unmap and destroy the region */ + memory_region_del_subregion(address_space_mem, mem); + object_unparent(OBJECT(mem)); + } + + if (!(s->pom[idx].sa & 1)) { + /* Not enabled, nothing to do */ + return; + } + + name =3D g_strdup_printf("PCI Outbound Window %d", idx); + size =3D ~(s->pom[idx].sa & 0xfffffffe) + 1; + if (!size) { + size =3D 0xffffffff; + } + memory_region_init_alias(mem, OBJECT(s), name, &s->busmem, + s->pom[idx].pcia, size); + memory_region_add_subregion(address_space_mem, s->pom[idx].la, mem); + g_free(name); + + DPRINTF("%s: Added window %d of size=3D%#x from CPU=3D%#"PRIx64 + " to PCI=3D%#"PRIx64"\n", __func__, idx, size, s->pom[idx].la, + s->pom[idx].pcia); +} + +static void ppc440_pcix_reg_write4(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + struct PPC440PCIXState *s =3D opaque; + + DPRINTF("%s: addr 0x%"PRIx64 " =3D %"PRIx64 "\n", __func__, addr, val); + switch (addr) { + case PCI_VENDOR_ID ... PCI_MAX_LAT: + stl_le_p(s->dev->config + addr, val); + break; + + case PCIX0_POM0LAL: + s->pom[0].la &=3D 0xffffffff00000000ULL; + s->pom[0].la |=3D val; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0LAH: + s->pom[0].la &=3D 0xffffffffULL; + s->pom[0].la |=3D val << 32; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0SA: + s->pom[0].sa =3D val; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0PCIAL: + s->pom[0].pcia &=3D 0xffffffff00000000ULL; + s->pom[0].pcia |=3D val; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM0PCIAH: + s->pom[0].pcia &=3D 0xffffffffULL; + s->pom[0].pcia |=3D val << 32; + ppc440_pcix_update_pom(s, 0); + break; + case PCIX0_POM1LAL: + s->pom[1].la &=3D 0xffffffff00000000ULL; + s->pom[1].la |=3D val; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1LAH: + s->pom[1].la &=3D 0xffffffffULL; + s->pom[1].la |=3D val << 32; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1SA: + s->pom[1].sa =3D val; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1PCIAL: + s->pom[1].pcia &=3D 0xffffffff00000000ULL; + s->pom[1].pcia |=3D val; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM1PCIAH: + s->pom[1].pcia &=3D 0xffffffffULL; + s->pom[1].pcia |=3D val << 32; + ppc440_pcix_update_pom(s, 1); + break; + case PCIX0_POM2SA: + s->pom[2].sa =3D val; + break; + + case PCIX0_PIM0SAL: + s->pim[0].sa &=3D 0xffffffff00000000ULL; + s->pim[0].sa |=3D val; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM0LAL: + s->pim[0].la &=3D 0xffffffff00000000ULL; + s->pim[0].la |=3D val; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM0LAH: + s->pim[0].la &=3D 0xffffffffULL; + s->pim[0].la |=3D val << 32; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM1SA: + s->pim[1].sa =3D val; + ppc440_pcix_update_pim(s, 1); + break; + case PCIX0_PIM1LAL: + s->pim[1].la &=3D 0xffffffff00000000ULL; + s->pim[1].la |=3D val; + ppc440_pcix_update_pim(s, 1); + break; + case PCIX0_PIM1LAH: + s->pim[1].la &=3D 0xffffffffULL; + s->pim[1].la |=3D val << 32; + ppc440_pcix_update_pim(s, 1); + break; + case PCIX0_PIM2SAL: + s->pim[2].sa &=3D 0xffffffff00000000ULL; + s->pim[2].sa =3D val; + ppc440_pcix_update_pim(s, 2); + break; + case PCIX0_PIM2LAL: + s->pim[2].la &=3D 0xffffffff00000000ULL; + s->pim[2].la |=3D val; + ppc440_pcix_update_pim(s, 2); + break; + case PCIX0_PIM2LAH: + s->pim[2].la &=3D 0xffffffffULL; + s->pim[2].la |=3D val << 32; + ppc440_pcix_update_pim(s, 2); + break; + + case PCIX0_STS: + s->sts =3D val; + break; + + case PCIX0_PIM0SAH: + s->pim[0].sa &=3D 0xffffffffULL; + s->pim[0].sa |=3D val << 32; + ppc440_pcix_update_pim(s, 0); + break; + case PCIX0_PIM2SAH: + s->pim[2].sa &=3D 0xffffffffULL; + s->pim[2].sa |=3D val << 32; + ppc440_pcix_update_pim(s, 2); + break; + + default: + printf("%s: unhandled PCI internal register 0x%lx\n", __func__, + (unsigned long)addr); + break; + } +} + +static uint64_t ppc440_pcix_reg_read4(void *opaque, hwaddr addr, + unsigned size) +{ + struct PPC440PCIXState *s =3D opaque; + uint32_t val; + + switch (addr) { + case PCI_VENDOR_ID ... PCI_MAX_LAT: + val =3D ldl_le_p(s->dev->config + addr); + break; + + case PCIX0_POM0LAL: + val =3D s->pom[0].la; + break; + case PCIX0_POM0LAH: + val =3D s->pom[0].la >> 32; + break; + case PCIX0_POM0SA: + val =3D s->pom[0].sa; + break; + case PCIX0_POM0PCIAL: + val =3D s->pom[0].pcia; + break; + case PCIX0_POM0PCIAH: + val =3D s->pom[0].pcia >> 32; + break; + case PCIX0_POM1LAL: + val =3D s->pom[1].la; + break; + case PCIX0_POM1LAH: + val =3D s->pom[1].la >> 32; + break; + case PCIX0_POM1SA: + val =3D s->pom[1].sa; + break; + case PCIX0_POM1PCIAL: + val =3D s->pom[1].pcia; + break; + case PCIX0_POM1PCIAH: + val =3D s->pom[1].pcia >> 32; + break; + case PCIX0_POM2SA: + val =3D s->pom[2].sa; + break; + + case PCIX0_PIM0SAL: + val =3D s->pim[0].sa; + break; + case PCIX0_PIM0LAL: + val =3D s->pim[0].la; + break; + case PCIX0_PIM0LAH: + val =3D s->pim[0].la >> 32; + break; + case PCIX0_PIM1SA: + val =3D s->pim[1].sa; + break; + case PCIX0_PIM1LAL: + val =3D s->pim[1].la; + break; + case PCIX0_PIM1LAH: + val =3D s->pim[1].la >> 32; + break; + case PCIX0_PIM2SAL: + val =3D s->pim[2].sa; + break; + case PCIX0_PIM2LAL: + val =3D s->pim[2].la; + break; + case PCIX0_PIM2LAH: + val =3D s->pim[2].la >> 32; + break; + + case PCIX0_STS: + val =3D s->sts; + break; + + case PCIX0_PIM0SAH: + val =3D s->pim[0].sa >> 32; + break; + case PCIX0_PIM2SAH: + val =3D s->pim[2].sa >> 32; + break; + + default: + printf("%s: invalid PCI internal register 0x%lx\n", __func__, + (unsigned long)addr); + val =3D 0; + } + + DPRINTF("%s: addr 0x%"PRIx64 " =3D %"PRIx32 "\n", __func__, addr, val); + return val; +} + +static const MemoryRegionOps pci_reg_ops =3D { + .read =3D ppc440_pcix_reg_read4, + .write =3D ppc440_pcix_reg_write4, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static void ppc440_pcix_reset(DeviceState *dev) +{ + struct PPC440PCIXState *s =3D PPC440_PCIX_HOST_BRIDGE(dev); + int i; + + memset(s->pom, 0, sizeof(s->pom)); + memset(s->pim, 0, sizeof(s->pim)); + for (i =3D 0; i < PPC440_PCIX_NR_PIMS; i++) { + s->pim[i].sa =3D 0xffffffff00000000ULL; + } + s->sts =3D 0; +} + +/* All pins from each slot are tied to a single board IRQ. + * This may need further refactoring for other boards. */ +static int ppc440_pcix_map_irq(PCIDevice *pci_dev, int irq_num) +{ + int slot =3D pci_dev->devfn >> 3; + + DPRINTF("%s: devfn %x irq %d -> %d\n", __func__, + pci_dev->devfn, irq_num, slot); + + return slot - 1; +} + +static void ppc440_pcix_set_irq(void *opaque, int irq_num, int level) +{ + qemu_irq *pci_irqs =3D opaque; + + DPRINTF("%s: PCI irq %d\n", __func__, irq_num); + if (irq_num < 0) { + fprintf(stderr, "%s: PCI irq %d\n", __func__, irq_num); + return; + } + qemu_set_irq(pci_irqs[irq_num], level); +} + +static AddressSpace *ppc440_pcix_set_iommu(PCIBus *b, void *opaque, int de= vfn) +{ + PPC440PCIXState *s =3D opaque; + + return &s->bm_as; +} + +static int ppc440_pcix_initfn(SysBusDevice *dev) +{ + PPC440PCIXState *s; + PCIHostState *h; + int i; + + h =3D PCI_HOST_BRIDGE(dev); + s =3D PPC440_PCIX_HOST_BRIDGE(dev); + + for (i =3D 0; i < ARRAY_SIZE(s->irq); i++) { + sysbus_init_irq(dev, &s->irq[i]); + } + + memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_M= AX); + h->bus =3D pci_register_bus(DEVICE(dev), NULL, ppc440_pcix_set_irq, + ppc440_pcix_map_irq, s->irq, &s->busmem, + get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS= ); + + s->dev =3D pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bri= dge"); + + memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); + memory_region_add_subregion(&s->bm, 0x0, &s->busmem); + address_space_init(&s->bm_as, &s->bm, "pci-bm"); + pci_setup_iommu(h->bus, ppc440_pcix_set_iommu, s); + + memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_= SIZE); + memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, = h, + "pci-conf-idx", 4); + memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, = h, + "pci-conf-data", 4); + memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, + "pci.reg", PPC440_REG_SIZE); + memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem= ); + memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem= ); + memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); + sysbus_init_mmio(dev, &s->container); + + return 0; +} + +static void ppc440_pcix_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *k =3D SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc =3D DEVICE_CLASS(klass); + + k->init =3D ppc440_pcix_initfn; + dc->reset =3D ppc440_pcix_reset; +} + +static const TypeInfo ppc440_pcix_info =3D { + .name =3D TYPE_PPC440_PCIX_HOST_BRIDGE, + .parent =3D TYPE_PCI_HOST_BRIDGE, + .instance_size =3D sizeof(PPC440PCIXState), + .class_init =3D ppc440_pcix_class_init, +}; + +static void ppc440_pcix_register_types(void) +{ + type_register_static(&ppc440_pcix_info); +} + +type_init(ppc440_pcix_register_types) --=20 2.7.4 From nobody Sat Apr 27 15:23:40 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.zohomail.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 15026664844815.207561963902094; Sun, 13 Aug 2017 16:21:24 -0700 (PDT) Received: from localhost ([::1]:46155 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2CB-0003BA-C1 for importer@patchew.org; Sun, 13 Aug 2017 19:21:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51880) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh273-0007Rf-Vf for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:07 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005wL-Mk for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:05 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:38232) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005ud-N0; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 848D2747ED9; Mon, 14 Aug 2017 01:15:52 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 6D294747EDF; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: <49e4b95ddbb40575bfb4db2e7c43b0b0801ce399.1502643878.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x [fuzzy] X-Received-From: 152.66.115.2 Subject: [Qemu-devel] [RFC PATCH 10/12] ppc: Add 460EX embedded CPU 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: Francois Revol , Alexander Graf , David Gibson 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" Despite its name it is a 440 core CPU Signed-off-by: BALATON Zoltan Reviewed-by: David Gibson --- target/ppc/cpu-models.c | 3 +++ target/ppc/cpu-models.h | 1 + target/ppc/translate_init.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 4d3e635..7c368fc 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -348,6 +348,8 @@ "PowerPC 440 EPb") POWERPC_DEF("440EPX", CPU_POWERPC_440EPX, 440EP, "PowerPC 440 EPX") + POWERPC_DEF("460EXb", CPU_POWERPC_460EXb, 460EX, + "PowerPC 460 EXb") #if defined(TODO_USER_ONLY) POWERPC_DEF("440GPb", CPU_POWERPC_440GPb, 440GP, "PowerPC 440 GPb") @@ -1238,6 +1240,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] =3D { { "440GP", "440GPc" }, { "440GR", "440GRa" }, { "440GX", "440GXf" }, + { "460EX", "460EXb" }, =20 { "RCPU", "MPC5xx" }, /* MPC5xx microcontrollers */ diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h index b563c45..92f99c0 100644 --- a/target/ppc/cpu-models.h +++ b/target/ppc/cpu-models.h @@ -241,6 +241,7 @@ enum { CPU_POWERPC_440SP =3D 0x53221850, CPU_POWERPC_440SP2 =3D 0x53221891, CPU_POWERPC_440SPE =3D 0x53421890, + CPU_POWERPC_460EXb =3D 0x130218A4, /* called 460 but 440 c= ore */ /* PowerPC 460 family */ #if 0 /* Generic PowerPC 464 */ diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index 8fb407e..1e0d566 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -3832,6 +3832,44 @@ POWERPC_FAMILY(440EP)(ObjectClass *oc, void *data) POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK; } =20 +POWERPC_FAMILY(460EX)(ObjectClass *oc, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + PowerPCCPUClass *pcc =3D POWERPC_CPU_CLASS(oc); + + dc->desc =3D "PowerPC 460 EX"; + pcc->init_proc =3D init_proc_440EP; + pcc->check_pow =3D check_pow_nocheck; + pcc->insns_flags =3D PPC_INSNS_BASE | PPC_STRING | + PPC_FLOAT | PPC_FLOAT_FRES | PPC_FLOAT_FSEL | + PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | + PPC_FLOAT_STFIWX | + PPC_DCR | PPC_DCRX | PPC_WRTEE | PPC_RFMCI | + PPC_CACHE | PPC_CACHE_ICBI | + PPC_CACHE_DCBZ | PPC_CACHE_DCBA | + PPC_MEM_TLBSYNC | PPC_MFTB | + PPC_BOOKE | PPC_4xx_COMMON | PPC_405_MAC | + PPC_440_SPEC; + pcc->msr_mask =3D (1ull << MSR_POW) | + (1ull << MSR_CE) | + (1ull << MSR_EE) | + (1ull << MSR_PR) | + (1ull << MSR_FP) | + (1ull << MSR_ME) | + (1ull << MSR_FE0) | + (1ull << MSR_DWE) | + (1ull << MSR_DE) | + (1ull << MSR_FE1) | + (1ull << MSR_IR) | + (1ull << MSR_DR); + pcc->mmu_model =3D POWERPC_MMU_BOOKE; + pcc->excp_model =3D POWERPC_EXCP_BOOKE; + pcc->bus_model =3D PPC_FLAGS_INPUT_BookE; + pcc->bfd_mach =3D bfd_mach_ppc_403; + pcc->flags =3D POWERPC_FLAG_CE | POWERPC_FLAG_DWE | + POWERPC_FLAG_DE | POWERPC_FLAG_BUS_CLK; +} + static void init_proc_440GP(CPUPPCState *env) { /* Time base */ --=20 2.7.4 From nobody Sat Apr 27 15:23:41 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.zohomail.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 1502666299822996.1983583147438; Sun, 13 Aug 2017 16:18:19 -0700 (PDT) Received: from localhost ([::1]:46141 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh29A-0000S5-29 for importer@patchew.org; Sun, 13 Aug 2017 19:18:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51828) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh272-0007Po-47 for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005w3-IR for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:04 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:38233) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005ub-Nt; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id AD000747EDD; Mon, 14 Aug 2017 01:15:52 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 87A54747EE0; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: <675e091387248b49c97ff99ef07eb23ed316aefb.1502643878.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [RFC PATCH 11/12] ppc4xx: Export ECB and PLB emulation 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: Francois Revol , Alexander Graf , David Gibson 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" These devices are found in some other ppc4xx cores too. Also add some more PLB registers for 460EX. Signed-off-by: BALATON Zoltan --- hw/ppc/ppc405.h | 3 +++ hw/ppc/ppc405_uc.c | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index a9ffc87..7ed25cf 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -59,6 +59,9 @@ struct ppc4xx_bd_info_t { ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, uint32_t flags); =20 +void ppc4xx_plb_init(CPUPPCState *env); +void ppc405_ebc_init(CPUPPCState *env); + CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem, MemoryRegion ram_memories[4], hwaddr ram_bases[4], diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 8f44cb4..8e58065 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -105,9 +105,12 @@ ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4= xx_bd_info_t *bd, /*************************************************************************= ****/ /* Peripheral local bus arbitrer */ enum { - PLB0_BESR =3D 0x084, - PLB0_BEAR =3D 0x086, - PLB0_ACR =3D 0x087, + PLB3A0_ACR =3D 0x077, + PLB4A0_ACR =3D 0x081, + PLB0_BESR =3D 0x084, + PLB0_BEAR =3D 0x086, + PLB0_ACR =3D 0x087, + PLB4A1_ACR =3D 0x089, }; =20 typedef struct ppc4xx_plb_t ppc4xx_plb_t; @@ -174,14 +177,17 @@ static void ppc4xx_plb_reset (void *opaque) plb->besr =3D 0x00000000; } =20 -static void ppc4xx_plb_init(CPUPPCState *env) +void ppc4xx_plb_init(CPUPPCState *env) { ppc4xx_plb_t *plb; =20 plb =3D g_malloc0(sizeof(ppc4xx_plb_t)); + ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); + ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); qemu_register_reset(ppc4xx_plb_reset, plb); } =20 @@ -585,7 +591,7 @@ static void ebc_reset (void *opaque) ebc->cfg =3D 0x80400000; } =20 -static void ppc405_ebc_init(CPUPPCState *env) +void ppc405_ebc_init(CPUPPCState *env) { ppc4xx_ebc_t *ebc; =20 --=20 2.7.4 From nobody Sat Apr 27 15:23:41 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.zohomail.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 1502666941856850.1581117311886; Sun, 13 Aug 2017 16:29:01 -0700 (PDT) Received: from localhost ([::1]:46589 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh2JY-0001V1-Bi for importer@patchew.org; Sun, 13 Aug 2017 19:29:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52023) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dh278-0007Xq-GG for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dh270-0005wt-O7 for qemu-devel@nongnu.org; Sun, 13 Aug 2017 19:16:10 -0400 Received: from zero.eik.bme.hu ([2001:738:2001:2001::2001]:38234) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dh26z-0005ug-Ny; Sun, 13 Aug 2017 19:16:02 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id EC38E747EDE; Mon, 14 Aug 2017 01:15:52 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id A2223747EE1; Mon, 14 Aug 2017 01:15:50 +0200 (CEST) Message-Id: <5e493fd14e60d92d4fd80492ceff5ba13eb7b558.1502643878.git.balaton@eik.bme.hu> In-Reply-To: References: From: BALATON Zoltan MIME-Version: 1.0 Date: Sun, 13 Aug 2017 19:04:38 +0200 To: qemu-devel@nongnu.org, qemu-ppc@nongnu.org Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:738:2001:2001::2001 Subject: [Qemu-devel] [RFC PATCH 12/12] ppc: Add aCube Sam460ex board 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: Francois Revol , Alexander Graf , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add emulation of aCube Sam460ex board based on AMCC 460EX embedded SoC. This is not a full implementation yet with a lot of components still missing but enough to start a Linux kernel and the U-Boot firmware. Signed-off-by: Fran=C3=A7ois Revol Signed-off-by: BALATON Zoltan --- default-configs/ppcemb-softmmu.mak | 3 + hw/ppc/Makefile.objs | 2 + hw/ppc/sam460ex.c | 1895 ++++++++++++++++++++++++++++++++= ++++ include/hw/pci/pcie_host.h | 2 +- 4 files changed, 1901 insertions(+), 1 deletion(-) create mode 100644 hw/ppc/sam460ex.c diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-so= ftmmu.mak index 94340de..9a0a177 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -16,3 +16,6 @@ CONFIG_XILINX=3Dy CONFIG_XILINX_ETHLITE=3Dy CONFIG_LIBDECNUMBER=3Dy CONFIG_SM501=3Dy +CONFIG_USB_EHCI_SYSBUS=3Dy +CONFIG_IDE_SII3112=3Dy +CONFIG_SAM460EX=3Dy diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 9c5d58a..a242a59 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -27,3 +27,5 @@ obj-$(CONFIG_E500) +=3D e500.o mpc8544ds.o e500plat.o obj-$(CONFIG_E500) +=3D mpc8544_guts.o ppce500_spin.o # PowerPC 440 Xilinx ML507 reference board. obj-$(CONFIG_XILINX) +=3D virtex_ml507.o +# ACube Sam460ex board. +obj-$(CONFIG_SAM460EX) +=3D sam460ex.o diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c new file mode 100644 index 0000000..c61eb99 --- /dev/null +++ b/hw/ppc/sam460ex.c @@ -0,0 +1,1895 @@ +/* + * QEMU aCube Sam460ex board emulation + * + * Copyright (c) 2012 Fran=C3=A7ois Revol + * Copyright (c) 2016-2017 BALATON Zoltan + * + * This file is derived from hw/ppc440_bamboo.c, + * the copyright for that material belongs to the original owners. + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/cutils.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "sysemu/blockdev.h" +#include "hw/boards.h" +#include "sysemu/kvm.h" +#include "kvm_ppc.h" +#include "sysemu/device_tree.h" +#include "sysemu/block-backend.h" +#include "hw/loader.h" +#include "elf.h" +#include "exec/address-spaces.h" +#include "exec/memory.h" +#include "hw/ppc/ppc.h" +#include "hw/ppc/ppc405.h" +#include "hw/block/flash.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "hw/char/serial.h" +#include "hw/i2c/ppc4xx_i2c.h" +#include "hw/i2c/smbus.h" +#include "hw/usb/hcd-ehci.h" + +#undef DEBUG_SDRAM +#undef DEBUG_L2SRAM +#undef DEBUG_CPR +#undef DEBUG_SDR +#undef DEBUG_AHB +#undef DEBUG_PCIE + +#define BINARY_DEVICE_TREE_FILE "sam460ex.dtb" +#define UBOOT_FILENAME "u-boot-sam460-20100605.bin" +/* to extract the official U-Boot bin from the updater: */ +/* dd bs=3D1 skip=3D$(($(stat -c '%s' updater/updater-460) - 0x80000)) \ + if=3Dupdater/updater-460 of=3Du-boot-sam460-20100605.bin */ + +/* from Sam460 U-Boot include/configs/Sam460ex.h */ +#define FLASH_BASE 0xfff00000 +#define FLASH_BASE_H 0x4 +#define FLASH_SIZE (1 << 20) +#define UBOOT_LOAD_BASE 0xfff80000 +#define UBOOT_SIZE 0x00080000 +#define UBOOT_ENTRY 0xfffffffc + +/* from U-Boot */ +#define EPAPR_MAGIC (0x45504150) +#define KERNEL_ADDR 0x1000000 +#define FDT_ADDR 0x1800000 +#define RAMDISK_ADDR 0x1900000 + +/* Sam460ex IRQ MAP: + IRQ0 =3D ETH_INT + IRQ1 =3D FPGA_INT + IRQ2 =3D PCI_INT (PCIA, PCIB, PCIC, PCIB) + IRQ3 =3D FPGA_INT2 + IRQ11 =3D RTC_INT + IRQ12 =3D SM502_INT +*/ + +#define SDRAM_NR_BANKS 4 + +/* FIXME: See u-boot.git 8ac41e */ +static const unsigned int ppc460ex_sdram_bank_sizes[] =3D { + 1024 << 20, 512 << 20, 256 << 20, 128 << 20, 64 << 20, 32 << 20, 0 +}; + +struct boot_info { + uint32_t dt_base; + uint32_t dt_size; + uint32_t entry; +}; + +/*************************************************************************= ****/ +/* L2 Cache as SRAM */ +/* FIXME:fix names */ +enum { + DCR_L2CACHE_BASE =3D 0x030, + DCR_L2CACHE_CFG =3D DCR_L2CACHE_BASE, + DCR_L2CACHE_CMD, + DCR_L2CACHE_ADDR, + DCR_L2CACHE_DATA, + DCR_L2CACHE_STAT, + DCR_L2CACHE_CVER, + DCR_L2CACHE_SNP0, + DCR_L2CACHE_SNP1, + DCR_L2CACHE_END =3D DCR_L2CACHE_SNP1, +}; + +/* base is 460ex-specific, cf. U-Boot, ppc4xx-isram.h */ +enum { + DCR_ISRAM0_BASE =3D 0x020, + DCR_ISRAM0_SB0CR =3D DCR_ISRAM0_BASE, + DCR_ISRAM0_SB1CR, + DCR_ISRAM0_SB2CR, + DCR_ISRAM0_SB3CR, + DCR_ISRAM0_BEAR, + DCR_ISRAM0_BESR0, + DCR_ISRAM0_BESR1, + DCR_ISRAM0_PMEG, + DCR_ISRAM0_CID, + DCR_ISRAM0_REVID, + DCR_ISRAM0_DPC, + DCR_ISRAM0_END =3D DCR_ISRAM0_DPC +}; + +enum { + DCR_ISRAM1_BASE =3D 0x0b0, + DCR_ISRAM1_SB0CR =3D DCR_ISRAM1_BASE, + /* single bank */ + DCR_ISRAM1_BEAR =3D DCR_ISRAM1_BASE + 0x04, + DCR_ISRAM1_BESR0, + DCR_ISRAM1_BESR1, + DCR_ISRAM1_PMEG, + DCR_ISRAM1_CID, + DCR_ISRAM1_REVID, + DCR_ISRAM1_DPC, + DCR_ISRAM1_END =3D DCR_ISRAM1_DPC +}; + +typedef struct ppc4xx_l2sram_t { + MemoryRegion bank[4]; + uint32_t l2cache[8]; + uint32_t isram0[11]; +} ppc4xx_l2sram_t; + +#ifdef MAP_L2SRAM +static void l2sram_update_mappings(ppc4xx_l2sram_t *l2sram, + uint32_t isarc, uint32_t isacntl, + uint32_t dsarc, uint32_t dsacntl) +{ +#ifdef DEBUG_L2SRAM + printf("L2SRAM update ISA %08" PRIx32 " %08" PRIx32 " (%08" PRIx32 + " %08" PRIx32 ") DSA %08" PRIx32 " %08" PRIx32 + " (%08" PRIx32 " %08" PRIx32 ")\n", + isarc, isacntl, dsarc, dsacntl, + l2sram->isarc, l2sram->isacntl, l2sram->dsarc, l2sram->dsacntl); +#endif + if (l2sram->isarc !=3D isarc || + (l2sram->isacntl & 0x80000000) !=3D (isacntl & 0x80000000)) { + if (l2sram->isacntl & 0x80000000) { + /* Unmap previously assigned memory region */ + printf("L2SRAM unmap ISA %08" PRIx32 "\n", l2sram->isarc); + memory_region_del_subregion(get_system_memory(), + &l2sram->isarc_ram); + } + if (isacntl & 0x80000000) { + /* Map new instruction memory region */ +#ifdef DEBUG_L2SRAM + printf("L2SRAM map ISA %08" PRIx32 "\n", isarc); +#endif + memory_region_add_subregion(get_system_memory(), isarc, + &l2sram->isarc_ram); + } + } + if (l2sram->dsarc !=3D dsarc || + (l2sram->dsacntl & 0x80000000) !=3D (dsacntl & 0x80000000)) { + if (l2sram->dsacntl & 0x80000000) { + /* Beware not to unmap the region we just mapped */ + if (!(isacntl & 0x80000000) || l2sram->dsarc !=3D isarc) { + /* Unmap previously assigned memory region */ +#ifdef DEBUG_L2SRAM + printf("L2SRAM unmap DSA %08" PRIx32 "\n", l2sram->dsarc); +#endif + memory_region_del_subregion(get_system_memory(), + &l2sram->dsarc_ram); + } + } + if (dsacntl & 0x80000000) { + /* Beware not to remap the region we just mapped */ + if (!(isacntl & 0x80000000) || dsarc !=3D isarc) { + /* Map new data memory region */ +#ifdef DEBUG_L2SRAM + printf("L2SRAM map DSA %08" PRIx32 "\n", dsarc); +#endif + memory_region_add_subregion(get_system_memory(), dsarc, + &l2sram->dsarc_ram); + } + } + } +} +#endif + +static uint32_t dcr_read_l2sram(void *opaque, int dcrn) +{ + ppc4xx_l2sram_t *l2sram; + uint32_t ret; + + l2sram =3D opaque; + switch (dcrn) { + case DCR_L2CACHE_CFG: + case DCR_L2CACHE_CMD: + case DCR_L2CACHE_ADDR: + case DCR_L2CACHE_DATA: + case DCR_L2CACHE_STAT: + case DCR_L2CACHE_CVER: + case DCR_L2CACHE_SNP0: + case DCR_L2CACHE_SNP1: + ret =3D l2sram->l2cache[dcrn - DCR_L2CACHE_BASE]; +#ifdef DEBUG_L2SRAM + printf("L2SRAM: read DCR[%x(L2CACHE+%x)]: %08" PRIx32 "\n", + dcrn, dcrn - DCR_L2CACHE_BASE, ret); +#endif + break; + + case DCR_ISRAM0_SB0CR: + case DCR_ISRAM0_SB1CR: + case DCR_ISRAM0_SB2CR: + case DCR_ISRAM0_SB3CR: + case DCR_ISRAM0_BEAR: + case DCR_ISRAM0_BESR0: + case DCR_ISRAM0_BESR1: + case DCR_ISRAM0_PMEG: + case DCR_ISRAM0_CID: + case DCR_ISRAM0_REVID: + case DCR_ISRAM0_DPC: + ret =3D l2sram->isram0[dcrn - DCR_ISRAM0_BASE]; +#ifdef DEBUG_L2SRAM + printf("L2SRAM: read DCR[%x(ISRAM0+%x)]: %08" PRIx32 "\n", + dcrn, dcrn - DCR_ISRAM0_BASE, ret); +#endif + break; + + default: + ret =3D 0; + break; + } + + return ret; +} + +static void dcr_write_l2sram(void *opaque, int dcrn, uint32_t val) +{ + /*ppc4xx_l2sram_t *l2sram =3D opaque;*/ + /* TODO */ + + switch (dcrn) { + case DCR_L2CACHE_CFG: + case DCR_L2CACHE_CMD: + case DCR_L2CACHE_ADDR: + case DCR_L2CACHE_DATA: + case DCR_L2CACHE_STAT: + case DCR_L2CACHE_CVER: + case DCR_L2CACHE_SNP0: + case DCR_L2CACHE_SNP1: + /*l2sram->l2cache[dcrn - DCR_L2CACHE_BASE] =3D val;*/ +#ifdef DEBUG_L2SRAM + printf("L2SRAM: write DCR[%x(L2CACHE+%x)]: %08" PRIx32 "\n", + dcrn, dcrn - DCR_L2CACHE_BASE, val); +#endif + break; + + case DCR_ISRAM0_SB0CR: + case DCR_ISRAM0_SB1CR: + case DCR_ISRAM0_SB2CR: + case DCR_ISRAM0_SB3CR: + case DCR_ISRAM0_BEAR: + case DCR_ISRAM0_BESR0: + case DCR_ISRAM0_BESR1: + case DCR_ISRAM0_PMEG: + case DCR_ISRAM0_CID: + case DCR_ISRAM0_REVID: + case DCR_ISRAM0_DPC: + /*l2sram->isram0[dcrn - DCR_L2CACHE_BASE] =3D val;*/ +#ifdef DEBUG_L2SRAM + printf("L2SRAM: write DCR[%x(ISRAM0+%x)]: %08" PRIx32 "\n", + dcrn, dcrn - DCR_ISRAM0_BASE, val); +#endif + break; + + case DCR_ISRAM1_SB0CR: + case DCR_ISRAM1_BEAR: + case DCR_ISRAM1_BESR0: + case DCR_ISRAM1_BESR1: + case DCR_ISRAM1_PMEG: + case DCR_ISRAM1_CID: + case DCR_ISRAM1_REVID: + case DCR_ISRAM1_DPC: + /*l2sram->isram1[dcrn - DCR_L2CACHE_BASE] =3D val;*/ +#ifdef DEBUG_L2SRAM + printf("L2SRAM: write DCR[%x(ISRAM1+%x)]: %08" PRIx32 "\n", + dcrn, dcrn - DCR_ISRAM1_BASE, val); +#endif + break; + } + /*l2sram_update_mappings(l2sram, isarc, isacntl, dsarc, dsacntl);*/ +} + +static void l2sram_reset(void *opaque) +{ + ppc4xx_l2sram_t *l2sram; + /*uint32_t isarc, dsarc, isacntl, dsacntl;*/ + + l2sram =3D opaque; + memset(l2sram->l2cache, 0, sizeof(l2sram->l2cache)); + l2sram->l2cache[DCR_L2CACHE_STAT - DCR_L2CACHE_BASE] =3D 0x80000000; + memset(l2sram->isram0, 0, sizeof(l2sram->isram0)); + /*l2sram_update_mappings(l2sram, isarc, isacntl, dsarc, dsacntl);*/ +} + +static void ppc4xx_l2sram_init(CPUPPCState *env) +{ + ppc4xx_l2sram_t *l2sram; + + l2sram =3D g_malloc0(sizeof(ppc4xx_l2sram_t)); + /* XXX: Size is 4*64kB for 460ex, cf. U-Boot, ppc4xx-isram.h */ + memory_region_init_ram(&l2sram->bank[0], NULL, "ppc4xx.l2sram_bank0", + 64 * 1024, &error_abort); + memory_region_init_ram(&l2sram->bank[1], NULL, "ppc4xx.l2sram_bank1", + 64 * 1024, &error_abort); + memory_region_init_ram(&l2sram->bank[2], NULL, "ppc4xx.l2sram_bank2", + 64 * 1024, &error_abort); + memory_region_init_ram(&l2sram->bank[3], NULL, "ppc4xx.l2sram_bank3", + 64 * 1024, &error_abort); + qemu_register_reset(&l2sram_reset, l2sram); + ppc_dcr_register(env, DCR_L2CACHE_CFG, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_L2CACHE_CMD, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_L2CACHE_ADDR, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_L2CACHE_DATA, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_L2CACHE_STAT, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_L2CACHE_CVER, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_L2CACHE_SNP0, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_L2CACHE_SNP1, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + + ppc_dcr_register(env, DCR_ISRAM0_SB0CR, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_ISRAM0_SB1CR, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_ISRAM0_SB2CR, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_ISRAM0_SB3CR, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_ISRAM0_PMEG, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_ISRAM0_DPC, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + + ppc_dcr_register(env, DCR_ISRAM1_SB0CR, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_ISRAM1_PMEG, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); + ppc_dcr_register(env, DCR_ISRAM1_DPC, + l2sram, &dcr_read_l2sram, &dcr_write_l2sram); +} + +/*************************************************************************= ****/ +/* Clocking Power on Reset */ +enum { + CPR0_CFGADDR =3D 0x00C, + CPR0_CFGDATA =3D 0x00D, +}; + +typedef struct ppc4xx_cpr_t { + uint32_t addr; +} ppc4xx_cpr_t; + +static uint32_t dcr_read_cpr(void *opaque, int dcrn) +{ + ppc4xx_cpr_t *cpr =3D opaque; + uint32_t ret; + + switch (dcrn) { + case CPR0_CFGADDR: + ret =3D cpr->addr; +#ifdef DEBUG_CPR + printf("read DCR[%x(CPR0ADDR)]: %08" PRIx32 "\n", dcrn, ret); +#endif + break; + case CPR0_CFGDATA: + ret =3D 0; +#ifdef DEBUG_CPR + printf("read DCR[%x(CPR0DATA)]: %08" PRIx32 "\n", dcrn, ret); +#endif + break; + default: + /* Avoid gcc warning */ + ret =3D 0; + break; + } + + return ret; +} + +static void dcr_write_cpr(void *opaque, int dcrn, uint32_t val) +{ + ppc4xx_cpr_t *cpr =3D opaque; + + switch (dcrn) { + case CPR0_CFGADDR: + cpr->addr =3D val; +#ifdef DEBUG_CPR + printf("write DCR[%x(CPRADDR)]: %08" PRIx32 "\n", dcrn, val); +#endif + break; + case CPR0_CFGDATA: +#ifdef DEBUG_CPR + printf("write DCR[%x(CPRDATA)]: %08" PRIx32 "\n", dcrn, val); +#endif + break; + default: +#ifdef DEBUG_CPR + printf("write DCR[%x]: %08" PRIx32 "\n", dcrn, val); +#endif + break; + } +} + +static void ppc4xx_cpr_reset(void *opaque) +{ + ppc4xx_cpr_t *cpr =3D opaque; + + cpr->addr =3D 0; +} + +static void ppc4xx_cpr_init(CPUPPCState *env) +{ + ppc4xx_cpr_t *cpr; + + cpr =3D g_malloc0(sizeof(*cpr)); + ppc_dcr_register(env, CPR0_CFGADDR, cpr, &dcr_read_cpr, &dcr_write_cpr= ); + ppc_dcr_register(env, CPR0_CFGDATA, cpr, &dcr_read_cpr, &dcr_write_cpr= ); + qemu_register_reset(ppc4xx_cpr_reset, cpr); +} + +/*************************************************************************= ****/ +/* System DCRs */ +typedef struct ppc4xx_sdr_t ppc4xx_sdr_t; +struct ppc4xx_sdr_t { + uint32_t addr; +}; + +enum { + SDR0_CFGADDR =3D 0x00e, + SDR0_CFGDATA, + SDR0_STRP0 =3D 0x020, + SDR0_STRP1, + SDR0_ECID3 =3D 0x083, + SDR0_DDR0 =3D 0x0e1, + SDR0_USB0 =3D 0x320, +}; + +enum { + PESDR0_LOOP =3D 0x303, + PESDR0_RCSSET, + PESDR0_RCSSTS, + PESDR0_RSTSTA =3D 0x310, + PESDR1_LOOP =3D 0x343, + PESDR1_RCSSET, + PESDR1_RCSSTS, + PESDR1_RSTSTA =3D 0x365, +}; + +#define SDR0_DDR0_DDRM_ENCODE(n) ((((unsigned long)(n)) & 0x03) << 29) +#define SDR0_DDR0_DDRM_DDR1 0x20000000 +#define SDR0_DDR0_DDRM_DDR2 0x40000000 + +static uint32_t dcr_read_sdr(void *opaque, int dcrn) +{ + ppc4xx_sdr_t *sdr; + uint32_t ret; + + sdr =3D opaque; + switch (dcrn) { + case SDR0_CFGADDR: + ret =3D sdr->addr; + break; + case SDR0_CFGDATA: + switch (sdr->addr) { + case SDR0_STRP0: + /* FIXME: Is this correct? This breaks timing */ + ret =3D 0 /*5 << 8 | 15 << 4*/; + break; + case SDR0_STRP1: + ret =3D 5 << 29 | 2 << 26 | 1 << 24; + break; + case SDR0_ECID3: + ret =3D 1 << 20; /* No Security/Kasumi support */ + break; + case SDR0_DDR0: + ret =3D SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1; + break; + case PESDR0_RCSSET: + case PESDR1_RCSSET: + ret =3D (1 << 24) | (1 << 16); + break; + case PESDR0_RCSSTS: + case PESDR1_RCSSTS: + ret =3D (1 << 16) | (1 << 12); + break; + case PESDR0_RSTSTA: + case PESDR1_RSTSTA: + ret =3D 1; + break; + case PESDR0_LOOP: + case PESDR1_LOOP: + ret =3D 1 << 12; + break; + default: + ret =3D 0; + break; + } +#ifdef DEBUG_SDR + if (sdr->addr !=3D 0x20 && sdr->addr !=3D 0x21) { + printf("read DCR[%x(SDRDATA[%x])]: %08" PRIx32 "\n", + dcrn, sdr->addr, ret); + } +#endif + break; + default: + ret =3D 0; +#ifdef DEBUG_SDR + printf("read DCR[%x]: %08" PRIx32 "\n", dcrn, ret); +#endif + break; + } + + return ret; +} + +static void dcr_write_sdr(void *opaque, int dcrn, uint32_t val) +{ + ppc4xx_sdr_t *sdr; + + sdr =3D opaque; + switch (dcrn) { + case SDR0_CFGADDR: + sdr->addr =3D val; + break; + case SDR0_CFGDATA: +#ifdef DEBUG_SDR + printf("write DCR[%x(SDRDATA[%x])]: %08" PRIx32 "\n", + dcrn, sdr->addr, val); +#endif + switch (sdr->addr) { + case 0x00: /* B0CR */ + break; + default: + break; + } + break; + default: +#ifdef DEBUG_SDR + printf("write DCR[%x]: %08" PRIx32 "\n", dcrn, val); +#endif + break; + } +} + +static void sdr_reset(void *opaque) +{ + ppc4xx_sdr_t *sdr; + + sdr =3D opaque; + sdr->addr =3D 0; +} + +static void ppc4xx_sdr_init(CPUPPCState *env) +{ + ppc4xx_sdr_t *sdr; + + sdr =3D g_malloc0(sizeof(ppc4xx_sdr_t)); + qemu_register_reset(&sdr_reset, sdr); + ppc_dcr_register(env, SDR0_CFGADDR, + sdr, &dcr_read_sdr, &dcr_write_sdr); + ppc_dcr_register(env, SDR0_CFGDATA, + sdr, &dcr_read_sdr, &dcr_write_sdr); + ppc_dcr_register(env, SDR0_USB0, + sdr, &dcr_read_sdr, &dcr_write_sdr); +} + +/*************************************************************************= ****/ +/* SDRAM controller */ +typedef struct ppc4xx_sdram_t { + uint32_t addr; + int nbanks; + MemoryRegion containers[4]; /* used for clipping */ + MemoryRegion *ram_memories; + hwaddr ram_bases[4]; + hwaddr ram_sizes[4]; + uint32_t bcr[4]; +} ppc4xx_sdram_t; + +enum { + SDRAM_R0BAS =3D 0x040, + SDRAM_R1BAS, + SDRAM_R2BAS, + SDRAM_R3BAS, + SDRAM_CONF1HB =3D 0x045, + SDRAM_PLBADDULL =3D 0x04a, + SDRAM_CONF1LL =3D 0x04b, + SDRAM_CONFPATHB =3D 0x04f, + SDRAM_PLBADDUHB =3D 0x050, + SDRAM0_CFGADDR =3D 0x010, + SDRAM0_CFGDATA, +}; + +/* XXX: TOFIX: some patches have made this code become inconsistent: + * there are type inconsistencies, mixing hwaddr, target_ulong + * and uint32_t + */ +static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size) +{ + uint32_t bcr; + + switch (ram_size) { + case (8 * M_BYTE): + bcr =3D 0xffc0; + break; + case (16 * M_BYTE): + bcr =3D 0xff80; + break; + case (32 * M_BYTE): + bcr =3D 0xff00; + break; + case (64 * M_BYTE): + bcr =3D 0xfe00; + break; + case (128 * M_BYTE): + bcr =3D 0xfc00; + break; + case (256 * M_BYTE): + bcr =3D 0xf800; + break; + case (512 * M_BYTE): + bcr =3D 0xf000; + break; + case (1 * G_BYTE): + bcr =3D 0xe000; + break; +/* + case (2 * G_BYTE): + bcr =3D 0xc000; + break; + case (4 * G_BYTE): + bcr =3D 0x8000; + break; +*/ + default: + printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__, + ram_size); + return 0; + } + bcr |=3D ram_base & 0xFF800000; + bcr |=3D 1; + + return bcr; +} + +static inline hwaddr sdram_base(uint32_t bcr) +{ + return bcr & 0xFF800000; +} + +static target_ulong sdram_size(uint32_t bcr) +{ + target_ulong size; + int sh; + + sh =3D 1024 - ((bcr >> 6) & 0x3ff); + if (sh =3D=3D 0) { + size =3D -1; + } else { + size =3D 8 * M_BYTE * sh; + } + + return size; +} + +static void sdram_set_bcr(ppc4xx_sdram_t *sdram, + uint32_t *bcrp, uint32_t bcr, int enabled) +{ + unsigned n =3D bcrp - sdram->bcr; + + if (*bcrp & 1) { + /* Unmap RAM */ +#ifdef DEBUG_SDRAM + printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", + __func__, sdram_base(*bcrp), sdram_size(*bcrp)); +#endif + memory_region_del_subregion(get_system_memory(), + &sdram->containers[n]); + memory_region_del_subregion(&sdram->containers[n], + &sdram->ram_memories[n]); + object_unparent(OBJECT(&sdram->containers[n])); + } + *bcrp =3D bcr & 0xFFDEE001; + if (enabled && (bcr & 1)) { +#ifdef DEBUG_SDRAM + printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", + __func__, sdram_base(bcr), sdram_size(bcr)); +#endif + memory_region_init(&sdram->containers[n], NULL, "sdram-containers", + sdram_size(bcr)); + memory_region_add_subregion(&sdram->containers[n], 0, + &sdram->ram_memories[n]); + memory_region_add_subregion(get_system_memory(), + sdram_base(bcr), + &sdram->containers[n]); + } +} + +static void sdram_map_bcr(ppc4xx_sdram_t *sdram) +{ + int i; + + for (i =3D 0; i < sdram->nbanks; i++) { + if (sdram->ram_sizes[i] !=3D 0) { + sdram_set_bcr(sdram, + &sdram->bcr[i], + sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[= i]), + 1); + } else { + sdram_set_bcr(sdram, &sdram->bcr[i], 0, 0); + } + } +} + +static uint32_t dcr_read_sdram(void *opaque, int dcrn) +{ + ppc4xx_sdram_t *sdram; + uint32_t ret; + + sdram =3D opaque; +#ifdef DEBUG_SDR + printf("read DCR[%x(SDRAM)]\n", dcrn); +#endif + switch (dcrn) { + case SDRAM_R0BAS: + case SDRAM_R1BAS: + case SDRAM_R2BAS: + case SDRAM_R3BAS: + ret =3D sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS], + sdram->ram_sizes[dcrn - SDRAM_R0BAS]); + break; + case SDRAM_CONF1HB: + case SDRAM_CONF1LL: + case SDRAM_CONFPATHB: + case SDRAM_PLBADDULL: + case SDRAM_PLBADDUHB: + ret =3D 0; + break; + case SDRAM0_CFGADDR: + ret =3D sdram->addr; +#ifdef DEBUG_SDR + printf("read DCR[%x(SDRAMADDR)]: %08" PRIx32 "\n", dcrn, ret); +#endif + break; + case SDRAM0_CFGDATA: + switch (sdram->addr) { + case 0x0014: /* SDRAM_MCSTAT (405EX) */ + case 0x001F: + ret =3D 0x80000000; + break; + case 0x0021: /* SDRAM_MCOPT2 */ + ret =3D 0x08000000; + break; + case 0x0040: /* SDRAM_MB0CF */ + ret =3D 0x00008001; + break; + case 0x007A: /* SDRAM_DLCR */ + ret =3D 0x02000000; + break; + case 0x00E1: /* SDR0_DDR0 */ + ret =3D SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1; + break; + default: + ret =3D 0; + break; + } +#ifdef DEBUG_SDR + printf("read DCR[%x(SDRAMDATA)]: %08" PRIx32 "\n", dcrn, ret); +#endif + break; + default: + ret =3D 0; + break; + } + + return ret; +} + +static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val) +{ + ppc4xx_sdram_t *sdram; + + sdram =3D opaque; +#ifdef DEBUG_SDR + printf("write DCR[%x(SDRAM)]: %08" PRIx32 "\n", dcrn, val); +#endif + switch (dcrn) { + case SDRAM_R0BAS: + case SDRAM_R1BAS: + case SDRAM_R2BAS: + case SDRAM_R3BAS: + case SDRAM_CONF1HB: + case SDRAM_CONF1LL: + case SDRAM_CONFPATHB: + case SDRAM_PLBADDULL: + case SDRAM_PLBADDUHB: + break; + case SDRAM0_CFGADDR: + sdram->addr =3D val; +#ifdef DEBUG_SDR + printf("write DCR[%x(SDRAMADDR)]: %08" PRIx32 "\n", dcrn, val); +#endif + break; + case SDRAM0_CFGDATA: +#ifdef DEBUG_SDR + printf("write DCR[%x(SDRAMDATA)]: %08" PRIx32 "\n", dcrn, val); +#endif + switch (sdram->addr) { + case 0x00: /* B0CR */ + break; + default: + break; + } + break; + default: + break; + } +} + +static void sdram_reset(void *opaque) +{ + ppc4xx_sdram_t *sdram; + + sdram =3D opaque; + sdram->addr =3D 0; +} + +static void ppc440_sdram_init(CPUPPCState *env, int nbanks, + MemoryRegion *ram_memories, + hwaddr *ram_bases, + hwaddr *ram_sizes, + int do_init) +{ + ppc4xx_sdram_t *sdram; + + sdram =3D g_malloc0(sizeof(ppc4xx_sdram_t)); + sdram->nbanks =3D nbanks; + sdram->ram_memories =3D ram_memories; + memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(hwaddr)); + memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(hwaddr)); + qemu_register_reset(&sdram_reset, sdram); + ppc_dcr_register(env, SDRAM0_CFGADDR, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM0_CFGDATA, + sdram, &dcr_read_sdram, &dcr_write_sdram); + if (do_init) { + sdram_map_bcr(sdram); + } + + ppc_dcr_register(env, SDRAM_R0BAS, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_R1BAS, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_R2BAS, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_R3BAS, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_CONF1HB, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_PLBADDULL, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_CONF1LL, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_CONFPATHB, + sdram, &dcr_read_sdram, &dcr_write_sdram); + ppc_dcr_register(env, SDRAM_PLBADDUHB, + sdram, &dcr_read_sdram, &dcr_write_sdram); +} + +/*************************************************************************= ****/ +/* PLB to AHB bridge */ +enum { + AHB_TOP =3D 0x0A4, + AHB_BOT =3D 0x0A5, +}; + +typedef struct ppc4xx_ahb_t { + uint32_t top; + uint32_t bot; +} ppc4xx_ahb_t; + +static uint32_t dcr_read_ahb(void *opaque, int dcrn) +{ + ppc4xx_ahb_t *ahb; + uint32_t ret; + + ahb =3D opaque; + switch (dcrn) { + case AHB_TOP: + ret =3D ahb->top; + break; + case AHB_BOT: + ret =3D ahb->bot; + break; + default: + /* Avoid gcc warning */ + ret =3D 0; + break; + } +#ifdef DEBUG_AHB + printf("read DCR[%x(AHB+%x)]: %08" PRIx32 "\n", dcrn, dcrn - 0xA0, ret= ); +#endif + + return ret; +} + +static void dcr_write_ahb(void *opaque, int dcrn, uint32_t val) +{ + ppc4xx_ahb_t *ahb; + + ahb =3D opaque; +#ifdef DEBUG_AHB + printf("write DCR[%x(AHB+%x)]: %08" PRIx32 "\n", dcrn, dcrn - 0xA0, va= l); +#endif + switch (dcrn) { + case AHB_TOP: + ahb->top =3D val; + break; + case AHB_BOT: + ahb->bot =3D val; + break; + } +} + +static void ppc4xx_ahb_reset(void *opaque) +{ + ppc4xx_ahb_t *ahb; + + ahb =3D opaque; + /* No error */ + ahb->top =3D 0; + ahb->bot =3D 0; +} + +static void ppc4xx_ahb_init(CPUPPCState *env) +{ + ppc4xx_ahb_t *ahb; + + ahb =3D g_malloc0(sizeof(ppc4xx_ahb_t)); + ppc_dcr_register(env, AHB_TOP, ahb, &dcr_read_ahb, &dcr_write_ahb); + ppc_dcr_register(env, AHB_BOT, ahb, &dcr_read_ahb, &dcr_write_ahb); + qemu_register_reset(ppc4xx_ahb_reset, ahb); +} + +/*************************************************************************= ****/ +/* PCI Express controller */ +/* This is not complete and not meant to work, only implemented partially + * to allow firmware and guests to find an empty bus. Cards should use PCI. + */ +#include "hw/pci/pcie_host.h" + +#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" +#define PPC460EX_PCIE_HOST(obj) \ + OBJECT_CHECK(PPC460EXPCIEState, (obj), TYPE_PPC460EX_PCIE_HOST) + +typedef struct PPC460EXPCIEState { + PCIExpressHost host; + + MemoryRegion iomem; + qemu_irq irq[4]; + int32_t dcrn_base; + + uint64_t cfg_base; + uint32_t cfg_mask; + uint64_t msg_base; + uint32_t msg_mask; + uint64_t omr1_base; + uint64_t omr1_mask; + uint64_t omr2_base; + uint64_t omr2_mask; + uint64_t omr3_base; + uint64_t omr3_mask; + uint64_t reg_base; + uint32_t reg_mask; + uint32_t special; + uint32_t cfg; +} PPC460EXPCIEState; + +#define DCRN_PCIE0_BASE 0x100 +#define DCRN_PCIE1_BASE 0x120 + +enum { + PEGPL_CFGBAH =3D 0x0, + PEGPL_CFGBAL, + PEGPL_CFGMSK, + PEGPL_MSGBAH, + PEGPL_MSGBAL, + PEGPL_MSGMSK, + PEGPL_OMR1BAH, + PEGPL_OMR1BAL, + PEGPL_OMR1MSKH, + PEGPL_OMR1MSKL, + PEGPL_OMR2BAH, + PEGPL_OMR2BAL, + PEGPL_OMR2MSKH, + PEGPL_OMR2MSKL, + PEGPL_OMR3BAH, + PEGPL_OMR3BAL, + PEGPL_OMR3MSKH, + PEGPL_OMR3MSKL, + PEGPL_REGBAH, + PEGPL_REGBAL, + PEGPL_REGMSK, + PEGPL_SPECIAL, + PEGPL_CFG, +}; + +#ifdef DEBUG_PCIE +static void dump_pcie_regs(PPC460EXPCIEState *state) +{ + printf("dcrn_base=3D%x\n", state->dcrn_base); + printf("cfg base=3D%lx, mask=3D%x, size=3D%x\n", state->cfg_base, + state->cfg_mask, ~(state->cfg_mask & 0xfffffffe) + 1); + printf("msg base=3D%lx, mask=3D%x, size=3D%x\n", state->msg_base, + state->msg_mask, ~(state->msg_mask & 0xfffffffe) + 1); + printf("omr1 base=3D%lx, mask=3D%lx, size=3D%"PRIu64"\n", state->omr1_= base, + state->omr1_mask, ~state->omr1_mask + 1); + printf("omr2 base=3D%lx, mask=3D%lx, size=3D%"PRIu64"\n", state->omr2_= base, + state->omr2_mask, ~state->omr2_mask + 1); + printf("omr3 base=3D%lx, mask=3D%lx, size=3D%"PRIu64"\n", state->omr3_= base, + state->omr3_mask, ~state->omr3_mask + 1); + printf("reg base=3D%lx, mask=3D%x, size=3D%x\n", state->reg_base, + state->reg_mask, ~(state->reg_mask & 0xfffffffe) + 1); + printf("special=3D%x, cfg=3D%x\n", state->special, state->cfg); +} +#endif + +static uint32_t dcr_read_pcie(void *opaque, int dcrn) +{ + uint32_t ret =3D 0; + PPC460EXPCIEState *state =3D opaque; + + switch (dcrn - state->dcrn_base) { + case PEGPL_CFGBAH: + ret =3D state->cfg_base >> 32; + break; + case PEGPL_CFGBAL: + ret =3D state->cfg_base; + break; + case PEGPL_CFGMSK: + ret =3D state->cfg_mask; + break; + case PEGPL_MSGBAH: + ret =3D state->msg_base >> 32; + break; + case PEGPL_MSGBAL: + ret =3D state->msg_base; + break; + case PEGPL_MSGMSK: + ret =3D state->msg_mask; + break; + case PEGPL_OMR1BAH: + ret =3D state->omr1_base >> 32; + break; + case PEGPL_OMR1BAL: + ret =3D state->omr1_base; + break; + case PEGPL_OMR1MSKH: + ret =3D state->omr1_mask >> 32; + break; + case PEGPL_OMR1MSKL: + ret =3D state->omr1_mask; + break; + case PEGPL_OMR2BAH: + ret =3D state->omr2_base >> 32; + break; + case PEGPL_OMR2BAL: + ret =3D state->omr2_base; + break; + case PEGPL_OMR2MSKH: + ret =3D state->omr2_mask >> 32; + break; + case PEGPL_OMR2MSKL: + ret =3D state->omr3_mask; + break; + case PEGPL_OMR3BAH: + ret =3D state->omr3_base >> 32; + break; + case PEGPL_OMR3BAL: + ret =3D state->omr3_base; + break; + case PEGPL_OMR3MSKH: + ret =3D state->omr3_mask >> 32; + break; + case PEGPL_OMR3MSKL: + ret =3D state->omr3_mask; + break; + case PEGPL_REGBAH: + ret =3D state->reg_base >> 32; + break; + case PEGPL_REGBAL: + ret =3D state->reg_base; + break; + case PEGPL_REGMSK: + ret =3D state->reg_mask; + break; + case PEGPL_SPECIAL: + ret =3D state->special; + break; + case PEGPL_CFG: + ret =3D state->cfg; + break; + } +#ifdef DEBUG_PCIE + printf("read DCR[%x(PCIE)]: %08" PRIx32 "\n", dcrn, ret); +#endif + + return ret; +} + +static void dcr_write_pcie(void *opaque, int dcrn, uint32_t val) +{ + PPC460EXPCIEState *s =3D opaque; + uint64_t size; + +#ifdef DEBUG_PCIE + printf("write DCR[%x(PCIE)]: %08" PRIx32 "\n", dcrn, val); +#endif + switch (dcrn - s->dcrn_base) { + case PEGPL_CFGBAH: + s->cfg_base =3D ((uint64_t)val << 32) | (s->cfg_base & 0xffffffff); + break; + case PEGPL_CFGBAL: + s->cfg_base =3D (s->cfg_base & 0xffffffff00000000ULL) | val; + break; + case PEGPL_CFGMSK: + s->cfg_mask =3D val; + size =3D ~(val & 0xfffffffe) + 1; +#ifdef DEBUG_PCIE + printf("%s: %smapping cfg at %lx/%x (size=3D%lx)\n", __func__, + (val & 1 ? "" : "un"), s->cfg_base, val, size); +#endif + qemu_mutex_lock_iothread(); + pcie_host_mmcfg_update(PCIE_HOST_BRIDGE(s), val & 1, s->cfg_base, = size); + qemu_mutex_unlock_iothread(); + break; + case PEGPL_MSGBAH: + s->msg_base =3D ((uint64_t)val << 32) | (s->msg_base & 0xffffffff); + break; + case PEGPL_MSGBAL: + s->msg_base =3D (s->msg_base & 0xffffffff00000000ULL) | val; + break; + case PEGPL_MSGMSK: + s->msg_mask =3D val; + break; + case PEGPL_OMR1BAH: + s->omr1_base =3D ((uint64_t)val << 32) | (s->omr1_base & 0xfffffff= f); + break; + case PEGPL_OMR1BAL: + s->omr1_base =3D (s->omr1_base & 0xffffffff00000000ULL) | val; + break; + case PEGPL_OMR1MSKH: + s->omr1_mask =3D ((uint64_t)val << 32) | (s->omr1_mask & 0xfffffff= f); + break; + case PEGPL_OMR1MSKL: + s->omr1_mask =3D (s->omr1_mask & 0xffffffff00000000ULL) | val; + break; + case PEGPL_OMR2BAH: + s->omr2_base =3D ((uint64_t)val << 32) | (s->omr2_base & 0xfffffff= f); + break; + case PEGPL_OMR2BAL: + s->omr2_base =3D (s->omr2_base & 0xffffffff00000000ULL) | val; + break; + case PEGPL_OMR2MSKH: + s->omr2_mask =3D ((uint64_t)val << 32) | (s->omr2_mask & 0xfffffff= f); + break; + case PEGPL_OMR2MSKL: + s->omr2_mask =3D (s->omr2_mask & 0xffffffff00000000ULL) | val; + break; + case PEGPL_OMR3BAH: + s->omr3_base =3D ((uint64_t)val << 32) | (s->omr3_base & 0xfffffff= f); + break; + case PEGPL_OMR3BAL: + s->omr3_base =3D (s->omr3_base & 0xffffffff00000000ULL) | val; + break; + case PEGPL_OMR3MSKH: + s->omr3_mask =3D ((uint64_t)val << 32) | (s->omr3_mask & 0xfffffff= f); + break; + case PEGPL_OMR3MSKL: + s->omr3_mask =3D (s->omr3_mask & 0xffffffff00000000ULL) | val; + break; + case PEGPL_REGBAH: + s->reg_base =3D ((uint64_t)val << 32) | (s->reg_base & 0xffffffff); + break; + case PEGPL_REGBAL: + s->reg_base =3D (s->reg_base & 0xffffffff00000000ULL) | val; + break; + case PEGPL_REGMSK: + s->reg_mask =3D val; + /* FIXME: how is size encoded? */ + size =3D (val =3D=3D 0x7001 ? 4096 : ~(val & 0xfffffffe) + 1); +#ifdef DEBUG_PCIE + printf("%s: %smapping reg at %lx/%x (size=3D%lx)\n", __func__, + (val & 1 ? "" : "un"), s->reg_base, val, size); +#endif + break; + case PEGPL_SPECIAL: + s->special =3D val; + break; + case PEGPL_CFG: + s->cfg =3D val; +#ifdef DEBUG_PCIE + dump_pcie_regs(s); +#endif + break; + } +} + +static void ppc460ex_set_irq(void *opaque, int irq_num, int level) +{ + PPC460EXPCIEState *s =3D opaque; + qemu_set_irq(s->irq[irq_num], level); +} + +static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) +{ + PPC460EXPCIEState *s =3D PPC460EX_PCIE_HOST(dev); + PCIHostState *pci =3D PCI_HOST_BRIDGE(dev); + int i, id; + char buf[16]; + + switch (s->dcrn_base) { + case DCRN_PCIE0_BASE: + id =3D 0; + break; + case DCRN_PCIE1_BASE: + id =3D 1; + break; + } + snprintf(buf, sizeof(buf), "pcie%d-io", id); + memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX); + for (i =3D 0; i < 4; i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); + } + snprintf(buf, sizeof(buf), "pcie.%d", id); + pci->bus =3D pci_register_bus(DEVICE(s), buf, ppc460ex_set_irq, + pci_swizzle_map_irq_fn, s, &s->iomem, + get_system_io(), 0, 4, TYPE_PCIE_BUS); +} + +static Property ppc460ex_pcie_props[] =3D { + DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc460ex_pcie_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->realize =3D ppc460ex_pcie_realize; + dc->props =3D ppc460ex_pcie_props; + dc->hotpluggable =3D false; +} + +static const TypeInfo ppc460ex_pcie_host_info =3D { + .name =3D TYPE_PPC460EX_PCIE_HOST, + .parent =3D TYPE_PCIE_HOST_BRIDGE, + .instance_size =3D sizeof(PPC460EXPCIEState), + .class_init =3D ppc460ex_pcie_class_init, +}; + +static void ppc460ex_pcie_register(void) +{ + type_register_static(&ppc460ex_pcie_host_info); +} + +type_init(ppc460ex_pcie_register) + +static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState = *env) +{ +#ifdef DEBUG_PCIE + printf("%s: base=3D%x\n", __func__, s->dcrn_base); +#endif + ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGMSK, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGMSK, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAH, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_REGMSK, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_SPECIAL, s, + &dcr_read_pcie, &dcr_write_pcie); + ppc_dcr_register(env, s->dcrn_base + PEGPL_CFG, s, + &dcr_read_pcie, &dcr_write_pcie); +} + +static void ppc460ex_pcie_init(CPUPPCState *env) +{ + DeviceState *dev; + + dev =3D qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE); + qdev_init_nofail(dev); + object_property_set_bool(OBJECT(dev), true, "realized", NULL); + ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); + + dev =3D qdev_create(NULL, TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE); + qdev_init_nofail(dev); + object_property_set_bool(OBJECT(dev), true, "realized", NULL); + ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); +} + +/*************************************************************************= ****/ +/* SPD eeprom content from mips_malta.c */ + +struct _eeprom24c0x_t { + uint8_t tick; + uint8_t address; + uint8_t command; + uint8_t ack; + uint8_t scl; + uint8_t sda; + uint8_t data; + uint8_t contents[256]; +}; + +typedef struct _eeprom24c0x_t eeprom24c0x_t; + +static eeprom24c0x_t spd_eeprom =3D { + .contents =3D { + /* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00, + /* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01, + /* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + /* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF, + /* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00, + /* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0, + /* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4, + }, +}; + +static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size) +{ + enum { SDR =3D 0x4, DDR1 =3D 0x7, DDR2 =3D 0x8 } type; + uint8_t *spd =3D spd_eeprom.contents; + uint8_t nbanks =3D 0; + uint16_t density =3D 0; + int i; + + /* work in terms of MB */ + ram_size >>=3D 20; + + while ((ram_size >=3D 4) && (nbanks <=3D 2)) { + int sz_log2 =3D MIN(31 - clz32(ram_size), 14); + nbanks++; + density |=3D 1 << (sz_log2 - 2); + ram_size -=3D 1 << sz_log2; + } + + /* split to 2 banks if possible */ + if ((nbanks =3D=3D 1) && (density > 1)) { + nbanks++; + density >>=3D 1; + } + + if (density & 0xff00) { + density =3D (density & 0xe0) | ((density >> 8) & 0x1f); + type =3D DDR2; + } else if (!(density & 0x1f)) { + type =3D DDR2; + } else { + type =3D SDR; + } + + if (ram_size) { + fprintf(stderr, "Warning: SPD cannot represent final %dMB" + " of SDRAM\n", (int)ram_size); + } + + /* fill in SPD memory information */ + spd[2] =3D type; + spd[5] =3D nbanks; + spd[31] =3D density; +#ifdef DEBUG_SDRAM + printf("SPD: nbanks %d density %d\n", nbanks, density); +#endif + /* XXX: this is totally random */ + spd[9] =3D 0x10; /* CAS tcyc */ + spd[18] =3D 0x20; /* CAS bit */ + spd[23] =3D 0x10; /* CAS tcyc */ + spd[25] =3D 0x10; /* CAS tcyc */ + + /* checksum */ + spd[63] =3D 0; + for (i =3D 0; i < 63; i++) { + spd[63] +=3D spd[i]; + } + + /* copy for SMBUS */ + memcpy(eeprom, spd, sizeof(spd_eeprom.contents)); +} + +static void generate_eeprom_serial(uint8_t *eeprom) +{ + int i, pos =3D 0; + uint8_t mac[6] =3D { 0x00 }; + uint8_t sn[5] =3D { 0x01, 0x23, 0x45, 0x67, 0x89 }; + + /* version */ + eeprom[pos++] =3D 0x01; + + /* count */ + eeprom[pos++] =3D 0x02; + + /* MAC address */ + eeprom[pos++] =3D 0x01; /* MAC */ + eeprom[pos++] =3D 0x06; /* length */ + memcpy(&eeprom[pos], mac, sizeof(mac)); + pos +=3D sizeof(mac); + + /* serial number */ + eeprom[pos++] =3D 0x02; /* serial */ + eeprom[pos++] =3D 0x05; /* length */ + memcpy(&eeprom[pos], sn, sizeof(sn)); + pos +=3D sizeof(sn); + + /* checksum */ + eeprom[pos] =3D 0; + for (i =3D 0; i < pos; i++) { + eeprom[pos] +=3D eeprom[i]; + } +} + +/*************************************************************************= ****/ + +static int sam460ex_load_uboot(void) +{ + DriveInfo *dinfo; + BlockBackend *blk =3D NULL; + hwaddr base =3D FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32); + long bios_size =3D FLASH_SIZE; + int fl_sectors; + + dinfo =3D drive_get(IF_PFLASH, 0, 0); + if (dinfo) { + blk =3D blk_by_legacy_dinfo(dinfo); + bios_size =3D blk_getlength(blk); + } + fl_sectors =3D (bios_size + 65535) >> 16; + + if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size, + blk, (64 * 1024), fl_sectors, + 1, 0x89, 0x18, 0x0000, 0x0, 1)) { + fprintf(stderr, "qemu: Error registering flash memory.\n"); + /* XXX: return an error instead? */ + exit(1); + } + + if (!blk) { + /*fprintf(stderr, "No flash image given with the 'pflash' paramete= r," + " using default u-boot image\n");*/ + base =3D UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32); + rom_add_file_fixed(UBOOT_FILENAME, base, -1); + } + + return 0; +} + +static int sam460ex_load_device_tree(hwaddr addr, + uint32_t ramsize, + hwaddr initrd_base, + hwaddr initrd_size, + const char *kernel_cmdline) +{ + int ret =3D -1; + uint32_t mem_reg_property[] =3D { 0, 0, cpu_to_be32(ramsize) }; + char *filename; + int fdt_size; + void *fdt; + uint32_t tb_freq =3D 400000000; + uint32_t clock_freq =3D 400000000; + + filename =3D qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FI= LE); + if (!filename) { + goto out; + } + fdt =3D load_device_tree(filename, &fdt_size); + g_free(filename); + if (fdt =3D=3D NULL) { + goto out; + } + + /* Manipulate device tree in memory. */ + + ret =3D qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, + sizeof(mem_reg_property)); + if (ret < 0) { + fprintf(stderr, "couldn't set /memory/reg\n"); + } + + /* default FDT doesn't have a /chosen node... */ + qemu_fdt_add_subnode(fdt, "/chosen"); + + ret =3D qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", + initrd_base); + if (ret < 0) { + fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); + } + + ret =3D qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + (initrd_base + initrd_size)); + if (ret < 0) { + fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); + } + + ret =3D qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", + kernel_cmdline); + if (ret < 0) { + fprintf(stderr, "couldn't set /chosen/bootargs\n"); + } + + /* Copy data from the host device tree into the guest. Since the guest= can + * directly access the timebase without host involvement, we must expo= se + * the correct frequencies. */ + if (kvm_enabled()) { + tb_freq =3D kvmppc_get_tbfreq(); + clock_freq =3D kvmppc_get_clockfreq(); + } + + qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency", + clock_freq); + qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency", + tb_freq); + + rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); + g_free(fdt); + ret =3D fdt_size; + +out: + + return ret; +} + +/* Create reset TLB entries for BookE, mapping only the flash memory. */ +static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env) +{ + ppcemb_tlb_t *tlb =3D &env->tlb.tlbe[0]; + + /* on reset the flash is mapped by a shadow TLB, + * but since we don't implement them we need to use + * the same values U-Boot will use to avoid a fault. + */ + tlb->attr =3D 0; + tlb->prot =3D PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); + tlb->size =3D 0x10000000; /* up to 0xffffffff */ + tlb->EPN =3D 0xf0000000 & TARGET_PAGE_MASK; + tlb->RPN =3D (0xf0000000 & TARGET_PAGE_MASK) | 0x4; + tlb->PID =3D 0; +} + +/* Create reset TLB entries for BookE, spanning the 32bit addr space. */ +static void mmubooke_create_initial_mapping(CPUPPCState *env, + target_ulong va, + hwaddr pa) +{ + ppcemb_tlb_t *tlb =3D &env->tlb.tlbe[0]; + + tlb->attr =3D 0; + tlb->prot =3D PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4); + tlb->size =3D 1 << 31; /* up to 0x80000000 */ + tlb->EPN =3D va & TARGET_PAGE_MASK; + tlb->RPN =3D pa & TARGET_PAGE_MASK; + tlb->PID =3D 0; +} + +static void main_cpu_reset(void *opaque) +{ + PowerPCCPU *cpu =3D opaque; + CPUPPCState *env =3D &cpu->env; + struct boot_info *bi =3D env->load_info; + + cpu_reset(CPU(cpu)); + + /* either we have a kernel to boot or we jump to U-Boot */ + if (bi->entry !=3D UBOOT_ENTRY) { + env->gpr[1] =3D (16 << 20) - 8; + env->gpr[3] =3D FDT_ADDR; + + fprintf(stderr, "cpu reset: kernel entry %x\n", bi->entry); + env->nip =3D bi->entry; + + /* Create a mapping for the kernel. */ + mmubooke_create_initial_mapping(env, 0, 0); + env->gpr[6] =3D tswap32(EPAPR_MAGIC); + env->gpr[7] =3D (16 << 20) - 8; /*bi->ima_size;*/ + + } else { + env->nip =3D UBOOT_ENTRY; + mmubooke_create_initial_mapping_uboot(env); + fprintf(stderr, "cpu reset: U-Boot entry\n"); + } +} + +static void sam460ex_init(MachineState *machine) +{ + MemoryRegion *address_space_mem =3D get_system_memory(); + MemoryRegion *isa =3D g_new(MemoryRegion, 1); + MemoryRegion *ram_memories =3D g_new(MemoryRegion, SDRAM_NR_BANKS); + hwaddr ram_bases[SDRAM_NR_BANKS]; + hwaddr ram_sizes[SDRAM_NR_BANKS]; + MemoryRegion *l2cache_ram =3D g_new(MemoryRegion, 1); + qemu_irq *irqs, *uic[4]; + PCIBus *pci_bus; + PowerPCCPU *cpu; + CPUPPCState *env; + PPC4xxI2CState *i2c[2]; + hwaddr entry =3D UBOOT_ENTRY; + hwaddr loadaddr =3D 0; + target_long initrd_size =3D 0; + DeviceState *dev; + SysBusDevice *sbdev; + int success; + int i; + struct boot_info *boot_info; + const size_t smbus_eeprom_size =3D 8 * 256; + uint8_t *smbus_eeprom_buf =3D g_malloc0(smbus_eeprom_size); + + /* Setup CPU. */ + if (machine->cpu_model =3D=3D NULL) { + machine->cpu_model =3D "460EX"; + } + cpu =3D cpu_ppc_init(machine->cpu_model); + if (cpu =3D=3D NULL) { + fprintf(stderr, "Unable to initialize CPU!\n"); + exit(1); + } + env =3D &cpu->env; + + qemu_register_reset(main_cpu_reset, cpu); + boot_info =3D g_malloc0(sizeof(*boot_info)); + env->load_info =3D boot_info; + + ppc_booke_timers_init(cpu, 50000000, 0); + ppc_dcr_init(env, NULL, NULL); + + /* PLB arbitrer */ + ppc4xx_plb_init(env); + + /* interrupt controllers */ + irqs =3D g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB); + irqs[PPCUIC_OUTPUT_INT] =3D ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT= _INT]; + irqs[PPCUIC_OUTPUT_CINT] =3D ((qemu_irq *)env->irq_inputs)[PPC40x_INPU= T_CINT]; + uic[0] =3D ppcuic_init(env, irqs, 0x0C0, 0, 1); + uic[1] =3D ppcuic_init(env, &uic[0][30], 0x0D0, 0, 1); + uic[2] =3D ppcuic_init(env, &uic[0][10], 0x0E0, 0, 1); + uic[3] =3D ppcuic_init(env, &uic[0][16], 0x0F0, 0, 1); + + /* SDRAM controller */ + memset(ram_bases, 0, sizeof(ram_bases)); + memset(ram_sizes, 0, sizeof(ram_sizes)); + /* put all RAM on first bank because board has one slot + * and firmware only checks that */ + machine->ram_size =3D ppc4xx_sdram_adjust(machine->ram_size, + 1/*SDRAM_NR_BANKS*/, + ram_memories, + ram_bases, ram_sizes, + ppc460ex_sdram_bank_sizes); +#ifdef DEBUG_SDRAM + printf("RAMSIZE %dMB\n", (int)(machine->ram_size / M_BYTE)); +#endif + + /* XXX does 460EX have ECC interrupts? */ + ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories, + ram_bases, ram_sizes, 1); + + /* generate SPD EEPROM data */ + for (i =3D 0; i < SDRAM_NR_BANKS; i++) { +#ifdef DEBUG_SDRAM + printf("bank %d: %" HWADDR_PRIx "\n", i, ram_sizes[i]); +#endif + generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]); + } + generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]); + generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]); + + /* IIC controllers */ + dev =3D sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]); + i2c[0] =3D PPC4xx_I2C(dev); + object_property_set_bool(OBJECT(dev), true, "realized", NULL); + smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size); + g_free(smbus_eeprom_buf); + + dev =3D sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]); + i2c[1] =3D PPC4xx_I2C(dev); + + /* External bus controller */ + ppc405_ebc_init(env); + + /* CPR */ + ppc4xx_cpr_init(env); + + /* PLB to AHB bridge */ + ppc4xx_ahb_init(env); + + /* System DCRs */ + ppc4xx_sdr_init(env); + + /* MAL */ + ppc4xx_mal_init(env, 4, 16, &uic[2][3]); + + /* 256K of L2 cache as memory */ + ppc4xx_l2sram_init(env); + /* FIXME: remove this after fixing l2sram mapping above? */ + memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 <<= 10, + &error_abort); + memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_= ram); + + /* USB */ + sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]); + dev =3D qdev_create(NULL, "sysbus-ohci"); + qdev_prop_set_string(dev, "masterbus", "usb-bus.0"); + qdev_prop_set_uint32(dev, "num-ports", 6); + qdev_init_nofail(dev); + sbdev =3D SYS_BUS_DEVICE(dev); + sysbus_mmio_map(sbdev, 0, 0x4bffd0000); + sysbus_connect_irq(sbdev, 0, uic[2][30]); + usb_create_simple(usb_bus_find(-1), "usb-kbd"); + usb_create_simple(usb_bus_find(-1), "usb-mouse"); + + /* PCI bus */ + ppc460ex_pcie_init(env); + /*XXX: FIXME: is this correct? */ + dev =3D sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000, + uic[1][0], uic[1][20], uic[1][21], uic[1][= 22], + NULL); + pci_bus =3D (PCIBus *)qdev_get_child_bus(dev, "pci.0"); + if (!pci_bus) { + fprintf(stderr, "couldn't create PCI controller!\n"); + exit(1); + } + memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), + 0, 0x10000); + memory_region_add_subregion(get_system_memory(), 0xc08000000, isa); + + /* PCI devices */ + pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501"); + /* SoC has a single SATA port but we don't emulate that yet + * However, firmware and usual clients have driver for SiI311x + * so add one for convenience by default */ + pci_create_simple(pci_bus, -1, "sii3112"); + + /* SoC has 4 UARTs + * but board has only one wired and two are present in fdt */ + if (serial_hds[0] !=3D NULL) { + serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1], + PPC_SERIAL_MM_BAUDBASE, serial_hds[0], + DEVICE_BIG_ENDIAN); + } + if (serial_hds[1] !=3D NULL) { + serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1], + PPC_SERIAL_MM_BAUDBASE, serial_hds[1], + DEVICE_BIG_ENDIAN); + } + + /* Load U-Boot image. */ + if (!machine->kernel_filename) { + success =3D sam460ex_load_uboot(); + if (success < 0) { + fprintf(stderr, "qemu: could not load firmware\n"); + exit(1); + } + } + + /* Load kernel. */ + if (machine->kernel_filename) { + success =3D load_uimage(machine->kernel_filename, &entry, &loadadd= r, NULL, + NULL, NULL); + fprintf(stderr, "load_uimage: %d\n", success); + if (success < 0) { + uint64_t elf_entry, elf_lowaddr; + + success =3D load_elf(machine->kernel_filename, NULL, NULL, &el= f_entry, + &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, = 0); + fprintf(stderr, "load_elf: %d\n", success); + entry =3D elf_entry; + loadaddr =3D elf_lowaddr; + } + /* XXX try again as binary */ + if (success < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + machine->kernel_filename); + exit(1); + } + } + + /* Load initrd. */ + if (machine->initrd_filename) { + initrd_size =3D load_image_targphys(machine->initrd_filename, + RAMDISK_ADDR, + machine->ram_size - RAMDISK_ADDR= ); + fprintf(stderr, "load_image: %d\n", initrd_size); + if (initrd_size < 0) { + fprintf(stderr, "qemu: could not load ram disk '%s' at %x\n", + machine->initrd_filename, RAMDISK_ADDR); + exit(1); + } + } + + /* If we're loading a kernel directly, we must load the device tree to= o. */ + if (machine->kernel_filename) { + int dt_size; + + dt_size =3D sam460ex_load_device_tree(FDT_ADDR, machine->ram_size, + RAMDISK_ADDR, initrd_size, + machine->kernel_cmdline); + if (dt_size < 0) { + fprintf(stderr, "couldn't load device tree\n"); + exit(1); + } + + boot_info->dt_base =3D FDT_ADDR; + boot_info->dt_size =3D dt_size; + } + + boot_info->entry =3D entry; +} + +static void sam460ex_machine_init(MachineClass *mc) +{ + mc->desc =3D "aCube Sam460ex"; + mc->init =3D sam460ex_init; + mc->default_ram_size =3D 512 * M_BYTE; +} + +DEFINE_MACHINE("sam460ex", sam460ex_machine_init) diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h index 4d23c80..3f7b988 100644 --- a/include/hw/pci/pcie_host.h +++ b/include/hw/pci/pcie_host.h @@ -65,7 +65,7 @@ void pcie_host_mmcfg_update(PCIExpressHost *e, * bit 12 - 14: function number * bit 0 - 11: offset in configuration space of a given device */ -#define PCIE_MMCFG_SIZE_MAX (1ULL << 28) +#define PCIE_MMCFG_SIZE_MAX (1ULL << 29) #define PCIE_MMCFG_SIZE_MIN (1ULL << 20) #define PCIE_MMCFG_BUS_BIT 20 #define PCIE_MMCFG_BUS_MASK 0x1ff --=20 2.7.4