Revision d8f699cb
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 |
b/hw/omap.h | ||
---|---|---|
479 | 479 |
struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base, |
480 | 480 |
qemu_irq *irq, omap_clk clk); |
481 | 481 |
|
482 |
struct i2s_codec_s { |
|
483 |
void *opaque; |
|
484 |
|
|
485 |
/* The CPU can call this if it is generating the clock signal on the |
|
486 |
* i2s port. The CODEC can ignore it if it is set up as a clock |
|
487 |
* master and generates its own clock. */ |
|
488 |
void (*set_rate)(void *opaque, int in, int out); |
|
489 |
|
|
490 |
void (*tx_swallow)(void *opaque); |
|
491 |
qemu_irq rx_swallow; |
|
492 |
qemu_irq tx_start; |
|
493 |
|
|
494 |
struct i2s_fifo_s { |
|
495 |
uint8_t *fifo; |
|
496 |
int len; |
|
497 |
int start; |
|
498 |
int size; |
|
499 |
} in, out; |
|
500 |
}; |
|
501 |
struct omap_mcbsp_s; |
|
502 |
struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base, |
|
503 |
qemu_irq *irq, qemu_irq *dma, omap_clk clk); |
|
504 |
void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, struct i2s_codec_s *slave); |
|
505 |
|
|
482 | 506 |
/* omap_lcdc.c */ |
483 | 507 |
struct omap_lcd_panel_s; |
484 | 508 |
void omap_lcdc_reset(struct omap_lcd_panel_s *s); |
... | ... | |
536 | 560 |
|
537 | 561 |
struct omap_gpio_s *gpio; |
538 | 562 |
|
563 |
struct omap_mcbsp_s *mcbsp1; |
|
564 |
struct omap_mcbsp_s *mcbsp3; |
|
565 |
|
|
539 | 566 |
/* MPU public TIPB peripherals */ |
540 | 567 |
struct omap_32khz_timer_s *os_timer; |
541 | 568 |
|
... | ... | |
563 | 590 |
|
564 | 591 |
struct omap_rtc_s *rtc; |
565 | 592 |
|
593 |
struct omap_mcbsp_s *mcbsp2; |
|
594 |
|
|
566 | 595 |
/* MPU private TIPB peripherals */ |
567 | 596 |
struct omap_intr_handler_s *ih[2]; |
568 | 597 |
|
... | ... | |
646 | 675 |
__FUNCTION__, paddr) |
647 | 676 |
|
648 | 677 |
# define TCMI_VERBOSE 1 |
678 |
//# define MEM_VERBOSE 1 |
|
649 | 679 |
|
650 | 680 |
# ifdef TCMI_VERBOSE |
651 | 681 |
# define OMAP_8B_REG(paddr) \ |
... | ... | |
665 | 695 |
|
666 | 696 |
# define OMAP_MPUI_REG_MASK 0x000007ff |
667 | 697 |
|
698 |
# ifdef MEM_VERBOSE |
|
699 |
struct io_fn { |
|
700 |
CPUReadMemoryFunc **mem_read; |
|
701 |
CPUWriteMemoryFunc **mem_write; |
|
702 |
void *opaque; |
|
703 |
int in; |
|
704 |
}; |
|
705 |
|
|
706 |
static uint32_t io_readb(void *opaque, target_phys_addr_t addr) |
|
707 |
{ |
|
708 |
struct io_fn *s = opaque; |
|
709 |
uint32_t ret; |
|
710 |
|
|
711 |
s->in ++; |
|
712 |
ret = s->mem_read[0](s->opaque, addr); |
|
713 |
s->in --; |
|
714 |
if (!s->in) |
|
715 |
fprintf(stderr, "%08x ---> %02x\n", (uint32_t) addr, ret); |
|
716 |
return ret; |
|
717 |
} |
|
718 |
static uint32_t io_readh(void *opaque, target_phys_addr_t addr) |
|
719 |
{ |
|
720 |
struct io_fn *s = opaque; |
|
721 |
uint32_t ret; |
|
722 |
|
|
723 |
s->in ++; |
|
724 |
ret = s->mem_read[1](s->opaque, addr); |
|
725 |
s->in --; |
|
726 |
if (!s->in) |
|
727 |
fprintf(stderr, "%08x ---> %04x\n", (uint32_t) addr, ret); |
|
728 |
return ret; |
|
729 |
} |
|
730 |
static uint32_t io_readw(void *opaque, target_phys_addr_t addr) |
|
731 |
{ |
|
732 |
struct io_fn *s = opaque; |
|
733 |
uint32_t ret; |
|
734 |
|
|
735 |
s->in ++; |
|
736 |
ret = s->mem_read[2](s->opaque, addr); |
|
737 |
s->in --; |
|
738 |
if (!s->in) |
|
739 |
fprintf(stderr, "%08x ---> %08x\n", (uint32_t) addr, ret); |
|
740 |
return ret; |
|
741 |
} |
|
742 |
static void io_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) |
|
743 |
{ |
|
744 |
struct io_fn *s = opaque; |
|
745 |
|
|
746 |
if (!s->in) |
|
747 |
fprintf(stderr, "%08x <--- %02x\n", (uint32_t) addr, value); |
|
748 |
s->in ++; |
|
749 |
s->mem_write[0](s->opaque, addr, value); |
|
750 |
s->in --; |
|
751 |
} |
|
752 |
static void io_writeh(void *opaque, target_phys_addr_t addr, uint32_t value) |
|
753 |
{ |
|
754 |
struct io_fn *s = opaque; |
|
755 |
|
|
756 |
if (!s->in) |
|
757 |
fprintf(stderr, "%08x <--- %04x\n", (uint32_t) addr, value); |
|
758 |
s->in ++; |
|
759 |
s->mem_write[1](s->opaque, addr, value); |
|
760 |
s->in --; |
|
761 |
} |
|
762 |
static void io_writew(void *opaque, target_phys_addr_t addr, uint32_t value) |
|
763 |
{ |
|
764 |
struct io_fn *s = opaque; |
|
765 |
|
|
766 |
if (!s->in) |
|
767 |
fprintf(stderr, "%08x <--- %08x\n", (uint32_t) addr, value); |
|
768 |
s->in ++; |
|
769 |
s->mem_write[2](s->opaque, addr, value); |
|
770 |
s->in --; |
|
771 |
} |
|
772 |
|
|
773 |
static CPUReadMemoryFunc *io_readfn[] = { io_readb, io_readh, io_readw, }; |
|
774 |
static CPUWriteMemoryFunc *io_writefn[] = { io_writeb, io_writeh, io_writew, }; |
|
775 |
|
|
776 |
inline static int debug_register_io_memory(int io_index, |
|
777 |
CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write, |
|
778 |
void *opaque) |
|
779 |
{ |
|
780 |
struct io_fn *s = qemu_malloc(sizeof(struct io_fn)); |
|
781 |
|
|
782 |
s->mem_read = mem_read; |
|
783 |
s->mem_write = mem_write; |
|
784 |
s->opaque = opaque; |
|
785 |
s->in = 0; |
|
786 |
return cpu_register_io_memory(io_index, io_readfn, io_writefn, s); |
|
787 |
} |
|
788 |
# define cpu_register_io_memory debug_register_io_memory |
|
789 |
# endif |
|
790 |
|
|
668 | 791 |
#endif /* hw_omap_h */ |
b/hw/omap1_clk.c | ||
---|---|---|
307 | 307 |
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, |
308 | 308 |
}; |
309 | 309 |
|
310 |
static struct clk hsab_ck = { |
|
311 |
.name = "hsab_ck", |
|
312 |
.parent = &tc_ck, |
|
313 |
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310, |
|
314 |
}; |
|
315 |
|
|
310 | 316 |
static struct clk rhea1_ck = { |
311 | 317 |
.name = "rhea1_ck", |
312 | 318 |
.parent = &tc_ck, |
... | ... | |
359 | 365 |
static struct clk uart3_1510 = { |
360 | 366 |
.name = "uart3_ck", |
361 | 367 |
/* Direct from ULPD, no real parent */ |
362 |
.parent = &armper_ck,/* either armper_ck or dpll4 */ |
|
368 |
.parent = &armper_ck, /* either armper_ck or dpll4 */
|
|
363 | 369 |
.rate = 12000000, |
364 | 370 |
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP310 | ALWAYS_ENABLED, |
365 | 371 |
}; |
... | ... | |
395 | 401 |
.flags = CLOCK_IN_OMAP16XX, |
396 | 402 |
}; |
397 | 403 |
|
398 |
static struct clk usb_dc_ck = { |
|
399 |
.name = "usb_dc_ck", |
|
400 |
/* Direct from ULPD, no parent */ |
|
404 |
static struct clk usb_w2fc_mclk = { |
|
405 |
.name = "usb_w2fc_mclk", |
|
406 |
.alias = "usb_w2fc_ck", |
|
407 |
.parent = &ck_48m, |
|
401 | 408 |
.rate = 48000000, |
402 |
.flags = CLOCK_IN_OMAP16XX, |
|
409 |
.flags = CLOCK_IN_OMAP310 | CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX,
|
|
403 | 410 |
}; |
404 | 411 |
|
405 | 412 |
static struct clk mclk_1510 = { |
... | ... | |
539 | 546 |
&api_ck, |
540 | 547 |
&lb_ck, |
541 | 548 |
&lbfree_ck, |
549 |
&hsab_ck, |
|
542 | 550 |
&rhea1_ck, |
543 | 551 |
&rhea2_ck, |
544 | 552 |
&lcd_ck_16xx, |
... | ... | |
551 | 559 |
&uart3_16xx, |
552 | 560 |
&usb_clk0, |
553 | 561 |
&usb_hhc_ck1510, &usb_hhc_ck16xx, |
554 |
&usb_dc_ck, |
|
555 | 562 |
&mclk_1510, &mclk_16xx, &mclk_310, |
556 | 563 |
&bclk_1510, &bclk_16xx, &bclk_310, |
557 | 564 |
&mmc1_ck, |
... | ... | |
560 | 567 |
&cam_exclk, |
561 | 568 |
&cam_lclk, |
562 | 569 |
&clk32k, |
570 |
&usb_w2fc_mclk, |
|
563 | 571 |
/* Virtual clocks */ |
564 | 572 |
&i2c_fck, |
565 | 573 |
&i2c_ick, |
b/hw/palm.c | ||
---|---|---|
78 | 78 |
|
79 | 79 |
static void palmte_microwire_setup(struct omap_mpu_state_s *cpu) |
80 | 80 |
{ |
81 |
omap_uwire_attach( |
|
82 |
cpu->microwire, |
|
83 |
tsc2102_init( |
|
84 |
omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO]), |
|
85 |
0); |
|
81 |
struct uwire_slave_s *tsc; |
|
82 |
AudioState *audio = 0; |
|
83 |
|
|
84 |
#ifdef HAS_AUDIO |
|
85 |
audio = AUD_init(); |
|
86 |
#endif |
|
87 |
|
|
88 |
tsc = tsc2102_init(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO], |
|
89 |
audio); |
|
90 |
|
|
91 |
omap_uwire_attach(cpu->microwire, tsc, 0); |
|
92 |
omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc)); |
|
86 | 93 |
} |
87 | 94 |
|
88 | 95 |
static struct { |
b/hw/tsc210x.c | ||
---|---|---|
32 | 32 |
struct tsc210x_state_s { |
33 | 33 |
qemu_irq pint; |
34 | 34 |
QEMUTimer *timer; |
35 |
QEMUSoundCard card; |
|
35 | 36 |
struct uwire_slave_s chip; |
37 |
struct i2s_codec_s codec; |
|
38 |
uint8_t in_fifo[16384]; |
|
39 |
uint8_t out_fifo[16384]; |
|
36 | 40 |
|
37 | 41 |
int x, y; |
38 | 42 |
int pressure; |
... | ... | |
63 | 67 |
uint16_t dac_power; |
64 | 68 |
int64_t powerdown; |
65 | 69 |
uint16_t filter_data[0x14]; |
70 |
|
|
71 |
const char *name; |
|
72 |
SWVoiceIn *adc_voice[1]; |
|
73 |
SWVoiceOut *dac_voice[1]; |
|
74 |
int i2s_rx_rate; |
|
75 |
int i2s_tx_rate; |
|
76 |
AudioState *audio; |
|
66 | 77 |
}; |
67 | 78 |
|
68 | 79 |
static const int resolution[4] = { 12, 8, 10, 12 }; |
... | ... | |
171 | 182 |
s->filter_data[0x12] = 0x7d83; |
172 | 183 |
s->filter_data[0x13] = 0x84ee; |
173 | 184 |
|
185 |
s->i2s_tx_rate = 0; |
|
186 |
s->i2s_rx_rate = 0; |
|
187 |
|
|
174 | 188 |
qemu_set_irq(s->pint, !s->irq); |
175 | 189 |
} |
176 | 190 |
|
191 |
struct tsc210x_rate_info_s { |
|
192 |
int rate; |
|
193 |
int dsor; |
|
194 |
int fsref; |
|
195 |
}; |
|
196 |
|
|
197 |
/* { rate, dsor, fsref } */ |
|
198 |
static const struct tsc210x_rate_info_s tsc2101_rates[] = { |
|
199 |
/* Fsref / 6.0 */ |
|
200 |
{ 7350, 7, 1 }, |
|
201 |
{ 8000, 7, 0 }, |
|
202 |
/* Fsref / 5.5 */ |
|
203 |
{ 8018, 6, 1 }, |
|
204 |
{ 8727, 6, 0 }, |
|
205 |
/* Fsref / 5.0 */ |
|
206 |
{ 8820, 5, 1 }, |
|
207 |
{ 9600, 5, 0 }, |
|
208 |
/* Fsref / 4.0 */ |
|
209 |
{ 11025, 4, 1 }, |
|
210 |
{ 12000, 4, 0 }, |
|
211 |
/* Fsref / 3.0 */ |
|
212 |
{ 14700, 3, 1 }, |
|
213 |
{ 16000, 3, 0 }, |
|
214 |
/* Fsref / 2.0 */ |
|
215 |
{ 22050, 2, 1 }, |
|
216 |
{ 24000, 2, 0 }, |
|
217 |
/* Fsref / 1.5 */ |
|
218 |
{ 29400, 1, 1 }, |
|
219 |
{ 32000, 1, 0 }, |
|
220 |
/* Fsref */ |
|
221 |
{ 44100, 0, 1 }, |
|
222 |
{ 48000, 0, 0 }, |
|
223 |
|
|
224 |
{ 0, 0, 0 }, |
|
225 |
}; |
|
226 |
|
|
227 |
/* { rate, dsor, fsref } */ |
|
228 |
static const struct tsc210x_rate_info_s tsc2102_rates[] = { |
|
229 |
/* Fsref / 6.0 */ |
|
230 |
{ 7350, 63, 1 }, |
|
231 |
{ 8000, 63, 0 }, |
|
232 |
/* Fsref / 6.0 */ |
|
233 |
{ 7350, 54, 1 }, |
|
234 |
{ 8000, 54, 0 }, |
|
235 |
/* Fsref / 5.0 */ |
|
236 |
{ 8820, 45, 1 }, |
|
237 |
{ 9600, 45, 0 }, |
|
238 |
/* Fsref / 4.0 */ |
|
239 |
{ 11025, 36, 1 }, |
|
240 |
{ 12000, 36, 0 }, |
|
241 |
/* Fsref / 3.0 */ |
|
242 |
{ 14700, 27, 1 }, |
|
243 |
{ 16000, 27, 0 }, |
|
244 |
/* Fsref / 2.0 */ |
|
245 |
{ 22050, 18, 1 }, |
|
246 |
{ 24000, 18, 0 }, |
|
247 |
/* Fsref / 1.5 */ |
|
248 |
{ 29400, 9, 1 }, |
|
249 |
{ 32000, 9, 0 }, |
|
250 |
/* Fsref */ |
|
251 |
{ 44100, 0, 1 }, |
|
252 |
{ 48000, 0, 0 }, |
|
253 |
|
|
254 |
{ 0, 0, 0 }, |
|
255 |
}; |
|
256 |
|
|
257 |
static inline void tsc210x_out_flush(struct tsc210x_state_s *s, int len) |
|
258 |
{ |
|
259 |
uint8_t *data = s->codec.out.fifo + s->codec.out.start; |
|
260 |
uint8_t *end = data + len; |
|
261 |
|
|
262 |
while (data < end) |
|
263 |
data += AUD_write(s->dac_voice[0], data, end - data) ?: (end - data); |
|
264 |
|
|
265 |
s->codec.out.len -= len; |
|
266 |
if (s->codec.out.len) |
|
267 |
memmove(s->codec.out.fifo, end, s->codec.out.len); |
|
268 |
s->codec.out.start = 0; |
|
269 |
} |
|
270 |
|
|
271 |
static void tsc210x_audio_out_cb(struct tsc210x_state_s *s, int free_b) |
|
272 |
{ |
|
273 |
if (s->codec.out.len >= free_b) { |
|
274 |
tsc210x_out_flush(s, free_b); |
|
275 |
return; |
|
276 |
} |
|
277 |
|
|
278 |
s->codec.out.size = MIN(free_b, 16384); |
|
279 |
qemu_irq_raise(s->codec.tx_start); |
|
280 |
} |
|
281 |
|
|
282 |
static void tsc2102_audio_set_format(struct tsc210x_state_s *s) |
|
283 |
{ |
|
284 |
int enable; |
|
285 |
const struct tsc210x_rate_info_s *rate; |
|
286 |
audsettings_t fmt; |
|
287 |
|
|
288 |
if (s->dac_voice[0]) { |
|
289 |
tsc210x_out_flush(s, s->codec.out.len); |
|
290 |
s->codec.out.size = 0; |
|
291 |
AUD_set_active_out(s->dac_voice[0], 0); |
|
292 |
AUD_close_out(&s->card, s->dac_voice[0]); |
|
293 |
s->dac_voice[0] = 0; |
|
294 |
} |
|
295 |
|
|
296 |
enable = |
|
297 |
(~s->dac_power & (1 << 15)) && /* PWDNC */ |
|
298 |
(~s->dac_power & (1 << 10)); /* DAPWDN */ |
|
299 |
if (!enable) |
|
300 |
return; |
|
301 |
|
|
302 |
for (rate = tsc2102_rates; rate->rate; rate ++) |
|
303 |
if (rate->dsor == (s->audio_ctrl1 & 0x3f) && /* DACFS */ |
|
304 |
rate->fsref == ((s->audio_ctrl3 >> 13) & 1))/* REFFS */ |
|
305 |
break; |
|
306 |
if (!rate->rate) { |
|
307 |
printf("%s: unknown sampling rate configured\n", __FUNCTION__); |
|
308 |
return; |
|
309 |
} |
|
310 |
|
|
311 |
/* Force our own sampling rate even in slave DAC mode */ |
|
312 |
fmt.endianness = 0; |
|
313 |
fmt.nchannels = 2; |
|
314 |
fmt.freq = rate->rate; |
|
315 |
fmt.fmt = AUD_FMT_S16; |
|
316 |
|
|
317 |
s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0], |
|
318 |
"tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt); |
|
319 |
if (s->dac_voice[0]) |
|
320 |
AUD_set_active_out(s->dac_voice[0], 1); |
|
321 |
} |
|
322 |
|
|
177 | 323 |
static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg) |
178 | 324 |
{ |
179 | 325 |
switch (reg) { |
... | ... | |
437 | 583 |
fprintf(stderr, "tsc2102_audio_register_write: " |
438 | 584 |
"wrong value written into Audio 1\n"); |
439 | 585 |
#endif |
586 |
if (s->audio) |
|
587 |
tsc2102_audio_set_format(s); |
|
440 | 588 |
return; |
441 | 589 |
|
442 | 590 |
case 0x01: |
... | ... | |
479 | 627 |
fprintf(stderr, "tsc2102_audio_register_write: " |
480 | 628 |
"wrong value written into Power\n"); |
481 | 629 |
#endif |
630 |
if (s->audio) |
|
631 |
tsc2102_audio_set_format(s); |
|
482 | 632 |
return; |
483 | 633 |
|
484 | 634 |
case 0x06: /* Audio Control 3 */ |
... | ... | |
489 | 639 |
fprintf(stderr, "tsc2102_audio_register_write: " |
490 | 640 |
"wrong value written into Audio 3\n"); |
491 | 641 |
#endif |
642 |
if (s->audio) |
|
643 |
tsc2102_audio_set_format(s); |
|
492 | 644 |
return; |
493 | 645 |
|
494 | 646 |
case 0x07: /* LCH_BASS_BOOST_N0 */ |
... | ... | |
718 | 870 |
tsc210x_pin_update(s); |
719 | 871 |
} |
720 | 872 |
|
873 |
static void tsc210x_i2s_swallow(struct tsc210x_state_s *s) |
|
874 |
{ |
|
875 |
if (s->dac_voice[0]) |
|
876 |
tsc210x_out_flush(s, s->codec.out.len); |
|
877 |
else |
|
878 |
s->codec.out.len = 0; |
|
879 |
} |
|
880 |
|
|
881 |
static void tsc210x_i2s_set_rate(struct tsc210x_state_s *s, int in, int out) |
|
882 |
{ |
|
883 |
s->i2s_tx_rate = out; |
|
884 |
s->i2s_rx_rate = in; |
|
885 |
} |
|
886 |
|
|
721 | 887 |
static void tsc210x_save(QEMUFile *f, void *opaque) |
722 | 888 |
{ |
723 | 889 |
struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque; |
... | ... | |
817 | 983 |
|
818 | 984 |
static int tsc2102_iid = 0; |
819 | 985 |
|
820 |
struct uwire_slave_s *tsc2102_init(qemu_irq pint) |
|
986 |
struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio)
|
|
821 | 987 |
{ |
822 | 988 |
struct tsc210x_state_s *s; |
823 | 989 |
|
... | ... | |
830 | 996 |
s->precision = s->nextprecision = 0; |
831 | 997 |
s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s); |
832 | 998 |
s->pint = pint; |
999 |
s->name = "tsc2102"; |
|
1000 |
s->audio = audio; |
|
833 | 1001 |
|
834 | 1002 |
s->chip.opaque = s; |
835 | 1003 |
s->chip.send = (void *) tsc210x_write; |
836 | 1004 |
s->chip.receive = (void *) tsc210x_read; |
837 | 1005 |
|
1006 |
s->codec.opaque = s; |
|
1007 |
s->codec.tx_swallow = (void *) tsc210x_i2s_swallow; |
|
1008 |
s->codec.set_rate = (void *) tsc210x_i2s_set_rate; |
|
1009 |
s->codec.in.fifo = s->in_fifo; |
|
1010 |
s->codec.out.fifo = s->out_fifo; |
|
1011 |
|
|
838 | 1012 |
tsc210x_reset(s); |
839 | 1013 |
|
840 | 1014 |
qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1, |
841 | 1015 |
"QEMU TSC2102-driven Touchscreen"); |
842 | 1016 |
|
1017 |
if (s->audio) |
|
1018 |
AUD_register_card(s->audio, s->name, &s->card); |
|
1019 |
|
|
843 | 1020 |
qemu_register_reset((void *) tsc210x_reset, s); |
844 |
register_savevm("tsc2102", tsc2102_iid ++, 0,
|
|
1021 |
register_savevm(s->name, tsc2102_iid ++, 0,
|
|
845 | 1022 |
tsc210x_save, tsc210x_load, s); |
846 | 1023 |
|
847 | 1024 |
return &s->chip; |
848 | 1025 |
} |
1026 |
|
|
1027 |
struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip) |
|
1028 |
{ |
|
1029 |
struct tsc210x_state_s *s = (struct tsc210x_state_s *) chip->opaque; |
|
1030 |
|
|
1031 |
return &s->codec; |
|
1032 |
} |
b/vl.h | ||
---|---|---|
1667 | 1667 |
#include "hw/omap.h" |
1668 | 1668 |
|
1669 | 1669 |
/* tsc210x.c */ |
1670 |
struct uwire_slave_s *tsc2102_init(qemu_irq pint); |
|
1670 |
struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio); |
|
1671 |
struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip); |
|
1671 | 1672 |
|
1672 | 1673 |
/* mcf_uart.c */ |
1673 | 1674 |
uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr); |
Also available in: Unified diff