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 + -
显示快捷键?