Commit a6569fc532698a7df1cc9c04f26503727a5a5bfd

Authored by balrog
1 parent c9fb531a

tc6393xb: initial support for nand control (Dmitry Baryshkov).

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5611 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 221 additions and 23 deletions
hw/tc6393xb.c
... ... @@ -10,6 +10,15 @@
10 10 #include "hw.h"
11 11 #include "pxa.h"
12 12 #include "devices.h"
  13 +#include "flash.h"
  14 +
  15 +#define IRQ_TC6393_NAND 0
  16 +#define IRQ_TC6393_MMC 1
  17 +#define IRQ_TC6393_OHCI 2
  18 +#define IRQ_TC6393_SERIAL 3
  19 +#define IRQ_TC6393_FB 4
  20 +
  21 +#define TC6393XB_NR_IRQS 8
13 22  
14 23 #define TC6393XB_GPIOS 16
15 24  
... ... @@ -40,8 +49,37 @@
40 49 #define SCR_CONFIG 0xfc /* b Configuration Control */
41 50 #define SCR_DEBUG 0xff /* b Debug */
42 51  
  52 +#define NAND_CFG_COMMAND 0x04 /* w Command */
  53 +#define NAND_CFG_BASE 0x10 /* l Control Base Address */
  54 +#define NAND_CFG_INTP 0x3d /* b Interrupt Pin */
  55 +#define NAND_CFG_INTE 0x48 /* b Int Enable */
  56 +#define NAND_CFG_EC 0x4a /* b Event Control */
  57 +#define NAND_CFG_ICC 0x4c /* b Internal Clock Control */
  58 +#define NAND_CFG_ECCC 0x5b /* b ECC Control */
  59 +#define NAND_CFG_NFTC 0x60 /* b NAND Flash Transaction Control */
  60 +#define NAND_CFG_NFM 0x61 /* b NAND Flash Monitor */
  61 +#define NAND_CFG_NFPSC 0x62 /* b NAND Flash Power Supply Control */
  62 +#define NAND_CFG_NFDC 0x63 /* b NAND Flash Detect Control */
  63 +
  64 +#define NAND_DATA 0x00 /* l Data */
  65 +#define NAND_MODE 0x04 /* b Mode */
  66 +#define NAND_STATUS 0x05 /* b Status */
  67 +#define NAND_ISR 0x06 /* b Interrupt Status */
  68 +#define NAND_IMR 0x07 /* b Interrupt Mask */
  69 +
  70 +#define NAND_MODE_WP 0x80
  71 +#define NAND_MODE_CE 0x10
  72 +#define NAND_MODE_ALE 0x02
  73 +#define NAND_MODE_CLE 0x01
  74 +#define NAND_MODE_ECC_MASK 0x60
  75 +#define NAND_MODE_ECC_EN 0x20
  76 +#define NAND_MODE_ECC_READ 0x40
  77 +#define NAND_MODE_ECC_RST 0x60
  78 +
43 79 struct tc6393xb_s {
44 80 target_phys_addr_t target_base;
  81 + qemu_irq irq;
  82 + qemu_irq *sub_irqs;
45 83 struct {
46 84 uint8_t ISR;
47 85 uint8_t IMR;
... ... @@ -71,6 +109,16 @@ struct tc6393xb_s {
71 109 uint32_t prev_level;
72 110 qemu_irq handler[TC6393XB_GPIOS];
73 111 qemu_irq *gpio_in;
  112 +
  113 + struct {
  114 + uint8_t mode;
  115 + uint8_t isr;
  116 + uint8_t imr;
  117 + } nand;
  118 + int nand_enable;
  119 + uint32_t nand_phys;
  120 + struct nand_flash_s *flash;
  121 + struct ecc_state_s ecc;
74 122 };
75 123  
76 124 qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s)
... ... @@ -116,6 +164,17 @@ static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s)
116 164 s->prev_level = level;
117 165 }
118 166  
  167 +static void tc6393xb_sub_irq(void *opaque, int line, int level) {
  168 + struct tc6393xb_s *s = opaque;
  169 + uint8_t isr = s->scr.ISR;
  170 + if (level)
  171 + isr |= 1 << line;
  172 + else
  173 + isr &= ~(1 << line);
  174 + s->scr.ISR = isr;
  175 + qemu_set_irq(s->irq, isr & s->scr.IMR);
  176 +}
  177 +
119 178 #define SCR_REG_B(N) \
120 179 case SCR_ ##N: return s->scr.N
121 180 #define SCR_REG_W(N) \
... ... @@ -131,10 +190,8 @@ static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s)
131 190 case SCR_ ##N(1): return s->scr.N[1]; \
132 191 case SCR_ ##N(2): return s->scr.N[2]
133 192  
134   -static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr)
  193 +static uint32_t tc6393xb_scr_readb(struct tc6393xb_s *s, target_phys_addr_t addr)
135 194 {
136   - struct tc6393xb_s *s = opaque;
137   - addr -= s->target_base;
138 195 switch (addr) {
139 196 case SCR_REVID:
140 197 return 3;
... ... @@ -171,7 +228,7 @@ static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr)
171 228 SCR_REG_B(CONFIG);
172 229 SCR_REG_B(DEBUG);
173 230 }
174   - fprintf(stderr, "tc6393xb: unhandled read at %08x\n", (uint32_t) addr);
  231 + fprintf(stderr, "tc6393xb_scr: unhandled read at %08x\n", (uint32_t) addr);
175 232 return 0;
176 233 }
177 234 #undef SCR_REG_B
... ... @@ -180,24 +237,22 @@ static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr)
180 237 #undef SCR_REG_A
181 238  
182 239 #define SCR_REG_B(N) \
183   - case SCR_ ##N: s->scr.N = value; break;
  240 + case SCR_ ##N: s->scr.N = value; return;
184 241 #define SCR_REG_W(N) \
185   - case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); break; \
186   - case SCR_ ##N + 1: s->scr.N = (s->scr.N & 0xff) | (value << 8); break
  242 + case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \
  243 + case SCR_ ##N + 1: s->scr.N = (s->scr.N & 0xff) | (value << 8); return
187 244 #define SCR_REG_L(N) \
188   - case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); break; \
189   - case SCR_ ##N + 1: s->scr.N = (s->scr.N & ~(0xff << 8)) | (value & (0xff << 8)); break; \
190   - case SCR_ ##N + 2: s->scr.N = (s->scr.N & ~(0xff << 16)) | (value & (0xff << 16)); break; \
191   - case SCR_ ##N + 3: s->scr.N = (s->scr.N & ~(0xff << 24)) | (value & (0xff << 24)); break;
  245 + case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \
  246 + case SCR_ ##N + 1: s->scr.N = (s->scr.N & ~(0xff << 8)) | (value & (0xff << 8)); return; \
  247 + case SCR_ ##N + 2: s->scr.N = (s->scr.N & ~(0xff << 16)) | (value & (0xff << 16)); return; \
  248 + case SCR_ ##N + 3: s->scr.N = (s->scr.N & ~(0xff << 24)) | (value & (0xff << 24)); return;
192 249 #define SCR_REG_A(N) \
193   - case SCR_ ##N(0): s->scr.N[0] = value; break; \
194   - case SCR_ ##N(1): s->scr.N[1] = value; break; \
195   - case SCR_ ##N(2): s->scr.N[2] = value; break
  250 + case SCR_ ##N(0): s->scr.N[0] = value; return; \
  251 + case SCR_ ##N(1): s->scr.N[1] = value; return; \
  252 + case SCR_ ##N(2): s->scr.N[2] = value; return
196 253  
197   -static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
  254 +static void tc6393xb_scr_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value)
198 255 {
199   - struct tc6393xb_s *s = opaque;
200   - addr -= s->target_base;
201 256 switch (addr) {
202 257 SCR_REG_B(ISR);
203 258 SCR_REG_B(IMR);
... ... @@ -212,13 +267,13 @@ static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t valu
212 267 case SCR_GPO_DSR(2):
213 268 s->gpio_level = (s->gpio_level & ~(0xff << ((addr - SCR_GPO_DSR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DSR(0))*8));
214 269 tc6393xb_gpio_handler_update(s);
215   - break;
  270 + return;
216 271 case SCR_GPO_DOECR(0):
217 272 case SCR_GPO_DOECR(1):
218 273 case SCR_GPO_DOECR(2):
219 274 s->gpio_dir = (s->gpio_dir & ~(0xff << ((addr - SCR_GPO_DOECR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DOECR(0))*8));
220 275 tc6393xb_gpio_handler_update(s);
221   - break;
  276 + return;
222 277 SCR_REG_A(GP_IARCR);
223 278 SCR_REG_A(GP_IARLCR);
224 279 SCR_REG_A(GPI_BCR);
... ... @@ -233,17 +288,155 @@ static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t valu
233 288 SCR_REG_W(MCR);
234 289 SCR_REG_B(CONFIG);
235 290 SCR_REG_B(DEBUG);
236   - default:
237   - fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n",
238   - (uint32_t) addr, value & 0xff);
239   - break;
240 291 }
  292 + fprintf(stderr, "tc6393xb_scr: unhandled write at %08x: %02x\n",
  293 + (uint32_t) addr, value & 0xff);
241 294 }
242 295 #undef SCR_REG_B
243 296 #undef SCR_REG_W
244 297 #undef SCR_REG_L
245 298 #undef SCR_REG_A
246 299  
  300 +static void tc6393xb_nand_irq(struct tc6393xb_s *s) {
  301 + qemu_set_irq(s->sub_irqs[IRQ_TC6393_NAND],
  302 + (s->nand.imr & 0x80) && (s->nand.imr & s->nand.isr));
  303 +}
  304 +
  305 +static uint32_t tc6393xb_nand_cfg_readb(struct tc6393xb_s *s, target_phys_addr_t addr) {
  306 + switch (addr) {
  307 + case NAND_CFG_COMMAND:
  308 + return s->nand_enable ? 2 : 0;
  309 + case NAND_CFG_BASE:
  310 + case NAND_CFG_BASE + 1:
  311 + case NAND_CFG_BASE + 2:
  312 + case NAND_CFG_BASE + 3:
  313 + return s->nand_phys >> (addr - NAND_CFG_BASE);
  314 + }
  315 + fprintf(stderr, "tc6393xb_nand_cfg: unhandled read at %08x\n", (uint32_t) addr);
  316 + return 0;
  317 +}
  318 +static void tc6393xb_nand_cfg_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) {
  319 + switch (addr) {
  320 + case NAND_CFG_COMMAND:
  321 + s->nand_enable = (value & 0x2);
  322 + return;
  323 + case NAND_CFG_BASE:
  324 + case NAND_CFG_BASE + 1:
  325 + case NAND_CFG_BASE + 2:
  326 + case NAND_CFG_BASE + 3:
  327 + s->nand_phys &= ~(0xff << ((addr - NAND_CFG_BASE) * 8));
  328 + s->nand_phys |= (value & 0xff) << ((addr - NAND_CFG_BASE) * 8);
  329 + return;
  330 + }
  331 + fprintf(stderr, "tc6393xb_nand_cfg: unhandled write at %08x: %02x\n",
  332 + (uint32_t) addr, value & 0xff);
  333 +}
  334 +
  335 +static uint32_t tc6393xb_nand_readb(struct tc6393xb_s *s, target_phys_addr_t addr) {
  336 + switch (addr) {
  337 + case NAND_DATA + 0:
  338 + case NAND_DATA + 1:
  339 + case NAND_DATA + 2:
  340 + case NAND_DATA + 3:
  341 + return nand_getio(s->flash);
  342 + case NAND_MODE:
  343 + return s->nand.mode;
  344 + case NAND_STATUS:
  345 + return 0x14;
  346 + case NAND_ISR:
  347 + return s->nand.isr;
  348 + case NAND_IMR:
  349 + return s->nand.imr;
  350 + }
  351 + fprintf(stderr, "tc6393xb_nand: unhandled read at %08x\n", (uint32_t) addr);
  352 + return 0;
  353 +}
  354 +static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) {
  355 +// fprintf(stderr, "tc6393xb_nand: write at %08x: %02x\n",
  356 +// (uint32_t) addr, value & 0xff);
  357 + switch (addr) {
  358 + case NAND_DATA + 0:
  359 + case NAND_DATA + 1:
  360 + case NAND_DATA + 2:
  361 + case NAND_DATA + 3:
  362 + nand_setio(s->flash, value);
  363 + s->nand.isr &= 1;
  364 + tc6393xb_nand_irq(s);
  365 + return;
  366 + case NAND_MODE:
  367 + s->nand.mode = value;
  368 + nand_setpins(s->flash,
  369 + value & NAND_MODE_CLE,
  370 + value & NAND_MODE_ALE,
  371 + !(value & NAND_MODE_CE),
  372 + value & NAND_MODE_WP,
  373 + 0); // FIXME: gnd
  374 + switch (value & NAND_MODE_ECC_MASK) {
  375 + case NAND_MODE_ECC_RST:
  376 + ecc_reset(&s->ecc);
  377 + break;
  378 + case NAND_MODE_ECC_READ:
  379 + // FIXME
  380 + break;
  381 + case NAND_MODE_ECC_EN:
  382 + ecc_reset(&s->ecc);
  383 + }
  384 + return;
  385 + case NAND_ISR:
  386 + s->nand.isr = value;
  387 + tc6393xb_nand_irq(s);
  388 + return;
  389 + case NAND_IMR:
  390 + s->nand.imr = value;
  391 + tc6393xb_nand_irq(s);
  392 + return;
  393 + }
  394 + fprintf(stderr, "tc6393xb_nand: unhandled write at %08x: %02x\n",
  395 + (uint32_t) addr, value & 0xff);
  396 +}
  397 +
  398 +static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) {
  399 + struct tc6393xb_s *s = opaque;
  400 + addr -= s->target_base;
  401 +
  402 + switch (addr >> 8) {
  403 + case 0:
  404 + return tc6393xb_scr_readb(s, addr & 0xff);
  405 + case 1:
  406 + return tc6393xb_nand_cfg_readb(s, addr & 0xff);
  407 + };
  408 +
  409 + if ((addr &~0xff) == s->nand_phys && s->nand_enable) {
  410 +// return tc6393xb_nand_readb(s, addr & 0xff);
  411 + uint8_t d = tc6393xb_nand_readb(s, addr & 0xff);
  412 +// fprintf(stderr, "tc6393xb_nand: read at %08x: %02hhx\n", (uint32_t) addr, d);
  413 + return d;
  414 + }
  415 +
  416 +// fprintf(stderr, "tc6393xb: unhandled read at %08x\n", (uint32_t) addr);
  417 + return 0;
  418 +}
  419 +
  420 +static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) {
  421 + struct tc6393xb_s *s = opaque;
  422 + addr -= s->target_base;
  423 +
  424 + switch (addr >> 8) {
  425 + case 0:
  426 + tc6393xb_scr_writeb(s, addr & 0xff, value);
  427 + return;
  428 + case 1:
  429 + tc6393xb_nand_cfg_writeb(s, addr & 0xff, value);
  430 + return;
  431 + };
  432 +
  433 + if ((addr &~0xff) == s->nand_phys && s->nand_enable)
  434 + tc6393xb_nand_writeb(s, addr & 0xff, value);
  435 + else
  436 + fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n",
  437 + (uint32_t) addr, value & 0xff);
  438 +}
  439 +
247 440 static uint32_t tc6393xb_readw(void *opaque, target_phys_addr_t addr)
248 441 {
249 442 return (tc6393xb_readb(opaque, addr) & 0xff) |
... ... @@ -289,8 +482,13 @@ struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq)
289 482  
290 483 s = (struct tc6393xb_s *) qemu_mallocz(sizeof(struct tc6393xb_s));
291 484 s->target_base = base;
  485 + s->irq = irq;
292 486 s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS);
293 487  
  488 + s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
  489 +
  490 + s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76);
  491 +
294 492 iomemtype = cpu_register_io_memory(0, tc6393xb_readfn,
295 493 tc6393xb_writefn, s);
296 494 cpu_register_physical_memory(s->target_base, 0x200000, iomemtype);
... ...