omap1.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,284 行 · 第 1/5 页
C
2,284 行
break; default: OMAP_BAD_REG(addr); }}static CPUReadMemoryFunc *omap_wd_timer_readfn[] = { omap_badwidth_read16, omap_wd_timer_read, omap_badwidth_read16,};static CPUWriteMemoryFunc *omap_wd_timer_writefn[] = { omap_badwidth_write16, omap_wd_timer_write, omap_badwidth_write16,};static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s){ qemu_del_timer(s->timer.timer); if (!s->mode) omap_clk_get(s->timer.clk); s->mode = 1; s->free = 1; s->reset = 0; s->timer.enable = 1; s->timer.it_ena = 1; s->timer.reset_val = 0xffff; s->timer.val = 0; s->timer.st = 0; s->timer.ptv = 0; s->timer.ar = 0; omap_timer_update(&s->timer);}struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base, qemu_irq irq, omap_clk clk){ int iomemtype; struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) qemu_mallocz(sizeof(struct omap_watchdog_timer_s)); s->timer.irq = irq; s->timer.clk = clk; s->timer.base = base; s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer); omap_wd_timer_reset(s); omap_timer_clk_setup(&s->timer); iomemtype = cpu_register_io_memory(0, omap_wd_timer_readfn, omap_wd_timer_writefn, s); cpu_register_physical_memory(s->timer.base, 0x100, iomemtype); return s;}/* 32-kHz timer */struct omap_32khz_timer_s { struct omap_mpu_timer_s timer;};static uint32_t omap_os_timer_read(void *opaque, target_phys_addr_t addr){ struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque; int offset = addr & OMAP_MPUI_REG_MASK; switch (offset) { case 0x00: /* TVR */ return s->timer.reset_val; case 0x04: /* TCR */ return omap_timer_read(&s->timer); case 0x08: /* CR */ return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st; default: break; } OMAP_BAD_REG(addr); return 0;}static void omap_os_timer_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque; int offset = addr & OMAP_MPUI_REG_MASK; switch (offset) { case 0x00: /* TVR */ s->timer.reset_val = value & 0x00ffffff; break; case 0x04: /* TCR */ OMAP_RO_REG(addr); break; case 0x08: /* CR */ s->timer.ar = (value >> 3) & 1; s->timer.it_ena = (value >> 2) & 1; if (s->timer.st != (value & 1) || (value & 2)) { omap_timer_sync(&s->timer); s->timer.enable = value & 1; s->timer.st = value & 1; omap_timer_update(&s->timer); } break; default: OMAP_BAD_REG(addr); }}static CPUReadMemoryFunc *omap_os_timer_readfn[] = { omap_badwidth_read32, omap_badwidth_read32, omap_os_timer_read,};static CPUWriteMemoryFunc *omap_os_timer_writefn[] = { omap_badwidth_write32, omap_badwidth_write32, omap_os_timer_write,};static void omap_os_timer_reset(struct omap_32khz_timer_s *s){ qemu_del_timer(s->timer.timer); s->timer.enable = 0; s->timer.it_ena = 0; s->timer.reset_val = 0x00ffffff; s->timer.val = 0; s->timer.st = 0; s->timer.ptv = 0; s->timer.ar = 1;}struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base, qemu_irq irq, omap_clk clk){ int iomemtype; struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) qemu_mallocz(sizeof(struct omap_32khz_timer_s)); s->timer.irq = irq; s->timer.clk = clk; s->timer.base = base; s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer); omap_os_timer_reset(s); omap_timer_clk_setup(&s->timer); iomemtype = cpu_register_io_memory(0, omap_os_timer_readfn, omap_os_timer_writefn, s); cpu_register_physical_memory(s->timer.base, 0x800, iomemtype); return s;}/* Ultra Low-Power Device Module */static uint32_t omap_ulpd_pm_read(void *opaque, target_phys_addr_t addr){ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; int offset = addr - s->ulpd_pm_base; uint16_t ret; switch (offset) { case 0x14: /* IT_STATUS */ ret = s->ulpd_pm_regs[offset >> 2]; s->ulpd_pm_regs[offset >> 2] = 0; qemu_irq_lower(s->irq[1][OMAP_INT_GAUGE_32K]); return ret; case 0x18: /* Reserved */ case 0x1c: /* Reserved */ case 0x20: /* Reserved */ case 0x28: /* Reserved */ case 0x2c: /* Reserved */ OMAP_BAD_REG(addr); case 0x00: /* COUNTER_32_LSB */ case 0x04: /* COUNTER_32_MSB */ case 0x08: /* COUNTER_HIGH_FREQ_LSB */ case 0x0c: /* COUNTER_HIGH_FREQ_MSB */ case 0x10: /* GAUGING_CTRL */ case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */ case 0x30: /* CLOCK_CTRL */ case 0x34: /* SOFT_REQ */ case 0x38: /* COUNTER_32_FIQ */ case 0x3c: /* DPLL_CTRL */ case 0x40: /* STATUS_REQ */ /* XXX: check clk::usecount state for every clock */ case 0x48: /* LOCL_TIME */ case 0x4c: /* APLL_CTRL */ case 0x50: /* POWER_CTRL */ return s->ulpd_pm_regs[offset >> 2]; } OMAP_BAD_REG(addr); return 0;}static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s, uint16_t diff, uint16_t value){ if (diff & (1 << 4)) /* USB_MCLK_EN */ omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1); if (diff & (1 << 5)) /* DIS_USB_PVCI_CLK */ omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);}static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s, uint16_t diff, uint16_t value){ if (diff & (1 << 0)) /* SOFT_DPLL_REQ */ omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1); if (diff & (1 << 1)) /* SOFT_COM_REQ */ omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1); if (diff & (1 << 2)) /* SOFT_SDW_REQ */ omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1); if (diff & (1 << 3)) /* SOFT_USB_REQ */ omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);}static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; int offset = addr - s->ulpd_pm_base; int64_t now, ticks; int div, mult; static const int bypass_div[4] = { 1, 2, 4, 4 }; uint16_t diff; switch (offset) { case 0x00: /* COUNTER_32_LSB */ case 0x04: /* COUNTER_32_MSB */ case 0x08: /* COUNTER_HIGH_FREQ_LSB */ case 0x0c: /* COUNTER_HIGH_FREQ_MSB */ case 0x14: /* IT_STATUS */ case 0x40: /* STATUS_REQ */ OMAP_RO_REG(addr); break; case 0x10: /* GAUGING_CTRL */ /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */ if ((s->ulpd_pm_regs[offset >> 2] ^ value) & 1) { now = qemu_get_clock(vm_clock); if (value & 1) s->ulpd_gauge_start = now; else { now -= s->ulpd_gauge_start; /* 32-kHz ticks */ ticks = muldiv64(now, 32768, ticks_per_sec); s->ulpd_pm_regs[0x00 >> 2] = (ticks >> 0) & 0xffff; s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff; if (ticks >> 32) /* OVERFLOW_32K */ s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2; /* High frequency ticks */ ticks = muldiv64(now, 12000000, ticks_per_sec); s->ulpd_pm_regs[0x08 >> 2] = (ticks >> 0) & 0xffff; s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff; if (ticks >> 32) /* OVERFLOW_HI_FREQ */ s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1; s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0; /* IT_GAUGING */ qemu_irq_raise(s->irq[1][OMAP_INT_GAUGE_32K]); } } s->ulpd_pm_regs[offset >> 2] = value; break; case 0x18: /* Reserved */ case 0x1c: /* Reserved */ case 0x20: /* Reserved */ case 0x28: /* Reserved */ case 0x2c: /* Reserved */ OMAP_BAD_REG(addr); case 0x24: /* SETUP_ANALOG_CELL3_ULPD1 */ case 0x38: /* COUNTER_32_FIQ */ case 0x48: /* LOCL_TIME */ case 0x50: /* POWER_CTRL */ s->ulpd_pm_regs[offset >> 2] = value; break; case 0x30: /* CLOCK_CTRL */ diff = s->ulpd_pm_regs[offset >> 2] ^ value; s->ulpd_pm_regs[offset >> 2] = value & 0x3f; omap_ulpd_clk_update(s, diff, value); break; case 0x34: /* SOFT_REQ */ diff = s->ulpd_pm_regs[offset >> 2] ^ value; s->ulpd_pm_regs[offset >> 2] = value & 0x1f; omap_ulpd_req_update(s, diff, value); break; case 0x3c: /* DPLL_CTRL */ /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is * omitted altogether, probably a typo. */ /* This register has identical semantics with DPLL(1:3) control * registers, see omap_dpll_write() */ diff = s->ulpd_pm_regs[offset >> 2] & value; s->ulpd_pm_regs[offset >> 2] = value & 0x2fff; if (diff & (0x3ff << 2)) { if (value & (1 << 4)) { /* PLL_ENABLE */ div = ((value >> 5) & 3) + 1; /* PLL_DIV */ mult = MIN((value >> 7) & 0x1f, 1); /* PLL_MULT */ } else { div = bypass_div[((value >> 2) & 3)]; /* BYPASS_DIV */ mult = 1; } omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult); } /* Enter the desired mode. */ s->ulpd_pm_regs[offset >> 2] = (s->ulpd_pm_regs[offset >> 2] & 0xfffe) | ((s->ulpd_pm_regs[offset >> 2] >> 4) & 1); /* Act as if the lock is restored. */ s->ulpd_pm_regs[offset >> 2] |= 2; break; case 0x4c: /* APLL_CTRL */ diff = s->ulpd_pm_regs[offset >> 2] & value; s->ulpd_pm_regs[offset >> 2] = value & 0xf; if (diff & (1 << 0)) /* APLL_NDPLL_SWITCH */ omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s, (value & (1 << 0)) ? "apll" : "dpll4")); break; default: OMAP_BAD_REG(addr); }}static CPUReadMemoryFunc *omap_ulpd_pm_readfn[] = { omap_badwidth_read16, omap_ulpd_pm_read, omap_badwidth_read16,};static CPUWriteMemoryFunc *omap_ulpd_pm_writefn[] = { omap_badwidth_write16, omap_ulpd_pm_write, omap_badwidth_write16,};static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu){ mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001; mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000; mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001; mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000; mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000; mpu->ulpd_pm_regs[0x18 >> 2] = 0x01; mpu->ulpd_pm_regs[0x1c >> 2] = 0x01; mpu->ulpd_pm_regs[0x20 >> 2] = 0x01; mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff; mpu->ulpd_pm_regs[0x28 >> 2] = 0x01; mpu->ulpd_pm_regs[0x2c >> 2] = 0x01; omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000); mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000; omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000); mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000; mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001; mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211; mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */ mpu->ulpd_pm_regs[0x48 >> 2] = 0x960; mpu->ulpd_pm_regs[0x4c >> 2] = 0x08; mpu->ulpd_pm_regs[0x50 >> 2] = 0x08; omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4); omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));}static void omap_ulpd_pm_init(target_phys_addr_t base, struct omap_mpu_state_s *mpu){ int iomemtype = cpu_register_io_memory(0, omap_ulpd_pm_readfn, omap_ulpd_pm_writefn, mpu); mpu->ulpd_pm_base = base; cpu_register_physical_memory(mpu->ulpd_pm_base, 0x800, iomemtype); omap_ulpd_pm_reset(mpu);}/* OMAP Pin Configuration */static uint32_t omap_pin_cfg_read(void *opaque, target_phys_addr_t addr){ struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; int offset = addr - s->pin_cfg_base; switch (offset) { case 0x00: /* FUNC_MUX_CTRL_0 */ case 0x04: /* FUNC_MUX_CTRL_1 */ case 0x08: /* FUNC_MUX_CTRL_2 */ return s->func_mux_ctrl[offset >> 2]; case 0x0c: /* COMP_MODE_CTRL_0 */ return s->comp_mode_ctrl[0]; case 0x10: /* FUNC_MUX_CTRL_3 */ case 0x14: /* FUNC_MUX_CTRL_4 */ case 0x18: /* FUNC_MUX_CTRL_5 */ case 0x1c: /* FUNC_MUX_CTRL_6 */ case 0x20: /* FUNC_MUX_CTRL_7 */ case 0x24: /* FUNC_MUX_CTRL_8 */ case 0x28: /* FUNC_MUX_CTRL_9 */ case 0x2c: /* FUNC_MUX_CTRL_A */ case 0x30: /* FUNC_MUX_CTRL_B */ case 0x34: /* FUNC_MUX_CTRL_C */ case 0x38: /* FUNC_MUX_CTRL_D */ return s->func_mux_ctrl[(offset >> 2) - 1]; case 0x40: /* PULL_DWN_CTRL_0 */ case 0x44: /* PULL_DWN_CTRL_1 */ case 0x48: /* PULL_DWN_CTRL_2 */ case 0x4c: /* PULL_DWN_CTRL_3 */ return s->pull_dwn_ctrl[(offset & 0xf) >> 2]; case 0x50: /* GATE_INH_CTRL_0 */ return s->gate_inh_ctrl[0]; case 0x60: /* VOLTAGE_CTRL_0 */ return s->voltage_ctrl[0]; case 0x70: /* TEST_DBG_CTRL_0 */ return s->test_dbg_ctrl[0]; case 0x80: /* MOD_CONF_CTRL_0 */ return s->mod_conf_ctrl[0]; } OMAP_BAD_REG(addr); return 0;}static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s, uint32_t diff, uint32_t value){ if (s->compat1509) { if (diff & (1 << 9)) /* BLUETOOTH */ omap_clk_onoff(omap_findclk(s, "bt_mclk_out"), (~value >> 9) & 1); if (diff & (1 << 7)) /* USB.CLKO */ omap_clk_onoff(omap_findclk(s, "usb.clko"), (value >> 7) & 1); }}static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s, uint32_t diff, uint32_t value)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?