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:
parent
f93eb9ff66
commit
827df9f3c5
@ -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
308
hw/omap.h
@ -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)
|
||||
|
441
hw/omap1.c
441
hw/omap1.c
@ -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
3860
hw/omap2.c
Normal file
File diff suppressed because it is too large
Load Diff
522
hw/omap_clk.c
522
hw/omap_clk.c
@ -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;
|
||||
|
||||
|
679
hw/omap_dma.c
679
hw/omap_dma.c
@ -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
1093
hw/omap_dss.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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:
|
||||
|
172
hw/omap_mmc.c
172
hw/omap_mmc.c
@ -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);
|
||||
}
|
||||
|
11
hw/palm.c
11
hw/palm.c
@ -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
51
hw/sd.c
@ -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;
|
||||
}
|
||||
|
1
hw/sd.h
1
hw/sd.h
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user