* [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL
@ 2008-12-09 1:46 Salvatore Lionetti
2008-12-09 16:57 ` Hollis Blanchard
0 siblings, 1 reply; 5+ messages in thread
From: Salvatore Lionetti @ 2008-12-09 1:46 UTC (permalink / raw)
To: qemu-devel; +Cc: hollis
Hi
This set of patch try to full support hw present in 'walnut' board.
http://elinux.org/DHT-Walnut
The fw used to successfully verify board is u-boot-1.3.4.
The only component not tested is PCI: perhaps should be a good start point for Hollis 's recent work, which i thanks for previous code review.
1) IIC: new eeprom device, full emulation of 4xx master core
MAL: Moved interface so can be shared with other modules
4xx boards: move MAL & IIC common part between ppc4xx cpu
add a list of created devices, so machine 2 phase creation is allowed,
Warning: to compile:
- comment line 'ppc4xx_emac_init(...)' in module hw/ppc405_boards.c
- rename ppc405ep_init(args) in ppc405xp_init("405ep", args, NULL)
Files changed:
- Makefile.target
- Makefile
- hw/ppc405_uc.c
- hw/ppc4xx_devs.c
- hw/ppc405.h
- hw/i2c.h
- hw/iic_eeprom.c (Added)
- hw/ppc4xx.h
Index: Makefile.target
===================================================================
--- Makefile.target (revision 5720)
+++ Makefile.target (working copy)
@@ -668,7 +668,7 @@
ifeq ($(TARGET_BASE_ARCH), ppc)
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
# shared objects
-OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o
+OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o i2c.o openpic.o
# PREP target
OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
OBJS+= prep_pci.o ppc_prep.o
@@ -679,7 +679,7 @@
# NewWorld PowerMac
OBJS+= unin_pci.o ppc_chrp.o
# PowerPC 4xx boards
-OBJS+= pflash_cfi02.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
+OBJS+= pflash_cfi02.o ppc4xx_emac.o ppc4xx_devs.o ppc405_uc.o ppc405_boards.o
endif
ifeq ($(TARGET_BASE_ARCH), mips)
OBJS+= mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
Index: Makefile
===================================================================
--- Makefile (revision 5720)
+++ Makefile (working copy)
@@ -69,7 +69,7 @@
OBJS+=readline.o console.o
OBJS+=irq.o
-OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
+OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o iic_eeprom.o
OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
OBJS+=tmp105.o lm832x.o
OBJS+=scsi-disk.o cdrom.o
Index: hw/ppc405_uc.c
===================================================================
--- hw/ppc405_uc.c (revision 5720)
+++ hw/ppc405_uc.c (working copy)
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include <assert.h>
#include "hw.h"
#include "ppc.h"
#include "ppc405.h"
@@ -28,13 +29,17 @@
#include "qemu-timer.h"
#include "sysemu.h"
#include "qemu-log.h"
+#include "net.h" /* To have nd_table.h */
+extern int loglevel;
+extern FILE *logfile;
+
#define DEBUG_OPBA
#define DEBUG_SDRAM
-#define DEBUG_GPIO
+/*#define DEBUG_GPIO*/
#define DEBUG_SERIAL
#define DEBUG_OCM
-//#define DEBUG_I2C
+/*#define DEBUG_I2C*/
#define DEBUG_GPT
#define DEBUG_MAL
#define DEBUG_CLOCKS
@@ -835,6 +840,8 @@
ret = 0x00000000;
break;
}
+ printf("Read ebc[%d]=>%x\n", ebc->addr, ret);
+ break;
default:
ret = 0x00000000;
break;
@@ -853,6 +860,7 @@
ebc->addr = val;
break;
case EBC0_CFGDATA:
+ printf("Write ebc[%d]=>%x\n", ebc->addr, val);
switch (ebc->addr) {
case 0x00: /* B0CR */
break;
@@ -1395,252 +1403,6 @@
}
/*****************************************************************************/
-/* I2C controller */
-typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
-struct ppc4xx_i2c_t {
- target_phys_addr_t base;
- qemu_irq irq;
- 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, target_phys_addr_t addr)
-{
- ppc4xx_i2c_t *i2c;
- uint32_t ret;
-
-#ifdef DEBUG_I2C
- printf("%s: addr " PADDRX "\n", __func__, addr);
-#endif
- i2c = opaque;
- switch (addr - i2c->base) {
- case 0x00:
- // i2c_readbyte(&i2c->mdata);
- ret = i2c->mdata;
- break;
- case 0x02:
- ret = i2c->sdata;
- break;
- case 0x04:
- ret = i2c->lmadr;
- break;
- case 0x05:
- ret = i2c->hmadr;
- break;
- case 0x06:
- ret = i2c->cntl;
- break;
- case 0x07:
- ret = i2c->mdcntl;
- break;
- case 0x08:
- ret = i2c->sts;
- break;
- case 0x09:
- ret = i2c->extsts;
- break;
- case 0x0A:
- ret = i2c->lsadr;
- break;
- case 0x0B:
- ret = i2c->hsadr;
- break;
- case 0x0C:
- ret = i2c->clkdiv;
- break;
- case 0x0D:
- ret = i2c->intrmsk;
- break;
- case 0x0E:
- ret = i2c->xfrcnt;
- break;
- case 0x0F:
- ret = i2c->xtcntlss;
- break;
- case 0x10:
- ret = i2c->directcntl;
- break;
- default:
- ret = 0x00;
- break;
- }
-#ifdef DEBUG_I2C
- printf("%s: addr " PADDRX " %02" PRIx32 "\n", __func__, addr, ret);
-#endif
-
- return ret;
-}
-
-static void ppc4xx_i2c_writeb (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- ppc4xx_i2c_t *i2c;
-
-#ifdef DEBUG_I2C
- printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
-#endif
- i2c = opaque;
- switch (addr - i2c->base) {
- case 0x00:
- i2c->mdata = value;
- // i2c_sendbyte(&i2c->mdata);
- break;
- case 0x02:
- i2c->sdata = value;
- break;
- case 0x04:
- i2c->lmadr = value;
- break;
- case 0x05:
- i2c->hmadr = value;
- break;
- case 0x06:
- i2c->cntl = value;
- break;
- case 0x07:
- i2c->mdcntl = value & 0xDF;
- break;
- case 0x08:
- i2c->sts &= ~(value & 0x0A);
- break;
- case 0x09:
- i2c->extsts &= ~(value & 0x8F);
- break;
- case 0x0A:
- i2c->lsadr = value;
- break;
- case 0x0B:
- i2c->hsadr = value;
- break;
- case 0x0C:
- i2c->clkdiv = value;
- break;
- case 0x0D:
- i2c->intrmsk = value;
- break;
- case 0x0E:
- i2c->xfrcnt = value & 0x77;
- break;
- case 0x0F:
- i2c->xtcntlss = value;
- break;
- case 0x10:
- i2c->directcntl = value & 0x7;
- break;
- }
-}
-
-static uint32_t ppc4xx_i2c_readw (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret;
-
-#ifdef DEBUG_I2C
- printf("%s: addr " PADDRX "\n", __func__, addr);
-#endif
- ret = ppc4xx_i2c_readb(opaque, addr) << 8;
- ret |= ppc4xx_i2c_readb(opaque, addr + 1);
-
- return ret;
-}
-
-static void ppc4xx_i2c_writew (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
- printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
-#endif
- ppc4xx_i2c_writeb(opaque, addr, value >> 8);
- ppc4xx_i2c_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t ppc4xx_i2c_readl (void *opaque, target_phys_addr_t addr)
-{
- uint32_t ret;
-
-#ifdef DEBUG_I2C
- printf("%s: addr " PADDRX "\n", __func__, addr);
-#endif
- ret = ppc4xx_i2c_readb(opaque, addr) << 24;
- ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
- ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
- ret |= ppc4xx_i2c_readb(opaque, addr + 3);
-
- return ret;
-}
-
-static void ppc4xx_i2c_writel (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
- printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, 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 CPUReadMemoryFunc *i2c_read[] = {
- &ppc4xx_i2c_readb,
- &ppc4xx_i2c_readw,
- &ppc4xx_i2c_readl,
-};
-
-static CPUWriteMemoryFunc *i2c_write[] = {
- &ppc4xx_i2c_writeb,
- &ppc4xx_i2c_writew,
- &ppc4xx_i2c_writel,
-};
-
-static void ppc4xx_i2c_reset (void *opaque)
-{
- ppc4xx_i2c_t *i2c;
-
- i2c = opaque;
- i2c->mdata = 0x00;
- i2c->sdata = 0x00;
- i2c->cntl = 0x00;
- i2c->mdcntl = 0x00;
- i2c->sts = 0x00;
- i2c->extsts = 0x00;
- i2c->clkdiv = 0x00;
- i2c->xfrcnt = 0x00;
- i2c->directcntl = 0x0F;
-}
-
-void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio,
- target_phys_addr_t offset, qemu_irq irq)
-{
- ppc4xx_i2c_t *i2c;
-
- i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t));
- if (i2c != NULL) {
- i2c->base = offset;
- i2c->irq = irq;
- ppc4xx_i2c_reset(i2c);
-#ifdef DEBUG_I2C
- printf("%s: offset " PADDRX "\n", __func__, offset);
-#endif
- ppc4xx_mmio_register(env, mmio, offset, 0x011,
- i2c_read, i2c_write, i2c);
- qemu_register_reset(ppc4xx_i2c_reset, i2c);
- }
-}
-
-/*****************************************************************************/
/* General purpose timers */
typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
struct ppc4xx_gpt_t {
@@ -1925,271 +1687,6 @@
}
/*****************************************************************************/
-/* MAL */
-enum {
- MAL0_CFG = 0x180,
- MAL0_ESR = 0x181,
- MAL0_IER = 0x182,
- MAL0_TXCASR = 0x184,
- MAL0_TXCARR = 0x185,
- MAL0_TXEOBISR = 0x186,
- MAL0_TXDEIR = 0x187,
- MAL0_RXCASR = 0x190,
- MAL0_RXCARR = 0x191,
- MAL0_RXEOBISR = 0x192,
- MAL0_RXDEIR = 0x193,
- MAL0_TXCTP0R = 0x1A0,
- MAL0_TXCTP1R = 0x1A1,
- MAL0_TXCTP2R = 0x1A2,
- MAL0_TXCTP3R = 0x1A3,
- MAL0_RXCTP0R = 0x1C0,
- MAL0_RXCTP1R = 0x1C1,
- MAL0_RCBS0 = 0x1E0,
- MAL0_RCBS1 = 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 target_ulong dcr_read_mal (void *opaque, int dcrn)
-{
- ppc40x_mal_t *mal;
- target_ulong ret;
-
- mal = opaque;
- switch (dcrn) {
- case MAL0_CFG:
- ret = mal->cfg;
- break;
- case MAL0_ESR:
- ret = mal->esr;
- break;
- case MAL0_IER:
- ret = mal->ier;
- break;
- case MAL0_TXCASR:
- ret = mal->txcasr;
- break;
- case MAL0_TXCARR:
- ret = mal->txcarr;
- break;
- case MAL0_TXEOBISR:
- ret = mal->txeobisr;
- break;
- case MAL0_TXDEIR:
- ret = mal->txdeir;
- break;
- case MAL0_RXCASR:
- ret = mal->rxcasr;
- break;
- case MAL0_RXCARR:
- ret = mal->rxcarr;
- break;
- case MAL0_RXEOBISR:
- ret = mal->rxeobisr;
- break;
- case MAL0_RXDEIR:
- ret = mal->rxdeir;
- break;
- case MAL0_TXCTP0R:
- ret = mal->txctpr[0];
- break;
- case MAL0_TXCTP1R:
- ret = mal->txctpr[1];
- break;
- case MAL0_TXCTP2R:
- ret = mal->txctpr[2];
- break;
- case MAL0_TXCTP3R:
- ret = mal->txctpr[3];
- break;
- case MAL0_RXCTP0R:
- ret = mal->rxctpr[0];
- break;
- case MAL0_RXCTP1R:
- ret = mal->rxctpr[1];
- break;
- case MAL0_RCBS0:
- ret = mal->rcbs[0];
- break;
- case MAL0_RCBS1:
- ret = mal->rcbs[1];
- break;
- default:
- ret = 0;
- break;
- }
-
- return ret;
-}
-
-static void dcr_write_mal (void *opaque, int dcrn, target_ulong val)
-{
- ppc40x_mal_t *mal;
- int idx;
-
- mal = opaque;
- switch (dcrn) {
- case MAL0_CFG:
- if (val & 0x80000000)
- ppc40x_mal_reset(mal);
- mal->cfg = val & 0x00FFC087;
- break;
- case MAL0_ESR:
- /* Read/clear */
- mal->esr &= ~val;
- break;
- case MAL0_IER:
- mal->ier = val & 0x0000001F;
- break;
- case MAL0_TXCASR:
- mal->txcasr = val & 0xF0000000;
- break;
- case MAL0_TXCARR:
- mal->txcarr = val & 0xF0000000;
- break;
- case MAL0_TXEOBISR:
- /* Read/clear */
- mal->txeobisr &= ~val;
- break;
- case MAL0_TXDEIR:
- /* Read/clear */
- mal->txdeir &= ~val;
- break;
- case MAL0_RXCASR:
- mal->rxcasr = val & 0xC0000000;
- break;
- case MAL0_RXCARR:
- mal->rxcarr = val & 0xC0000000;
- break;
- case MAL0_RXEOBISR:
- /* Read/clear */
- mal->rxeobisr &= ~val;
- break;
- case MAL0_RXDEIR:
- /* Read/clear */
- mal->rxdeir &= ~val;
- break;
- case MAL0_TXCTP0R:
- idx = 0;
- goto update_tx_ptr;
- case MAL0_TXCTP1R:
- idx = 1;
- goto update_tx_ptr;
- case MAL0_TXCTP2R:
- idx = 2;
- goto update_tx_ptr;
- case MAL0_TXCTP3R:
- idx = 3;
- update_tx_ptr:
- mal->txctpr[idx] = val;
- break;
- case MAL0_RXCTP0R:
- idx = 0;
- goto update_rx_ptr;
- case MAL0_RXCTP1R:
- idx = 1;
- update_rx_ptr:
- mal->rxctpr[idx] = val;
- break;
- case MAL0_RCBS0:
- idx = 0;
- goto update_rx_size;
- case MAL0_RCBS1:
- idx = 1;
- update_rx_size:
- mal->rcbs[idx] = val & 0x000000FF;
- break;
- }
-}
-
-static void ppc40x_mal_reset (void *opaque)
-{
- ppc40x_mal_t *mal;
-
- mal = opaque;
- mal->cfg = 0x0007C000;
- mal->esr = 0x00000000;
- mal->ier = 0x00000000;
- mal->rxcasr = 0x00000000;
- mal->rxdeir = 0x00000000;
- mal->rxeobisr = 0x00000000;
- mal->txcasr = 0x00000000;
- mal->txdeir = 0x00000000;
- mal->txeobisr = 0x00000000;
-}
-
-void ppc405_mal_init (CPUState *env, qemu_irq irqs[4])
-{
- ppc40x_mal_t *mal;
- int i;
-
- mal = qemu_mallocz(sizeof(ppc40x_mal_t));
- if (mal != NULL) {
- for (i = 0; i < 4; i++)
- mal->irqs[i] = irqs[i];
- ppc40x_mal_reset(mal);
- 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 (CPUState *env)
{
@@ -2234,6 +1731,7 @@
qemu_system_reset_request();
}
+/* ->halted=1 seem that loose memory. */
void store_40x_dbcr0 (CPUState *env, uint32_t val)
{
switch ((val >> 28) & 0x3) {
@@ -2541,12 +2039,14 @@
CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
target_phys_addr_t ram_sizes[4],
uint32_t sysclk, qemu_irq **picp,
- ram_addr_t *offsetp, int do_init)
+ ram_addr_t *offsetp, int do_init,
+ ppc4xx_devsL *devsL)
{
clk_setup_t clk_setup[PPC405CR_CLK_NB];
qemu_irq dma_irqs[4];
CPUState *env;
ppc4xx_mmio_t *mmio;
+ ppc4xx_i2c_t *i2c;
qemu_irq *pic, *irqs;
ram_addr_t offset;
int i;
@@ -2591,13 +2091,16 @@
ppc405_serial_init(env, mmio, 0x400, pic[1], serial_hds[1]);
}
/* IIC controller */
- ppc405_i2c_init(env, mmio, 0x500, pic[2]);
+ i2c = ppc4xx_i2c_init(env, mmio, 0x500, pic[2]);
/* GPIO */
ppc405_gpio_init(env, mmio, 0x700);
/* CPU control */
ppc405cr_cpc_init(env, clk_setup, sysclk);
*offsetp = offset;
+ if (devsL) {
+ devsL->i2c0 = i2c;
+ }
return env;
}
@@ -2891,22 +2394,28 @@
}
}
-CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
+CPUState *ppc405xp_init (const char* cpu_model,
+ target_phys_addr_t ram_bases[2],
target_phys_addr_t ram_sizes[2],
uint32_t sysclk, qemu_irq **picp,
- ram_addr_t *offsetp, int do_init)
+ ram_addr_t *offsetp, int do_init,
+ struct ppc4xx_devsL *devsL)
{
clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
- qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
+ qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[5];
CPUState *env;
ppc4xx_mmio_t *mmio;
qemu_irq *pic, *irqs;
ram_addr_t offset;
+ ppc4xx_mal_t *mal;
+ ppc4xx_i2c_t *i2c;
int i;
memset(clk_setup, 0, sizeof(clk_setup));
/* init CPUs */
- env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
+ if (!cpu_model)
+ cpu_model = "405ep";
+ env = ppc4xx_init(cpu_model, &clk_setup[PPC405EP_CPU_CLK],
&tlb_clk_setup, sysclk);
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
@@ -2942,7 +2451,7 @@
dma_irqs[3] = pic[8];
ppc405_dma_init(env, dma_irqs);
/* IIC controller */
- ppc405_i2c_init(env, mmio, 0x500, pic[2]);
+ i2c = ppc4xx_i2c_init(env, mmio, 0x500, pic[2]);
/* GPIO */
ppc405_gpio_init(env, mmio, 0x700);
/* Serial ports */
@@ -2965,16 +2474,21 @@
/* PCI */
/* Uses pic[3], pic[16], pic[18] */
/* MAL */
- mal_irqs[0] = pic[11];
- mal_irqs[1] = pic[12];
- mal_irqs[2] = pic[13];
- mal_irqs[3] = pic[14];
- ppc405_mal_init(env, mal_irqs);
- /* Ethernet */
+ mal_irqs[0] = pic[11]; /* TX end of buffer */
+ mal_irqs[1] = pic[12]; /* RX end of buffer */
+ mal_irqs[2] = pic[13]; /* TX data error */
+ mal_irqs[3] = pic[14]; /* RX data error */
+ mal_irqs[4] = pic[10]; /* Mal System error */
+ mal = ppc4xx_mal_init(env, mal_irqs);
+ /* EMAC (Ethernet Media Access Controller) */
+ ppc4xx_emac_init(env, mmio, 0x800, &nd_table[0], mal);
/* Uses pic[9], pic[15], pic[17] */
/* CPU control */
ppc405ep_cpc_init(env, clk_setup, sysclk);
*offsetp = offset;
+ if (devsL) {
+ devsL->i2c0 = i2c;
+ }
return env;
}
Index: hw/ppc4xx_devs.c
===================================================================
--- hw/ppc4xx_devs.c (revision 5720)
+++ hw/ppc4xx_devs.c (working copy)
@@ -21,15 +21,19 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include <assert.h>
#include "hw.h"
#include "ppc.h"
#include "ppc4xx.h"
#include "sysemu.h"
#include "qemu-log.h"
+#include "qemu-timer.h"
//#define DEBUG_MMIO
//#define DEBUG_UNASSIGNED
#define DEBUG_UIC
+//#define DEBUG_I2C
+#define I2C_USE_EXISTING 1
/*****************************************************************************/
/* Generic PowerPC 4xx processor instanciation */
@@ -296,10 +300,10 @@
cr = uic->uicsr & uic->uicer & uic->uiccr;
#ifdef DEBUG_UIC
if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: uicsr %08" PRIx32 " uicer %08" PRIx32
+ fprintf(logfile, "%s %" PRIu64 ": uicsr %08" PRIx32 " uicer %08" PRIx32
" uiccr %08" PRIx32 "\n"
" %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
- __func__, uic->uicsr, uic->uicer, uic->uiccr,
+ __func__, qemu_get_clock(rt_clock), uic->uicsr, uic->uicer, uic->uiccr,
uic->uicsr & uic->uicer, ir, cr);
}
#endif
@@ -366,9 +370,9 @@
mask = 1 << (31-irq_num);
#ifdef DEBUG_UIC
if (loglevel & CPU_LOG_INT) {
- fprintf(logfile, "%s: irq %d level %d uicsr %08" PRIx32
+ fprintf(logfile, "%s %" PRIu64 ": irq %d level %d uicsr %08" PRIx32
" mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
- __func__, irq_num, level,
+ __func__, qemu_get_clock(rt_clock), irq_num, level,
uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
}
#endif
@@ -532,3 +536,756 @@
return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
}
+
+
+/*****************************************************************************/
+/* MAL */
+/* TODO: INTEGRATION IN PROGRESS
+ * Tested successfully on
+ * - 405GPr(OSE/Proprietary NSN 4G Board),
+ * - 405EP (u-boot-1.1.6/DHT Walnut),
+ *
+ * Modified (need test) for
+ * - 440ep.
+ *
+ * There is a number of variant among PowerPC4xx uP.
+ * However basic work can be reused.
+ *
+ * VARIANT KNOWN:
+ *
+ * 440ep
+ * serial device register: SDR0_MAL{R,T}x{BL,BS}
+ * DCR @reset
+ * SDR0_MALRBL, 2A0 0x55550000 #word to transfer in a single transact.
+ * SDR0_MALRBS, 2E0 0xF0000000
+ * SDR0_MALTBL, 280 0x55550000 #Reserver
+ * SDR0_MALTBS, 2C0 0xF0000000
+ * 4 TX channel, 2 RX channel
+ * MAL0_RXCTP1R (already present)
+ * MAL0_RCBS1 (already present)
+ *
+ *
+ *
+ * number of tx channel {1, 2}
+ * 440 has txbattr register
+ * 440SPE, 440EPX, 440GRX have different content of IER. ESR
+ * Interrupt enable register: all such cause muxed on SERR
+Common
+#define MAL_IER_DE 0x00000010 * Descriptor erro
+#define MAL_IER_TE 0x00000004 * OPB Time Out error
+#define MAL_IER_OPBE 0x00000002 * OPB Slave error
+#define MAL_IER_PLBE 0x00000001 * PLB Bus error
+
+440SPE, 440EPX, 440GRX
+#define MAL_IER_PT 0x00000080
+#define MAL_IER_PRE 0x00000040
+#define MAL_IER_PWE 0x00000020
+
+Other
+#define MAL_IER_NE 0x00000008 * OPB Non word error
+ *
+ *
+ *
+ * TODO:
+ * NO ERRATA IS IMPLEMENTED HERE!
+ * Es PPC440GP_RB: Errata 1.12: MAL_1 -- Disable MAL bursting
+ */
+
+enum {
+ MAL0_CFG = 0x180,
+ MAL0_ESR = 0x181,
+ MAL0_IER = 0x182,
+ MAL0_TXCASR = 0x184,
+ MAL0_TXCARR = 0x185,
+ MAL0_TXEOBISR = 0x186,
+ MAL0_TXDEIR = 0x187,
+ MAL0_RXCASR = 0x190,
+ MAL0_RXCARR = 0x191,
+ MAL0_RXEOBISR = 0x192,
+ MAL0_RXDEIR = 0x193,
+ MAL0_TXCTP0R = 0x1A0,
+ MAL0_TXCTP1R = 0x1A1,
+ MAL0_TXCTP2R = 0x1A2,
+ MAL0_TXCTP3R = 0x1A3,
+ MAL0_RXCTP0R = 0x1C0,
+ MAL0_RXCTP1R = 0x1C1,
+ MAL0_RCBS0 = 0x1E0,
+ MAL0_RCBS1 = 0x1E1,
+ /* For ppc440ep System device control */
+ SDR0_MALTBL = 0x280,
+ SDR0_MALRBL = 0x2A0,
+ SDR0_MALTBS = 0x2C0,
+ SDR0_MALRBS = 0x2E0,
+};
+
+static void ppc4xx_mal_reset (void *opaque);
+
+static target_ulong dcr_read_mal (void *opaque, int dcrn)
+{
+ ppc4xx_mal_t *mal;
+ target_ulong ret;
+
+ mal = opaque;
+ switch (dcrn) {
+ case MAL0_CFG:
+ ret = mal->cfg;
+ break;
+ case MAL0_ESR:
+ ret = mal->esr;
+ break;
+ case MAL0_IER:
+ ret = mal->ier;
+ break;
+ case MAL0_TXCASR:
+ ret = mal->txcasr;
+ break;
+ case MAL0_TXCARR:
+ ret = mal->txcarr;
+ break;
+ case MAL0_TXEOBISR:
+ ret = mal->txeobisr;
+ break;
+ case MAL0_TXDEIR:
+ ret = mal->txdeir;
+ break;
+ case MAL0_RXCASR:
+ ret = mal->rxcasr;
+ break;
+ case MAL0_RXCARR:
+ ret = mal->rxcarr;
+ break;
+ case MAL0_RXEOBISR:
+ ret = mal->rxeobisr;
+ break;
+ case MAL0_RXDEIR:
+ ret = mal->rxdeir;
+ break;
+ case MAL0_TXCTP0R:
+ ret = mal->txctpr[0];
+ break;
+ case MAL0_TXCTP1R:
+ ret = mal->txctpr[1];
+ break;
+ case MAL0_TXCTP2R:
+ ret = mal->txctpr[2];
+ break;
+ case MAL0_TXCTP3R:
+ ret = mal->txctpr[3];
+ break;
+ case MAL0_RXCTP0R:
+ ret = mal->rxctpr[0];
+ break;
+ case MAL0_RXCTP1R:
+ ret = mal->rxctpr[1];
+ break;
+ case MAL0_RCBS0:
+ ret = mal->rcbs[0];
+ break;
+ case MAL0_RCBS1:
+ ret = mal->rcbs[1];
+ break;
+ case SDR0_MALTBL:
+ ret = mal->tbl;
+ break;
+ case SDR0_MALRBL:
+ ret = mal->rbl;
+ break;
+ case SDR0_MALTBS:
+ ret = mal->tbs;
+ break;
+ case SDR0_MALRBS:
+ ret = mal->rbs;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static void dcr_write_mal (void *opaque, int dcrn, target_ulong val)
+{
+ ppc4xx_mal_t *mal;
+ int idx;
+
+ mal = opaque;
+ switch (dcrn) {
+ case MAL0_CFG:
+ if (val & 0x80000000)
+ ppc4xx_mal_reset(mal);
+ mal->cfg = val & 0x00FFC087;
+ break;
+ case MAL0_ESR:
+ /* Read/clear */
+ mal->esr &= ~val;
+ break;
+ case MAL0_IER:
+ mal->ier = val & 0x0000001F;
+ break;
+ case MAL0_TXCASR:
+ mal->txcasr = val & 0xF0000000;
+ break;
+ case MAL0_TXCARR:
+ mal->txcarr = val & 0xF0000000;
+ break;
+ case MAL0_TXEOBISR:
+ /* Read/clear TODO SEPARATE CHANNEL */
+ if (mal->txeobisr & val & 0xC0000000) {
+ mal->txeobisr &= ~val;
+ qemu_irq_lower(mal->txeob);
+ }
+ mal->txeobisr &= ~val;
+ break;
+ case MAL0_TXDEIR:
+ /* Read/clear */
+ mal->txdeir &= ~val;
+ break;
+ case MAL0_RXCASR:
+ mal->rxcasr = val & ~0xC0000000; /* Active Set immediately rx channel */
+ break;
+ case MAL0_RXCARR:
+ mal->rxcarr = val & 0xC0000000;
+ break;
+ case MAL0_RXEOBISR:
+ /* Read/clear */
+ if (mal->rxeobisr & val & 0x80000000) {
+ mal->rxeobisr &= ~val;
+ qemu_irq_lower(mal->rxeob);
+ }
+ mal->rxeobisr &= ~val;
+ break;
+ case MAL0_RXDEIR:
+ /* Read/clear */
+ mal->rxdeir &= ~val;
+ break;
+ case MAL0_TXCTP0R:
+ idx = 0;
+ goto update_tx_ptr;
+ case MAL0_TXCTP1R:
+ idx = 1;
+ goto update_tx_ptr;
+ case MAL0_TXCTP2R:
+ idx = 2;
+ goto update_tx_ptr;
+ case MAL0_TXCTP3R:
+ idx = 3;
+ update_tx_ptr:
+ mal->txctpr[idx] = val;
+ break;
+ case MAL0_RXCTP0R:
+ idx = 0;
+ goto update_rx_ptr;
+ case MAL0_RXCTP1R:
+ idx = 1;
+ update_rx_ptr:
+ mal->rxctpr[idx] = val;
+ break;
+ case MAL0_RCBS0:
+ idx = 0;
+ goto update_rx_size;
+ case MAL0_RCBS1:
+ idx = 1;
+ update_rx_size:
+ mal->rcbs[idx] = val & 0x000000FF;
+ break;
+ case SDR0_MALTBL:
+ mal->tbl = val;
+ break;
+ case SDR0_MALRBL:
+ mal->rbl = val;
+ break;
+ case SDR0_MALTBS:
+ mal->tbs = val;
+ break;
+ case SDR0_MALRBS:
+ mal->rbs = val;
+ break;
+ }
+}
+
+static void ppc4xx_mal_reset (void *opaque)
+{
+ ppc4xx_mal_t *mal;
+
+ mal = opaque;
+ mal->cfg = 0x0007C000;
+ mal->esr = 0x00000000;
+ mal->ier = 0x00000000;
+ mal->rxcasr = 0x00000000;
+ mal->rxdeir = 0x00000000;
+ mal->rxeobisr = 0x00000000;
+ mal->txcasr = 0x00000000;
+ mal->txdeir = 0x00000000;
+ mal->txeobisr = 0x00000000;
+}
+
+ppc4xx_mal_t *ppc4xx_mal_init (CPUState *env, qemu_irq irqs[4])
+{
+ ppc4xx_mal_t *mal;
+
+ mal = qemu_mallocz(sizeof(ppc4xx_mal_t));
+ if (mal != NULL) {
+ mal->txeob = irqs[0];
+ mal->rxeob = irqs[1];
+ mal->txde = irqs[2];
+ mal->rxde = irqs[3];
+ mal->serr = irqs[4];
+ ppc4xx_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,
+ 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);
+ /* For 440ep */
+ ppc_dcr_register(env, SDR0_MALTBL,
+ mal, &dcr_read_mal, &dcr_write_mal);
+ ppc_dcr_register(env, SDR0_MALRBL,
+ mal, &dcr_read_mal, &dcr_write_mal);
+ ppc_dcr_register(env, SDR0_MALTBS,
+ mal, &dcr_read_mal, &dcr_write_mal);
+ ppc_dcr_register(env, SDR0_MALRBS,
+ mal, &dcr_read_mal, &dcr_write_mal);
+ }
+ return mal;
+}
+
+/*****************************************************************************/
+/*
+ * I2C controller (SEE ALSO IN i2c.h before choice!!!)
+ *
+ * Control many device through uP resource.
+ * User could implement their device linked with this bus,
+ * specializing simple read(offset,value)/writec(offset,value)
+ * Only 7 bit address mode is supported.
+ *
+ * Difference known at me from 440EP/405GPr
+ *
+ * 440EP 405GPr
+ * Base Addr BASE4PERIPH+{0x700, 0x400} EF600500
+ *
+ * MDCNTL/bit2 Enable general call Reserved
+ * XTCNTLSS/bit6 Enable pulsed irq Reserved
+ * DIRECTCNTL/bit5 SCLC SCC
+ * bit7 MSCL MSC
+ * INTR Not exist
+ * 2 Bus Interface 1 Bus Interface
+ *
+ *
+ * Attached device, that must be indipendent from core implementation
+ * eeprom: data address with is 8/16/32 bits, use file as nv storage.
+ */
+#define I2C_VER2
+
+/*
+ * This method simulate the insertion of a byte from the bus,
+ * and acquisition in uP registers.
+ *
+ * Return number of readed bytes
+ * FIX: Should be linked to OPB clock
+ */
+static uint32_t ppc4xx_i2c_pushb (ppc4xx_i2c_t *i2c, uint8_t val)
+{
+ uint32_t ret = 0;
+
+ assert(i2c->dataLen<=sizeof(i2c->data));
+ /* Check if space */
+ if (i2c->dataLen<sizeof(i2c->data)) {
+ i2c->data[i2c->dataLen] = val;
+ i2c->dataLen++;
+ /* Signal to uP that data exist */
+ i2c->sts |= 0x20;
+ ret=1;
+ } else {
+ /* Signal to uP that no more space exist */
+ i2c->sts |= 0x10;
+ }
+ /* Always read a byte, also need different read/write cursor? */
+ return ret;
+}
+
+static uint8_t ppc4xx_i2c_popb (ppc4xx_i2c_t *i2c)
+{
+ uint8_t ret = 0;
+
+ assert(i2c->dataLen<=sizeof(i2c->data));
+ if (i2c->dataLen>0) {
+ uint8_t i;
+ ret = i2c->data[0];
+ i2c->dataLen--;
+ for (i=0; i<(sizeof(i2c->data)-1); i++)
+ i2c->data[i] = i2c->data[i+1];
+ }
+
+ if (i2c->dataLen<=0) {
+ /* Signal to uP that no more data exist */
+ i2c->sts &= ~0x30;
+ }
+ return ret;
+}
+
+static uint32_t ppc4xx_i2c_readb (void *opaque, target_phys_addr_t addr)
+{
+ ppc4xx_i2c_t *i2c;
+ uint32_t ret;
+
+ i2c = opaque;
+ switch (addr - i2c->base) {
+ case 0x00:
+#ifndef I2C_VER2
+ ret = i2c->mdata;
+#else
+ ret = ppc4xx_i2c_popb(i2c);
+#endif
+ break;
+ case 0x02:
+ ret = i2c->sdata;
+ break;
+ case 0x04:
+ ret = i2c->lmadr;
+ break;
+ case 0x05:
+ ret = i2c->hmadr;
+ break;
+ case 0x06:
+ ret = i2c->cntl;
+ break;
+ case 0x07:
+ ret = i2c->mdcntl;
+ break;
+ case 0x08:
+ ret = i2c->sts;
+ break;
+ case 0x09:
+ ret = i2c->extsts;
+ break;
+ case 0x0A:
+ ret = i2c->lsadr;
+ break;
+ case 0x0B:
+ ret = i2c->hsadr;
+ break;
+ case 0x0C:
+ ret = i2c->clkdiv;
+ break;
+ case 0x0D:
+ ret = i2c->intrmsk;
+ break;
+ case 0x0E:
+ ret = i2c->xfrcnt;
+ break;
+ case 0x0F:
+ ret = i2c->xtcntlss;
+ break;
+ case 0x10:
+ ret = i2c->directcntl;
+ break;
+ case 0x11:
+ ret = i2c->intr;
+ break;
+ default:
+ ret = 0x00;
+ break;
+ }
+#ifdef DEBUG_I2C
+ printf("%s: addr " PADDRX " %02" PRIx32 "\n", __func__, addr, ret);
+#endif
+
+ return ret;
+}
+
+
+/* Interaction with i2c.{h,c} module. Here we play the master role. */
+size_t ppc4xx_i2c_rw(i2c_bus *i2c, int dev_addr, uint8_t *data_addr, size_t len, char readfromdev) {
+ size_t ret;
+ int l;
+ ret = 0;
+#ifdef DEBUG_I2C
+ printf("%s: dev %x, len %d, %s\n", __func__, dev_addr, len, readfromdev?"read":"write");
+#endif
+ for (l=0; l<len; l++) {
+ if (l==0) {
+ i2c_start_transfer(i2c, dev_addr, readfromdev); /* 1=>RECV (from device) */
+ }
+ if (readfromdev) {
+ data_addr[l] = i2c_recv(i2c);
+ } else {
+ i2c_send(i2c, data_addr[l]);
+ }
+ if (l==len-1) {
+ i2c_end_transfer(i2c); /* 1=>RECV (from device) */
+ }
+ }
+ ret = l;
+ return ret;
+}
+static void ppc4xx_i2c_writeb (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+ ppc4xx_i2c_t *i2c;
+
+#ifdef DEBUG_I2C
+ printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
+#endif
+ i2c = opaque;
+ switch (addr - i2c->base) {
+ case 0x00:
+#ifndef I2C_VER2
+ i2c->mdata = value;
+ // i2c_sendbyte(&i2c->mdata);
+#else
+ ppc4xx_i2c_pushb(i2c, (char)value);
+#endif
+ break;
+ case 0x02:
+ i2c->sdata = value;
+ break;
+ case 0x04:
+ i2c->lmadr = value;
+ break;
+ case 0x05:
+ i2c->hmadr = value;
+ break;
+ case 0x06:
+ i2c->cntl = value;
+#ifdef I2C_VER2
+ /* IIC0_CNTL (8bits)
+ * -----------------
+ * HMT 0x80 Halt master Transfer
+ * AMD 0x40 Address MoDe
+ * TCT 0x30 Transfer CounT
+ * RPST 0x08 RePeated STart
+ * CHT 0x04 CHain Tranfer
+ * RW 0x02 ReadWrite
+ * PT 0x01 PendingTransfer
+ *
+ * State/Action
+ * HMT RPSP CHT PT
+ * 0 - - 0 No action
+ * 0 0 1 1 Start, Transfer, ACK on last byte, Pause
+ * 0 0 0 1 NACK , Stop
+ * 0 1 x 1 , Wait
+ * 1 x x x NACK on current byte, Stop
+ */
+ if (value & 0x81) {
+ unsigned char len, lettu, aspe;
+ int addr;
+ size_t ret;
+ len = ((value >> 4) & 3) + 1;
+ lettu = (value & 2);
+ aspe = (value & 1);
+ addr = i2c->lmadr;
+ ret = 0;
+#ifdef DEBUG_I2C
+ printf("(I2C command len %d, %s, start %s pending transfer)\n", len, lettu?"READING":"WRITING", aspe?"only if not":"also if");
+#endif
+ assert(len<=sizeof(i2c->data));
+#ifdef I2C_USE_EXISTING
+ ret = ppc4xx_i2c_rw(i2c->bus, addr, i2c->data, len, lettu);
+#else
+ if (lettu && i2c->sl.readF) {
+ ret = i2c->sl.readF(i2c->sl.opaque, addr, i2c->data, len);
+ }
+ if (!lettu && i2c->sl.writeF) {
+ ret = i2c->sl.writeF(i2c->sl.opaque, addr, i2c->data, len);
+ }
+#endif
+#ifdef DEBUG_I2C
+ printf("User command return %d\n", ret);
+#endif
+ /*
+ * on read from device => Push bytes in uP buffer (simulate controller acquiring)
+ * on write ... => Pop bytes from uP buffer (simulate device reading)
+ */
+ {
+ unsigned int l;
+ for (l=0; l<ret; l++) {
+ lettu ?
+ ppc4xx_i2c_pushb(i2c, i2c->data[l]) : /* Produce data for uP */
+ ppc4xx_i2c_popb(i2c) ; /* Consume data for uP */
+ }
+
+ }
+ }
+#endif
+ break;
+ case 0x07:
+ i2c->mdcntl = value & 0xDF;
+ break;
+ case 0x08:
+ i2c->sts &= ~(value & 0x0A);
+ break;
+ case 0x09:
+ i2c->extsts &= ~(value & 0x8F);
+ break;
+ case 0x0A:
+ i2c->lsadr = value;
+ break;
+ case 0x0B:
+ i2c->hsadr = value;
+ break;
+ case 0x0C:
+ i2c->clkdiv = value;
+ break;
+ case 0x0D:
+ i2c->intrmsk = value;
+ break;
+ case 0x0E:
+ i2c->xfrcnt = value & 0x77;
+ break;
+ case 0x0F:
+ i2c->xtcntlss = value;
+ break;
+ case 0x10:
+ i2c->directcntl = value & 0x7;
+ break;
+ case 0x11:
+ i2c->intr = value;
+ break;
+ }
+}
+
+static uint32_t ppc4xx_i2c_readw (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t ret;
+
+#ifdef DEBUG_I2C
+ printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+ ret = ppc4xx_i2c_readb(opaque, addr) << 8;
+ ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+
+ return ret;
+}
+
+static void ppc4xx_i2c_writew (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+ printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, value);
+#endif
+ ppc4xx_i2c_writeb(opaque, addr, value >> 8);
+ ppc4xx_i2c_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t ppc4xx_i2c_readl (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t ret;
+
+#ifdef DEBUG_I2C
+ printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+ ret = ppc4xx_i2c_readb(opaque, addr) << 24;
+ ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
+ ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
+ ret |= ppc4xx_i2c_readb(opaque, addr + 3);
+
+ return ret;
+}
+
+static void ppc4xx_i2c_writel (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+ printf("%s: addr " PADDRX " val %08" PRIx32 "\n", __func__, addr, 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 CPUReadMemoryFunc *i2c_read[] = {
+ &ppc4xx_i2c_readb,
+ &ppc4xx_i2c_readw,
+ &ppc4xx_i2c_readl,
+};
+
+static CPUWriteMemoryFunc *i2c_write[] = {
+ &ppc4xx_i2c_writeb,
+ &ppc4xx_i2c_writew,
+ &ppc4xx_i2c_writel,
+};
+
+static void ppc4xx_i2c_reset (void *opaque)
+{
+ ppc4xx_i2c_t *i2c;
+
+ i2c = opaque;
+ i2c->mdata = 0x00;
+ i2c->sdata = 0x00;
+ i2c->cntl = 0x00;
+ i2c->mdcntl = 0x00;
+ i2c->sts = 0x00;
+ i2c->extsts = 0x00;
+ i2c->clkdiv = 0x00;
+ i2c->xfrcnt = 0x00;
+ i2c->directcntl = 0x0F;
+ i2c->intr = 0;
+}
+
+/* Qemu I2C infrastructure
+ * - why associate irq when binding to a slave?
+ */
+ppc4xx_i2c_t *ppc4xx_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio,
+ target_phys_addr_t offset, qemu_irq irq)
+{
+ ppc4xx_i2c_t *i2c;
+
+ i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t));
+ if (i2c != NULL) {
+ i2c->base = offset;
+ i2c->irq = irq;
+#ifdef I2C_USE_EXISTING
+ i2c->bus = i2c_init_bus();
+#else
+ if (sl) {
+ i2c->sl.readF = sl->readF;
+ i2c->sl.writeF = sl->writeF;
+ i2c->sl.opaque = sl->opaque;
+ }
+#endif
+ ppc4xx_i2c_reset(i2c);
+#ifdef DEBUG_I2C
+ printf("%s: offset " PADDRX "\n", __func__, offset);
+#endif
+ ppc4xx_mmio_register(env, mmio, offset, 0x011,
+ i2c_read, i2c_write, i2c);
+ qemu_register_reset(ppc4xx_i2c_reset, i2c);
+ }
+ return i2c;
+}
Index: hw/ppc405.h
===================================================================
--- hw/ppc405.h (revision 5720)
+++ hw/ppc405.h (working copy)
@@ -84,9 +84,6 @@
CharDriverState *chr);
/* On Chip Memory */
void ppc405_ocm_init (CPUState *env, unsigned long offset);
-/* I2C controller */
-void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio,
- target_phys_addr_t offset, qemu_irq irq);
/* General purpose timers */
void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio,
target_phys_addr_t offset, qemu_irq irq[5]);
@@ -96,11 +93,15 @@
CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
target_phys_addr_t ram_sizes[4],
uint32_t sysclk, qemu_irq **picp,
- ram_addr_t *offsetp, int do_init);
-CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
+ ram_addr_t *offsetp, int do_init,
+ ppc4xx_devsL *devsL);
+CPUState *ppc405xp_init (const char* cpu_model,
+ target_phys_addr_t ram_bases[2],
target_phys_addr_t ram_sizes[2],
uint32_t sysclk, qemu_irq **picp,
- ram_addr_t *offsetp, int do_init);
+ ram_addr_t *offsetp, int do_init,
+ ppc4xx_devsL *devsL);
+
/* IBM STBxxx microcontrollers */
CPUState *ppc_stb025_init (target_phys_addr_t ram_bases[2],
target_phys_addr_t ram_sizes[2],
Index: hw/i2c.h
===================================================================
--- hw/i2c.h (revision 5720)
+++ hw/i2c.h (working copy)
@@ -87,4 +87,7 @@
struct i2c_slave *lm8323_init(i2c_bus *bus, qemu_irq nirq);
void lm832x_key_event(struct i2c_slave *i2c, int key, int state);
+/* eeprom, like 24LC256 */
+enum iic_eeprom_cp {IIC_EEPROM_DEEP_COPY, IIC_EEPROM_SHALLOW_COPY};
+struct i2c_slave *iic_eeprom_init(i2c_bus *bus, int bus_width, size_t sizeB, char *data, enum iic_eeprom_cp);
#endif
Index: hw/ppc4xx.h
===================================================================
--- hw/ppc4xx.h (revision 5720)
+++ hw/ppc4xx.h (working copy)
@@ -25,6 +25,8 @@
#if !defined(PPC_4XX_H)
#define PPC_4XX_H
+#include "i2c.h"
+
/* PowerPC 4xx core initialization */
CPUState *ppc4xx_init (const char *cpu_model,
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
@@ -46,4 +48,77 @@
qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
uint32_t dcr_base, int has_ssr, int has_vr);
+/* PowerPC 4xx Memory Access Layer */
+typedef struct ppc4xx_mal_t ppc4xx_mal_t;
+struct ppc4xx_mal_t {
+ qemu_irq txeob;
+ qemu_irq rxeob;
+ qemu_irq txde;
+ qemu_irq rxde;
+ qemu_irq serr;
+ 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];
+ uint32_t tbl;
+ uint32_t rbl;
+ uint32_t tbs;
+ uint32_t rbs;
+};
+ppc4xx_mal_t *ppc4xx_mal_init (CPUState *env, qemu_irq irqs[5]);
+
+/* PowerPC 4xx Ethernet Media Access Controller */
+void ppc4xx_emac_init (CPUState *env, ppc4xx_mmio_t *mmio, target_phys_addr_t offset, NICInfo *nic, ppc4xx_mal_t *mal);
+
+/* I2C controller */
+typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
+struct ppc4xx_i2c_t {
+ /* Master emulation */
+ target_phys_addr_t base;
+ qemu_irq irq;
+ 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;
+ uint8_t intr;
+
+ /* TODO This is treated like a FIFO with same OPB beat (now served immediately) */
+ uint8_t dataLen;
+ uint8_t data[4];
+
+ /* Main bus to which link all slave */
+ i2c_bus *bus;
+};
+
+ppc4xx_i2c_t *ppc4xx_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio, target_phys_addr_t offset, qemu_irq irq);
+
+
+/* PowerPC4xx: let user configurate just builded machine
+ * Since no configuration is still present... */
+typedef struct ppc4xx_devsL ppc4xx_devsL;
+struct ppc4xx_devsL {
+ ppc4xx_i2c_t *i2c0;
+ ppc4xx_i2c_t *i2c1;
+};
#endif /* !defined(PPC_4XX_H) */
Index: hw/iic_eeprom.c
===================================================================
--- hw/iic_eeprom.c (revision 0)
+++ hw/iic_eeprom.c (revision 0)
@@ -0,0 +1,209 @@
+/*
+ * PID eeprom via I2C
+ *
+ * Copyright (C) 2008 Lionetti Salvatore
+ * Written by Salvatore Lionetti <salvatorelionetti@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include "hw.h"
+#include "i2c.h"
+
+/*#define DEBUG_I2CE2P 1*/
+/* Setup
+ * =====
+ * s->i2c[0] = new()
+ * s->i2c[0]->slave.{event, recv, send} = ...
+ * s->i2c[0]->bus = i2c_init_bus() new(i2c_bus)
+ *
+ * i2c_set_slave_address(tmp105_init(s->i2c[0], irq)) i2c_slave_init(bus)
+ *
+ *
+ * Run-time
+ * ========
+ * slave->event()
+ * slave->recv()
+ * slave->send()
+ */
+struct iic_eeprom {
+ i2c_slave i2c;
+
+ char addr_bytes;
+ char latch_addr;
+ uint32_t cur_addr;
+
+ uint8_t *data;
+ size_t dataB;
+};
+
+
+#ifdef DEBUG_I2CE2P
+#define DPRINTF(fmt, args...) do { printf("%s: " fmt , __func__, ##args); } while (0)
+#define BADF(fmt, args...) do { fprintf(stderr, "%s: " fmt , __func__, ##args); exit(1);} while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#define BADF(fmt, args...) do { fprintf(stderr, "iic_eeprom: error: " fmt , ##args);} while (0)
+#endif
+
+
+static int iic_eeprom_read(i2c_slave *i2c)
+{
+ struct iic_eeprom *s = (struct iic_eeprom *) i2c;
+ uint8_t ret = 0xFF;
+
+ if (s->cur_addr<s->dataB) {
+ ret = s->data[s->cur_addr];
+ }
+ DPRINTF("read %x@%x\n", ret, s->cur_addr);
+ s->cur_addr++;
+ return (int)ret;
+}
+
+static int iic_eeprom_write(i2c_slave *i2c, uint8_t data)
+{
+ struct iic_eeprom *s = (struct iic_eeprom *) i2c;
+
+ if (s->latch_addr>0) {
+ s->cur_addr = (s->cur_addr<<8) | data;
+ s->latch_addr--;
+ DPRINTF("address %x\n", s->cur_addr);
+ } else {
+ DPRINTF("write %x@%x\n", data, s->cur_addr);
+ if (s->cur_addr<s->dataB) {
+ s->data[s->cur_addr] = data;
+ }
+ s->cur_addr++;
+ }
+ return 0;
+}
+
+static const char* getEventDes(enum i2c_event ev) {
+ const char* ret="UNKNOWN COMMAND";
+ switch (ev) {
+ case I2C_START_SEND: ret = "START_SEND"; break;
+ case I2C_START_RECV: ret = "START_RECV"; break;
+ case I2C_FINISH: ret = "FINISH"; break;
+ case I2C_NACK: ret = "NACK"; break;
+ }
+ return ret;
+}
+static void iic_eeprom_event(i2c_slave *i2c, enum i2c_event event)
+{
+ struct iic_eeprom *s = (struct iic_eeprom *) i2c;
+
+ switch (event) {
+ case I2C_START_SEND:
+ /* Write sequence always start with address */
+ s->latch_addr = s->addr_bytes;
+ s->cur_addr = 0;
+ case I2C_START_RECV:
+ case I2C_FINISH:
+ case I2C_NACK:
+ break;
+ }
+ DPRINTF(" %s\n", getEventDes(event));
+}
+
+static void iic_eeprom_save(QEMUFile *f, void *opaque)
+{
+ struct iic_eeprom *s = (struct iic_eeprom *) opaque;
+
+ qemu_put_byte(f, s->latch_addr);
+ qemu_put_buffer(f, (uint8_t*)&s->cur_addr, sizeof(s->cur_addr));
+
+ i2c_slave_save(f, &s->i2c);
+}
+
+static int iic_eeprom_load(QEMUFile *f, void *opaque, int version_id)
+{
+ struct iic_eeprom *s = (struct iic_eeprom *) opaque;
+
+ s->latch_addr = qemu_get_byte(f);
+ qemu_get_buffer(f, (uint8_t*)&s->cur_addr, sizeof(s->cur_addr));
+
+ i2c_slave_load(f, &s->i2c);
+ return 0;
+}
+
+void iic_eeprom_reset(i2c_slave *opaque)
+{
+ struct iic_eeprom *s = (struct iic_eeprom *) opaque;
+ s->latch_addr = 0;
+ s->cur_addr = 0;
+}
+
+/* Signal:
+ * - Clk given by master
+ * - Data shared
+ * - change when Clk high=>STATE CHANGE, start/stop command.
+ * - !change when Clk high=>DATA
+ * - change when Clk low =>NO STATE CHANGE
+ * - !change when Clk low =>NO STATE CHANGE
+ *
+ * A: BUS NOT BUSY
+ * Data = Clk = '1'
+ *
+ * B: START DATA TRANSFER
+ * Data '1'->'0' when Clk = '1'
+ *
+ * C: STOP DATA TRANSFER
+ * Data '0'->'1' when Clk = '1'
+ *
+ * D: DATA VALID
+ * Data stable when Clk = '1'
+ *
+ * START/STOP transfer: data change during clk'high
+ * data change while clk
+ */
+/* 24LC256 Microchip:
+ * =================
+ * Addressing
+ * bit7:4 1010
+ * bit3:1 A2 A1 A0
+ * bit0 1=>Read, 0=>Write
+ * Ack bit
+ *
+ * 34XX02 Microchip, SPD (serial presence detect) for DIMM SDRAM
+ * Agree to JEDEC standard: www.jedec.org/download/search/4_01_02_00R9.PDF
+ */
+struct i2c_slave *iic_eeprom_init(i2c_bus *bus, int addr_width, size_t sizeB, char *data, enum iic_eeprom_cp cp)
+{
+ struct iic_eeprom *s;
+
+ assert(data);
+ assert(addr_width==8 || addr_width==16 || addr_width==32);
+ s = (struct iic_eeprom *) i2c_slave_init(bus, 0, sizeof(struct iic_eeprom) + (cp==IIC_EEPROM_DEEP_COPY?sizeB:0));
+
+ s->i2c.event = iic_eeprom_event;
+ s->i2c.recv = iic_eeprom_read;
+ s->i2c.send = iic_eeprom_write;
+
+ s->data = data;
+ s->dataB = sizeB;
+ s->addr_bytes = (addr_width>>=3);
+ if (cp == IIC_EEPROM_DEEP_COPY) {
+ s->data = (char*) &s[1];
+ memcpy(s->data, data, sizeB);
+ }
+ iic_eeprom_reset(&s->i2c);
+ DPRINTF(" Bus %p, width %d, sizeB %d, data %p\n, copy %s", bus, addr_width, sizeB, data, cp==IIC_EEPROM_DEEP_COPY?"DEEP":"SHALLOW");
+
+ register_savevm("I2CE2PROM", -1, 0, iic_eeprom_save, iic_eeprom_load, s);
+
+ return &s->i2c;
+}
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL
2008-12-09 1:46 [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL Salvatore Lionetti
@ 2008-12-09 16:57 ` Hollis Blanchard
2008-12-10 14:13 ` Salvatore Lionetti
0 siblings, 1 reply; 5+ messages in thread
From: Hollis Blanchard @ 2008-12-09 16:57 UTC (permalink / raw)
To: salvatorelionetti; +Cc: qemu-devel
On Tue, 2008-12-09 at 01:46 +0000, Salvatore Lionetti wrote:
> Hi
>
> This set of patch try to full support hw present in 'walnut' board.
> http://elinux.org/DHT-Walnut
>
> The fw used to successfully verify board is u-boot-1.3.4.
>
> The only component not tested is PCI: perhaps should be a good start
> point for Hollis 's recent work, which i thanks for previous code
> review.
>
> 1) IIC: new eeprom device, full emulation of 4xx master core
> MAL: Moved interface so can be shared with other modules
> 4xx boards: move MAL & IIC common part between ppc4xx cpu
> add a list of created devices, so machine 2 phase
> creation is allowed,
>
> Warning: to compile:
> - comment line 'ppc4xx_emac_init(...)' in module hw/ppc405_boards.c
> - rename ppc405ep_init(args) in ppc405xp_init("405ep", args, NULL)
>
> Files changed:
> - Makefile.target
> - Makefile
> - hw/ppc405_uc.c
> - hw/ppc4xx_devs.c
> - hw/ppc405.h
> - hw/i2c.h
> - hw/iic_eeprom.c (Added)
> - hw/ppc4xx.h
Please split this into smaller patches which can be more easily
reviewed. For example, you should send one patch that *only* moves the
i2c code (and makes no changes). Then submit a patch that modifies the
code in its new location. You should submit separate patches for MAL and
I2C. You should not change the DEBUG #defines, nor add debug calls to
printf.
In other words, please remove all extraneous changes from your patch,
and break it up into small self-contained pieces that can be committed
one by one.
--
Hollis Blanchard
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL
2008-12-09 16:57 ` Hollis Blanchard
@ 2008-12-10 14:13 ` Salvatore Lionetti
2008-12-10 18:53 ` Hollis Blanchard
0 siblings, 1 reply; 5+ messages in thread
From: Salvatore Lionetti @ 2008-12-10 14:13 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: qemu-devel
Ok
1) The line code modified is 80% IIC, only few row about MAL
2) MAL until today (if ever this patch enter in qemu) is only used to rw registers, so no malfunction is present.
3) As you can see many ppc* file are to modify since I2C previous support it totally not integrated: have sense modify ppc* and never use an IIC device?
4) Is error prone and very tedious to extract some code, expecially if there is no modularity advantage: one piece require the other,
5) I already have successfully tested the expected patch.
6) I can't do that directly so every time have 2 see if main line is updated or not, merge svn file with current my patch status
7) Who apply the patch only apply one click?
In this moment i have no time to make all this retail and test.
Thanks for punctual feeling.
Salvatore
--- Mar 9/12/08, Hollis Blanchard <hollisb@us.ibm.com> ha scritto:
> Da: Hollis Blanchard <hollisb@us.ibm.com>
> Oggetto: Re: [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL
> A: salvatorelionetti@yahoo.it
> Cc: "qemu-devel" <qemu-devel@nongnu.org>
> Data: Martedì 9 dicembre 2008, 17:57
> On Tue, 2008-12-09 at 01:46 +0000, Salvatore Lionetti wrote:
> > Hi
> >
> > This set of patch try to full support hw present in
> 'walnut' board.
> > http://elinux.org/DHT-Walnut
> >
> > The fw used to successfully verify board is
> u-boot-1.3.4.
> >
> > The only component not tested is PCI: perhaps should
> be a good start
> > point for Hollis 's recent work, which i thanks
> for previous code
> > review.
> >
> > 1) IIC: new eeprom device, full emulation of 4xx
> master core
> > MAL: Moved interface so can be shared with other
> modules
> > 4xx boards: move MAL & IIC common part between
> ppc4xx cpu
> > add a list of created devices, so
> machine 2 phase
> > creation is allowed,
> >
> > Warning: to compile:
> > - comment line 'ppc4xx_emac_init(...)' in
> module hw/ppc405_boards.c
> > - rename ppc405ep_init(args) in
> ppc405xp_init("405ep", args, NULL)
> >
> > Files changed:
> > - Makefile.target
> > - Makefile
> > - hw/ppc405_uc.c
> > - hw/ppc4xx_devs.c
> > - hw/ppc405.h
> > - hw/i2c.h
> > - hw/iic_eeprom.c (Added)
> > - hw/ppc4xx.h
>
> Please split this into smaller patches which can be more
> easily
> reviewed. For example, you should send one patch that
> *only* moves the
> i2c code (and makes no changes). Then submit a patch that
> modifies the
> code in its new location. You should submit separate
> patches for MAL and
> I2C. You should not change the DEBUG #defines, nor add
> debug calls to
> printf.
>
> In other words, please remove all extraneous changes from
> your patch,
> and break it up into small self-contained pieces that can
> be committed
> one by one.
>
> --
> Hollis Blanchard
> IBM Linux Technology Center
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL
2008-12-10 14:13 ` Salvatore Lionetti
@ 2008-12-10 18:53 ` Hollis Blanchard
2008-12-10 22:09 ` Salvatore Lionetti
0 siblings, 1 reply; 5+ messages in thread
From: Hollis Blanchard @ 2008-12-10 18:53 UTC (permalink / raw)
To: salvatorelionetti; +Cc: qemu-devel
On Wed, 2008-12-10 at 14:13 +0000, Salvatore Lionetti wrote:
> Ok
>
> 1) The line code modified is 80% IIC, only few row about MAL
> 2) MAL until today (if ever this patch enter in qemu) is only used to
> rw registers, so no malfunction is present.
> 3) As you can see many ppc* file are to modify since I2C previous
> support it totally not integrated: have sense modify ppc* and never
> use an IIC device?
> 4) Is error prone and very tedious to extract some code, expecially if
> there is no modularity advantage: one piece require the other,
> 5) I already have successfully tested the expected patch.
> 6) I can't do that directly so every time have 2 see if main line is
> updated or not, merge svn file with current my patch status
> 7) Who apply the patch only apply one click?
>
> In this moment i have no time to make all this retail and test.
I would be very surprised if somebody applies your patch as-is, because
it's messy (there are a lot of unnecessary/unrelated changes) and it's
very difficult to see the functional changes.
Yes, there is a natural dependency of a patch on the previous ones. This
is called a "patch queue" or "patch series", and you can see other
people submitting them on qemu-devel. (In fact the most recent series
contains 13 patches, with #13 depending on #1-12 being committed
already.)
There are tools (such as quilt, guilt, and MQ) that help you manage
patch series. You can use these tools to maintain your patches and
update them to match the latest qemu tree.
If you submit small independent patches, people will be able to easily
see that they're good and commit them instantly. When you submit a large
patch with lots of changes, it takes a lot more time and effort to
review, and it's much less likely to be accepted.
--
Hollis Blanchard
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL
2008-12-10 18:53 ` Hollis Blanchard
@ 2008-12-10 22:09 ` Salvatore Lionetti
0 siblings, 0 replies; 5+ messages in thread
From: Salvatore Lionetti @ 2008-12-10 22:09 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: qemu-devel
Hi,
I organized my little work in three 'patch queue', one for each argument:
- IIC
MAL (only moved in other place plus 4,5 line added)
- EMAC
- WALNUT MACHINE
There is really need of endless soap for these three change?
Really having only a piece of entire patch about eg IIC will help people to comment this work?
Perhaps is wrong my point of view, but after three times that i mistake in patch , this is a reciprocal time wasting.
My personal opinion is that an integrator, when possible, for a cpu family is needed: not only saying 'this patch is big, this one is uncomprensible', but also to validate how qemu architecture is used or modified relatively to device specification, and how such device specification is reached, at least with coarse-grained; in the case comment about, i thing, is welcome. At least for me.
Have a good day
--- Mer 10/12/08, Hollis Blanchard <hollisb@us.ibm.com> ha scritto:
> Da: Hollis Blanchard <hollisb@us.ibm.com>
> Oggetto: Re: [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL
> A: salvatorelionetti@yahoo.it
> Cc: "qemu-devel" <qemu-devel@nongnu.org>
> Data: Mercoledì 10 dicembre 2008, 19:53
> On Wed, 2008-12-10 at 14:13 +0000, Salvatore Lionetti wrote:
> > Ok
> >
> > 1) The line code modified is 80% IIC, only few row
> about MAL
> > 2) MAL until today (if ever this patch enter in qemu)
> is only used to
> > rw registers, so no malfunction is present.
> > 3) As you can see many ppc* file are to modify since
> I2C previous
> > support it totally not integrated: have sense modify
> ppc* and never
> > use an IIC device?
> > 4) Is error prone and very tedious to extract some
> code, expecially if
> > there is no modularity advantage: one piece require
> the other,
> > 5) I already have successfully tested the expected
> patch.
> > 6) I can't do that directly so every time have 2
> see if main line is
> > updated or not, merge svn file with current my patch
> status
> > 7) Who apply the patch only apply one click?
> >
> > In this moment i have no time to make all this retail
> and test.
>
> I would be very surprised if somebody applies your patch
> as-is, because
> it's messy (there are a lot of unnecessary/unrelated
> changes) and it's
> very difficult to see the functional changes.
>
> Yes, there is a natural dependency of a patch on the
> previous ones. This
> is called a "patch queue" or "patch
> series", and you can see other
> people submitting them on qemu-devel. (In fact the most
> recent series
> contains 13 patches, with #13 depending on #1-12 being
> committed
> already.)
>
> There are tools (such as quilt, guilt, and MQ) that help
> you manage
> patch series. You can use these tools to maintain your
> patches and
> update them to match the latest qemu tree.
>
> If you submit small independent patches, people will be
> able to easily
> see that they're good and commit them instantly. When
> you submit a large
> patch with lots of changes, it takes a lot more time and
> effort to
> review, and it's much less likely to be accepted.
>
> --
> Hollis Blanchard
> IBM Linux Technology Center
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-12-10 22:09 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-09 1:46 [Qemu-devel] [PATCH 1/3] PPC4xx IIC and MAL Salvatore Lionetti
2008-12-09 16:57 ` Hollis Blanchard
2008-12-10 14:13 ` Salvatore Lionetti
2008-12-10 18:53 ` Hollis Blanchard
2008-12-10 22:09 ` Salvatore Lionetti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).