Commit f938f6b60c85e2a06bbfdadcff21df2192c2b1da

Authored by Evgeniy Dushistov
1 parent 34f64942

fix spi: add interrupt support, increase size, so

linux can boot now
hw/at91.h
... ... @@ -39,7 +39,19 @@ typedef int (*pdc_start_transfer_t)(void *opaque,
39 39 unsigned int rx_len,
40 40 int last_transfer);
41 41  
42   -PDCState *at91_pdc_init(void *opaque, pdc_start_transfer_t start_transfer);
  42 +#define PDCF_ENDRX 1
  43 +#define PDCF_ENDTX 2
  44 +#define PDCF_RXFULL 4
  45 +#define PDCF_TXFULL 8
  46 +#define PDCF_NOT_ENDRX 16
  47 +#define PDCF_NOT_RXFULL 32
  48 +#define PDCF_NOT_ENDTX 64
  49 +#define PDCF_NOT_TXFULL 128
  50 +
  51 +typedef void (*pdc_state_changed_t)(void *opaque, unsigned int state);
  52 +
  53 +PDCState *at91_pdc_init(void *opaque, pdc_start_transfer_t start_transfer,
  54 + pdc_state_changed_t state_changed);
43 55 extern void at91_pdc_reset(PDCState *s);
44 56 extern void at91_pdc_write(void *opaque, target_phys_addr_t offset, uint32_t val);
45 57 extern uint32_t at91_pdc_read(void *opaque, target_phys_addr_t offset);
... ...
hw/at91_pdc.c
... ... @@ -46,15 +46,18 @@ struct PDCState {
46 46 uint16_t tncr;
47 47 void *opaque;
48 48 pdc_start_transfer_t start_transfer;
  49 + pdc_state_changed_t state_changed;
49 50 };
50 51  
51   -PDCState *at91_pdc_init(void *opaque, pdc_start_transfer_t start_transfer)
  52 +PDCState *at91_pdc_init(void *opaque, pdc_start_transfer_t start_transfer,
  53 + pdc_state_changed_t state_changed)
52 54 {
53 55 PDCState *s;
54 56  
55 57 s = qemu_mallocz(sizeof(PDCState));
56 58 s->opaque = opaque;
57 59 s->start_transfer = start_transfer;
  60 + s->state_changed = state_changed;
58 61 return s;
59 62 }
60 63  
... ... @@ -62,6 +65,7 @@ void at91_pdc_write(void *opaque, target_phys_addr_t offset, uint32_t val)
62 65 {
63 66 PDCState *s = opaque;
64 67 int last_transfer = 1;
  68 + unsigned int state = 0;
65 69  
66 70 switch (offset) {
67 71 case PDC_PTCR:
... ... @@ -71,25 +75,15 @@ void at91_pdc_write(void *opaque, target_phys_addr_t offset, uint32_t val)
71 75 s->ptsr & PDC_PTCR_RXTEN ? "enable recieve" : "<>",
72 76 s->ptsr & PDC_PTCR_TXTEN ? "enable transfer" : "<>");
73 77  
74   - if (val & PDC_PTCR_RXTEN) {
75   - s->ptsr |= PDC_PTCR_RXTEN;
76   - }
77   -
78   - if (val & PDC_PTCR_RXTDIS) {
79   - s->ptsr &= ~PDC_PTCR_RXTEN;
80   - }
  78 + s->ptsr |= (val & PDC_PTCR_RXTEN) ? PDC_PTCR_RXTEN : 0;
  79 + s->ptsr &= ~((val & PDC_PTCR_RXTDIS) ? PDC_PTCR_RXTEN : 0);
81 80  
82 81 if (s->ptsr & PDC_PTCR_RXTEN) {
83 82 last_transfer = s->rncr == 0;
84 83 }
85 84  
86   - if (val & PDC_PTCR_TXTEN) {
87   - s->ptsr |= PDC_PTCR_TXTEN;
88   - }
89   -
90   - if (val & PDC_PTCR_TXTDIS) {
91   - s->ptsr &= ~PDC_PTCR_TXTEN;
92   - }
  85 + s->ptsr |= (val & PDC_PTCR_TXTEN) ? PDC_PTCR_TXTEN : 0;
  86 + s->ptsr &= ~((val & PDC_PTCR_TXTDIS) ? PDC_PTCR_TXTEN : 0);
93 87  
94 88 if (s->ptsr & PDC_PTCR_TXTEN) {
95 89 last_transfer |= s->tncr == 0;
... ... @@ -103,9 +97,15 @@ void at91_pdc_write(void *opaque, target_phys_addr_t offset, uint32_t val)
103 97  
104 98 if (ret == 0) {
105 99 if (s->ptsr & PDC_PTCR_RXTEN) {
  100 + if (s->rcr) {
  101 + state |= PDCF_ENDRX;
  102 + }
106 103 s->rcr = 0;
107 104 }
108 105 if (s->ptsr & PDC_PTCR_TXTEN) {
  106 + if (s->tcr) {
  107 + state |= PDCF_ENDTX;
  108 + }
109 109 s->tcr = 0;
110 110 }
111 111  
... ... @@ -136,7 +136,15 @@ void at91_pdc_write(void *opaque, target_phys_addr_t offset, uint32_t val)
136 136 }
137 137 }
138 138 }
139   -
  139 + if (s->rcr == 0 && s->rncr == 0) {
  140 + state |= PDCF_RXFULL;
  141 + }
  142 + if (s->tcr == 0 && s->tncr == 0) {
  143 + state |= PDCF_TXFULL;
  144 + }
  145 + if (state != 0) {
  146 + s->state_changed(s->opaque, state);
  147 + }
140 148 break;
141 149 case PDC_RPR:
142 150 s->rpr = val;
... ... @@ -146,21 +154,33 @@ void at91_pdc_write(void *opaque, target_phys_addr_t offset, uint32_t val)
146 154 break;
147 155 case PDC_RCR:
148 156 s->rcr = val;
  157 + if (s->rcr != 0) {
  158 + s->state_changed(s->opaque, PDCF_NOT_ENDRX | PDCF_NOT_RXFULL);
  159 + }
149 160 break;
150 161 case PDC_TCR:
151 162 s->tcr = val;
  163 + if (s->tcr != 0) {
  164 + s->state_changed(s->opaque, PDCF_NOT_ENDTX | PDCF_NOT_TXFULL);
  165 + }
152 166 break;
153 167 case PDC_RNPR:
154 168 s->rnpr = val;
155 169 break;
156 170 case PDC_RNCR:
157 171 s->rncr = val;
  172 + if (s->rncr != 0) {
  173 + s->state_changed(s->opaque, PDCF_NOT_RXFULL);
  174 + }
158 175 break;
159 176 case PDC_TNPR:
160 177 s->tnpr = val;
161 178 break;
162 179 case PDC_TNCR:
163 180 s->tncr = val;
  181 + if (s->tncr != 0) {
  182 + s->state_changed(s->opaque, PDCF_NOT_TXFULL);
  183 + }
164 184 break;
165 185 default:
166 186 DPRINTF("ignore write of %X to %X\n", val, offset);
... ...
hw/at91_spi.c
... ... @@ -84,6 +84,8 @@ static uint32_t at91_spi_mem_read(void *opaque, target_phys_addr_t offset)
84 84 return s->sr;
85 85 case SPI_RDR:
86 86 return s->rdr;
  87 + case SPI_IMR:
  88 + return s->imr;
87 89 case SPI_CSR0 ... SPI_CSR3:
88 90 return s->csr[(offset - SPI_CSR0) / sizeof(s->csr[0])];
89 91 case 0x100 ... 0x124:
... ... @@ -109,6 +111,12 @@ static void at91_spi_mem_write(void *opaque, target_phys_addr_t offset,
109 111 if (value & SPI_CR_SPIDIS)
110 112 s->sr &= ~SPI_SR_SPIENS;
111 113 break;
  114 + case SPI_IER:
  115 + s->imr |= value;
  116 + break;
  117 + case SPI_IDR:
  118 + s->imr &= ~value;
  119 + break;
112 120 case SPI_MR:
113 121 s->mr = value;
114 122 break;
... ... @@ -137,6 +145,24 @@ static CPUWriteMemoryFunc *at91_spi_writefn[] = {
137 145 at91_spi_mem_write,
138 146 };
139 147  
  148 +static void pdc_state_changed(void *opaque, unsigned int state)
  149 +{
  150 + SPIState *s = opaque;
  151 +
  152 + s->sr |= (state & PDCF_ENDRX) ? SPI_SR_ENDRX : 0;
  153 + s->sr &= ~((state & PDCF_NOT_ENDRX) ? SPI_SR_ENDRX : 0);
  154 + s->sr |= (state & PDCF_ENDTX) ? SPI_SR_ENDTX : 0;
  155 + s->sr &= ~((state & PDCF_NOT_ENDTX) ? SPI_SR_ENDTX : 0);
  156 +
  157 + s->sr |= (state & PDCF_RXFULL) ? SPI_SR_RXBUFF : 0;
  158 + s->sr &= ~((state & PDCF_NOT_RXFULL) ? SPI_SR_RXBUFF : 0);
  159 +
  160 + s->sr |= (state & PDCF_TXFULL) ? SPI_SR_TXBUFE : 0;
  161 + s->sr &= ~((state & PDCF_NOT_TXFULL) ? SPI_SR_TXBUFE : 0);
  162 +
  163 + qemu_set_irq(s->irq, !!(s->sr & s->imr));
  164 +}
  165 +
140 166 static int pdc_start_transfer(void *opaque,
141 167 target_phys_addr_t tx,
142 168 unsigned int tx_len,
... ... @@ -176,14 +202,23 @@ static int pdc_start_transfer(void *opaque,
176 202 --rx_len;
177 203 }
178 204 }
  205 +#if 0
179 206 if (flags & 1) {//tx
180   - s->sr |= SPI_SR_ENDTX | SPI_SR_TXBUFE;
  207 + s->sr |= SPI_SR_ENDTX;
  208 + if (last_transfer) {
  209 + s->sr |= SPI_SR_TXBUFE;
  210 + }
181 211 }
182 212 if (flags & 2) {//rx
183   - s->sr |= SPI_SR_RXBUFF | SPI_SR_ENDRX;
  213 + s->sr |= SPI_SR_ENDRX;
  214 + if (last_transfer) {
  215 + s->sr |= SPI_SR_RXBUFF;
  216 + }
184 217 }
185   - if (last_transfer)
  218 +#endif
  219 + if (last_transfer) {
186 220 s->spi_control->set_chipselect(s->spi_control->opaque, 0);
  221 + }
187 222 return 0;
188 223 }
189 224  
... ... @@ -193,7 +228,7 @@ static void at91_spi_reset(void *opaque)
193 228  
194 229 s->mr = 0;
195 230 s->rdr = 0;
196   - s->sr = 0xf0;
  231 + s->sr = SPI_SR_ENDRX | SPI_SR_ENDTX | SPI_SR_RXBUFF | SPI_SR_TXBUFE;
197 232 s->imr = 0;
198 233 memset(s->csr, 0, sizeof(s->csr));
199 234 at91_pdc_reset(s->pdc_state);
... ... @@ -204,7 +239,7 @@ static void at91_spi_init(SysBusDevice *dev)
204 239 SPIState *s = FROM_SYSBUS(typeof(*s), dev);
205 240 int spi_regs;
206 241  
207   - s->pdc_state = at91_pdc_init(s, pdc_start_transfer);
  242 + s->pdc_state = at91_pdc_init(s, pdc_start_transfer, pdc_state_changed);
208 243 sysbus_init_irq(dev, &s->irq);
209 244 spi_regs = cpu_register_io_memory(at91_spi_readfn, at91_spi_writefn, s);
210 245 sysbus_init_mmio(dev, SPI_SIZE, spi_regs);
... ...
hw/at91sam9.c
... ... @@ -344,7 +344,7 @@ static void at91sam9_init(ram_addr_t ram_size,
344 344 dinfo = drive_get(IF_PFLASH, 0, 0);
345 345 if (dinfo) {
346 346 if (bms) {
347   - if (spi_flash_register(dinfo->bdrv, 2 * 1024 * 1024, cs0_spi_handler) < 0) {
  347 + if (spi_flash_register(dinfo->bdrv, 4 * 1024 * 1024, cs0_spi_handler) < 0) {
348 348 fprintf(stderr, "init of spi flash failed\n");
349 349 exit(EXIT_FAILURE);
350 350 }
... ...
hw/spi_flash.c
... ... @@ -12,7 +12,7 @@ typedef struct SPIFlash {
12 12 BlockDriverState *bs;
13 13 } SPIFlash;
14 14  
15   -#define AT91_SPI_FLASH_DEBUG
  15 +//#define AT91_SPI_FLASH_DEBUG
16 16 #ifdef AT91_SPI_FLASH_DEBUG
17 17 #define DPRINTF(fmt, ...) \
18 18 do { \
... ... @@ -67,7 +67,8 @@ static uint32_t spi_flash_txrx(void *opaque, uint32_t val, int len)
67 67 case 0xD7:
68 68 spi_flash_reset_state(s);
69 69 DPRINTF("return id\n");
70   - return (1 << 2) | (1 << 3) | (1 << 5) | (1 << 7);
  70 + return /*(1 << 2) | (1 << 3) | (1 << 5) | (1 << 7) AT45.*16*/
  71 + (1 << 2) | (1 << 4) | (1 << 5) | (1 << 7);
71 72 default:
72 73 DPRINTF("Unknown cmd\n");
73 74 return 0;
... ...