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