Revision d8f699cb hw/omap.c
b/hw/omap.c | ||
---|---|---|
254 | 254 |
|
255 | 255 |
switch (offset) { |
256 | 256 |
case 0x00: /* ITR */ |
257 |
s->irqs &= value; |
|
257 |
s->irqs &= value | 1;
|
|
258 | 258 |
omap_inth_sir_update(s); |
259 | 259 |
omap_inth_update(s); |
260 | 260 |
return; |
... | ... | |
992 | 992 |
struct omap_dma_s *s = (struct omap_dma_s *) opaque; |
993 | 993 |
|
994 | 994 |
if (on) { |
995 |
s->delay = ticks_per_sec >> 5;
|
|
995 |
s->delay = ticks_per_sec >> 7;
|
|
996 | 996 |
if (s->run_count) |
997 | 997 |
qemu_mod_timer(s->tm, qemu_get_clock(vm_clock) + s->delay); |
998 | 998 |
} else { |
... | ... | |
1325 | 1325 |
s->mode |= (value >> 15) & 1; |
1326 | 1326 |
if (s->last_wr == 0xf5) { |
1327 | 1327 |
if ((value & 0xff) == 0xa0) { |
1328 |
s->mode = 0; |
|
1329 |
omap_clk_put(s->timer.clk); |
|
1328 |
if (s->mode) { |
|
1329 |
s->mode = 0; |
|
1330 |
omap_clk_put(s->timer.clk); |
|
1331 |
} |
|
1330 | 1332 |
} else { |
1331 | 1333 |
/* XXX: on T|E hardware somehow this has no effect, |
1332 | 1334 |
* on Zire 71 it works as specified. */ |
... | ... | |
2217 | 2219 |
uint32_t ret; |
2218 | 2220 |
|
2219 | 2221 |
switch (offset) { |
2220 |
case 0xfffecc00: /* IMIF_PRIO */
|
|
2221 |
case 0xfffecc04: /* EMIFS_PRIO */
|
|
2222 |
case 0xfffecc08: /* EMIFF_PRIO */
|
|
2223 |
case 0xfffecc0c: /* EMIFS_CONFIG */
|
|
2224 |
case 0xfffecc10: /* EMIFS_CS0_CONFIG */
|
|
2225 |
case 0xfffecc14: /* EMIFS_CS1_CONFIG */
|
|
2226 |
case 0xfffecc18: /* EMIFS_CS2_CONFIG */
|
|
2227 |
case 0xfffecc1c: /* EMIFS_CS3_CONFIG */
|
|
2228 |
case 0xfffecc24: /* EMIFF_MRS */
|
|
2229 |
case 0xfffecc28: /* TIMEOUT1 */
|
|
2230 |
case 0xfffecc2c: /* TIMEOUT2 */
|
|
2231 |
case 0xfffecc30: /* TIMEOUT3 */
|
|
2232 |
case 0xfffecc3c: /* EMIFF_SDRAM_CONFIG_2 */
|
|
2233 |
case 0xfffecc40: /* EMIFS_CFG_DYN_WAIT */
|
|
2222 |
case 0x00: /* IMIF_PRIO */ |
|
2223 |
case 0x04: /* EMIFS_PRIO */ |
|
2224 |
case 0x08: /* EMIFF_PRIO */ |
|
2225 |
case 0x0c: /* EMIFS_CONFIG */ |
|
2226 |
case 0x10: /* EMIFS_CS0_CONFIG */ |
|
2227 |
case 0x14: /* EMIFS_CS1_CONFIG */ |
|
2228 |
case 0x18: /* EMIFS_CS2_CONFIG */ |
|
2229 |
case 0x1c: /* EMIFS_CS3_CONFIG */ |
|
2230 |
case 0x24: /* EMIFF_MRS */ |
|
2231 |
case 0x28: /* TIMEOUT1 */ |
|
2232 |
case 0x2c: /* TIMEOUT2 */ |
|
2233 |
case 0x30: /* TIMEOUT3 */ |
|
2234 |
case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */ |
|
2235 |
case 0x40: /* EMIFS_CFG_DYN_WAIT */ |
|
2234 | 2236 |
return s->tcmi_regs[offset >> 2]; |
2235 | 2237 |
|
2236 |
case 0xfffecc20: /* EMIFF_SDRAM_CONFIG */
|
|
2238 |
case 0x20: /* EMIFF_SDRAM_CONFIG */ |
|
2237 | 2239 |
ret = s->tcmi_regs[offset >> 2]; |
2238 | 2240 |
s->tcmi_regs[offset >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */ |
2239 | 2241 |
/* XXX: We can try using the VGA_DIRTY flag for this */ |
... | ... | |
2251 | 2253 |
int offset = addr - s->tcmi_base; |
2252 | 2254 |
|
2253 | 2255 |
switch (offset) { |
2254 |
case 0xfffecc00: /* IMIF_PRIO */
|
|
2255 |
case 0xfffecc04: /* EMIFS_PRIO */
|
|
2256 |
case 0xfffecc08: /* EMIFF_PRIO */
|
|
2257 |
case 0xfffecc10: /* EMIFS_CS0_CONFIG */
|
|
2258 |
case 0xfffecc14: /* EMIFS_CS1_CONFIG */
|
|
2259 |
case 0xfffecc18: /* EMIFS_CS2_CONFIG */
|
|
2260 |
case 0xfffecc1c: /* EMIFS_CS3_CONFIG */
|
|
2261 |
case 0xfffecc20: /* EMIFF_SDRAM_CONFIG */
|
|
2262 |
case 0xfffecc24: /* EMIFF_MRS */
|
|
2263 |
case 0xfffecc28: /* TIMEOUT1 */
|
|
2264 |
case 0xfffecc2c: /* TIMEOUT2 */
|
|
2265 |
case 0xfffecc30: /* TIMEOUT3 */
|
|
2266 |
case 0xfffecc3c: /* EMIFF_SDRAM_CONFIG_2 */
|
|
2267 |
case 0xfffecc40: /* EMIFS_CFG_DYN_WAIT */
|
|
2256 |
case 0x00: /* IMIF_PRIO */ |
|
2257 |
case 0x04: /* EMIFS_PRIO */ |
|
2258 |
case 0x08: /* EMIFF_PRIO */ |
|
2259 |
case 0x10: /* EMIFS_CS0_CONFIG */ |
|
2260 |
case 0x14: /* EMIFS_CS1_CONFIG */ |
|
2261 |
case 0x18: /* EMIFS_CS2_CONFIG */ |
|
2262 |
case 0x1c: /* EMIFS_CS3_CONFIG */ |
|
2263 |
case 0x20: /* EMIFF_SDRAM_CONFIG */ |
|
2264 |
case 0x24: /* EMIFF_MRS */ |
|
2265 |
case 0x28: /* TIMEOUT1 */ |
|
2266 |
case 0x2c: /* TIMEOUT2 */ |
|
2267 |
case 0x30: /* TIMEOUT3 */ |
|
2268 |
case 0x3c: /* EMIFF_SDRAM_CONFIG_2 */ |
|
2269 |
case 0x40: /* EMIFS_CFG_DYN_WAIT */ |
|
2268 | 2270 |
s->tcmi_regs[offset >> 2] = value; |
2269 | 2271 |
break; |
2270 |
case 0xfffecc0c: /* EMIFS_CONFIG */
|
|
2272 |
case 0x0c: /* EMIFS_CONFIG */ |
|
2271 | 2273 |
s->tcmi_regs[offset >> 2] = (value & 0xf) | (1 << 4); |
2272 | 2274 |
break; |
2273 | 2275 |
|
... | ... | |
2441 | 2443 |
return s->clkm.arm_rstct2; |
2442 | 2444 |
|
2443 | 2445 |
case 0x18: /* ARM_SYSST */ |
2444 |
return (s->clkm.clocking_scheme < 11) | s->clkm.cold_start; |
|
2446 |
return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
|
|
2445 | 2447 |
|
2446 | 2448 |
case 0x1c: /* ARM_CKOUT1 */ |
2447 | 2449 |
return s->clkm.arm_ckout1; |
... | ... | |
2720 | 2722 |
return s->clkm.dsp_rstct2; |
2721 | 2723 |
|
2722 | 2724 |
case 0x18: /* DSP_SYSST */ |
2723 |
return (s->clkm.clocking_scheme < 11) | s->clkm.cold_start | |
|
2725 |
return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
|
|
2724 | 2726 |
(s->env->halted << 6); /* Quite useless... */ |
2725 | 2727 |
} |
2726 | 2728 |
|
... | ... | |
2796 | 2798 |
s->clkm.clocking_scheme = 0; |
2797 | 2799 |
omap_clkm_ckctl_update(s, ~0, 0x3000); |
2798 | 2800 |
s->clkm.arm_ckctl = 0x3000; |
2799 |
omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 & 0x0400, 0x0400);
|
|
2801 |
omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
|
|
2800 | 2802 |
s->clkm.arm_idlect1 = 0x0400; |
2801 |
omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 & 0x0100, 0x0100);
|
|
2803 |
omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
|
|
2802 | 2804 |
s->clkm.arm_idlect2 = 0x0100; |
2803 | 2805 |
s->clkm.arm_ewupct = 0x003f; |
2804 | 2806 |
s->clkm.arm_rstct1 = 0x0000; |
... | ... | |
2822 | 2824 |
|
2823 | 2825 |
s->clkm.mpu_base = mpu_base; |
2824 | 2826 |
s->clkm.dsp_base = dsp_base; |
2825 |
s->clkm.cold_start = 0x3a; |
|
2827 |
s->clkm.arm_idlect1 = 0x03ff; |
|
2828 |
s->clkm.arm_idlect2 = 0x0100; |
|
2829 |
s->clkm.dsp_idlect1 = 0x0002; |
|
2826 | 2830 |
omap_clkm_reset(s); |
2831 |
s->clkm.cold_start = 0x3a; |
|
2827 | 2832 |
|
2828 | 2833 |
cpu_register_physical_memory(s->clkm.mpu_base, 0x100, iomemtype[0]); |
2829 | 2834 |
cpu_register_physical_memory(s->clkm.dsp_base, 0x1000, iomemtype[1]); |
... | ... | |
2956 | 2961 |
|
2957 | 2962 |
switch (offset) { |
2958 | 2963 |
case 0x04: /* OUTPUT_REG */ |
2959 |
diff = s->outputs ^ (value & ~s->dir);
|
|
2964 |
diff = (s->outputs ^ value) & ~s->dir;
|
|
2960 | 2965 |
s->outputs = value; |
2961 |
value &= ~s->dir; |
|
2962 | 2966 |
while ((ln = ffs(diff))) { |
2963 | 2967 |
ln --; |
2964 | 2968 |
if (s->handler[ln]) |
... | ... | |
3120 | 3124 |
uint16_t edge; |
3121 | 3125 |
uint16_t mask; |
3122 | 3126 |
uint16_t ints; |
3127 |
uint16_t pins; |
|
3123 | 3128 |
}; |
3124 | 3129 |
|
3125 | 3130 |
static void omap_gpio_set(void *opaque, int line, int level) |
... | ... | |
3146 | 3151 |
|
3147 | 3152 |
switch (offset) { |
3148 | 3153 |
case 0x00: /* DATA_INPUT */ |
3149 |
return s->inputs; |
|
3154 |
return s->inputs & s->pins;
|
|
3150 | 3155 |
|
3151 | 3156 |
case 0x04: /* DATA_OUTPUT */ |
3152 | 3157 |
return s->outputs; |
... | ... | |
3162 | 3167 |
|
3163 | 3168 |
case 0x14: /* INTERRUPT_STATUS */ |
3164 | 3169 |
return s->ints; |
3170 |
|
|
3171 |
case 0x18: /* PIN_CONTROL (not in OMAP310) */ |
|
3172 |
OMAP_BAD_REG(addr); |
|
3173 |
return s->pins; |
|
3165 | 3174 |
} |
3166 | 3175 |
|
3167 | 3176 |
OMAP_BAD_REG(addr); |
... | ... | |
3219 | 3228 |
qemu_irq_lower(s->irq); |
3220 | 3229 |
break; |
3221 | 3230 |
|
3231 |
case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */ |
|
3232 |
OMAP_BAD_REG(addr); |
|
3233 |
s->pins = value; |
|
3234 |
break; |
|
3235 |
|
|
3222 | 3236 |
default: |
3223 | 3237 |
OMAP_BAD_REG(addr); |
3224 | 3238 |
return; |
... | ... | |
3246 | 3260 |
s->edge = ~0; |
3247 | 3261 |
s->mask = ~0; |
3248 | 3262 |
s->ints = 0; |
3263 |
s->pins = ~0; |
|
3249 | 3264 |
} |
3250 | 3265 |
|
3251 | 3266 |
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base, |
... | ... | |
4058 | 4073 |
return s; |
4059 | 4074 |
} |
4060 | 4075 |
|
4076 |
/* Multi-channel Buffered Serial Port interfaces */ |
|
4077 |
struct omap_mcbsp_s { |
|
4078 |
target_phys_addr_t base; |
|
4079 |
qemu_irq txirq; |
|
4080 |
qemu_irq rxirq; |
|
4081 |
qemu_irq txdrq; |
|
4082 |
qemu_irq rxdrq; |
|
4083 |
|
|
4084 |
uint16_t spcr[2]; |
|
4085 |
uint16_t rcr[2]; |
|
4086 |
uint16_t xcr[2]; |
|
4087 |
uint16_t srgr[2]; |
|
4088 |
uint16_t mcr[2]; |
|
4089 |
uint16_t pcr; |
|
4090 |
uint16_t rcer[8]; |
|
4091 |
uint16_t xcer[8]; |
|
4092 |
int tx_rate; |
|
4093 |
int rx_rate; |
|
4094 |
int tx_req; |
|
4095 |
|
|
4096 |
struct i2s_codec_s *codec; |
|
4097 |
}; |
|
4098 |
|
|
4099 |
static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s) |
|
4100 |
{ |
|
4101 |
int irq; |
|
4102 |
|
|
4103 |
switch ((s->spcr[0] >> 4) & 3) { /* RINTM */ |
|
4104 |
case 0: |
|
4105 |
irq = (s->spcr[0] >> 1) & 1; /* RRDY */ |
|
4106 |
break; |
|
4107 |
case 3: |
|
4108 |
irq = (s->spcr[0] >> 3) & 1; /* RSYNCERR */ |
|
4109 |
break; |
|
4110 |
default: |
|
4111 |
irq = 0; |
|
4112 |
break; |
|
4113 |
} |
|
4114 |
|
|
4115 |
qemu_set_irq(s->rxirq, irq); |
|
4116 |
|
|
4117 |
switch ((s->spcr[1] >> 4) & 3) { /* XINTM */ |
|
4118 |
case 0: |
|
4119 |
irq = (s->spcr[1] >> 1) & 1; /* XRDY */ |
|
4120 |
break; |
|
4121 |
case 3: |
|
4122 |
irq = (s->spcr[1] >> 3) & 1; /* XSYNCERR */ |
|
4123 |
break; |
|
4124 |
default: |
|
4125 |
irq = 0; |
|
4126 |
break; |
|
4127 |
} |
|
4128 |
|
|
4129 |
qemu_set_irq(s->txirq, irq); |
|
4130 |
} |
|
4131 |
|
|
4132 |
static void omap_mcbsp_req_update(struct omap_mcbsp_s *s) |
|
4133 |
{ |
|
4134 |
int prev = s->tx_req; |
|
4135 |
|
|
4136 |
s->tx_req = (s->tx_rate || |
|
4137 |
(s->spcr[0] & (1 << 12))) && /* CLKSTP */ |
|
4138 |
(s->spcr[1] & (1 << 6)) && /* GRST */ |
|
4139 |
(s->spcr[1] & (1 << 0)); /* XRST */ |
|
4140 |
|
|
4141 |
if (!s->tx_req && prev) { |
|
4142 |
s->spcr[1] &= ~(1 << 1); /* XRDY */ |
|
4143 |
qemu_irq_lower(s->txdrq); |
|
4144 |
omap_mcbsp_intr_update(s); |
|
4145 |
|
|
4146 |
if (s->codec) |
|
4147 |
s->codec->tx_swallow(s->codec->opaque); |
|
4148 |
} else if (s->codec && s->tx_req && !prev) { |
|
4149 |
s->spcr[1] |= 1 << 1; /* XRDY */ |
|
4150 |
qemu_irq_raise(s->txdrq); |
|
4151 |
omap_mcbsp_intr_update(s); |
|
4152 |
} |
|
4153 |
} |
|
4154 |
|
|
4155 |
static void omap_mcbsp_rate_update(struct omap_mcbsp_s *s) |
|
4156 |
{ |
|
4157 |
int rx_clk = 0, tx_clk = 0; |
|
4158 |
int cpu_rate = 1500000; /* XXX */ |
|
4159 |
if (!s->codec) |
|
4160 |
return; |
|
4161 |
|
|
4162 |
if (s->spcr[1] & (1 << 6)) { /* GRST */ |
|
4163 |
if (s->spcr[0] & (1 << 0)) /* RRST */ |
|
4164 |
if ((s->srgr[1] & (1 << 13)) && /* CLKSM */ |
|
4165 |
(s->pcr & (1 << 8))) /* CLKRM */ |
|
4166 |
if (~s->pcr & (1 << 7)) /* SCLKME */ |
|
4167 |
rx_clk = cpu_rate / |
|
4168 |
((s->srgr[0] & 0xff) + 1); /* CLKGDV */ |
|
4169 |
if (s->spcr[1] & (1 << 0)) /* XRST */ |
|
4170 |
if ((s->srgr[1] & (1 << 13)) && /* CLKSM */ |
|
4171 |
(s->pcr & (1 << 9))) /* CLKXM */ |
|
4172 |
if (~s->pcr & (1 << 7)) /* SCLKME */ |
|
4173 |
tx_clk = cpu_rate / |
|
4174 |
((s->srgr[0] & 0xff) + 1); /* CLKGDV */ |
|
4175 |
} |
|
4176 |
|
|
4177 |
s->codec->set_rate(s->codec->opaque, rx_clk, tx_clk); |
|
4178 |
} |
|
4179 |
|
|
4180 |
static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s) |
|
4181 |
{ |
|
4182 |
if (!(s->spcr[0] & 1)) { /* RRST */ |
|
4183 |
if (s->codec) |
|
4184 |
s->codec->in.len = 0; |
|
4185 |
return; |
|
4186 |
} |
|
4187 |
|
|
4188 |
if ((s->spcr[0] >> 1) & 1) /* RRDY */ |
|
4189 |
s->spcr[0] |= 1 << 2; /* RFULL */ |
|
4190 |
s->spcr[0] |= 1 << 1; /* RRDY */ |
|
4191 |
qemu_irq_raise(s->rxdrq); |
|
4192 |
omap_mcbsp_intr_update(s); |
|
4193 |
} |
|
4194 |
|
|
4195 |
static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s) |
|
4196 |
{ |
|
4197 |
s->spcr[0] &= ~(1 << 1); /* RRDY */ |
|
4198 |
qemu_irq_lower(s->rxdrq); |
|
4199 |
omap_mcbsp_intr_update(s); |
|
4200 |
} |
|
4201 |
|
|
4202 |
static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s) |
|
4203 |
{ |
|
4204 |
if (s->tx_rate) |
|
4205 |
return; |
|
4206 |
s->tx_rate = 1; |
|
4207 |
omap_mcbsp_req_update(s); |
|
4208 |
} |
|
4209 |
|
|
4210 |
static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s) |
|
4211 |
{ |
|
4212 |
s->tx_rate = 0; |
|
4213 |
omap_mcbsp_req_update(s); |
|
4214 |
} |
|
4215 |
|
|
4216 |
static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr) |
|
4217 |
{ |
|
4218 |
struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; |
|
4219 |
int offset = addr & OMAP_MPUI_REG_MASK; |
|
4220 |
uint16_t ret; |
|
4221 |
|
|
4222 |
switch (offset) { |
|
4223 |
case 0x00: /* DRR2 */ |
|
4224 |
if (((s->rcr[0] >> 5) & 7) < 3) /* RWDLEN1 */ |
|
4225 |
return 0x0000; |
|
4226 |
/* Fall through. */ |
|
4227 |
case 0x02: /* DRR1 */ |
|
4228 |
if (!s->codec) |
|
4229 |
return 0x0000; |
|
4230 |
if (s->codec->in.len < 2) { |
|
4231 |
printf("%s: Rx FIFO underrun\n", __FUNCTION__); |
|
4232 |
omap_mcbsp_rx_stop(s); |
|
4233 |
} else { |
|
4234 |
s->codec->in.len -= 2; |
|
4235 |
ret = s->codec->in.fifo[s->codec->in.start ++] << 8; |
|
4236 |
ret |= s->codec->in.fifo[s->codec->in.start ++]; |
|
4237 |
if (!s->codec->in.len) |
|
4238 |
omap_mcbsp_rx_stop(s); |
|
4239 |
return ret; |
|
4240 |
} |
|
4241 |
return 0x0000; |
|
4242 |
|
|
4243 |
case 0x04: /* DXR2 */ |
|
4244 |
case 0x06: /* DXR1 */ |
|
4245 |
return 0x0000; |
|
4246 |
|
|
4247 |
case 0x08: /* SPCR2 */ |
|
4248 |
return s->spcr[1]; |
|
4249 |
case 0x0a: /* SPCR1 */ |
|
4250 |
return s->spcr[0]; |
|
4251 |
case 0x0c: /* RCR2 */ |
|
4252 |
return s->rcr[1]; |
|
4253 |
case 0x0e: /* RCR1 */ |
|
4254 |
return s->rcr[0]; |
|
4255 |
case 0x10: /* XCR2 */ |
|
4256 |
return s->xcr[1]; |
|
4257 |
case 0x12: /* XCR1 */ |
|
4258 |
return s->xcr[0]; |
|
4259 |
case 0x14: /* SRGR2 */ |
|
4260 |
return s->srgr[1]; |
|
4261 |
case 0x16: /* SRGR1 */ |
|
4262 |
return s->srgr[0]; |
|
4263 |
case 0x18: /* MCR2 */ |
|
4264 |
return s->mcr[1]; |
|
4265 |
case 0x1a: /* MCR1 */ |
|
4266 |
return s->mcr[0]; |
|
4267 |
case 0x1c: /* RCERA */ |
|
4268 |
return s->rcer[0]; |
|
4269 |
case 0x1e: /* RCERB */ |
|
4270 |
return s->rcer[1]; |
|
4271 |
case 0x20: /* XCERA */ |
|
4272 |
return s->xcer[0]; |
|
4273 |
case 0x22: /* XCERB */ |
|
4274 |
return s->xcer[1]; |
|
4275 |
case 0x24: /* PCR0 */ |
|
4276 |
return s->pcr; |
|
4277 |
case 0x26: /* RCERC */ |
|
4278 |
return s->rcer[2]; |
|
4279 |
case 0x28: /* RCERD */ |
|
4280 |
return s->rcer[3]; |
|
4281 |
case 0x2a: /* XCERC */ |
|
4282 |
return s->xcer[2]; |
|
4283 |
case 0x2c: /* XCERD */ |
|
4284 |
return s->xcer[3]; |
|
4285 |
case 0x2e: /* RCERE */ |
|
4286 |
return s->rcer[4]; |
|
4287 |
case 0x30: /* RCERF */ |
|
4288 |
return s->rcer[5]; |
|
4289 |
case 0x32: /* XCERE */ |
|
4290 |
return s->xcer[4]; |
|
4291 |
case 0x34: /* XCERF */ |
|
4292 |
return s->xcer[5]; |
|
4293 |
case 0x36: /* RCERG */ |
|
4294 |
return s->rcer[6]; |
|
4295 |
case 0x38: /* RCERH */ |
|
4296 |
return s->rcer[7]; |
|
4297 |
case 0x3a: /* XCERG */ |
|
4298 |
return s->xcer[6]; |
|
4299 |
case 0x3c: /* XCERH */ |
|
4300 |
return s->xcer[7]; |
|
4301 |
} |
|
4302 |
|
|
4303 |
OMAP_BAD_REG(addr); |
|
4304 |
return 0; |
|
4305 |
} |
|
4306 |
|
|
4307 |
static void omap_mcbsp_write(void *opaque, target_phys_addr_t addr, |
|
4308 |
uint32_t value) |
|
4309 |
{ |
|
4310 |
struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; |
|
4311 |
int offset = addr & OMAP_MPUI_REG_MASK; |
|
4312 |
|
|
4313 |
switch (offset) { |
|
4314 |
case 0x00: /* DRR2 */ |
|
4315 |
case 0x02: /* DRR1 */ |
|
4316 |
OMAP_RO_REG(addr); |
|
4317 |
return; |
|
4318 |
|
|
4319 |
case 0x04: /* DXR2 */ |
|
4320 |
if (((s->xcr[0] >> 5) & 7) < 3) /* XWDLEN1 */ |
|
4321 |
return; |
|
4322 |
/* Fall through. */ |
|
4323 |
case 0x06: /* DXR1 */ |
|
4324 |
if (!s->codec) |
|
4325 |
return; |
|
4326 |
if (s->tx_req) { |
|
4327 |
if (s->codec->out.len > s->codec->out.size - 2) { |
|
4328 |
printf("%s: Tx FIFO overrun\n", __FUNCTION__); |
|
4329 |
omap_mcbsp_tx_stop(s); |
|
4330 |
} else { |
|
4331 |
s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff; |
|
4332 |
s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff; |
|
4333 |
if (s->codec->out.len >= s->codec->out.size) |
|
4334 |
omap_mcbsp_tx_stop(s); |
|
4335 |
} |
|
4336 |
} else |
|
4337 |
printf("%s: Tx FIFO overrun\n", __FUNCTION__); |
|
4338 |
return; |
|
4339 |
|
|
4340 |
case 0x08: /* SPCR2 */ |
|
4341 |
s->spcr[1] &= 0x0002; |
|
4342 |
s->spcr[1] |= 0x03f9 & value; |
|
4343 |
s->spcr[1] |= 0x0004 & (value << 2); /* XEMPTY := XRST */ |
|
4344 |
if (~value & 1) { /* XRST */ |
|
4345 |
s->spcr[1] &= ~6; |
|
4346 |
qemu_irq_lower(s->rxdrq); |
|
4347 |
if (s->codec) |
|
4348 |
s->codec->out.len = 0; |
|
4349 |
} |
|
4350 |
if (s->codec) |
|
4351 |
omap_mcbsp_rate_update(s); |
|
4352 |
omap_mcbsp_req_update(s); |
|
4353 |
return; |
|
4354 |
case 0x0a: /* SPCR1 */ |
|
4355 |
s->spcr[0] &= 0x0006; |
|
4356 |
s->spcr[0] |= 0xf8f9 & value; |
|
4357 |
if (value & (1 << 15)) /* DLB */ |
|
4358 |
printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__); |
|
4359 |
if (~value & 1) { /* RRST */ |
|
4360 |
s->spcr[0] &= ~6; |
|
4361 |
qemu_irq_lower(s->txdrq); |
|
4362 |
if (s->codec) |
|
4363 |
s->codec->in.len = 0; |
|
4364 |
} |
|
4365 |
if (s->codec) |
|
4366 |
omap_mcbsp_rate_update(s); |
|
4367 |
omap_mcbsp_req_update(s); |
|
4368 |
return; |
|
4369 |
|
|
4370 |
case 0x0c: /* RCR2 */ |
|
4371 |
s->rcr[1] = value & 0xffff; |
|
4372 |
return; |
|
4373 |
case 0x0e: /* RCR1 */ |
|
4374 |
s->rcr[0] = value & 0x7fe0; |
|
4375 |
return; |
|
4376 |
case 0x10: /* XCR2 */ |
|
4377 |
s->xcr[1] = value & 0xffff; |
|
4378 |
return; |
|
4379 |
case 0x12: /* XCR1 */ |
|
4380 |
s->xcr[0] = value & 0x7fe0; |
|
4381 |
return; |
|
4382 |
case 0x14: /* SRGR2 */ |
|
4383 |
s->srgr[1] = value & 0xffff; |
|
4384 |
omap_mcbsp_rate_update(s); |
|
4385 |
return; |
|
4386 |
case 0x16: /* SRGR1 */ |
|
4387 |
s->srgr[0] = value & 0xffff; |
|
4388 |
omap_mcbsp_rate_update(s); |
|
4389 |
return; |
|
4390 |
case 0x18: /* MCR2 */ |
|
4391 |
s->mcr[1] = value & 0x03e3; |
|
4392 |
if (value & 3) /* XMCM */ |
|
4393 |
printf("%s: Tx channel selection mode enable attempt\n", |
|
4394 |
__FUNCTION__); |
|
4395 |
return; |
|
4396 |
case 0x1a: /* MCR1 */ |
|
4397 |
s->mcr[0] = value & 0x03e1; |
|
4398 |
if (value & 1) /* RMCM */ |
|
4399 |
printf("%s: Rx channel selection mode enable attempt\n", |
|
4400 |
__FUNCTION__); |
|
4401 |
return; |
|
4402 |
case 0x1c: /* RCERA */ |
|
4403 |
s->rcer[0] = value & 0xffff; |
|
4404 |
return; |
|
4405 |
case 0x1e: /* RCERB */ |
|
4406 |
s->rcer[1] = value & 0xffff; |
|
4407 |
return; |
|
4408 |
case 0x20: /* XCERA */ |
|
4409 |
s->xcer[0] = value & 0xffff; |
|
4410 |
return; |
|
4411 |
case 0x22: /* XCERB */ |
|
4412 |
s->xcer[1] = value & 0xffff; |
|
4413 |
return; |
|
4414 |
case 0x24: /* PCR0 */ |
|
4415 |
s->pcr = value & 0x7faf; |
|
4416 |
return; |
|
4417 |
case 0x26: /* RCERC */ |
|
4418 |
s->rcer[2] = value & 0xffff; |
|
4419 |
return; |
|
4420 |
case 0x28: /* RCERD */ |
|
4421 |
s->rcer[3] = value & 0xffff; |
|
4422 |
return; |
|
4423 |
case 0x2a: /* XCERC */ |
|
4424 |
s->xcer[2] = value & 0xffff; |
|
4425 |
return; |
|
4426 |
case 0x2c: /* XCERD */ |
|
4427 |
s->xcer[3] = value & 0xffff; |
|
4428 |
return; |
|
4429 |
case 0x2e: /* RCERE */ |
|
4430 |
s->rcer[4] = value & 0xffff; |
|
4431 |
return; |
|
4432 |
case 0x30: /* RCERF */ |
|
4433 |
s->rcer[5] = value & 0xffff; |
|
4434 |
return; |
|
4435 |
case 0x32: /* XCERE */ |
|
4436 |
s->xcer[4] = value & 0xffff; |
|
4437 |
return; |
|
4438 |
case 0x34: /* XCERF */ |
|
4439 |
s->xcer[5] = value & 0xffff; |
|
4440 |
return; |
|
4441 |
case 0x36: /* RCERG */ |
|
4442 |
s->rcer[6] = value & 0xffff; |
|
4443 |
return; |
|
4444 |
case 0x38: /* RCERH */ |
|
4445 |
s->rcer[7] = value & 0xffff; |
|
4446 |
return; |
|
4447 |
case 0x3a: /* XCERG */ |
|
4448 |
s->xcer[6] = value & 0xffff; |
|
4449 |
return; |
|
4450 |
case 0x3c: /* XCERH */ |
|
4451 |
s->xcer[7] = value & 0xffff; |
|
4452 |
return; |
|
4453 |
} |
|
4454 |
|
|
4455 |
OMAP_BAD_REG(addr); |
|
4456 |
} |
|
4457 |
|
|
4458 |
static CPUReadMemoryFunc *omap_mcbsp_readfn[] = { |
|
4459 |
omap_badwidth_read16, |
|
4460 |
omap_mcbsp_read, |
|
4461 |
omap_badwidth_read16, |
|
4462 |
}; |
|
4463 |
|
|
4464 |
static CPUWriteMemoryFunc *omap_mcbsp_writefn[] = { |
|
4465 |
omap_badwidth_write16, |
|
4466 |
omap_mcbsp_write, |
|
4467 |
omap_badwidth_write16, |
|
4468 |
}; |
|
4469 |
|
|
4470 |
static void omap_mcbsp_reset(struct omap_mcbsp_s *s) |
|
4471 |
{ |
|
4472 |
memset(&s->spcr, 0, sizeof(s->spcr)); |
|
4473 |
memset(&s->rcr, 0, sizeof(s->rcr)); |
|
4474 |
memset(&s->xcr, 0, sizeof(s->xcr)); |
|
4475 |
s->srgr[0] = 0x0001; |
|
4476 |
s->srgr[1] = 0x2000; |
|
4477 |
memset(&s->mcr, 0, sizeof(s->mcr)); |
|
4478 |
memset(&s->pcr, 0, sizeof(s->pcr)); |
|
4479 |
memset(&s->rcer, 0, sizeof(s->rcer)); |
|
4480 |
memset(&s->xcer, 0, sizeof(s->xcer)); |
|
4481 |
s->tx_req = 0; |
|
4482 |
s->tx_rate = 0; |
|
4483 |
s->rx_rate = 0; |
|
4484 |
} |
|
4485 |
|
|
4486 |
struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base, |
|
4487 |
qemu_irq *irq, qemu_irq *dma, omap_clk clk) |
|
4488 |
{ |
|
4489 |
int iomemtype; |
|
4490 |
struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) |
|
4491 |
qemu_mallocz(sizeof(struct omap_mcbsp_s)); |
|
4492 |
|
|
4493 |
s->base = base; |
|
4494 |
s->txirq = irq[0]; |
|
4495 |
s->rxirq = irq[1]; |
|
4496 |
s->txdrq = dma[0]; |
|
4497 |
s->rxdrq = dma[1]; |
|
4498 |
omap_mcbsp_reset(s); |
|
4499 |
|
|
4500 |
iomemtype = cpu_register_io_memory(0, omap_mcbsp_readfn, |
|
4501 |
omap_mcbsp_writefn, s); |
|
4502 |
cpu_register_physical_memory(s->base, 0x800, iomemtype); |
|
4503 |
|
|
4504 |
return s; |
|
4505 |
} |
|
4506 |
|
|
4507 |
void omap_mcbsp_i2s_swallow(void *opaque, int line, int level) |
|
4508 |
{ |
|
4509 |
struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; |
|
4510 |
|
|
4511 |
omap_mcbsp_rx_start(s); |
|
4512 |
} |
|
4513 |
|
|
4514 |
void omap_mcbsp_i2s_start(void *opaque, int line, int level) |
|
4515 |
{ |
|
4516 |
struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque; |
|
4517 |
|
|
4518 |
omap_mcbsp_tx_start(s); |
|
4519 |
} |
|
4520 |
|
|
4521 |
void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave) |
|
4522 |
{ |
|
4523 |
s->codec = slave; |
|
4524 |
slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0]; |
|
4525 |
slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0]; |
|
4526 |
} |
|
4527 |
|
|
4061 | 4528 |
/* General chip reset */ |
4062 | 4529 |
static void omap_mpu_reset(void *opaque) |
4063 | 4530 |
{ |
... | ... | |
4092 | 4559 |
omap_pwt_reset(mpu); |
4093 | 4560 |
omap_i2c_reset(mpu->i2c); |
4094 | 4561 |
omap_rtc_reset(mpu->rtc); |
4562 |
omap_mcbsp_reset(mpu->mcbsp1); |
|
4563 |
omap_mcbsp_reset(mpu->mcbsp2); |
|
4564 |
omap_mcbsp_reset(mpu->mcbsp3); |
|
4095 | 4565 |
cpu_reset(mpu->env); |
4096 | 4566 |
} |
4097 | 4567 |
|
... | ... | |
4254 | 4724 |
s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX], |
4255 | 4725 |
s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); |
4256 | 4726 |
|
4257 |
omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz"));
|
|
4258 |
omap_pwt_init(0xfffb6000, s, omap_findclk(s, "xtal_osc_12m"));
|
|
4727 |
omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
|
|
4728 |
omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
|
|
4259 | 4729 |
|
4260 | 4730 |
s->i2c = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C], |
4261 | 4731 |
&s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck")); |
... | ... | |
4263 | 4733 |
s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER], |
4264 | 4734 |
omap_findclk(s, "clk32-kHz")); |
4265 | 4735 |
|
4736 |
s->mcbsp1 = omap_mcbsp_init(0xfffb1800, &s->irq[1][OMAP_INT_McBSP1TX], |
|
4737 |
&s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck")); |
|
4738 |
s->mcbsp2 = omap_mcbsp_init(0xfffb1000, &s->irq[0][OMAP_INT_310_McBSP2_TX], |
|
4739 |
&s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck")); |
|
4740 |
s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX], |
|
4741 |
&s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck")); |
|
4742 |
|
|
4266 | 4743 |
/* Register mappings not currenlty implemented: |
4267 |
* McBSP2 Comm fffb1000 - fffb17ff |
|
4268 |
* McBSP1 Audio fffb1800 - fffb1fff (not mapped on OMAP310) |
|
4269 | 4744 |
* MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310) |
4270 | 4745 |
* MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310) |
4271 | 4746 |
* USB W2FC fffb4000 - fffb47ff |
4272 | 4747 |
* Camera Interface fffb6800 - fffb6fff |
4273 |
* McBSP3 fffb7000 - fffb77ff (not mapped on OMAP310) |
|
4274 | 4748 |
* USB Host fffba000 - fffba7ff |
4275 | 4749 |
* FAC fffba800 - fffbafff |
4276 | 4750 |
* HDQ/1-Wire fffbc000 - fffbc7ff |
Also available in: Unified diff