/* * $Id: p64lcd.c,v 1.1 2008/01/07 20:24:49 nbrk Exp $ */ #include #include #include #include #include /* * 44780-based LCD connected to my p64 board. * Wiring for chip logic: * RS -> PA10 * R/W -> PA9 * E -> PA8 * D{0..7} -> PA{7,6,5,4,3,2,1,0} * * We will fake-up as a 10-bit bus for our child (real 44780 driver). * This 10-bit bus is: MSB .. LSB * Please note that p64lcd_read() returns 8-bit D0..D7. */ int p64lcd_attach(struct device *self, uint32_t loc, uint8_t flags); void p64lcd_write(void *pldd, uint16_t data); uint8_t p64lcd_read(void *pldd); uint8_t p64lcd_readbf(void *pldd); void p64lcd_strobe(void *pldd); /* our devdata */ struct p64lcd_dd { struct gpio_controller *pl_gcp; struct h44780_busops pl_bus; /* our 10-bit control bus for driver */ }; struct driver p64lcd_dr = { sizeof(struct p64lcd_dd), p64lcd_attach, NULL, NULL }; int p64lcd_attach(struct device *self, uint32_t loc, uint8_t flags) { struct p64lcd_dd *ddp = self->dv_devdata; struct gpio_pin pin; uint8_t i; int j; /* grab parent's gpio_controller */ ddp->pl_gcp = self->dv_parent->dv_aux; /* configure pins */ pin.gp_pio = 1; pin.gp_flags = GPIO_PIN_OUTPUT; /* XXX what about read? */ pin.gp_value = 0; for(i = 0; i < 11; i++) { pin.gp_pinno = i; ddp->pl_gcp->gc_pinset(ddp->pl_gcp->gc_selfdd, pin); } /* XXX enable synchronous data output on our data lines */ *AT91C_PIOA_OWER = 0xff; // *AT91C_PIOA_ODSR = 0xaa; // *AT91C_PIOA_ODSR = ~0xaa; printf("p64 10-bit bus for LCD, dedicated E strobe\n"); /* link 44780_ops */ ddp->pl_bus.write = p64lcd_write; ddp->pl_bus.read = p64lcd_read; ddp->pl_bus.readbf = p64lcd_readbf; ddp->pl_bus.strobe = p64lcd_strobe; ddp->pl_bus.selfdd = ddp; /* export */ self->dv_aux = &ddp->pl_bus; return(0); } void p64lcd_write(void *pldd, uint16_t data) { uint32_t setmask = 0; uint8_t i, rs, rw = rs = 0; /* * Decode and place given 10-bit data on the wires. * We will use raw PIOA registers instead of gpio_controller abstraction * so we can hit all pins in one shoot. */ /* * Caller gives us: (LSB) */ /* strip unneeded bits */ data = data & 0x3ff; /* XXX bring all our lines to high */ //*AT91C_PIOA_CODR = 0x3ff; /* check if caller requested to assert RS */ if (data & 0x200) rs = 1; // setmask |= 1 << 10; /* 'RS' is PA10 */ // *AT91C_PIOA_CODR = 1 << 10; // else *AT91C_PIOA_SODR = 1 << 10; /* check if caller requested to assert R/W */ if (data & 0x100) rw = 1; // setmask |= 1 << 9; /* 'RW' is PA9 */ // *AT91C_PIOA_CODR = 1 << 9; // else *AT91C_PIOA_SODR = 1 << 9; /* * Deal with LSB of data which contains D0..D7 value. * Since D0..D7 is wired to PA7..PA0 we need to reverse bits. */ for(i = 0; i < 7; i++) if (data & (1 << i)) setmask |= 1 << (7 - i); // setmask = data & 0xff; printf("p64lcd_write: rs=%d rw=%d setmask=0x%x\n", rs, rw, setmask); // *AT91C_PIOA_SODR = setmask; // *AT91C_PIOA_CODR = (uint8_t)(~setmask); if (rs) *AT91C_PIOA_SODR = 1 << 10; else *AT91C_PIOA_CODR = 1 << 10; if (rw) *AT91C_PIOA_SODR = 1 << 9; else *AT91C_PIOA_CODR = 1 << 9; /* E high */ *AT91C_PIOA_SODR = 1 << 8; *AT91C_PIOA_ODSR = setmask; /* E low */ *AT91C_PIOA_CODR = 1 << 8; //*AT91C_PIOA_ODSR = ~setmask; } uint8_t p64lcd_read(void *pldd) { /* TODO */ return(1); } uint8_t p64lcd_readbf(void *pldd) { /* TODO */ return(1); } void p64lcd_strobe(void *pldd) { volatile int i; *AT91C_PIOA_SODR = 1 << 8; /* XXX delay? */ for(i = 0; i < 10; i++) ; *AT91C_PIOA_CODR = 1 << 8; }