Commit 5eb9fc83f2a2badaa8389539f789e9e660c3816a

Authored by Evgeniy Dushistov
1 parent 0c250455

spi flash and at91_spi plus at91_pdc initial implementation

Makefile.target
... ... @@ -411,7 +411,7 @@ obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
411 411 endif
412 412  
413 413 obj-arm-y = integratorcp.o versatilepb.o smc91c111.o arm_pic.o arm_timer.o
414   -obj-arm-y += pflash_atmel.o at91sam9.o
  414 +obj-arm-y += pflash_atmel.o at91sam9.o spi_flash.o
415 415 obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
416 416 obj-arm-y += versatile_pci.o
417 417 obj-arm-y += realview_gic.o realview.o arm_sysctl.o mpcore.o
... ... @@ -433,7 +433,7 @@ obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
433 433 obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
434 434 obj-arm-y += syborg_virtio.o
435 435 obj-arm-y += at91_aic.o at91_dbgu.o at91_pio.o at91_pit.o at91_pmc.o at91_rtt.o
436   -obj-arm-y += at91_rstc.o at91_intor.o at91_tc.o at91_emac.o at91pes.o
  436 +obj-arm-y += at91_rstc.o at91_intor.o at91_tc.o at91_emac.o at91_spi.o at91_pdc.o at91pes.o
437 437 obj-arm-y += gpio_rotary.o gpio_keypad.o hd44780.o
438 438  
439 439 ifeq ($(TARGET_BASE_ARCH), arm)
... ...
hw/at91.h
... ... @@ -29,4 +29,19 @@
29 29 Controller. */
30 30 extern int at91_master_clock_frequency;
31 31  
  32 +typedef uint32_t (*spi_txrx_callback_fun_t)(void *opaque, uint32_t cmd, int len);
  33 +
  34 +typedef struct PDCState PDCState;
  35 +typedef int (*pdc_start_transfer_t)(void *opaque,
  36 + target_phys_addr_t tx,
  37 + unsigned int tx_len,
  38 + target_phys_addr_t rx,
  39 + unsigned int rx_len,
  40 + int last_transfer);
  41 +
  42 +PDCState *at91_pdc_init(void *opaque, pdc_start_transfer_t start_transfer);
  43 +extern void at91_pdc_reset(PDCState *s);
  44 +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);
  46 +
32 47 #endif /* !AT91_H */
... ...
hw/at91_pdc.c 0 → 100644
  1 +/*
  2 + * AT91 Peripheral DMA Controller (PDC) User Interface
  3 + * Written by Evgeniy Dushistov
  4 + * This code is licenced under the GPL.
  5 + */
  6 +#include <stdint.h>
  7 +#include "sysbus.h"
  8 +#include "at91.h"
  9 +
  10 +
  11 +#define PDC_RPR 0x100 //Receive Pointer Register Read/Write 0
  12 +#define PDC_RCR 0x104 //Receive Counter Register PDC_RCR Read/Write 0
  13 +#define PDC_TPR 0x108 //Transmit Pointer Register PDC_TPR Read/Write 0
  14 +#define PDC_TCR 0x10C //Transmit Counter Register PDC_TCR Read/Write 0
  15 +#define PDC_RNPR 0x110 //Receive Next Pointer Register PDC_RNPR Read/Write 0
  16 +#define PDC_RNCR 0x114 //Receive Next Counter Register PDC_RNCR Read/Write 0
  17 +#define PDC_TNPR 0x118 //Transmit Next Pointer Register PDC_TNPR Read/Write 0
  18 +#define PDC_TNCR 0x11C //Transmit Next Counter Register PDC_TNCR Read/Write 0
  19 +#define PDC_PTCR 0x120 //Transfer Control Register PDC_PTCR Write 0
  20 +#define PDC_PTSR 0x124 //Transfer Status Register PDC_PTSR Read 0
  21 +
  22 +#define PDC_PTCR_RXTEN (1 << 0)
  23 +#define PDC_PTCR_RXTDIS (1 << 1)
  24 +#define PDC_PTCR_TXTEN (1 << 8)
  25 +#define PDC_PTCR_TXTDIS (1 << 9)
  26 +
  27 +#define AT91_PDC_DEBUG
  28 +#ifdef AT91_PDC_DEBUG
  29 +#define DPRINTF(fmt, ...) \
  30 + do { \
  31 + printf("AT91PDC: " fmt , ## __VA_ARGS__); \
  32 + } while (0)
  33 +#else
  34 +#define DPRINTF(fmt, ...) do { } while (0)
  35 +#endif
  36 +
  37 +struct PDCState {
  38 + uint32_t ptsr;
  39 + uint32_t rpr;
  40 + uint32_t tpr;
  41 + uint16_t rcr;
  42 + uint16_t tcr;
  43 + uint32_t rnpr;
  44 + uint32_t tnpr;
  45 + uint16_t rncr;
  46 + uint16_t tncr;
  47 + void *opaque;
  48 + pdc_start_transfer_t start_transfer;
  49 +};
  50 +
  51 +PDCState *at91_pdc_init(void *opaque, pdc_start_transfer_t start_transfer)
  52 +{
  53 + PDCState *s;
  54 +
  55 + s = qemu_mallocz(sizeof(PDCState));
  56 + s->opaque = opaque;
  57 + s->start_transfer = start_transfer;
  58 + return s;
  59 +}
  60 +
  61 +void at91_pdc_write(void *opaque, target_phys_addr_t offset, uint32_t val)
  62 +{
  63 + PDCState *s = opaque;
  64 + int last_transfer = 1;
  65 +
  66 + switch (offset) {
  67 + case PDC_PTCR:
  68 + DPRINTF("%s, %s was (%s, %s)\n",
  69 + val & PDC_PTCR_RXTEN ? "enable recieve" : "<>",
  70 + val & PDC_PTCR_TXTEN ? "enable transfer" : "<>",
  71 + s->ptsr & PDC_PTCR_RXTEN ? "enable recieve" : "<>",
  72 + s->ptsr & PDC_PTCR_TXTEN ? "enable transfer" : "<>");
  73 +
  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 + }
  81 +
  82 + if (s->ptsr & PDC_PTCR_RXTEN) {
  83 + last_transfer = s->rncr == 0;
  84 + }
  85 +
  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 + }
  93 +
  94 + if (s->ptsr & PDC_PTCR_TXTEN) {
  95 + last_transfer |= s->tncr == 0;
  96 + }
  97 +
  98 + if ((s->ptsr & PDC_PTCR_RXTEN) || (s->ptsr & PDC_PTCR_TXTEN)) {
  99 + int ret = s->start_transfer(s->opaque, s->tpr,
  100 + (s->ptsr & PDC_PTCR_TXTEN) ? s->tcr : 0,
  101 + s->rpr, (s->ptsr & PDC_PTCR_RXTEN) ? s->rcr : 0,
  102 + last_transfer);
  103 +
  104 + if (ret == 0) {
  105 + if (s->ptsr & PDC_PTCR_RXTEN) {
  106 + s->rcr = 0;
  107 + }
  108 + if (s->ptsr & PDC_PTCR_TXTEN) {
  109 + s->tcr = 0;
  110 + }
  111 +
  112 + } else
  113 + break;
  114 +
  115 +
  116 + if (last_transfer == 0) {
  117 + if (s->ptsr & PDC_PTCR_RXTEN) {
  118 + s->rpr = s->rnpr;
  119 + s->rcr = s->rncr;
  120 + s->rncr = 0;
  121 + }
  122 + if (s->ptsr & PDC_PTCR_TXTEN) {
  123 + s->tpr = s->tnpr;
  124 + s->tcr = s->tncr;
  125 + s->tncr = 0;
  126 + }
  127 + s->start_transfer(s->opaque, s->tpr,
  128 + (s->ptsr & PDC_PTCR_TXTEN) ? s->tcr : 0,
  129 + s->rpr, (s->ptsr & PDC_PTCR_RXTEN) ? s->rcr : 0, 1);
  130 +
  131 + if (s->ptsr & PDC_PTCR_RXTEN) {
  132 + s->rcr = 0;
  133 + }
  134 + if (s->ptsr & PDC_PTCR_TXTEN) {
  135 + s->tcr = 0;
  136 + }
  137 + }
  138 + }
  139 +
  140 + break;
  141 + case PDC_RPR:
  142 + s->rpr = val;
  143 + break;
  144 + case PDC_TPR:
  145 + s->tpr = val;
  146 + break;
  147 + case PDC_RCR:
  148 + s->rcr = val;
  149 + break;
  150 + case PDC_TCR:
  151 + s->tcr = val;
  152 + break;
  153 + case PDC_RNPR:
  154 + s->rnpr = val;
  155 + break;
  156 + case PDC_RNCR:
  157 + s->rncr = val;
  158 + break;
  159 + case PDC_TNPR:
  160 + s->tnpr = val;
  161 + break;
  162 + case PDC_TNCR:
  163 + s->tncr = val;
  164 + break;
  165 + default:
  166 + DPRINTF("ignore write of %X to %X\n", val, offset);
  167 + /*ignore*/break;
  168 + }
  169 +}
  170 +
  171 +uint32_t at91_pdc_read(void *opaque, target_phys_addr_t offset)
  172 +{
  173 +//PDCState *s = opaque;
  174 + DPRINTF("ignore read from %X\n", offset);
  175 + return 0;
  176 +}
  177 +
  178 +void at91_pdc_reset(PDCState *s)
  179 +{
  180 + s->ptsr = 0;
  181 + s->rpr = 0;
  182 + s->tpr = 0;
  183 + s->rcr = 0;
  184 + s->tcr = 0;
  185 +
  186 + s->tnpr = 0;
  187 + s->rnpr = 0;
  188 + s->tncr = 0;
  189 + s->rncr = 0;
  190 +}
... ...
hw/at91_spi.c 0 → 100644
  1 +/*
  2 + * AT91 Serial Peripheral Interface
  3 + * Written by Evgeniy Dushistov
  4 + * This code is licenced under the GPL.
  5 + */
  6 +#include "sysbus.h"
  7 +#include "spi.h"
  8 +#include "at91.h"
  9 +
  10 +#define SPI_SIZE 0x4000
  11 +#define SPI_CR 0x0
  12 +#define SPI_MR 0x4
  13 +#define SPI_RDR 0x8
  14 +#define SPI_TDR 0xC
  15 +#define SPI_SR 0x10
  16 +#define SPI_IER 0x14
  17 +#define SPI_IDR 0x18
  18 +#define SPI_IMR 0x1C
  19 +#define SPI_CSR0 0x30
  20 +#define SPI_CSR1 0x34
  21 +#define SPI_CSR2 0x38
  22 +#define SPI_CSR3 0x3C
  23 +
  24 +#define SPI_CR_SPIEN 1
  25 +#define SPI_CR_SPIDIS 2
  26 +#define SPI_SR_ENDRX (1 << 4)
  27 +#define SPI_SR_ENDTX (1 << 5)
  28 +#define SPI_SR_RXBUFF (1 << 6)
  29 +#define SPI_SR_TXBUFE (1 << 7)
  30 +#define SPI_SR_SPIENS (1 << 16)
  31 +
  32 +typedef struct SPIState {
  33 + SysBusDevice busdev;
  34 + qemu_irq irq;
  35 + uint32_t mr;
  36 + uint32_t rdr;
  37 + uint32_t tdr;
  38 + uint32_t sr;
  39 + uint32_t imr;
  40 + uint32_t csr[4];
  41 + SPIControl *spi_control;
  42 + PDCState *pdc_state;
  43 +} SPIState;
  44 +
  45 +#define AT91_SPI_DEBUG
  46 +#ifdef AT91_SPI_DEBUG
  47 +#define DPRINTF(fmt, ...) \
  48 + do { \
  49 + printf("AT91SPI: " fmt , ## __VA_ARGS__); \
  50 + } while (0)
  51 +#else
  52 +#define DPRINTF(fmt, ...) do { } while (0)
  53 +#endif
  54 +
  55 +static uint32_t txrx_callback_empty_fun(void *opaque, uint32_t cmd, int len)
  56 +{
  57 + return 0;
  58 +}
  59 +
  60 +static void set_chipselect_empty(void *opaque, int on)
  61 +{
  62 +}
  63 +
  64 +static const SPIControl txrx_callback_empty = {
  65 + .txrx_callback = txrx_callback_empty_fun,
  66 + .set_chipselect = set_chipselect_empty,
  67 + .opaque = NULL,
  68 +};
  69 +
  70 +extern CPUState *g_env;
  71 +
  72 +static uint32_t at91_spi_mem_read(void *opaque, target_phys_addr_t offset)
  73 +{
  74 + SPIState *s = opaque;
  75 +
  76 + offset &= SPI_SIZE - 1;
  77 + DPRINTF("spi read off %X, %X\n", offset, g_env->regs[15]);
  78 +
  79 + switch (offset) {
  80 + case SPI_MR:
  81 + return s->mr;
  82 + case SPI_SR:
  83 + DPRINTF("s->sr %X\n", s->sr);
  84 + return s->sr;
  85 + case SPI_RDR:
  86 + return s->rdr;
  87 + case SPI_CSR0 ... SPI_CSR3:
  88 + return s->csr[(offset - SPI_CSR0) / sizeof(s->csr[0])];
  89 + case 0x100 ... 0x124:
  90 + return at91_pdc_read(s->pdc_state, offset);
  91 + case SPI_CR:/*write only*/
  92 + default:
  93 + DPRINTF("unsupported offset %X\n", offset);
  94 + return 0;
  95 + }
  96 +}
  97 +
  98 +static void at91_spi_mem_write(void *opaque, target_phys_addr_t offset,
  99 + uint32_t value)
  100 +{
  101 + SPIState *s = opaque;
  102 +
  103 + offset &= SPI_SIZE - 1;
  104 + DPRINTF("spi write off %X, val %X, %X\n", offset, value, g_env->regs[15]);
  105 + switch (offset ){
  106 + case SPI_CR:
  107 + if (value & SPI_CR_SPIEN)
  108 + s->sr |= SPI_SR_SPIENS;
  109 + if (value & SPI_CR_SPIDIS)
  110 + s->sr &= ~SPI_SR_SPIENS;
  111 + break;
  112 + case SPI_MR:
  113 + s->mr = value;
  114 + break;
  115 + case SPI_CSR0 ... SPI_CSR3:
  116 + DPRINTF("bits per transfer %d\n", 8 + ((value & 0xF0) >> 4));
  117 + s->csr[(offset - SPI_CSR0) / sizeof(s->csr[0])] = value;
  118 + break;
  119 + case 0x100 ... 0x124:
  120 + at91_pdc_write(s->pdc_state, offset, value);
  121 + break;
  122 + default:
  123 + DPRINTF("unsupported offset %X, val %X\n", offset, value);
  124 + break;
  125 + }
  126 +}
  127 +
  128 +static CPUReadMemoryFunc *at91_spi_readfn[] = {
  129 + at91_spi_mem_read,
  130 + at91_spi_mem_read,
  131 + at91_spi_mem_read,
  132 +};
  133 +
  134 +static CPUWriteMemoryFunc *at91_spi_writefn[] = {
  135 + at91_spi_mem_write,
  136 + at91_spi_mem_write,
  137 + at91_spi_mem_write,
  138 +};
  139 +
  140 +static int pdc_start_transfer(void *opaque,
  141 + target_phys_addr_t tx,
  142 + unsigned int tx_len,
  143 + target_phys_addr_t rx,
  144 + unsigned int rx_len,
  145 + int last_transfer)
  146 +{
  147 + SPIState *s = opaque;
  148 + unsigned int i;
  149 + unsigned int tlen = rx_len > tx_len ? rx_len : tx_len;
  150 + int flags = ((tx_len > 0) ? 1 : 0) | ((rx_len > 0) ? 2 : 0);
  151 +
  152 + DPRINTF("pdc: start transfer, last trans %d\n", last_transfer);
  153 +#if 1
  154 + if (flags == 2) {
  155 + DPRINTF("ignore only read request\n");
  156 + return -1;
  157 + }
  158 +#endif
  159 + /* suppose that transfer 8 bit,
  160 + TODO: fix this, extract right value from csr
  161 + */
  162 + s->spi_control->set_chipselect(s->spi_control->opaque, 1);
  163 + for (i = 0; i < tlen; ++i) {
  164 + DPRINTF("pdc: transfering\n");
  165 + uint8_t tmp = 0;
  166 + if (tx_len > 0) {
  167 + cpu_physical_memory_read(tx, &tmp, 1);
  168 + ++tx;
  169 + --tx_len;
  170 + }
  171 + tmp = s->spi_control->txrx_callback(s->spi_control->opaque, tmp, 8);
  172 + s->rdr = tmp;
  173 + if (rx_len > 0) {
  174 + cpu_physical_memory_write(rx, &tmp, 1);
  175 + ++rx;
  176 + --rx_len;
  177 + }
  178 + }
  179 + if (flags & 1) {//tx
  180 + s->sr |= SPI_SR_ENDTX | SPI_SR_TXBUFE;
  181 + }
  182 + if (flags & 2) {//rx
  183 + s->sr |= SPI_SR_RXBUFF | SPI_SR_ENDRX;
  184 + }
  185 + if (last_transfer)
  186 + s->spi_control->set_chipselect(s->spi_control->opaque, 0);
  187 + return 0;
  188 +}
  189 +
  190 +static void at91_spi_reset(void *opaque)
  191 +{
  192 + SPIState *s = opaque;
  193 +
  194 + s->mr = 0;
  195 + s->rdr = 0;
  196 + s->sr = 0xf0;
  197 + s->imr = 0;
  198 + memset(s->csr, 0, sizeof(s->csr));
  199 + at91_pdc_reset(s->pdc_state);
  200 +}
  201 +
  202 +static void at91_spi_init(SysBusDevice *dev)
  203 +{
  204 + SPIState *s = FROM_SYSBUS(typeof(*s), dev);
  205 + int spi_regs;
  206 +
  207 + s->pdc_state = at91_pdc_init(s, pdc_start_transfer);
  208 + sysbus_init_irq(dev, &s->irq);
  209 + spi_regs = cpu_register_io_memory(at91_spi_readfn, at91_spi_writefn, s);
  210 + sysbus_init_mmio(dev, SPI_SIZE, spi_regs);
  211 + qemu_register_reset(at91_spi_reset, s);
  212 +}
  213 +
  214 +static SysBusDeviceInfo spi_info = {
  215 + .init = at91_spi_init,
  216 + .qdev.name = "at91,spi",
  217 + .qdev.size = sizeof(SPIState),
  218 + .qdev.props = (Property[]) {
  219 + {
  220 + .name = "spi_control",
  221 + .info = &qdev_prop_ptr,
  222 + .offset = offsetof(SPIState, spi_control),
  223 + .defval = (void *)&txrx_callback_empty,
  224 + },
  225 + {/* end of list */}
  226 + }
  227 +};
  228 +
  229 +
  230 +static void at91_spi_register(void)
  231 +{
  232 + sysbus_register_withprop(&spi_info);
  233 +}
  234 +
  235 +device_init(at91_spi_register)
... ...
hw/at91sam9.c
... ... @@ -13,11 +13,13 @@
13 13 #include "devices.h"
14 14 #include "net.h"
15 15 #include "sysemu.h"
  16 +#include "spi.h"
16 17 #include "flash.h"
17 18 #include "boards.h"
18 19 #include "qemu-char.h"
19 20 #include "qemu-timer.h"
20 21 #include "sysbus.h"
  22 +#include "at91.h"
21 23  
22 24 #include "at91sam9263_defs.h"
23 25  
... ... @@ -62,7 +64,7 @@ struct at91sam9_state {
62 64 uint32_t sdramc0_regs[(AT91_SMC0_BASE - AT91_SDRAMC0_BASE) / sizeof(uint32_t)];
63 65 uint32_t smc0_regs[(AT91_ECC1_BASE - AT91_SMC0_BASE) / sizeof(uint32_t)];
64 66 uint32_t usart0_regs[0x1000 / sizeof(uint32_t)];
65   - struct dbgu_state dbgu;
  67 +// struct dbgu_state dbgu;
66 68 pflash_t *norflash;
67 69 ram_addr_t internal_sram;
68 70 QEMUTimer *dbgu_tr_timer;
... ... @@ -70,6 +72,8 @@ struct at91sam9_state {
70 72 int timer_active;
71 73 CPUState *env;
72 74 qemu_irq *qirq;
  75 + ram_addr_t bootrom;
  76 + int rom_size;
73 77 };
74 78  
75 79 static uint32_t at91_bus_matrix_read(void *opaque, target_phys_addr_t offset)
... ... @@ -125,7 +129,7 @@ static void at91_ccfg_write(void *opaque, target_phys_addr_t offset,
125 129 static uint32_t at91_sdramc0_read(void *opaque, target_phys_addr_t offset)
126 130 {
127 131 struct at91sam9_state *sam9 = (struct at91sam9_state *)opaque;
128   -
  132 +
129 133 TRACE("sdramc0 read offset %X\n", offset);
130 134 return sam9->sdramc0_regs[offset / sizeof(sam9->sdramc0_regs[0])];
131 135 }
... ... @@ -134,7 +138,7 @@ static void at91_sdramc0_write(void *opaque, target_phys_addr_t offset,
134 138 uint32_t value)
135 139 {
136 140 struct at91sam9_state *sam9 = (struct at91sam9_state *)opaque;
137   -
  141 +
138 142 TRACE("sdramc0 write offset %X, value %X\n", offset, value);
139 143 sam9->sdramc0_regs[offset / sizeof(sam9->sdramc0_regs[0])] = value;
140 144 }
... ... @@ -223,6 +227,7 @@ static CPUWriteMemoryFunc *at91_periph_writefn[] = {
223 227 at91_periph_write
224 228 };
225 229  
  230 +CPUState *g_env;
226 231  
227 232 static void at91sam9_init(ram_addr_t ram_size,
228 233 const char *boot_device,
... ... @@ -241,9 +246,23 @@ static void at91sam9_init(ram_addr_t ram_size,
241 246 DeviceState *dev;
242 247 DeviceState *pit;
243 248 DeviceState *pmc;
  249 + DeviceState *spi;
244 250 int i;
  251 + int bms;
  252 + SPIControl *cs0_spi_handler;
  253 +
  254 + cs0_spi_handler = qemu_mallocz(sizeof(SPIControl));
  255 + DEBUG("begin, ram_size %llu, boot dev %s\n", (unsigned long long)ram_size,
  256 + boot_device ? boot_device : "<empty>");
  257 +
  258 + if (option_rom[0] && boot_device[0] == 'n') {
  259 + printf("Emulate ROM code\n");
  260 + bms = 1;
  261 + } else {
  262 + printf("Emulate start from EBI0_NCS0\n");
  263 + bms = 0;
  264 + }
245 265  
246   - DEBUG("begin, ram_size %llu\n", (unsigned long long)ram_size);
247 266 #ifdef TRACE_ON
248 267 trace_file = fopen("/tmp/trace.log", "w");
249 268 #endif
... ... @@ -267,6 +286,12 @@ static void at91sam9_init(ram_addr_t ram_size,
267 286 /* Internal SRAM */
268 287 sam9->internal_sram = qemu_ram_alloc(80 * 1024);
269 288 cpu_register_physical_memory(0x00300000, 80 * 1024, sam9->internal_sram | IO_MEM_RAM);
  289 + sam9->bootrom = qemu_ram_alloc(0x100000);
  290 + cpu_register_physical_memory(0x00400000, 0x100000, sam9->bootrom | IO_MEM_RAM);
  291 + if (option_rom[0]) {
  292 + sam9->rom_size = load_image_targphys(option_rom[0], 0x00400000, 0x100000);
  293 + printf("load bootrom, size %d\n", sam9->rom_size);
  294 + }
270 295  
271 296 /*Internal Peripherals */
272 297 iomemtype = cpu_register_io_memory(at91_periph_readfn, at91_periph_writefn, sam9);
... ... @@ -291,7 +316,7 @@ static void at91sam9_init(ram_addr_t ram_size,
291 316 qdev_prop_set_uint32(pmc, "mo_freq", 16000000);
292 317 pit = sysbus_create_simple("at91,pit", AT91_PITC_BASE, pic1[3]);
293 318 sysbus_create_varargs("at91,tc", AT91_TC012_BASE, pic[19], pic[19], pic[19], NULL);
294   -
  319 + spi = sysbus_create_simple("at91,spi", AT91_SPI0_BASE, pic[14]);
295 320 at91_init_bus_matrix(sam9);
296 321 memset(&sam9->ccfg_regs, 0, sizeof(sam9->ccfg_regs));
297 322 sysbus_create_simple("at91,pio", AT91_PIOA_BASE, pic[2]);
... ... @@ -318,33 +343,46 @@ static void at91sam9_init(ram_addr_t ram_size,
318 343 */
319 344 dinfo = drive_get(IF_PFLASH, 0, 0);
320 345 if (dinfo) {
321   - ram_addr_t nor_flash_mem = qemu_ram_alloc(NOR_FLASH_SIZE);
322   - if (!nor_flash_mem) {
323   - fprintf(stderr, "allocation failed\n");
324   - exit(EXIT_FAILURE);
  346 + if (bms) {
  347 + if (spi_flash_register(dinfo->bdrv, 2 * 1024 * 1024, cs0_spi_handler) < 0) {
  348 + fprintf(stderr, "init of spi flash failed\n");
  349 + exit(EXIT_FAILURE);
  350 + }
  351 + qdev_prop_set_ptr(spi, "spi_control", cs0_spi_handler);
  352 + //rom
  353 + cpu_register_physical_memory(0x0, 100 * 1024,
  354 + sam9->bootrom | IO_MEM_ROMD);
  355 + } else {
  356 + //nor flash
  357 + ram_addr_t nor_flash_mem = qemu_ram_alloc(NOR_FLASH_SIZE);
  358 + if (!nor_flash_mem) {
  359 + fprintf(stderr, "allocation failed\n");
  360 + exit(EXIT_FAILURE);
  361 + }
  362 +
  363 + sam9->norflash = pflash_cfi_atmel_register(AT91SAM9263EK_NORFLASH_OFF,
  364 + nor_flash_mem,
  365 + dinfo->bdrv,
  366 + 4 * 1024 * 2, 8,
  367 + 32 * 1024 * 2,
  368 + (135 - 8),
  369 + 2, 0x001F, 0x01D6, 0, 0);
  370 +
  371 + if (!sam9->norflash) {
  372 + fprintf(stderr, "qemu: error registering flash memory.\n");
  373 + exit(EXIT_FAILURE);
  374 + }
  375 +
  376 + DEBUG("register flash at 0x0\n");
  377 + //register only part of flash, to prevent conflict with internal sram
  378 + cpu_register_physical_memory(0x0, 100 * 1024,
  379 + nor_flash_mem | IO_MEM_ROMD);
325 380 }
326   -
327   - sam9->norflash = pflash_cfi_atmel_register(AT91SAM9263EK_NORFLASH_OFF,
328   - nor_flash_mem,
329   - dinfo->bdrv,
330   - 4 * 1024 * 2, 8,
331   - 32 * 1024 * 2,
332   - (135 - 8),
333   - 2, 0x001F, 0x01D6, 0, 0);
334   -
335   - if (!sam9->norflash) {
336   - fprintf(stderr, "qemu: error registering flash memory.\n");
337   - exit(EXIT_FAILURE);
338   - }
339   -
340   - DEBUG("register flash at 0x0\n");
341   - //register only part of flash, to prevent conflict with internal sram
342   - cpu_register_physical_memory(0x0, 100 * 1024 /*NOR_FLASH_SIZE*/,
343   - nor_flash_mem | IO_MEM_ROMD);
344 381 } else {
345 382 fprintf(stderr, "qemu: can not start without flash.\n");
346 383 exit(EXIT_FAILURE);
347 384 }
  385 + g_env = env;
348 386 env->regs[15] = 0x0;
349 387 }
350 388  
... ...
hw/at91sam9263_defs.h
... ... @@ -6,6 +6,7 @@
6 6 #define AT91_TC012_BASE 0xFFF7C000
7 7 #define AT91_USART0_BASE 0xFFF8C000
8 8 #define AT91_EMAC_BASE 0xFFFBC000
  9 +#define AT91_SPI0_BASE 0xFFFA4000
9 10 #define AT91_SDRAMC0_BASE 0xFFFFE200
10 11 #define AT91_SMC0_BASE 0xFFFFE400
11 12 #define AT91_ECC1_BASE 0xFFFFE600
... ...
hw/flash.h
... ... @@ -26,6 +26,10 @@ pflash_t *pflash_cfi_atmel_register(target_phys_addr_t base, ram_addr_t off,
26 26 uint16_t id0, uint16_t id1,
27 27 uint16_t id2, uint16_t id3);
28 28  
  29 +struct SPIControl;
  30 +/* spi_flash.c */
  31 +extern int spi_flash_register(BlockDriverState *bs, unsigned int len,
  32 + struct SPIControl *spi_control);
29 33  
30 34 /* nand.c */
31 35 typedef struct NANDFlashState NANDFlashState;
... ...
hw/spi.h 0 → 100644
  1 +#ifndef _HW_SPI_H_
  2 +#define _HW_SPI_H_
  3 +
  4 +/* minimal interface to separate device connected via SPI and SPI controller */
  5 +typedef struct SPIControl {
  6 + void *opaque;
  7 + uint32_t (*txrx_callback)(void *opaque, uint32_t val, int len);
  8 + void (*set_chipselect)(void *opaque, int on);
  9 +} SPIControl;
  10 +
  11 +#endif//!_HW_SPI_H_
... ...
hw/spi_flash.c 0 → 100644
  1 +#include "hw.h"
  2 +#include "block.h"
  3 +#include "spi.h"
  4 +#include "flash.h"
  5 +
  6 +typedef struct SPIFlash {
  7 + uint32_t cmd;
  8 + unsigned cmd_len;
  9 + uint32_t addr;
  10 + void *storage;
  11 + unsigned int len;
  12 + BlockDriverState *bs;
  13 +} SPIFlash;
  14 +
  15 +#define AT91_SPI_FLASH_DEBUG
  16 +#ifdef AT91_SPI_FLASH_DEBUG
  17 +#define DPRINTF(fmt, ...) \
  18 + do { \
  19 + printf("AT91SPI_FLASH: " fmt , ## __VA_ARGS__); \
  20 + } while (0)
  21 +#else
  22 +#define DPRINTF(fmt, ...) do { } while (0)
  23 +#endif
  24 +
  25 +static void spi_flash_reset_state(SPIFlash *s)
  26 +{
  27 + s->cmd = 0;
  28 + s->cmd_len = 0;
  29 + s->addr = 0;
  30 +}
  31 +
  32 +static void spi_flash_set_chipselect(void *opaque, int on)
  33 +{
  34 + SPIFlash *s = opaque;
  35 +
  36 + DPRINTF("set NS %d\n", on);
  37 + if (on == 0)
  38 + spi_flash_reset_state(s);
  39 +}
  40 +
  41 +static uint32_t spi_flash_txrx(void *opaque, uint32_t val, int len)
  42 +{
  43 + SPIFlash *s = opaque;
  44 +
  45 + DPRINTF("txrx: val %X\n", val);
  46 + switch (s->cmd) {
  47 + case 0:
  48 + s->cmd = val;
  49 + ++s->cmd_len;
  50 + return 0;
  51 + case 0xE8:
  52 + ++s->cmd_len;
  53 + if (s->cmd_len >= 2 && s->cmd_len <= 4) {
  54 + s->addr |= (val & 0xFF) << ((4 - s->cmd_len) * 8);
  55 + } else if (s->cmd_len >= 5 && s->cmd_len < (5 + 4)) {
  56 + /*ignore bytes*/
  57 + } else {
  58 + uint8_t *bytes = s->storage;
  59 + /*TODO: handle different page sizes*/
  60 + uint32_t addr = (s->addr >> 10) * 528 + (s->addr & 0x3ff);
  61 + DPRINTF("we read %X\n", bytes[addr + s->cmd_len - 9]);
  62 +
  63 + return bytes[addr + s->cmd_len - 9];
  64 + }
  65 +
  66 + return 0;
  67 + case 0xD7:
  68 + spi_flash_reset_state(s);
  69 + DPRINTF("return id\n");
  70 + return (1 << 2) | (1 << 3) | (1 << 5) | (1 << 7);
  71 + default:
  72 + DPRINTF("Unknown cmd\n");
  73 + return 0;
  74 + }
  75 +}
  76 +
  77 +int spi_flash_register(BlockDriverState *bs, unsigned int len,
  78 + SPIControl *spi_control)
  79 +{
  80 + SPIFlash *spi_flash;
  81 + int ret = 0;
  82 +
  83 + spi_flash = qemu_mallocz(sizeof(SPIFlash));
  84 + spi_control->opaque = spi_flash;
  85 + spi_control->txrx_callback = spi_flash_txrx;
  86 + spi_control->set_chipselect = spi_flash_set_chipselect;
  87 +
  88 + spi_flash_reset_state(spi_flash);
  89 + spi_flash->storage = qemu_malloc(len);
  90 + spi_flash->len = len;
  91 + spi_flash->bs = bs;
  92 + if (spi_flash->bs) {
  93 + ret = bdrv_read(spi_flash->bs, 0, spi_flash->storage, len >> 9);
  94 + if (ret < 0) {
  95 + qemu_free(spi_flash->storage);
  96 + qemu_free(spi_flash);
  97 + goto out;
  98 + }
  99 + }
  100 +out:
  101 + return ret;
  102 +}
... ...