Add basic OMAP2 chip support.

Add the OMAP242x (arm1136 core) initialisation with basic on-chip
peripherals and update OMAP1 peripherals which are re-used in OMAP2.
Make palmte.c and sd.c errors go to stderr.
Allow disabling SD chipselect.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4213 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
balrog 2008-04-14 21:05:22 +00:00
parent f93eb9ff66
commit 827df9f3c5
14 changed files with 6936 additions and 226 deletions

View File

@ -610,6 +610,7 @@ OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
OBJS+= pflash_cfi01.o gumstix.o
OBJS+= spitz.o ide.o serial.o nand.o ecc.o
OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
OBJS+= omap2.o omap_dss.o
OBJS+= palm.o tsc210x.o
OBJS+= mst_fpga.o mainstone.o
CPPFLAGS += -DHAS_AUDIO

308
hw/omap.h
View File

@ -5,8 +5,8 @@
*
* 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 of
* the License, or (at your option) any later version.
* 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
@ -22,6 +22,7 @@
# define hw_omap_h "omap.h"
# define OMAP_EMIFS_BASE 0x00000000
# define OMAP2_Q0_BASE 0x00000000
# define OMAP_CS0_BASE 0x00000000
# define OMAP_CS1_BASE 0x04000000
# define OMAP_CS2_BASE 0x08000000
@ -29,18 +30,26 @@
# define OMAP_EMIFF_BASE 0x10000000
# define OMAP_IMIF_BASE 0x20000000
# define OMAP_LOCALBUS_BASE 0x30000000
# define OMAP2_Q1_BASE 0x40000000
# define OMAP2_L4_BASE 0x48000000
# define OMAP2_SRAM_BASE 0x40200000
# define OMAP2_L3_BASE 0x68000000
# define OMAP2_Q2_BASE 0x80000000
# define OMAP2_Q3_BASE 0xc0000000
# define OMAP_MPUI_BASE 0xe1000000
# define OMAP730_SRAM_SIZE 0x00032000
# define OMAP15XX_SRAM_SIZE 0x00030000
# define OMAP16XX_SRAM_SIZE 0x00004000
# define OMAP1611_SRAM_SIZE 0x0003e800
# define OMAP242X_SRAM_SIZE 0x000a0000
# define OMAP243X_SRAM_SIZE 0x00010000
# define OMAP_CS0_SIZE 0x04000000
# define OMAP_CS1_SIZE 0x04000000
# define OMAP_CS2_SIZE 0x04000000
# define OMAP_CS3_SIZE 0x04000000
/* omap1_clk.c */
/* omap_clk.c */
struct omap_mpu_state_s;
typedef struct clk *omap_clk;
omap_clk omap_findclk(struct omap_mpu_state_s *mpu, const char *name);
@ -55,14 +64,41 @@ int64_t omap_clk_getrate(omap_clk clk);
void omap_clk_reparent(omap_clk clk, omap_clk parent);
/* omap[123].c */
struct omap_intr_handler_s;
struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
unsigned long size, unsigned char nbanks,
qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk);
struct omap_l4_s;
struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num);
struct omap_target_agent_s;
static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
int region, int iotype) { return 0; }
struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs);
target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
int iotype);
struct omap_intr_handler_s;
struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
unsigned long size, unsigned char nbanks, qemu_irq **pins,
qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk);
struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
int size, int nbanks, qemu_irq **pins,
qemu_irq parent_irq, qemu_irq parent_fiq,
omap_clk fclk, omap_clk iclk);
void omap_inth_reset(struct omap_intr_handler_s *s);
struct omap_prcm_s;
struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
struct omap_mpu_state_s *mpu);
struct omap_sysctl_s;
struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
omap_clk iclk, struct omap_mpu_state_s *mpu);
struct omap_sdrc_s;
struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base);
struct omap_gpmc_s;
struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq);
void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
void (*base_upd)(void *opaque, target_phys_addr_t new),
void (*unmap)(void *opaque), void *opaque);
/*
* Common IRQ numbers for level 1 interrupt handler
@ -295,10 +331,20 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
* OMAP-24xx common IRQ numbers
*/
# define OMAP_INT_24XX_SYS_NIRQ 7
# define OMAP_INT_24XX_L3_IRQ 10
# define OMAP_INT_24XX_PRCM_MPU_IRQ 11
# define OMAP_INT_24XX_SDMA_IRQ0 12
# define OMAP_INT_24XX_SDMA_IRQ1 13
# define OMAP_INT_24XX_SDMA_IRQ2 14
# define OMAP_INT_24XX_SDMA_IRQ3 15
# define OMAP_INT_243X_MCBSP2_IRQ 16
# define OMAP_INT_243X_MCBSP3_IRQ 17
# define OMAP_INT_243X_MCBSP4_IRQ 18
# define OMAP_INT_243X_MCBSP5_IRQ 19
# define OMAP_INT_24XX_GPMC_IRQ 20
# define OMAP_INT_24XX_GUFFAW_IRQ 21
# define OMAP_INT_24XX_IVA_IRQ 22
# define OMAP_INT_24XX_EAC_IRQ 23
# define OMAP_INT_24XX_CAM_IRQ 24
# define OMAP_INT_24XX_DSS_IRQ 25
# define OMAP_INT_24XX_MAIL_U0_MPU 26
@ -308,8 +354,10 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
# define OMAP_INT_24XX_GPIO_BANK2 30
# define OMAP_INT_24XX_GPIO_BANK3 31
# define OMAP_INT_24XX_GPIO_BANK4 32
# define OMAP_INT_24XX_GPIO_BANK5 33
# define OMAP_INT_243X_GPIO_BANK5 33
# define OMAP_INT_24XX_MAIL_U3_MPU 34
# define OMAP_INT_24XX_WDT3 35
# define OMAP_INT_24XX_WDT4 36
# define OMAP_INT_24XX_GPTIMER1 37
# define OMAP_INT_24XX_GPTIMER2 38
# define OMAP_INT_24XX_GPTIMER3 39
@ -322,10 +370,24 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
# define OMAP_INT_24XX_GPTIMER10 46
# define OMAP_INT_24XX_GPTIMER11 47
# define OMAP_INT_24XX_GPTIMER12 48
# define OMAP_INT_24XX_PKA_IRQ 50
# define OMAP_INT_24XX_SHA1MD5_IRQ 51
# define OMAP_INT_24XX_RNG_IRQ 52
# define OMAP_INT_24XX_MG_IRQ 53
# define OMAP_INT_24XX_I2C1_IRQ 56
# define OMAP_INT_24XX_I2C2_IRQ 57
# define OMAP_INT_24XX_MCBSP1_IRQ_TX 59
# define OMAP_INT_24XX_MCBSP1_IRQ_RX 60
# define OMAP_INT_24XX_MCBSP2_IRQ_TX 62
# define OMAP_INT_24XX_MCBSP2_IRQ_RX 63
# define OMAP_INT_243X_MCBSP1_IRQ 64
# define OMAP_INT_24XX_MCSPI1_IRQ 65
# define OMAP_INT_24XX_MCSPI2_IRQ 66
# define OMAP_INT_24XX_SSI1_IRQ0 67
# define OMAP_INT_24XX_SSI1_IRQ1 68
# define OMAP_INT_24XX_SSI2_IRQ0 69
# define OMAP_INT_24XX_SSI2_IRQ1 70
# define OMAP_INT_24XX_SSI_GDD_IRQ 71
# define OMAP_INT_24XX_UART1_IRQ 72
# define OMAP_INT_24XX_UART2_IRQ 73
# define OMAP_INT_24XX_UART3_IRQ 74
@ -335,10 +397,15 @@ static inline target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta,
# define OMAP_INT_24XX_USB_IRQ_HGEN 78
# define OMAP_INT_24XX_USB_IRQ_HSOF 79
# define OMAP_INT_24XX_USB_IRQ_OTG 80
# define OMAP_INT_24XX_VLYNQ_IRQ 81
# define OMAP_INT_24XX_MMC_IRQ 83
# define OMAP_INT_24XX_MS_IRQ 84
# define OMAP_INT_24XX_FAC_IRQ 85
# define OMAP_INT_24XX_MCSPI3_IRQ 91
# define OMAP_INT_243X_HS_USB_MC 92
# define OMAP_INT_243X_HS_USB_DMA 93
# define OMAP_INT_243X_CARKIT 94
# define OMAP_INT_34XX_GPTIMER12 95
/* omap_dma.c */
enum omap_dma_model {
@ -352,6 +419,9 @@ struct omap_dma_s;
struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
enum omap_dma_model model);
struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
struct omap_mpu_state_s *mpu, int fifo,
int chans, omap_clk iclk, omap_clk fclk);
void omap_dma_reset(struct omap_dma_s *s);
struct dma_irq_map {
@ -367,7 +437,7 @@ enum omap_dma_port {
tipb,
local, /* omap16xx: ocp_t2 */
tipb_mpui,
omap_dma_port_last,
__omap_dma_port_last,
};
typedef enum {
@ -488,11 +558,83 @@ struct omap_dma_lcd_channel_s {
# define OMAP_DMA_MMC2_RX 55
# define OMAP_DMA_CRYPTO_DES_OUT 56
/*
* DMA request numbers for the OMAP2
*/
# define OMAP24XX_DMA_NO_DEVICE 0
# define OMAP24XX_DMA_XTI_DMA 1 /* Not in OMAP2420 */
# define OMAP24XX_DMA_EXT_DMAREQ0 2
# define OMAP24XX_DMA_EXT_DMAREQ1 3
# define OMAP24XX_DMA_GPMC 4
# define OMAP24XX_DMA_GFX 5 /* Not in OMAP2420 */
# define OMAP24XX_DMA_DSS 6
# define OMAP24XX_DMA_VLYNQ_TX 7 /* Not in OMAP2420 */
# define OMAP24XX_DMA_CWT 8 /* Not in OMAP2420 */
# define OMAP24XX_DMA_AES_TX 9 /* Not in OMAP2420 */
# define OMAP24XX_DMA_AES_RX 10 /* Not in OMAP2420 */
# define OMAP24XX_DMA_DES_TX 11 /* Not in OMAP2420 */
# define OMAP24XX_DMA_DES_RX 12 /* Not in OMAP2420 */
# define OMAP24XX_DMA_SHA1MD5_RX 13 /* Not in OMAP2420 */
# define OMAP24XX_DMA_EXT_DMAREQ2 14
# define OMAP24XX_DMA_EXT_DMAREQ3 15
# define OMAP24XX_DMA_EXT_DMAREQ4 16
# define OMAP24XX_DMA_EAC_AC_RD 17
# define OMAP24XX_DMA_EAC_AC_WR 18
# define OMAP24XX_DMA_EAC_MD_UL_RD 19
# define OMAP24XX_DMA_EAC_MD_UL_WR 20
# define OMAP24XX_DMA_EAC_MD_DL_RD 21
# define OMAP24XX_DMA_EAC_MD_DL_WR 22
# define OMAP24XX_DMA_EAC_BT_UL_RD 23
# define OMAP24XX_DMA_EAC_BT_UL_WR 24
# define OMAP24XX_DMA_EAC_BT_DL_RD 25
# define OMAP24XX_DMA_EAC_BT_DL_WR 26
# define OMAP24XX_DMA_I2C1_TX 27
# define OMAP24XX_DMA_I2C1_RX 28
# define OMAP24XX_DMA_I2C2_TX 29
# define OMAP24XX_DMA_I2C2_RX 30
# define OMAP24XX_DMA_MCBSP1_TX 31
# define OMAP24XX_DMA_MCBSP1_RX 32
# define OMAP24XX_DMA_MCBSP2_TX 33
# define OMAP24XX_DMA_MCBSP2_RX 34
# define OMAP24XX_DMA_SPI1_TX0 35
# define OMAP24XX_DMA_SPI1_RX0 36
# define OMAP24XX_DMA_SPI1_TX1 37
# define OMAP24XX_DMA_SPI1_RX1 38
# define OMAP24XX_DMA_SPI1_TX2 39
# define OMAP24XX_DMA_SPI1_RX2 40
# define OMAP24XX_DMA_SPI1_TX3 41
# define OMAP24XX_DMA_SPI1_RX3 42
# define OMAP24XX_DMA_SPI2_TX0 43
# define OMAP24XX_DMA_SPI2_RX0 44
# define OMAP24XX_DMA_SPI2_TX1 45
# define OMAP24XX_DMA_SPI2_RX1 46
# define OMAP24XX_DMA_UART1_TX 49
# define OMAP24XX_DMA_UART1_RX 50
# define OMAP24XX_DMA_UART2_TX 51
# define OMAP24XX_DMA_UART2_RX 52
# define OMAP24XX_DMA_UART3_TX 53
# define OMAP24XX_DMA_UART3_RX 54
# define OMAP24XX_DMA_USB_W2FC_TX0 55
# define OMAP24XX_DMA_USB_W2FC_RX0 56
# define OMAP24XX_DMA_USB_W2FC_TX1 57
# define OMAP24XX_DMA_USB_W2FC_RX1 58
# define OMAP24XX_DMA_USB_W2FC_TX2 59
# define OMAP24XX_DMA_USB_W2FC_RX2 60
# define OMAP24XX_DMA_MMC1_TX 61
# define OMAP24XX_DMA_MMC1_RX 62
# define OMAP24XX_DMA_MS 63 /* Not in OMAP2420 */
# define OMAP24XX_DMA_EXT_DMAREQ5 64
/* omap[123].c */
struct omap_mpu_timer_s;
struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk);
struct omap_gp_timer_s;
struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
qemu_irq irq, omap_clk fclk, omap_clk iclk);
struct omap_watchdog_timer_s;
struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk);
@ -501,13 +643,21 @@ struct omap_32khz_timer_s;
struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk);
void omap_synctimer_init(struct omap_target_agent_s *ta,
struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk);
struct omap_tipb_bridge_s;
struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
qemu_irq abort_irq, omap_clk clk);
struct omap_uart_s;
struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk, CharDriverState *chr);
qemu_irq irq, omap_clk fclk, omap_clk iclk,
qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr);
struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
qemu_irq irq, omap_clk fclk, omap_clk iclk,
qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr);
void omap_uart_reset(struct omap_uart_s *s);
struct omap_mpuio_s;
struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
@ -523,6 +673,12 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
struct omap_gpif_s;
struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
struct uwire_slave_s {
uint16_t (*receive)(void *opaque);
void (*send)(void *opaque, uint16_t data);
@ -534,6 +690,13 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
void omap_uwire_attach(struct omap_uwire_s *s,
struct uwire_slave_s *slave, int chipselect);
struct omap_mcspi_s;
struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk);
void omap_mcspi_attach(struct omap_mcspi_s *s,
uint32_t (*txrx)(void *opaque, uint32_t), void *opaque,
int chipselect);
struct omap_rtc_s;
struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
qemu_irq *irq, omap_clk clk);
@ -570,6 +733,9 @@ void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave);
struct omap_lpg_s;
struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk);
void omap_tap_init(struct omap_target_agent_s *ta,
struct omap_mpu_state_s *mpu);
/* omap_lcdc.c */
struct omap_lcd_panel_s;
void omap_lcdc_reset(struct omap_lcd_panel_s *s);
@ -577,13 +743,33 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
struct omap_dma_lcd_channel_s *dma, DisplayState *ds,
ram_addr_t imif_base, ram_addr_t emiff_base, omap_clk clk);
/* omap_dss.c */
struct rfbi_chip_s {
void *opaque;
void (*write)(void *opaque, int dc, uint16_t value);
void (*block)(void *opaque, int dc, void *buf, size_t len, int pitch);
uint16_t (*read)(void *opaque, int dc);
};
struct omap_dss_s;
void omap_dss_reset(struct omap_dss_s *s);
struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
target_phys_addr_t l3_base, DisplayState *ds,
qemu_irq irq, qemu_irq drq,
omap_clk fck1, omap_clk fck2, omap_clk ck54m,
omap_clk ick1, omap_clk ick2);
void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
/* omap_mmc.c */
struct omap_mmc_s;
struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
BlockDriverState *bd,
qemu_irq irq, qemu_irq dma[], omap_clk clk);
struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
omap_clk fclk, omap_clk iclk);
void omap_mmc_reset(struct omap_mmc_s *s);
void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
void omap_mmc_enable(struct omap_mmc_s *s, int enable);
/* omap_i2c.c */
struct omap_i2c_s;
@ -596,14 +782,37 @@ i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310)
# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510)
# define cpu_is_omap1610(cpu) (cpu->mpu_model == omap1610)
# define cpu_is_omap1710(cpu) (cpu->mpu_model == omap1710)
# define cpu_is_omap2410(cpu) (cpu->mpu_model == omap2410)
# define cpu_is_omap2420(cpu) (cpu->mpu_model == omap2420)
# define cpu_is_omap2430(cpu) (cpu->mpu_model == omap2430)
# define cpu_is_omap3430(cpu) (cpu->mpu_model == omap3430)
# define cpu_is_omap15xx(cpu) \
(cpu_is_omap310(cpu) || cpu_is_omap1510(cpu))
# define cpu_class_omap1(cpu) 1
# define cpu_is_omap16xx(cpu) \
(cpu_is_omap1610(cpu) || cpu_is_omap1710(cpu))
# define cpu_is_omap24xx(cpu) \
(cpu_is_omap2410(cpu) || cpu_is_omap2420(cpu) || cpu_is_omap2430(cpu))
# define cpu_class_omap1(cpu) \
(cpu_is_omap15xx(cpu) || cpu_is_omap16xx(cpu))
# define cpu_class_omap2(cpu) cpu_is_omap24xx(cpu)
# define cpu_class_omap3(cpu) cpu_is_omap3430(cpu)
struct omap_mpu_state_s {
enum omap1_mpu_model {
enum omap_mpu_model {
omap310,
omap1510,
omap1610,
omap1710,
omap2410,
omap2420,
omap2422,
omap2423,
omap2430,
omap3430,
} mpu_model;
CPUState *env;
@ -620,7 +829,7 @@ struct omap_mpu_state_s {
target_phys_addr_t offset, uint32_t value);
int (*addr_valid)(struct omap_mpu_state_s *s,
target_phys_addr_t addr);
} port[omap_dma_port_last];
} port[__omap_dma_port_last];
unsigned long sdram_size;
unsigned long sram_size;
@ -656,7 +865,7 @@ struct omap_mpu_state_s {
omap_clk clk;
} pwt;
struct omap_i2c_s *i2c;
struct omap_i2c_s *i2c[2];
struct omap_rtc_s *rtc;
@ -722,7 +931,38 @@ struct omap_mpu_state_s {
uint16_t dsp_idlect2;
uint16_t dsp_rstct2;
} clkm;
} *omap310_mpu_init(unsigned long sdram_size,
/* OMAP2-only peripherals */
struct omap_l4_s *l4;
struct omap_gp_timer_s *gptimer[12];
target_phys_addr_t tap_base;
struct omap_synctimer_s {
target_phys_addr_t base;
uint32_t val;
uint16_t readh;
} synctimer;
struct omap_prcm_s *prcm;
struct omap_sdrc_s *sdrc;
struct omap_gpmc_s *gpmc;
struct omap_sysctl_s *sysc;
struct omap_gpif_s *gpif;
struct omap_mcspi_s *mcspi[2];
struct omap_dss_s *dss;
};
/* omap1.c */
struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
DisplayState *ds, const char *core);
/* omap2.c */
struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
DisplayState *ds, const char *core);
# if TARGET_PHYS_ADDR_BITS == 32
@ -743,24 +983,46 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr);
void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
uint32_t value);
void omap_mpu_wakeup(void *opaque, int irq, int req);
# define OMAP_BAD_REG(paddr) \
printf("%s: Bad register " OMAP_FMT_plx "\n", __FUNCTION__, paddr)
# define OMAP_RO_REG(paddr) \
printf("%s: Read-only register " OMAP_FMT_plx "\n", \
fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
# define OMAP_RO_REG(paddr) \
fprintf(stderr, "%s: Read-only register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
/* OMAP-specific Linux bootloader tags for the ATAG_BOARD area
(Board-specifc tags are not here) */
#define OMAP_TAG_CLOCK 0x4f01
#define OMAP_TAG_MMC 0x4f02
#define OMAP_TAG_SERIAL_CONSOLE 0x4f03
#define OMAP_TAG_USB 0x4f04
#define OMAP_TAG_LCD 0x4f05
#define OMAP_TAG_GPIO_SWITCH 0x4f06
#define OMAP_TAG_UART 0x4f07
#define OMAP_TAG_FBMEM 0x4f08
#define OMAP_TAG_STI_CONSOLE 0x4f09
#define OMAP_TAG_CAMERA_SENSOR 0x4f0a
#define OMAP_TAG_PARTITION 0x4f0b
#define OMAP_TAG_TEA5761 0x4f10
#define OMAP_TAG_TMP105 0x4f11
#define OMAP_TAG_BOOT_REASON 0x4f80
#define OMAP_TAG_FLASH_PART_STR 0x4f81
#define OMAP_TAG_VERSION_STR 0x4f82
# define TCMI_VERBOSE 1
//# define MEM_VERBOSE 1
# ifdef TCMI_VERBOSE
# define OMAP_8B_REG(paddr) \
printf("%s: 8-bit register " OMAP_FMT_plx "\n", \
fprintf(stderr, "%s: 8-bit register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
# define OMAP_16B_REG(paddr) \
printf("%s: 16-bit register " OMAP_FMT_plx "\n", \
fprintf(stderr, "%s: 16-bit register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
# define OMAP_32B_REG(paddr) \
printf("%s: 32-bit register " OMAP_FMT_plx "\n", \
fprintf(stderr, "%s: 32-bit register " OMAP_FMT_plx "\n", \
__FUNCTION__, paddr)
# else
# define OMAP_8B_REG(paddr)

View File

@ -5,8 +5,8 @@
*
* 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 of
* the License, or (at your option) any later version.
* 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
@ -23,10 +23,11 @@
#include "omap.h"
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
/* We use pc-style serial ports. */
#include "pc.h"
/* Should signal the TCMI */
/* Should signal the TCMI/GPMC */
uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
{
uint8_t ret;
@ -86,6 +87,7 @@ struct omap_intr_handler_bank_s {
uint32_t mask;
uint32_t fiq;
uint32_t sens_edge;
uint32_t swi;
unsigned char priority[32];
};
@ -94,11 +96,14 @@ struct omap_intr_handler_s {
qemu_irq parent_intr[2];
target_phys_addr_t base;
unsigned char nbanks;
int level_only;
/* state */
uint32_t new_agr[2];
int sir_intr[2];
struct omap_intr_handler_bank_s banks[];
int autoidle;
uint32_t mask;
struct omap_intr_handler_bank_s bank[];
};
static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
@ -113,11 +118,11 @@ static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
* If all interrupts have the same priority, the default order is IRQ_N,
* IRQ_N-1,...,IRQ_0. */
for (j = 0; j < s->nbanks; ++j) {
level = s->banks[j].irqs & ~s->banks[j].mask &
(is_fiq ? s->banks[j].fiq : ~s->banks[j].fiq);
level = s->bank[j].irqs & ~s->bank[j].mask &
(is_fiq ? s->bank[j].fiq : ~s->bank[j].fiq);
for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f,
level >>= f) {
p = s->banks[j].priority[i];
p = s->bank[j].priority[i];
if (p <= p_intr) {
p_intr = p;
sir_intr = 32 * j + i;
@ -134,10 +139,10 @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
uint32_t has_intr = 0;
for (i = 0; i < s->nbanks; ++i)
has_intr |= s->banks[i].irqs & ~s->banks[i].mask &
(is_fiq ? s->banks[i].fiq : ~s->banks[i].fiq);
has_intr |= s->bank[i].irqs & ~s->bank[i].mask &
(is_fiq ? s->bank[i].fiq : ~s->bank[i].fiq);
if (s->new_agr[is_fiq] && has_intr) {
if (s->new_agr[is_fiq] & has_intr & s->mask) {
s->new_agr[is_fiq] = 0;
omap_inth_sir_update(s, is_fiq);
qemu_set_irq(s->parent_intr[is_fiq], 1);
@ -152,13 +157,13 @@ static void omap_set_intr(void *opaque, int irq, int req)
struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
uint32_t rise;
struct omap_intr_handler_bank_s *bank = &ih->banks[irq >> 5];
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
int n = irq & 31;
if (req) {
rise = ~bank->irqs & (1 << n);
if (~bank->sens_edge & (1 << n))
rise &= ~bank->inputs & (1 << n);
rise &= ~bank->inputs;
bank->inputs |= (1 << n);
if (rise) {
@ -173,13 +178,33 @@ static void omap_set_intr(void *opaque, int irq, int req)
}
}
/* Simplified version with no edge detection */
static void omap_set_intr_noedge(void *opaque, int irq, int req)
{
struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
uint32_t rise;
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
int n = irq & 31;
if (req) {
rise = ~bank->inputs & (1 << n);
if (rise) {
bank->irqs |= bank->inputs |= rise;
omap_inth_update(ih, 0);
omap_inth_update(ih, 1);
}
} else
bank->irqs = (bank->inputs &= ~(1 << n)) | bank->swi;
}
static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
{
struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
int i, offset = addr - s->base;
int bank_no = offset >> 8;
int line_no;
struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
offset &= 0xff;
switch (offset) {
@ -194,7 +219,7 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr)
if (bank_no != 0)
break;
line_no = s->sir_intr[(offset - 0x10) >> 2];
bank = &s->banks[line_no >> 5];
bank = &s->bank[line_no >> 5];
i = line_no & 31;
if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE)
bank->irqs &= ~(1 << i);
@ -256,7 +281,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr,
struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
int i, offset = addr - s->base;
int bank_no = offset >> 8;
struct omap_intr_handler_bank_s *bank = &s->banks[bank_no];
struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
offset &= 0xff;
switch (offset) {
@ -360,25 +385,31 @@ void omap_inth_reset(struct omap_intr_handler_s *s)
int i;
for (i = 0; i < s->nbanks; ++i){
s->banks[i].irqs = 0x00000000;
s->banks[i].mask = 0xffffffff;
s->banks[i].sens_edge = 0x00000000;
s->banks[i].fiq = 0x00000000;
s->banks[i].inputs = 0x00000000;
memset(s->banks[i].priority, 0, sizeof(s->banks[i].priority));
s->bank[i].irqs = 0x00000000;
s->bank[i].mask = 0xffffffff;
s->bank[i].sens_edge = 0x00000000;
s->bank[i].fiq = 0x00000000;
s->bank[i].inputs = 0x00000000;
s->bank[i].swi = 0x00000000;
memset(s->bank[i].priority, 0, sizeof(s->bank[i].priority));
if (s->level_only)
s->bank[i].sens_edge = 0xffffffff;
}
s->new_agr[0] = ~0;
s->new_agr[1] = ~0;
s->sir_intr[0] = 0;
s->sir_intr[1] = 0;
s->autoidle = 0;
s->mask = ~0;
qemu_set_irq(s->parent_intr[0], 0);
qemu_set_irq(s->parent_intr[1], 0);
}
struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
unsigned long size, unsigned char nbanks,
unsigned long size, unsigned char nbanks, qemu_irq **pins,
qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk)
{
int iomemtype;
@ -391,6 +422,8 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
s->base = base;
s->nbanks = nbanks;
s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32);
if (pins)
*pins = s->pins;
omap_inth_reset(s);
@ -401,6 +434,227 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
return s;
}
static uint32_t omap2_inth_read(void *opaque, target_phys_addr_t addr)
{
struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
int offset = addr - s->base;
int bank_no, line_no;
struct omap_intr_handler_bank_s *bank = 0;
if ((offset & 0xf80) == 0x80) {
bank_no = (offset & 0x60) >> 5;
if (bank_no < s->nbanks) {
offset &= ~0x60;
bank = &s->bank[bank_no];
}
}
switch (offset) {
case 0x00: /* INTC_REVISION */
return 0x21;
case 0x10: /* INTC_SYSCONFIG */
return (s->autoidle >> 2) & 1;
case 0x14: /* INTC_SYSSTATUS */
return 1; /* RESETDONE */
case 0x40: /* INTC_SIR_IRQ */
return s->sir_intr[0];
case 0x44: /* INTC_SIR_FIQ */
return s->sir_intr[1];
case 0x48: /* INTC_CONTROL */
return (!s->mask) << 2; /* GLOBALMASK */
case 0x4c: /* INTC_PROTECTION */
return 0;
case 0x50: /* INTC_IDLE */
return s->autoidle & 3;
/* Per-bank registers */
case 0x80: /* INTC_ITR */
return bank->inputs;
case 0x84: /* INTC_MIR */
return bank->mask;
case 0x88: /* INTC_MIR_CLEAR */
case 0x8c: /* INTC_MIR_SET */
return 0;
case 0x90: /* INTC_ISR_SET */
return bank->swi;
case 0x94: /* INTC_ISR_CLEAR */
return 0;
case 0x98: /* INTC_PENDING_IRQ */
return bank->irqs & ~bank->mask & ~bank->fiq;
case 0x9c: /* INTC_PENDING_FIQ */
return bank->irqs & ~bank->mask & bank->fiq;
/* Per-line registers */
case 0x100 ... 0x300: /* INTC_ILR */
bank_no = (offset - 0x100) >> 7;
if (bank_no > s->nbanks)
break;
bank = &s->bank[bank_no];
line_no = (offset & 0x7f) >> 2;
return (bank->priority[line_no] << 2) |
((bank->fiq >> line_no) & 1);
}
OMAP_BAD_REG(addr);
return 0;
}
static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
int offset = addr - s->base;
int bank_no, line_no;
struct omap_intr_handler_bank_s *bank = 0;
if ((offset & 0xf80) == 0x80) {
bank_no = (offset & 0x60) >> 5;
if (bank_no < s->nbanks) {
offset &= ~0x60;
bank = &s->bank[bank_no];
}
}
switch (offset) {
case 0x10: /* INTC_SYSCONFIG */
s->autoidle &= 4;
s->autoidle |= (value & 1) << 2;
if (value & 2) /* SOFTRESET */
omap_inth_reset(s);
return;
case 0x48: /* INTC_CONTROL */
s->mask = (value & 4) ? 0 : ~0; /* GLOBALMASK */
if (value & 2) { /* NEWFIQAGR */
qemu_set_irq(s->parent_intr[1], 0);
s->new_agr[1] = ~0;
omap_inth_update(s, 1);
}
if (value & 1) { /* NEWIRQAGR */
qemu_set_irq(s->parent_intr[0], 0);
s->new_agr[0] = ~0;
omap_inth_update(s, 0);
}
return;
case 0x4c: /* INTC_PROTECTION */
/* TODO: Make a bitmap (or sizeof(char)map) of access privileges
* for every register, see Chapter 3 and 4 for privileged mode. */
if (value & 1)
fprintf(stderr, "%s: protection mode enable attempt\n",
__FUNCTION__);
return;
case 0x50: /* INTC_IDLE */
s->autoidle &= ~3;
s->autoidle |= value & 3;
return;
/* Per-bank registers */
case 0x84: /* INTC_MIR */
bank->mask = value;
omap_inth_update(s, 0);
omap_inth_update(s, 1);
return;
case 0x88: /* INTC_MIR_CLEAR */
bank->mask &= ~value;
omap_inth_update(s, 0);
omap_inth_update(s, 1);
return;
case 0x8c: /* INTC_MIR_SET */
bank->mask |= value;
return;
case 0x90: /* INTC_ISR_SET */
bank->irqs |= bank->swi |= value;
omap_inth_update(s, 0);
omap_inth_update(s, 1);
return;
case 0x94: /* INTC_ISR_CLEAR */
bank->swi &= ~value;
bank->irqs = bank->swi & bank->inputs;
return;
/* Per-line registers */
case 0x100 ... 0x300: /* INTC_ILR */
bank_no = (offset - 0x100) >> 7;
if (bank_no > s->nbanks)
break;
bank = &s->bank[bank_no];
line_no = (offset & 0x7f) >> 2;
bank->priority[line_no] = (value >> 2) & 0x3f;
bank->fiq &= ~(1 << line_no);
bank->fiq |= (value & 1) << line_no;
return;
case 0x00: /* INTC_REVISION */
case 0x14: /* INTC_SYSSTATUS */
case 0x40: /* INTC_SIR_IRQ */
case 0x44: /* INTC_SIR_FIQ */
case 0x80: /* INTC_ITR */
case 0x98: /* INTC_PENDING_IRQ */
case 0x9c: /* INTC_PENDING_FIQ */
OMAP_RO_REG(addr);
return;
}
OMAP_BAD_REG(addr);
}
static CPUReadMemoryFunc *omap2_inth_readfn[] = {
omap_badwidth_read32,
omap_badwidth_read32,
omap2_inth_read,
};
static CPUWriteMemoryFunc *omap2_inth_writefn[] = {
omap2_inth_write,
omap2_inth_write,
omap2_inth_write,
};
struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
int size, int nbanks, qemu_irq **pins,
qemu_irq parent_irq, qemu_irq parent_fiq,
omap_clk fclk, omap_clk iclk)
{
int iomemtype;
struct omap_intr_handler_s *s = (struct omap_intr_handler_s *)
qemu_mallocz(sizeof(struct omap_intr_handler_s) +
sizeof(struct omap_intr_handler_bank_s) * nbanks);
s->parent_intr[0] = parent_irq;
s->parent_intr[1] = parent_fiq;
s->base = base;
s->nbanks = nbanks;
s->level_only = 1;
s->pins = qemu_allocate_irqs(omap_set_intr_noedge, s, nbanks * 32);
if (pins)
*pins = s->pins;
omap_inth_reset(s);
iomemtype = cpu_register_io_memory(0, omap2_inth_readfn,
omap2_inth_writefn, s);
cpu_register_physical_memory(s->base, size, iomemtype);
return s;
}
/* MPU OS timers */
struct omap_mpu_timer_s {
qemu_irq irq;
@ -1289,6 +1543,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
return 0x03310315;
case omap1510:
return 0x03310115;
default:
cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
}
break;
@ -1298,6 +1554,8 @@ static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
return 0xfb57402f;
case omap1510:
return 0xfb47002f;
default:
cpu_abort(cpu_single_env, "%s: bad mpu model\n", __FUNCTION__);
}
break;
}
@ -1722,19 +1980,116 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
/* UARTs */
struct omap_uart_s {
SerialState *serial; /* TODO */
struct omap_target_agent_s *ta;
target_phys_addr_t base;
uint8_t eblr;
uint8_t syscontrol;
uint8_t wkup;
uint8_t cfps;
};
static void omap_uart_reset(struct omap_uart_s *s)
void omap_uart_reset(struct omap_uart_s *s)
{
s->eblr = 0x00;
s->syscontrol = 0;
s->wkup = 0x3f;
s->cfps = 0x69;
}
struct omap_uart_s *omap_uart_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk, CharDriverState *chr)
qemu_irq irq, omap_clk fclk, omap_clk iclk,
qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
{
struct omap_uart_s *s = (struct omap_uart_s *)
qemu_mallocz(sizeof(struct omap_uart_s));
if (chr)
s->serial = serial_mm_init(base, 2, irq, chr, 1);
s->serial = serial_mm_init(base, 2, irq, chr ?: qemu_chr_open("null"), 1);
return s;
}
static uint32_t omap_uart_read(void *opaque, target_phys_addr_t addr)
{
struct omap_uart_s *s = (struct omap_uart_s *) opaque;
int offset = addr - s->base;
switch (offset) {
case 0x48: /* EBLR */
return s->eblr;
case 0x50: /* MVR */
return 0x30;
case 0x54: /* SYSC */
return s->syscontrol;
case 0x58: /* SYSS */
return 1;
case 0x5c: /* WER */
return s->wkup;
case 0x60: /* CFPS */
return s->cfps;
}
OMAP_BAD_REG(addr);
return 0;
}
static void omap_uart_write(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
struct omap_uart_s *s = (struct omap_uart_s *) opaque;
int offset = addr - s->base;
switch (offset) {
case 0x48: /* EBLR */
s->eblr = value & 0xff;
break;
case 0x50: /* MVR */
case 0x58: /* SYSS */
OMAP_RO_REG(addr);
break;
case 0x54: /* SYSC */
s->syscontrol = value & 0x1d;
if (value & 2)
omap_uart_reset(s);
break;
case 0x5c: /* WER */
s->wkup = value & 0x7f;
break;
case 0x60: /* CFPS */
s->cfps = value & 0xff;
break;
default:
OMAP_BAD_REG(addr);
}
}
static CPUReadMemoryFunc *omap_uart_readfn[] = {
omap_uart_read,
omap_uart_read,
omap_badwidth_read8,
};
static CPUWriteMemoryFunc *omap_uart_writefn[] = {
omap_uart_write,
omap_uart_write,
omap_badwidth_write8,
};
struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
qemu_irq irq, omap_clk fclk, omap_clk iclk,
qemu_irq txdma, qemu_irq rxdma, CharDriverState *chr)
{
target_phys_addr_t base = omap_l4_attach(ta, 0, 0);
struct omap_uart_s *s = omap_uart_init(base, irq,
fclk, iclk, txdma, rxdma, chr);
int iomemtype = cpu_register_io_memory(0, omap_uart_readfn,
omap_uart_writefn, s);
s->ta = ta;
s->base = base;
cpu_register_physical_memory(s->base + 0x20, 0x100, iomemtype);
return s;
}
@ -2778,9 +3133,10 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
void omap_uwire_attach(struct omap_uwire_s *s,
struct uwire_slave_s *slave, int chipselect)
{
if (chipselect < 0 || chipselect > 3)
cpu_abort(cpu_single_env, "%s: Bad chipselect %i\n", __FUNCTION__,
chipselect);
if (chipselect < 0 || chipselect > 3) {
fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
exit(-1);
}
s->chip[chipselect] = slave;
}
@ -4123,7 +4479,7 @@ static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu)
}
/* General chip reset */
static void omap_mpu_reset(void *opaque)
static void omap1_mpu_reset(void *opaque)
{
struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
@ -4153,7 +4509,7 @@ static void omap_mpu_reset(void *opaque)
omap_uwire_reset(mpu->microwire);
omap_pwl_reset(mpu);
omap_pwt_reset(mpu);
omap_i2c_reset(mpu->i2c);
omap_i2c_reset(mpu->i2c[0]);
omap_rtc_reset(mpu->rtc);
omap_mcbsp_reset(mpu->mcbsp1);
omap_mcbsp_reset(mpu->mcbsp2);
@ -4205,7 +4561,7 @@ static void omap_setup_dsp_mapping(const struct omap_map_s *map)
}
}
static void omap_mpu_wakeup(void *opaque, int irq, int req)
void omap_mpu_wakeup(void *opaque, int irq, int req)
{
struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
@ -4213,7 +4569,7 @@ static void omap_mpu_wakeup(void *opaque, int irq, int req)
cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
}
static const struct dma_irq_map omap_dma_irq_map[] = {
static const struct dma_irq_map omap1_dma_irq_map[] = {
{ 0, OMAP_INT_DMA_CH0_6 },
{ 0, OMAP_INT_DMA_CH1_7 },
{ 0, OMAP_INT_DMA_CH2_8 },
@ -4307,17 +4663,16 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
omap_clkm_init(0xfffece00, 0xe1008000, s);
cpu_irq = arm_pic_init_cpu(s->env);
s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1,
s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, &s->irq[0],
cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
omap_findclk(s, "arminth_ck"));
s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1,
s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, &s->irq[1],
s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL,
omap_findclk(s, "arminth_ck"));
s->irq[0] = s->ih[0]->pins;
s->irq[1] = s->ih[1]->pins;
for (i = 0; i < 6; i ++)
dma_irqs[i] = s->irq[omap_dma_irq_map[i].ih][omap_dma_irq_map[i].intr];
dma_irqs[i] =
s->irq[omap1_dma_irq_map[i].ih][omap1_dma_irq_map[i].intr];
s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD],
s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
@ -4367,12 +4722,18 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
omap_findclk(s, "uart1_ck"),
omap_findclk(s, "uart1_ck"),
s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
serial_hds[0]);
s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
omap_findclk(s, "uart2_ck"),
omap_findclk(s, "uart2_ck"),
s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
serial_hds[0] ? serial_hds[1] : 0);
s->uart[2] = omap_uart_init(0xe1019800, s->irq[0][OMAP_INT_UART3],
omap_findclk(s, "uart3_ck"),
omap_findclk(s, "uart3_ck"),
s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1"));
@ -4401,7 +4762,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
s->i2c[0] = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
&s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
@ -4435,7 +4796,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
omap_setup_dsp_mapping(omap15xx_dsp_mm);
omap_setup_mpui_io(s);
qemu_register_reset(omap_mpu_reset, s);
qemu_register_reset(omap1_mpu_reset, s);
return s;
}

3860
hw/omap2.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* OMAP clocks.
*
* Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
* Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
*
* Clocks data comes in part from arch/arm/mach-omap1/clock.h in Linux.
*
@ -34,6 +34,9 @@ struct clk {
#define CLOCK_IN_OMAP730 (1 << 11)
#define CLOCK_IN_OMAP1510 (1 << 12)
#define CLOCK_IN_OMAP16XX (1 << 13)
#define CLOCK_IN_OMAP242X (1 << 14)
#define CLOCK_IN_OMAP243X (1 << 15)
#define CLOCK_IN_OMAP343X (1 << 16)
uint32_t flags;
int id;
@ -55,7 +58,8 @@ static struct clk xtal_osc12m = {
static struct clk xtal_osc32k = {
.name = "xtal_osc_32k",
.rate = 32768,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP310 |
CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
};
static struct clk ck_ref = {
@ -502,11 +506,441 @@ static struct clk i2c_ick = {
static struct clk clk32k = {
.name = "clk32-kHz",
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
ALWAYS_ENABLED,
.parent = &xtal_osc32k,
CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
.parent = &xtal_osc32k,
};
static struct clk apll_96m = {
.name = "apll_96m",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
.rate = 96000000,
/*.parent = sys.xtalin */
};
static struct clk apll_54m = {
.name = "apll_54m",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
.rate = 54000000,
/*.parent = sys.xtalin */
};
static struct clk sys_clk = {
.name = "sys_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
.rate = 32768,
/*.parent = sys.xtalin */
};
static struct clk sleep_clk = {
.name = "sleep_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
.rate = 32768,
/*.parent = sys.xtalin */
};
static struct clk dpll_ck = {
.name = "dpll",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
/*.parent = sys.xtalin */
};
static struct clk dpll_x2_ck = {
.name = "dpll_x2",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
/*.parent = sys.xtalin */
};
static struct clk wdt1_sys_clk = {
.name = "wdt1_sys_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | ALWAYS_ENABLED,
.rate = 32768,
/*.parent = sys.xtalin */
};
static struct clk func_96m_clk = {
.name = "func_96m_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.divisor = 1,
.parent = &apll_96m,
};
static struct clk func_48m_clk = {
.name = "func_48m_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.divisor = 2,
.parent = &apll_96m,
};
static struct clk func_12m_clk = {
.name = "func_12m_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.divisor = 8,
.parent = &apll_96m,
};
static struct clk func_54m_clk = {
.name = "func_54m_clk",
.flags = CLOCK_IN_OMAP242X,
.divisor = 1,
.parent = &apll_54m,
};
static struct clk sys_clkout = {
.name = "clkout",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk sys_clkout2 = {
.name = "clkout2",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_clk = {
.name = "core_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &dpll_ck,
};
static struct clk l3_clk = {
.name = "l3_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_clk,
};
static struct clk core_l4_iclk = {
.name = "core_l4_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &l3_clk,
};
static struct clk wu_l4_iclk = {
.name = "wu_l4_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &l3_clk,
};
static struct clk core_l3_iclk = {
.name = "core_l3_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_clk,
};
static struct clk core_l4_usb_clk = {
.name = "core_l4_usb_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &l3_clk,
};
static struct clk wu_gpt1_clk = {
.name = "wu_gpt1_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk wu_32k_clk = {
.name = "wu_32k_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk uart1_fclk = {
.name = "uart1_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_48m_clk,
};
static struct clk uart1_iclk = {
.name = "uart1_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
};
static struct clk uart2_fclk = {
.name = "uart2_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_48m_clk,
};
static struct clk uart2_iclk = {
.name = "uart2_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
};
static struct clk uart3_fclk = {
.name = "uart3_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_48m_clk,
};
static struct clk uart3_iclk = {
.name = "uart3_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
};
static struct clk mpu_fclk = {
.name = "mpu_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_clk,
};
static struct clk mpu_iclk = {
.name = "mpu_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_clk,
};
static struct clk int_m_fclk = {
.name = "int_m_fclk",
.alias = "mpu_intc_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_clk,
};
static struct clk int_m_iclk = {
.name = "int_m_iclk",
.alias = "mpu_intc_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_clk,
};
static struct clk core_gpt2_clk = {
.name = "core_gpt2_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt3_clk = {
.name = "core_gpt3_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt4_clk = {
.name = "core_gpt4_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt5_clk = {
.name = "core_gpt5_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt6_clk = {
.name = "core_gpt6_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt7_clk = {
.name = "core_gpt7_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt8_clk = {
.name = "core_gpt8_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt9_clk = {
.name = "core_gpt9_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt10_clk = {
.name = "core_gpt10_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt11_clk = {
.name = "core_gpt11_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk core_gpt12_clk = {
.name = "core_gpt12_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
};
static struct clk mcbsp1_clk = {
.name = "mcbsp1_cg",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.divisor = 2,
.parent = &func_96m_clk,
};
static struct clk mcbsp2_clk = {
.name = "mcbsp2_cg",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.divisor = 2,
.parent = &func_96m_clk,
};
static struct clk emul_clk = {
.name = "emul_ck",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_54m_clk,
};
static struct clk sdma_fclk = {
.name = "sdma_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &l3_clk,
};
static struct clk sdma_iclk = {
.name = "sdma_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l3_iclk, /* core_l4_iclk for the configuration port */
};
static struct clk i2c1_fclk = {
.name = "i2c1.fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_12m_clk,
.divisor = 1,
};
static struct clk i2c1_iclk = {
.name = "i2c1.iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
};
static struct clk i2c2_fclk = {
.name = "i2c2.fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_12m_clk,
.divisor = 1,
};
static struct clk i2c2_iclk = {
.name = "i2c2.iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
};
static struct clk gpio_dbclk[4] = {
{
.name = "gpio1_dbclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &wu_32k_clk,
}, {
.name = "gpio2_dbclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &wu_32k_clk,
}, {
.name = "gpio3_dbclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &wu_32k_clk,
}, {
.name = "gpio4_dbclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &wu_32k_clk,
},
};
static struct clk gpio_iclk = {
.name = "gpio_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &wu_l4_iclk,
};
static struct clk mmc_fck = {
.name = "mmc_fclk",
.flags = CLOCK_IN_OMAP242X,
.parent = &func_96m_clk,
};
static struct clk mmc_ick = {
.name = "mmc_iclk",
.flags = CLOCK_IN_OMAP242X,
.parent = &core_l4_iclk,
};
static struct clk spi_fclk[3] = {
{
.name = "spi1_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_48m_clk,
}, {
.name = "spi2_fclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_48m_clk,
}, {
.name = "spi3_fclk",
.flags = CLOCK_IN_OMAP243X,
.parent = &func_48m_clk,
},
};
static struct clk dss_clk[2] = {
{
.name = "dss_clk1",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_clk,
}, {
.name = "dss_clk2",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &sys_clk,
},
};
static struct clk dss_54m_clk = {
.name = "dss_54m_clk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &func_54m_clk,
};
static struct clk dss_l3_iclk = {
.name = "dss_l3_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l3_iclk,
};
static struct clk dss_l4_iclk = {
.name = "dss_l4_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
};
static struct clk spi_iclk[3] = {
{
.name = "spi1_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
}, {
.name = "spi2_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
}, {
.name = "spi3_iclk",
.flags = CLOCK_IN_OMAP243X,
.parent = &core_l4_iclk,
},
};
static struct clk omapctrl_clk = {
.name = "omapctrl_iclk",
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
/* XXX Should be in WKUP domain */
.parent = &core_l4_iclk,
};
static struct clk *onchip_clks[] = {
/* OMAP 1 */
/* non-ULPD clocks */
&xtal_osc12m,
&xtal_osc32k,
@ -572,6 +1006,80 @@ static struct clk *onchip_clks[] = {
/* Virtual clocks */
&i2c_fck,
&i2c_ick,
/* OMAP 2 */
&apll_96m,
&apll_54m,
&sys_clk,
&sleep_clk,
&dpll_ck,
&dpll_x2_ck,
&wdt1_sys_clk,
&func_96m_clk,
&func_48m_clk,
&func_12m_clk,
&func_54m_clk,
&sys_clkout,
&sys_clkout2,
&core_clk,
&l3_clk,
&core_l4_iclk,
&wu_l4_iclk,
&core_l3_iclk,
&core_l4_usb_clk,
&wu_gpt1_clk,
&wu_32k_clk,
&uart1_fclk,
&uart1_iclk,
&uart2_fclk,
&uart2_iclk,
&uart3_fclk,
&uart3_iclk,
&mpu_fclk,
&mpu_iclk,
&int_m_fclk,
&int_m_iclk,
&core_gpt2_clk,
&core_gpt3_clk,
&core_gpt4_clk,
&core_gpt5_clk,
&core_gpt6_clk,
&core_gpt7_clk,
&core_gpt8_clk,
&core_gpt9_clk,
&core_gpt10_clk,
&core_gpt11_clk,
&core_gpt12_clk,
&mcbsp1_clk,
&mcbsp2_clk,
&emul_clk,
&sdma_fclk,
&sdma_iclk,
&i2c1_fclk,
&i2c1_iclk,
&i2c2_fclk,
&i2c2_iclk,
&gpio_dbclk[0],
&gpio_dbclk[1],
&gpio_dbclk[2],
&gpio_dbclk[3],
&gpio_iclk,
&mmc_fck,
&mmc_ick,
&spi_fclk[0],
&spi_iclk[0],
&spi_fclk[1],
&spi_iclk[1],
&spi_fclk[2],
&spi_iclk[2],
&dss_clk[0],
&dss_clk[1],
&dss_54m_clk,
&dss_l3_iclk,
&dss_l4_iclk,
&omapctrl_clk,
0
};
@ -727,6 +1235,12 @@ void omap_clk_init(struct omap_mpu_state_s *mpu)
flag = CLOCK_IN_OMAP310;
else if (cpu_is_omap1510(mpu))
flag = CLOCK_IN_OMAP1510;
else if (cpu_is_omap2410(mpu) || cpu_is_omap2420(mpu))
flag = CLOCK_IN_OMAP242X;
else if (cpu_is_omap2430(mpu))
flag = CLOCK_IN_OMAP243X;
else if (cpu_is_omap3430(mpu))
flag = CLOCK_IN_OMAP243X;
else
return;

View File

@ -28,12 +28,15 @@ struct omap_dma_channel_s {
/* transfer data */
int burst[2];
int pack[2];
int endian[2];
int endian_lock[2];
int translate[2];
enum omap_dma_port port[2];
target_phys_addr_t addr[2];
omap_dma_addressing_t mode[2];
uint16_t elements;
uint32_t elements;
uint16_t frames;
int16_t frame_index[2];
int32_t frame_index[2];
int16_t element_index[2];
int data_type;
@ -41,6 +44,7 @@ struct omap_dma_channel_s {
int transparent_copy;
int constant_fill;
uint32_t color;
int prefetch;
/* auto init and linked channel data */
int end_prog;
@ -52,11 +56,13 @@ struct omap_dma_channel_s {
/* interruption data */
int interrupts;
int status;
int cstatus;
/* state data */
int active;
int enable;
int sync;
int src_sync;
int pending_request;
int waiting_end_prog;
uint16_t cpc;
@ -75,16 +81,21 @@ struct omap_dma_channel_s {
target_phys_addr_t src, dest;
int frame;
int element;
int pck_element;
int frame_delta[2];
int elem_delta[2];
int frames;
int elements;
int pck_elements;
} active_set;
/* unused parameters */
int write_mode;
int priority;
int interleave_disabled;
int type;
int suspend;
int buf_disable;
};
struct omap_dma_s {
@ -93,15 +104,21 @@ struct omap_dma_s {
target_phys_addr_t base;
omap_clk clk;
int64_t delay;
uint32_t drq;
uint64_t drq;
qemu_irq irq[4];
void (*intr_update)(struct omap_dma_s *s);
enum omap_dma_model model;
int omap_3_1_mapping_disabled;
uint16_t gcr;
uint32_t gcr;
uint32_t ocp;
uint32_t caps[5];
uint32_t irqen[4];
uint32_t irqstat[4];
int run_count;
int chans;
struct omap_dma_channel_s ch[16];
struct omap_dma_channel_s ch[32];
struct omap_dma_lcd_channel_s lcd_ch;
};
@ -113,23 +130,13 @@ struct omap_dma_s {
#define LAST_FRAME_INTR (1 << 4)
#define END_BLOCK_INTR (1 << 5)
#define SYNC (1 << 6)
#define END_PKT_INTR (1 << 7)
#define TRANS_ERR_INTR (1 << 8)
#define MISALIGN_INTR (1 << 11)
static void omap_dma_interrupts_update(struct omap_dma_s *s)
static inline void omap_dma_interrupts_update(struct omap_dma_s *s)
{
struct omap_dma_channel_s *ch = s->ch;
int i;
if (s->omap_3_1_mapping_disabled) {
for (i = 0; i < s->chans; i ++, ch ++)
if (ch->status)
qemu_irq_raise(ch->irq);
} else {
/* First three interrupts are shared between two channels each. */
for (i = 0; i < 6; i ++, ch ++) {
if (ch->status || (ch->sibling && ch->sibling->status))
qemu_irq_raise(ch->irq);
}
}
return s->intr_update(s);
}
static void omap_dma_channel_load(struct omap_dma_s *s,
@ -148,8 +155,10 @@ static void omap_dma_channel_load(struct omap_dma_s *s,
a->dest = ch->addr[1];
a->frames = ch->frames;
a->elements = ch->elements;
a->pck_elements = ch->frame_index[!ch->src_sync];
a->frame = 0;
a->element = 0;
a->pck_element = 0;
if (unlikely(!ch->elements || !ch->frames)) {
printf("%s: bad DMA request\n", __FUNCTION__);
@ -202,16 +211,15 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s,
/* Update cpc */
ch->cpc = ch->active_set.dest & 0xffff;
if (ch->pending_request && !ch->waiting_end_prog) {
if (ch->pending_request && !ch->waiting_end_prog && ch->enable) {
/* Don't deactivate the channel */
ch->pending_request = 0;
if (ch->enable)
return;
return;
}
/* Don't deactive the channel if it is synchronized and the DMA request is
active */
if (ch->sync && (s->drq & (1 << ch->sync)) && ch->enable)
if (ch->sync && ch->enable && (s->drq & (1 << ch->sync)))
return;
if (ch->active) {
@ -231,6 +239,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s,
ch->enable = 1;
ch->waiting_end_prog = 0;
omap_dma_channel_load(s, ch);
/* TODO: theoretically if ch->sync && ch->prefetch &&
* !s->drq[ch->sync], we should also activate and fetch from source
* and then stall until signalled. */
if ((!ch->sync) || (s->drq & (1 << ch->sync)))
omap_dma_activate_channel(s, ch);
}
@ -259,16 +270,47 @@ static void omap_dma_channel_end_prog(struct omap_dma_s *s,
}
}
static void omap_dma_interrupts_3_1_update(struct omap_dma_s *s)
{
struct omap_dma_channel_s *ch = s->ch;
/* First three interrupts are shared between two channels each. */
if (ch[0].status | ch[6].status)
qemu_irq_raise(ch[0].irq);
if (ch[1].status | ch[7].status)
qemu_irq_raise(ch[1].irq);
if (ch[2].status | ch[8].status)
qemu_irq_raise(ch[2].irq);
if (ch[3].status)
qemu_irq_raise(ch[3].irq);
if (ch[4].status)
qemu_irq_raise(ch[4].irq);
if (ch[5].status)
qemu_irq_raise(ch[5].irq);
}
static void omap_dma_interrupts_3_2_update(struct omap_dma_s *s)
{
struct omap_dma_channel_s *ch = s->ch;
int i;
for (i = s->chans; i; ch ++, i --)
if (ch->status)
qemu_irq_raise(ch->irq);
}
static void omap_dma_enable_3_1_mapping(struct omap_dma_s *s)
{
s->omap_3_1_mapping_disabled = 0;
s->chans = 9;
s->intr_update = omap_dma_interrupts_3_1_update;
}
static void omap_dma_disable_3_1_mapping(struct omap_dma_s *s)
{
s->omap_3_1_mapping_disabled = 1;
s->chans = 16;
s->intr_update = omap_dma_interrupts_3_2_update;
}
static void omap_dma_process_request(struct omap_dma_s *s, int request)
@ -358,6 +400,22 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
if (ch->interrupts & HALF_FRAME_INTR)
ch->status |= HALF_FRAME_INTR;
if (ch->fs && ch->bs) {
a->pck_element ++;
/* Check if a full packet has beed transferred. */
if (a->pck_element == a->pck_elements) {
a->pck_element = 0;
/* Set the END_PKT interrupt */
if ((ch->interrupts & END_PKT_INTR) && !ch->src_sync)
ch->status |= END_PKT_INTR;
/* If the channel is packet-synchronized, deactivate it */
if (ch->sync)
omap_dma_deactivate_channel(s, ch);
}
}
if (a->element == a->elements) {
/* End of Frame */
a->element = 0;
@ -366,7 +424,7 @@ static void omap_dma_channel_run(struct omap_dma_s *s)
a->frame ++;
/* If the channel is frame synchronized, deactivate it */
if (ch->sync && ch->fs)
if (ch->sync && ch->fs && !ch->bs)
omap_dma_deactivate_channel(s, ch);
/* If the channel is async, update cpc */
@ -414,50 +472,62 @@ void omap_dma_reset(struct omap_dma_s *s)
int i;
qemu_del_timer(s->tm);
s->gcr = 0x0004;
if (s->model < omap_dma_4)
s->gcr = 0x0004;
else
s->gcr = 0x00010010;
s->ocp = 0x00000000;
memset(&s->irqstat, 0, sizeof(s->irqstat));
memset(&s->irqen, 0, sizeof(s->irqen));
s->drq = 0x00000000;
s->run_count = 0;
s->lcd_ch.src = emiff;
s->lcd_ch.condition = 0;
s->lcd_ch.interrupts = 0;
s->lcd_ch.dual = 0;
omap_dma_enable_3_1_mapping(s);
if (s->model < omap_dma_4)
omap_dma_enable_3_1_mapping(s);
for (i = 0; i < s->chans; i ++) {
s->ch[i].suspend = 0;
s->ch[i].prefetch = 0;
s->ch[i].buf_disable = 0;
s->ch[i].src_sync = 0;
memset(&s->ch[i].burst, 0, sizeof(s->ch[i].burst));
memset(&s->ch[i].port, 0, sizeof(s->ch[i].port));
memset(&s->ch[i].mode, 0, sizeof(s->ch[i].mode));
memset(&s->ch[i].elements, 0, sizeof(s->ch[i].elements));
memset(&s->ch[i].frames, 0, sizeof(s->ch[i].frames));
memset(&s->ch[i].frame_index, 0, sizeof(s->ch[i].frame_index));
memset(&s->ch[i].element_index, 0, sizeof(s->ch[i].element_index));
memset(&s->ch[i].data_type, 0, sizeof(s->ch[i].data_type));
memset(&s->ch[i].transparent_copy, 0,
sizeof(s->ch[i].transparent_copy));
memset(&s->ch[i].constant_fill, 0, sizeof(s->ch[i].constant_fill));
memset(&s->ch[i].color, 0, sizeof(s->ch[i].color));
memset(&s->ch[i].end_prog, 0, sizeof(s->ch[i].end_prog));
memset(&s->ch[i].repeat, 0, sizeof(s->ch[i].repeat));
memset(&s->ch[i].auto_init, 0, sizeof(s->ch[i].auto_init));
memset(&s->ch[i].link_enabled, 0, sizeof(s->ch[i].link_enabled));
memset(&s->ch[i].link_next_ch, 0, sizeof(s->ch[i].link_next_ch));
s->ch[i].interrupts = 0x0003;
memset(&s->ch[i].status, 0, sizeof(s->ch[i].status));
memset(&s->ch[i].active, 0, sizeof(s->ch[i].active));
memset(&s->ch[i].enable, 0, sizeof(s->ch[i].enable));
memset(&s->ch[i].sync, 0, sizeof(s->ch[i].sync));
memset(&s->ch[i].pending_request, 0, sizeof(s->ch[i].pending_request));
memset(&s->ch[i].waiting_end_prog, 0,
sizeof(s->ch[i].waiting_end_prog));
memset(&s->ch[i].cpc, 0, sizeof(s->ch[i].cpc));
memset(&s->ch[i].fs, 0, sizeof(s->ch[i].fs));
memset(&s->ch[i].bs, 0, sizeof(s->ch[i].bs));
memset(&s->ch[i].omap_3_1_compatible_disable, 0,
sizeof(s->ch[i].omap_3_1_compatible_disable));
memset(&s->ch[i].endian, 0, sizeof(s->ch[i].endian));
memset(&s->ch[i].endian_lock, 0, sizeof(s->ch[i].endian_lock));
memset(&s->ch[i].translate, 0, sizeof(s->ch[i].translate));
s->ch[i].write_mode = 0;
s->ch[i].data_type = 0;
s->ch[i].transparent_copy = 0;
s->ch[i].constant_fill = 0;
s->ch[i].color = 0x00000000;
s->ch[i].end_prog = 0;
s->ch[i].repeat = 0;
s->ch[i].auto_init = 0;
s->ch[i].link_enabled = 0;
if (s->model < omap_dma_4)
s->ch[i].interrupts = 0x0003;
else
s->ch[i].interrupts = 0x0000;
s->ch[i].status = 0;
s->ch[i].cstatus = 0;
s->ch[i].active = 0;
s->ch[i].enable = 0;
s->ch[i].sync = 0;
s->ch[i].pending_request = 0;
s->ch[i].waiting_end_prog = 0;
s->ch[i].cpc = 0x0000;
s->ch[i].fs = 0;
s->ch[i].bs = 0;
s->ch[i].omap_3_1_compatible_disable = 0;
memset(&s->ch[i].active_set, 0, sizeof(s->ch[i].active_set));
memset(&s->ch[i].priority, 0, sizeof(s->ch[i].priority));
memset(&s->ch[i].interleave_disabled, 0,
sizeof(s->ch[i].interleave_disabled));
memset(&s->ch[i].type, 0, sizeof(s->ch[i].type));
s->ch[i].priority = 0;
s->ch[i].interleave_disabled = 0;
s->ch[i].type = 0;
}
}
@ -476,7 +546,7 @@ static int omap_dma_ch_reg_read(struct omap_dma_s *s,
break;
case 0x02: /* SYS_DMA_CCR_CH0 */
if (s->model == omap_dma_3_1)
if (s->model <= omap_dma_3_1)
*value = 0 << 10; /* FIFO_FLUSH reads as 0 */
else
*value = ch->omap_3_1_compatible_disable << 10;
@ -596,11 +666,11 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
ch->burst[0] = (value & 0x0180) >> 7;
ch->pack[0] = (value & 0x0040) >> 6;
ch->port[0] = (enum omap_dma_port) ((value & 0x003c) >> 2);
ch->data_type = (1 << (value & 3));
if (ch->port[0] >= omap_dma_port_last)
ch->data_type = 1 << (value & 3);
if (ch->port[0] >= __omap_dma_port_last)
printf("%s: invalid DMA port %i\n", __FUNCTION__,
ch->port[0]);
if (ch->port[1] >= omap_dma_port_last)
if (ch->port[1] >= __omap_dma_port_last)
printf("%s: invalid DMA port %i\n", __FUNCTION__,
ch->port[1]);
if ((value & 3) == 3)
@ -611,7 +681,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
ch->end_prog = (value & 0x0800) >> 11;
if (s->model > omap_dma_3_1)
if (s->model >= omap_dma_3_2)
ch->omap_3_1_compatible_disable = (value >> 10) & 0x1;
ch->repeat = (value & 0x0200) >> 9;
ch->auto_init = (value & 0x0100) >> 8;
@ -630,7 +700,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
break;
case 0x04: /* SYS_DMA_CICR_CH0 */
ch->interrupts = value;
ch->interrupts = value & 0x3f;
break;
case 0x06: /* SYS_DMA_CSR_CH0 */
@ -696,7 +766,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s,
break;
case 0x24: /* DMA_CCR2 */
ch->bs = (value >> 2) & 0x1;
ch->bs = (value >> 2) & 0x1;
ch->transparent_copy = (value >> 1) & 0x1;
ch->constant_fill = value & 0x1;
break;
@ -1126,48 +1196,29 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
break;
case 0x44e: /* DMA_CAPS_0_U */
*ret = (1 << 3) | /* Constant Fill Capacity */
(1 << 2); /* Transparent BLT Capacity */
*ret = (s->caps[0] >> 16) & 0xffff;
break;
case 0x450: /* DMA_CAPS_0_L */
case 0x452: /* DMA_CAPS_1_U */
*ret = 0;
*ret = (s->caps[0] >> 0) & 0xffff;
break;
case 0x452: /* DMA_CAPS_1_U */
*ret = (s->caps[1] >> 16) & 0xffff;
break;
case 0x454: /* DMA_CAPS_1_L */
*ret = (1 << 1); /* 1-bit palletized capability */
*ret = (s->caps[1] >> 0) & 0xffff;
break;
case 0x456: /* DMA_CAPS_2 */
*ret = (1 << 8) | /* SSDIC */
(1 << 7) | /* DDIAC */
(1 << 6) | /* DSIAC */
(1 << 5) | /* DPIAC */
(1 << 4) | /* DCAC */
(1 << 3) | /* SDIAC */
(1 << 2) | /* SSIAC */
(1 << 1) | /* SPIAC */
1; /* SCAC */
*ret = s->caps[2];
break;
case 0x458: /* DMA_CAPS_3 */
*ret = (1 << 5) | /* CCC */
(1 << 4) | /* IC */
(1 << 3) | /* ARC */
(1 << 2) | /* AEC */
(1 << 1) | /* FSC */
1; /* ESC */
*ret = s->caps[3];
break;
case 0x45a: /* DMA_CAPS_4 */
*ret = (1 << 6) | /* SSC */
(1 << 5) | /* BIC */
(1 << 4) | /* LFIC */
(1 << 3) | /* FIC */
(1 << 2) | /* HFIC */
(1 << 1) | /* EDIC */
1; /* TOIC */
*ret = s->caps[4];
break;
case 0x460: /* DMA_PCh2_SR */
@ -1193,7 +1244,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
switch (offset) {
case 0x300 ... 0x3fe:
if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret))
break;
return ret;
@ -1207,7 +1258,7 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr)
return ret;
case 0x404 ... 0x4fe:
if (s->model == omap_dma_3_1)
if (s->model <= omap_dma_3_1)
break;
/* Fall through. */
case 0x400:
@ -1236,7 +1287,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
switch (offset) {
case 0x300 ... 0x3fe:
if (s->model == omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) {
if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value))
break;
return;
@ -1250,7 +1301,7 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr,
return;
case 0x404 ... 0x4fe:
if (s->model == omap_dma_3_1)
if (s->model <= omap_dma_3_1)
break;
case 0x400:
/* Fall through. */
@ -1285,7 +1336,7 @@ static CPUWriteMemoryFunc *omap_dma_writefn[] = {
static void omap_dma_request(void *opaque, int drq, int req)
{
struct omap_dma_s *s = (struct omap_dma_s *) opaque;
/* The request pins are level triggered. */
/* The request pins are level triggered in QEMU. */
if (req) {
if (~s->drq & (1 << drq)) {
s->drq |= 1 << drq;
@ -1310,6 +1361,52 @@ static void omap_dma_clk_update(void *opaque, int line, int on)
}
}
static void omap_dma_setcaps(struct omap_dma_s *s)
{
switch (s->model) {
default:
case omap_dma_3_1:
break;
case omap_dma_3_2:
case omap_dma_4:
/* XXX Only available for sDMA */
s->caps[0] =
(1 << 19) | /* Constant Fill Capability */
(1 << 18); /* Transparent BLT Capability */
s->caps[1] =
(1 << 1); /* 1-bit palettized capability (DMA 3.2 only) */
s->caps[2] =
(1 << 8) | /* SEPARATE_SRC_AND_DST_INDEX_CPBLTY */
(1 << 7) | /* DST_DOUBLE_INDEX_ADRS_CPBLTY */
(1 << 6) | /* DST_SINGLE_INDEX_ADRS_CPBLTY */
(1 << 5) | /* DST_POST_INCRMNT_ADRS_CPBLTY */
(1 << 4) | /* DST_CONST_ADRS_CPBLTY */
(1 << 3) | /* SRC_DOUBLE_INDEX_ADRS_CPBLTY */
(1 << 2) | /* SRC_SINGLE_INDEX_ADRS_CPBLTY */
(1 << 1) | /* SRC_POST_INCRMNT_ADRS_CPBLTY */
(1 << 0); /* SRC_CONST_ADRS_CPBLTY */
s->caps[3] =
(1 << 6) | /* BLOCK_SYNCHR_CPBLTY (DMA 4 only) */
(1 << 7) | /* PKT_SYNCHR_CPBLTY (DMA 4 only) */
(1 << 5) | /* CHANNEL_CHAINING_CPBLTY */
(1 << 4) | /* LCh_INTERLEAVE_CPBLTY */
(1 << 3) | /* AUTOINIT_REPEAT_CPBLTY (DMA 3.2 only) */
(1 << 2) | /* AUTOINIT_ENDPROG_CPBLTY (DMA 3.2 only) */
(1 << 1) | /* FRAME_SYNCHR_CPBLTY */
(1 << 0); /* ELMNT_SYNCHR_CPBLTY */
s->caps[4] =
(1 << 7) | /* PKT_INTERRUPT_CPBLTY (DMA 4 only) */
(1 << 6) | /* SYNC_STATUS_CPBLTY */
(1 << 5) | /* BLOCK_INTERRUPT_CPBLTY */
(1 << 4) | /* LAST_FRAME_INTERRUPT_CPBLTY */
(1 << 3) | /* FRAME_INTERRUPT_CPBLTY */
(1 << 2) | /* HALF_FRAME_INTERRUPT_CPBLTY */
(1 << 1) | /* EVENT_DROP_INTERRUPT_CPBLTY */
(1 << 0); /* TIMEOUT_INTERRUPT_CPBLTY (DMA 3.2 only) */
break;
}
}
struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk,
enum omap_dma_model model)
@ -1318,7 +1415,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
struct omap_dma_s *s = (struct omap_dma_s *)
qemu_mallocz(sizeof(struct omap_dma_s));
if (model == omap_dma_3_1) {
if (model <= omap_dma_3_1) {
num_irqs = 6;
memsize = 0x800;
} else {
@ -1331,6 +1428,7 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
s->clk = clk;
s->lcd_ch.irq = lcd_irq;
s->lcd_ch.mpu = mpu;
omap_dma_setcaps(s);
while (num_irqs --)
s->ch[num_irqs].irq = irqs[num_irqs];
for (i = 0; i < 3; i ++) {
@ -1350,6 +1448,393 @@ struct omap_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
return s;
}
static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
{
struct omap_dma_channel_s *ch = s->ch;
uint32_t bmp, bit;
for (bmp = 0, bit = 1; bit; ch ++, bit <<= 1)
if (ch->status) {
bmp |= bit;
ch->cstatus |= ch->status;
ch->status = 0;
}
if ((s->irqstat[0] |= s->irqen[0] & bmp))
qemu_irq_raise(s->irq[0]);
if ((s->irqstat[1] |= s->irqen[1] & bmp))
qemu_irq_raise(s->irq[1]);
if ((s->irqstat[2] |= s->irqen[2] & bmp))
qemu_irq_raise(s->irq[2]);
if ((s->irqstat[3] |= s->irqen[3] & bmp))
qemu_irq_raise(s->irq[3]);
}
static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr)
{
struct omap_dma_s *s = (struct omap_dma_s *) opaque;
int irqn = 0, chnum, offset = addr - s->base;
struct omap_dma_channel_s *ch;
switch (offset) {
case 0x00: /* DMA4_REVISION */
return 0x40;
case 0x14: /* DMA4_IRQSTATUS_L3 */
irqn ++;
case 0x10: /* DMA4_IRQSTATUS_L2 */
irqn ++;
case 0x0c: /* DMA4_IRQSTATUS_L1 */
irqn ++;
case 0x08: /* DMA4_IRQSTATUS_L0 */
return s->irqstat[irqn];
case 0x24: /* DMA4_IRQENABLE_L3 */
irqn ++;
case 0x20: /* DMA4_IRQENABLE_L2 */
irqn ++;
case 0x1c: /* DMA4_IRQENABLE_L1 */
irqn ++;
case 0x18: /* DMA4_IRQENABLE_L0 */
return s->irqen[irqn];
case 0x28: /* DMA4_SYSSTATUS */
return 1; /* RESETDONE */
case 0x2c: /* DMA4_OCP_SYSCONFIG */
return s->ocp;
case 0x64: /* DMA4_CAPS_0 */
return s->caps[0];
case 0x6c: /* DMA4_CAPS_2 */
return s->caps[2];
case 0x70: /* DMA4_CAPS_3 */
return s->caps[3];
case 0x74: /* DMA4_CAPS_4 */
return s->caps[4];
case 0x78: /* DMA4_GCR */
return s->gcr;
case 0x80 ... 0xfff:
offset -= 0x80;
chnum = offset / 0x60;
ch = s->ch + chnum;
offset -= chnum * 0x60;
break;
default:
OMAP_BAD_REG(addr);
return 0;
}
/* Per-channel registers */
switch (offset) {
case 0x00: /* DMA4_CCR */
return (ch->buf_disable << 25) |
(ch->src_sync << 24) |
(ch->prefetch << 23) |
((ch->sync & 0x60) << 14) |
(ch->bs << 18) |
(ch->transparent_copy << 17) |
(ch->constant_fill << 16) |
(ch->mode[1] << 14) |
(ch->mode[0] << 12) |
(0 << 10) | (0 << 9) |
(ch->suspend << 8) |
(ch->enable << 7) |
(ch->priority << 6) |
(ch->fs << 5) | (ch->sync & 0x1f);
case 0x04: /* DMA4_CLNK_CTRL */
return (ch->link_enabled << 15) | ch->link_next_ch;
case 0x08: /* DMA4_CICR */
return ch->interrupts;
case 0x0c: /* DMA4_CSR */
return ch->cstatus;
case 0x10: /* DMA4_CSDP */
return (ch->endian[0] << 21) |
(ch->endian_lock[0] << 20) |
(ch->endian[1] << 19) |
(ch->endian_lock[1] << 18) |
(ch->write_mode << 16) |
(ch->burst[1] << 14) |
(ch->pack[1] << 13) |
(ch->translate[1] << 9) |
(ch->burst[0] << 7) |
(ch->pack[0] << 6) |
(ch->translate[0] << 2) |
(ch->data_type >> 1);
case 0x14: /* DMA4_CEN */
return ch->elements;
case 0x18: /* DMA4_CFN */
return ch->frames;
case 0x1c: /* DMA4_CSSA */
return ch->addr[0];
case 0x20: /* DMA4_CDSA */
return ch->addr[1];
case 0x24: /* DMA4_CSEI */
return ch->element_index[0];
case 0x28: /* DMA4_CSFI */
return ch->frame_index[0];
case 0x2c: /* DMA4_CDEI */
return ch->element_index[1];
case 0x30: /* DMA4_CDFI */
return ch->frame_index[1];
case 0x34: /* DMA4_CSAC */
return ch->active_set.src & 0xffff;
case 0x38: /* DMA4_CDAC */
return ch->active_set.dest & 0xffff;
case 0x3c: /* DMA4_CCEN */
return ch->active_set.element;
case 0x40: /* DMA4_CCFN */
return ch->active_set.frame;
case 0x44: /* DMA4_COLOR */
/* XXX only in sDMA */
return ch->color;
default:
OMAP_BAD_REG(addr);
return 0;
}
}
static void omap_dma4_write(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
struct omap_dma_s *s = (struct omap_dma_s *) opaque;
int chnum, irqn = 0, offset = addr - s->base;
struct omap_dma_channel_s *ch;
switch (offset) {
case 0x14: /* DMA4_IRQSTATUS_L3 */
irqn ++;
case 0x10: /* DMA4_IRQSTATUS_L2 */
irqn ++;
case 0x0c: /* DMA4_IRQSTATUS_L1 */
irqn ++;
case 0x08: /* DMA4_IRQSTATUS_L0 */
s->irqstat[irqn] &= ~value;
if (!s->irqstat[irqn])
qemu_irq_lower(s->irq[irqn]);
return;
case 0x24: /* DMA4_IRQENABLE_L3 */
irqn ++;
case 0x20: /* DMA4_IRQENABLE_L2 */
irqn ++;
case 0x1c: /* DMA4_IRQENABLE_L1 */
irqn ++;
case 0x18: /* DMA4_IRQENABLE_L0 */
s->irqen[irqn] = value;
return;
case 0x2c: /* DMA4_OCP_SYSCONFIG */
if (value & 2) /* SOFTRESET */
omap_dma_reset(s);
s->ocp = value & 0x3321;
if (((s->ocp >> 12) & 3) == 3) /* MIDLEMODE */
fprintf(stderr, "%s: invalid DMA power mode\n", __FUNCTION__);
return;
case 0x78: /* DMA4_GCR */
s->gcr = value & 0x00ff00ff;
if ((value & 0xff) == 0x00) /* MAX_CHANNEL_FIFO_DEPTH */
fprintf(stderr, "%s: wrong FIFO depth in GCR\n", __FUNCTION__);
return;
case 0x80 ... 0xfff:
offset -= 0x80;
chnum = offset / 0x60;
ch = s->ch + chnum;
offset -= chnum * 0x60;
break;
case 0x00: /* DMA4_REVISION */
case 0x28: /* DMA4_SYSSTATUS */
case 0x64: /* DMA4_CAPS_0 */
case 0x6c: /* DMA4_CAPS_2 */
case 0x70: /* DMA4_CAPS_3 */
case 0x74: /* DMA4_CAPS_4 */
OMAP_RO_REG(addr);
return;
default:
OMAP_BAD_REG(addr);
return;
}
/* Per-channel registers */
switch (offset) {
case 0x00: /* DMA4_CCR */
ch->buf_disable = (value >> 25) & 1;
ch->src_sync = (value >> 24) & 1; /* XXX For CamDMA must be 1 */
if (ch->buf_disable && !ch->src_sync)
fprintf(stderr, "%s: Buffering disable is not allowed in "
"destination synchronised mode\n", __FUNCTION__);
ch->prefetch = (value >> 23) & 1;
ch->bs = (value >> 18) & 1;
ch->transparent_copy = (value >> 17) & 1;
ch->constant_fill = (value >> 16) & 1;
ch->mode[1] = (omap_dma_addressing_t) ((value & 0xc000) >> 14);
ch->mode[0] = (omap_dma_addressing_t) ((value & 0x3000) >> 12);
ch->suspend = (value & 0x0100) >> 8;
ch->priority = (value & 0x0040) >> 6;
ch->fs = (value & 0x0020) >> 5;
if (ch->fs && ch->bs && ch->mode[0] && ch->mode[1])
fprintf(stderr, "%s: For a packet transfer at least one port "
"must be constant-addressed\n", __FUNCTION__);
ch->sync = (value & 0x001f) | ((value >> 14) & 0x0060);
/* XXX must be 0x01 for CamDMA */
if (value & 0x0080)
omap_dma_enable_channel(s, ch);
else
omap_dma_disable_channel(s, ch);
break;
case 0x04: /* DMA4_CLNK_CTRL */
ch->link_enabled = (value >> 15) & 0x1;
ch->link_next_ch = value & 0x1f;
break;
case 0x08: /* DMA4_CICR */
ch->interrupts = value & 0x09be;
break;
case 0x0c: /* DMA4_CSR */
ch->cstatus &= ~value;
break;
case 0x10: /* DMA4_CSDP */
ch->endian[0] =(value >> 21) & 1;
ch->endian_lock[0] =(value >> 20) & 1;
ch->endian[1] =(value >> 19) & 1;
ch->endian_lock[1] =(value >> 18) & 1;
if (ch->endian[0] != ch->endian[1])
fprintf(stderr, "%s: DMA endianned conversion enable attempt\n",
__FUNCTION__);
ch->write_mode = (value >> 16) & 3;
ch->burst[1] = (value & 0xc000) >> 14;
ch->pack[1] = (value & 0x2000) >> 13;
ch->translate[1] = (value & 0x1e00) >> 9;
ch->burst[0] = (value & 0x0180) >> 7;
ch->pack[0] = (value & 0x0040) >> 6;
ch->translate[0] = (value & 0x003c) >> 2;
if (ch->translate[0] | ch->translate[1])
fprintf(stderr, "%s: bad MReqAddressTranslate sideband signal\n",
__FUNCTION__);
ch->data_type = 1 << (value & 3);
if ((value & 3) == 3)
printf("%s: bad data_type for DMA channel\n", __FUNCTION__);
break;
case 0x14: /* DMA4_CEN */
ch->elements = value & 0xffffff;
break;
case 0x18: /* DMA4_CFN */
ch->frames = value & 0xffff;
break;
case 0x1c: /* DMA4_CSSA */
ch->addr[0] = (target_phys_addr_t) (uint32_t) value;
break;
case 0x20: /* DMA4_CDSA */
ch->addr[1] = (target_phys_addr_t) (uint32_t) value;
break;
case 0x24: /* DMA4_CSEI */
ch->element_index[0] = (int16_t) value;
break;
case 0x28: /* DMA4_CSFI */
ch->frame_index[0] = (int32_t) value;
break;
case 0x2c: /* DMA4_CDEI */
ch->element_index[1] = (int16_t) value;
break;
case 0x30: /* DMA4_CDFI */
ch->frame_index[1] = (int32_t) value;
break;
case 0x44: /* DMA4_COLOR */
/* XXX only in sDMA */
ch->color = value;
break;
case 0x34: /* DMA4_CSAC */
case 0x38: /* DMA4_CDAC */
case 0x3c: /* DMA4_CCEN */
case 0x40: /* DMA4_CCFN */
OMAP_RO_REG(addr);
break;
default:
OMAP_BAD_REG(addr);
}
}
static CPUReadMemoryFunc *omap_dma4_readfn[] = {
omap_badwidth_read16,
omap_dma4_read,
omap_dma4_read,
};
static CPUWriteMemoryFunc *omap_dma4_writefn[] = {
omap_badwidth_write16,
omap_dma4_write,
omap_dma4_write,
};
struct omap_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
struct omap_mpu_state_s *mpu, int fifo,
int chans, omap_clk iclk, omap_clk fclk)
{
int iomemtype;
struct omap_dma_s *s = (struct omap_dma_s *)
qemu_mallocz(sizeof(struct omap_dma_s));
s->base = base;
s->model = omap_dma_4;
s->chans = chans;
s->mpu = mpu;
s->clk = fclk;
memcpy(&s->irq, irqs, sizeof(s->irq));
s->intr_update = omap_dma_interrupts_4_update;
omap_dma_setcaps(s);
s->tm = qemu_new_timer(vm_clock, (QEMUTimerCB *) omap_dma_channel_run, s);
omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
mpu->drq = qemu_allocate_irqs(omap_dma_request, s, 64);
omap_dma_reset(s);
omap_dma_clk_update(s, 0, 1);
iomemtype = cpu_register_io_memory(0, omap_dma4_readfn,
omap_dma4_writefn, s);
cpu_register_physical_memory(s->base, 0x1000, iomemtype);
return s;
}
struct omap_dma_lcd_channel_s *omap_dma_get_lcdch(struct omap_dma_s *s)
{
return &s->lcd_ch;

1093
hw/omap_dss.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -150,6 +150,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
}
if (ack && s->count_cur)
s->stat |= 1 << 4; /* XRDY */
else
s->stat &= ~(1 << 4); /* XRDY */
if (!s->count_cur) {
s->stat |= 1 << 2; /* ARDY */
s->control &= ~(1 << 10); /* MST */
@ -161,6 +163,8 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
}
if (s->rxlen)
s->stat |= 1 << 3; /* RRDY */
else
s->stat &= ~(1 << 3); /* RRDY */
}
if (!s->count_cur) {
if ((s->control >> 1) & 1) { /* STP */
@ -321,7 +325,8 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
return;
}
s->stat &= ~(value & 0x3f);
/* RRDY and XRDY are reset by hardware. (in all versions???) */
s->stat &= ~(value & 0x27);
omap_i2c_interrupts_update(s);
break;
@ -376,11 +381,13 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
break;
}
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
fprintf(stderr, "%s: I^2C slave mode not supported\n",
__FUNCTION__);
break;
}
if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
__FUNCTION__);
break;
}
if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */
@ -427,7 +434,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
omap_i2c_interrupts_update(s);
}
if (value & (1 << 15)) /* ST_EN */
printf("%s: System Test not supported\n", __FUNCTION__);
fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
break;
default:

View File

@ -5,8 +5,8 @@
*
* 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 of
* the License, or (at your option) any later version.
* 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
@ -26,19 +26,24 @@ struct omap_mmc_s {
target_phys_addr_t base;
qemu_irq irq;
qemu_irq *dma;
qemu_irq coverswitch;
omap_clk clk;
SDState *card;
uint16_t last_cmd;
uint16_t sdio;
uint16_t rsp[8];
uint32_t arg;
int lines;
int dw;
int mode;
int enable;
int be;
int rev;
uint16_t status;
uint16_t mask;
uint8_t cto;
uint16_t dto;
int clkdiv;
uint16_t fifo[32];
int fifo_start;
int fifo_len;
@ -53,6 +58,11 @@ struct omap_mmc_s {
int ddir;
int transfer;
int cdet_wakeup;
int cdet_enable;
int cdet_state;
qemu_irq cdet;
};
static void omap_mmc_interrupts_update(struct omap_mmc_s *s)
@ -107,6 +117,11 @@ static void omap_mmc_command(struct omap_mmc_s *host, int cmd, int dir,
struct sd_request_s request;
uint8_t response[16];
if (init && cmd == 0) {
host->status |= 0x0001;
return;
}
if (resptype == sd_r1 && busy)
resptype = sd_r1b;
@ -265,6 +280,34 @@ static void omap_mmc_update(void *opaque)
omap_mmc_interrupts_update(s);
}
void omap_mmc_reset(struct omap_mmc_s *host)
{
host->last_cmd = 0;
memset(host->rsp, 0, sizeof(host->rsp));
host->arg = 0;
host->dw = 0;
host->mode = 0;
host->enable = 0;
host->status = 0;
host->mask = 0;
host->cto = 0;
host->dto = 0;
host->fifo_len = 0;
host->blen = 0;
host->blen_counter = 0;
host->nblk = 0;
host->nblk_counter = 0;
host->tx_dma = 0;
host->rx_dma = 0;
host->ae_level = 0x00;
host->af_level = 0x1f;
host->transfer = 0;
host->cdet_wakeup = 0;
host->cdet_enable = 0;
qemu_set_irq(host->coverswitch, host->cdet_state);
host->clkdiv = 0;
}
static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
{
uint16_t i;
@ -282,7 +325,8 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
return s->arg >> 16;
case 0x0c: /* MMC_CON */
return (s->dw << 15) | (s->mode << 12) | (s->enable << 11);
return (s->dw << 15) | (s->mode << 12) | (s->enable << 11) |
(s->be << 10) | s->clkdiv;
case 0x10: /* MMC_STAT */
return s->status;
@ -324,12 +368,12 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
case 0x30: /* MMC_SPI */
return 0x0000;
case 0x34: /* MMC_SDIO */
return s->sdio;
return (s->cdet_wakeup << 2) | (s->cdet_enable) | s->sdio;
case 0x38: /* MMC_SYST */
return 0x0000;
case 0x3c: /* MMC_REV */
return 0x0001;
return s->rev;
case 0x40: /* MMC_RSP0 */
case 0x44: /* MMC_RSP1 */
@ -340,6 +384,13 @@ static uint32_t omap_mmc_read(void *opaque, target_phys_addr_t offset)
case 0x58: /* MMC_RSP6 */
case 0x5c: /* MMC_RSP7 */
return s->rsp[(offset - 0x40) >> 2];
/* OMAP2-specific */
case 0x60: /* MMC_IOSR */
case 0x64: /* MMC_SYSC */
return 0;
case 0x68: /* MMC_SYSS */
return 1; /* RSTD */
}
OMAP_BAD_REG(offset);
@ -383,10 +434,16 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
s->dw = (value >> 15) & 1;
s->mode = (value >> 12) & 3;
s->enable = (value >> 11) & 1;
s->be = (value >> 10) & 1;
s->clkdiv = (value >> 0) & (s->rev >= 2 ? 0x3ff : 0xff);
if (s->mode != 0)
printf("SD mode %i unimplemented!\n", s->mode);
if (s->dw != 0)
if (s->be != 0)
printf("SD FIFO byte sex unimplemented!\n");
if (s->dw != 0 && s->lines < 4)
printf("4-bit SD bus enabled\n");
if (!s->enable)
omap_mmc_reset(s);
break;
case 0x10: /* MMC_STAT */
@ -395,13 +452,13 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
break;
case 0x14: /* MMC_IE */
s->mask = value;
s->mask = value & 0x7fff;
omap_mmc_interrupts_update(s);
break;
case 0x18: /* MMC_CTO */
s->cto = value & 0xff;
if (s->cto > 0xfd)
if (s->cto > 0xfd && s->rev <= 1)
printf("MMC: CTO of 0xff and 0xfe cannot be used!\n");
break;
@ -446,10 +503,12 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
break;
/* SPI, SDIO and TEST modes unimplemented */
case 0x30: /* MMC_SPI */
case 0x30: /* MMC_SPI (OMAP1 only) */
break;
case 0x34: /* MMC_SDIO */
s->sdio = value & 0x2020;
s->sdio = value & (s->rev >= 2 ? 0xfbf3 : 0x2020);
s->cdet_wakeup = (value >> 9) & 1;
s->cdet_enable = (value >> 2) & 1;
break;
case 0x38: /* MMC_SYST */
break;
@ -466,6 +525,19 @@ static void omap_mmc_write(void *opaque, target_phys_addr_t offset,
OMAP_RO_REG(offset);
break;
/* OMAP2-specific */
case 0x60: /* MMC_IOSR */
if (value & 0xf)
printf("MMC: SDIO bits used!\n");
break;
case 0x64: /* MMC_SYSC */
if (value & (1 << 2)) /* SRTS */
omap_mmc_reset(s);
break;
case 0x68: /* MMC_SYSS */
OMAP_RO_REG(offset);
break;
default:
OMAP_BAD_REG(offset);
}
@ -483,28 +555,21 @@ static CPUWriteMemoryFunc *omap_mmc_writefn[] = {
omap_badwidth_write16,
};
void omap_mmc_reset(struct omap_mmc_s *host)
static void omap_mmc_cover_cb(void *opaque, int line, int level)
{
host->last_cmd = 0;
memset(host->rsp, 0, sizeof(host->rsp));
host->arg = 0;
host->dw = 0;
host->mode = 0;
host->enable = 0;
host->status = 0;
host->mask = 0;
host->cto = 0;
host->dto = 0;
host->fifo_len = 0;
host->blen = 0;
host->blen_counter = 0;
host->nblk = 0;
host->nblk_counter = 0;
host->tx_dma = 0;
host->rx_dma = 0;
host->ae_level = 0x00;
host->af_level = 0x1f;
host->transfer = 0;
struct omap_mmc_s *host = (struct omap_mmc_s *) opaque;
if (!host->cdet_state && level) {
host->status |= 0x0002;
omap_mmc_interrupts_update(host);
if (host->cdet_wakeup)
/* TODO: Assert wake-up */;
}
if (host->cdet_state != level) {
qemu_set_irq(host->coverswitch, level);
host->cdet_state = level;
}
}
struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
@ -519,6 +584,10 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
s->base = base;
s->dma = dma;
s->clk = clk;
s->lines = 1; /* TODO: needs to be settable per-board */
s->rev = 1;
omap_mmc_reset(s);
iomemtype = cpu_register_io_memory(0, omap_mmc_readfn,
omap_mmc_writefn, s);
@ -530,7 +599,46 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
return s;
}
struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
omap_clk fclk, omap_clk iclk)
{
int iomemtype;
struct omap_mmc_s *s = (struct omap_mmc_s *)
qemu_mallocz(sizeof(struct omap_mmc_s));
s->irq = irq;
s->dma = dma;
s->clk = fclk;
s->lines = 4;
s->rev = 2;
omap_mmc_reset(s);
iomemtype = cpu_register_io_memory(0, omap_mmc_readfn,
omap_mmc_writefn, s);
s->base = omap_l4_attach(ta, 0, iomemtype);
/* Instantiate the storage */
s->card = sd_init(bd, 0);
s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0];
sd_set_cb(s->card, 0, s->cdet);
return s;
}
void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover)
{
sd_set_cb(s->card, ro, cover);
if (s->cdet) {
sd_set_cb(s->card, ro, s->cdet);
s->coverswitch = cover;
qemu_set_irq(cover, s->cdet_state);
} else
sd_set_cb(s->card, ro, cover);
}
void omap_mmc_enable(struct omap_mmc_s *s, int enable)
{
sd_enable(s->card, enable);
}

View File

@ -5,8 +5,8 @@
*
* 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 of
* the License, or (at your option) any later version.
* 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
@ -25,6 +25,7 @@
#include "omap.h"
#include "boards.h"
#include "arm-misc.h"
#include "devices.h"
static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
{
@ -32,12 +33,14 @@ static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
return *val >> ((offset & 3) << 3);
}
static uint32_t static_readh(void *opaque, target_phys_addr_t offset) {
static uint32_t static_readh(void *opaque, target_phys_addr_t offset)
{
uint32_t *val = (uint32_t *) opaque;
return *val >> ((offset & 1) << 3);
}
static uint32_t static_readw(void *opaque, target_phys_addr_t offset) {
static uint32_t static_readw(void *opaque, target_phys_addr_t offset)
{
uint32_t *val = (uint32_t *) opaque;
return *val >> ((offset & 0) << 3);
}

51
hw/sd.c
View File

@ -37,7 +37,7 @@
#ifdef DEBUG_SD
#define DPRINTF(fmt, args...) \
do { printf("SD: " fmt , ##args); } while (0)
do { fprintf(stderr, "SD: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while(0)
#endif
@ -99,6 +99,8 @@ struct SDState {
qemu_irq inserted_cb;
BlockDriverState *bdrv;
uint8_t *buf;
int enable;
};
static void sd_set_status(SDState *sd)
@ -530,7 +532,7 @@ static void sd_lock_command(SDState *sd)
sd->card_status &= ~CARD_IS_LOCKED;
sd->pwd_len = 0;
/* Erasing the entire card here! */
printf("SD: Card force-erased by CMD42\n");
fprintf(stderr, "SD: Card force-erased by CMD42\n");
return;
}
@ -1076,7 +1078,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
return sd_r1;
case 56: /* CMD56: GEN_CMD */
printf("SD: GEN_CMD 0x%08x\n", req.arg);
fprintf(stderr, "SD: GEN_CMD 0x%08x\n", req.arg);
switch (sd->state) {
case sd_transfer_state:
@ -1096,18 +1098,18 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
bad_cmd:
sd->card_status |= ILLEGAL_COMMAND;
printf("SD: Unknown CMD%i\n", req.cmd);
fprintf(stderr, "SD: Unknown CMD%i\n", req.cmd);
return sd_r0;
unimplemented_cmd:
/* Commands that are recognised but not yet implemented in SPI mode. */
sd->card_status |= ILLEGAL_COMMAND;
printf ("SD: CMD%i not implemented in SPI mode\n", req.cmd);
fprintf(stderr, "SD: CMD%i not implemented in SPI mode\n", req.cmd);
return sd_r0;
}
sd->card_status |= ILLEGAL_COMMAND;
printf("SD: CMD%i in a wrong state\n", req.cmd);
fprintf(stderr, "SD: CMD%i in a wrong state\n", req.cmd);
return sd_r0;
}
@ -1217,7 +1219,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
return sd_normal_command(sd, req);
}
printf("SD: ACMD%i in a wrong state\n", req.cmd);
fprintf(stderr, "SD: ACMD%i in a wrong state\n", req.cmd);
return sd_r0;
}
@ -1227,7 +1229,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
sd_rsp_type_t rtype;
int rsplen;
if (!bdrv_is_inserted(sd->bdrv)) {
if (!bdrv_is_inserted(sd->bdrv) || !sd->enable) {
return 0;
}
@ -1247,7 +1249,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
sd_cmd_class[req->cmd] == 7 ||
req->cmd == 16 || req->cmd == 55))) {
sd->card_status |= ILLEGAL_COMMAND;
printf("SD: Card is locked\n");
fprintf(stderr, "SD: Card is locked\n");
return 0;
}
@ -1321,7 +1323,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len)
uint32_t end = addr + len;
if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
printf("sd_blk_read: read error on host side\n");
fprintf(stderr, "sd_blk_read: read error on host side\n");
return;
}
@ -1329,7 +1331,7 @@ static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len)
memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511));
if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
printf("sd_blk_read: read error on host side\n");
fprintf(stderr, "sd_blk_read: read error on host side\n");
return;
}
memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511);
@ -1343,28 +1345,28 @@ static void sd_blk_write(SDState *sd, uint32_t addr, uint32_t len)
if ((addr & 511) || len < 512)
if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
printf("sd_blk_write: read error on host side\n");
fprintf(stderr, "sd_blk_write: read error on host side\n");
return;
}
if (end > (addr & ~511) + 512) {
memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511));
if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
printf("sd_blk_write: write error on host side\n");
fprintf(stderr, "sd_blk_write: write error on host side\n");
return;
}
if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
printf("sd_blk_write: read error on host side\n");
fprintf(stderr, "sd_blk_write: read error on host side\n");
return;
}
memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511);
if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) == -1)
printf("sd_blk_write: write error on host side\n");
fprintf(stderr, "sd_blk_write: write error on host side\n");
} else {
memcpy(sd->buf + (addr & 511), sd->data, len);
if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1)
printf("sd_blk_write: write error on host side\n");
fprintf(stderr, "sd_blk_write: write error on host side\n");
}
}
@ -1377,11 +1379,11 @@ void sd_write_data(SDState *sd, uint8_t value)
{
int i;
if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
return;
if (sd->state != sd_receivingdata_state) {
printf("sd_write_data: not in Receiving-Data state\n");
fprintf(stderr, "sd_write_data: not in Receiving-Data state\n");
return;
}
@ -1489,7 +1491,7 @@ void sd_write_data(SDState *sd, uint8_t value)
break;
default:
printf("sd_write_data: unknown command\n");
fprintf(stderr, "sd_write_data: unknown command\n");
break;
}
}
@ -1499,11 +1501,11 @@ uint8_t sd_read_data(SDState *sd)
/* TODO: Append CRCs */
uint8_t ret;
if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
return 0x00;
if (sd->state != sd_sendingdata_state) {
printf("sd_read_data: not in Sending-Data state\n");
fprintf(stderr, "sd_read_data: not in Sending-Data state\n");
return 0x00;
}
@ -1603,7 +1605,7 @@ uint8_t sd_read_data(SDState *sd)
break;
default:
printf("sd_read_data: unknown command\n");
fprintf(stderr, "sd_read_data: unknown command\n");
return 0x00;
}
@ -1614,3 +1616,8 @@ int sd_data_ready(SDState *sd)
{
return sd->state == sd_sendingdata_state;
}
void sd_enable(SDState *sd, int enable)
{
sd->enable = enable;
}

View File

@ -74,6 +74,7 @@ void sd_write_data(SDState *sd, uint8_t value);
uint8_t sd_read_data(SDState *sd);
void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
int sd_data_ready(SDState *sd);
void sd_enable(SDState *sd, int enable);
/* ssi-sd.c */
int ssi_sd_xfer(void *opaque, int val);

View File

@ -373,6 +373,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
#define ARM_CPUID_PXA270_C0 0x69054114
#define ARM_CPUID_PXA270_C5 0x69054117
#define ARM_CPUID_ARM1136 0x4117b363
#define ARM_CPUID_ARM1136_R2 0x4107b362
#define ARM_CPUID_ARM11MPCORE 0x410fb022
#define ARM_CPUID_CORTEXA8 0x410fc080
#define ARM_CPUID_CORTEXM3 0x410fc231

View File

@ -55,6 +55,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
env->cp15.c0_cachetype = 0x1dd20d2;
env->cp15.c1_sys = 0x00090078;
break;
case ARM_CPUID_ARM1136_R2:
case ARM_CPUID_ARM1136:
set_feature(env, ARM_FEATURE_V6);
set_feature(env, ARM_FEATURE_VFP);
@ -206,6 +207,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
{ ARM_CPUID_ARM946, "arm946"},
{ ARM_CPUID_ARM1026, "arm1026"},
{ ARM_CPUID_ARM1136, "arm1136"},
{ ARM_CPUID_ARM1136_R2, "arm1136-r2"},
{ ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
{ ARM_CPUID_CORTEXM3, "cortex-m3"},
{ ARM_CPUID_CORTEXA8, "cortex-a8"},
@ -1582,6 +1584,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
case ARM_CPUID_ARM1026:
return 1;
case ARM_CPUID_ARM1136:
case ARM_CPUID_ARM1136_R2:
return 7;
case ARM_CPUID_ARM11MPCORE:
return 1;
@ -1762,6 +1765,10 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
case 8: /* TI925T_status */
return 0;
}
/* TODO: Peripheral port remap register:
* On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt
* controller base address at $rn & ~0xfff and map size of
* 0x200 << ($rn & 0xfff), when MMU is off. */
goto bad_reg;
}
return 0;