static int cpp_daisy(struct parport *port, int cmd) { unsigned char s; parport_data_forward(port); parport_write_data(port, 0xaa); udelay(2); parport_write_data(port, 0x55); udelay(2); parport_write_data(port, 0x00); udelay(2); parport_write_data(port, 0xff); udelay(2); s = parport_read_status(port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK(KERN_DEBUG "%s: cpp_daisy: aa5500ff(%02x)\n", port->name, s); return -ENXIO; } parport_write_data(port, 0x87); udelay(2); s = parport_read_status(port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK(KERN_DEBUG "%s: cpp_daisy: aa5500ff87(%02x)\n", port->name, s); return -ENXIO; } parport_write_data(port, 0x78); udelay(2); parport_write_data(port, cmd); udelay(2); parport_frob_control(port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); udelay(1); s = parport_read_status(port); parport_frob_control(port, PARPORT_CONTROL_STROBE, 0); udelay(1); parport_write_data(port, 0xff); udelay(2); return s; }
static void butterfly_chipselect(struct spi_device *spi, int value) { struct butterfly *pp = spidev_to_pp(spi); if (value != BITBANG_CS_INACTIVE) setsck(spi, spi->mode & SPI_CPOL); if (spi_cs_bit == PARPORT_CONTROL_INIT) value = !value; parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); }
static void butterfly_chipselect(struct spi_device *spi, int value) { struct butterfly *pp = spidev_to_pp(spi); /* set default clock polarity */ if (value != BITBANG_CS_INACTIVE) setsck(spi, spi->mode & SPI_CPOL); /* here, value == "activate or not"; * most PARPORT_CONTROL_* bits are negated, so we must * morph it to value == "bit value to write in control register" */ if (spi_cs_bit == PARPORT_CONTROL_INIT) value = !value; parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); }
static void butterfly_chipselect(struct spi_device *spi, int value) { struct butterfly *pp = spidev_to_pp(spi); /* set default clock polarity */ if (value) setsck(spi, spi->mode & SPI_CPOL); /* no chipselect on this USI link config */ if (is_usidev(spi)) return; /* here, value == "activate or not" */ /* most PARPORT_CONTROL_* bits are negated */ if (spi_cs_bit == PARPORT_CONTROL_INIT) value = !value; /* here, value == "bit value to write in control register" */ parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); }
static void butterfly_attach(struct parport *p) { struct pardevice *pd; int status; struct butterfly *pp; struct spi_master *master; struct device *dev = p->physport->dev; if (butterfly || !dev) return; /* REVISIT: this just _assumes_ a butterfly is there ... no probe, * and no way to be selective about what it binds to. */ master = spi_alloc_master(dev, sizeof *pp); if (!master) { status = -ENOMEM; goto done; } pp = spi_master_get_devdata(master); /* * SPI and bitbang hookup * * use default setup(), cleanup(), and transfer() methods; and * only bother implementing mode 0. Start it later. */ master->bus_num = 42; master->num_chipselect = 2; pp->bitbang.master = spi_master_get(master); pp->bitbang.chipselect = butterfly_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; /* * parport hookup */ pp->port = p; pd = parport_register_device(p, "spi_butterfly", NULL, NULL, NULL, 0 /* FLAGS */, pp); if (!pd) { status = -ENOMEM; goto clean0; } pp->pd = pd; status = parport_claim(pd); if (status < 0) goto clean1; /* * Butterfly reset, powerup, run firmware */ pr_debug("%s: powerup/reset Butterfly\n", p->name); /* nCS for dataflash (this bit is inverted on output) */ parport_frob_control(pp->port, spi_cs_bit, 0); /* stabilize power with chip in reset (nRESET), and * spi_sck_bit clear (CPOL=0) */ pp->lastbyte |= vcc_bits; parport_write_data(pp->port, pp->lastbyte); msleep(5); /* take it out of reset; assume long reset delay */ pp->lastbyte |= butterfly_nreset; parport_write_data(pp->port, pp->lastbyte); msleep(100); /* * Start SPI ... for now, hide that we're two physical busses. */ status = spi_bitbang_start(&pp->bitbang); if (status < 0) goto clean2; /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR * (firmware resets at45, acts as spi slave) or neither (we ignore * both, AVR uses AT45). Here we expect firmware for the first option. */ pp->info[0].max_speed_hz = 15 * 1000 * 1000; strcpy(pp->info[0].modalias, "mtd_dataflash"); pp->info[0].platform_data = &flash; pp->info[0].chip_select = 1; pp->info[0].controller_data = pp; pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); if (pp->dataflash) pr_debug("%s: dataflash at %s\n", p->name, dev_name(&pp->dataflash->dev)); // dev_info(_what?_, ...) pr_info("%s: AVR Butterfly\n", p->name); butterfly = pp; return; clean2: /* turn off VCC */ parport_write_data(pp->port, 0); parport_release(pp->pd); clean1: parport_unregister_device(pd); clean0: (void) spi_master_put(pp->bitbang.master); done: pr_debug("%s: butterfly probe, fail %d\n", p->name, status); }
int parport_negotiate (struct parport *port, int mode) { #ifndef CONFIG_PARPORT_1284 if (mode == IEEE1284_MODE_COMPAT) return 0; printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n"); return -1; #else int m = mode & ~IEEE1284_ADDR; int r; unsigned char xflag; port = port->physport; /* Is there anything to do? */ if (port->ieee1284.mode == mode) return 0; /* Is the difference just an address-or-not bit? */ if ((port->ieee1284.mode & ~IEEE1284_ADDR) == (mode & ~IEEE1284_ADDR)){ port->ieee1284.mode = mode; return 0; } /* Go to compability forward idle mode */ if (port->ieee1284.mode != IEEE1284_MODE_COMPAT) parport_ieee1284_terminate (port); if (mode == IEEE1284_MODE_COMPAT) /* Compatibility mode: no negotiation. */ return 0; switch (mode) { case IEEE1284_MODE_ECPSWE: m = IEEE1284_MODE_ECP; break; case IEEE1284_MODE_EPPSL: case IEEE1284_MODE_EPPSWE: m = IEEE1284_MODE_EPP; break; case IEEE1284_MODE_BECP: return -ENOSYS; /* FIXME (implement BECP) */ } if (mode & IEEE1284_EXT_LINK) m = 1<<7; /* request extensibility link */ port->ieee1284.phase = IEEE1284_PH_NEGOTIATION; /* Start off with nStrobe and nAutoFd high, and nSelectIn low */ parport_frob_control (port, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT, PARPORT_CONTROL_SELECT); udelay(1); /* Event 0: Set data */ parport_data_forward (port); parport_write_data (port, m); udelay (400); /* Shouldn't need to wait this long. */ /* Event 1: Set nSelectIn high, nAutoFd low */ parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); /* Event 2: PError, Select, nFault go high, nAck goes low */ if (parport_wait_peripheral (port, PARPORT_STATUS_ERROR | PARPORT_STATUS_SELECT | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_ACK, PARPORT_STATUS_ERROR | PARPORT_STATUS_SELECT | PARPORT_STATUS_PAPEROUT)) { /* Timeout */ parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_SELECT); DPRINTK (KERN_DEBUG "%s: Peripheral not IEEE1284 compliant (0x%02X)\n", port->name, parport_read_status (port)); port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return -1; /* Not IEEE1284 compliant */ } /* Event 3: Set nStrobe low */ parport_frob_control (port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); /* Event 4: Set nStrobe and nAutoFd high */ udelay (5); parport_frob_control (port, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD, 0); /* Event 6: nAck goes high */ if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK)) { /* This shouldn't really happen with a compliant device. */ DPRINTK (KERN_DEBUG "%s: Mode 0x%02x not supported? (0x%02x)\n", port->name, mode, port->ops->read_status (port)); parport_ieee1284_terminate (port); return 1; } xflag = parport_read_status (port) & PARPORT_STATUS_SELECT; /* xflag should be high for all modes other than nibble (0). */ if (mode && !xflag) { /* Mode not supported. */ DPRINTK (KERN_DEBUG "%s: Mode 0x%02x rejected by peripheral\n", port->name, mode); parport_ieee1284_terminate (port); return 1; } /* More to do if we've requested extensibility link. */ if (mode & IEEE1284_EXT_LINK) { m = mode & 0x7f; udelay (1); parport_write_data (port, m); udelay (1); /* Event 51: Set nStrobe low */ parport_frob_control (port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); /* Event 52: nAck goes low */ if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) { /* This peripheral is _very_ slow. */ DPRINTK (KERN_DEBUG "%s: Event 52 didn't happen\n", port->name); parport_ieee1284_terminate (port); return 1; } /* Event 53: Set nStrobe high */ parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); /* Event 55: nAck goes high */ if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK)) { /* This shouldn't really happen with a compliant * device. */ DPRINTK (KERN_DEBUG "%s: Mode 0x%02x not supported? (0x%02x)\n", port->name, mode, port->ops->read_status (port)); parport_ieee1284_terminate (port); return 1; } /* Event 54: Peripheral sets XFlag to reflect support */ xflag = parport_read_status (port) & PARPORT_STATUS_SELECT; /* xflag should be high. */ if (!xflag) { /* Extended mode not supported. */ DPRINTK (KERN_DEBUG "%s: Extended mode 0x%02x not " "supported\n", port->name, mode); parport_ieee1284_terminate (port); return 1; } /* Any further setup is left to the caller. */ } /* Mode is supported */ DPRINTK (KERN_DEBUG "%s: In mode 0x%02x\n", port->name, mode); port->ieee1284.mode = mode; /* But ECP is special */ if (!(mode & IEEE1284_EXT_LINK) && (m & IEEE1284_MODE_ECP)) { port->ieee1284.phase = IEEE1284_PH_ECP_SETUP; /* Event 30: Set nAutoFd low */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); /* Event 31: PError goes high. */ r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); if (r) { DPRINTK (KERN_INFO "%s: Timeout at event 31\n", port->name); } port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n", port->name); } else switch (mode) { case IEEE1284_MODE_NIBBLE: case IEEE1284_MODE_BYTE: port->ieee1284.phase = IEEE1284_PH_REV_IDLE; break; default: port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; } return 0; #endif /* IEEE1284 support */ }
/* Terminate a negotiated mode. */ static void parport_ieee1284_terminate (struct parport *port) { int r; port = port->physport; /* EPP terminates differently. */ switch (port->ieee1284.mode) { case IEEE1284_MODE_EPP: case IEEE1284_MODE_EPPSL: case IEEE1284_MODE_EPPSWE: /* Terminate from EPP mode. */ /* Event 68: Set nInit low */ parport_frob_control (port, PARPORT_CONTROL_INIT, 0); udelay (50); /* Event 69: Set nInit high, nSelectIn low */ parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT); break; case IEEE1284_MODE_ECP: case IEEE1284_MODE_ECPRLE: case IEEE1284_MODE_ECPSWE: /* In ECP we can only terminate from fwd idle phase. */ if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { /* Event 47: Set nInit high */ parport_frob_control (port, PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD); /* Event 49: PError goes high */ r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); if (r) DPRINTK (KERN_INFO "%s: Timeout at event 49\n", port->name); parport_data_forward (port); DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n", port->name); port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; } /* fall-though.. */ default: /* Terminate from all other modes. */ /* Event 22: Set nSelectIn low, nAutoFd high */ parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_SELECT); /* Event 24: nAck goes low */ r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0); if (r) DPRINTK (KERN_INFO "%s: Timeout at event 24\n", port->name); /* Event 25: Set nAutoFd low */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); /* Event 27: nAck goes high */ r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK); if (r) DPRINTK (KERN_INFO "%s: Timeout at event 27\n", port->name); /* Event 29: Set nAutoFd high */ parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); } port->ieee1284.mode = IEEE1284_MODE_COMPAT; port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; DPRINTK (KERN_DEBUG "%s: In compatibility (forward idle) mode\n", port->name); }
static int assign_addrs(struct parport *port) { unsigned char s; unsigned char daisy; int thisdev = numdevs; int detected; char *deviceid; parport_data_forward(port); parport_write_data(port, 0xaa); udelay(2); parport_write_data(port, 0x55); udelay(2); parport_write_data(port, 0x00); udelay(2); parport_write_data(port, 0xff); udelay(2); s = parport_read_status(port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK(KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n", port->name, s); return 0; } parport_write_data(port, 0x87); udelay(2); s = parport_read_status(port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK(KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n", port->name, s); return 0; } parport_write_data(port, 0x78); udelay(2); s = parport_read_status(port); for (daisy = 0; (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)) == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT) && daisy < 4; ++daisy) { parport_write_data(port, daisy); udelay(2); parport_frob_control(port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); udelay(1); parport_frob_control(port, PARPORT_CONTROL_STROBE, 0); udelay(1); add_dev(numdevs++, port, daisy); if (!(s & PARPORT_STATUS_BUSY)) break; s = parport_read_status(port); } parport_write_data(port, 0xff); udelay(2); detected = numdevs - thisdev; DPRINTK(KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name, detected); deviceid = kmalloc(1024, GFP_KERNEL); if (!deviceid) return 0; for (daisy = 0; thisdev < numdevs; thisdev++, daisy++) parport_device_id(thisdev, deviceid, 1024); kfree(deviceid); return detected; }
static void butterfly_attach(struct parport *p) { struct pardevice *pd; int status; struct butterfly *pp; struct spi_master *master; struct device *dev = p->physport->dev; if (butterfly || !dev) return; master = spi_alloc_master(dev, sizeof *pp); if (!master) { status = -ENOMEM; goto done; } pp = spi_master_get_devdata(master); master->bus_num = 42; master->num_chipselect = 2; pp->bitbang.master = spi_master_get(master); pp->bitbang.chipselect = butterfly_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; pp->port = p; pd = parport_register_device(p, "spi_butterfly", NULL, NULL, NULL, 0 , pp); if (!pd) { status = -ENOMEM; goto clean0; } pp->pd = pd; status = parport_claim(pd); if (status < 0) goto clean1; pr_debug("%s: powerup/reset Butterfly\n", p->name); parport_frob_control(pp->port, spi_cs_bit, 0); pp->lastbyte |= vcc_bits; parport_write_data(pp->port, pp->lastbyte); msleep(5); pp->lastbyte |= butterfly_nreset; parport_write_data(pp->port, pp->lastbyte); msleep(100); status = spi_bitbang_start(&pp->bitbang); if (status < 0) goto clean2; pp->info[0].max_speed_hz = 15 * 1000 * 1000; strcpy(pp->info[0].modalias, "mtd_dataflash"); pp->info[0].platform_data = &flash; pp->info[0].chip_select = 1; pp->info[0].controller_data = pp; pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); if (pp->dataflash) pr_debug("%s: dataflash at %s\n", p->name, dev_name(&pp->dataflash->dev)); pr_info("%s: AVR Butterfly\n", p->name); butterfly = pp; return; clean2: parport_write_data(pp->port, 0); parport_release(pp->pd); clean1: parport_unregister_device(pd); clean0: (void) spi_master_put(pp->bitbang.master); done: pr_debug("%s: butterfly probe, fail %d\n", p->name, status); }
static int assign_addrs(struct parport *port) { unsigned char s; unsigned char daisy; int thisdev = numdevs; int detected; char *deviceid; parport_data_forward(port); parport_write_data(port, 0xaa); udelay(2); parport_write_data(port, 0x55); udelay(2); parport_write_data(port, 0x00); udelay(2); parport_write_data(port, 0xff); udelay(2); s = parport_read_status(port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK(KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n", port->name, s); return 0; } parport_write_data(port, 0x87); udelay(2); s = parport_read_status(port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK(KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n", port->name, s); return 0; } parport_write_data(port, 0x78); udelay(2); s = parport_read_status(port); for (daisy = 0; (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)) == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT) && daisy < 4; ++daisy) { parport_write_data(port, daisy); udelay(2); parport_frob_control(port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); udelay(1); parport_frob_control(port, PARPORT_CONTROL_STROBE, 0); udelay(1); add_dev(numdevs++, port, daisy); /* See if this device thought it was the last in the * chain. */ if (!(s & PARPORT_STATUS_BUSY)) break; /* We are seeing pass through status now. We see last_dev from next device or if last_dev does not work status lines from some non-daisy chain device. */ s = parport_read_status(port); } parport_write_data(port, 0xff); udelay(2); detected = numdevs - thisdev; DPRINTK(KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name, detected); /* Ask the new devices to introduce themselves. */ deviceid = kmalloc(1024, GFP_KERNEL); if (!deviceid) return 0; for (daisy = 0; thisdev < numdevs; thisdev++, daisy++) parport_device_id(thisdev, deviceid, 1024); kfree(deviceid); return detected; }
static int assign_addrs (struct parport *port) { unsigned char s, last_dev; unsigned char daisy; int thisdev = numdevs; int detected; char *deviceid; parport_data_forward (port); parport_write_data (port, 0xaa); udelay (2); parport_write_data (port, 0x55); udelay (2); parport_write_data (port, 0x00); udelay (2); parport_write_data (port, 0xff); udelay (2); s = parport_read_status (port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n", port->name, s); return 0; } parport_write_data (port, 0x87); udelay (2); s = parport_read_status (port) & (PARPORT_STATUS_BUSY | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR); if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) { DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n", port->name, s); return 0; } parport_write_data (port, 0x78); udelay (2); last_dev = 0; /* We've just been speaking to a device, so we know there must be at least _one_ out there. */ for (daisy = 0; daisy < 4; daisy++) { parport_write_data (port, daisy); udelay (2); parport_frob_control (port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); udelay (1); parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); udelay (1); if (last_dev) /* No more devices. */ break; last_dev = !(parport_read_status (port) & PARPORT_STATUS_BUSY); add_dev (numdevs++, port, daisy); } parport_write_data (port, 0xff); udelay (2); detected = numdevs - thisdev; DPRINTK (KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name, detected); /* Ask the new devices to introduce themselves. */ deviceid = kmalloc (1000, GFP_KERNEL); if (!deviceid) return 0; for (daisy = 0; thisdev < numdevs; thisdev++, daisy++) parport_device_id (thisdev, deviceid, 1000); kfree (deviceid); return detected; }
int parport_negotiate (struct parport *port, int mode) { #ifndef CONFIG_PARPORT_1284 if (mode == IEEE1284_MODE_COMPAT) return 0; printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n"); return -1; #else int m = mode & ~IEEE1284_ADDR; int r; unsigned char xflag; port = port->physport; if (port->ieee1284.mode == mode) return 0; if ((port->ieee1284.mode & ~IEEE1284_ADDR) == (mode & ~IEEE1284_ADDR)){ port->ieee1284.mode = mode; return 0; } if (port->ieee1284.mode != IEEE1284_MODE_COMPAT) parport_ieee1284_terminate (port); if (mode == IEEE1284_MODE_COMPAT) return 0; switch (mode) { case IEEE1284_MODE_ECPSWE: m = IEEE1284_MODE_ECP; break; case IEEE1284_MODE_EPPSL: case IEEE1284_MODE_EPPSWE: m = IEEE1284_MODE_EPP; break; case IEEE1284_MODE_BECP: return -ENOSYS; } if (mode & IEEE1284_EXT_LINK) m = 1<<7; port->ieee1284.phase = IEEE1284_PH_NEGOTIATION; parport_frob_control (port, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT, PARPORT_CONTROL_SELECT); udelay(1); parport_data_forward (port); parport_write_data (port, m); udelay (400); parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); if (parport_wait_peripheral (port, PARPORT_STATUS_ERROR | PARPORT_STATUS_SELECT | PARPORT_STATUS_PAPEROUT | PARPORT_STATUS_ACK, PARPORT_STATUS_ERROR | PARPORT_STATUS_SELECT | PARPORT_STATUS_PAPEROUT)) { parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_SELECT); DPRINTK (KERN_DEBUG "%s: Peripheral not IEEE1284 compliant (0x%02X)\n", port->name, parport_read_status (port)); port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return -1; } parport_frob_control (port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); udelay (5); parport_frob_control (port, PARPORT_CONTROL_STROBE | PARPORT_CONTROL_AUTOFD, 0); if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK)) { DPRINTK (KERN_DEBUG "%s: Mode 0x%02x not supported? (0x%02x)\n", port->name, mode, port->ops->read_status (port)); parport_ieee1284_terminate (port); return 1; } xflag = parport_read_status (port) & PARPORT_STATUS_SELECT; if (mode && !xflag) { DPRINTK (KERN_DEBUG "%s: Mode 0x%02x rejected by peripheral\n", port->name, mode); parport_ieee1284_terminate (port); return 1; } if (mode & IEEE1284_EXT_LINK) { m = mode & 0x7f; udelay (1); parport_write_data (port, m); udelay (1); parport_frob_control (port, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) { DPRINTK (KERN_DEBUG "%s: Event 52 didn't happen\n", port->name); parport_ieee1284_terminate (port); return 1; } parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK)) { DPRINTK (KERN_DEBUG "%s: Mode 0x%02x not supported? (0x%02x)\n", port->name, mode, port->ops->read_status (port)); parport_ieee1284_terminate (port); return 1; } xflag = parport_read_status (port) & PARPORT_STATUS_SELECT; if (!xflag) { DPRINTK (KERN_DEBUG "%s: Extended mode 0x%02x not " "supported\n", port->name, mode); parport_ieee1284_terminate (port); return 1; } } DPRINTK (KERN_DEBUG "%s: In mode 0x%02x\n", port->name, mode); port->ieee1284.mode = mode; if (!(mode & IEEE1284_EXT_LINK) && (m & IEEE1284_MODE_ECP)) { port->ieee1284.phase = IEEE1284_PH_ECP_SETUP; parport_frob_control (port, PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); if (r) { DPRINTK (KERN_INFO "%s: Timeout at event 31\n", port->name); } port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n", port->name); } else switch (mode) { case IEEE1284_MODE_NIBBLE: case IEEE1284_MODE_BYTE: port->ieee1284.phase = IEEE1284_PH_REV_IDLE; break; default: port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; } return 0; #endif }
static void parport_ieee1284_terminate (struct parport *port) { int r; port = port->physport; switch (port->ieee1284.mode) { case IEEE1284_MODE_EPP: case IEEE1284_MODE_EPPSL: case IEEE1284_MODE_EPPSWE: parport_frob_control (port, PARPORT_CONTROL_INIT, 0); udelay (50); parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT); break; case IEEE1284_MODE_ECP: case IEEE1284_MODE_ECPRLE: case IEEE1284_MODE_ECPSWE: if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { parport_frob_control (port, PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_INIT | PARPORT_CONTROL_AUTOFD); r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); if (r) DPRINTK (KERN_INFO "%s: Timeout at event 49\n", port->name); parport_data_forward (port); DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n", port->name); port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; } default: parport_frob_control (port, PARPORT_CONTROL_SELECT | PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_SELECT); r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0); if (r) DPRINTK (KERN_INFO "%s: Timeout at event 24\n", port->name); parport_frob_control (port, PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD); r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK); if (r) DPRINTK (KERN_INFO "%s: Timeout at event 27\n", port->name); parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); } port->ieee1284.mode = IEEE1284_MODE_COMPAT; port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; DPRINTK (KERN_DEBUG "%s: In compatibility (forward idle) mode\n", port->name); }
static void butterfly_attach(struct parport *p) { struct pardevice *pd; int status; struct butterfly *pp; struct spi_master *master; struct platform_device *pdev; if (butterfly) return; /* REVISIT: this just _assumes_ a butterfly is there ... no probe, * and no way to be selective about what it binds to. */ /* FIXME where should master->cdev.dev come from? * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc * setting up a platform device like this is an ugly kluge... */ pdev = platform_device_register_simple("butterfly", -1, NULL, 0); master = spi_alloc_master(&pdev->dev, sizeof *pp); if (!master) { status = -ENOMEM; goto done; } pp = spi_master_get_devdata(master); /* * SPI and bitbang hookup * * use default setup(), cleanup(), and transfer() methods; and * only bother implementing mode 0. Start it later. */ master->bus_num = 42; master->num_chipselect = 2; pp->bitbang.master = spi_master_get(master); pp->bitbang.chipselect = butterfly_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; /* * parport hookup */ pp->port = p; pd = parport_register_device(p, "spi_butterfly", NULL, NULL, NULL, 0 /* FLAGS */, pp); if (!pd) { status = -ENOMEM; goto clean0; } pp->pd = pd; status = parport_claim(pd); if (status < 0) goto clean1; /* * Butterfly reset, powerup, run firmware */ pr_debug("%s: powerup/reset Butterfly\n", p->name); /* nCS for dataflash (this bit is inverted on output) */ parport_frob_control(pp->port, spi_cs_bit, 0); /* stabilize power with chip in reset (nRESET), and * both spi_sck_bit and usi_sck_bit clear (CPOL=0) */ pp->lastbyte |= vcc_bits; parport_write_data(pp->port, pp->lastbyte); msleep(5); /* take it out of reset; assume long reset delay */ pp->lastbyte |= butterfly_nreset; parport_write_data(pp->port, pp->lastbyte); msleep(100); /* * Start SPI ... for now, hide that we're two physical busses. */ status = spi_bitbang_start(&pp->bitbang); if (status < 0) goto clean2; /* Bus 1 lets us talk to at45db041b (firmware disables AVR) * or AVR (firmware resets at45, acts as spi slave) */ pp->info[0].max_speed_hz = 15 * 1000 * 1000; strcpy(pp->info[0].modalias, "mtd_dataflash"); pp->info[0].platform_data = &flash; pp->info[0].chip_select = 1; pp->info[0].controller_data = pp; pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); if (pp->dataflash) pr_debug("%s: dataflash at %s\n", p->name, pp->dataflash->dev.bus_id); #ifdef HAVE_USI /* even more custom AVR firmware */ pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; strcpy(pp->info[1].modalias, "butterfly"); // pp->info[1].platform_data = ... TBD ... ; pp->info[1].chip_select = 2, pp->info[1].controller_data = pp; pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]); if (pp->butterfly) pr_debug("%s: butterfly at %s\n", p->name, pp->butterfly->dev.bus_id); /* FIXME setup ACK for the IRQ line ... */ #endif // dev_info(_what?_, ...) pr_info("%s: AVR Butterfly\n", p->name); butterfly = pp; return; clean2: /* turn off VCC */ parport_write_data(pp->port, 0); parport_release(pp->pd); clean1: parport_unregister_device(pd); clean0: (void) spi_master_put(pp->bitbang.master); done: platform_device_unregister(pdev); pr_debug("%s: butterfly probe, fail %d\n", p->name, status); }