omap2.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,270 行 · 第 1/5 页

C
2,270
字号
static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,                uint32_t value){    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;    if (addr & 2)        return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);    else        s->writeh = (uint16_t) value;}static CPUWriteMemoryFunc *omap_gp_timer_writefn[] = {    omap_badwidth_write32,    omap_gp_timer_writeh,    omap_gp_timer_write,};struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,                qemu_irq irq, omap_clk fclk, omap_clk iclk){    int iomemtype;    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)            qemu_mallocz(sizeof(struct omap_gp_timer_s));    s->ta = ta;    s->irq = irq;    s->clk = fclk;    s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s);    s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s);    s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];    omap_gp_timer_reset(s);    omap_gp_timer_clk_setup(s);    iomemtype = cpu_register_io_memory(0, omap_gp_timer_readfn,                    omap_gp_timer_writefn, s);    s->base = omap_l4_attach(ta, 0, iomemtype);    return s;}/* 32-kHz Sync Timer of the OMAP2 */static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {    return muldiv64(qemu_get_clock(vm_clock), 0x8000, ticks_per_sec);}static void omap_synctimer_reset(struct omap_synctimer_s *s){    s->val = omap_synctimer_read(s);}static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr){    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;    int offset = addr - s->base;    switch (offset) {    case 0x00:	/* 32KSYNCNT_REV */        return 0x21;    case 0x10:	/* CR */        return omap_synctimer_read(s) - s->val;    }    OMAP_BAD_REG(addr);    return 0;}static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr){    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;    uint32_t ret;    if (addr & 2)        return s->readh;    else {        ret = omap_synctimer_readw(opaque, addr);        s->readh = ret >> 16;        return ret & 0xffff;    }}static CPUReadMemoryFunc *omap_synctimer_readfn[] = {    omap_badwidth_read32,    omap_synctimer_readh,    omap_synctimer_readw,};static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,                uint32_t value){    OMAP_BAD_REG(addr);}static CPUWriteMemoryFunc *omap_synctimer_writefn[] = {    omap_badwidth_write32,    omap_synctimer_write,    omap_synctimer_write,};void omap_synctimer_init(struct omap_target_agent_s *ta,                struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk){    struct omap_synctimer_s *s = &mpu->synctimer;    omap_synctimer_reset(s);    s->base = omap_l4_attach(ta, 0, cpu_register_io_memory(0,                            omap_synctimer_readfn, omap_synctimer_writefn, s));}/* General-Purpose Interface of OMAP2 */struct omap2_gpio_s {    target_phys_addr_t base;    qemu_irq irq[2];    qemu_irq wkup;    qemu_irq *in;    qemu_irq handler[32];    uint8_t config[2];    uint32_t inputs;    uint32_t outputs;    uint32_t dir;    uint32_t level[2];    uint32_t edge[2];    uint32_t mask[2];    uint32_t wumask;    uint32_t ints[2];    uint32_t debounce;    uint8_t delay;};static inline void omap_gpio_module_int_update(struct omap2_gpio_s *s,                int line){    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);}static void omap_gpio_module_wake(struct omap2_gpio_s *s, int line){    if (!(s->config[0] & (1 << 2)))			/* ENAWAKEUP */        return;    if (!(s->config[0] & (3 << 3)))			/* Force Idle */        return;    if (!(s->wumask & (1 << line)))        return;    qemu_irq_raise(s->wkup);}static inline void omap_gpio_module_out_update(struct omap2_gpio_s *s,                uint32_t diff){    int ln;    s->outputs ^= diff;    diff &= ~s->dir;    while ((ln = ffs(diff))) {        ln --;        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);        diff &= ~(1 << ln);    }}static void omap_gpio_module_level_update(struct omap2_gpio_s *s, int line){    s->ints[line] |= s->dir &            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));    omap_gpio_module_int_update(s, line);}static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line){    s->ints[0] |= 1 << line;    omap_gpio_module_int_update(s, 0);    s->ints[1] |= 1 << line;    omap_gpio_module_int_update(s, 1);    omap_gpio_module_wake(s, line);}static void omap_gpio_module_set(void *opaque, int line, int level){    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;    if (level) {        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))            omap_gpio_module_int(s, line);        s->inputs |= 1 << line;    } else {        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))            omap_gpio_module_int(s, line);        s->inputs &= ~(1 << line);    }}static void omap_gpio_module_reset(struct omap2_gpio_s *s){    s->config[0] = 0;    s->config[1] = 2;    s->ints[0] = 0;    s->ints[1] = 0;    s->mask[0] = 0;    s->mask[1] = 0;    s->wumask = 0;    s->dir = ~0;    s->level[0] = 0;    s->level[1] = 0;    s->edge[0] = 0;    s->edge[1] = 0;    s->debounce = 0;    s->delay = 0;}static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr){    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;    int offset = addr - s->base;    switch (offset) {    case 0x00:	/* GPIO_REVISION */        return 0x18;    case 0x10:	/* GPIO_SYSCONFIG */        return s->config[0];    case 0x14:	/* GPIO_SYSSTATUS */        return 0x01;    case 0x18:	/* GPIO_IRQSTATUS1 */        return s->ints[0];    case 0x1c:	/* GPIO_IRQENABLE1 */    case 0x60:	/* GPIO_CLEARIRQENABLE1 */    case 0x64:	/* GPIO_SETIRQENABLE1 */        return s->mask[0];    case 0x20:	/* GPIO_WAKEUPENABLE */    case 0x80:	/* GPIO_CLEARWKUENA */    case 0x84:	/* GPIO_SETWKUENA */        return s->wumask;    case 0x28:	/* GPIO_IRQSTATUS2 */        return s->ints[1];    case 0x2c:	/* GPIO_IRQENABLE2 */    case 0x70:	/* GPIO_CLEARIRQENABLE2 */    case 0x74:	/* GPIO_SETIREQNEABLE2 */        return s->mask[1];    case 0x30:	/* GPIO_CTRL */        return s->config[1];    case 0x34:	/* GPIO_OE */        return s->dir;    case 0x38:	/* GPIO_DATAIN */        return s->inputs;    case 0x3c:	/* GPIO_DATAOUT */    case 0x90:	/* GPIO_CLEARDATAOUT */    case 0x94:	/* GPIO_SETDATAOUT */        return s->outputs;    case 0x40:	/* GPIO_LEVELDETECT0 */        return s->level[0];    case 0x44:	/* GPIO_LEVELDETECT1 */        return s->level[1];    case 0x48:	/* GPIO_RISINGDETECT */        return s->edge[0];    case 0x4c:	/* GPIO_FALLINGDETECT */        return s->edge[1];    case 0x50:	/* GPIO_DEBOUNCENABLE */        return s->debounce;    case 0x54:	/* GPIO_DEBOUNCINGTIME */        return s->delay;    }    OMAP_BAD_REG(addr);    return 0;}static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr,                uint32_t value){    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;    int offset = addr - s->base;    uint32_t diff;    int ln;    switch (offset) {    case 0x00:	/* GPIO_REVISION */    case 0x14:	/* GPIO_SYSSTATUS */    case 0x38:	/* GPIO_DATAIN */        OMAP_RO_REG(addr);        break;    case 0x10:	/* GPIO_SYSCONFIG */        if (((value >> 3) & 3) == 3)            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);        if (value & 2)            omap_gpio_module_reset(s);        s->config[0] = value & 0x1d;        break;    case 0x18:	/* GPIO_IRQSTATUS1 */        if (s->ints[0] & value) {            s->ints[0] &= ~value;            omap_gpio_module_level_update(s, 0);        }        break;    case 0x1c:	/* GPIO_IRQENABLE1 */        s->mask[0] = value;        omap_gpio_module_int_update(s, 0);        break;    case 0x20:	/* GPIO_WAKEUPENABLE */        s->wumask = value;        break;    case 0x28:	/* GPIO_IRQSTATUS2 */        if (s->ints[1] & value) {            s->ints[1] &= ~value;            omap_gpio_module_level_update(s, 1);        }        break;    case 0x2c:	/* GPIO_IRQENABLE2 */        s->mask[1] = value;        omap_gpio_module_int_update(s, 1);        break;    case 0x30:	/* GPIO_CTRL */        s->config[1] = value & 7;        break;    case 0x34:	/* GPIO_OE */        diff = s->outputs & (s->dir ^ value);        s->dir = value;        value = s->outputs & ~s->dir;        while ((ln = ffs(diff))) {            diff &= ~(1 <<-- ln);            qemu_set_irq(s->handler[ln], (value >> ln) & 1);        }        omap_gpio_module_level_update(s, 0);        omap_gpio_module_level_update(s, 1);        break;    case 0x3c:	/* GPIO_DATAOUT */        omap_gpio_module_out_update(s, s->outputs ^ value);        break;    case 0x40:	/* GPIO_LEVELDETECT0 */        s->level[0] = value;        omap_gpio_module_level_update(s, 0);        omap_gpio_module_level_update(s, 1);        break;    case 0x44:	/* GPIO_LEVELDETECT1 */        s->level[1] = value;        omap_gpio_module_level_update(s, 0);        omap_gpio_module_level_update(s, 1);        break;    case 0x48:	/* GPIO_RISINGDETECT */        s->edge[0] = value;        break;    case 0x4c:	/* GPIO_FALLINGDETECT */        s->edge[1] = value;        break;    case 0x50:	/* GPIO_DEBOUNCENABLE */        s->debounce = value;        break;    case 0x54:	/* GPIO_DEBOUNCINGTIME */        s->delay = value;        break;    case 0x60:	/* GPIO_CLEARIRQENABLE1 */        s->mask[0] &= ~value;        omap_gpio_module_int_update(s, 0);        break;    case 0x64:	/* GPIO_SETIRQENABLE1 */        s->mask[0] |= value;        omap_gpio_module_int_update(s, 0);        break;    case 0x70:	/* GPIO_CLEARIRQENABLE2 */        s->mask[1] &= ~value;        omap_gpio_module_int_update(s, 1);        break;    case 0x74:	/* GPIO_SETIREQNEABLE2 */        s->mask[1] |= value;        omap_gpio_module_int_update(s, 1);        break;    case 0x80:	/* GPIO_CLEARWKUENA */        s->wumask &= ~value;        break;    case 0x84:	/* GPIO_SETWKUENA */        s->wumask |= value;        break;    case 0x90:	/* GPIO_CLEARDATAOUT */        omap_gpio_module_out_update(s, s->outputs & value);        break;    case 0x94:	/* GPIO_SETDATAOUT */        omap_gpio_module_out_update(s, ~s->outputs & value);        break;    default:        OMAP_BAD_REG(addr);        return;    }}static uint32_t omap_gpio_module_readp(void *opaque, target_phys_addr_t addr){    return omap_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);}static void omap_gpio_module_writep(void *opaque, target_phys_addr_t addr,                uint32_t value){    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;    int offset = addr - s->base;    uint32_t cur = 0;    uint32_t mask = 0xffff;    switch (offset & ~3) {    case 0x00:	/* GPIO_REVISION */    case 0x14:	/* GPIO_SYSSTATUS */    case 0x38:	/* GPIO_DATAIN */        OMAP_RO_REG(addr);        break;    case 0x10:	/* GPIO_SYSCONFIG */    case 0x1c:	/* GPIO_IRQENABLE1 */    case 0x20:	/* GPIO_WAKEUPENABLE */    case 0x2c:	/* GPIO_IRQENABLE2 */    case 0x30:	/* GPIO_CTRL */    case 0x34:	/* GPIO_OE */    case 0x3c:	/* GPIO_DATAOUT */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?