omap2.c

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

C
2,270
字号
    case 0x40:	/* GPIO_LEVELDETECT0 */    case 0x44:	/* GPIO_LEVELDETECT1 */    case 0x48:	/* GPIO_RISINGDETECT */    case 0x4c:	/* GPIO_FALLINGDETECT */    case 0x50:	/* GPIO_DEBOUNCENABLE */    case 0x54:	/* GPIO_DEBOUNCINGTIME */        cur = omap_gpio_module_read(opaque, addr & ~3) &                ~(mask << ((addr & 3) << 3));        /* Fall through.  */    case 0x18:	/* GPIO_IRQSTATUS1 */    case 0x28:	/* GPIO_IRQSTATUS2 */    case 0x60:	/* GPIO_CLEARIRQENABLE1 */    case 0x64:	/* GPIO_SETIRQENABLE1 */    case 0x70:	/* GPIO_CLEARIRQENABLE2 */    case 0x74:	/* GPIO_SETIREQNEABLE2 */    case 0x80:	/* GPIO_CLEARWKUENA */    case 0x84:	/* GPIO_SETWKUENA */    case 0x90:	/* GPIO_CLEARDATAOUT */    case 0x94:	/* GPIO_SETDATAOUT */        value <<= (addr & 3) << 3;        omap_gpio_module_write(opaque, addr, cur | value);        break;    default:        OMAP_BAD_REG(addr);        return;    }}static CPUReadMemoryFunc *omap_gpio_module_readfn[] = {    omap_gpio_module_readp,    omap_gpio_module_readp,    omap_gpio_module_read,};static CPUWriteMemoryFunc *omap_gpio_module_writefn[] = {    omap_gpio_module_writep,    omap_gpio_module_writep,    omap_gpio_module_write,};static void omap_gpio_module_init(struct omap2_gpio_s *s,                struct omap_target_agent_s *ta, int region,                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,                omap_clk fclk, omap_clk iclk){    int iomemtype;    s->irq[0] = mpu;    s->irq[1] = dsp;    s->wkup = wkup;    s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32);    iomemtype = cpu_register_io_memory(0, omap_gpio_module_readfn,                    omap_gpio_module_writefn, s);    s->base = omap_l4_attach(ta, region, iomemtype);}struct omap_gpif_s {    struct omap2_gpio_s module[5];    int modules;    target_phys_addr_t topbase;    int autoidle;    int gpo;};static void omap_gpif_reset(struct omap_gpif_s *s){    int i;    for (i = 0; i < s->modules; i ++)        omap_gpio_module_reset(s->module + i);    s->autoidle = 0;    s->gpo = 0;}static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr){    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;    int offset = addr - s->topbase;    switch (offset) {    case 0x00:	/* IPGENERICOCPSPL_REVISION */        return 0x18;    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */        return s->autoidle;    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */        return 0x01;    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */        return 0x00;    case 0x40:	/* IPGENERICOCPSPL_GPO */        return s->gpo;    case 0x50:	/* IPGENERICOCPSPL_GPI */        return 0x00;    }    OMAP_BAD_REG(addr);    return 0;}static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,                uint32_t value){    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;    int offset = addr - s->topbase;    switch (offset) {    case 0x00:	/* IPGENERICOCPSPL_REVISION */    case 0x14:	/* IPGENERICOCPSPL_SYSSTATUS */    case 0x18:	/* IPGENERICOCPSPL_IRQSTATUS */    case 0x50:	/* IPGENERICOCPSPL_GPI */        OMAP_RO_REG(addr);        break;    case 0x10:	/* IPGENERICOCPSPL_SYSCONFIG */        if (value & (1 << 1))					/* SOFTRESET */            omap_gpif_reset(s);        s->autoidle = value & 1;        break;    case 0x40:	/* IPGENERICOCPSPL_GPO */        s->gpo = value & 1;        break;    default:        OMAP_BAD_REG(addr);        return;    }}static CPUReadMemoryFunc *omap_gpif_top_readfn[] = {    omap_gpif_top_read,    omap_gpif_top_read,    omap_gpif_top_read,};static CPUWriteMemoryFunc *omap_gpif_top_writefn[] = {    omap_gpif_top_write,    omap_gpif_top_write,    omap_gpif_top_write,};struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules){    int iomemtype, i;    struct omap_gpif_s *s = (struct omap_gpif_s *)            qemu_mallocz(sizeof(struct omap_gpif_s));    int region[4] = { 0, 2, 4, 5 };    s->modules = modules;    for (i = 0; i < modules; i ++)        omap_gpio_module_init(s->module + i, ta, region[i],                        irq[i], 0, 0, fclk[i], iclk);    omap_gpif_reset(s);    iomemtype = cpu_register_io_memory(0, omap_gpif_top_readfn,                    omap_gpif_top_writefn, s);    s->topbase = omap_l4_attach(ta, 1, iomemtype);    return s;}qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start){    if (start >= s->modules * 32 || start < 0)        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n",                        __FUNCTION__, start);    return s->module[start >> 5].in + (start & 31);}void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler){    if (line >= s->modules * 32 || line < 0)        cpu_abort(cpu_single_env, "%s: No GPIO line %i\n", __FUNCTION__, line);    s->module[line >> 5].handler[line & 31] = handler;}/* Multichannel SPI */struct omap_mcspi_s {    target_phys_addr_t base;    qemu_irq irq;    int chnum;    uint32_t sysconfig;    uint32_t systest;    uint32_t irqst;    uint32_t irqen;    uint32_t wken;    uint32_t control;    struct omap_mcspi_ch_s {        qemu_irq txdrq;        qemu_irq rxdrq;        uint32_t (*txrx)(void *opaque, uint32_t, int);        void *opaque;        uint32_t tx;        uint32_t rx;        uint32_t config;        uint32_t status;        uint32_t control;    } ch[4];};static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s){    qemu_set_irq(s->irq, s->irqst & s->irqen);}static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch){    qemu_set_irq(ch->txdrq,                    (ch->control & 1) &&		/* EN */                    (ch->config & (1 << 14)) &&		/* DMAW */                    (ch->status & (1 << 1)) &&		/* TXS */                    ((ch->config >> 12) & 3) != 1);	/* TRM */    qemu_set_irq(ch->rxdrq,                    (ch->control & 1) &&		/* EN */                    (ch->config & (1 << 15)) &&		/* DMAW */                    (ch->status & (1 << 0)) &&		/* RXS */                    ((ch->config >> 12) & 3) != 2);	/* TRM */}static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum){    struct omap_mcspi_ch_s *ch = s->ch + chnum;    if (!(ch->control & 1))				/* EN */        return;    if ((ch->status & (1 << 0)) &&			/* RXS */                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */                    !(ch->config & (1 << 19)))		/* TURBO */        goto intr_update;    if ((ch->status & (1 << 1)) &&			/* TXS */                    ((ch->config >> 12) & 3) != 1)	/* TRM */        goto intr_update;    if (!(s->control & 1) ||				/* SINGLE */                    (ch->config & (1 << 20))) {		/* FORCE */        if (ch->txrx)            ch->rx = ch->txrx(ch->opaque, ch->tx,	/* WL */                            1 + (0x1f & (ch->config >> 7)));    }    ch->tx = 0;    ch->status |= 1 << 2;				/* EOT */    ch->status |= 1 << 1;				/* TXS */    if (((ch->config >> 12) & 3) != 2)			/* TRM */        ch->status |= 1 << 0;				/* RXS */intr_update:    if ((ch->status & (1 << 0)) &&			/* RXS */                    ((ch->config >> 12) & 3) != 2 &&	/* TRM */                    !(ch->config & (1 << 19)))		/* TURBO */        s->irqst |= 1 << (2 + 4 * chnum);		/* RX_FULL */    if ((ch->status & (1 << 1)) &&			/* TXS */                    ((ch->config >> 12) & 3) != 1)	/* TRM */        s->irqst |= 1 << (0 + 4 * chnum);		/* TX_EMPTY */    omap_mcspi_interrupt_update(s);    omap_mcspi_dmarequest_update(ch);}static void omap_mcspi_reset(struct omap_mcspi_s *s){    int ch;    s->sysconfig = 0;    s->systest = 0;    s->irqst = 0;    s->irqen = 0;    s->wken = 0;    s->control = 4;    for (ch = 0; ch < 4; ch ++) {        s->ch[ch].config = 0x060000;        s->ch[ch].status = 2;				/* TXS */        s->ch[ch].control = 0;        omap_mcspi_dmarequest_update(s->ch + ch);    }    omap_mcspi_interrupt_update(s);}static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr){    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;    int offset = addr - s->base;    int ch = 0;    uint32_t ret;    switch (offset) {    case 0x00:	/* MCSPI_REVISION */        return 0x91;    case 0x10:	/* MCSPI_SYSCONFIG */        return s->sysconfig;    case 0x14:	/* MCSPI_SYSSTATUS */        return 1;					/* RESETDONE */    case 0x18:	/* MCSPI_IRQSTATUS */        return s->irqst;    case 0x1c:	/* MCSPI_IRQENABLE */        return s->irqen;    case 0x20:	/* MCSPI_WAKEUPENABLE */        return s->wken;    case 0x24:	/* MCSPI_SYST */        return s->systest;    case 0x28:	/* MCSPI_MODULCTRL */        return s->control;    case 0x68: ch ++;    case 0x54: ch ++;    case 0x40: ch ++;    case 0x2c:	/* MCSPI_CHCONF */        return s->ch[ch].config;    case 0x6c: ch ++;    case 0x58: ch ++;    case 0x44: ch ++;    case 0x30:	/* MCSPI_CHSTAT */        return s->ch[ch].status;    case 0x70: ch ++;    case 0x5c: ch ++;    case 0x48: ch ++;    case 0x34:	/* MCSPI_CHCTRL */        return s->ch[ch].control;    case 0x74: ch ++;    case 0x60: ch ++;    case 0x4c: ch ++;    case 0x38:	/* MCSPI_TX */        return s->ch[ch].tx;    case 0x78: ch ++;    case 0x64: ch ++;    case 0x50: ch ++;    case 0x3c:	/* MCSPI_RX */        s->ch[ch].status &= ~(1 << 0);			/* RXS */        ret = s->ch[ch].rx;        omap_mcspi_transfer_run(s, ch);        return ret;    }    OMAP_BAD_REG(addr);    return 0;}static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,                uint32_t value){    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;    int offset = addr - s->base;    int ch = 0;    switch (offset) {    case 0x00:	/* MCSPI_REVISION */    case 0x14:	/* MCSPI_SYSSTATUS */    case 0x30:	/* MCSPI_CHSTAT0 */    case 0x3c:	/* MCSPI_RX0 */    case 0x44:	/* MCSPI_CHSTAT1 */    case 0x50:	/* MCSPI_RX1 */    case 0x58:	/* MCSPI_CHSTAT2 */    case 0x64:	/* MCSPI_RX2 */    case 0x6c:	/* MCSPI_CHSTAT3 */    case 0x78:	/* MCSPI_RX3 */        OMAP_RO_REG(addr);        return;    case 0x10:	/* MCSPI_SYSCONFIG */        if (value & (1 << 1))				/* SOFTRESET */            omap_mcspi_reset(s);        s->sysconfig = value & 0x31d;        break;    case 0x18:	/* MCSPI_IRQSTATUS */        if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) {            s->irqst &= ~value;            omap_mcspi_interrupt_update(s);        }        break;    case 0x1c:	/* MCSPI_IRQENABLE */        s->irqen = value & 0x1777f;        omap_mcspi_interrupt_update(s);        break;    case 0x20:	/* MCSPI_WAKEUPENABLE */        s->wken = value & 1;        break;    case 0x24:	/* MCSPI_SYST */        if (s->control & (1 << 3))			/* SYSTEM_TEST */            if (value & (1 << 11)) {			/* SSB */                s->irqst |= 0x1777f;                omap_mcspi_interrupt_update(s);            }        s->systest = value & 0xfff;        break;    case 0x28:	/* MCSPI_MODULCTRL */        if (value & (1 << 3))				/* SYSTEM_TEST */            if (s->systest & (1 << 11)) {		/* SSB */                s->irqst |= 0x1777f;                omap_mcspi_interrupt_update(s);            }        s->control = value & 0xf;        break;    case 0x68: ch ++;    case 0x54: ch ++;    case 0x40: ch ++;    case 0x2c:	/* MCSPI_CHCONF */        if ((value ^ s->ch[ch].config) & (3 << 14))	/* DMAR | DMAW */            omap_mcspi_dmarequest_update(s->ch + ch);        if (((value >> 12) & 3) == 3)			/* TRM */            fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);        if (((value >> 7) & 0x1f) < 3)			/* WL */            fprintf(stderr, "%s: invalid WL value (%i)\n",                            __FUNCTION__, (value >> 7) & 0x1f);        s->ch[ch].config = value & 0x7fffff;        break;    case 0x70: ch ++;    case 0x5c: ch ++;    case 0x48: ch ++;    case 0x34:	/* MCSPI_CHCTRL */        if (value & ~s->ch[ch].control & 1) {		/* EN */            s->ch[ch].control |= 1;            omap_mcspi_transfer_run(s, ch);        } else            s->ch[ch].control = value & 1;        break;    case 0x74: ch ++;    case 0x60: ch ++;    case 0x4c: ch ++;

⌨️ 快捷键说明

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