mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'qemu-kvm/memory/urgent' into staging
* qemu-kvm/memory/urgent: (42 commits) memory: check for watchpoints when getting code ram_addr exec: fix write tlb entry misused as iotlb Sparc: avoid AREG0 wrappers for memory access helpers Sparc: avoid AREG0 for memory access helpers TCG: add 5 arg helpers to def-helper.h softmmu templates: optionally pass CPUState to memory access functions i386: Remove REGPARM sparc64: implement PCI and ISA irqs sparc: reset CPU state on reset apb: use normal PCI device header for PBM device w64: Fix data type of next_tb and tcg_qemu_tb_exec softfloat: fix for C99 vmstate: fix varrays with uint32_t indexes Fix large memory chunks allocation with tcg_malloc. hw/pxa2xx.c: Fix handling of pxa2xx_i2c variable offset within region hw/pxa2xx_lcd.c: drop target_phys_addr_t usage in device state hw/pxa2xx_dma.c: drop target_phys_addr_t usage in device state ARM: Remove unnecessary subpage workarounds malta: Fix display for LED array malta: Use symbolic hardware addresses ...
This commit is contained in:
+9
-3
@@ -80,7 +80,10 @@ libobj-y = exec.o translate-all.o cpu-exec.o translate.o
|
||||
libobj-y += tcg/tcg.o tcg/optimize.o
|
||||
libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
|
||||
libobj-y += fpu/softfloat.o
|
||||
libobj-y += op_helper.o helper.o
|
||||
ifneq ($(TARGET_BASE_ARCH), sparc)
|
||||
libobj-y += op_helper.o
|
||||
endif
|
||||
libobj-y += helper.o
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
libobj-y += cpuid.o
|
||||
endif
|
||||
@@ -101,9 +104,12 @@ tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
|
||||
|
||||
$(libobj-y): $(GENERATED_HEADERS)
|
||||
|
||||
# HELPER_CFLAGS is used for all the code compiled with static register
|
||||
# HELPER_CFLAGS is used for all the legacy code compiled with static register
|
||||
# variables
|
||||
op_helper.o ldst_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
ifneq ($(TARGET_BASE_ARCH), sparc)
|
||||
op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
endif
|
||||
user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
|
||||
# Note: this is a workaround. The real fix is to avoid compiling
|
||||
# cpu_signal_handler() in user-exec.c.
|
||||
|
||||
@@ -3606,6 +3606,13 @@ case "$target_arch2" in
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$target_arch2" in
|
||||
sparc*)
|
||||
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak
|
||||
echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak
|
||||
echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak
|
||||
|
||||
@@ -259,12 +259,21 @@ extern unsigned long reserved_va;
|
||||
#define stfl(p, v) stfl_raw(p, v)
|
||||
#define stfq(p, v) stfq_raw(p, v)
|
||||
|
||||
#ifndef CONFIG_TCG_PASS_AREG0
|
||||
#define ldub_code(p) ldub_raw(p)
|
||||
#define ldsb_code(p) ldsb_raw(p)
|
||||
#define lduw_code(p) lduw_raw(p)
|
||||
#define ldsw_code(p) ldsw_raw(p)
|
||||
#define ldl_code(p) ldl_raw(p)
|
||||
#define ldq_code(p) ldq_raw(p)
|
||||
#else
|
||||
#define cpu_ldub_code(env1, p) ldub_raw(p)
|
||||
#define cpu_ldsb_code(env1, p) ldsb_raw(p)
|
||||
#define cpu_lduw_code(env1, p) lduw_raw(p)
|
||||
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
|
||||
#define cpu_ldl_code(env1, p) ldl_raw(p)
|
||||
#define cpu_ldq_code(env1, p) ldq_raw(p)
|
||||
#endif
|
||||
|
||||
#define ldub_kernel(p) ldub_raw(p)
|
||||
#define ldsb_kernel(p) ldsb_raw(p)
|
||||
|
||||
+3
-3
@@ -55,7 +55,7 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc)
|
||||
static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
|
||||
TranslationBlock *orig_tb)
|
||||
{
|
||||
unsigned long next_tb;
|
||||
tcg_target_ulong next_tb;
|
||||
TranslationBlock *tb;
|
||||
|
||||
/* Should never happen.
|
||||
@@ -186,7 +186,7 @@ int cpu_exec(CPUArchState *env)
|
||||
int ret, interrupt_request;
|
||||
TranslationBlock *tb;
|
||||
uint8_t *tc_ptr;
|
||||
unsigned long next_tb;
|
||||
tcg_target_ulong next_tb;
|
||||
|
||||
if (env->halted) {
|
||||
if (!cpu_has_work(env)) {
|
||||
@@ -565,7 +565,7 @@ int cpu_exec(CPUArchState *env)
|
||||
if ((next_tb & 3) == 2) {
|
||||
/* Instruction counter expired. */
|
||||
int insns_left;
|
||||
tb = (TranslationBlock *)(long)(next_tb & ~3);
|
||||
tb = (TranslationBlock *)(next_tb & ~3);
|
||||
/* Restore PC. */
|
||||
cpu_pc_from_tb(env, tb);
|
||||
insns_left = env->icount_decr.u32;
|
||||
|
||||
@@ -118,6 +118,8 @@
|
||||
DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3)
|
||||
#define DEF_HELPER_4(name, ret, t1, t2, t3, t4) \
|
||||
DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4)
|
||||
#define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \
|
||||
DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
|
||||
|
||||
#endif /* DEF_HELPER_H */
|
||||
|
||||
@@ -140,6 +142,10 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4));
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4), dh_ctype(t5));
|
||||
|
||||
#undef GEN_HELPER
|
||||
#define GEN_HELPER -1
|
||||
|
||||
@@ -203,6 +209,22 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) dh_arg_decl(t1, 1
|
||||
tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 4, args); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
|
||||
{ \
|
||||
TCGArg args[5]; \
|
||||
int sizemask = 0; \
|
||||
dh_sizemask(ret, 0); \
|
||||
dh_arg(t1, 1); \
|
||||
dh_arg(t2, 2); \
|
||||
dh_arg(t3, 3); \
|
||||
dh_arg(t4, 4); \
|
||||
dh_arg(t5, 5); \
|
||||
tcg_gen_helperN(HELPER(name), flags, sizemask, dh_retvar(ret), 5, args); \
|
||||
}
|
||||
|
||||
#undef GEN_HELPER
|
||||
#define GEN_HELPER -1
|
||||
|
||||
@@ -224,6 +246,9 @@ DEF_HELPER_FLAGS_0(name, flags, ret)
|
||||
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
|
||||
DEF_HELPER_FLAGS_0(name, flags, ret)
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
DEF_HELPER_FLAGS_0(name, flags, ret)
|
||||
|
||||
#undef GEN_HELPER
|
||||
#define GEN_HELPER -1
|
||||
|
||||
@@ -235,6 +260,7 @@ DEF_HELPER_FLAGS_0(name, flags, ret)
|
||||
#undef DEF_HELPER_FLAGS_2
|
||||
#undef DEF_HELPER_FLAGS_3
|
||||
#undef DEF_HELPER_FLAGS_4
|
||||
#undef DEF_HELPER_FLAGS_5
|
||||
#undef GEN_HELPER
|
||||
|
||||
#endif
|
||||
|
||||
@@ -312,7 +312,9 @@ void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx,
|
||||
|
||||
#define ACCESS_TYPE (NB_MMU_MODES + 1)
|
||||
#define MEMSUFFIX _code
|
||||
#ifndef CONFIG_TCG_PASS_AREG0
|
||||
#define env cpu_single_env
|
||||
#endif
|
||||
|
||||
#define DATA_SIZE 1
|
||||
#include "softmmu_header.h"
|
||||
|
||||
@@ -2031,14 +2031,19 @@ static void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
|
||||
cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
|
||||
}
|
||||
|
||||
static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
|
||||
{
|
||||
return (tlbe->addr_write & (TLB_INVALID_MASK|TLB_MMIO|TLB_NOTDIRTY)) == 0;
|
||||
}
|
||||
|
||||
static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
|
||||
unsigned long start, unsigned long length)
|
||||
{
|
||||
unsigned long addr;
|
||||
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
|
||||
if (tlb_is_dirty_ram(tlb_entry)) {
|
||||
addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) + tlb_entry->addend;
|
||||
if ((addr - start) < length) {
|
||||
tlb_entry->addr_write = (tlb_entry->addr_write & TARGET_PAGE_MASK) | TLB_NOTDIRTY;
|
||||
tlb_entry->addr_write |= TLB_NOTDIRTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2091,7 +2096,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
|
||||
ram_addr_t ram_addr;
|
||||
void *p;
|
||||
|
||||
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == io_mem_ram.ram_addr) {
|
||||
if (tlb_is_dirty_ram(tlb_entry)) {
|
||||
p = (void *)(unsigned long)((tlb_entry->addr_write & TARGET_PAGE_MASK)
|
||||
+ tlb_entry->addend);
|
||||
ram_addr = qemu_ram_addr_from_host_nofail(p);
|
||||
@@ -4595,12 +4600,17 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
||||
mmu_idx = cpu_mmu_index(env1);
|
||||
if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
|
||||
(addr & TARGET_PAGE_MASK))) {
|
||||
#ifdef CONFIG_TCG_PASS_AREG0
|
||||
cpu_ldub_code(env1, addr);
|
||||
#else
|
||||
ldub_code(addr);
|
||||
#endif
|
||||
}
|
||||
pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
|
||||
mr = iotlb_to_region(pd);
|
||||
if (mr != &io_mem_ram && mr != &io_mem_rom
|
||||
&& mr != &io_mem_notdirty && !mr->rom_device) {
|
||||
&& mr != &io_mem_notdirty && !mr->rom_device
|
||||
&& mr != &io_mem_watch) {
|
||||
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
|
||||
cpu_unassigned_access(env1, addr, 0, 1, 0, 4);
|
||||
#else
|
||||
|
||||
@@ -89,8 +89,8 @@ const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
|
||||
#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
|
||||
#endif
|
||||
|
||||
const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
|
||||
floatx80_default_nan_low);
|
||||
const floatx80 floatx80_default_nan
|
||||
= make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated quadruple-precision NaN. The `high' and
|
||||
@@ -104,8 +104,8 @@ const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
|
||||
#define float128_default_nan_low LIT64( 0x0000000000000000 )
|
||||
#endif
|
||||
|
||||
const float128 float128_default_nan = make_float128(float128_default_nan_high,
|
||||
float128_default_nan_low);
|
||||
const float128 float128_default_nan
|
||||
= make_float128_init(float128_default_nan_high, float128_default_nan_low);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Raises the exceptions specified by `flags'. Floating-point traps can be
|
||||
|
||||
@@ -129,6 +129,7 @@ typedef struct {
|
||||
uint16_t high;
|
||||
} floatx80;
|
||||
#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
|
||||
#define make_floatx80_init(exp, mant) { .low = mant, .high = exp }
|
||||
typedef struct {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
uint64_t high, low;
|
||||
@@ -137,6 +138,7 @@ typedef struct {
|
||||
#endif
|
||||
} float128;
|
||||
#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ })
|
||||
#define make_float128_init(high_, low_) { .high = high_, .low = low_ }
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point underflow tininess-detection mode.
|
||||
|
||||
+35
-14
@@ -66,6 +66,8 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#define RESET_WCMASK 0x98000000
|
||||
#define RESET_WMASK 0x60000000
|
||||
|
||||
#define MAX_IVEC 0x30
|
||||
|
||||
typedef struct APBState {
|
||||
SysBusDevice busdev;
|
||||
PCIBus *bus;
|
||||
@@ -77,7 +79,8 @@ typedef struct APBState {
|
||||
uint32_t pci_control[16];
|
||||
uint32_t pci_irq_map[8];
|
||||
uint32_t obio_irq_map[32];
|
||||
qemu_irq pci_irqs[32];
|
||||
qemu_irq *pbm_irqs;
|
||||
qemu_irq *ivec_irqs;
|
||||
uint32_t reset_control;
|
||||
unsigned int nr_resets;
|
||||
} APBState;
|
||||
@@ -87,7 +90,7 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr,
|
||||
{
|
||||
APBState *s = opaque;
|
||||
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
|
||||
|
||||
switch (addr & 0xffff) {
|
||||
case 0x30 ... 0x4f: /* DMA error registers */
|
||||
@@ -104,6 +107,12 @@ static void apb_config_writel (void *opaque, target_phys_addr_t addr,
|
||||
s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
|
||||
}
|
||||
break;
|
||||
case 0x1000 ... 0x1080: /* OBIO interrupt control */
|
||||
if (addr & 4) {
|
||||
s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
|
||||
s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
|
||||
}
|
||||
break;
|
||||
case 0x2000 ... 0x202f: /* PCI control */
|
||||
s->pci_control[(addr & 0x3f) >> 2] = val;
|
||||
break;
|
||||
@@ -154,6 +163,13 @@ static uint64_t apb_config_readl (void *opaque,
|
||||
val = 0;
|
||||
}
|
||||
break;
|
||||
case 0x1000 ... 0x1080: /* OBIO interrupt control */
|
||||
if (addr & 4) {
|
||||
val = s->obio_irq_map[(addr & 0xff) >> 3];
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
break;
|
||||
case 0x2000 ... 0x202f: /* PCI control */
|
||||
val = s->pci_control[(addr & 0x3f) >> 2];
|
||||
break;
|
||||
@@ -190,7 +206,7 @@ static void apb_pci_config_write(void *opaque, target_phys_addr_t addr,
|
||||
APBState *s = opaque;
|
||||
|
||||
val = qemu_bswap_len(val, size);
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
|
||||
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", __func__, addr, val);
|
||||
pci_data_write(s->bus, addr, val, size);
|
||||
}
|
||||
|
||||
@@ -280,10 +296,19 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
|
||||
if (irq_num < 32) {
|
||||
if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
|
||||
APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
|
||||
qemu_set_irq(s->pci_irqs[irq_num], level);
|
||||
qemu_set_irq(s->ivec_irqs[irq_num], level);
|
||||
} else {
|
||||
APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
|
||||
qemu_irq_lower(s->pci_irqs[irq_num]);
|
||||
qemu_irq_lower(s->ivec_irqs[irq_num]);
|
||||
}
|
||||
} else {
|
||||
/* OBIO IRQ map onto the next 16 INO. */
|
||||
if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
|
||||
APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
|
||||
qemu_set_irq(s->ivec_irqs[irq_num], level);
|
||||
} else {
|
||||
APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
|
||||
qemu_irq_lower(s->ivec_irqs[irq_num]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,12 +341,12 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
|
||||
|
||||
PCIBus *pci_apb_init(target_phys_addr_t special_base,
|
||||
target_phys_addr_t mem_base,
|
||||
qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
|
||||
qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
|
||||
qemu_irq **pbm_irqs)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
APBState *d;
|
||||
unsigned int i;
|
||||
PCIDevice *pci_dev;
|
||||
PCIBridge *br;
|
||||
|
||||
@@ -346,9 +371,8 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
|
||||
get_system_io(),
|
||||
0, 32);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
sysbus_connect_irq(s, i, pic[i]);
|
||||
}
|
||||
*pbm_irqs = d->pbm_irqs;
|
||||
d->ivec_irqs = ivec_irqs;
|
||||
|
||||
pci_create_simple(d->bus, 0, "pbm-pci");
|
||||
|
||||
@@ -402,9 +426,7 @@ static int pci_pbm_init_device(SysBusDevice *dev)
|
||||
for (i = 0; i < 8; i++) {
|
||||
s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
sysbus_init_irq(dev, &s->pci_irqs[i]);
|
||||
}
|
||||
s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
|
||||
|
||||
/* apb_config */
|
||||
memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
|
||||
@@ -444,7 +466,6 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
|
||||
k->vendor_id = PCI_VENDOR_ID_SUN;
|
||||
k->device_id = PCI_DEVICE_ID_SUN_SABRE;
|
||||
k->class_id = PCI_CLASS_BRIDGE_HOST;
|
||||
k->is_bridge = 1;
|
||||
}
|
||||
|
||||
static TypeInfo pbm_pci_host_info = {
|
||||
|
||||
+2
-1
@@ -5,5 +5,6 @@
|
||||
|
||||
PCIBus *pci_apb_init(target_phys_addr_t special_base,
|
||||
target_phys_addr_t mem_base,
|
||||
qemu_irq *pic, PCIBus **bus2, PCIBus **bus3);
|
||||
qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
|
||||
qemu_irq **pbm_irqs);
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,6 @@ static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
|
||||
{
|
||||
mpcore_priv_state *s = (mpcore_priv_state *)opaque;
|
||||
int id;
|
||||
offset &= 0xff;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0x00: /* Control. */
|
||||
@@ -63,7 +62,6 @@ static void mpcore_scu_write(void *opaque, target_phys_addr_t offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
mpcore_priv_state *s = (mpcore_priv_state *)opaque;
|
||||
offset &= 0xff;
|
||||
/* SCU */
|
||||
switch (offset) {
|
||||
case 0: /* Control register. */
|
||||
|
||||
+4
-4
@@ -658,14 +658,14 @@ static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
|
||||
unsigned size)
|
||||
{
|
||||
gic_state *s = (gic_state *)opaque;
|
||||
return gic_cpu_read(s, gic_get_current_cpu(), addr & 0xff);
|
||||
return gic_cpu_read(s, gic_get_current_cpu(), addr);
|
||||
}
|
||||
|
||||
static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
gic_state *s = (gic_state *)opaque;
|
||||
gic_cpu_write(s, gic_get_current_cpu(), addr & 0xff, value);
|
||||
gic_cpu_write(s, gic_get_current_cpu(), addr, value);
|
||||
}
|
||||
|
||||
/* Wrappers to read/write the GIC CPU interface for a specific CPU.
|
||||
@@ -677,7 +677,7 @@ static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
|
||||
gic_state **backref = (gic_state **)opaque;
|
||||
gic_state *s = *backref;
|
||||
int id = (backref - s->backref);
|
||||
return gic_cpu_read(s, id, addr & 0xff);
|
||||
return gic_cpu_read(s, id, addr);
|
||||
}
|
||||
|
||||
static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
|
||||
@@ -686,7 +686,7 @@ static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
|
||||
gic_state **backref = (gic_state **)opaque;
|
||||
gic_state *s = *backref;
|
||||
int id = (backref - s->backref);
|
||||
gic_cpu_write(s, id, addr & 0xff, value);
|
||||
gic_cpu_write(s, id, addr, value);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gic_thiscpu_ops = {
|
||||
|
||||
@@ -97,7 +97,6 @@ static uint64_t timerblock_read(void *opaque, target_phys_addr_t addr,
|
||||
{
|
||||
timerblock *tb = (timerblock *)opaque;
|
||||
int64_t val;
|
||||
addr &= 0x1f;
|
||||
switch (addr) {
|
||||
case 0: /* Load */
|
||||
return tb->load;
|
||||
@@ -126,7 +125,6 @@ static void timerblock_write(void *opaque, target_phys_addr_t addr,
|
||||
{
|
||||
timerblock *tb = (timerblock *)opaque;
|
||||
int64_t old;
|
||||
addr &= 0x1f;
|
||||
switch (addr) {
|
||||
case 0: /* Load */
|
||||
tb->load = value;
|
||||
|
||||
+36
-48
@@ -55,6 +55,13 @@
|
||||
#define ENVP_NB_ENTRIES 16
|
||||
#define ENVP_ENTRY_SIZE 256
|
||||
|
||||
/* Hardware addresses */
|
||||
#define FLASH_ADDRESS 0x1e000000ULL
|
||||
#define FPGA_ADDRESS 0x1f000000ULL
|
||||
#define RESET_ADDRESS 0x1fc00000ULL
|
||||
|
||||
#define FLASH_SIZE 0x400000
|
||||
|
||||
#define MAX_IDE_BUS 2
|
||||
|
||||
typedef struct {
|
||||
@@ -331,9 +338,9 @@ static void malta_fpga_write(void *opaque, target_phys_addr_t addr,
|
||||
break;
|
||||
|
||||
/* LEDBAR Register */
|
||||
/* XXX: implement a 8-LED array */
|
||||
case 0x00408:
|
||||
s->leds = val & 0xff;
|
||||
malta_fpga_update_display(s);
|
||||
break;
|
||||
|
||||
/* ASCIIWORD Register */
|
||||
@@ -777,7 +784,7 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
|
||||
target_long bios_size;
|
||||
target_long bios_size = FLASH_SIZE;
|
||||
int64_t kernel_entry;
|
||||
PCIBus *pci_bus;
|
||||
ISABus *isa_bus;
|
||||
@@ -791,7 +798,7 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
DriveInfo *fd[MAX_FD];
|
||||
int fl_idx = 0;
|
||||
int fl_sectors = 0;
|
||||
int fl_sectors = bios_size >> 16;
|
||||
int be;
|
||||
|
||||
DeviceState *dev = qdev_create(NULL, "mips-malta");
|
||||
@@ -847,19 +854,26 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
be = 0;
|
||||
#endif
|
||||
/* FPGA */
|
||||
malta_fpga_init(system_memory, 0x1f000000LL, env->irq[2], serial_hds[2]);
|
||||
malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[2], serial_hds[2]);
|
||||
|
||||
/* Load firmware in flash / BIOS unless we boot directly into a kernel. */
|
||||
/* Load firmware in flash / BIOS. */
|
||||
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
|
||||
#ifdef DEBUG_BOARD_INIT
|
||||
if (dinfo) {
|
||||
printf("Register parallel flash %d size " TARGET_FMT_lx " at "
|
||||
"addr %08llx '%s' %x\n",
|
||||
fl_idx, bios_size, FLASH_ADDRESS,
|
||||
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
|
||||
}
|
||||
#endif
|
||||
fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
|
||||
BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
|
||||
65536, fl_sectors,
|
||||
4, 0x0000, 0x0000, 0x0000, 0x0000, be);
|
||||
bios = pflash_cfi01_get_memory(fl);
|
||||
fl_idx++;
|
||||
if (kernel_filename) {
|
||||
/* Write a small bootloader to the flash location. */
|
||||
bios = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
|
||||
vmstate_register_ram_global(bios);
|
||||
memory_region_set_readonly(bios, true);
|
||||
memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
|
||||
/* Map the bios at two physical locations, as on the real board. */
|
||||
memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
|
||||
memory_region_add_subregion(system_memory, 0x1fc00000LL, bios_alias);
|
||||
loaderparams.ram_size = ram_size;
|
||||
loaderparams.kernel_filename = kernel_filename;
|
||||
loaderparams.kernel_cmdline = kernel_cmdline;
|
||||
@@ -867,45 +881,15 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
kernel_entry = load_kernel();
|
||||
write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
|
||||
} else {
|
||||
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
|
||||
if (dinfo) {
|
||||
/* Load firmware from flash. */
|
||||
bios_size = 0x400000;
|
||||
fl_sectors = bios_size >> 16;
|
||||
#ifdef DEBUG_BOARD_INIT
|
||||
printf("Register parallel flash %d size " TARGET_FMT_lx " at "
|
||||
"addr %08llx '%s' %x\n",
|
||||
fl_idx, bios_size, 0x1e000000LL,
|
||||
bdrv_get_device_name(dinfo->bdrv), fl_sectors);
|
||||
#endif
|
||||
fl = pflash_cfi01_register(0x1e000000LL,
|
||||
NULL, "mips_malta.bios", BIOS_SIZE,
|
||||
dinfo->bdrv, 65536, fl_sectors,
|
||||
4, 0x0000, 0x0000, 0x0000, 0x0000, be);
|
||||
bios = pflash_cfi01_get_memory(fl);
|
||||
/* Map the bios at two physical locations, as on the real board. */
|
||||
memory_region_init_alias(bios_alias, "bios.1fc",
|
||||
bios, 0, BIOS_SIZE);
|
||||
memory_region_add_subregion(system_memory, 0x1fc00000LL,
|
||||
bios_alias);
|
||||
fl_idx++;
|
||||
} else {
|
||||
bios = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(bios, "mips_malta.bios", BIOS_SIZE);
|
||||
vmstate_register_ram_global(bios);
|
||||
memory_region_set_readonly(bios, true);
|
||||
memory_region_init_alias(bios_alias, "bios.1fc",
|
||||
bios, 0, BIOS_SIZE);
|
||||
/* Map the bios at two physical locations, as on the real board. */
|
||||
memory_region_add_subregion(system_memory, 0x1e000000LL, bios);
|
||||
memory_region_add_subregion(system_memory, 0x1fc00000LL,
|
||||
bios_alias);
|
||||
/* Load firmware from flash. */
|
||||
if (!dinfo) {
|
||||
/* Load a BIOS image. */
|
||||
if (bios_name == NULL)
|
||||
if (bios_name == NULL) {
|
||||
bios_name = BIOS_FILENAME;
|
||||
}
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
if (filename) {
|
||||
bios_size = load_image_targphys(filename, 0x1fc00000LL,
|
||||
bios_size = load_image_targphys(filename, FLASH_ADDRESS,
|
||||
BIOS_SIZE);
|
||||
g_free(filename);
|
||||
} else {
|
||||
@@ -932,6 +916,10 @@ void mips_malta_init (ram_addr_t ram_size,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Map the BIOS at a 2nd physical location, as on the real board. */
|
||||
memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE);
|
||||
memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
|
||||
|
||||
/* Board ID = 0x420 (Malta Board with CoreLV)
|
||||
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
|
||||
map to the board ID. */
|
||||
|
||||
+5
-7
@@ -45,7 +45,6 @@ struct n800_s {
|
||||
uint32_t (*txrx)(void *opaque, uint32_t value, int len);
|
||||
uWireSlave *chip;
|
||||
} ts;
|
||||
i2c_bus *i2c;
|
||||
|
||||
int keymap[0x80];
|
||||
DeviceState *kbd;
|
||||
@@ -194,12 +193,10 @@ static void n8x0_i2c_setup(struct n800_s *s)
|
||||
{
|
||||
DeviceState *dev;
|
||||
qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
|
||||
|
||||
/* Attach the CPU on one end of our I2C bus. */
|
||||
s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
|
||||
i2c_bus *i2c = omap_i2c_bus(s->cpu->i2c[0]);
|
||||
|
||||
/* Attach a menelaus PM chip */
|
||||
dev = i2c_create_slave(s->i2c, "twl92230", N8X0_MENELAUS_ADDR);
|
||||
dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR);
|
||||
qdev_connect_gpio_out(dev, 3,
|
||||
qdev_get_gpio_in(s->cpu->ih[0],
|
||||
OMAP_INT_24XX_SYS_NIRQ));
|
||||
@@ -207,7 +204,7 @@ static void n8x0_i2c_setup(struct n800_s *s)
|
||||
qemu_system_powerdown = qdev_get_gpio_in(dev, 3);
|
||||
|
||||
/* Attach a TMP105 PM chip (A0 wired to ground) */
|
||||
dev = i2c_create_slave(s->i2c, "tmp105", N8X0_TMP105_ADDR);
|
||||
dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
|
||||
qdev_connect_gpio_out(dev, 0, tmp_irq);
|
||||
}
|
||||
|
||||
@@ -391,7 +388,8 @@ static void n810_kbd_setup(struct n800_s *s)
|
||||
|
||||
/* Attach the LM8322 keyboard to the I2C bus,
|
||||
* should happen in n8x0_i2c_setup and s->kbd be initialised here. */
|
||||
s->kbd = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR);
|
||||
s->kbd = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[0]),
|
||||
"lm8323", N810_LM8323_ADDR);
|
||||
qdev_connect_gpio_out(s->kbd, 0, kbd_irq);
|
||||
}
|
||||
|
||||
|
||||
@@ -764,16 +764,7 @@ 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;
|
||||
struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
|
||||
target_phys_addr_t base,
|
||||
qemu_irq irq,
|
||||
qemu_irq *dma,
|
||||
omap_clk clk);
|
||||
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
|
||||
qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk);
|
||||
void omap_i2c_reset(struct omap_i2c_s *s);
|
||||
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s);
|
||||
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c);
|
||||
|
||||
# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310)
|
||||
# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510)
|
||||
@@ -867,7 +858,7 @@ struct omap_mpu_state_s {
|
||||
|
||||
struct omap_pwl_s *pwl;
|
||||
struct omap_pwt_s *pwt;
|
||||
struct omap_i2c_s *i2c[2];
|
||||
DeviceState *i2c[2];
|
||||
|
||||
struct omap_rtc_s *rtc;
|
||||
|
||||
|
||||
+9
-4
@@ -3694,7 +3694,6 @@ static void omap1_mpu_reset(void *opaque)
|
||||
omap_uwire_reset(mpu->microwire);
|
||||
omap_pwl_reset(mpu->pwl);
|
||||
omap_pwt_reset(mpu->pwt);
|
||||
omap_i2c_reset(mpu->i2c[0]);
|
||||
omap_rtc_reset(mpu->rtc);
|
||||
omap_mcbsp_reset(mpu->mcbsp1);
|
||||
omap_mcbsp_reset(mpu->mcbsp2);
|
||||
@@ -3993,9 +3992,15 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
|
||||
s->pwt = omap_pwt_init(system_memory, 0xfffb6000,
|
||||
omap_findclk(s, "armxor_ck"));
|
||||
|
||||
s->i2c[0] = omap_i2c_init(system_memory, 0xfffb3800,
|
||||
qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C),
|
||||
&s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
|
||||
s->i2c[0] = qdev_create(NULL, "omap_i2c");
|
||||
qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
|
||||
qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
|
||||
qdev_init_nofail(s->i2c[0]);
|
||||
busdev = sysbus_from_qdev(s->i2c[0]);
|
||||
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
|
||||
sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
|
||||
sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
|
||||
sysbus_mmio_map(busdev, 0, 0xfffb3800);
|
||||
|
||||
s->rtc = omap_rtc_init(system_memory, 0xfffb4800,
|
||||
qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER),
|
||||
|
||||
+23
-12
@@ -2222,8 +2222,6 @@ static void omap2_mpu_reset(void *opaque)
|
||||
omap_mmc_reset(mpu->mmc);
|
||||
omap_mcspi_reset(mpu->mcspi[0]);
|
||||
omap_mcspi_reset(mpu->mcspi[1]);
|
||||
omap_i2c_reset(mpu->i2c[0]);
|
||||
omap_i2c_reset(mpu->i2c[1]);
|
||||
cpu_state_reset(mpu->env);
|
||||
}
|
||||
|
||||
@@ -2395,16 +2393,29 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
|
||||
omap_findclk(s, "clk32-kHz"),
|
||||
omap_findclk(s, "core_l4_iclk"));
|
||||
|
||||
s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5),
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ),
|
||||
&s->drq[OMAP24XX_DMA_I2C1_TX],
|
||||
omap_findclk(s, "i2c1.fclk"),
|
||||
omap_findclk(s, "i2c1.iclk"));
|
||||
s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6),
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ),
|
||||
&s->drq[OMAP24XX_DMA_I2C2_TX],
|
||||
omap_findclk(s, "i2c2.fclk"),
|
||||
omap_findclk(s, "i2c2.iclk"));
|
||||
s->i2c[0] = qdev_create(NULL, "omap_i2c");
|
||||
qdev_prop_set_uint8(s->i2c[0], "revision", 0x34);
|
||||
qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
|
||||
qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
|
||||
qdev_init_nofail(s->i2c[0]);
|
||||
busdev = sysbus_from_qdev(s->i2c[0]);
|
||||
sysbus_connect_irq(busdev, 0,
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
|
||||
sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
|
||||
sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]);
|
||||
sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0));
|
||||
|
||||
s->i2c[1] = qdev_create(NULL, "omap_i2c");
|
||||
qdev_prop_set_uint8(s->i2c[1], "revision", 0x34);
|
||||
qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
|
||||
qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
|
||||
qdev_init_nofail(s->i2c[1]);
|
||||
busdev = sysbus_from_qdev(s->i2c[1]);
|
||||
sysbus_connect_irq(busdev, 0,
|
||||
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
|
||||
sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
|
||||
sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]);
|
||||
sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0));
|
||||
|
||||
s->gpio = qdev_create(NULL, "omap2-gpio");
|
||||
qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
|
||||
|
||||
+64
-47
@@ -19,14 +19,20 @@
|
||||
#include "hw.h"
|
||||
#include "i2c.h"
|
||||
#include "omap.h"
|
||||
#include "sysbus.h"
|
||||
|
||||
struct omap_i2c_s {
|
||||
|
||||
typedef struct OMAPI2CState {
|
||||
SysBusDevice busdev;
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq;
|
||||
qemu_irq drq[2];
|
||||
i2c_bus *bus;
|
||||
|
||||
uint8_t revision;
|
||||
void *iclk;
|
||||
void *fclk;
|
||||
|
||||
uint8_t mask;
|
||||
uint16_t stat;
|
||||
uint16_t dma;
|
||||
@@ -40,12 +46,12 @@ struct omap_i2c_s {
|
||||
uint8_t divider;
|
||||
uint8_t times[2];
|
||||
uint16_t test;
|
||||
};
|
||||
} OMAPI2CState;
|
||||
|
||||
#define OMAP2_INTR_REV 0x34
|
||||
#define OMAP2_GC_REV 0x34
|
||||
|
||||
static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
|
||||
static void omap_i2c_interrupts_update(OMAPI2CState *s)
|
||||
{
|
||||
qemu_set_irq(s->irq, s->stat & s->mask);
|
||||
if ((s->dma >> 15) & 1) /* RDMA_EN */
|
||||
@@ -54,7 +60,7 @@ static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
|
||||
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
|
||||
}
|
||||
|
||||
static void omap_i2c_fifo_run(struct omap_i2c_s *s)
|
||||
static void omap_i2c_fifo_run(OMAPI2CState *s)
|
||||
{
|
||||
int ack = 1;
|
||||
|
||||
@@ -122,8 +128,10 @@ static void omap_i2c_fifo_run(struct omap_i2c_s *s)
|
||||
s->control &= ~(1 << 1); /* STP */
|
||||
}
|
||||
|
||||
void omap_i2c_reset(struct omap_i2c_s *s)
|
||||
static void omap_i2c_reset(DeviceState *dev)
|
||||
{
|
||||
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
|
||||
sysbus_from_qdev(dev));
|
||||
s->mask = 0;
|
||||
s->stat = 0;
|
||||
s->dma = 0;
|
||||
@@ -143,7 +151,7 @@ void omap_i2c_reset(struct omap_i2c_s *s)
|
||||
|
||||
static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
||||
OMAPI2CState *s = opaque;
|
||||
int offset = addr & OMAP_MPUI_REG_MASK;
|
||||
uint16_t ret;
|
||||
|
||||
@@ -243,7 +251,7 @@ static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
|
||||
static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t value)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
||||
OMAPI2CState *s = opaque;
|
||||
int offset = addr & OMAP_MPUI_REG_MASK;
|
||||
int nack;
|
||||
|
||||
@@ -309,14 +317,14 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
|
||||
}
|
||||
|
||||
if (value & 2)
|
||||
omap_i2c_reset(s);
|
||||
omap_i2c_reset(&s->busdev.qdev);
|
||||
break;
|
||||
|
||||
case 0x24: /* I2C_CON */
|
||||
s->control = value & 0xcf87;
|
||||
if (~value & (1 << 15)) { /* I2C_EN */
|
||||
if (s->revision < OMAP2_INTR_REV)
|
||||
omap_i2c_reset(s);
|
||||
omap_i2c_reset(&s->busdev.qdev);
|
||||
break;
|
||||
}
|
||||
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
|
||||
@@ -385,7 +393,7 @@ static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
|
||||
static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
|
||||
uint32_t value)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
||||
OMAPI2CState *s = opaque;
|
||||
int offset = addr & OMAP_MPUI_REG_MASK;
|
||||
|
||||
switch (offset) {
|
||||
@@ -426,50 +434,59 @@ static const MemoryRegionOps omap_i2c_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem,
|
||||
target_phys_addr_t base,
|
||||
qemu_irq irq,
|
||||
qemu_irq *dma,
|
||||
omap_clk clk)
|
||||
static int omap_i2c_init(SysBusDevice *dev)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *)
|
||||
g_malloc0(sizeof(struct omap_i2c_s));
|
||||
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev);
|
||||
|
||||
/* TODO: set a value greater or equal to real hardware */
|
||||
s->revision = 0x11;
|
||||
s->irq = irq;
|
||||
s->drq[0] = dma[0];
|
||||
s->drq[1] = dma[1];
|
||||
s->bus = i2c_init_bus(NULL, "i2c");
|
||||
omap_i2c_reset(s);
|
||||
|
||||
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", 0x800);
|
||||
memory_region_add_subregion(sysmem, base, &s->iomem);
|
||||
|
||||
return s;
|
||||
if (!s->fclk) {
|
||||
hw_error("omap_i2c: fclk not connected\n");
|
||||
}
|
||||
if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
|
||||
/* Note that OMAP1 doesn't have a separate interface clock */
|
||||
hw_error("omap_i2c: iclk not connected\n");
|
||||
}
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
sysbus_init_irq(dev, &s->drq[0]);
|
||||
sysbus_init_irq(dev, &s->drq[1]);
|
||||
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c",
|
||||
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
s->bus = i2c_init_bus(&dev->qdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
|
||||
qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
|
||||
static Property omap_i2c_properties[] = {
|
||||
DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
|
||||
DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
|
||||
DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void omap_i2c_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
struct omap_i2c_s *s = (struct omap_i2c_s *)
|
||||
g_malloc0(sizeof(struct omap_i2c_s));
|
||||
|
||||
s->revision = 0x34;
|
||||
s->irq = irq;
|
||||
s->drq[0] = dma[0];
|
||||
s->drq[1] = dma[1];
|
||||
s->bus = i2c_init_bus(NULL, "i2c");
|
||||
omap_i2c_reset(s);
|
||||
|
||||
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap2.i2c",
|
||||
omap_l4_region_size(ta, 0));
|
||||
omap_l4_attach(ta, 0, &s->iomem);
|
||||
|
||||
return s;
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
k->init = omap_i2c_init;
|
||||
dc->props = omap_i2c_properties;
|
||||
dc->reset = omap_i2c_reset;
|
||||
}
|
||||
|
||||
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
|
||||
static TypeInfo omap_i2c_info = {
|
||||
.name = "omap_i2c",
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(OMAPI2CState),
|
||||
.class_init = omap_i2c_class_init,
|
||||
};
|
||||
|
||||
static void omap_i2c_register_types(void)
|
||||
{
|
||||
type_register_static(&omap_i2c_info);
|
||||
}
|
||||
|
||||
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
|
||||
{
|
||||
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, sysbus_from_qdev(omap_i2c));
|
||||
return s->bus;
|
||||
}
|
||||
|
||||
type_init(omap_i2c_register_types)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user