diff options
Diffstat (limited to 'drivers/sbus')
26 files changed, 794 insertions, 7911 deletions
diff --git a/drivers/sbus/Makefile b/drivers/sbus/Makefile index 7b1d24d9530..e94dc25805f 100644 --- a/drivers/sbus/Makefile +++ b/drivers/sbus/Makefile @@ -2,8 +2,4 @@ # Makefile for the linux kernel. # -ifneq ($(ARCH),m68k) -obj-y := sbus.o dvma.o -endif - obj-$(CONFIG_SBUSCHAR) += char/ diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index 3a8152906bf..5ba684f73ab 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig @@ -13,15 +13,6 @@ config SUN_OPENPROMIO If unsure, say Y. -config SUN_MOSTEK_RTC - tristate "Mostek real time clock support" - help - The Mostek RTC chip is used on all known Sun computers except - some JavaStations. For a JavaStation you need to say Y both here - and to "Enhanced Real Time Clock Support". - - Say Y here unless you are building a special purpose kernel. - config OBP_FLASH tristate "OBP Flash Device support" depends on SPARC64 @@ -29,33 +20,8 @@ config OBP_FLASH The OpenBoot PROM on Ultra systems is flashable. If you want to be able to upgrade the OBP firmware, say Y here. -config SUN_BPP - tristate "Bidirectional parallel port support (OBSOLETE)" - depends on EXPERIMENTAL - help - Say Y here to support Sun's obsolete variant of IEEE1284 - bidirectional parallel port protocol as /dev/bppX. Can be built on - x86 machines. - -config SUN_VIDEOPIX - tristate "Videopix Frame Grabber (EXPERIMENTAL)" - depends on EXPERIMENTAL && (BROKEN || !64BIT) - help - Say Y here to support the Videopix Frame Grabber from Sun - Microsystems, commonly found on SPARCstations. This card, which is - based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and - SVIDEO signals. - -config SUN_AURORA - tristate "Aurora Multiboard 1600se (EXPERIMENTAL)" - depends on EXPERIMENTAL && BROKEN - help - The Aurora Multiboard is a multi-port high-speed serial controller. - If you have one of these, say Y. - config TADPOLE_TS102_UCTRL - tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)" - depends on EXPERIMENTAL && SPARC32 + tristate "Tadpole TS102 Microcontroller support" help Say Y here to directly support the TS102 Microcontroller interface on the Tadpole Sparcbook 3. This device handles power-management @@ -63,8 +29,8 @@ config TADPOLE_TS102_UCTRL monitors and mice. config SUN_JSFLASH - tristate "JavaStation OS Flash SIMM (EXPERIMENTAL)" - depends on EXPERIMENTAL && SPARC32 + tristate "JavaStation OS Flash SIMM" + depends on SPARC32 help If you say Y here, you will be able to boot from your JavaStation's Flash memory. diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index 3a5ea1dc789..78b6183c986 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile @@ -7,19 +7,12 @@ # Rewritten to use lists instead of if-statements. # -vfc-objs := vfc_dev.o vfc_i2c.o bbc-objs := bbc_i2c.o bbc_envctrl.o obj-$(CONFIG_ENVCTRL) += envctrl.o obj-$(CONFIG_DISPLAY7SEG) += display7seg.o -obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwatchdog.o -obj-$(CONFIG_WATCHDOG_RIO) += riowatchdog.o obj-$(CONFIG_OBP_FLASH) += flash.o obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o -obj-$(CONFIG_SUN_MOSTEK_RTC) += rtc.o -obj-$(CONFIG_SUN_BPP) += bpp.o -obj-$(CONFIG_SUN_VIDEOPIX) += vfc.o -obj-$(CONFIG_SUN_AURORA) += aurora.o obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o obj-$(CONFIG_SUN_JSFLASH) += jsflash.o obj-$(CONFIG_BBC_I2C) += bbc.o diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c deleted file mode 100644 index 4fdb2c93221..00000000000 --- a/drivers/sbus/char/aurora.c +++ /dev/null @@ -1,2364 +0,0 @@ -/* $Id: aurora.c,v 1.19 2002/01/08 16:00:16 davem Exp $ - * linux/drivers/sbus/char/aurora.c -- Aurora multiport driver - * - * Copyright (c) 1999 by Oliver Aldulea (oli at bv dot ro) - * - * This code is based on the RISCom/8 multiport serial driver written - * by Dmitry Gorodchanin (pgmdsg@ibi.com), based on the Linux serial - * driver, written by Linus Torvalds, Theodore T'so and others. - * The Aurora multiport programming info was obtained mainly from the - * Cirrus Logic CD180 documentation (available on the web), and by - * doing heavy tests on the board. Many thanks to Eddie C. Dost for the - * help on the sbus interface. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Revision 1.0 - * - * This is the first public release. - * - * Most of the information you need is in the aurora.h file. Please - * read that file before reading this one. - * - * Several parts of the code do not have comments yet. - * - * n.b. The board can support 115.2 bit rates, but only on a few - * ports. The total badwidth of one chip (ports 0-7 or 8-15) is equal - * to OSC_FREQ div 16. In case of my board, each chip can take 6 - * channels of 115.2 kbaud. This information is not well-tested. - * - * Fixed to use tty_get_baud_rate(). - * Theodore Ts'o <tytso@mit.edu>, 2001-Oct-12 - */ - -#include <linux/module.h> - -#include <linux/errno.h> -#include <linux/sched.h> -#ifdef AURORA_INT_DEBUG -#include <linux/timer.h> -#endif -#include <linux/interrupt.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/major.h> -#include <linux/string.h> -#include <linux/fcntl.h> -#include <linux/mm.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/bitops.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/oplib.h> -#include <asm/system.h> -#include <asm/kdebug.h> -#include <asm/sbus.h> -#include <asm/uaccess.h> - -#include "aurora.h" -#include "cd180.h" - -unsigned char irqs[4] = { - 0, 0, 0, 0 -}; - -#ifdef AURORA_INT_DEBUG -int irqhit=0; -#endif - -static struct tty_driver *aurora_driver; -static struct Aurora_board aurora_board[AURORA_NBOARD] = { - {0,}, -}; - -static struct Aurora_port aurora_port[AURORA_TNPORTS] = { - { 0, }, -}; - -/* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ -static unsigned char * tmp_buf = NULL; - -DECLARE_TASK_QUEUE(tq_aurora); - -static inline int aurora_paranoia_check(struct Aurora_port const * port, - char *name, const char *routine) -{ -#ifdef AURORA_PARANOIA_CHECK - static const char *badmagic = - KERN_DEBUG "aurora: Warning: bad aurora port magic number for device %s in %s\n"; - static const char *badinfo = - KERN_DEBUG "aurora: Warning: null aurora port for device %s in %s\n"; - - if (!port) { - printk(badinfo, name, routine); - return 1; - } - if (port->magic != AURORA_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -/* - * - * Service functions for aurora driver. - * - */ - -/* Get board number from pointer */ -static inline int board_No (struct Aurora_board const * bp) -{ - return bp - aurora_board; -} - -/* Get port number from pointer */ -static inline int port_No (struct Aurora_port const * port) -{ - return AURORA_PORT(port - aurora_port); -} - -/* Get pointer to board from pointer to port */ -static inline struct Aurora_board * port_Board(struct Aurora_port const * port) -{ - return &aurora_board[AURORA_BOARD(port - aurora_port)]; -} - -/* Wait for Channel Command Register ready */ -static inline void aurora_wait_CCR(struct aurora_reg128 * r) -{ - unsigned long delay; - -#ifdef AURORA_DEBUG -printk("aurora_wait_CCR\n"); -#endif - /* FIXME: need something more descriptive than 100000 :) */ - for (delay = 100000; delay; delay--) - if (!sbus_readb(&r->r[CD180_CCR])) - return; - printk(KERN_DEBUG "aurora: Timeout waiting for CCR.\n"); -} - -/* - * aurora probe functions. - */ - -/* Must be called with enabled interrupts */ -static inline void aurora_long_delay(unsigned long delay) -{ - unsigned long i; - -#ifdef AURORA_DEBUG - printk("aurora_long_delay: start\n"); -#endif - for (i = jiffies + delay; time_before(jiffies, i); ) ; -#ifdef AURORA_DEBUG - printk("aurora_long_delay: end\n"); -#endif -} - -/* Reset and setup CD180 chip */ -static int aurora_init_CD180(struct Aurora_board * bp, int chip) -{ - unsigned long flags; - int id; - -#ifdef AURORA_DEBUG - printk("aurora_init_CD180: start %d:%d\n", - board_No(bp), chip); -#endif - save_flags(flags); cli(); - sbus_writeb(0, &bp->r[chip]->r[CD180_CAR]); - sbus_writeb(0, &bp->r[chip]->r[CD180_GSVR]); - - /* Wait for CCR ready */ - aurora_wait_CCR(bp->r[chip]); - - /* Reset CD180 chip */ - sbus_writeb(CCR_HARDRESET, &bp->r[chip]->r[CD180_CCR]); - udelay(1); - sti(); - id=1000; - while((--id) && - (sbus_readb(&bp->r[chip]->r[CD180_GSVR])!=0xff))udelay(100); - if(!id) { - printk(KERN_ERR "aurora%d: Chip %d failed init.\n", - board_No(bp), chip); - restore_flags(flags); - return(-1); - } - cli(); - sbus_writeb((board_No(bp)<<5)|((chip+1)<<3), - &bp->r[chip]->r[CD180_GSVR]); /* Set ID for this chip */ - sbus_writeb(0x80|bp->ACK_MINT, - &bp->r[chip]->r[CD180_MSMR]); /* Prio for modem intr */ - sbus_writeb(0x80|bp->ACK_TINT, - &bp->r[chip]->r[CD180_TSMR]); /* Prio for transmitter intr */ - sbus_writeb(0x80|bp->ACK_RINT, - &bp->r[chip]->r[CD180_RSMR]); /* Prio for receiver intr */ - /* Setting up prescaler. We need 4 tick per 1 ms */ - sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) >> 8, - &bp->r[chip]->r[CD180_PPRH]); - sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) & 0xff, - &bp->r[chip]->r[CD180_PPRL]); - - sbus_writeb(SRCR_AUTOPRI|SRCR_GLOBPRI, - &bp->r[chip]->r[CD180_SRCR]); - - id = sbus_readb(&bp->r[chip]->r[CD180_GFRCR]); - printk(KERN_INFO "aurora%d: Chip %d id %02x: ", - board_No(bp), chip,id); - if(sbus_readb(&bp->r[chip]->r[CD180_SRCR]) & 128) { - switch (id) { - case 0x82:printk("CL-CD1864 rev A\n");break; - case 0x83:printk("CL-CD1865 rev A\n");break; - case 0x84:printk("CL-CD1865 rev B\n");break; - case 0x85:printk("CL-CD1865 rev C\n");break; - default:printk("Unknown.\n"); - }; - } else { - switch (id) { - case 0x81:printk("CL-CD180 rev B\n");break; - case 0x82:printk("CL-CD180 rev C\n");break; - default:printk("Unknown.\n"); - }; - } - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_init_CD180: end\n"); -#endif - return 0; -} - -static int valid_irq(unsigned char irq) -{ -int i; -for(i=0;i<TYPE_1_IRQS;i++) - if (type_1_irq[i]==irq) return 1; -return 0; -} - -static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs); - -/* Main probing routine, also sets irq. */ -static int aurora_probe(void) -{ - struct sbus_bus *sbus; - struct sbus_dev *sdev; - int grrr; - char buf[30]; - int bn = 0; - struct Aurora_board *bp; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { -/* printk("Try: %x %s\n",sdev,sdev->prom_name);*/ - if (!strcmp(sdev->prom_name, "sio16")) { -#ifdef AURORA_DEBUG - printk(KERN_INFO "aurora: sio16 at %p\n",sdev); -#endif - if((sdev->reg_addrs[0].reg_size!=1) && - (sdev->reg_addrs[1].reg_size!=128) && - (sdev->reg_addrs[2].reg_size!=128) && - (sdev->reg_addrs[3].reg_size!=4)) { - printk(KERN_ERR "aurora%d: registers' sizes " - "do not match.\n", bn); - break; - } - bp = &aurora_board[bn]; - bp->r0 = (struct aurora_reg1 *) - sbus_ioremap(&sdev->resource[0], 0, - sdev->reg_addrs[0].reg_size, - "sio16"); - if (bp->r0 == NULL) { - printk(KERN_ERR "aurora%d: can't map " - "reg_addrs[0]\n", bn); - break; - } -#ifdef AURORA_DEBUG - printk("Map reg 0: %p\n", bp->r0); -#endif - bp->r[0] = (struct aurora_reg128 *) - sbus_ioremap(&sdev->resource[1], 0, - sdev->reg_addrs[1].reg_size, - "sio16"); - if (bp->r[0] == NULL) { - printk(KERN_ERR "aurora%d: can't map " - "reg_addrs[1]\n", bn); - break; - } -#ifdef AURORA_DEBUG - printk("Map reg 1: %p\n", bp->r[0]); -#endif - bp->r[1] = (struct aurora_reg128 *) - sbus_ioremap(&sdev->resource[2], 0, - sdev->reg_addrs[2].reg_size, - "sio16"); - if (bp->r[1] == NULL) { - printk(KERN_ERR "aurora%d: can't map " - "reg_addrs[2]\n", bn); - break; - } -#ifdef AURORA_DEBUG - printk("Map reg 2: %p\n", bp->r[1]); -#endif - bp->r3 = (struct aurora_reg4 *) - sbus_ioremap(&sdev->resource[3], 0, - sdev->reg_addrs[3].reg_size, - "sio16"); - if (bp->r3 == NULL) { - printk(KERN_ERR "aurora%d: can't map " - "reg_addrs[3]\n", bn); - break; - } -#ifdef AURORA_DEBUG - printk("Map reg 3: %p\n", bp->r3); -#endif - /* Variables setup */ - bp->flags = 0; -#ifdef AURORA_DEBUG - grrr=prom_getint(sdev->prom_node,"intr"); - printk("intr pri %d\n", grrr); -#endif - if ((bp->irq=irqs[bn]) && valid_irq(bp->irq) && - !request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) { - free_irq(bp->irq|0x30, bp); - } else - if ((bp->irq=prom_getint(sdev->prom_node, "bintr")) && valid_irq(bp->irq) && - !request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) { - free_irq(bp->irq|0x30, bp); - } else - if ((bp->irq=prom_getint(sdev->prom_node, "intr")) && valid_irq(bp->irq) && - !request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) { - free_irq(bp->irq|0x30, bp); - } else - for(grrr=0;grrr<TYPE_1_IRQS;grrr++) { - if ((bp->irq=type_1_irq[grrr])&&!request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, "sio16", bp)) { - free_irq(bp->irq|0x30, bp); - break; - } else { - printk(KERN_ERR "aurora%d: Could not get an irq for this board !!!\n",bn); - bp->flags=0xff; - } - } - if(bp->flags==0xff)break; - printk(KERN_INFO "aurora%d: irq %d\n",bn,bp->irq&0x0f); - buf[0]=0; - grrr=prom_getproperty(sdev->prom_node,"dtr_rts",buf,sizeof(buf)); - if(!strcmp(buf,"swapped")){ - printk(KERN_INFO "aurora%d: Swapped DTR and RTS\n",bn); - bp->DTR=MSVR_RTS; - bp->RTS=MSVR_DTR; - bp->MSVDTR=CD180_MSVRTS; - bp->MSVRTS=CD180_MSVDTR; - bp->flags|=AURORA_BOARD_DTR_FLOW_OK; - }else{ - #ifdef AURORA_FORCE_DTR_FLOW - printk(KERN_INFO "aurora%d: Forcing swapped DTR-RTS\n",bn); - bp->DTR=MSVR_RTS; - bp->RTS=MSVR_DTR; - bp->MSVDTR=CD180_MSVRTS; - bp->MSVRTS=CD180_MSVDTR; - bp->flags|=AURORA_BOARD_DTR_FLOW_OK; - #else - printk(KERN_INFO "aurora%d: Normal DTR and RTS\n",bn); - bp->DTR=MSVR_DTR; - bp->RTS=MSVR_RTS; - bp->MSVDTR=CD180_MSVDTR; - bp->MSVRTS=CD180_MSVRTS; - #endif - } - bp->oscfreq=prom_getint(sdev->prom_node,"clk")*100; - printk(KERN_INFO "aurora%d: Oscillator: %d Hz\n",bn,bp->oscfreq); - grrr=prom_getproperty(sdev->prom_node,"chip",buf,sizeof(buf)); - printk(KERN_INFO "aurora%d: Chips: %s\n",bn,buf); - grrr=prom_getproperty(sdev->prom_node,"manu",buf,sizeof(buf)); - printk(KERN_INFO "aurora%d: Manufacturer: %s\n",bn,buf); - grrr=prom_getproperty(sdev->prom_node,"model",buf,sizeof(buf)); - printk(KERN_INFO "aurora%d: Model: %s\n",bn,buf); - grrr=prom_getproperty(sdev->prom_node,"rev",buf,sizeof(buf)); - printk(KERN_INFO "aurora%d: Revision: %s\n",bn,buf); - grrr=prom_getproperty(sdev->prom_node,"mode",buf,sizeof(buf)); - printk(KERN_INFO "aurora%d: Mode: %s\n",bn,buf); - #ifdef MODULE - bp->count=0; - #endif - bp->flags = AURORA_BOARD_PRESENT; - /* hardware ack */ - bp->ACK_MINT=1; - bp->ACK_TINT=2; - bp->ACK_RINT=3; - bn++; - } - } - } - return bn; -} - -static void aurora_release_io_range(struct Aurora_board *bp) -{ - sbus_iounmap((unsigned long)bp->r0, 1); - sbus_iounmap((unsigned long)bp->r[0], 128); - sbus_iounmap((unsigned long)bp->r[1], 128); - sbus_iounmap((unsigned long)bp->r3, 4); -} - -static inline void aurora_mark_event(struct Aurora_port * port, int event) -{ -#ifdef AURORA_DEBUG - printk("aurora_mark_event: start\n"); -#endif - set_bit(event, &port->event); - queue_task(&port->tqueue, &tq_aurora); - mark_bh(AURORA_BH); -#ifdef AURORA_DEBUG - printk("aurora_mark_event: end\n"); -#endif -} - -static __inline__ struct Aurora_port * aurora_get_port(struct Aurora_board const * bp, - int chip, - unsigned char const *what) -{ - unsigned char channel; - struct Aurora_port * port; - - channel = ((chip << 3) | - ((sbus_readb(&bp->r[chip]->r[CD180_GSCR]) & GSCR_CHAN) >> GSCR_CHAN_OFF)); - port = &aurora_port[board_No(bp) * AURORA_NPORT * AURORA_NCD180 + channel]; - if (port->flags & ASYNC_INITIALIZED) - return port; - - printk(KERN_DEBUG "aurora%d: %s interrupt from invalid port %d\n", - board_No(bp), what, channel); - return NULL; -} - -static void aurora_receive_exc(struct Aurora_board const * bp, int chip) -{ - struct Aurora_port *port; - struct tty_struct *tty; - unsigned char status; - unsigned char ch; - - if (!(port = aurora_get_port(bp, chip, "Receive_x"))) - return; - - tty = port->tty; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { -#ifdef AURORA_INTNORM - printk("aurora%d: port %d: Working around flip buffer overflow.\n", - board_No(bp), port_No(port)); -#endif - return; - } - -#ifdef AURORA_REPORT_OVERRUN - status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]); - if (status & RCSR_OE) { - port->overrun++; -#if 1 - printk("aurora%d: port %d: Overrun. Total %ld overruns.\n", - board_No(bp), port_No(port), port->overrun); -#endif - } - status &= port->mark_mask; -#else - status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]) & port->mark_mask; -#endif - ch = sbus_readb(&bp->r[chip]->r[CD180_RDR]); - if (!status) - return; - - if (status & RCSR_TOUT) { -/* printk("aurora%d: port %d: Receiver timeout. Hardware problems ?\n", - board_No(bp), port_No(port));*/ - return; - - } else if (status & RCSR_BREAK) { - printk(KERN_DEBUG "aurora%d: port %d: Handling break...\n", - board_No(bp), port_No(port)); - *tty->flip.flag_buf_ptr++ = TTY_BREAK; - if (port->flags & ASYNC_SAK) - do_SAK(tty); - - } else if (status & RCSR_PE) - *tty->flip.flag_buf_ptr++ = TTY_PARITY; - - else if (status & RCSR_FE) - *tty->flip.flag_buf_ptr++ = TTY_FRAME; - - else if (status & RCSR_OE) - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - - else - *tty->flip.flag_buf_ptr++ = 0; - - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - queue_task(&tty->flip.tqueue, &tq_timer); -} - -static void aurora_receive(struct Aurora_board const * bp, int chip) -{ - struct Aurora_port *port; - struct tty_struct *tty; - unsigned char count,cnt; - - if (!(port = aurora_get_port(bp, chip, "Receive"))) - return; - - tty = port->tty; - - count = sbus_readb(&bp->r[chip]->r[CD180_RDCR]); - -#ifdef AURORA_REPORT_FIFO - port->hits[count > 8 ? 9 : count]++; -#endif - - while (count--) { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { -#ifdef AURORA_INTNORM - printk("aurora%d: port %d: Working around flip buffer overflow.\n", - board_No(bp), port_No(port)); -#endif - break; - } - cnt = sbus_readb(&bp->r[chip]->r[CD180_RDR]); - *tty->flip.char_buf_ptr++ = cnt; - *tty->flip.flag_buf_ptr++ = 0; - tty->flip.count++; - } - queue_task(&tty->flip.tqueue, &tq_timer); -} - -static void aurora_transmit(struct Aurora_board const * bp, int chip) -{ - struct Aurora_port *port; - struct tty_struct *tty; - unsigned char count; - - if (!(port = aurora_get_port(bp, chip, "Transmit"))) - return; - - tty = port->tty; - - if (port->SRER & SRER_TXEMPTY) { - /* FIFO drained */ - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - port->SRER &= ~SRER_TXEMPTY; - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - return; - } - - if ((port->xmit_cnt <= 0 && !port->break_length) - || tty->stopped || tty->hw_stopped) { - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - port->SRER &= ~SRER_TXRDY; - sbus_writeb(port->SRER, - &bp->r[chip]->r[CD180_SRER]); - return; - } - - if (port->break_length) { - if (port->break_length > 0) { - if (port->COR2 & COR2_ETC) { - sbus_writeb(CD180_C_ESC, - &bp->r[chip]->r[CD180_TDR]); - sbus_writeb(CD180_C_SBRK, - &bp->r[chip]->r[CD180_TDR]); - port->COR2 &= ~COR2_ETC; - } - count = min(port->break_length, 0xff); - sbus_writeb(CD180_C_ESC, - &bp->r[chip]->r[CD180_TDR]); - sbus_writeb(CD180_C_DELAY, - &bp->r[chip]->r[CD180_TDR]); - sbus_writeb(count, - &bp->r[chip]->r[CD180_TDR]); - if (!(port->break_length -= count)) - port->break_length--; - } else { - sbus_writeb(CD180_C_ESC, - &bp->r[chip]->r[CD180_TDR]); - sbus_writeb(CD180_C_EBRK, - &bp->r[chip]->r[CD180_TDR]); - sbus_writeb(port->COR2, - &bp->r[chip]->r[CD180_COR2]); - aurora_wait_CCR(bp->r[chip]); - sbus_writeb(CCR_CORCHG2, - &bp->r[chip]->r[CD180_CCR]); - port->break_length = 0; - } - return; - } - - count = CD180_NFIFO; - do { - u8 byte = port->xmit_buf[port->xmit_tail++]; - - sbus_writeb(byte, &bp->r[chip]->r[CD180_TDR]); - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1); - if (--port->xmit_cnt <= 0) - break; - } while (--count > 0); - - if (port->xmit_cnt <= 0) { - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - port->SRER &= ~SRER_TXRDY; - sbus_writeb(port->SRER, - &bp->r[chip]->r[CD180_SRER]); - } - if (port->xmit_cnt <= port->wakeup_chars) - aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP); -} - -static void aurora_check_modem(struct Aurora_board const * bp, int chip) -{ - struct Aurora_port *port; - struct tty_struct *tty; - unsigned char mcr; - - if (!(port = aurora_get_port(bp, chip, "Modem"))) - return; - - tty = port->tty; - - mcr = sbus_readb(&bp->r[chip]->r[CD180_MCR]); - if (mcr & MCR_CDCHG) { - if (sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD) - wake_up_interruptible(&port->open_wait); - else - schedule_task(&port->tqueue_hangup); - } - -/* We don't have such things yet. My aurora board has DTR and RTS swapped, but that doesn't count in this driver. Let's hope - * Aurora didn't made any boards with CTS or DSR broken... - */ -/* #ifdef AURORA_BRAIN_DAMAGED_CTS - if (mcr & MCR_CTSCHG) { - if (aurora_in(bp, CD180_MSVR) & MSVR_CTS) { - tty->hw_stopped = 0; - port->SRER |= SRER_TXRDY; - if (port->xmit_cnt <= port->wakeup_chars) - aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP); - } else { - tty->hw_stopped = 1; - port->SRER &= ~SRER_TXRDY; - } - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - } - if (mcr & MCR_DSRCHG) { - if (aurora_in(bp, CD180_MSVR) & MSVR_DSR) { - tty->hw_stopped = 0; - port->SRER |= SRER_TXRDY; - if (port->xmit_cnt <= port->wakeup_chars) - aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP); - } else { - tty->hw_stopped = 1; - port->SRER &= ~SRER_TXRDY; - } - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - } -#endif AURORA_BRAIN_DAMAGED_CTS */ - - /* Clear change bits */ - sbus_writeb(0, &bp->r[chip]->r[CD180_MCR]); -} - -/* The main interrupt processing routine */ -static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs) -{ - unsigned char status; - unsigned char ack,chip/*,chip_id*/; - struct Aurora_board * bp = (struct Aurora_board *) dev_id; - unsigned long loop = 0; - -#ifdef AURORA_INT_DEBUG - printk("IRQ%d %d\n",irq,++irqhit); -#ifdef AURORA_FLOODPRO - if (irqhit>=AURORA_FLOODPRO) - sbus_writeb(8, &bp->r0->r); -#endif -#endif - -/* old bp = IRQ_to_board[irq&0x0f];*/ - - if (!bp || !(bp->flags & AURORA_BOARD_ACTIVE)) - return IRQ_NONE; - -/* The while() below takes care of this. - status = sbus_readb(&bp->r[0]->r[CD180_SRSR]); -#ifdef AURORA_INT_DEBUG - printk("mumu: %02x\n", status); -#endif - if (!(status&SRSR_ANYINT)) - return IRQ_NONE; * Nobody has anything to say, so exit * -*/ - while ((loop++ < 48) && - (status = sbus_readb(&bp->r[0]->r[CD180_SRSR]) & SRSR_ANYINT)){ -#ifdef AURORA_INT_DEBUG - printk("SRSR: %02x\n", status); -#endif - if (status & SRSR_REXT) { - ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]); -#ifdef AURORA_INT_DEBUG - printk("R-ACK %02x\n", ack); -#endif - if ((ack >> 5) == board_No(bp)) { - if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { - if ((ack&GSVR_ITMASK)==GSVR_IT_RGD) { - aurora_receive(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } else if ((ack & GSVR_ITMASK) == GSVR_IT_REXC) { - aurora_receive_exc(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } - } - } - } else if (status & SRSR_TEXT) { - ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]); -#ifdef AURORA_INT_DEBUG - printk("T-ACK %02x\n", ack); -#endif - if ((ack >> 5) == board_No(bp)) { - if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { - if ((ack&GSVR_ITMASK)==GSVR_IT_TX) { - aurora_transmit(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } - } - } - } else if (status & SRSR_MEXT) { - ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]); -#ifdef AURORA_INT_DEBUG - printk("M-ACK %02x\n", ack); -#endif - if ((ack >> 5) == board_No(bp)) { - if ((chip = ((ack>>3)&3)-1) < AURORA_NCD180) { - if ((ack&GSVR_ITMASK)==GSVR_IT_MDM) { - aurora_check_modem(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } - } - } - } - } -/* I guess this faster code can be used with CD1865, using AUROPRI and GLOBPRI. */ -#if 0 - while ((loop++ < 48)&&(status=bp->r[0]->r[CD180_SRSR]&SRSR_ANYINT)){ -#ifdef AURORA_INT_DEBUG - printk("SRSR: %02x\n",status); -#endif - ack = sbus_readb(&bp->r3->r[0]); -#ifdef AURORA_INT_DEBUG - printk("ACK: %02x\n",ack); -#endif - if ((ack>>5)==board_No(bp)) { - if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) { - ack&=GSVR_ITMASK; - if (ack==GSVR_IT_RGD) { - aurora_receive(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } else if (ack==GSVR_IT_REXC) { - aurora_receive_exc(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } else if (ack==GSVR_IT_TX) { - aurora_transmit(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } else if (ack==GSVR_IT_MDM) { - aurora_check_modem(bp,chip); - sbus_writeb(0, - &bp->r[chip]->r[CD180_EOSRR]); - } - } - } - } -#endif - -/* This is the old handling routine, used in riscom8 for only one CD180. I keep it here for reference. */ -#if 0 - for(chip=0;chip<AURORA_NCD180;chip++){ - chip_id=(board_No(bp)<<5)|((chip+1)<<3); - loop=0; - while ((loop++ < 1) && - ((status = sbus_readb(&bp->r[chip]->r[CD180_SRSR])) & - (SRSR_TEXT | SRSR_MEXT | SRSR_REXT))) { - - if (status & SRSR_REXT) { - ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]); - if (ack == (chip_id | GSVR_IT_RGD)) { -#ifdef AURORA_INTMSG - printk("RX ACK\n"); -#endif - aurora_receive(bp,chip); - } else if (ack == (chip_id | GSVR_IT_REXC)) { -#ifdef AURORA_INTMSG - printk("RXC ACK\n"); -#endif - aurora_receive_exc(bp,chip); - } else { -#ifdef AURORA_INTNORM - printk("aurora%d-%d: Bad receive ack 0x%02x.\n", - board_No(bp), chip, ack); -#endif - } - } else if (status & SRSR_TEXT) { - ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]); - if (ack == (chip_id | GSVR_IT_TX)){ -#ifdef AURORA_INTMSG - printk("TX ACK\n"); -#endif - aurora_transmit(bp,chip); - } else { -#ifdef AURORA_INTNORM - printk("aurora%d-%d: Bad transmit ack 0x%02x.\n", - board_No(bp), chip, ack); -#endif - } - } else if (status & SRSR_MEXT) { - ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]); - if (ack == (chip_id | GSVR_IT_MDM)){ -#ifdef AURORA_INTMSG - printk("MDM ACK\n"); -#endif - aurora_check_modem(bp,chip); - } else { -#ifdef AURORA_INTNORM - printk("aurora%d-%d: Bad modem ack 0x%02x.\n", - board_No(bp), chip, ack); -#endif - } - } - sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]); - } - } -#endif - - return IRQ_HANDLED; -} - -#ifdef AURORA_INT_DEBUG -static void aurora_timer (unsigned long ignored); - -static DEFINE_TIMER(aurora_poll_timer, aurora_timer, 0, 0); - -static void -aurora_timer (unsigned long ignored) -{ - unsigned long flags; - int i; - - save_flags(flags); cli(); - - printk("SRSR: %02x,%02x - ", - sbus_readb(&aurora_board[0].r[0]->r[CD180_SRSR]), - sbus_readb(&aurora_board[0].r[1]->r[CD180_SRSR])); - for (i = 0; i < 4; i++) { - udelay(1); - printk("%02x ", - sbus_readb(&aurora_board[0].r3->r[i])); - } - printk("\n"); - - aurora_poll_timer.expires = jiffies + 300; - add_timer (&aurora_poll_timer); - - restore_flags(flags); -} -#endif - -/* - * Routines for open & close processing. - */ - -/* Called with disabled interrupts */ -static int aurora_setup_board(struct Aurora_board * bp) -{ - int error; - -#ifdef AURORA_ALLIRQ - int i; - for (i = 0; i < AURORA_ALLIRQ; i++) { - error = request_irq(allirq[i]|0x30, aurora_interrupt, IRQF_SHARED, - "sio16", bp); - if (error) - printk(KERN_ERR "IRQ%d request error %d\n", - allirq[i], error); - } -#else - error = request_irq(bp->irq|0x30, aurora_interrupt, IRQF_SHARED, - "sio16", bp); - if (error) { - printk(KERN_ERR "IRQ request error %d\n", error); - return error; - } -#endif - /* Board reset */ - sbus_writeb(0, &bp->r0->r); - udelay(1); - if (bp->flags & AURORA_BOARD_TYPE_2) { - /* unknown yet */ - } else { - sbus_writeb((AURORA_CFG_ENABLE_IO | AURORA_CFG_ENABLE_IRQ | - (((bp->irq)&0x0f)>>2)), - &bp->r0->r); - } - udelay(10000); - - if (aurora_init_CD180(bp,0))error=1;error=0; - if (aurora_init_CD180(bp,1))error++; - if (error == AURORA_NCD180) { - printk(KERN_ERR "Both chips failed initialisation.\n"); - return -EIO; - } - -#ifdef AURORA_INT_DEBUG - aurora_poll_timer.expires= jiffies + 1; - add_timer(&aurora_poll_timer); -#endif -#ifdef AURORA_DEBUG - printk("aurora_setup_board: end\n"); -#endif - return 0; -} - -/* Called with disabled interrupts */ -static void aurora_shutdown_board(struct Aurora_board *bp) -{ - int i; - -#ifdef AURORA_DEBUG - printk("aurora_shutdown_board: start\n"); -#endif - -#ifdef AURORA_INT_DEBUG - del_timer(&aurora_poll_timer); -#endif - -#ifdef AURORA_ALLIRQ - for(i=0;i<AURORA_ALLIRQ;i++){ - free_irq(allirq[i]|0x30, bp); -/* IRQ_to_board[allirq[i]&0xf] = NULL;*/ - } -#else - free_irq(bp->irq|0x30, bp); -/* IRQ_to_board[bp->irq&0xf] = NULL;*/ -#endif - /* Drop all DTR's */ - for(i=0;i<16;i++){ - sbus_writeb(i & 7, &bp->r[i>>3]->r[CD180_CAR]); - udelay(1); - sbus_writeb(0, &bp->r[i>>3]->r[CD180_MSVR]); - udelay(1); - } - /* Board shutdown */ - sbus_writeb(0, &bp->r0->r); - -#ifdef AURORA_DEBUG - printk("aurora_shutdown_board: end\n"); -#endif -} - -/* Setting up port characteristics. - * Must be called with disabled interrupts - */ -static void aurora_change_speed(struct Aurora_board *bp, struct Aurora_port *port) -{ - struct tty_struct *tty; - unsigned long baud; - long tmp; - unsigned char cor1 = 0, cor3 = 0; - unsigned char mcor1 = 0, mcor2 = 0,chip; - -#ifdef AURORA_DEBUG - printk("aurora_change_speed: start\n"); -#endif - if (!(tty = port->tty) || !tty->termios) - return; - - chip = AURORA_CD180(port_No(port)); - - port->SRER = 0; - port->COR2 = 0; - port->MSVR = MSVR_RTS|MSVR_DTR; - - baud = tty_get_baud_rate(tty); - - /* Select port on the board */ - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - - if (!baud) { - /* Drop DTR & exit */ - port->MSVR &= ~(bp->DTR|bp->RTS); - sbus_writeb(port->MSVR, - &bp->r[chip]->r[CD180_MSVR]); - return; - } else { - /* Set DTR on */ - port->MSVR |= bp->DTR; - sbus_writeb(port->MSVR, - &bp->r[chip]->r[CD180_MSVR]); - } - - /* Now we must calculate some speed dependent things. */ - - /* Set baud rate for port. */ - tmp = (((bp->oscfreq + baud/2) / baud + - CD180_TPC/2) / CD180_TPC); - -/* tmp = (bp->oscfreq/7)/baud; - if((tmp%10)>4)tmp=tmp/10+1;else tmp=tmp/10;*/ -/* printk("Prescaler period: %d\n",tmp);*/ - - sbus_writeb((tmp >> 8) & 0xff, - &bp->r[chip]->r[CD180_RBPRH]); - sbus_writeb((tmp >> 8) & 0xff, - &bp->r[chip]->r[CD180_TBPRH]); - sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_RBPRL]); - sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_TBPRL]); - - baud = (baud + 5) / 10; /* Estimated CPS */ - - /* Two timer ticks seems enough to wakeup something like SLIP driver */ - tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO; - port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ? - SERIAL_XMIT_SIZE - 1 : tmp); - - /* Receiver timeout will be transmission time for 1.5 chars */ - tmp = (AURORA_TPS + AURORA_TPS/2 + baud/2) / baud; - tmp = (tmp > 0xff) ? 0xff : tmp; - sbus_writeb(tmp, &bp->r[chip]->r[CD180_RTPR]); - - switch (C_CSIZE(tty)) { - case CS5: - cor1 |= COR1_5BITS; - break; - case CS6: - cor1 |= COR1_6BITS; - break; - case CS7: - cor1 |= COR1_7BITS; - break; - case CS8: - cor1 |= COR1_8BITS; - break; - } - - if (C_CSTOPB(tty)) - cor1 |= COR1_2SB; - - cor1 |= COR1_IGNORE; - if (C_PARENB(tty)) { - cor1 |= COR1_NORMPAR; - if (C_PARODD(tty)) - cor1 |= COR1_ODDP; - if (I_INPCK(tty)) - cor1 &= ~COR1_IGNORE; - } - /* Set marking of some errors */ - port->mark_mask = RCSR_OE | RCSR_TOUT; - if (I_INPCK(tty)) - port->mark_mask |= RCSR_FE | RCSR_PE; - if (I_BRKINT(tty) || I_PARMRK(tty)) - port->mark_mask |= RCSR_BREAK; - if (I_IGNPAR(tty)) - port->mark_mask &= ~(RCSR_FE | RCSR_PE); - if (I_IGNBRK(tty)) { - port->mark_mask &= ~RCSR_BREAK; - if (I_IGNPAR(tty)) - /* Real raw mode. Ignore all */ - port->mark_mask &= ~RCSR_OE; - } - /* Enable Hardware Flow Control */ - if (C_CRTSCTS(tty)) { -/*#ifdef AURORA_BRAIN_DAMAGED_CTS - port->SRER |= SRER_DSR | SRER_CTS; - mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; - mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; - tty->hw_stopped = !(aurora_in(bp, CD180_MSVR) & (MSVR_CTS|MSVR_DSR)); -#else*/ - port->COR2 |= COR2_CTSAE; -/*#endif*/ - if (bp->flags&AURORA_BOARD_DTR_FLOW_OK) { - mcor1 |= AURORA_RXTH; - } - } - /* Enable Software Flow Control. FIXME: I'm not sure about this */ - /* Some people reported that it works, but I still doubt */ - if (I_IXON(tty)) { - port->COR2 |= COR2_TXIBE; - cor3 |= (COR3_FCT | COR3_SCDE); - if (I_IXANY(tty)) - port->COR2 |= COR2_IXM; - sbus_writeb(START_CHAR(tty), - &bp->r[chip]->r[CD180_SCHR1]); - sbus_writeb(STOP_CHAR(tty), - &bp->r[chip]->r[CD180_SCHR2]); - sbus_writeb(START_CHAR(tty), - &bp->r[chip]->r[CD180_SCHR3]); - sbus_writeb(STOP_CHAR(tty), - &bp->r[chip]->r[CD180_SCHR4]); - } - if (!C_CLOCAL(tty)) { - /* Enable CD check */ - port->SRER |= SRER_CD; - mcor1 |= MCOR1_CDZD; - mcor2 |= MCOR2_CDOD; - } - - if (C_CREAD(tty)) - /* Enable receiver */ - port->SRER |= SRER_RXD; - - /* Set input FIFO size (1-8 bytes) */ - cor3 |= AURORA_RXFIFO; - /* Setting up CD180 channel registers */ - sbus_writeb(cor1, &bp->r[chip]->r[CD180_COR1]); - sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]); - sbus_writeb(cor3, &bp->r[chip]->r[CD180_COR3]); - /* Make CD180 know about registers change */ - aurora_wait_CCR(bp->r[chip]); - sbus_writeb(CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3, - &bp->r[chip]->r[CD180_CCR]); - /* Setting up modem option registers */ - sbus_writeb(mcor1, &bp->r[chip]->r[CD180_MCOR1]); - sbus_writeb(mcor2, &bp->r[chip]->r[CD180_MCOR2]); - /* Enable CD180 transmitter & receiver */ - aurora_wait_CCR(bp->r[chip]); - sbus_writeb(CCR_TXEN | CCR_RXEN, &bp->r[chip]->r[CD180_CCR]); - /* Enable interrupts */ - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - /* And finally set RTS on */ - sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); -#ifdef AURORA_DEBUG - printk("aurora_change_speed: end\n"); -#endif -} - -/* Must be called with interrupts enabled */ -static int aurora_setup_port(struct Aurora_board *bp, struct Aurora_port *port) -{ - unsigned long flags; - -#ifdef AURORA_DEBUG - printk("aurora_setup_port: start %d\n",port_No(port)); -#endif - if (port->flags & ASYNC_INITIALIZED) - return 0; - - if (!port->xmit_buf) { - /* We may sleep in get_zeroed_page() */ - unsigned long tmp; - - if (!(tmp = get_zeroed_page(GFP_KERNEL))) - return -ENOMEM; - - if (port->xmit_buf) { - free_page(tmp); - return -ERESTARTSYS; - } - port->xmit_buf = (unsigned char *) tmp; - } - - save_flags(flags); cli(); - - if (port->tty) - clear_bit(TTY_IO_ERROR, &port->tty->flags); - -#ifdef MODULE - if ((port->count == 1) && ((++bp->count) == 1)) - bp->flags |= AURORA_BOARD_ACTIVE; -#endif - - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - aurora_change_speed(bp, port); - port->flags |= ASYNC_INITIALIZED; - - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_setup_port: end\n"); -#endif - return 0; -} - -/* Must be called with interrupts disabled */ -static void aurora_shutdown_port(struct Aurora_board *bp, struct Aurora_port *port) -{ - struct tty_struct *tty; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_shutdown_port: start\n"); -#endif - if (!(port->flags & ASYNC_INITIALIZED)) - return; - - chip = AURORA_CD180(port_No(port)); - -#ifdef AURORA_REPORT_OVERRUN - printk("aurora%d: port %d: Total %ld overruns were detected.\n", - board_No(bp), port_No(port), port->overrun); -#endif -#ifdef AURORA_REPORT_FIFO - { - int i; - - printk("aurora%d: port %d: FIFO hits [ ", - board_No(bp), port_No(port)); - for (i = 0; i < 10; i++) { - printk("%ld ", port->hits[i]); - } - printk("].\n"); - } -#endif - if (port->xmit_buf) { - free_page((unsigned long) port->xmit_buf); - port->xmit_buf = NULL; - } - - if (!(tty = port->tty) || C_HUPCL(tty)) { - /* Drop DTR */ - port->MSVR &= ~(bp->DTR|bp->RTS); - sbus_writeb(port->MSVR, - &bp->r[chip]->r[CD180_MSVR]); - } - - /* Select port */ - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - - /* Reset port */ - aurora_wait_CCR(bp->r[chip]); - sbus_writeb(CCR_SOFTRESET, &bp->r[chip]->r[CD180_CCR]); - - /* Disable all interrupts from this port */ - port->SRER = 0; - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - - if (tty) - set_bit(TTY_IO_ERROR, &tty->flags); - port->flags &= ~ASYNC_INITIALIZED; - -#ifdef MODULE - if (--bp->count < 0) { - printk(KERN_DEBUG "aurora%d: aurora_shutdown_port: " - "bad board count: %d\n", - board_No(bp), bp->count); - bp->count = 0; - } - - if (!bp->count) - bp->flags &= ~AURORA_BOARD_ACTIVE; -#endif - -#ifdef AURORA_DEBUG - printk("aurora_shutdown_port: end\n"); -#endif -} - - -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct Aurora_port *port) -{ - DECLARE_WAITQUEUE(wait, current); - struct Aurora_board *bp = port_Board(port); - int retval; - int do_clocal = 0; - int CD; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("block_til_ready: start\n"); -#endif - chip = AURORA_CD180(port_No(port)); - - /* If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&port->close_wait); - if (port->flags & ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; - } - - /* If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - port->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (C_CLOCAL(tty)) - do_clocal = 1; - - /* Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&port->open_wait, &wait); - cli(); - if (!tty_hung_up_p(filp)) - port->count--; - sti(); - port->blocked_open++; - while (1) { - cli(); - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - CD = sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD; - port->MSVR=bp->RTS; - - /* auto drops DTR */ - sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); - sti(); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(port->flags & ASYNC_INITIALIZED)) { - if (port->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(port->flags & ASYNC_CLOSING) && - (do_clocal || CD)) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&port->open_wait, &wait); - if (!tty_hung_up_p(filp)) - port->count++; - port->blocked_open--; - if (retval) - return retval; - - port->flags |= ASYNC_NORMAL_ACTIVE; -#ifdef AURORA_DEBUG - printk("block_til_ready: end\n"); -#endif - return 0; -} - -static int aurora_open(struct tty_struct * tty, struct file * filp) -{ - int board; - int error; - struct Aurora_port * port; - struct Aurora_board * bp; - unsigned long flags; - -#ifdef AURORA_DEBUG - printk("aurora_open: start\n"); -#endif - - board = AURORA_BOARD(tty->index); - if (board > AURORA_NBOARD || - !(aurora_board[board].flags & AURORA_BOARD_PRESENT)) { -#ifdef AURORA_DEBUG - printk("aurora_open: error board %d present %d\n", - board, aurora_board[board].flags & AURORA_BOARD_PRESENT); -#endif - return -ENODEV; - } - - bp = &aurora_board[board]; - port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(tty->index); - if ((aurora_paranoia_check(port, tty->name, "aurora_open")) { -#ifdef AURORA_DEBUG - printk("aurora_open: error paranoia check\n"); -#endif - return -ENODEV; - } - - port->count++; - tty->driver_data = port; - port->tty = tty; - - if ((error = aurora_setup_port(bp, port))) { -#ifdef AURORA_DEBUG - printk("aurora_open: error aurora_setup_port ret %d\n",error); -#endif - return error; - } - - if ((error = block_til_ready(tty, filp, port))) { -#ifdef AURORA_DEBUG - printk("aurora_open: error block_til_ready ret %d\n",error); -#endif - return error; - } - -#ifdef AURORA_DEBUG - printk("aurora_open: end\n"); -#endif - return 0; -} - -static void aurora_close(struct tty_struct * tty, struct file * filp) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board *bp; - unsigned long flags; - unsigned long timeout; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_close: start\n"); -#endif - - if (!port || (aurora_paranoia_check(port, tty->name, "close")) - return; - - chip = AURORA_CD180(port_No(port)); - - save_flags(flags); cli(); - if (tty_hung_up_p(filp)) { - restore_flags(flags); - return; - } - - bp = port_Board(port); - if ((tty->count == 1) && (port->count != 1)) { - printk(KERN_DEBUG "aurora%d: aurora_close: bad port count; " - "tty->count is 1, port count is %d\n", - board_No(bp), port->count); - port->count = 1; - } - if (--port->count < 0) { - printk(KERN_DEBUG "aurora%d: aurora_close: bad port " - "count for tty%d: %d\n", - board_No(bp), port_No(port), port->count); - port->count = 0; - } - if (port->count) { - restore_flags(flags); - return; - } - port->flags |= ASYNC_CLOSING; - - /* Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE){ -#ifdef AURORA_DEBUG - printk("aurora_close: waiting to flush...\n"); -#endif - tty_wait_until_sent(tty, port->closing_wait); - } - - /* At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - port->SRER &= ~SRER_RXD; - if (port->flags & ASYNC_INITIALIZED) { - port->SRER &= ~SRER_TXRDY; - port->SRER |= SRER_TXEMPTY; - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = jiffies+HZ; - while(port->SRER & SRER_TXEMPTY) { - msleep_interruptible(jiffies_to_msecs(port->timeout)); - if (time_after(jiffies, timeout)) - break; - } - } -#ifdef AURORA_DEBUG - printk("aurora_close: shutdown_port\n"); -#endif - aurora_shutdown_port(bp, port); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - tty_ldisc_flush(tty); - tty->closing = 0; - port->event = 0; - port->tty = 0; - if (port->blocked_open) { - if (port->close_delay) { - msleep_interruptible(jiffies_to_msecs(port->close_delay)); - } - wake_up_interruptible(&port->open_wait); - } - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&port->close_wait); - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_close: end\n"); -#endif -} - -static int aurora_write(struct tty_struct * tty, - const unsigned char *buf, int count) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board *bp; - int c, total = 0; - unsigned long flags; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_write: start %d\n",count); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_write")) - return 0; - - chip = AURORA_CD180(port_No(port)); - - bp = port_Board(port); - - if (!tty || !port->xmit_buf || !tmp_buf) - return 0; - - save_flags(flags); - while (1) { - cli(); - c = min(count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, - SERIAL_XMIT_SIZE - port->xmit_head)); - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(port->xmit_buf + port->xmit_head, buf, c); - port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - port->xmit_cnt += c; - restore_flags(flags); - - buf += c; - count -= c; - total += c; - } - - cli(); - if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && - !(port->SRER & SRER_TXRDY)) { - port->SRER |= SRER_TXRDY; - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - } - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_write: end %d\n",total); -#endif - return total; -} - -static void aurora_put_char(struct tty_struct * tty, unsigned char ch) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - unsigned long flags; - -#ifdef AURORA_DEBUG - printk("aurora_put_char: start %c\n",ch); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_put_char")) - return; - - if (!tty || !port->xmit_buf) - return; - - save_flags(flags); cli(); - - if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - restore_flags(flags); - return; - } - - port->xmit_buf[port->xmit_head++] = ch; - port->xmit_head &= SERIAL_XMIT_SIZE - 1; - port->xmit_cnt++; - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_put_char: end\n"); -#endif -} - -static void aurora_flush_chars(struct tty_struct * tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - unsigned long flags; - unsigned char chip; - -/*#ifdef AURORA_DEBUG - printk("aurora_flush_chars: start\n"); -#endif*/ - if ((aurora_paranoia_check(port, tty->name, "aurora_flush_chars")) - return; - - chip = AURORA_CD180(port_No(port)); - - if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !port->xmit_buf) - return; - - save_flags(flags); cli(); - port->SRER |= SRER_TXRDY; - sbus_writeb(port_No(port) & 7, - &port_Board(port)->r[chip]->r[CD180_CAR]); - udelay(1); - sbus_writeb(port->SRER, - &port_Board(port)->r[chip]->r[CD180_SRER]); - restore_flags(flags); -/*#ifdef AURORA_DEBUG - printk("aurora_flush_chars: end\n"); -#endif*/ -} - -static int aurora_write_room(struct tty_struct * tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - int ret; - -#ifdef AURORA_DEBUG - printk("aurora_write_room: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_write_room")) - return 0; - - ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1; - if (ret < 0) - ret = 0; -#ifdef AURORA_DEBUG - printk("aurora_write_room: end\n"); -#endif - return ret; -} - -static int aurora_chars_in_buffer(struct tty_struct *tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - - if ((aurora_paranoia_check(port, tty->name, "aurora_chars_in_buffer")) - return 0; - - return port->xmit_cnt; -} - -static void aurora_flush_buffer(struct tty_struct *tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - unsigned long flags; - -#ifdef AURORA_DEBUG - printk("aurora_flush_buffer: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_flush_buffer")) - return; - - save_flags(flags); cli(); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - restore_flags(flags); - - tty_wakeup(tty); -#ifdef AURORA_DEBUG - printk("aurora_flush_buffer: end\n"); -#endif -} - -static int aurora_tiocmget(struct tty_struct *tty, struct file *file) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board * bp; - unsigned char status,chip; - unsigned int result; - unsigned long flags; - -#ifdef AURORA_DEBUG - printk("aurora_get_modem_info: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, __FUNCTION__)) - return -ENODEV; - - chip = AURORA_CD180(port_No(port)); - - bp = port_Board(port); - - save_flags(flags); cli(); - - sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); - udelay(1); - - status = sbus_readb(&bp->r[chip]->r[CD180_MSVR]); - result = 0/*bp->r[chip]->r[AURORA_RI] & (1u << port_No(port)) ? 0 : TIOCM_RNG*/; - - restore_flags(flags); - - result |= ((status & bp->RTS) ? TIOCM_RTS : 0) - | ((status & bp->DTR) ? TIOCM_DTR : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - | ((status & MSVR_DSR) ? TIOCM_DSR : 0) - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); - -#ifdef AURORA_DEBUG - printk("aurora_get_modem_info: end\n"); -#endif - return result; -} - -static int aurora_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - unsigned int arg; - unsigned long flags; - struct Aurora_board *bp = port_Board(port); - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_set_modem_info: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, __FUNCTION__)) - return -ENODEV; - - chip = AURORA_CD180(port_No(port)); - - save_flags(flags); cli(); - if (set & TIOCM_RTS) - port->MSVR |= bp->RTS; - if (set & TIOCM_DTR) - port->MSVR |= bp->DTR; - if (clear & TIOCM_RTS) - port->MSVR &= ~bp->RTS; - if (clear & TIOCM_DTR) - port->MSVR &= ~bp->DTR; - - sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); - udelay(1); - - sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); - - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_set_modem_info: end\n"); -#endif - return 0; -} - -static void aurora_send_break(struct Aurora_port * port, unsigned long length) -{ - struct Aurora_board *bp = port_Board(port); - unsigned long flags; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_send_break: start\n"); -#endif - chip = AURORA_CD180(port_No(port)); - - save_flags(flags); cli(); - - port->break_length = AURORA_TPS / HZ * length; - port->COR2 |= COR2_ETC; - port->SRER |= SRER_TXRDY; - sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); - udelay(1); - - sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]); - sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]); - aurora_wait_CCR(bp->r[chip]); - - sbus_writeb(CCR_CORCHG2, &bp->r[chip]->r[CD180_CCR]); - aurora_wait_CCR(bp->r[chip]); - - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_send_break: end\n"); -#endif -} - -static int aurora_set_serial_info(struct Aurora_port * port, - struct serial_struct * newinfo) -{ - struct serial_struct tmp; - struct Aurora_board *bp = port_Board(port); - int change_speed; - unsigned long flags; - -#ifdef AURORA_DEBUG - printk("aurora_set_serial_info: start\n"); -#endif - if (copy_from_user(&tmp, newinfo, sizeof(tmp))) - return -EFAULT; -#if 0 - if ((tmp.irq != bp->irq) || - (tmp.port != bp->base) || - (tmp.type != PORT_CIRRUS) || - (tmp.baud_base != (bp->oscfreq + CD180_TPC/2) / CD180_TPC) || - (tmp.custom_divisor != 0) || - (tmp.xmit_fifo_size != CD180_NFIFO) || - (tmp.flags & ~AURORA_LEGAL_FLAGS)) - return -EINVAL; -#endif - - change_speed = ((port->flags & ASYNC_SPD_MASK) != - (tmp.flags & ASYNC_SPD_MASK)); - - if (!capable(CAP_SYS_ADMIN)) { - if ((tmp.close_delay != port->close_delay) || - (tmp.closing_wait != port->closing_wait) || - ((tmp.flags & ~ASYNC_USR_MASK) != - (port->flags & ~ASYNC_USR_MASK))) - return -EPERM; - port->flags = ((port->flags & ~ASYNC_USR_MASK) | - (tmp.flags & ASYNC_USR_MASK)); - } else { - port->flags = ((port->flags & ~ASYNC_FLAGS) | - (tmp.flags & ASYNC_FLAGS)); - port->close_delay = tmp.close_delay; - port->closing_wait = tmp.closing_wait; - } - if (change_speed) { - save_flags(flags); cli(); - aurora_change_speed(bp, port); - restore_flags(flags); - } -#ifdef AURORA_DEBUG - printk("aurora_set_serial_info: end\n"); -#endif - return 0; -} - -extern int aurora_get_serial_info(struct Aurora_port * port, - struct serial_struct * retinfo) -{ - struct serial_struct tmp; - struct Aurora_board *bp = port_Board(port); - -#ifdef AURORA_DEBUG - printk("aurora_get_serial_info: start\n"); -#endif - if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp))) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = PORT_CIRRUS; - tmp.line = port - aurora_port; - tmp.port = 0; - tmp.irq = bp->irq; - tmp.flags = port->flags; - tmp.baud_base = (bp->oscfreq + CD180_TPC/2) / CD180_TPC; - tmp.close_delay = port->close_delay * HZ/100; - tmp.closing_wait = port->closing_wait * HZ/100; - tmp.xmit_fifo_size = CD180_NFIFO; - copy_to_user(retinfo, &tmp, sizeof(tmp)); -#ifdef AURORA_DEBUG -printk("aurora_get_serial_info: end\n"); -#endif - return 0; -} - -static int aurora_ioctl(struct tty_struct * tty, struct file * filp, - unsigned int cmd, unsigned long arg) - -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - int retval; - -#ifdef AURORA_DEBUG - printk("aurora_ioctl: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_ioctl")) - return -ENODEV; - - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - aurora_send_break(port, HZ/4); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - aurora_send_break(port, arg ? arg*(HZ/10) : HZ/4); - return 0; - case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg); - case TIOCSSOFTCAR: - if (get_user(arg,(unsigned long *)arg)) - return -EFAULT; - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - return 0; - case TIOCGSERIAL: - return aurora_get_serial_info(port, (struct serial_struct *) arg); - case TIOCSSERIAL: - return aurora_set_serial_info(port, (struct serial_struct *) arg); - default: - return -ENOIOCTLCMD; - }; -#ifdef AURORA_DEBUG - printk("aurora_ioctl: end\n"); -#endif - return 0; -} - -static void aurora_throttle(struct tty_struct * tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board *bp; - unsigned long flags; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_throttle: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_throttle")) - return; - - bp = port_Board(port); - chip = AURORA_CD180(port_No(port)); - - save_flags(flags); cli(); - port->MSVR &= ~bp->RTS; - sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); - udelay(1); - if (I_IXOFF(tty)) { - aurora_wait_CCR(bp->r[chip]); - sbus_writeb(CCR_SSCH2, &bp->r[chip]->r[CD180_CCR]); - aurora_wait_CCR(bp->r[chip]); - } - sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_throttle: end\n"); -#endif -} - -static void aurora_unthrottle(struct tty_struct * tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board *bp; - unsigned long flags; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_unthrottle: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_unthrottle")) - return; - - bp = port_Board(port); - - chip = AURORA_CD180(port_No(port)); - - save_flags(flags); cli(); - port->MSVR |= bp->RTS; - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - if (I_IXOFF(tty)) { - aurora_wait_CCR(bp->r[chip]); - sbus_writeb(CCR_SSCH1, - &bp->r[chip]->r[CD180_CCR]); - aurora_wait_CCR(bp->r[chip]); - } - sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]); - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_unthrottle: end\n"); -#endif -} - -static void aurora_stop(struct tty_struct * tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board *bp; - unsigned long flags; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_stop: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_stop")) - return; - - bp = port_Board(port); - - chip = AURORA_CD180(port_No(port)); - - save_flags(flags); cli(); - port->SRER &= ~SRER_TXRDY; - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - sbus_writeb(port->SRER, - &bp->r[chip]->r[CD180_SRER]); - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_stop: end\n"); -#endif -} - -static void aurora_start(struct tty_struct * tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board *bp; - unsigned long flags; - unsigned char chip; - -#ifdef AURORA_DEBUG - printk("aurora_start: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_start")) - return; - - bp = port_Board(port); - - chip = AURORA_CD180(port_No(port)); - - save_flags(flags); cli(); - if (port->xmit_cnt && port->xmit_buf && !(port->SRER & SRER_TXRDY)) { - port->SRER |= SRER_TXRDY; - sbus_writeb(port_No(port) & 7, - &bp->r[chip]->r[CD180_CAR]); - udelay(1); - sbus_writeb(port->SRER, - &bp->r[chip]->r[CD180_SRER]); - } - restore_flags(flags); -#ifdef AURORA_DEBUG - printk("aurora_start: end\n"); -#endif -} - -/* - * This routine is called from the scheduler tqueue when the interrupt - * routine has signalled that a hangup has occurred. The path of - * hangup processing is: - * - * serial interrupt routine -> (scheduler tqueue) -> - * do_aurora_hangup() -> tty->hangup() -> aurora_hangup() - * - */ -static void do_aurora_hangup(void *private_) -{ - struct Aurora_port *port = (struct Aurora_port *) private_; - struct tty_struct *tty; - -#ifdef AURORA_DEBUG - printk("do_aurora_hangup: start\n"); -#endif - tty = port->tty; - if (tty != NULL) { - tty_hangup(tty); /* FIXME: module removal race - AKPM */ -#ifdef AURORA_DEBUG - printk("do_aurora_hangup: end\n"); -#endif - } -} - -static void aurora_hangup(struct tty_struct * tty) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - struct Aurora_board *bp; - -#ifdef AURORA_DEBUG - printk("aurora_hangup: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_hangup")) - return; - - bp = port_Board(port); - - aurora_shutdown_port(bp, port); - port->event = 0; - port->count = 0; - port->flags &= ~ASYNC_NORMAL_ACTIVE; - port->tty = 0; - wake_up_interruptible(&port->open_wait); -#ifdef AURORA_DEBUG - printk("aurora_hangup: end\n"); -#endif -} - -static void aurora_set_termios(struct tty_struct * tty, struct termios * old_termios) -{ - struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; - unsigned long flags; - -#ifdef AURORA_DEBUG - printk("aurora_set_termios: start\n"); -#endif - if ((aurora_paranoia_check(port, tty->name, "aurora_set_termios")) - return; - - if (tty->termios->c_cflag == old_termios->c_cflag && - tty->termios->c_iflag == old_termios->c_iflag) - return; - - save_flags(flags); cli(); - aurora_change_speed(port_Board(port), port); - restore_flags(flags); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - aurora_start(tty); - } -#ifdef AURORA_DEBUG - printk("aurora_set_termios: end\n"); -#endif -} - -static void do_aurora_bh(void) -{ - run_task_queue(&tq_aurora); -} - -static void do_softint(void *private_) -{ - struct Aurora_port *port = (struct Aurora_port *) private_; - struct tty_struct *tty; - -#ifdef AURORA_DEBUG - printk("do_softint: start\n"); -#endif - tty = port->tty; - if (tty == NULL) - return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { - tty_wakeup(tty); - } -#ifdef AURORA_DEBUG - printk("do_softint: end\n"); -#endif -} - -static struct tty_operations aurora_ops = { - .open = aurora_open, - .close = aurora_close, - .write = aurora_write, - .put_char = aurora_put_char, - .flush_chars = aurora_flush_chars, - .write_room = aurora_write_room, - .chars_in_buffer = aurora_chars_in_buffer, - .flush_buffer = aurora_flush_buffer, - .ioctl = aurora_ioctl, - .throttle = aurora_throttle, - .unthrottle = aurora_unthrottle, - .set_termios = aurora_set_termios, - .stop = aurora_stop, - .start = aurora_start, - .hangup = aurora_hangup, - .tiocmget = aurora_tiocmget, - .tiocmset = aurora_tiocmset, -}; - -static int aurora_init_drivers(void) -{ - int error; - int i; - -#ifdef AURORA_DEBUG - printk("aurora_init_drivers: start\n"); -#endif - tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL); - if (tmp_buf == NULL) { - printk(KERN_ERR "aurora: Couldn't get free page.\n"); - return 1; - } - init_bh(AURORA_BH, do_aurora_bh); - aurora_driver = alloc_tty_driver(AURORA_INPORTS); - if (!aurora_driver) { - printk(KERN_ERR "aurora: Couldn't allocate tty driver.\n"); - free_page((unsigned long) tmp_buf); - return 1; - } - aurora_driver->owner = THIS_MODULE; - aurora_driver->name = "ttyA"; - aurora_driver->major = AURORA_MAJOR; - aurora_driver->type = TTY_DRIVER_TYPE_SERIAL; - aurora_driver->subtype = SERIAL_TYPE_NORMAL; - aurora_driver->init_termios = tty_std_termios; - aurora_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - aurora_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(aurora_driver, &aurora_ops); - error = tty_register_driver(aurora_driver); - if (error) { - put_tty_driver(aurora_driver); - free_page((unsigned long) tmp_buf); - printk(KERN_ERR "aurora: Couldn't register aurora driver, error = %d\n", - error); - return 1; - } - - memset(aurora_port, 0, sizeof(aurora_port)); - for (i = 0; i < AURORA_TNPORTS; i++) { - aurora_port[i].magic = AURORA_MAGIC; - aurora_port[i].tqueue.routine = do_softint; - aurora_port[i].tqueue.data = &aurora_port[i]; - aurora_port[i].tqueue_hangup.routine = do_aurora_hangup; - aurora_port[i].tqueue_hangup.data = &aurora_port[i]; - aurora_port[i].close_delay = 50 * HZ/100; - aurora_port[i].closing_wait = 3000 * HZ/100; - init_waitqueue_head(&aurora_port[i].open_wait); - init_waitqueue_head(&aurora_port[i].close_wait); - } -#ifdef AURORA_DEBUG - printk("aurora_init_drivers: end\n"); -#endif - return 0; -} - -static void aurora_release_drivers(void) -{ -#ifdef AURORA_DEBUG - printk("aurora_release_drivers: start\n"); -#endif - free_page((unsigned long)tmp_buf); - tty_unregister_driver(aurora_driver); - put_tty_driver(aurora_driver); -#ifdef AURORA_DEBUG - printk("aurora_release_drivers: end\n"); -#endif -} - -/* - * Called at boot time. - * - * You can specify IO base for up to RC_NBOARD cards, - * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt. - * Note that there will be no probing at default - * addresses in this case. - * - */ -void __init aurora_setup(char *str, int *ints) -{ - int i; - - for(i=0;(i<ints[0])&&(i<4);i++) { - if (ints[i+1]) irqs[i]=ints[i+1]; - } -} - -static int __init aurora_real_init(void) -{ - int found; - int i; - - printk(KERN_INFO "aurora: Driver starting.\n"); - if(aurora_init_drivers()) - return -EIO; - found = aurora_probe(); - if(!found) { - aurora_release_drivers(); - printk(KERN_INFO "aurora: No Aurora Multiport boards detected.\n"); - return -EIO; - } else { - printk(KERN_INFO "aurora: %d boards found.\n", found); - } - for (i = 0; i < found; i++) { - int ret = aurora_setup_board(&aurora_board[i]); - - if (ret) { -#ifdef AURORA_DEBUG - printk(KERN_ERR "aurora_init: error aurora_setup_board ret %d\n", - ret); -#endif - return ret; - } - } - return 0; -} - -int irq = 0; -int irq1 = 0; -int irq2 = 0; -int irq3 = 0; -module_param(irq , int, 0); -module_param(irq1, int, 0); -module_param(irq2, int, 0); -module_param(irq3, int, 0); - -static int __init aurora_init(void) -{ - if (irq ) irqs[0]=irq ; - if (irq1) irqs[1]=irq1; - if (irq2) irqs[2]=irq2; - if (irq3) irqs[3]=irq3; - return aurora_real_init(); -} - -static void __exit aurora_cleanup(void) -{ - int i; - -#ifdef AURORA_DEBUG -printk("cleanup_module: aurora_release_drivers\n"); -#endif - - aurora_release_drivers(); - for (i = 0; i < AURORA_NBOARD; i++) - if (aurora_board[i].flags & AURORA_BOARD_PRESENT) { - aurora_shutdown_board(&aurora_board[i]); - aurora_release_io_range(&aurora_board[i]); - } -} - -module_init(aurora_init); -module_exit(aurora_cleanup); -MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/aurora.h b/drivers/sbus/char/aurora.h deleted file mode 100644 index b8b5476d986..00000000000 --- a/drivers/sbus/char/aurora.h +++ /dev/null @@ -1,276 +0,0 @@ -/* $Id: aurora.h,v 1.6 2001/06/05 12:23:38 davem Exp $ - * linux/drivers/sbus/char/aurora.h -- Aurora multiport driver - * - * Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro) - * - * This code is based on the RISCom/8 multiport serial driver written - * by Dmitry Gorodchanin (pgmdsg@ibi.com), based on the Linux serial - * driver, written by Linus Torvalds, Theodore T'so and others. - * The Aurora multiport programming info was obtained mainly from the - * Cirrus Logic CD180 documentation (available on the web), and by - * doing heavy tests on the board. Many thanks to Eddie C. Dost for the - * help on the sbus interface. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Revision 1.0 - * - * This is the first public release. - * - * This version needs a lot of feedback. This is the version that works - * with _my_ board. My board is model 1600se, revision '@(#)1600se.fth - * 1.2 3/28/95 1'. The driver might work with your board, but I do not - * guarantee it. If you have _any_ type of board, I need to know if the - * driver works or not, I need to know exactly your board parameters - * (get them with 'cd /proc/openprom/iommu/sbus/sio16/; ls *; cat *') - * Also, I need your board revision code, which is written on the board. - * Send me the output of my driver too (it outputs through klogd). - * - * If the driver does not work, you can try enabling the debug options - * to see what's wrong or what should be done. - * - * I'm sorry about the alignment of the code. It was written in a - * 128x48 environment. - * - * I must say that I do not like Aurora Technologies' policy. I asked - * them to help me do this driver faster, but they ended by something - * like "don't call us, we'll call you", and I never heard anything - * from them. They told me "knowing the way the board works, I don't - * doubt you and others on the net will make the driver." - * The truth about this board is that it has nothing intelligent on it. - * If you want to say to somebody what kind of board you have, say that - * it uses Cirrus Logic processors (CD180). The power of the board is - * in those two chips. The rest of the board is the interface to the - * sbus and to the peripherals. Still, they did something smart: they - * reversed DTR and RTS to make on-board automatic hardware flow - * control usable. - * Thanks to Aurora Technologies for wasting my time, nerves and money. - */ - -#ifndef __LINUX_AURORA_H -#define __LINUX_AURORA_H - -#include <linux/serial.h> -#include <linux/serialP.h> - -#ifdef __KERNEL__ - -/* This is the number of boards to support. I've only tested this driver with - * one board, so it might not work. - */ -#define AURORA_NBOARD 1 - -/* Useful ? Yes. But you can safely comment the warnings if they annoy you - * (let me say that again: the warnings in the code, not this define). - */ -#define AURORA_PARANOIA_CHECK - -/* Well, after many lost nights, I found that the IRQ for this board is - * selected from four built-in values by writing some bits in the - * configuration register. This causes a little problem to occur: which - * IRQ to select ? Which one is the best for the user ? Well, I finally - * decided for the following algorithm: if the "bintr" value is not acceptable - * (not within type_1_irq[], then test the "intr" value, if that fails too, - * try each value from type_1_irq until succeded. Hope it's ok. - * You can safely reorder the irq's. - */ -#define TYPE_1_IRQS 4 -unsigned char type_1_irq[TYPE_1_IRQS] = { - 3, 5, 9, 13 -}; -/* I know something about another method of interrupt setting, but not enough. - * Also, this is for another type of board, so I first have to learn how to - * detect it. -#define TYPE_2_IRQS 3 -unsigned char type_2_irq[TYPE_2_IRQS] = { - 0, 0, 0 ** could anyone find these for me ? (see AURORA_ALLIRQ below) ** - }; -unsigned char type_2_mask[TYPE_2_IRQS] = { - 32, 64, 128 - }; -*/ - -/* The following section should only be modified by those who know what - * they're doing (or don't, but want to help with some feedback). Modifying - * anything raises a _big_ probability for your system to hang, but the - * sacrifice worths. (I sacrificed my ext2fs many, many times...) - */ - -/* This one tries to dump to console the name of almost every function called, - * and many other debugging info. - */ -#undef AURORA_DEBUG - -/* These are the most dangerous and useful defines. They do printk() during - * the interrupt processing routine(s), so if you manage to get "flooded" by - * irq's, start thinking about the "Power off/on" button... - */ -#undef AURORA_INTNORM /* This one enables the "normal" messages, but some - * of them cause flood, so I preffered putting - * them under a define */ -#undef AURORA_INT_DEBUG /* This one is really bad. */ - -/* Here's something helpful: after n irq's, the board will be disabled. This - * prevents irq flooding during debug (no need to think about power - * off/on anymore...) - */ -#define AURORA_FLOODPRO 10 - -/* This one helps finding which irq the board calls, in case of a strange/ - * unsupported board. AURORA_INT_DEBUG should be enabled, because I don't - * think /proc/interrupts or any command will be available in case of an irq - * flood... "allirq" is the list of all free irq's. - */ -/* -#define AURORA_ALLIRQ 6 -int allirq[AURORA_ALLIRQ]={ - 2,3,5,7,9,13 - }; -*/ - -/* These must not be modified. These values are assumed during the code for - * performance optimisations. - */ -#define AURORA_NCD180 2 /* two chips per board */ -#define AURORA_NPORT 8 /* 8 ports per chip */ - -/* several utilities */ -#define AURORA_BOARD(line) (((line) >> 4) & 0x01) -#define AURORA_CD180(line) (((line) >> 3) & 0x01) -#define AURORA_PORT(line) ((line) & 15) - -#define AURORA_TNPORTS (AURORA_NBOARD*AURORA_NCD180*AURORA_NPORT) - -/* Ticks per sec. Used for setting receiver timeout and break length */ -#define AURORA_TPS 4000 - -#define AURORA_MAGIC 0x0A18 - -/* Yeah, after heavy testing I decided it must be 6. - * Sure, You can change it if needed. - */ -#define AURORA_RXFIFO 6 /* Max. receiver FIFO size (1-8) */ - -#define AURORA_RXTH 7 - -struct aurora_reg1 { - __volatile__ unsigned char r; -}; - -struct aurora_reg128 { - __volatile__ unsigned char r[128]; -}; - -struct aurora_reg4 { - __volatile__ unsigned char r[4]; -}; - -struct Aurora_board { - unsigned long flags; - struct aurora_reg1 * r0; /* This is the board configuration - * register (write-only). */ - struct aurora_reg128 * r[2]; /* These are the registers for the - * two chips. */ - struct aurora_reg4 * r3; /* These are used for hardware-based - * acknowledge. Software-based ack is - * not supported by CD180. */ - unsigned int oscfreq; /* The on-board oscillator - * frequency, in Hz. */ - unsigned char irq; -#ifdef MODULE - signed char count; /* counts the use of the board */ -#endif - /* Values for the dtr_rts swapped mode. */ - unsigned char DTR; - unsigned char RTS; - unsigned char MSVDTR; - unsigned char MSVRTS; - /* Values for hardware acknowledge. */ - unsigned char ACK_MINT, ACK_TINT, ACK_RINT; -}; - -/* Board configuration register */ -#define AURORA_CFG_ENABLE_IO 8 -#define AURORA_CFG_ENABLE_IRQ 4 - -/* Board flags */ -#define AURORA_BOARD_PRESENT 0x00000001 -#define AURORA_BOARD_ACTIVE 0x00000002 -#define AURORA_BOARD_TYPE_2 0x00000004 /* don't know how to - * detect this yet */ -#define AURORA_BOARD_DTR_FLOW_OK 0x00000008 - -/* The story goes like this: Cirrus programmed the CD-180 chip to do automatic - * hardware flow control, and do it using CTS and DTR. CTS is ok, but, if you - * have a modem and the chip drops DTR, then the modem will drop the carrier - * (ain't that cute...). Luckily, the guys at Aurora decided to swap DTR and - * RTS, which makes the flow control usable. I hope that all the boards made - * by Aurora have these two signals swapped. If your's doesn't but you have a - * breakout box, you can try to reverse them yourself, then set the following - * flag. - */ -#undef AURORA_FORCE_DTR_FLOW - -/* In fact, a few more words have to be said about hardware flow control. - * This driver handles "output" flow control through the on-board facility - * CTS Auto Enable. For the "input" flow control there are two cases when - * the flow should be controlled. The first case is when the kernel is so - * busy that it cannot process IRQ's in time; this flow control can only be - * activated by the on-board chip, and if the board has RTS and DTR swapped, - * this facility is usable. The second case is when the application is so - * busy that it cannot receive bytes from the kernel, and this flow must be - * activated by software. This second case is not yet implemented in this - * driver. Unfortunately, I estimate that the second case is the one that - * occurs the most. - */ - - -struct Aurora_port { - int magic; - int baud_base; - int flags; - struct tty_struct * tty; - int count; - int blocked_open; - long event; - int timeout; - int close_delay; - unsigned char * xmit_buf; - int custom_divisor; - int xmit_head; - int xmit_tail; - int xmit_cnt; - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - struct tq_struct tqueue; - struct tq_struct tqueue_hangup; - short wakeup_chars; - short break_length; - unsigned short closing_wait; - unsigned char mark_mask; - unsigned char SRER; - unsigned char MSVR; - unsigned char COR2; -#ifdef AURORA_REPORT_OVERRUN - unsigned long overrun; -#endif -#ifdef AURORA_REPORT_FIFO - unsigned long hits[10]; -#endif -}; - -#endif -#endif /*__LINUX_AURORA_H*/ - diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 1cc706e1111..160e7510aca 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -1,19 +1,16 @@ -/* $Id: bbc_envctrl.c,v 1.4 2001/04/06 16:48:08 davem Exp $ - * bbc_envctrl.c: UltraSPARC-III environment control driver. +/* bbc_envctrl.c: UltraSPARC-III environment control driver. * - * Copyright (C) 2001 David S. Miller (davem@redhat.com) + * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) */ -#define __KERNEL_SYSCALLS__ -static int errno; - -#include <linux/kernel.h> #include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/slab.h> #include <linux/delay.h> +#include <linux/kmod.h> +#include <linux/reboot.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/of_device.h> #include <asm/oplib.h> -#include <asm/ebus.h> #include "bbc_i2c.h" #include "max1617.h" @@ -79,43 +76,8 @@ static struct temp_limits amb_temp_limits[2] = { { 65, 55, 40, 5, -5, -10 }, }; -enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; - -struct bbc_cpu_temperature { - struct bbc_cpu_temperature *next; - - struct bbc_i2c_client *client; - int index; - - /* Current readings, and history. */ - s8 curr_cpu_temp; - s8 curr_amb_temp; - s8 prev_cpu_temp; - s8 prev_amb_temp; - s8 avg_cpu_temp; - s8 avg_amb_temp; - - int sample_tick; - - enum fan_action fan_todo[2]; -#define FAN_AMBIENT 0 -#define FAN_CPU 1 -}; - -struct bbc_cpu_temperature *all_bbc_temps; - -struct bbc_fan_control { - struct bbc_fan_control *next; - - struct bbc_i2c_client *client; - int index; - - int psupply_fan_on; - int cpu_fan_speed; - int system_fan_speed; -}; - -struct bbc_fan_control *all_bbc_fans; +static LIST_HEAD(all_temps); +static LIST_HEAD(all_fans); #define CPU_FAN_REG 0xf0 #define SYS_FAN_REG 0xf2 @@ -175,8 +137,6 @@ static void get_current_temps(struct bbc_cpu_temperature *tp) static void do_envctrl_shutdown(struct bbc_cpu_temperature *tp) { static int shutting_down = 0; - static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - char *argv[] = { "/sbin/shutdown", "-h", "now", NULL }; char *type = "???"; s8 val = -1; @@ -200,7 +160,7 @@ static void do_envctrl_shutdown(struct bbc_cpu_temperature *tp) printk(KERN_CRIT "kenvctrld: Shutting down the system now.\n"); shutting_down = 1; - if (execve("/sbin/shutdown", argv, envp) < 0) + if (orderly_poweroff(true) < 0) printk(KERN_CRIT "envctrl: shutdown execution failed\n"); } @@ -336,7 +296,7 @@ static enum fan_action prioritize_fan_action(int which_fan) * recommend we do, and perform that action on all the * fans. */ - for (tp = all_bbc_temps; tp; tp = tp->next) { + list_for_each_entry(tp, &all_temps, glob_list) { if (tp->fan_todo[which_fan] == FAN_FULLBLAST) { decision = FAN_FULLBLAST; break; @@ -445,7 +405,7 @@ static void fans_full_blast(void) /* Since we will not be monitoring things anymore, put * the fans on full blast. */ - for (fp = all_bbc_fans; fp; fp = fp->next) { + list_for_each_entry(fp, &all_fans, glob_list) { fp->cpu_fan_speed = FAN_SPEED_MAX; fp->system_fan_speed = FAN_SPEED_MAX; fp->psupply_fan_on = 1; @@ -469,11 +429,11 @@ static int kenvctrld(void *__unused) if (kthread_should_stop()) break; - for (tp = all_bbc_temps; tp; tp = tp->next) { + list_for_each_entry(tp, &all_temps, glob_list) { get_current_temps(tp); analyze_temps(tp, &last_warning_jiffies); } - for (fp = all_bbc_fans; fp; fp = fp->next) + list_for_each_entry(fp, &all_fans, glob_list) maybe_new_fan_speeds(fp); } printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n"); @@ -483,27 +443,26 @@ static int kenvctrld(void *__unused) return 0; } -static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) +static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op, + int temp_idx) { - struct bbc_cpu_temperature *tp = kmalloc(sizeof(*tp), GFP_KERNEL); + struct bbc_cpu_temperature *tp; + tp = kzalloc(sizeof(*tp), GFP_KERNEL); if (!tp) return; - memset(tp, 0, sizeof(*tp)); - tp->client = bbc_i2c_attach(echild); + + tp->client = bbc_i2c_attach(bp, op); if (!tp->client) { kfree(tp); return; } + tp->index = temp_idx; - { - struct bbc_cpu_temperature **tpp = &all_bbc_temps; - while (*tpp) - tpp = &((*tpp)->next); - tp->next = NULL; - *tpp = tp; - } + + list_add(&tp->glob_list, &all_temps); + list_add(&tp->bp_list, &bp->temps); /* Tell it to convert once every 5 seconds, clear all cfg * bits. @@ -529,14 +488,16 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) tp->fan_todo[FAN_CPU] = FAN_SAME; } -static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) +static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op, + int fan_idx) { - struct bbc_fan_control *fp = kmalloc(sizeof(*fp), GFP_KERNEL); + struct bbc_fan_control *fp; + fp = kzalloc(sizeof(*fp), GFP_KERNEL); if (!fp) return; - memset(fp, 0, sizeof(*fp)); - fp->client = bbc_i2c_attach(echild); + + fp->client = bbc_i2c_attach(bp, op); if (!fp->client) { kfree(fp); return; @@ -544,13 +505,8 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) fp->index = fan_idx; - { - struct bbc_fan_control **fpp = &all_bbc_fans; - while (*fpp) - fpp = &((*fpp)->next); - fp->next = NULL; - *fpp = fp; - } + list_add(&fp->glob_list, &all_fans); + list_add(&fp->bp_list, &bp->fans); /* The i2c device controlling the fans is write-only. * So the only way to keep track of the current power @@ -567,60 +523,73 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) set_fan_speeds(fp); } -int bbc_envctrl_init(void) -{ - struct linux_ebus_child *echild; - int temp_index = 0; - int fan_index = 0; - int devidx = 0; - - while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { - if (!strcmp(echild->prom_node->name, "temperature")) - attach_one_temp(echild, temp_index++); - if (!strcmp(echild->prom_node->name, "fan-control")) - attach_one_fan(echild, fan_index++); - } - if (temp_index != 0 && fan_index != 0) { - kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); - if (IS_ERR(kenvctrld_task)) - return PTR_ERR(kenvctrld_task); - } - - return 0; -} - static void destroy_one_temp(struct bbc_cpu_temperature *tp) { bbc_i2c_detach(tp->client); kfree(tp); } +static void destroy_all_temps(struct bbc_i2c_bus *bp) +{ + struct bbc_cpu_temperature *tp, *tpos; + + list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { + list_del(&tp->bp_list); + list_del(&tp->glob_list); + destroy_one_temp(tp); + } +} + static void destroy_one_fan(struct bbc_fan_control *fp) { bbc_i2c_detach(fp->client); kfree(fp); } -void bbc_envctrl_cleanup(void) +static void destroy_all_fans(struct bbc_i2c_bus *bp) { - struct bbc_cpu_temperature *tp; - struct bbc_fan_control *fp; + struct bbc_fan_control *fp, *fpos; - kthread_stop(kenvctrld_task); + list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) { + list_del(&fp->bp_list); + list_del(&fp->glob_list); + destroy_one_fan(fp); + } +} - tp = all_bbc_temps; - while (tp != NULL) { - struct bbc_cpu_temperature *next = tp->next; - destroy_one_temp(tp); - tp = next; +int bbc_envctrl_init(struct bbc_i2c_bus *bp) +{ + struct platform_device *op; + int temp_index = 0; + int fan_index = 0; + int devidx = 0; + + while ((op = bbc_i2c_getdev(bp, devidx++)) != NULL) { + if (!strcmp(op->dev.of_node->name, "temperature")) + attach_one_temp(bp, op, temp_index++); + if (!strcmp(op->dev.of_node->name, "fan-control")) + attach_one_fan(bp, op, fan_index++); } - all_bbc_temps = NULL; + if (temp_index != 0 && fan_index != 0) { + kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); + if (IS_ERR(kenvctrld_task)) { + int err = PTR_ERR(kenvctrld_task); - fp = all_bbc_fans; - while (fp != NULL) { - struct bbc_fan_control *next = fp->next; - destroy_one_fan(fp); - fp = next; + kenvctrld_task = NULL; + destroy_all_temps(bp); + destroy_all_fans(bp); + return err; + } } - all_bbc_fans = NULL; + + return 0; +} + +void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) +{ + if (kenvctrld_task) + kthread_stop(kenvctrld_task); + + destroy_all_temps(bp); + destroy_all_fans(bp); } diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 7186235594f..c7763e482eb 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -1,8 +1,7 @@ -/* $Id: bbc_i2c.c,v 1.2 2001/04/02 09:59:08 davem Exp $ - * bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III +/* bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III * platforms. * - * Copyright (C) 2001 David S. Miller (davem@redhat.com) + * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) */ #include <linux/module.h> @@ -12,12 +11,11 @@ #include <linux/sched.h> #include <linux/wait.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/interrupt.h> -#include <asm/oplib.h> -#include <asm/ebus.h> -#include <asm/spitfire.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/bbc.h> +#include <asm/io.h> #include "bbc_i2c.h" @@ -52,54 +50,12 @@ * The second controller also connects to the smartcard reader, if present. */ -#define NUM_CHILDREN 8 -struct bbc_i2c_bus { - struct bbc_i2c_bus *next; - int index; - spinlock_t lock; - void __iomem *i2c_bussel_reg; - void __iomem *i2c_control_regs; - unsigned char own, clock; - - wait_queue_head_t wq; - volatile int waiting; - - struct linux_ebus_device *bus_edev; - struct { - struct linux_ebus_child *device; - int client_claimed; - } devs[NUM_CHILDREN]; -}; - -static struct bbc_i2c_bus *all_bbc_i2c; - -struct bbc_i2c_client { - struct bbc_i2c_bus *bp; - struct linux_ebus_child *echild; - int bus; - int address; -}; - -static int find_device(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild) +static void set_device_claimage(struct bbc_i2c_bus *bp, struct platform_device *op, int val) { int i; for (i = 0; i < NUM_CHILDREN; i++) { - if (bp->devs[i].device == echild) { - if (bp->devs[i].client_claimed) - return 0; - return 1; - } - } - return 0; -} - -static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild, int val) -{ - int i; - - for (i = 0; i < NUM_CHILDREN; i++) { - if (bp->devs[i].device == echild) { + if (bp->devs[i].device == op) { bp->devs[i].client_claimed = val; return; } @@ -109,62 +65,47 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) -static struct bbc_i2c_bus *find_bus_for_device(struct linux_ebus_child *echild) +struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) { - struct bbc_i2c_bus *bp = all_bbc_i2c; + struct platform_device *op = NULL; + int curidx = 0, i; - while (bp != NULL) { - if (find_device(bp, echild) != 0) + for (i = 0; i < NUM_CHILDREN; i++) { + if (!(op = bp->devs[i].device)) break; - bp = bp->next; + if (curidx == index) + goto out; + op = NULL; + curidx++; } - return bp; -} - -struct linux_ebus_child *bbc_i2c_getdev(int index) -{ - struct bbc_i2c_bus *bp = all_bbc_i2c; - struct linux_ebus_child *echild = NULL; - int curidx = 0; - - while (bp != NULL) { - struct bbc_i2c_bus *next = bp->next; - int i; - - for (i = 0; i < NUM_CHILDREN; i++) { - if (!(echild = bp->devs[i].device)) - break; - if (curidx == index) - goto out; - echild = NULL; - curidx++; - } - bp = next; - } out: if (curidx == index) - return echild; + return op; return NULL; } -struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild) +struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *op) { - struct bbc_i2c_bus *bp = find_bus_for_device(echild); struct bbc_i2c_client *client; + const u32 *reg; - if (!bp) - return NULL; - client = kmalloc(sizeof(*client), GFP_KERNEL); + client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) return NULL; - memset(client, 0, sizeof(*client)); client->bp = bp; - client->echild = echild; - client->bus = echild->resource[0].start; - client->address = echild->resource[1].start; + client->op = op; + + reg = of_get_property(op->dev.of_node, "reg", NULL); + if (!reg) { + kfree(client); + return NULL; + } + + client->bus = reg[0]; + client->address = reg[1]; - claim_device(bp, echild); + claim_device(bp, op); return client; } @@ -172,9 +113,9 @@ struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild) void bbc_i2c_detach(struct bbc_i2c_client *client) { struct bbc_i2c_bus *bp = client->bp; - struct linux_ebus_child *echild = client->echild; + struct platform_device *op = client->op; - release_device(bp, echild); + release_device(bp, op); kfree(client); } @@ -187,19 +128,20 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status) bp->waiting = 1; add_wait_queue(&bp->wq, &wait); while (limit-- > 0) { - u8 val; - - set_current_state(TASK_INTERRUPTIBLE); - *status = val = readb(bp->i2c_control_regs + 0); - if ((val & I2C_PCF_PIN) == 0) { + long val; + + val = wait_event_interruptible_timeout( + bp->wq, + (((*status = readb(bp->i2c_control_regs + 0)) + & I2C_PCF_PIN) == 0), + msecs_to_jiffies(250)); + if (val > 0) { ret = 0; break; } - msleep_interruptible(250); } remove_wait_queue(&bp->wq, &wait); bp->waiting = 0; - current->state = TASK_RUNNING; return ret; } @@ -290,13 +232,9 @@ int bbc_i2c_write_buf(struct bbc_i2c_client *client, int ret = 0; while (len > 0) { - int err = bbc_i2c_writeb(client, *buf, off); - - if (err < 0) { - ret = err; + ret = bbc_i2c_writeb(client, *buf, off); + if (ret < 0) break; - } - len--; buf++; off++; @@ -310,11 +248,9 @@ int bbc_i2c_read_buf(struct bbc_i2c_client *client, int ret = 0; while (len > 0) { - int err = bbc_i2c_readb(client, buf, off); - if (err < 0) { - ret = err; + ret = bbc_i2c_readb(client, buf, off); + if (ret < 0) break; - } len--; buf++; off++; @@ -331,7 +267,7 @@ EXPORT_SYMBOL(bbc_i2c_readb); EXPORT_SYMBOL(bbc_i2c_write_buf); EXPORT_SYMBOL(bbc_i2c_read_buf); -static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id) { struct bbc_i2c_bus *bp = dev_id; @@ -340,12 +276,12 @@ static irqreturn_t bbc_i2c_interrupt(int irq, void *dev_id, struct pt_regs *regs */ if (bp->waiting && !(readb(bp->i2c_control_regs + 0x0) & I2C_PCF_PIN)) - wake_up(&bp->wq); + wake_up_interruptible(&bp->wq); return IRQ_HANDLED; } -static void __init reset_one_i2c(struct bbc_i2c_bus *bp) +static void reset_one_i2c(struct bbc_i2c_bus *bp) { writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0); writeb(bp->own, bp->i2c_control_regs + 0x1); @@ -354,44 +290,43 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); } -static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) +static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index) { - struct bbc_i2c_bus *bp = kmalloc(sizeof(*bp), GFP_KERNEL); - struct linux_ebus_child *echild; + struct bbc_i2c_bus *bp; + struct device_node *dp; int entry; + bp = kzalloc(sizeof(*bp), GFP_KERNEL); if (!bp) - return -ENOMEM; - memset(bp, 0, sizeof(*bp)); + return NULL; - bp->i2c_control_regs = ioremap(edev->resource[0].start, 0x2); + bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs"); if (!bp->i2c_control_regs) goto fail; - if (edev->num_addrs == 2) { - bp->i2c_bussel_reg = ioremap(edev->resource[1].start, 0x1); - if (!bp->i2c_bussel_reg) - goto fail; - } + bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel"); + if (!bp->i2c_bussel_reg) + goto fail; bp->waiting = 0; init_waitqueue_head(&bp->wq); - if (request_irq(edev->irqs[0], bbc_i2c_interrupt, + if (request_irq(op->archdata.irqs[0], bbc_i2c_interrupt, IRQF_SHARED, "bbc_i2c", bp)) goto fail; bp->index = index; - bp->bus_edev = edev; + bp->op = op; spin_lock_init(&bp->lock); - bp->next = all_bbc_i2c; - all_bbc_i2c = bp; entry = 0; - for (echild = edev->children; - echild && entry < 8; - echild = echild->next, entry++) { - bp->devs[entry].device = echild; + for (dp = op->dev.of_node->child; + dp && entry < 8; + dp = dp->sibling, entry++) { + struct platform_device *child_op; + + child_op = of_find_device_by_node(dp); + bp->devs[entry].device = child_op; bp->devs[entry].client_claimed = 0; } @@ -405,86 +340,81 @@ static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) reset_one_i2c(bp); - return 0; + return bp; fail: if (bp->i2c_bussel_reg) - iounmap(bp->i2c_bussel_reg); + of_iounmap(&op->resource[1], bp->i2c_bussel_reg, 1); if (bp->i2c_control_regs) - iounmap(bp->i2c_control_regs); + of_iounmap(&op->resource[0], bp->i2c_control_regs, 2); kfree(bp); - return -EINVAL; -} - -static int __init bbc_present(void) -{ - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "bbc")) - return 1; - } - } - return 0; + return NULL; } -extern int bbc_envctrl_init(void); -extern void bbc_envctrl_cleanup(void); -static void bbc_i2c_cleanup(void); +extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); +extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); -static int __init bbc_i2c_init(void) +static int bbc_i2c_probe(struct platform_device *op) { - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; + struct bbc_i2c_bus *bp; int err, index = 0; - if ((tlb_type != cheetah && tlb_type != cheetah_plus) || - !bbc_present()) - return -ENODEV; + bp = attach_one_i2c(op, index); + if (!bp) + return -EINVAL; - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "i2c")) { - if (!attach_one_i2c(edev, index)) - index++; - } - } + err = bbc_envctrl_init(bp); + if (err) { + free_irq(op->archdata.irqs[0], bp); + if (bp->i2c_bussel_reg) + of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); + if (bp->i2c_control_regs) + of_iounmap(&op->resource[1], bp->i2c_control_regs, 2); + kfree(bp); + } else { + dev_set_drvdata(&op->dev, bp); } - if (!index) - return -ENODEV; - - err = bbc_envctrl_init(); - if (err) - bbc_i2c_cleanup(); return err; } -static void bbc_i2c_cleanup(void) +static int bbc_i2c_remove(struct platform_device *op) { - struct bbc_i2c_bus *bp = all_bbc_i2c; - - bbc_envctrl_cleanup(); + struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); - while (bp != NULL) { - struct bbc_i2c_bus *next = bp->next; + bbc_envctrl_cleanup(bp); - free_irq(bp->bus_edev->irqs[0], bp); + free_irq(op->archdata.irqs[0], bp); - if (bp->i2c_bussel_reg) - iounmap(bp->i2c_bussel_reg); - if (bp->i2c_control_regs) - iounmap(bp->i2c_control_regs); + if (bp->i2c_bussel_reg) + of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); + if (bp->i2c_control_regs) + of_iounmap(&op->resource[1], bp->i2c_control_regs, 2); - kfree(bp); + kfree(bp); - bp = next; - } - all_bbc_i2c = NULL; + return 0; } -module_init(bbc_i2c_init); -module_exit(bbc_i2c_cleanup); +static const struct of_device_id bbc_i2c_match[] = { + { + .name = "i2c", + .compatible = "SUNW,bbc-i2c", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, bbc_i2c_match); + +static struct platform_driver bbc_i2c_driver = { + .driver = { + .name = "bbc_i2c", + .owner = THIS_MODULE, + .of_match_table = bbc_i2c_match, + }, + .probe = bbc_i2c_probe, + .remove = bbc_i2c_remove, +}; + +module_platform_driver(bbc_i2c_driver); + MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h index fb01bd17704..4b4531066e7 100644 --- a/drivers/sbus/char/bbc_i2c.h +++ b/drivers/sbus/char/bbc_i2c.h @@ -1,14 +1,79 @@ -/* $Id: bbc_i2c.h,v 1.2 2001/04/02 09:59:25 davem Exp $ */ #ifndef _BBC_I2C_H #define _BBC_I2C_H -#include <asm/ebus.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/list.h> -struct bbc_i2c_client; +struct bbc_i2c_client { + struct bbc_i2c_bus *bp; + struct platform_device *op; + int bus; + int address; +}; + +enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; + +struct bbc_cpu_temperature { + struct list_head bp_list; + struct list_head glob_list; + + struct bbc_i2c_client *client; + int index; + + /* Current readings, and history. */ + s8 curr_cpu_temp; + s8 curr_amb_temp; + s8 prev_cpu_temp; + s8 prev_amb_temp; + s8 avg_cpu_temp; + s8 avg_amb_temp; + + int sample_tick; + + enum fan_action fan_todo[2]; +#define FAN_AMBIENT 0 +#define FAN_CPU 1 +}; + +struct bbc_fan_control { + struct list_head bp_list; + struct list_head glob_list; + + struct bbc_i2c_client *client; + int index; + + int psupply_fan_on; + int cpu_fan_speed; + int system_fan_speed; +}; + +#define NUM_CHILDREN 8 + +struct bbc_i2c_bus { + struct bbc_i2c_bus *next; + int index; + spinlock_t lock; + void __iomem *i2c_bussel_reg; + void __iomem *i2c_control_regs; + unsigned char own, clock; + + wait_queue_head_t wq; + volatile int waiting; + + struct list_head temps; + struct list_head fans; + + struct platform_device *op; + struct { + struct platform_device *device; + int client_claimed; + } devs[NUM_CHILDREN]; +}; /* Probing and attachment. */ -extern struct linux_ebus_child *bbc_i2c_getdev(int); -extern struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *); +extern struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); +extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *); extern void bbc_i2c_detach(struct bbc_i2c_client *); /* Register read/write. NOTE: Blocking! */ diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c deleted file mode 100644 index 385f4f76831..00000000000 --- a/drivers/sbus/char/bpp.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * drivers/sbus/char/bpp.c - * - * Copyright (c) 1995 Picture Elements - * Stephen Williams (steve@icarus.com) - * Gus Baldauf (gbaldauf@ix.netcom.com) - * - * Linux/SPARC port by Peter Zaitcev. - * Integration into SPARC tree by Tom Dyas. - */ - - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/smp_lock.h> -#include <linux/spinlock.h> -#include <linux/timer.h> -#include <linux/ioport.h> -#include <linux/major.h> - -#include <asm/uaccess.h> -#include <asm/io.h> - -#if defined(__i386__) -# include <asm/system.h> -#endif - -#if defined(__sparc__) -# include <linux/init.h> -# include <linux/delay.h> /* udelay() */ - -# include <asm/oplib.h> /* OpenProm Library */ -# include <asm/sbus.h> -#endif - -#include <asm/bpp.h> - -#define BPP_PROBE_CODE 0x55 -#define BPP_DELAY 100 - -static const unsigned BPP_MAJOR = LP_MAJOR; -static const char* dev_name = "bpp"; - -/* When switching from compatibility to a mode where I can read, try - the following mode first. */ - -/* const unsigned char DEFAULT_ECP = 0x10; */ -static const unsigned char DEFAULT_ECP = 0x30; -static const unsigned char DEFAULT_NIBBLE = 0x00; - -/* - * These are 1284 time constraints, in units of jiffies. - */ - -static const unsigned long TIME_PSetup = 1; -static const unsigned long TIME_PResponse = 6; -static const unsigned long TIME_IDLE_LIMIT = 2000; - -/* - * One instance per supported subdevice... - */ -# define BPP_NO 3 - -enum IEEE_Mode { COMPATIBILITY, NIBBLE, ECP, ECP_RLE, EPP }; - -struct inst { - unsigned present : 1; /* True if the hardware exists */ - unsigned enhanced : 1; /* True if the hardware in "enhanced" */ - unsigned opened : 1; /* True if the device is opened already */ - unsigned run_flag : 1; /* True if waiting for a repeate byte */ - - unsigned char direction; /* 0 --> out, 0x20 --> IN */ - unsigned char pp_state; /* State of host controlled pins. */ - enum IEEE_Mode mode; - - unsigned char run_length; - unsigned char repeat_byte; -}; - -static struct inst instances[BPP_NO]; - -#if defined(__i386__) - -static const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc }; - -/* - * These are for data access. - * Control lines accesses are hidden in set_bits() and get_bits(). - * The exception is the probe procedure, which is system-dependent. - */ -#define bpp_outb_p(data, base) outb_p((data), (base)) -#define bpp_inb(base) inb(base) -#define bpp_inb_p(base) inb_p(base) - -/* - * This method takes the pin values mask and sets the hardware pins to - * the requested value: 1 == high voltage, 0 == low voltage. This - * burries the annoying PC bit inversion and preserves the direction - * flag. - */ -static void set_pins(unsigned short pins, unsigned minor) -{ - unsigned char bits = instances[minor].direction; /* == 0x20 */ - - if (! (pins & BPP_PP_nStrobe)) bits |= 1; - if (! (pins & BPP_PP_nAutoFd)) bits |= 2; - if ( pins & BPP_PP_nInit) bits |= 4; - if (! (pins & BPP_PP_nSelectIn)) bits |= 8; - - instances[minor].pp_state = bits; - - outb_p(bits, base_addrs[minor]+2); -} - -static unsigned short get_pins(unsigned minor) -{ - unsigned short bits = 0; - - unsigned value = instances[minor].pp_state; - if (! (value & 0x01)) bits |= BPP_PP_nStrobe; - if (! (value & 0x02)) bits |= BPP_PP_nAutoFd; - if (value & 0x04) bits |= BPP_PP_nInit; - if (! (value & 0x08)) bits |= BPP_PP_nSelectIn; - - value = inb_p(base_addrs[minor]+1); - if (value & 0x08) bits |= BPP_GP_nFault; - if (value & 0x10) bits |= BPP_GP_Select; - if (value & 0x20) bits |= BPP_GP_PError; - if (value & 0x40) bits |= BPP_GP_nAck; - if (! (value & 0x80)) bits |= BPP_GP_Busy; - - return bits; -} - -#endif /* __i386__ */ - -#if defined(__sparc__) - -/* - * Register block - */ - /* DMA registers */ -#define BPP_CSR 0x00 -#define BPP_ADDR 0x04 -#define BPP_BCNT 0x08 -#define BPP_TST_CSR 0x0C - /* Parallel Port registers */ -#define BPP_HCR 0x10 -#define BPP_OCR 0x12 -#define BPP_DR 0x14 -#define BPP_TCR 0x15 -#define BPP_OR 0x16 -#define BPP_IR 0x17 -#define BPP_ICR 0x18 -#define BPP_SIZE 0x1A - -/* BPP_CSR. Bits of type RW1 are cleared with writting '1'. */ -#define P_DEV_ID_MASK 0xf0000000 /* R */ -#define P_DEV_ID_ZEBRA 0x40000000 -#define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */ -#define P_NA_LOADED 0x08000000 /* R NA wirtten but was not used */ -#define P_A_LOADED 0x04000000 /* R */ -#define P_DMA_ON 0x02000000 /* R DMA is not disabled */ -#define P_EN_NEXT 0x01000000 /* RW */ -#define P_TCI_DIS 0x00800000 /* RW TCI forbidden from interrupts */ -#define P_DIAG 0x00100000 /* RW Disables draining and resetting - of P-FIFO on loading of P_ADDR*/ -#define P_BURST_SIZE 0x000c0000 /* RW SBus burst size */ -#define P_BURST_8 0x00000000 -#define P_BURST_4 0x00040000 -#define P_BURST_1 0x00080000 /* "No burst" write */ -#define P_TC 0x00004000 /* RW1 Term Count, can be cleared when - P_EN_NEXT=1 */ -#define P_EN_CNT 0x00002000 /* RW */ -#define P_EN_DMA 0x00000200 /* RW */ -#define P_WRITE 0x00000100 /* R DMA dir, 1=to ram, 0=to port */ -#define P_RESET 0x00000080 /* RW */ -#define P_SLAVE_ERR 0x00000040 /* RW1 Access size error */ -#define P_INVALIDATE 0x00000020 /* W Drop P-FIFO */ -#define P_INT_EN 0x00000010 /* RW OK to P_INT_PEND||P_ERR_PEND */ -#define P_DRAINING 0x0000000c /* R P-FIFO is draining to memory */ -#define P_ERR_PEND 0x00000002 /* R */ -#define P_INT_PEND 0x00000001 /* R */ - -/* BPP_HCR. Time is in increments of SBus clock. */ -#define P_HCR_TEST 0x8000 /* Allows buried counters to be read */ -#define P_HCR_DSW 0x7f00 /* Data strobe width (in ticks) */ -#define P_HCR_DDS 0x007f /* Data setup before strobe (in ticks) */ - -/* BPP_OCR. */ -#define P_OCR_MEM_CLR 0x8000 -#define P_OCR_DATA_SRC 0x4000 /* ) */ -#define P_OCR_DS_DSEL 0x2000 /* ) Bidirectional */ -#define P_OCR_BUSY_DSEL 0x1000 /* ) selects */ -#define P_OCR_ACK_DSEL 0x0800 /* ) */ -#define P_OCR_EN_DIAG 0x0400 -#define P_OCR_BUSY_OP 0x0200 /* Busy operation */ -#define P_OCR_ACK_OP 0x0100 /* Ack operation */ -#define P_OCR_SRST 0x0080 /* Reset state machines. Not selfcleaning. */ -#define P_OCR_IDLE 0x0008 /* PP data transfer state machine is idle */ -#define P_OCR_V_ILCK 0x0002 /* Versatec faded. Zebra only. */ -#define P_OCR_EN_VER 0x0001 /* Enable Versatec (0 - enable). Zebra only. */ - -/* BPP_TCR */ -#define P_TCR_DIR 0x08 -#define P_TCR_BUSY 0x04 -#define P_TCR_ACK 0x02 -#define P_TCR_DS 0x01 /* Strobe */ - -/* BPP_OR */ -#define P_OR_V3 0x20 /* ) */ -#define P_OR_V2 0x10 /* ) on Zebra only */ -#define P_OR_V1 0x08 /* ) */ -#define P_OR_INIT 0x04 -#define P_OR_AFXN 0x02 /* Auto Feed */ -#define P_OR_SLCT_IN 0x01 - -/* BPP_IR */ -#define P_IR_PE 0x04 -#define P_IR_SLCT 0x02 -#define P_IR_ERR 0x01 - -/* BPP_ICR */ -#define P_DS_IRQ 0x8000 /* RW1 */ -#define P_ACK_IRQ 0x4000 /* RW1 */ -#define P_BUSY_IRQ 0x2000 /* RW1 */ -#define P_PE_IRQ 0x1000 /* RW1 */ -#define P_SLCT_IRQ 0x0800 /* RW1 */ -#define P_ERR_IRQ 0x0400 /* RW1 */ -#define P_DS_IRQ_EN 0x0200 /* RW Always on rising edge */ -#define P_ACK_IRQ_EN 0x0100 /* RW Always on rising edge */ -#define P_BUSY_IRP 0x0080 /* RW 1= rising edge */ -#define P_BUSY_IRQ_EN 0x0040 /* RW */ -#define P_PE_IRP 0x0020 /* RW 1= rising edge */ -#define P_PE_IRQ_EN 0x0010 /* RW */ -#define P_SLCT_IRP 0x0008 /* RW 1= rising edge */ -#define P_SLCT_IRQ_EN 0x0004 /* RW */ -#define P_ERR_IRP 0x0002 /* RW1 1= rising edge */ -#define P_ERR_IRQ_EN 0x0001 /* RW */ - -static void __iomem *base_addrs[BPP_NO]; - -#define bpp_outb_p(data, base) sbus_writeb(data, (base) + BPP_DR) -#define bpp_inb_p(base) sbus_readb((base) + BPP_DR) -#define bpp_inb(base) sbus_readb((base) + BPP_DR) - -static void set_pins(unsigned short pins, unsigned minor) -{ - void __iomem *base = base_addrs[minor]; - unsigned char bits_tcr = 0, bits_or = 0; - - if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR; - if ( pins & BPP_PP_nStrobe) bits_tcr |= P_TCR_DS; - - if ( pins & BPP_PP_nAutoFd) bits_or |= P_OR_AFXN; - if (! (pins & BPP_PP_nInit)) bits_or |= P_OR_INIT; - if (! (pins & BPP_PP_nSelectIn)) bits_or |= P_OR_SLCT_IN; - - sbus_writeb(bits_or, base + BPP_OR); - sbus_writeb(bits_tcr, base + BPP_TCR); -} - -/* - * i386 people read output pins from a software image. - * We may get them back from hardware. - * Again, inversion of pins must he buried here. - */ -static unsigned short get_pins(unsigned minor) -{ - void __iomem *base = base_addrs[minor]; - unsigned short bits = 0; - unsigned value_tcr = sbus_readb(base + BPP_TCR); - unsigned value_ir = sbus_readb(base + BPP_IR); - unsigned value_or = sbus_readb(base + BPP_OR); - - if (value_tcr & P_TCR_DS) bits |= BPP_PP_nStrobe; - if (value_or & P_OR_AFXN) bits |= BPP_PP_nAutoFd; - if (! (value_or & P_OR_INIT)) bits |= BPP_PP_nInit; - if (! (value_or & P_OR_SLCT_IN)) bits |= BPP_PP_nSelectIn; - - if (value_ir & P_IR_ERR) bits |= BPP_GP_nFault; - if (! (value_ir & P_IR_SLCT)) bits |= BPP_GP_Select; - if (! (value_ir & P_IR_PE)) bits |= BPP_GP_PError; - if (! (value_tcr & P_TCR_ACK)) bits |= BPP_GP_nAck; - if (value_tcr & P_TCR_BUSY) bits |= BPP_GP_Busy; - - return bits; -} - -#endif /* __sparc__ */ - -static void snooze(unsigned long snooze_time, unsigned minor) -{ - schedule_timeout_uninterruptible(snooze_time + 1); -} - -static int wait_for(unsigned short set, unsigned short clr, - unsigned long delay, unsigned minor) -{ - unsigned short pins = get_pins(minor); - - unsigned long extime = 0; - - /* - * Try a real fast scan for the first jiffy, in case the device - * responds real good. The first while loop guesses an expire - * time accounting for possible wraparound of jiffies. - */ - while (time_after_eq(jiffies, extime)) extime = jiffies + 1; - while ( (time_before(jiffies, extime)) - && (((pins & set) != set) || ((pins & clr) != 0)) ) { - pins = get_pins(minor); - } - - delay -= 1; - - /* - * If my delay expired or the pins are still not where I want - * them, then resort to using the timer and greatly reduce my - * sample rate. If the peripheral is going to be slow, this will - * give the CPU up to some more worthy process. - */ - while ( delay && (((pins & set) != set) || ((pins & clr) != 0)) ) { - - snooze(1, minor); - pins = get_pins(minor); - delay -= 1; - } - - if (delay == 0) return -1; - else return pins; -} - -/* - * Return ZERO(0) If the negotiation succeeds, an errno otherwise. An - * errno means something broke, and I do not yet know how to fix it. - */ -static int negotiate(unsigned char mode, unsigned minor) -{ - int rc; - unsigned short pins = get_pins(minor); - if (pins & BPP_PP_nSelectIn) return -EIO; - - - /* Event 0: Write the mode to the data lines */ - bpp_outb_p(mode, base_addrs[minor]); - - snooze(TIME_PSetup, minor); - - /* Event 1: Strobe the mode code into the peripheral */ - set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nInit, minor); - - /* Wait for Event 2: Peripheral responds as a 1284 device. */ - rc = wait_for(BPP_GP_PError|BPP_GP_Select|BPP_GP_nFault, - BPP_GP_nAck, - TIME_PResponse, - minor); - - if (rc == -1) return -ETIMEDOUT; - - /* Event 3: latch extensibility request */ - set_pins(BPP_PP_nSelectIn|BPP_PP_nInit, minor); - - /* ... quick nap while peripheral ponders the byte i'm sending...*/ - snooze(1, minor); - - /* Event 4: restore strobe, to ACK peripheral's response. */ - set_pins(BPP_PP_nSelectIn|BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); - - /* Wait for Event 6: Peripheral latches response bits */ - rc = wait_for(BPP_GP_nAck, 0, TIME_PSetup+TIME_PResponse, minor); - if (rc == -1) return -EIO; - - /* A 1284 device cannot refuse nibble mode */ - if (mode == DEFAULT_NIBBLE) return 0; - - if (pins & BPP_GP_Select) return 0; - - return -EPROTONOSUPPORT; -} - -static int terminate(unsigned minor) -{ - int rc; - - /* Event 22: Request termination of 1284 mode */ - set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); - - /* Wait for Events 23 and 24: ACK termination request. */ - rc = wait_for(BPP_GP_Busy|BPP_GP_nFault, - BPP_GP_nAck, - TIME_PSetup+TIME_PResponse, - minor); - - instances[minor].direction = 0; - instances[minor].mode = COMPATIBILITY; - - if (rc == -1) { - return -EIO; - } - - /* Event 25: Handshake by lowering nAutoFd */ - set_pins(BPP_PP_nStrobe|BPP_PP_nInit, minor); - - /* Event 26: Peripheral wiggles lines... */ - - /* Event 27: Peripheral sets nAck HIGH to ack handshake */ - rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); - if (rc == -1) { - set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); - return -EIO; - } - - /* Event 28: Finish phase by raising nAutoFd */ - set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); - - return 0; -} - -static DEFINE_SPINLOCK(bpp_open_lock); - -/* - * Allow only one process to open the device at a time. - */ -static int bpp_open(struct inode *inode, struct file *f) -{ - unsigned minor = iminor(inode); - int ret; - - spin_lock(&bpp_open_lock); - ret = 0; - if (minor >= BPP_NO) { - ret = -ENODEV; - } else { - if (! instances[minor].present) { - ret = -ENODEV; - } else { - if (instances[minor].opened) - ret = -EBUSY; - else - instances[minor].opened = 1; - } - } - spin_unlock(&bpp_open_lock); - - return ret; -} - -/* - * When the process closes the device, this method is called to clean - * up and reset the hardware. Always leave the device in compatibility - * mode as this is a reasonable place to clean up from messes made by - * ioctls, or other mayhem. - */ -static int bpp_release(struct inode *inode, struct file *f) -{ - unsigned minor = iminor(inode); - - spin_lock(&bpp_open_lock); - instances[minor].opened = 0; - - if (instances[minor].mode != COMPATIBILITY) - terminate(minor); - - spin_unlock(&bpp_open_lock); - - return 0; -} - -static long read_nibble(unsigned minor, char __user *c, unsigned long cnt) -{ - unsigned long remaining = cnt; - long rc; - - while (remaining > 0) { - unsigned char byte = 0; - int pins; - - /* Event 7: request nibble */ - set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); - - /* Wait for event 9: Peripher strobes first nibble */ - pins = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); - if (pins == -1) return -ETIMEDOUT; - - /* Event 10: I handshake nibble */ - set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); - if (pins & BPP_GP_nFault) byte |= 0x01; - if (pins & BPP_GP_Select) byte |= 0x02; - if (pins & BPP_GP_PError) byte |= 0x04; - if (pins & BPP_GP_Busy) byte |= 0x08; - - /* Wait for event 11: Peripheral handshakes nibble */ - rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); - - /* Event 7: request nibble */ - set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); - - /* Wait for event 9: Peripher strobes first nibble */ - pins = wait_for(0, BPP_GP_nAck, TIME_PResponse, minor); - if (rc == -1) return -ETIMEDOUT; - - /* Event 10: I handshake nibble */ - set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); - if (pins & BPP_GP_nFault) byte |= 0x10; - if (pins & BPP_GP_Select) byte |= 0x20; - if (pins & BPP_GP_PError) byte |= 0x40; - if (pins & BPP_GP_Busy) byte |= 0x80; - - if (put_user(byte, c)) - return -EFAULT; - c += 1; - remaining -= 1; - - /* Wait for event 11: Peripheral handshakes nibble */ - rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); - if (rc == -1) return -EIO; - } - - return cnt - remaining; -} - -static long read_ecp(unsigned minor, char __user *c, unsigned long cnt) -{ - unsigned long remaining; - long rc; - - /* Turn ECP mode from forward to reverse if needed. */ - if (! instances[minor].direction) { - unsigned short pins = get_pins(minor); - - /* Event 38: Turn the bus around */ - instances[minor].direction = 0x20; - pins &= ~BPP_PP_nAutoFd; - set_pins(pins, minor); - - /* Event 39: Set pins for reverse mode. */ - snooze(TIME_PSetup, minor); - set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); - - /* Wait for event 40: Peripheral ready to be strobed */ - rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor); - if (rc == -1) return -ETIMEDOUT; - } - - remaining = cnt; - - while (remaining > 0) { - - /* If there is a run length for a repeated byte, repeat */ - /* that byte a few times. */ - if (instances[minor].run_length && !instances[minor].run_flag) { - - char buffer[128]; - unsigned idx; - unsigned repeat = remaining < instances[minor].run_length - ? remaining - : instances[minor].run_length; - - for (idx = 0 ; idx < repeat ; idx += 1) - buffer[idx] = instances[minor].repeat_byte; - - if (copy_to_user(c, buffer, repeat)) - return -EFAULT; - remaining -= repeat; - c += repeat; - instances[minor].run_length -= repeat; - } - - if (remaining == 0) break; - - - /* Wait for Event 43: Data active on the bus. */ - rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); - if (rc == -1) break; - - if (rc & BPP_GP_Busy) { - /* OK, this is data. read it in. */ - unsigned char byte = bpp_inb(base_addrs[minor]); - if (put_user(byte, c)) - return -EFAULT; - c += 1; - remaining -= 1; - - if (instances[minor].run_flag) { - instances[minor].repeat_byte = byte; - instances[minor].run_flag = 0; - } - - } else { - unsigned char byte = bpp_inb(base_addrs[minor]); - if (byte & 0x80) { - printk("bpp%d: " - "Ignoring ECP channel %u from device.\n", - minor, byte & 0x7f); - } else { - instances[minor].run_length = byte; - instances[minor].run_flag = 1; - } - } - - /* Event 44: I got it. */ - set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor); - - /* Wait for event 45: peripheral handshake */ - rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); - if (rc == -1) return -ETIMEDOUT; - - /* Event 46: Finish handshake */ - set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); - - } - - - return cnt - remaining; -} - -static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos) -{ - long rc; - unsigned minor = iminor(f->f_dentry->d_inode); - if (minor >= BPP_NO) return -ENODEV; - if (!instances[minor].present) return -ENODEV; - - switch (instances[minor].mode) { - - default: - if (instances[minor].mode != COMPATIBILITY) - terminate(minor); - - if (instances[minor].enhanced) { - /* For now, do all reads with ECP-RLE mode */ - unsigned short pins; - - rc = negotiate(DEFAULT_ECP, minor); - if (rc < 0) break; - - instances[minor].mode = ECP_RLE; - - /* Event 30: set nAutoFd low to setup for ECP mode */ - pins = get_pins(minor); - pins &= ~BPP_PP_nAutoFd; - set_pins(pins, minor); - - /* Wait for Event 31: peripheral ready */ - rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); - if (rc == -1) return -ETIMEDOUT; - - rc = read_ecp(minor, c, cnt); - - } else { - rc = negotiate(DEFAULT_NIBBLE, minor); - if (rc < 0) break; - - instances[minor].mode = NIBBLE; - - rc = read_nibble(minor, c, cnt); - } - break; - - case NIBBLE: - rc = read_nibble(minor, c, cnt); - break; - - case ECP: - case ECP_RLE: - rc = read_ecp(minor, c, cnt); - break; - - } - - - return rc; -} - -/* - * Compatibility mode handshaking is a matter of writing data, - * strobing it, and waiting for the printer to stop being busy. - */ -static long write_compat(unsigned minor, const char __user *c, unsigned long cnt) -{ - long rc; - unsigned short pins = get_pins(minor); - - unsigned long remaining = cnt; - - - while (remaining > 0) { - unsigned char byte; - - if (get_user(byte, c)) - return -EFAULT; - c += 1; - - rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); - if (rc == -1) return -ETIMEDOUT; - - bpp_outb_p(byte, base_addrs[minor]); - remaining -= 1; - /* snooze(1, minor); */ - - pins &= ~BPP_PP_nStrobe; - set_pins(pins, minor); - - rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); - - pins |= BPP_PP_nStrobe; - set_pins(pins, minor); - } - - return cnt - remaining; -} - -/* - * Write data using ECP mode. Watch out that the port may be set up - * for reading. If so, turn the port around. - */ -static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) -{ - unsigned short pins = get_pins(minor); - unsigned long remaining = cnt; - - if (instances[minor].direction) { - int rc; - - /* Event 47 Request bus be turned around */ - pins |= BPP_PP_nInit; - set_pins(pins, minor); - - /* Wait for Event 49: Peripheral relinquished bus */ - rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); - - pins |= BPP_PP_nAutoFd; - instances[minor].direction = 0; - set_pins(pins, minor); - } - - while (remaining > 0) { - unsigned char byte; - int rc; - - if (get_user(byte, c)) - return -EFAULT; - - rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor); - if (rc == -1) return -ETIMEDOUT; - - c += 1; - - bpp_outb_p(byte, base_addrs[minor]); - - pins &= ~BPP_PP_nStrobe; - set_pins(pins, minor); - - pins |= BPP_PP_nStrobe; - rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); - if (rc == -1) return -EIO; - - set_pins(pins, minor); - } - - return cnt - remaining; -} - -/* - * Write to the peripheral. Be sensitive of the current mode. If I'm - * in a mode that can be turned around (ECP) then just do - * that. Otherwise, terminate and do my writing in compat mode. This - * is the safest course as any device can handle it. - */ -static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos) -{ - long errno = 0; - unsigned minor = iminor(f->f_dentry->d_inode); - if (minor >= BPP_NO) return -ENODEV; - if (!instances[minor].present) return -ENODEV; - - switch (instances[minor].mode) { - - case ECP: - case ECP_RLE: - errno = write_ecp(minor, c, cnt); - break; - case COMPATIBILITY: - errno = write_compat(minor, c, cnt); - break; - default: - terminate(minor); - errno = write_compat(minor, c, cnt); - } - - return errno; -} - -static int bpp_ioctl(struct inode *inode, struct file *f, unsigned int cmd, - unsigned long arg) -{ - int errno = 0; - - unsigned minor = iminor(inode); - if (minor >= BPP_NO) return -ENODEV; - if (!instances[minor].present) return -ENODEV; - - - switch (cmd) { - - case BPP_PUT_PINS: - set_pins(arg, minor); - break; - - case BPP_GET_PINS: - errno = get_pins(minor); - break; - - case BPP_PUT_DATA: - bpp_outb_p(arg, base_addrs[minor]); - break; - - case BPP_GET_DATA: - errno = bpp_inb_p(base_addrs[minor]); - break; - - case BPP_SET_INPUT: - if (arg) - if (instances[minor].enhanced) { - unsigned short bits = get_pins(minor); - instances[minor].direction = 0x20; - set_pins(bits, minor); - } else { - errno = -ENOTTY; - } - else { - unsigned short bits = get_pins(minor); - instances[minor].direction = 0x00; - set_pins(bits, minor); - } - break; - - default: - errno = -EINVAL; - } - - return errno; -} - -static struct file_operations bpp_fops = { - .owner = THIS_MODULE, - .read = bpp_read, - .write = bpp_write, - .ioctl = bpp_ioctl, - .open = bpp_open, - .release = bpp_release, -}; - -#if defined(__i386__) - -#define collectLptPorts() {} - -static void probeLptPort(unsigned idx) -{ - unsigned int testvalue; - const unsigned short lpAddr = base_addrs[idx]; - - instances[idx].present = 0; - instances[idx].enhanced = 0; - instances[idx].direction = 0; - instances[idx].mode = COMPATIBILITY; - instances[idx].run_length = 0; - instances[idx].run_flag = 0; - if (!request_region(lpAddr,3, dev_name)) return; - - /* - * First, make sure the instance exists. Do this by writing to - * the data latch and reading the value back. If the port *is* - * present, test to see if it supports extended-mode - * operation. This will be required for IEEE1284 reverse - * transfers. - */ - - outb_p(BPP_PROBE_CODE, lpAddr); - for (testvalue=0; testvalue<BPP_DELAY; testvalue++) - ; - testvalue = inb_p(lpAddr); - if (testvalue == BPP_PROBE_CODE) { - unsigned save; - instances[idx].present = 1; - - save = inb_p(lpAddr+2); - for (testvalue=0; testvalue<BPP_DELAY; testvalue++) - ; - outb_p(save|0x20, lpAddr+2); - for (testvalue=0; testvalue<BPP_DELAY; testvalue++) - ; - outb_p(~BPP_PROBE_CODE, lpAddr); - for (testvalue=0; testvalue<BPP_DELAY; testvalue++) - ; - testvalue = inb_p(lpAddr); - if ((testvalue&0xff) == (0xff&~BPP_PROBE_CODE)) - instances[idx].enhanced = 0; - else - instances[idx].enhanced = 1; - outb_p(save, lpAddr+2); - } - else { - release_region(lpAddr,3); - } - /* - * Leave the port in compat idle mode. - */ - set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); - - printk("bpp%d: Port at 0x%03x: Enhanced mode %s\n", idx, base_addrs[idx], - instances[idx].enhanced? "SUPPORTED" : "UNAVAILABLE"); -} - -static inline void freeLptPort(int idx) -{ - release_region(base_addrs[idx], 3); -} - -#endif - -#if defined(__sparc__) - -static void __iomem *map_bpp(struct sbus_dev *dev, int idx) -{ - return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp"); -} - -static int collectLptPorts(void) -{ - struct sbus_bus *bus; - struct sbus_dev *dev; - int count; - - count = 0; - for_all_sbusdev(dev, bus) { - if (strcmp(dev->prom_name, "SUNW,bpp") == 0) { - if (count >= BPP_NO) { - printk(KERN_NOTICE - "bpp: More than %d bpp ports," - " rest is ignored\n", BPP_NO); - return count; - } - base_addrs[count] = map_bpp(dev, count); - count++; - } - } - return count; -} - -static void probeLptPort(unsigned idx) -{ - void __iomem *rp = base_addrs[idx]; - __u32 csr; - char *brand; - - instances[idx].present = 0; - instances[idx].enhanced = 0; - instances[idx].direction = 0; - instances[idx].mode = COMPATIBILITY; - instances[idx].run_length = 0; - instances[idx].run_flag = 0; - - if (!rp) return; - - instances[idx].present = 1; - instances[idx].enhanced = 1; /* Sure */ - - csr = sbus_readl(rp + BPP_CSR); - if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { - udelay(20); - csr = sbus_readl(rp + BPP_CSR); - if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { - printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr); - } - } - printk("bpp%d: reset with 0x%08x ..", idx, csr); - sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR); - udelay(500); - sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR); - csr = sbus_readl(rp + BPP_CSR); - printk(" done with csr=0x%08x ocr=0x%04x\n", - csr, sbus_readw(rp + BPP_OCR)); - - switch (csr & P_DEV_ID_MASK) { - case P_DEV_ID_ZEBRA: - brand = "Zebra"; - break; - case P_DEV_ID_L64854: - brand = "DMA2"; - break; - default: - brand = "Unknown"; - } - printk("bpp%d: %s at %p\n", idx, brand, rp); - - /* - * Leave the port in compat idle mode. - */ - set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); - - return; -} - -static inline void freeLptPort(int idx) -{ - sbus_iounmap(base_addrs[idx], BPP_SIZE); -} - -#endif - -static int __init bpp_init(void) -{ - int rc; - unsigned idx; - - rc = collectLptPorts(); - if (rc == 0) - return -ENODEV; - - rc = register_chrdev(BPP_MAJOR, dev_name, &bpp_fops); - if (rc < 0) - return rc; - - for (idx = 0; idx < BPP_NO; idx++) { - instances[idx].opened = 0; - probeLptPort(idx); - } - - return 0; -} - -static void __exit bpp_cleanup(void) -{ - unsigned idx; - - unregister_chrdev(BPP_MAJOR, dev_name); - - for (idx = 0; idx < BPP_NO; idx++) { - if (instances[idx].present) - freeLptPort(idx); - } -} - -module_init(bpp_init); -module_exit(bpp_cleanup); - -MODULE_LICENSE("GPL"); - diff --git a/drivers/sbus/char/cd180.h b/drivers/sbus/char/cd180.h deleted file mode 100644 index 445b86cc65e..00000000000 --- a/drivers/sbus/char/cd180.h +++ /dev/null @@ -1,240 +0,0 @@ - -/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */ -#define CD180_NCH 8 /* Total number of channels */ -#define CD180_TPC 16 /* Ticks per character */ -#define CD180_NFIFO 8 /* TX FIFO size */ - -/* Global registers */ -#define CD180_GFRCR 0x6b /* Global Firmware Revision Code Register */ -#define CD180_SRCR 0x66 /* Service Request Configuration Register */ -#define CD180_PPRH 0x70 /* Prescaler Period Register High */ -#define CD180_PPRL 0x71 /* Prescaler Period Register Low */ -#define CD180_MSMR 0x61 /* Modem Service Match Register */ -#define CD180_TSMR 0x62 /* Transmit Service Match Register */ -#define CD180_RSMR 0x63 /* Receive Service Match Register */ -#define CD180_GSVR 0x40 /* Global Service Vector Register */ -#define CD180_SRSR 0x65 /* Service Request Status Register */ -#define CD180_GSCR 0x41 /* Global Service Channel Register */ -#define CD180_CAR 0x64 /* Channel Access Register */ - -/* Indexed registers */ -#define CD180_RDCR 0x07 /* Receive Data Count Register */ -#define CD180_RDR 0x78 /* Receiver Data Register */ -#define CD180_RCSR 0x7a /* Receiver Character Status Register */ -#define CD180_TDR 0x7b /* Transmit Data Register */ -#define CD180_EOSRR 0x7f /* End of Service Request Register */ - -/* Channel Registers */ -#define CD180_SRER 0x02 /* Service Request Enable Register */ -#define CD180_CCR 0x01 /* Channel Command Register */ -#define CD180_COR1 0x03 /* Channel Option Register 1 */ -#define CD180_COR2 0x04 /* Channel Option Register 2 */ -#define CD180_COR3 0x05 /* Channel Option Register 3 */ -#define CD180_CCSR 0x06 /* Channel Control Status Register */ -#define CD180_RTPR 0x18 /* Receive Timeout Period Register */ -#define CD180_RBPRH 0x31 /* Receive Bit Rate Period Register High */ -#define CD180_RBPRL 0x32 /* Receive Bit Rate Period Register Low */ -#define CD180_TBPRH 0x39 /* Transmit Bit Rate Period Register High */ -#define CD180_TBPRL 0x3a /* Transmit Bit Rate Period Register Low */ -#define CD180_SCHR1 0x09 /* Special Character Register 1 */ -#define CD180_SCHR2 0x0a /* Special Character Register 2 */ -#define CD180_SCHR3 0x0b /* Special Character Register 3 */ -#define CD180_SCHR4 0x0c /* Special Character Register 4 */ -#define CD180_MCR 0x12 /* Modem Change Register */ -#define CD180_MCOR1 0x10 /* Modem Change Option 1 Register */ -#define CD180_MCOR2 0x11 /* Modem Change Option 2 Register */ -#define CD180_MSVR 0x28 /* Modem Signal Value Register */ -#define CD180_MSVRTS 0x29 /* Modem Signal Value RTS */ -#define CD180_MSVDTR 0x2a /* Modem Signal Value DTR */ - -/* Global Interrupt Vector Register (R/W) */ - -#define GSVR_ITMASK 0x07 /* Interrupt type mask */ -#define GSVR_IT_MDM 0x01 /* Modem Signal Change Interrupt */ -#define GSVR_IT_TX 0x02 /* Transmit Data Interrupt */ -#define GSVR_IT_RGD 0x03 /* Receive Good Data Interrupt */ -#define GSVR_IT_REXC 0x07 /* Receive Exception Interrupt */ - - -/* Global Interrupt Channel Register (R/W) */ - -#define GSCR_CHAN 0x1c /* Channel Number Mask */ -#define GSCR_CHAN_OFF 2 /* Channel Number Offset */ - - -/* Channel Address Register (R/W) */ - -#define CAR_CHAN 0x07 /* Channel Number Mask */ - - -/* Receive Character Status Register (R/O) */ - -#define RCSR_TOUT 0x80 /* Rx Timeout */ -#define RCSR_SCDET 0x70 /* Special Character Detected Mask */ -#define RCSR_NO_SC 0x00 /* No Special Characters Detected */ -#define RCSR_SC_1 0x10 /* Special Char 1 (or 1 & 3) Detected */ -#define RCSR_SC_2 0x20 /* Special Char 2 (or 2 & 4) Detected */ -#define RCSR_SC_3 0x30 /* Special Char 3 Detected */ -#define RCSR_SC_4 0x40 /* Special Char 4 Detected */ -#define RCSR_BREAK 0x08 /* Break has been detected */ -#define RCSR_PE 0x04 /* Parity Error */ -#define RCSR_FE 0x02 /* Frame Error */ -#define RCSR_OE 0x01 /* Overrun Error */ - - -/* Channel Command Register (R/W) (commands in groups can be OR-ed) */ - -#define CCR_HARDRESET 0x81 /* Reset the chip */ - -#define CCR_SOFTRESET 0x80 /* Soft Channel Reset */ - -#define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */ -#define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */ -#define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */ - -#define CCR_SSCH1 0x21 /* Send Special Character 1 */ - -#define CCR_SSCH2 0x22 /* Send Special Character 2 */ - -#define CCR_SSCH3 0x23 /* Send Special Character 3 */ - -#define CCR_SSCH4 0x24 /* Send Special Character 4 */ - -#define CCR_TXEN 0x18 /* Enable Transmitter */ -#define CCR_RXEN 0x12 /* Enable Receiver */ - -#define CCR_TXDIS 0x14 /* Disable Transmitter */ -#define CCR_RXDIS 0x11 /* Disable Receiver */ - - -/* Service Request Enable Register (R/W) */ - -#define SRER_DSR 0x80 /* Enable interrupt on DSR change */ -#define SRER_CD 0x40 /* Enable interrupt on CD change */ -#define SRER_CTS 0x20 /* Enable interrupt on CTS change */ -#define SRER_RXD 0x10 /* Enable interrupt on Receive Data */ -#define SRER_RXSC 0x08 /* Enable interrupt on Receive Spec. Char */ -#define SRER_TXRDY 0x04 /* Enable interrupt on TX FIFO empty */ -#define SRER_TXEMPTY 0x02 /* Enable interrupt on TX completely empty */ -#define SRER_RET 0x01 /* Enable interrupt on RX Exc. Timeout */ - - -/* Channel Option Register 1 (R/W) */ - -#define COR1_ODDP 0x80 /* Odd Parity */ -#define COR1_PARMODE 0x60 /* Parity Mode mask */ -#define COR1_NOPAR 0x00 /* No Parity */ -#define COR1_FORCEPAR 0x20 /* Force Parity */ -#define COR1_NORMPAR 0x40 /* Normal Parity */ -#define COR1_IGNORE 0x10 /* Ignore Parity on RX */ -#define COR1_STOPBITS 0x0c /* Number of Stop Bits */ -#define COR1_1SB 0x00 /* 1 Stop Bit */ -#define COR1_15SB 0x04 /* 1.5 Stop Bits */ -#define COR1_2SB 0x08 /* 2 Stop Bits */ -#define COR1_CHARLEN 0x03 /* Character Length */ -#define COR1_5BITS 0x00 /* 5 bits */ -#define COR1_6BITS 0x01 /* 6 bits */ -#define COR1_7BITS 0x02 /* 7 bits */ -#define COR1_8BITS 0x03 /* 8 bits */ - - -/* Channel Option Register 2 (R/W) */ - -#define COR2_IXM 0x80 /* Implied XON mode */ -#define COR2_TXIBE 0x40 /* Enable In-Band (XON/XOFF) Flow Control */ -#define COR2_ETC 0x20 /* Embedded Tx Commands Enable */ -#define COR2_LLM 0x10 /* Local Loopback Mode */ -#define COR2_RLM 0x08 /* Remote Loopback Mode */ -#define COR2_RTSAO 0x04 /* RTS Automatic Output Enable */ -#define COR2_CTSAE 0x02 /* CTS Automatic Enable */ -#define COR2_DSRAE 0x01 /* DSR Automatic Enable */ - - -/* Channel Option Register 3 (R/W) */ - -#define COR3_XONCH 0x80 /* XON is a pair of characters (1 & 3) */ -#define COR3_XOFFCH 0x40 /* XOFF is a pair of characters (2 & 4) */ -#define COR3_FCT 0x20 /* Flow-Control Transparency Mode */ -#define COR3_SCDE 0x10 /* Special Character Detection Enable */ -#define COR3_RXTH 0x0f /* RX FIFO Threshold value (1-8) */ - - -/* Channel Control Status Register (R/O) */ - -#define CCSR_RXEN 0x80 /* Receiver Enabled */ -#define CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF was sent) */ -#define CCSR_RXFLON 0x20 /* Receive Flow On (XON was sent) */ -#define CCSR_TXEN 0x08 /* Transmitter Enabled */ -#define CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF) */ -#define CCSR_TXFLON 0x02 /* Transmit Flow On (got XON) */ - - -/* Modem Change Option Register 1 (R/W) */ - -#define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */ -#define MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD */ -#define MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS */ -#define MCOR1_DTRTH 0x0f /* Auto DTR flow control Threshold (1-8) */ -#define MCOR1_NODTRFC 0x0 /* Automatic DTR flow control disabled */ - - -/* Modem Change Option Register 2 (R/W) */ - -#define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */ -#define MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD */ -#define MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS */ - - -/* Modem Change Register (R/W) */ - -#define MCR_DSRCHG 0x80 /* DSR Changed */ -#define MCR_CDCHG 0x40 /* CD Changed */ -#define MCR_CTSCHG 0x20 /* CTS Changed */ - - -/* Modem Signal Value Register (R/W) */ - -#define MSVR_DSR 0x80 /* Current state of DSR input */ -#define MSVR_CD 0x40 /* Current state of CD input */ -#define MSVR_CTS 0x20 /* Current state of CTS input */ -#define MSVR_DTR 0x02 /* Current state of DTR output */ -#define MSVR_RTS 0x01 /* Current state of RTS output */ - - -/* Service Request Status Register */ - -#define SRSR_CMASK 0xC0 /* Current Service Context Mask */ -#define SRSR_CNONE 0x00 /* Not in a service context */ -#define SRSR_CRX 0x40 /* Rx Context */ -#define SRSR_CTX 0x80 /* Tx Context */ -#define SRSR_CMDM 0xC0 /* Modem Context */ -#define SRSR_ANYINT 0x6F /* Any interrupt flag */ -#define SRSR_RINT 0x10 /* Receive Interrupt */ -#define SRSR_TINT 0x04 /* Transmit Interrupt */ -#define SRSR_MINT 0x01 /* Modem Interrupt */ -#define SRSR_REXT 0x20 /* Receive External Interrupt */ -#define SRSR_TEXT 0x08 /* Transmit External Interrupt */ -#define SRSR_MEXT 0x02 /* Modem External Interrupt */ - - -/* Service Request Configuration Register */ - -#define SRCR_PKGTYPE 0x80 -#define SRCR_REGACKEN 0x40 -#define SRCR_DAISYEN 0x20 -#define SRCR_GLOBPRI 0x10 -#define SRCR_UNFAIR 0x08 -#define SRCR_AUTOPRI 0x02 -#define SRCR_PRISEL 0x01 - -/* Values for register-based Interrupt ACKs */ -#define CD180_ACK_MINT 0x75 /* goes to MSMR */ -#define CD180_ACK_TINT 0x76 /* goes to TSMR */ -#define CD180_ACK_RINT 0x77 /* goes to RSMR */ - -/* Escape characters */ - -#define CD180_C_ESC 0x00 /* Escape character */ -#define CD180_C_SBRK 0x81 /* Start sending BREAK */ -#define CD180_C_DELAY 0x82 /* Delay output */ -#define CD180_C_EBRK 0x83 /* Stop sending BREAK */ diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c deleted file mode 100644 index 836a58bb030..00000000000 --- a/drivers/sbus/char/cpwatchdog.c +++ /dev/null @@ -1,856 +0,0 @@ -/* cpwatchdog.c - driver implementation for hardware watchdog - * timers found on Sun Microsystems CP1400 and CP1500 boards. - * - * This device supports both the generic Linux watchdog - * interface and Solaris-compatible ioctls as best it is - * able. - * - * NOTE: CP1400 systems appear to have a defective intr_mask - * register on the PLD, preventing the disabling of - * timer interrupts. We use a timer to periodically - * reset 'stopped' watchdogs on affected platforms. - * - * TODO: DevFS support (/dev/watchdogs/0 ... /dev/watchdogs/2) - * - * Copyright (c) 2000 Eric Brower (ebrower@usa.net) - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/major.h> -#include <linux/init.h> -#include <linux/miscdevice.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timer.h> -#include <linux/smp_lock.h> -#include <asm/irq.h> -#include <asm/ebus.h> -#include <asm/oplib.h> -#include <asm/uaccess.h> - -#include <asm/watchdog.h> - -#define WD_OBPNAME "watchdog" -#define WD_BADMODEL "SUNW,501-5336" -#define WD_BTIMEOUT (jiffies + (HZ * 1000)) -#define WD_BLIMIT 0xFFFF - -#define WD0_DEVNAME "watchdog0" -#define WD1_DEVNAME "watchdog1" -#define WD2_DEVNAME "watchdog2" - -#define WD0_MINOR 212 -#define WD1_MINOR 213 -#define WD2_MINOR 214 - - -/* Internal driver definitions - */ -#define WD0_ID 0 /* Watchdog0 */ -#define WD1_ID 1 /* Watchdog1 */ -#define WD2_ID 2 /* Watchdog2 */ -#define WD_NUMDEVS 3 /* Device contains 3 timers */ - -#define WD_INTR_OFF 0 /* Interrupt disable value */ -#define WD_INTR_ON 1 /* Interrupt enable value */ - -#define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */ -#define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */ -#define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */ - -/* Register value definitions - */ -#define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */ -#define WD1_INTR_MASK 0x02 -#define WD2_INTR_MASK 0x04 - -#define WD_S_RUNNING 0x01 /* Watchdog device status running */ -#define WD_S_EXPIRED 0x02 /* Watchdog device status expired */ - -/* Sun uses Altera PLD EPF8820ATC144-4 - * providing three hardware watchdogs: - * - * 1) RIC - sends an interrupt when triggered - * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU - * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board - * - *** Timer register block definition (struct wd_timer_regblk) - * - * dcntr and limit registers (halfword access): - * ------------------- - * | 15 | ...| 1 | 0 | - * ------------------- - * |- counter val -| - * ------------------- - * dcntr - Current 16-bit downcounter value. - * When downcounter reaches '0' watchdog expires. - * Reading this register resets downcounter with 'limit' value. - * limit - 16-bit countdown value in 1/10th second increments. - * Writing this register begins countdown with input value. - * Reading from this register does not affect counter. - * NOTES: After watchdog reset, dcntr and limit contain '1' - * - * status register (byte access): - * --------------------------- - * | 7 | ... | 2 | 1 | 0 | - * --------------+------------ - * |- UNUSED -| EXP | RUN | - * --------------------------- - * status- Bit 0 - Watchdog is running - * Bit 1 - Watchdog has expired - * - *** PLD register block definition (struct wd_pld_regblk) - * - * intr_mask register (byte access): - * --------------------------------- - * | 7 | ... | 3 | 2 | 1 | 0 | - * +-------------+------------------ - * |- UNUSED -| WD3 | WD2 | WD1 | - * --------------------------------- - * WD3 - 1 == Interrupt disabled for watchdog 3 - * WD2 - 1 == Interrupt disabled for watchdog 2 - * WD1 - 1 == Interrupt disabled for watchdog 1 - * - * pld_status register (byte access): - * UNKNOWN, MAGICAL MYSTERY REGISTER - * - */ -#define WD_TIMER_REGSZ 16 -#define WD0_OFF 0 -#define WD1_OFF (WD_TIMER_REGSZ * 1) -#define WD2_OFF (WD_TIMER_REGSZ * 2) -#define PLD_OFF (WD_TIMER_REGSZ * 3) - -#define WD_DCNTR 0x00 -#define WD_LIMIT 0x04 -#define WD_STATUS 0x08 - -#define PLD_IMASK (PLD_OFF + 0x00) -#define PLD_STATUS (PLD_OFF + 0x04) - -/* Individual timer structure - */ -struct wd_timer { - __u16 timeout; - __u8 intr_mask; - unsigned char runstatus; - void __iomem *regs; -}; - -/* Device structure - */ -struct wd_device { - int irq; - spinlock_t lock; - unsigned char isbaddoggie; /* defective PLD */ - unsigned char opt_enable; - unsigned char opt_reboot; - unsigned short opt_timeout; - unsigned char initialized; - struct wd_timer watchdog[WD_NUMDEVS]; - void __iomem *regs; -}; - -static struct wd_device wd_dev = { - 0, SPIN_LOCK_UNLOCKED, 0, 0, 0, 0, -}; - -static struct timer_list wd_timer; - -static int wd0_timeout = 0; -static int wd1_timeout = 0; -static int wd2_timeout = 0; - -#ifdef MODULE -module_param (wd0_timeout, int, 0); -MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); -module_param (wd1_timeout, int, 0); -MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); -module_param (wd2_timeout, int, 0); -MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); - -MODULE_AUTHOR - ("Eric Brower <ebrower@usa.net>"); -MODULE_DESCRIPTION - ("Hardware watchdog driver for Sun Microsystems CP1400/1500"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE - ("watchdog"); -#endif /* ifdef MODULE */ - -/* Forward declarations of internal methods - */ -#ifdef WD_DEBUG -static void wd_dumpregs(void); -#endif -static irqreturn_t wd_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void wd_toggleintr(struct wd_timer* pTimer, int enable); -static void wd_pingtimer(struct wd_timer* pTimer); -static void wd_starttimer(struct wd_timer* pTimer); -static void wd_resetbrokentimer(struct wd_timer* pTimer); -static void wd_stoptimer(struct wd_timer* pTimer); -static void wd_brokentimer(unsigned long data); -static int wd_getstatus(struct wd_timer* pTimer); - -/* PLD expects words to be written in LSB format, - * so we must flip all words prior to writing them to regs - */ -static inline unsigned short flip_word(unsigned short word) -{ - return ((word & 0xff) << 8) | ((word >> 8) & 0xff); -} - -#define wd_writew(val, addr) (writew(flip_word(val), addr)) -#define wd_readw(addr) (flip_word(readw(addr))) -#define wd_writeb(val, addr) (writeb(val, addr)) -#define wd_readb(addr) (readb(addr)) - - -/* CP1400s seem to have broken PLD implementations-- - * the interrupt_mask register cannot be written, so - * no timer interrupts can be masked within the PLD. - */ -static inline int wd_isbroken(void) -{ - /* we could test this by read/write/read/restore - * on the interrupt mask register only if OBP - * 'watchdog-enable?' == FALSE, but it seems - * ubiquitous on CP1400s - */ - char val[32]; - prom_getproperty(prom_root_node, "model", val, sizeof(val)); - return((!strcmp(val, WD_BADMODEL)) ? 1 : 0); -} - -/* Retrieve watchdog-enable? option from OBP - * Returns 0 if false, 1 if true - */ -static inline int wd_opt_enable(void) -{ - int opt_node; - - opt_node = prom_getchild(prom_root_node); - opt_node = prom_searchsiblings(opt_node, "options"); - return((-1 == prom_getint(opt_node, "watchdog-enable?")) ? 0 : 1); -} - -/* Retrieve watchdog-reboot? option from OBP - * Returns 0 if false, 1 if true - */ -static inline int wd_opt_reboot(void) -{ - int opt_node; - - opt_node = prom_getchild(prom_root_node); - opt_node = prom_searchsiblings(opt_node, "options"); - return((-1 == prom_getint(opt_node, "watchdog-reboot?")) ? 0 : 1); -} - -/* Retrieve watchdog-timeout option from OBP - * Returns OBP value, or 0 if not located - */ -static inline int wd_opt_timeout(void) -{ - int opt_node; - char value[32]; - char *p = value; - - opt_node = prom_getchild(prom_root_node); - opt_node = prom_searchsiblings(opt_node, "options"); - opt_node = prom_getproperty(opt_node, - "watchdog-timeout", - value, - sizeof(value)); - if(-1 != opt_node) { - /* atoi implementation */ - for(opt_node = 0; /* nop */; p++) { - if(*p >= '0' && *p <= '9') { - opt_node = (10*opt_node)+(*p-'0'); - } - else { - break; - } - } - } - return((-1 == opt_node) ? (0) : (opt_node)); -} - -static int wd_open(struct inode *inode, struct file *f) -{ - switch(iminor(inode)) - { - case WD0_MINOR: - f->private_data = &wd_dev.watchdog[WD0_ID]; - break; - case WD1_MINOR: - f->private_data = &wd_dev.watchdog[WD1_ID]; - break; - case WD2_MINOR: - f->private_data = &wd_dev.watchdog[WD2_ID]; - break; - default: - return(-ENODEV); - } - - /* Register IRQ on first open of device */ - if(0 == wd_dev.initialized) - { - if (request_irq(wd_dev.irq, - &wd_interrupt, - IRQF_SHARED, - WD_OBPNAME, - (void *)wd_dev.regs)) { - printk("%s: Cannot register IRQ %d\n", - WD_OBPNAME, wd_dev.irq); - return(-EBUSY); - } - wd_dev.initialized = 1; - } - - return(nonseekable_open(inode, f)); -} - -static int wd_release(struct inode *inode, struct file *file) -{ - return 0; -} - -static int wd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int setopt = 0; - struct wd_timer* pTimer = (struct wd_timer*)file->private_data; - void __user *argp = (void __user *)arg; - struct watchdog_info info = { - 0, - 0, - "Altera EPF8820ATC144-4" - }; - - if(NULL == pTimer) { - return(-EINVAL); - } - - switch(cmd) - { - /* Generic Linux IOCTLs */ - case WDIOC_GETSUPPORT: - if(copy_to_user(argp, &info, sizeof(struct watchdog_info))) { - return(-EFAULT); - } - break; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - if (put_user(0, (int __user *)argp)) - return -EFAULT; - break; - case WDIOC_KEEPALIVE: - wd_pingtimer(pTimer); - break; - case WDIOC_SETOPTIONS: - if(copy_from_user(&setopt, argp, sizeof(unsigned int))) { - return -EFAULT; - } - if(setopt & WDIOS_DISABLECARD) { - if(wd_dev.opt_enable) { - printk( - "%s: cannot disable watchdog in ENABLED mode\n", - WD_OBPNAME); - return(-EINVAL); - } - wd_stoptimer(pTimer); - } - else if(setopt & WDIOS_ENABLECARD) { - wd_starttimer(pTimer); - } - else { - return(-EINVAL); - } - break; - /* Solaris-compatible IOCTLs */ - case WIOCGSTAT: - setopt = wd_getstatus(pTimer); - if(copy_to_user(argp, &setopt, sizeof(unsigned int))) { - return(-EFAULT); - } - break; - case WIOCSTART: - wd_starttimer(pTimer); - break; - case WIOCSTOP: - if(wd_dev.opt_enable) { - printk("%s: cannot disable watchdog in ENABLED mode\n", - WD_OBPNAME); - return(-EINVAL); - } - wd_stoptimer(pTimer); - break; - default: - return(-EINVAL); - } - return(0); -} - -static long wd_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int rval = -ENOIOCTLCMD; - - switch (cmd) { - /* solaris ioctls are specific to this driver */ - case WIOCSTART: - case WIOCSTOP: - case WIOCGSTAT: - lock_kernel(); - rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg); - unlock_kernel(); - break; - /* everything else is handled by the generic compat layer */ - default: - break; - } - - return rval; -} - -static ssize_t wd_write(struct file *file, - const char __user *buf, - size_t count, - loff_t *ppos) -{ - struct wd_timer* pTimer = (struct wd_timer*)file->private_data; - - if(NULL == pTimer) { - return(-EINVAL); - } - - if (count) { - wd_pingtimer(pTimer); - return 1; - } - return 0; -} - -static ssize_t wd_read(struct file * file, char __user *buffer, - size_t count, loff_t *ppos) -{ -#ifdef WD_DEBUG - wd_dumpregs(); - return(0); -#else - return(-EINVAL); -#endif /* ifdef WD_DEBUG */ -} - -static irqreturn_t wd_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - /* Only WD0 will interrupt-- others are NMI and we won't - * see them here.... - */ - spin_lock_irq(&wd_dev.lock); - if((unsigned long)wd_dev.regs == (unsigned long)dev_id) - { - wd_stoptimer(&wd_dev.watchdog[WD0_ID]); - wd_dev.watchdog[WD0_ID].runstatus |= WD_STAT_SVCD; - } - spin_unlock_irq(&wd_dev.lock); - return IRQ_HANDLED; -} - -static struct file_operations wd_fops = { - .owner = THIS_MODULE, - .ioctl = wd_ioctl, - .compat_ioctl = wd_compat_ioctl, - .open = wd_open, - .write = wd_write, - .read = wd_read, - .release = wd_release, -}; - -static struct miscdevice wd0_miscdev = { WD0_MINOR, WD0_DEVNAME, &wd_fops }; -static struct miscdevice wd1_miscdev = { WD1_MINOR, WD1_DEVNAME, &wd_fops }; -static struct miscdevice wd2_miscdev = { WD2_MINOR, WD2_DEVNAME, &wd_fops }; - -#ifdef WD_DEBUG -static void wd_dumpregs(void) -{ - /* Reading from downcounters initiates watchdog countdown-- - * Example is included below for illustration purposes. - */ - int i; - printk("%s: dumping register values\n", WD_OBPNAME); - for(i = WD0_ID; i < WD_NUMDEVS; ++i) { - /* printk("\t%s%i: dcntr at 0x%lx: 0x%x\n", - * WD_OBPNAME, - * i, - * (unsigned long)(&wd_dev.watchdog[i].regs->dcntr), - * readw(&wd_dev.watchdog[i].regs->dcntr)); - */ - printk("\t%s%i: limit at 0x%lx: 0x%x\n", - WD_OBPNAME, - i, - (unsigned long)(&wd_dev.watchdog[i].regs->limit), - readw(&wd_dev.watchdog[i].regs->limit)); - printk("\t%s%i: status at 0x%lx: 0x%x\n", - WD_OBPNAME, - i, - (unsigned long)(&wd_dev.watchdog[i].regs->status), - readb(&wd_dev.watchdog[i].regs->status)); - printk("\t%s%i: driver status: 0x%x\n", - WD_OBPNAME, - i, - wd_getstatus(&wd_dev.watchdog[i])); - } - printk("\tintr_mask at %p: 0x%x\n", - wd_dev.regs + PLD_IMASK, - readb(wd_dev.regs + PLD_IMASK)); - printk("\tpld_status at %p: 0x%x\n", - wd_dev.regs + PLD_STATUS, - readb(wd_dev.regs + PLD_STATUS)); -} -#endif - -/* Enable or disable watchdog interrupts - * Because of the CP1400 defect this should only be - * called during initialzation or by wd_[start|stop]timer() - * - * pTimer - pointer to timer device, or NULL to indicate all timers - * enable - non-zero to enable interrupts, zero to disable - */ -static void wd_toggleintr(struct wd_timer* pTimer, int enable) -{ - unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK); - unsigned char setregs = - (NULL == pTimer) ? - (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : - (pTimer->intr_mask); - - (WD_INTR_ON == enable) ? - (curregs &= ~setregs): - (curregs |= setregs); - - wd_writeb(curregs, wd_dev.regs + PLD_IMASK); - return; -} - -/* Reset countdown timer with 'limit' value and continue countdown. - * This will not start a stopped timer. - * - * pTimer - pointer to timer device - */ -static void wd_pingtimer(struct wd_timer* pTimer) -{ - if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { - wd_readw(pTimer->regs + WD_DCNTR); - } -} - -/* Stop a running watchdog timer-- the timer actually keeps - * running, but the interrupt is masked so that no action is - * taken upon expiration. - * - * pTimer - pointer to timer device - */ -static void wd_stoptimer(struct wd_timer* pTimer) -{ - if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { - wd_toggleintr(pTimer, WD_INTR_OFF); - - if(wd_dev.isbaddoggie) { - pTimer->runstatus |= WD_STAT_BSTOP; - wd_brokentimer((unsigned long)&wd_dev); - } - } -} - -/* Start a watchdog timer with the specified limit value - * If the watchdog is running, it will be restarted with - * the provided limit value. - * - * This function will enable interrupts on the specified - * watchdog. - * - * pTimer - pointer to timer device - * limit - limit (countdown) value in 1/10th seconds - */ -static void wd_starttimer(struct wd_timer* pTimer) -{ - if(wd_dev.isbaddoggie) { - pTimer->runstatus &= ~WD_STAT_BSTOP; - } - pTimer->runstatus &= ~WD_STAT_SVCD; - - wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT); - wd_toggleintr(pTimer, WD_INTR_ON); -} - -/* Restarts timer with maximum limit value and - * does not unset 'brokenstop' value. - */ -static void wd_resetbrokentimer(struct wd_timer* pTimer) -{ - wd_toggleintr(pTimer, WD_INTR_ON); - wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT); -} - -/* Timer device initialization helper. - * Returns 0 on success, other on failure - */ -static int wd_inittimer(int whichdog) -{ - struct miscdevice *whichmisc; - void __iomem *whichregs; - char whichident[8]; - int whichmask; - __u16 whichlimit; - - switch(whichdog) - { - case WD0_ID: - whichmisc = &wd0_miscdev; - strcpy(whichident, "RIC"); - whichregs = wd_dev.regs + WD0_OFF; - whichmask = WD0_INTR_MASK; - whichlimit= (0 == wd0_timeout) ? - (wd_dev.opt_timeout): - (wd0_timeout); - break; - case WD1_ID: - whichmisc = &wd1_miscdev; - strcpy(whichident, "XIR"); - whichregs = wd_dev.regs + WD1_OFF; - whichmask = WD1_INTR_MASK; - whichlimit= (0 == wd1_timeout) ? - (wd_dev.opt_timeout): - (wd1_timeout); - break; - case WD2_ID: - whichmisc = &wd2_miscdev; - strcpy(whichident, "POR"); - whichregs = wd_dev.regs + WD2_OFF; - whichmask = WD2_INTR_MASK; - whichlimit= (0 == wd2_timeout) ? - (wd_dev.opt_timeout): - (wd2_timeout); - break; - default: - printk("%s: %s: invalid watchdog id: %i\n", - WD_OBPNAME, __FUNCTION__, whichdog); - return(1); - } - if(0 != misc_register(whichmisc)) - { - return(1); - } - wd_dev.watchdog[whichdog].regs = whichregs; - wd_dev.watchdog[whichdog].timeout = whichlimit; - wd_dev.watchdog[whichdog].intr_mask = whichmask; - wd_dev.watchdog[whichdog].runstatus &= ~WD_STAT_BSTOP; - wd_dev.watchdog[whichdog].runstatus |= WD_STAT_INIT; - - printk("%s%i: %s hardware watchdog [%01i.%i sec] %s\n", - WD_OBPNAME, - whichdog, - whichident, - wd_dev.watchdog[whichdog].timeout / 10, - wd_dev.watchdog[whichdog].timeout % 10, - (0 != wd_dev.opt_enable) ? "in ENABLED mode" : ""); - return(0); -} - -/* Timer method called to reset stopped watchdogs-- - * because of the PLD bug on CP1400, we cannot mask - * interrupts within the PLD so me must continually - * reset the timers ad infinitum. - */ -static void wd_brokentimer(unsigned long data) -{ - struct wd_device* pDev = (struct wd_device*)data; - int id, tripped = 0; - - /* kill a running timer instance, in case we - * were called directly instead of by kernel timer - */ - if(timer_pending(&wd_timer)) { - del_timer(&wd_timer); - } - - for(id = WD0_ID; id < WD_NUMDEVS; ++id) { - if(pDev->watchdog[id].runstatus & WD_STAT_BSTOP) { - ++tripped; - wd_resetbrokentimer(&pDev->watchdog[id]); - } - } - - if(tripped) { - /* there is at least one timer brokenstopped-- reschedule */ - init_timer(&wd_timer); - wd_timer.expires = WD_BTIMEOUT; - add_timer(&wd_timer); - } -} - -static int wd_getstatus(struct wd_timer* pTimer) -{ - unsigned char stat = wd_readb(pTimer->regs + WD_STATUS); - unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK); - unsigned char ret = WD_STOPPED; - - /* determine STOPPED */ - if(0 == stat ) { - return(ret); - } - /* determine EXPIRED vs FREERUN vs RUNNING */ - else if(WD_S_EXPIRED & stat) { - ret = WD_EXPIRED; - } - else if(WD_S_RUNNING & stat) { - if(intr & pTimer->intr_mask) { - ret = WD_FREERUN; - } - else { - /* Fudge WD_EXPIRED status for defective CP1400-- - * IF timer is running - * AND brokenstop is set - * AND an interrupt has been serviced - * we are WD_EXPIRED. - * - * IF timer is running - * AND brokenstop is set - * AND no interrupt has been serviced - * we are WD_FREERUN. - */ - if(wd_dev.isbaddoggie && (pTimer->runstatus & WD_STAT_BSTOP)) { - if(pTimer->runstatus & WD_STAT_SVCD) { - ret = WD_EXPIRED; - } - else { - /* we could as well pretend we are expired */ - ret = WD_FREERUN; - } - } - else { - ret = WD_RUNNING; - } - } - } - - /* determine SERVICED */ - if(pTimer->runstatus & WD_STAT_SVCD) { - ret |= WD_SERVICED; - } - - return(ret); -} - -static int __init wd_init(void) -{ - int id; - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->ofdev.node->name, WD_OBPNAME)) - goto ebus_done; - } - } - -ebus_done: - if(!edev) { - printk("%s: unable to locate device\n", WD_OBPNAME); - return -ENODEV; - } - - wd_dev.regs = - ioremap(edev->resource[0].start, 4 * WD_TIMER_REGSZ); /* ? */ - - if(NULL == wd_dev.regs) { - printk("%s: unable to map registers\n", WD_OBPNAME); - return(-ENODEV); - } - - /* initialize device structure from OBP parameters */ - wd_dev.irq = edev->irqs[0]; - wd_dev.opt_enable = wd_opt_enable(); - wd_dev.opt_reboot = wd_opt_reboot(); - wd_dev.opt_timeout = wd_opt_timeout(); - wd_dev.isbaddoggie = wd_isbroken(); - - /* disable all interrupts unless watchdog-enabled? == true */ - if(! wd_dev.opt_enable) { - wd_toggleintr(NULL, WD_INTR_OFF); - } - - /* register miscellaneous devices */ - for(id = WD0_ID; id < WD_NUMDEVS; ++id) { - if(0 != wd_inittimer(id)) { - printk("%s%i: unable to initialize\n", WD_OBPNAME, id); - } - } - - /* warn about possible defective PLD */ - if(wd_dev.isbaddoggie) { - init_timer(&wd_timer); - wd_timer.function = wd_brokentimer; - wd_timer.data = (unsigned long)&wd_dev; - wd_timer.expires = WD_BTIMEOUT; - - printk("%s: PLD defect workaround enabled for model %s\n", - WD_OBPNAME, WD_BADMODEL); - } - return(0); -} - -static void __exit wd_cleanup(void) -{ - int id; - - /* if 'watchdog-enable?' == TRUE, timers are not stopped - * when module is unloaded. All brokenstopped timers will - * also now eventually trip. - */ - for(id = WD0_ID; id < WD_NUMDEVS; ++id) { - if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) { - if(wd_dev.opt_enable) { - printk(KERN_WARNING "%s%i: timer not stopped at release\n", - WD_OBPNAME, id); - } - else { - wd_stoptimer(&wd_dev.watchdog[id]); - if(wd_dev.watchdog[id].runstatus & WD_STAT_BSTOP) { - wd_resetbrokentimer(&wd_dev.watchdog[id]); - printk(KERN_WARNING - "%s%i: defect workaround disabled at release, "\ - "timer expires in ~%01i sec\n", - WD_OBPNAME, id, - wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10); - } - } - } - } - - if(wd_dev.isbaddoggie && timer_pending(&wd_timer)) { - del_timer(&wd_timer); - } - if(0 != (wd_dev.watchdog[WD0_ID].runstatus & WD_STAT_INIT)) { - misc_deregister(&wd0_miscdev); - } - if(0 != (wd_dev.watchdog[WD1_ID].runstatus & WD_STAT_INIT)) { - misc_deregister(&wd1_miscdev); - } - if(0 != (wd_dev.watchdog[WD2_ID].runstatus & WD_STAT_INIT)) { - misc_deregister(&wd2_miscdev); - } - if(0 != wd_dev.initialized) { - free_irq(wd_dev.irq, (void *)wd_dev.regs); - } - iounmap(wd_dev.regs); -} - -module_init(wd_init); -module_exit(wd_cleanup); diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index d92bc8827a9..7c71e7b4feb 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -1,10 +1,7 @@ -/* $Id: display7seg.c,v 1.6 2002/01/08 16:00:16 davem Exp $ - * - * display7seg - Driver implementation for the 7-segment display - * present on Sun Microsystems CP1400 and CP1500 +/* display7seg.c - Driver implementation for the 7-segment display + * present on Sun Microsystems CP1400 and CP1500 * * Copyright (c) 2000 Eric Brower (ebrower@usa.net) - * */ #include <linux/kernel.h> @@ -12,25 +9,25 @@ #include <linux/fs.h> #include <linux/errno.h> #include <linux/major.h> -#include <linux/init.h> #include <linux/miscdevice.h> #include <linux/ioport.h> /* request_region */ -#include <linux/smp_lock.h> -#include <asm/atomic.h> -#include <asm/ebus.h> /* EBus device */ -#include <asm/oplib.h> /* OpenProm Library */ +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/atomic.h> #include <asm/uaccess.h> /* put_/get_user */ +#include <asm/io.h> #include <asm/display7seg.h> #define D7S_MINOR 193 -#define D7S_OBPNAME "display7seg" -#define D7S_DEVNAME "d7s" +#define DRIVER_NAME "d7s" +#define PFX DRIVER_NAME ": " +static DEFINE_MUTEX(d7s_mutex); static int sol_compat = 0; /* Solaris compatibility mode */ -#ifdef MODULE - /* Solaris compatibility flag - * The Solaris implementation omits support for several * documented driver features (ref Sun doc 806-0180-03). @@ -45,20 +42,20 @@ static int sol_compat = 0; /* Solaris compatibility mode */ * If you wish the device to operate as under Solaris, * omitting above features, set this parameter to non-zero. */ -module_param - (sol_compat, int, 0); -MODULE_PARM_DESC - (sol_compat, - "Disables documented functionality omitted from Solaris driver"); - -MODULE_AUTHOR - ("Eric Brower <ebrower@usa.net>"); -MODULE_DESCRIPTION - ("7-Segment Display driver for Sun Microsystems CP1400/1500"); +module_param(sol_compat, int, 0); +MODULE_PARM_DESC(sol_compat, + "Disables documented functionality omitted from Solaris driver"); + +MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); +MODULE_DESCRIPTION("7-Segment Display driver for Sun Microsystems CP1400/1500"); MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE - ("d7s"); -#endif /* ifdef MODULE */ +MODULE_SUPPORTED_DEVICE("d7s"); + +struct d7s { + void __iomem *regs; + bool flipped; +}; +struct d7s *d7s_device; /* * Register block address- see header for details @@ -71,22 +68,6 @@ MODULE_SUPPORTED_DEVICE * FLIP - Inverts display for upside-down mounted board * bits 0-4 - 7-segment display contents */ -static void __iomem* d7s_regs; - -static inline void d7s_free(void) -{ - iounmap(d7s_regs); -} - -static inline int d7s_obpflipped(void) -{ - int opt_node; - - opt_node = prom_getchild(prom_root_node); - opt_node = prom_searchsiblings(opt_node, "options"); - return ((-1 != prom_getintdefault(opt_node, "d7s-flipped?", -1)) ? 0 : 1); -} - static atomic_t d7s_users = ATOMIC_INIT(0); static int d7s_open(struct inode *inode, struct file *f) @@ -104,12 +85,15 @@ static int d7s_release(struct inode *inode, struct file *f) * are not operating in solaris-compat mode */ if (atomic_dec_and_test(&d7s_users) && !sol_compat) { - int regval = 0; - - regval = readb(d7s_regs); - (0 == d7s_obpflipped()) ? - writeb(regval |= D7S_FLIP, d7s_regs): - writeb(regval &= ~D7S_FLIP, d7s_regs); + struct d7s *p = d7s_device; + u8 regval = 0; + + regval = readb(p->regs); + if (p->flipped) + regval |= D7S_FLIP; + else + regval &= ~D7S_FLIP; + writeb(regval, p->regs); } return 0; @@ -117,28 +101,31 @@ static int d7s_release(struct inode *inode, struct file *f) static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - __u8 regs = readb(d7s_regs); - __u8 ireg = 0; + struct d7s *p = d7s_device; + u8 regs = readb(p->regs); int error = 0; + u8 ireg = 0; - if (D7S_MINOR != iminor(file->f_dentry->d_inode)) + if (D7S_MINOR != iminor(file_inode(file))) return -ENODEV; - lock_kernel(); + mutex_lock(&d7s_mutex); switch (cmd) { case D7SIOCWR: - /* assign device register values - * we mask-out D7S_FLIP if in sol_compat mode + /* assign device register values we mask-out D7S_FLIP + * if in sol_compat mode */ if (get_user(ireg, (int __user *) arg)) { error = -EFAULT; break; } - if (0 != sol_compat) { - (regs & D7S_FLIP) ? - (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP); + if (sol_compat) { + if (regs & D7S_FLIP) + ireg |= D7S_FLIP; + else + ireg &= ~D7S_FLIP; } - writeb(ireg, d7s_regs); + writeb(ireg, p->regs); break; case D7SIOCRD: @@ -156,87 +143,135 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case D7SIOCTM: /* toggle device mode-- flip display orientation */ - (regs & D7S_FLIP) ? - (regs &= ~D7S_FLIP) : (regs |= D7S_FLIP); - writeb(regs, d7s_regs); + if (regs & D7S_FLIP) + regs &= ~D7S_FLIP; + else + regs |= D7S_FLIP; + writeb(regs, p->regs); break; - }; - unlock_kernel(); + } + mutex_unlock(&d7s_mutex); return error; } -static struct file_operations d7s_fops = { +static const struct file_operations d7s_fops = { .owner = THIS_MODULE, .unlocked_ioctl = d7s_ioctl, .compat_ioctl = d7s_ioctl, .open = d7s_open, .release = d7s_release, + .llseek = noop_llseek, }; -static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops }; +static struct miscdevice d7s_miscdev = { + .minor = D7S_MINOR, + .name = DRIVER_NAME, + .fops = &d7s_fops +}; -static int __init d7s_init(void) +static int d7s_probe(struct platform_device *op) { - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; - int iTmp = 0, regs = 0; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, D7S_OBPNAME)) - goto ebus_done; - } + struct device_node *opts; + int err = -EINVAL; + struct d7s *p; + u8 regs; + + if (d7s_device) + goto out; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + err = -ENOMEM; + if (!p) + goto out; + + p->regs = of_ioremap(&op->resource[0], 0, sizeof(u8), "d7s"); + if (!p->regs) { + printk(KERN_ERR PFX "Cannot map chip registers\n"); + goto out_free; } -ebus_done: - if(!edev) { - printk("%s: unable to locate device\n", D7S_DEVNAME); - return -ENODEV; - } - - d7s_regs = ioremap(edev->resource[0].start, sizeof(__u8)); - - iTmp = misc_register(&d7s_miscdev); - if (0 != iTmp) { - printk("%s: unable to acquire miscdevice minor %i\n", - D7S_DEVNAME, D7S_MINOR); - iounmap(d7s_regs); - return iTmp; + err = misc_register(&d7s_miscdev); + if (err) { + printk(KERN_ERR PFX "Unable to acquire miscdevice minor %i\n", + D7S_MINOR); + goto out_iounmap; } - /* OBP option "d7s-flipped?" is honored as default - * for the device, and reset default when detached + /* OBP option "d7s-flipped?" is honored as default for the + * device, and reset default when detached */ - regs = readb(d7s_regs); - iTmp = d7s_obpflipped(); - (0 == iTmp) ? - writeb(regs |= D7S_FLIP, d7s_regs): - writeb(regs &= ~D7S_FLIP, d7s_regs); - - printk("%s: 7-Segment Display%s at 0x%lx %s\n", - D7S_DEVNAME, - (0 == iTmp) ? (" (FLIPPED)") : (""), - edev->resource[0].start, - (0 != sol_compat) ? ("in sol_compat mode") : ("")); - - return 0; + regs = readb(p->regs); + opts = of_find_node_by_path("/options"); + if (opts && + of_get_property(opts, "d7s-flipped?", NULL)) + p->flipped = true; + + if (p->flipped) + regs |= D7S_FLIP; + else + regs &= ~D7S_FLIP; + + writeb(regs, p->regs); + + printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%llx] %s\n", + op->dev.of_node->full_name, + (regs & D7S_FLIP) ? " (FLIPPED)" : "", + op->resource[0].start, + sol_compat ? "in sol_compat mode" : ""); + + dev_set_drvdata(&op->dev, p); + d7s_device = p; + err = 0; + +out: + return err; + +out_iounmap: + of_iounmap(&op->resource[0], p->regs, sizeof(u8)); + +out_free: + kfree(p); + goto out; } -static void __exit d7s_cleanup(void) +static int d7s_remove(struct platform_device *op) { - int regs = readb(d7s_regs); + struct d7s *p = dev_get_drvdata(&op->dev); + u8 regs = readb(p->regs); /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ - if (0 == sol_compat) { - (0 == d7s_obpflipped()) ? - writeb(regs |= D7S_FLIP, d7s_regs): - writeb(regs &= ~D7S_FLIP, d7s_regs); + if (sol_compat) { + if (p->flipped) + regs |= D7S_FLIP; + else + regs &= ~D7S_FLIP; + writeb(regs, p->regs); } misc_deregister(&d7s_miscdev); - d7s_free(); + of_iounmap(&op->resource[0], p->regs, sizeof(u8)); + kfree(p); + + return 0; } -module_init(d7s_init); -module_exit(d7s_cleanup); +static const struct of_device_id d7s_match[] = { + { + .name = "display7seg", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, d7s_match); + +static struct platform_driver d7s_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = d7s_match, + }, + .probe = d7s_probe, + .remove = d7s_remove, +}; + +module_platform_driver(d7s_driver); diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 063e676a3ac..af15a2fdab5 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1,5 +1,4 @@ -/* $Id: envctrl.c,v 1.25 2002/01/15 09:01:26 davem Exp $ - * envctrl.c: Temperature and Fan monitoring on Machines providing it. +/* envctrl.c: Temperature and Fan monitoring on Machines providing it. * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com) @@ -19,24 +18,23 @@ * Daniele Bellucci <bellucda@tiscali.it> */ -#define __KERNEL_SYSCALLS__ -static int errno; - #include <linux/module.h> -#include <linux/sched.h> #include <linux/kthread.h> -#include <linux/errno.h> #include <linux/delay.h> #include <linux/ioport.h> -#include <linux/init.h> #include <linux/miscdevice.h> -#include <linux/mm.h> +#include <linux/kmod.h> +#include <linux/reboot.h> #include <linux/slab.h> -#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/of_device.h> -#include <asm/ebus.h> #include <asm/uaccess.h> #include <asm/envctrl.h> +#include <asm/io.h> + +#define DRIVER_NAME "envctrl" +#define PFX DRIVER_NAME ": " #define ENVCTRL_MINOR 162 @@ -93,11 +91,11 @@ static int errno; #define ENVCTRL_CPUTEMP_MON 1 /* cpu temperature monitor */ #define ENVCTRL_CPUVOLTAGE_MON 2 /* voltage monitor */ #define ENVCTRL_FANSTAT_MON 3 /* fan status monitor */ -#define ENVCTRL_ETHERTEMP_MON 4 /* ethernet temperarture */ +#define ENVCTRL_ETHERTEMP_MON 4 /* ethernet temperature */ /* monitor */ #define ENVCTRL_VOLTAGESTAT_MON 5 /* voltage status monitor */ #define ENVCTRL_MTHRBDTEMP_MON 6 /* motherboard temperature */ -#define ENVCTRL_SCSITEMP_MON 7 /* scsi temperarture */ +#define ENVCTRL_SCSITEMP_MON 7 /* scsi temperature */ #define ENVCTRL_GLOBALADDR_MON 8 /* global address */ /* Child device type. @@ -197,7 +195,7 @@ static void envtrl_i2c_test_pin(void) } if (limit <= 0) - printk(KERN_INFO "envctrl: Pin status will not clear.\n"); + printk(KERN_INFO PFX "Pin status will not clear.\n"); } /* Function Description: Test busy bit. @@ -215,7 +213,7 @@ static void envctrl_i2c_test_bb(void) } if (limit <= 0) - printk(KERN_INFO "envctrl: Busy bit will not clear.\n"); + printk(KERN_INFO PFX "Busy bit will not clear.\n"); } /* Function Description: Send the address for a read access. @@ -354,7 +352,7 @@ static int envctrl_i2c_data_translate(unsigned char data, int translate_type, default: break; - }; + } return len; } @@ -645,7 +643,7 @@ envctrl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) default: break; - }; + } return ret; } @@ -688,7 +686,7 @@ envctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) default: return -EINVAL; - }; + } return 0; } @@ -712,7 +710,7 @@ envctrl_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations envctrl_fops = { +static const struct file_operations envctrl_fops = { .owner = THIS_MODULE, .read = envctrl_read, .unlocked_ioctl = envctrl_ioctl, @@ -721,6 +719,7 @@ static struct file_operations envctrl_fops = { #endif .open = envctrl_open, .release = envctrl_release, + .llseek = noop_llseek, }; static struct miscdevice envctrl_dev = { @@ -733,7 +732,7 @@ static struct miscdevice envctrl_dev = { * Return: None. */ static void envctrl_set_mon(struct i2c_child_t *pchild, - char *chnl_desc, + const char *chnl_desc, int chnl_no) { /* Firmware only has temperature type. It does not distinguish @@ -770,8 +769,8 @@ static void envctrl_set_mon(struct i2c_child_t *pchild, static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp) { int i = 0, len; - char *pos; - unsigned int *pval; + const char *pos; + const unsigned int *pval; /* Firmware describe channels into a stream separated by a '\0'. */ pos = of_get_property(dp, "channels-description", &len); @@ -861,12 +860,11 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild) /* Function Description: Initialize i2c child device. * Return: None. */ -static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, +static void envctrl_init_i2c_child(struct device_node *dp, struct i2c_child_t *pchild) { int len, i, tbls_size = 0; - struct device_node *dp = edev_child->prom_node; - void *pval; + const void *pval; /* Get device address. */ pval = of_get_property(dp, "reg", &len); @@ -885,12 +883,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, pchild->tables = kmalloc(tbls_size, GFP_KERNEL); if (pchild->tables == NULL){ - printk("envctrl: Failed to allocate table.\n"); + printk(KERN_ERR PFX "Failed to allocate table.\n"); return; } pval = of_get_property(dp, "tables", &len); if (!pval || len <= 0) { - printk("envctrl: Failed to get table.\n"); + printk(KERN_ERR PFX "Failed to get table.\n"); return; } memcpy(pchild->tables, pval, len); @@ -948,7 +946,7 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, default: break; - }; + } } } @@ -972,17 +970,15 @@ static struct i2c_child_t *envctrl_get_i2c_child(unsigned char mon_type) static void envctrl_do_shutdown(void) { static int inprog = 0; - static char *envp[] = { - "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - char *argv[] = { - "/sbin/shutdown", "-h", "now", NULL }; + int ret; if (inprog != 0) return; inprog = 1; printk(KERN_CRIT "kenvctrld: WARNING: Shutting down the system now.\n"); - if (0 > execve("/sbin/shutdown", argv, envp)) { + ret = orderly_poweroff(true); + if (ret < 0) { printk(KERN_CRIT "kenvctrld: WARNING: system shutdown failed!\n"); inprog = 0; /* unlikely to succeed, but we could try again */ } @@ -998,14 +994,14 @@ static int kenvctrld(void *__unused) struct i2c_child_t *cputemp; if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) { - printk(KERN_ERR - "envctrl: kenvctrld unable to monitor CPU temp-- exiting\n"); + printk(KERN_ERR PFX + "kenvctrld unable to monitor CPU temp-- exiting\n"); return -ENODEV; } poll_interval = 5000; /* TODO env_mon_interval */ - printk(KERN_INFO "envctrl: %s starting...\n", current->comm); + printk(KERN_INFO PFX "%s starting...\n", current->comm); for (;;) { msleep_interruptible(poll_interval); @@ -1027,54 +1023,34 @@ static int kenvctrld(void *__unused) } } } - printk(KERN_INFO "envctrl: %s exiting...\n", current->comm); + printk(KERN_INFO PFX "%s exiting...\n", current->comm); return 0; } -static int __init envctrl_init(void) +static int envctrl_probe(struct platform_device *op) { - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; - struct linux_ebus_child *edev_child = NULL; - int err, i = 0; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "bbc")) { - /* If we find a boot-bus controller node, - * then this envctrl driver is not for us. - */ - return -ENODEV; - } - } - } + struct device_node *dp; + int index, err; - /* Traverse through ebus and ebus device list for i2c device and - * adc and gpio nodes. - */ - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "i2c")) { - i2c = ioremap(edev->resource[0].start, 0x2); - for_each_edevchild(edev, edev_child) { - if (!strcmp("gpio", edev_child->prom_node->name)) { - i2c_childlist[i].i2ctype = I2C_GPIO; - envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); - } - if (!strcmp("adc", edev_child->prom_node->name)) { - i2c_childlist[i].i2ctype = I2C_ADC; - envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); - } - } - goto done; - } + if (i2c) + return -EINVAL; + + i2c = of_ioremap(&op->resource[0], 0, 0x2, DRIVER_NAME); + if (!i2c) + return -ENOMEM; + + index = 0; + dp = op->dev.of_node->child; + while (dp) { + if (!strcmp(dp->name, "gpio")) { + i2c_childlist[index].i2ctype = I2C_GPIO; + envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); + } else if (!strcmp(dp->name, "adc")) { + i2c_childlist[index].i2ctype = I2C_ADC; + envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); } - } -done: - if (!edev) { - printk("envctrl: I2C device not found.\n"); - return -ENODEV; + dp = dp->sibling; } /* Set device address. */ @@ -1092,7 +1068,7 @@ done: /* Register the device as a minor miscellaneous device. */ err = misc_register(&envctrl_dev); if (err) { - printk("envctrl: Unable to get misc minor %d\n", + printk(KERN_ERR PFX "Unable to get misc minor %d\n", envctrl_dev.minor); goto out_iounmap; } @@ -1101,12 +1077,12 @@ done: * a next child device, so we decrement before reverse-traversal of * child devices. */ - printk("envctrl: initialized "); - for (--i; i >= 0; --i) { + printk(KERN_INFO PFX "Initialized "); + for (--index; index >= 0; --index) { printk("[%s 0x%lx]%s", - (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") : - ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")), - i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); + (I2C_ADC == i2c_childlist[index].i2ctype) ? "adc" : + ((I2C_GPIO == i2c_childlist[index].i2ctype) ? "gpio" : "unknown"), + i2c_childlist[index].addr, (0 == index) ? "\n" : " "); } kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); @@ -1120,26 +1096,47 @@ done: out_deregister: misc_deregister(&envctrl_dev); out_iounmap: - iounmap(i2c); - for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) - kfree(i2c_childlist[i].tables); + of_iounmap(&op->resource[0], i2c, 0x2); + for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) + kfree(i2c_childlist[index].tables); return err; } -static void __exit envctrl_cleanup(void) +static int envctrl_remove(struct platform_device *op) { - int i; + int index; kthread_stop(kenvctrld_task); - iounmap(i2c); + of_iounmap(&op->resource[0], i2c, 0x2); misc_deregister(&envctrl_dev); - for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) - kfree(i2c_childlist[i].tables); + for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) + kfree(i2c_childlist[index].tables); + + return 0; } -module_init(envctrl_init); -module_exit(envctrl_cleanup); +static const struct of_device_id envctrl_match[] = { + { + .name = "i2c", + .compatible = "i2cpcf,8584", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, envctrl_match); + +static struct platform_driver envctrl_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = envctrl_match, + }, + .probe = envctrl_probe, + .remove = envctrl_remove, +}; + +module_platform_driver(envctrl_driver); + MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index fa2418f7ad3..25c738e9ef1 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -1,5 +1,4 @@ -/* $Id: flash.c,v 1.25 2001/12/21 04:56:16 davem Exp $ - * flash.c: Allow mmap access to the OBP Flash, for OBP updates. +/* flash.c: Allow mmap access to the OBP Flash, for OBP updates. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) */ @@ -8,21 +7,20 @@ #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> -#include <linux/slab.h> #include <linux/fcntl.h> #include <linux/poll.h> -#include <linux/init.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/of.h> +#include <linux/of_device.h> -#include <asm/system.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/io.h> -#include <asm/sbus.h> -#include <asm/ebus.h> #include <asm/upa.h> +static DEFINE_MUTEX(flash_mutex); static DEFINE_SPINLOCK(flash_lock); static struct { unsigned long read_base; /* Physical read address */ @@ -81,7 +79,7 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) static long long flash_llseek(struct file *file, long long offset, int origin) { - lock_kernel(); + mutex_lock(&flash_mutex); switch (origin) { case 0: file->f_pos = offset; @@ -95,10 +93,10 @@ flash_llseek(struct file *file, long long offset, int origin) file->f_pos = flash.read_size; break; default: - unlock_kernel(); + mutex_unlock(&flash_mutex); return -EINVAL; } - unlock_kernel(); + mutex_unlock(&flash_mutex); return file->f_pos; } @@ -106,9 +104,9 @@ static ssize_t flash_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - unsigned long p = file->f_pos; + loff_t p = *ppos; int i; - + if (count > flash.read_size - p) count = flash.read_size - p; @@ -119,16 +117,20 @@ flash_read(struct file * file, char __user * buf, buf++; } - file->f_pos += count; + *ppos += count; return count; } static int flash_open(struct inode *inode, struct file *file) { - if (test_and_set_bit(0, (void *)&flash.busy) != 0) + mutex_lock(&flash_mutex); + if (test_and_set_bit(0, (void *)&flash.busy) != 0) { + mutex_unlock(&flash_mutex); return -EBUSY; + } + mutex_unlock(&flash_mutex); return 0; } @@ -142,7 +144,7 @@ flash_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations flash_fops = { +static const struct file_operations flash_fops = { /* no write to the Flash, use mmap * and play flash dependent tricks. */ @@ -156,99 +158,62 @@ static struct file_operations flash_fops = { static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; -static int __init flash_init(void) +static int flash_probe(struct platform_device *op) { - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; -#ifdef CONFIG_PCI - struct linux_ebus *ebus; - struct linux_ebus_device *edev = NULL; - struct linux_prom_registers regs[2]; - int len, nregs; -#endif - int err; - - for_all_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, "flashprom")) { - if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) { - flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | - (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); - flash.read_size = sdev->reg_addrs[0].reg_size; - flash.write_base = flash.read_base; - flash.write_size = flash.read_size; - } else { - flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | - (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); - flash.read_size = sdev->reg_addrs[0].reg_size; - flash.write_base = ((unsigned long)sdev->reg_addrs[1].phys_addr) | - (((unsigned long)sdev->reg_addrs[1].which_io)<<32UL); - flash.write_size = sdev->reg_addrs[1].reg_size; - } - flash.busy = 0; - break; - } - } - if (!sdev) { -#ifdef CONFIG_PCI - struct linux_prom_registers *ebus_regs; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->prom_node->name, "flashprom")) - goto ebus_done; - } - } - ebus_done: - if (!edev) - return -ENODEV; - - ebus_regs = of_get_property(edev->prom_node, "reg", &len); - if (!ebus_regs || (len % sizeof(regs[0])) != 0) { - printk("flash: Strange reg property size %d\n", len); - return -ENODEV; - } - - nregs = len / sizeof(ebus_regs[0]); - - flash.read_base = edev->resource[0].start; - flash.read_size = ebus_regs[0].reg_size; - - if (nregs == 1) { - flash.write_base = edev->resource[0].start; - flash.write_size = ebus_regs[0].reg_size; - } else if (nregs == 2) { - flash.write_base = edev->resource[1].start; - flash.write_size = ebus_regs[1].reg_size; - } else { - printk("flash: Strange number of regs %d\n", nregs); - return -ENODEV; - } + struct device_node *dp = op->dev.of_node; + struct device_node *parent; - flash.busy = 0; + parent = dp->parent; -#else + if (strcmp(parent->name, "sbus") && + strcmp(parent->name, "sbi") && + strcmp(parent->name, "ebus")) return -ENODEV; -#endif + + flash.read_base = op->resource[0].start; + flash.read_size = resource_size(&op->resource[0]); + if (op->resource[1].flags) { + flash.write_base = op->resource[1].start; + flash.write_size = resource_size(&op->resource[1]); + } else { + flash.write_base = op->resource[0].start; + flash.write_size = resource_size(&op->resource[0]); } + flash.busy = 0; - printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n", + printk(KERN_INFO "%s: OBP Flash, RD %lx[%lx] WR %lx[%lx]\n", + op->dev.of_node->full_name, flash.read_base, flash.read_size, flash.write_base, flash.write_size); - err = misc_register(&flash_dev); - if (err) { - printk(KERN_ERR "flash: unable to get misc minor\n"); - return err; - } - - return 0; + return misc_register(&flash_dev); } -static void __exit flash_cleanup(void) +static int flash_remove(struct platform_device *op) { misc_deregister(&flash_dev); + + return 0; } -module_init(flash_init); -module_exit(flash_cleanup); +static const struct of_device_id flash_match[] = { + { + .name = "flashprom", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, flash_match); + +static struct platform_driver flash_driver = { + .driver = { + .name = "flash", + .owner = THIS_MODULE, + .of_match_table = flash_match, + }, + .probe = flash_probe, + .remove = flash_remove, +}; + +module_platform_driver(flash_driver); + MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index 14631ac11bc..a40ee1e3748 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -13,7 +13,7 @@ * TODO: Erase/program both banks of a 8MB SIMM. * * It is anticipated that programming an OS Flash will be a routine - * procedure. In the same time it is exeedingly dangerous because + * procedure. In the same time it is exceedingly dangerous because * a user can program its OBP flash with OS image and effectively * kill the machine. * @@ -27,20 +27,16 @@ */ #include <linux/module.h> +#include <linux/mutex.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> -#include <linux/slab.h> #include <linux/fcntl.h> #include <linux/poll.h> #include <linux/init.h> #include <linux/string.h> -#include <linux/smp_lock.h> #include <linux/genhd.h> #include <linux/blkdev.h> - -#define MAJOR_NR JSFD_MAJOR - #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/io.h> @@ -72,6 +68,8 @@ #define JSF_PART_BITS 2 /* 2 bits of minors to cover JSF_NPART */ #define JSF_PART_MASK 0x3 /* 2 bits mask */ +static DEFINE_MUTEX(jsf_mutex); + /* * Access functions. * We could ioremap(), but it's easier this way. @@ -185,35 +183,35 @@ static void jsfd_read(char *buf, unsigned long p, size_t togo) { } } -static void jsfd_do_request(request_queue_t *q) +static void jsfd_do_request(struct request_queue *q) { struct request *req; - while ((req = elv_next_request(q)) != NULL) { + req = blk_fetch_request(q); + while (req) { struct jsfd_part *jdp = req->rq_disk->private_data; - unsigned long offset = req->sector << 9; - size_t len = req->current_nr_sectors << 9; + unsigned long offset = blk_rq_pos(req) << 9; + size_t len = blk_rq_cur_bytes(req); + int err = -EIO; - if ((offset + len) > jdp->dsize) { - end_request(req, 0); - continue; - } + if ((offset + len) > jdp->dsize) + goto end; if (rq_data_dir(req) != READ) { printk(KERN_ERR "jsfd: write\n"); - end_request(req, 0); - continue; + goto end; } if ((jdp->dbase & 0xff000000) != 0x20000000) { printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase); - end_request(req, 0); - continue; + goto end; } - jsfd_read(req->buffer, jdp->dbase + offset, len); - - end_request(req, 1); + jsfd_read(bio_data(req->bio), jdp->dbase + offset, len); + err = 0; + end: + if (!__blk_end_request_cur(req, err)) + req = blk_fetch_request(q); } } @@ -229,7 +227,7 @@ static loff_t jsf_lseek(struct file * file, loff_t offset, int orig) { loff_t ret; - lock_kernel(); + mutex_lock(&jsf_mutex); switch (orig) { case 0: file->f_pos = offset; @@ -242,7 +240,7 @@ static loff_t jsf_lseek(struct file * file, loff_t offset, int orig) default: ret = -EINVAL; } - unlock_kernel(); + mutex_unlock(&jsf_mutex); return ret; } @@ -386,18 +384,22 @@ static int jsf_ioctl_program(void __user *arg) return 0; } -static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd, - unsigned long arg) +static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { + mutex_lock(&jsf_mutex); int error = -ENOTTY; void __user *argp = (void __user *)arg; - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) { + mutex_unlock(&jsf_mutex); return -EPERM; + } switch (cmd) { case JSFLASH_IDENT: - if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) + if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) { + mutex_unlock(&jsf_mutex); return -EFAULT; + } break; case JSFLASH_ERASE: error = jsf_ioctl_erase(arg); @@ -407,6 +409,7 @@ static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd, break; } + mutex_unlock(&jsf_mutex); return error; } @@ -417,11 +420,17 @@ static int jsf_mmap(struct file * file, struct vm_area_struct * vma) static int jsf_open(struct inode * inode, struct file * filp) { - - if (jsf0.base == 0) return -ENXIO; - if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) + mutex_lock(&jsf_mutex); + if (jsf0.base == 0) { + mutex_unlock(&jsf_mutex); + return -ENXIO; + } + if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) { + mutex_unlock(&jsf_mutex); return -EBUSY; + } + mutex_unlock(&jsf_mutex); return 0; /* XXX What security? */ } @@ -431,12 +440,12 @@ static int jsf_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations jsf_fops = { +static const struct file_operations jsf_fops = { .owner = THIS_MODULE, .llseek = jsf_lseek, .read = jsf_read, .write = jsf_write, - .ioctl = jsf_ioctl, + .unlocked_ioctl = jsf_ioctl, .mmap = jsf_mmap, .open = jsf_open, .release = jsf_release, @@ -444,7 +453,7 @@ static struct file_operations jsf_fops = { static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops }; -static struct block_device_operations jsfd_fops = { +static const struct block_device_operations jsfd_fops = { .owner = THIS_MODULE, }; @@ -452,13 +461,13 @@ static int jsflash_init(void) { int rc; struct jsflash *jsf; - int node; + phandle node; char banner[128]; struct linux_prom_registers reg0; node = prom_getchild(prom_root_node); node = prom_searchsiblings(node, "flash-memory"); - if (node != 0 && node != -1) { + if (node != 0 && (s32)node != -1) { if (prom_getproperty(node, "reg", (char *)®0, sizeof(reg0)) == -1) { printk("jsflash: no \"reg\" property\n"); @@ -498,7 +507,6 @@ static int jsflash_init(void) } /* Let us be really paranoid for modifications to probing code. */ - /* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */ if (sparc_cpu_model != sun4m) { /* We must be on sun4m because we use MMU Bypass ASI. */ return -ENXIO; @@ -619,8 +627,7 @@ static void __exit jsflash_cleanup_module(void) jsf0.busy = 0; misc_deregister(&jsf_dev); - if (unregister_blkdev(JSFD_MAJOR, "jsfd") != 0) - printk("jsfd: cleanup_module failed\n"); + unregister_blkdev(JSFD_MAJOR, "jsfd"); blk_cleanup_queue(jsf_queue); } diff --git a/drivers/sbus/char/max1617.h b/drivers/sbus/char/max1617.h index 0bb09c286cb..cd30819a0a3 100644 --- a/drivers/sbus/char/max1617.h +++ b/drivers/sbus/char/max1617.h @@ -6,7 +6,7 @@ #define MAX1617_CPU_TEMP 0x01 /* Processor die temp in C */ #define MAX1617_STATUS 0x02 /* Chip status bits */ -/* Read-only versions of changable registers. */ +/* Read-only versions of changeable registers. */ #define MAX1617_RD_CFG_BYTE 0x03 /* Config register */ #define MAX1617_RD_CVRATE_BYTE 0x04 /* Temp conversion rate */ #define MAX1617_RD_AMB_HIGHLIM 0x05 /* Ambient high limit */ diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 2f698763ba5..5843288f64b 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -31,27 +31,26 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/sched.h> #include <linux/errno.h> #include <linux/slab.h> +#include <linux/mutex.h> #include <linux/string.h> #include <linux/miscdevice.h> #include <linux/init.h> #include <linux/fs.h> #include <asm/oplib.h> #include <asm/prom.h> -#include <asm/system.h> #include <asm/uaccess.h> #include <asm/openpromio.h> #ifdef CONFIG_PCI #include <linux/pci.h> -#include <asm/pbm.h> #endif MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@skynet.be)"); MODULE_DESCRIPTION("OPENPROM Configuration Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); +MODULE_ALIAS_MISCDEV(SUN_OPENPROM_MINOR); /* Private data kept by the driver for each descriptor. */ typedef struct openprom_private_data @@ -61,6 +60,7 @@ typedef struct openprom_private_data } DATA; /* ID of the PROM node containing all of the EEPROM options. */ +static DEFINE_MUTEX(openprom_mutex); static struct device_node *options_node; /* @@ -142,7 +142,7 @@ static int copyout(void __user *info, struct openpromio *opp, int len) static int opromgetprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize) { - void *pval; + const void *pval; int len; if (!dp || @@ -222,7 +222,7 @@ static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp case OPROMSETCUR: default: break; - }; + } } else { /* Sibling of node zero is the root node. */ if (cmd != OPROMNEXT) @@ -233,7 +233,7 @@ static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp ph = 0; if (dp) - ph = dp->node; + ph = dp->phandle; data->current_node = dp; *((int *) op->oprom_array) = ph; @@ -249,18 +249,18 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp if (bufsize >= 2*sizeof(int)) { #ifdef CONFIG_PCI struct pci_dev *pdev; - struct pcidev_cookie *pcp; - pdev = pci_find_slot (((int *) op->oprom_array)[0], + struct device_node *dp; + + pdev = pci_get_bus_and_slot (((int *) op->oprom_array)[0], ((int *) op->oprom_array)[1]); - pcp = pdev->sysdata; - if (pcp != NULL) { - dp = pcp->prom_node; - data->current_node = dp; - *((int *)op->oprom_array) = dp->node; - op->oprom_size = sizeof(int); - err = copyout(argp, op, bufsize + sizeof(int)); - } + dp = pci_device_to_OF_node(pdev); + data->current_node = dp; + *((int *)op->oprom_array) = dp->phandle; + op->oprom_size = sizeof(int); + err = copyout(argp, op, bufsize + sizeof(int)); + + pci_dev_put(pdev); #endif } @@ -273,7 +273,7 @@ static int oprompath2node(void __user *argp, struct device_node *dp, struct open dp = of_find_node_by_path(op->oprom_array); if (dp) - ph = dp->node; + ph = dp->phandle; data->current_node = dp; *((int *)op->oprom_array) = ph; op->oprom_size = sizeof(int); @@ -298,12 +298,12 @@ static int opromgetbootargs(void __user *argp, struct openpromio *op, int bufsiz /* * SunOS and Solaris /dev/openprom ioctl calls. */ -static int openprom_sunos_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg, - struct device_node *dp) +static long openprom_sunos_ioctl(struct file * file, + unsigned int cmd, unsigned long arg, + struct device_node *dp) { DATA *data = file->private_data; - struct openpromio *opp; + struct openpromio *opp = NULL; int bufsize, error = 0; static int cnt; void __user *argp = (void __user *)arg; @@ -316,6 +316,8 @@ static int openprom_sunos_ioctl(struct inode * inode, struct file * file, if (bufsize < 0) return bufsize; + mutex_lock(&openprom_mutex); + switch (cmd) { case OPROMGETOPT: case OPROMGETPROP: @@ -365,6 +367,8 @@ static int openprom_sunos_ioctl(struct inode * inode, struct file * file, } kfree(opp); + mutex_unlock(&openprom_mutex); + return error; } @@ -410,7 +414,7 @@ static int opiocget(void __user *argp, DATA *data) struct opiocdesc op; struct device_node *dp; char *str; - void *pval; + const void *pval; int err, len; if (copy_from_user(&op, argp, sizeof(op))) @@ -540,20 +544,21 @@ static int opiocgetnext(unsigned int cmd, void __user *argp) } } if (dp) - nd = dp->node; + nd = dp->phandle; if (copy_to_user(argp, &nd, sizeof(phandle))) return -EFAULT; return 0; } -static int openprom_bsd_ioctl(struct inode * inode, struct file * file, +static int openprom_bsd_ioctl(struct file * file, unsigned int cmd, unsigned long arg) { - DATA *data = (DATA *) file->private_data; + DATA *data = file->private_data; void __user *argp = (void __user *)arg; int err; + mutex_lock(&openprom_mutex); switch (cmd) { case OPIOCGET: err = opiocget(argp, data); @@ -570,10 +575,10 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, case OPIOCGETOPTNODE: BUILD_BUG_ON(sizeof(phandle) != sizeof(int)); - if (copy_to_user(argp, &options_node->node, sizeof(phandle))) - return -EFAULT; - - return 0; + err = 0; + if (copy_to_user(argp, &options_node->phandle, sizeof(phandle))) + err = -EFAULT; + break; case OPIOCGETNEXT: case OPIOCGETCHILD: @@ -581,9 +586,10 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, break; default: - return -EINVAL; - - }; + err = -EINVAL; + break; + } + mutex_unlock(&openprom_mutex); return err; } @@ -592,24 +598,24 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, /* * Handoff control to the correct ioctl handler. */ -static int openprom_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +static long openprom_ioctl(struct file * file, + unsigned int cmd, unsigned long arg) { - DATA *data = (DATA *) file->private_data; + DATA *data = file->private_data; switch (cmd) { case OPROMGETOPT: case OPROMNXTOPT: if ((file->f_mode & FMODE_READ) == 0) return -EPERM; - return openprom_sunos_ioctl(inode, file, cmd, arg, + return openprom_sunos_ioctl(file, cmd, arg, options_node); case OPROMSETOPT: case OPROMSETOPT2: if ((file->f_mode & FMODE_WRITE) == 0) return -EPERM; - return openprom_sunos_ioctl(inode, file, cmd, arg, + return openprom_sunos_ioctl(file, cmd, arg, options_node); case OPROMNEXT: @@ -618,7 +624,7 @@ static int openprom_ioctl(struct inode * inode, struct file * file, case OPROMNXTPROP: if ((file->f_mode & FMODE_READ) == 0) return -EPERM; - return openprom_sunos_ioctl(inode, file, cmd, arg, + return openprom_sunos_ioctl(file, cmd, arg, data->current_node); case OPROMU2P: @@ -630,7 +636,7 @@ static int openprom_ioctl(struct inode * inode, struct file * file, case OPROMPATH2NODE: if ((file->f_mode & FMODE_READ) == 0) return -EPERM; - return openprom_sunos_ioctl(inode, file, cmd, arg, 0); + return openprom_sunos_ioctl(file, cmd, arg, NULL); case OPIOCGET: case OPIOCNEXTPROP: @@ -639,12 +645,12 @@ static int openprom_ioctl(struct inode * inode, struct file * file, case OPIOCGETCHILD: if ((file->f_mode & FMODE_READ) == 0) return -EBADF; - return openprom_bsd_ioctl(inode,file,cmd,arg); + return openprom_bsd_ioctl(file,cmd,arg); case OPIOCSET: if ((file->f_mode & FMODE_WRITE) == 0) return -EBADF; - return openprom_bsd_ioctl(inode,file,cmd,arg); + return openprom_bsd_ioctl(file,cmd,arg); default: return -EINVAL; @@ -676,7 +682,7 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd, case OPROMSETCUR: case OPROMPCI2NODE: case OPROMPATH2NODE: - rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg); + rval = openprom_ioctl(file, cmd, arg); break; } @@ -691,9 +697,11 @@ static int openprom_open(struct inode * inode, struct file * file) if (!data) return -ENOMEM; + mutex_lock(&openprom_mutex); data->current_node = of_find_node_by_path("/"); data->lastnode = data->current_node; file->private_data = (void *) data; + mutex_unlock(&openprom_mutex); return 0; } @@ -704,10 +712,10 @@ static int openprom_release(struct inode * inode, struct file * file) return 0; } -static struct file_operations openprom_fops = { +static const struct file_operations openprom_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = openprom_ioctl, + .unlocked_ioctl = openprom_ioctl, .compat_ioctl = openprom_compat_ioctl, .open = openprom_open, .release = openprom_release, diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c deleted file mode 100644 index 2a9cc820442..00000000000 --- a/drivers/sbus/char/riowatchdog.c +++ /dev/null @@ -1,293 +0,0 @@ -/* $Id: riowatchdog.c,v 1.3.2.2 2002/01/23 18:48:02 davem Exp $ - * riowatchdog.c - driver for hw watchdog inside Super I/O of RIO - * - * Copyright (C) 2001 David S. Miller (davem@redhat.com) - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/miscdevice.h> - -#include <asm/io.h> -#include <asm/ebus.h> -#include <asm/bbc.h> -#include <asm/oplib.h> -#include <asm/uaccess.h> - -#include <asm/watchdog.h> - -/* RIO uses the NatSemi Super I/O power management logical device - * as its' watchdog. - * - * When the watchdog triggers, it asserts a line to the BBC (Boot Bus - * Controller) of the machine. The BBC can only be configured to - * trigger a power-on reset when the signal is asserted. The BBC - * can be configured to ignore the signal entirely as well. - * - * The only Super I/O device register we care about is at index - * 0x05 (WDTO_INDEX) which is the watchdog time-out in minutes (1-255). - * If set to zero, this disables the watchdog. When set, the system - * must periodically (before watchdog expires) clear (set to zero) and - * re-set the watchdog else it will trigger. - * - * There are two other indexed watchdog registers inside this Super I/O - * logical device, but they are unused. The first, at index 0x06 is - * the watchdog control and can be used to make the watchdog timer re-set - * when the PS/2 mouse or serial lines show activity. The second, at - * index 0x07 is merely a sampling of the line from the watchdog to the - * BBC. - * - * The watchdog device generates no interrupts. - */ - -MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); -MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO"); -MODULE_SUPPORTED_DEVICE("watchdog"); -MODULE_LICENSE("GPL"); - -#define RIOWD_NAME "pmc" -#define RIOWD_MINOR 215 - -static DEFINE_SPINLOCK(riowd_lock); - -static void __iomem *bbc_regs; -static void __iomem *riowd_regs; -#define WDTO_INDEX 0x05 - -static int riowd_timeout = 1; /* in minutes */ -module_param(riowd_timeout, int, 0); -MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes"); - -#if 0 /* Currently unused. */ -static u8 riowd_readreg(int index) -{ - unsigned long flags; - u8 ret; - - spin_lock_irqsave(&riowd_lock, flags); - writeb(index, riowd_regs + 0); - ret = readb(riowd_regs + 1); - spin_unlock_irqrestore(&riowd_lock, flags); - - return ret; -} -#endif - -static void riowd_writereg(u8 val, int index) -{ - unsigned long flags; - - spin_lock_irqsave(&riowd_lock, flags); - writeb(index, riowd_regs + 0); - writeb(val, riowd_regs + 1); - spin_unlock_irqrestore(&riowd_lock, flags); -} - -static void riowd_pingtimer(void) -{ - riowd_writereg(riowd_timeout, WDTO_INDEX); -} - -static void riowd_stoptimer(void) -{ - u8 val; - - riowd_writereg(0, WDTO_INDEX); - - val = readb(bbc_regs + BBC_WDACTION); - val &= ~BBC_WDACTION_RST; - writeb(val, bbc_regs + BBC_WDACTION); -} - -static void riowd_starttimer(void) -{ - u8 val; - - riowd_writereg(riowd_timeout, WDTO_INDEX); - - val = readb(bbc_regs + BBC_WDACTION); - val |= BBC_WDACTION_RST; - writeb(val, bbc_regs + BBC_WDACTION); -} - -static int riowd_open(struct inode *inode, struct file *filp) -{ - nonseekable_open(inode, filp); - return 0; -} - -static int riowd_release(struct inode *inode, struct file *filp) -{ - return 0; -} - -static int riowd_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - static struct watchdog_info info = { - WDIOF_SETTIMEOUT, 0, "Natl. Semiconductor PC97317" - }; - void __user *argp = (void __user *)arg; - unsigned int options; - int new_margin; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - if (put_user(0, (int __user *)argp)) - return -EFAULT; - break; - - case WDIOC_KEEPALIVE: - riowd_pingtimer(); - break; - - case WDIOC_SETOPTIONS: - if (copy_from_user(&options, argp, sizeof(options))) - return -EFAULT; - - if (options & WDIOS_DISABLECARD) - riowd_stoptimer(); - else if (options & WDIOS_ENABLECARD) - riowd_starttimer(); - else - return -EINVAL; - - break; - - case WDIOC_SETTIMEOUT: - if (get_user(new_margin, (int __user *)argp)) - return -EFAULT; - if ((new_margin < 60) || (new_margin > (255 * 60))) - return -EINVAL; - riowd_timeout = (new_margin + 59) / 60; - riowd_pingtimer(); - /* Fall */ - - case WDIOC_GETTIMEOUT: - return put_user(riowd_timeout * 60, (int __user *)argp); - - default: - return -EINVAL; - }; - - return 0; -} - -static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) -{ - if (count) { - riowd_pingtimer(); - return 1; - } - - return 0; -} - -static struct file_operations riowd_fops = { - .owner = THIS_MODULE, - .ioctl = riowd_ioctl, - .open = riowd_open, - .write = riowd_write, - .release = riowd_release, -}; - -static struct miscdevice riowd_miscdev = { RIOWD_MINOR, RIOWD_NAME, &riowd_fops }; - -static int __init riowd_bbc_init(void) -{ - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; - u8 val; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->ofdev.node->name, "bbc")) - goto found_bbc; - } - } - -found_bbc: - if (!edev) - return -ENODEV; - bbc_regs = ioremap(edev->resource[0].start, BBC_REGS_SIZE); - if (!bbc_regs) - return -ENODEV; - - /* Turn it off. */ - val = readb(bbc_regs + BBC_WDACTION); - val &= ~BBC_WDACTION_RST; - writeb(val, bbc_regs + BBC_WDACTION); - - return 0; -} - -static int __init riowd_init(void) -{ - struct linux_ebus *ebus = NULL; - struct linux_ebus_device *edev = NULL; - - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - if (!strcmp(edev->ofdev.node->name, RIOWD_NAME)) - goto ebus_done; - } - } - -ebus_done: - if (!edev) - goto fail; - - riowd_regs = ioremap(edev->resource[0].start, 2); - if (riowd_regs == NULL) { - printk(KERN_ERR "pmc: Cannot map registers.\n"); - return -ENODEV; - } - - if (riowd_bbc_init()) { - printk(KERN_ERR "pmc: Failure initializing BBC config.\n"); - goto fail; - } - - if (misc_register(&riowd_miscdev)) { - printk(KERN_ERR "pmc: Cannot register watchdog misc device.\n"); - goto fail; - } - - printk(KERN_INFO "pmc: Hardware watchdog [%i minutes], " - "regs at %p\n", riowd_timeout, riowd_regs); - - return 0; - -fail: - if (riowd_regs) { - iounmap(riowd_regs); - riowd_regs = NULL; - } - if (bbc_regs) { - iounmap(bbc_regs); - bbc_regs = NULL; - } - return -ENODEV; -} - -static void __exit riowd_cleanup(void) -{ - misc_deregister(&riowd_miscdev); - iounmap(riowd_regs); - riowd_regs = NULL; - iounmap(bbc_regs); - bbc_regs = NULL; -} - -module_init(riowd_init); -module_exit(riowd_cleanup); diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c deleted file mode 100644 index 9b988baf0b5..00000000000 --- a/drivers/sbus/char/rtc.c +++ /dev/null @@ -1,273 +0,0 @@ -/* $Id: rtc.c,v 1.28 2001/10/08 22:19:51 davem Exp $ - * - * Linux/SPARC Real Time Clock Driver - * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) - * - * This is a little driver that lets a user-level program access - * the SPARC Mostek real time clock chip. It is no use unless you - * use the modified clock utility. - * - * Get the modified clock utility from: - * ftp://vger.kernel.org/pub/linux/Sparc/userland/clock.c - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/miscdevice.h> -#include <linux/slab.h> -#include <linux/fcntl.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/smp_lock.h> -#include <asm/io.h> -#include <asm/mostek.h> -#include <asm/system.h> -#include <asm/uaccess.h> -#include <asm/rtc.h> - -static int rtc_busy = 0; - -/* This is the structure layout used by drivers/char/rtc.c, we - * support that driver's ioctls so that things are less messy in - * userspace. - */ -struct rtc_time_generic { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; -}; -#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */ -#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */ -#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ -#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */ -#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */ -#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */ -#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */ -#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */ -#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time */ -#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time */ -#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */ -#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */ -#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */ -#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */ -#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ -#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ -#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ -#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ -#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ -#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ - -/* Retrieve the current date and time from the real time clock. */ -static void get_rtc_time(struct rtc_time *t) -{ - void __iomem *regs = mstk48t02_regs; - u8 tmp; - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(regs + MOSTEK_CREG, tmp); - - t->sec = MSTK_REG_SEC(regs); - t->min = MSTK_REG_MIN(regs); - t->hour = MSTK_REG_HOUR(regs); - t->dow = MSTK_REG_DOW(regs); - t->dom = MSTK_REG_DOM(regs); - t->month = MSTK_REG_MONTH(regs); - t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); -} - -/* Set the current date and time inthe real time clock. */ -void set_rtc_time(struct rtc_time *t) -{ - void __iomem *regs = mstk48t02_regs; - u8 tmp; - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - MSTK_SET_REG_SEC(regs,t->sec); - MSTK_SET_REG_MIN(regs,t->min); - MSTK_SET_REG_HOUR(regs,t->hour); - MSTK_SET_REG_DOW(regs,t->dow); - MSTK_SET_REG_DOM(regs,t->dom); - MSTK_SET_REG_MONTH(regs,t->month); - MSTK_SET_REG_YEAR(regs,t->year - MSTK_YEAR_ZERO); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); -} - -static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm) -{ - struct rtc_time_generic __user *utm = argp; - - if (__put_user(tm->sec, &utm->tm_sec) || - __put_user(tm->min, &utm->tm_min) || - __put_user(tm->hour, &utm->tm_hour) || - __put_user(tm->dom, &utm->tm_mday) || - __put_user(tm->month, &utm->tm_mon) || - __put_user(tm->year, &utm->tm_year) || - __put_user(tm->dow, &utm->tm_wday) || - __put_user(0, &utm->tm_yday) || - __put_user(0, &utm->tm_isdst)) - return -EFAULT; - - return 0; -} - -static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp) -{ - struct rtc_time_generic __user *utm = argp; - - if (__get_user(tm->sec, &utm->tm_sec) || - __get_user(tm->min, &utm->tm_min) || - __get_user(tm->hour, &utm->tm_hour) || - __get_user(tm->dom, &utm->tm_mday) || - __get_user(tm->month, &utm->tm_mon) || - __get_user(tm->year, &utm->tm_year) || - __get_user(tm->dow, &utm->tm_wday)) - return -EFAULT; - - return 0; -} - -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct rtc_time rtc_tm; - void __user *argp = (void __user *)arg; - - switch (cmd) { - /* No interrupt support, return an error - * compatible with drivers/char/rtc.c - */ - case RTC_AIE_OFF: - case RTC_AIE_ON: - case RTC_PIE_OFF: - case RTC_PIE_ON: - case RTC_UIE_OFF: - case RTC_UIE_ON: - case RTC_IRQP_READ: - case RTC_IRQP_SET: - case RTC_EPOCH_SET: - case RTC_EPOCH_READ: - return -EINVAL; - - case RTCGET: - case RTC_RD_TIME: - memset(&rtc_tm, 0, sizeof(struct rtc_time)); - get_rtc_time(&rtc_tm); - - if (cmd == RTCGET) { - if (copy_to_user(argp, &rtc_tm, - sizeof(struct rtc_time))) - return -EFAULT; - } else if (put_rtc_time_generic(argp, &rtc_tm)) - return -EFAULT; - - return 0; - - - case RTCSET: - case RTC_SET_TIME: - if (!capable(CAP_SYS_TIME)) - return -EPERM; - - if (cmd == RTCSET) { - if (copy_from_user(&rtc_tm, argp, - sizeof(struct rtc_time))) - return -EFAULT; - } else if (get_rtc_time_generic(&rtc_tm, argp)) - return -EFAULT; - - set_rtc_time(&rtc_tm); - - return 0; - - default: - return -EINVAL; - } -} - -static int rtc_open(struct inode *inode, struct file *file) -{ - int ret; - - spin_lock_irq(&mostek_lock); - if (rtc_busy) { - ret = -EBUSY; - } else { - rtc_busy = 1; - ret = 0; - } - spin_unlock_irq(&mostek_lock); - - return ret; -} - -static int rtc_release(struct inode *inode, struct file *file) -{ - rtc_busy = 0; - - return 0; -} - -static struct file_operations rtc_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, -}; - -static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops }; - -static int __init rtc_sun_init(void) -{ - int error; - - /* It is possible we are being driven by some other RTC chip - * and thus another RTC driver is handling things. - */ - if (!mstk48t02_regs) - return -ENODEV; - - error = misc_register(&rtc_dev); - if (error) { - printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n"); - return error; - } - printk("rtc_sun_init: Registered Mostek RTC driver.\n"); - - return 0; -} - -static void __exit rtc_sun_cleanup(void) -{ - misc_deregister(&rtc_dev); -} - -module_init(rtc_sun_init); -module_exit(rtc_sun_cleanup); -MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 575b1f7ed41..b7acafc8509 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -1,27 +1,26 @@ -/* $Id: uctrl.c,v 1.12 2001/10/08 22:19:51 davem Exp $ - * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 +/* uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 * * Copyright 1999 Derrick J Brashear (shadow@dementia.org) + * Copyright 2008 David S. Miller (davem@davemloft.net) */ #include <linux/module.h> -#include <linux/sched.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/slab.h> +#include <linux/mutex.h> #include <linux/ioport.h> -#include <linux/init.h> #include <linux/miscdevice.h> #include <linux/mm.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/openprom.h> #include <asm/oplib.h> -#include <asm/system.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/pgtable.h> -#include <asm/sbus.h> #define UCTRL_MINOR 174 @@ -33,26 +32,26 @@ #endif struct uctrl_regs { - volatile u32 uctrl_intr; - volatile u32 uctrl_data; - volatile u32 uctrl_stat; - volatile u32 uctrl_xxx[5]; + u32 uctrl_intr; + u32 uctrl_data; + u32 uctrl_stat; + u32 uctrl_xxx[5]; }; struct ts102_regs { - volatile u32 card_a_intr; - volatile u32 card_a_stat; - volatile u32 card_a_ctrl; - volatile u32 card_a_xxx; - volatile u32 card_b_intr; - volatile u32 card_b_stat; - volatile u32 card_b_ctrl; - volatile u32 card_b_xxx; - volatile u32 uctrl_intr; - volatile u32 uctrl_data; - volatile u32 uctrl_stat; - volatile u32 uctrl_xxx; - volatile u32 ts102_xxx[4]; + u32 card_a_intr; + u32 card_a_stat; + u32 card_a_ctrl; + u32 card_a_xxx; + u32 card_b_intr; + u32 card_b_stat; + u32 card_b_ctrl; + u32 card_b_xxx; + u32 uctrl_intr; + u32 uctrl_data; + u32 uctrl_stat; + u32 uctrl_xxx; + u32 ts102_xxx[4]; }; /* Bits for uctrl_intr register */ @@ -71,6 +70,7 @@ struct ts102_regs { #define UCTRL_STAT_RXNE_STA 0x04 /* receive FIFO not empty status */ #define UCTRL_STAT_RXO_STA 0x08 /* receive FIFO overflow status */ +static DEFINE_MUTEX(uctrl_mutex); static const char *uctrl_extstatus[16] = { "main power available", "internal battery attached", @@ -186,21 +186,18 @@ enum uctrl_opcode { POWER_RESTART=0x83, }; -struct uctrl_driver { - struct uctrl_regs *regs; +static struct uctrl_driver { + struct uctrl_regs __iomem *regs; int irq; int pending; struct uctrl_status status; -}; - -static struct uctrl_driver drv; +} *global_driver; -void uctrl_get_event_status(void); -void uctrl_get_external_status(void); +static void uctrl_get_event_status(struct uctrl_driver *); +static void uctrl_get_external_status(struct uctrl_driver *); -static int -uctrl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long +uctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { default: @@ -212,22 +209,22 @@ uctrl_ioctl(struct inode *inode, struct file *file, static int uctrl_open(struct inode *inode, struct file *file) { - uctrl_get_event_status(); - uctrl_get_external_status(); + mutex_lock(&uctrl_mutex); + uctrl_get_event_status(global_driver); + uctrl_get_external_status(global_driver); + mutex_unlock(&uctrl_mutex); return 0; } -static irqreturn_t uctrl_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t uctrl_interrupt(int irq, void *dev_id) { - struct uctrl_driver *driver = (struct uctrl_driver *)dev_id; - printk("in uctrl_interrupt\n"); return IRQ_HANDLED; } -static struct file_operations uctrl_fops = { +static const struct file_operations uctrl_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = uctrl_ioctl, + .unlocked_ioctl = uctrl_ioctl, .open = uctrl_open, }; @@ -242,11 +239,11 @@ static struct miscdevice uctrl_dev = { { \ unsigned int i; \ for (i = 0; i < 10000; i++) { \ - if (UCTRL_STAT_TXNF_STA & driver->regs->uctrl_stat) \ + if (UCTRL_STAT_TXNF_STA & sbus_readl(&driver->regs->uctrl_stat)) \ break; \ } \ dprintk(("write data 0x%02x\n", value)); \ - driver->regs->uctrl_data = value; \ + sbus_writel(value, &driver->regs->uctrl_data); \ } /* Wait for something to read, read it, then clear the bit */ @@ -255,30 +252,23 @@ static struct miscdevice uctrl_dev = { unsigned int i; \ value = 0; \ for (i = 0; i < 10000; i++) { \ - if ((UCTRL_STAT_RXNE_STA & driver->regs->uctrl_stat) == 0) \ + if ((UCTRL_STAT_RXNE_STA & sbus_readl(&driver->regs->uctrl_stat)) == 0) \ break; \ udelay(1); \ } \ - value = driver->regs->uctrl_data; \ + value = sbus_readl(&driver->regs->uctrl_data); \ dprintk(("read data 0x%02x\n", value)); \ - driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \ -} - -void uctrl_set_video(int status) -{ - struct uctrl_driver *driver = &drv; - + sbus_writel(UCTRL_STAT_RXNE_STA, &driver->regs->uctrl_stat); \ } -static void uctrl_do_txn(struct uctrl_txn *txn) +static void uctrl_do_txn(struct uctrl_driver *driver, struct uctrl_txn *txn) { - struct uctrl_driver *driver = &drv; int stat, incnt, outcnt, bytecnt, intr; u32 byte; - stat = driver->regs->uctrl_stat; - intr = driver->regs->uctrl_intr; - driver->regs->uctrl_stat = stat; + stat = sbus_readl(&driver->regs->uctrl_stat); + intr = sbus_readl(&driver->regs->uctrl_intr); + sbus_writel(stat, &driver->regs->uctrl_stat); dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr)); @@ -309,9 +299,8 @@ static void uctrl_do_txn(struct uctrl_txn *txn) } } -void uctrl_get_event_status(void) +static void uctrl_get_event_status(struct uctrl_driver *driver) { - struct uctrl_driver *driver = &drv; struct uctrl_txn txn; u8 outbits[2]; @@ -321,7 +310,7 @@ void uctrl_get_event_status(void) txn.inbuf = NULL; txn.outbuf = outbits; - uctrl_do_txn(&txn); + uctrl_do_txn(driver, &txn); dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); driver->status.event_status = @@ -329,9 +318,8 @@ void uctrl_get_event_status(void) dprintk(("ev is %x\n", driver->status.event_status)); } -void uctrl_get_external_status(void) +static void uctrl_get_external_status(struct uctrl_driver *driver) { - struct uctrl_driver *driver = &drv; struct uctrl_txn txn; u8 outbits[2]; int i, v; @@ -342,7 +330,7 @@ void uctrl_get_external_status(void) txn.inbuf = NULL; txn.outbuf = outbits; - uctrl_do_txn(&txn); + uctrl_do_txn(driver, &txn); dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); driver->status.external_status = @@ -358,65 +346,93 @@ void uctrl_get_external_status(void) } -static int __init ts102_uctrl_init(void) +static int uctrl_probe(struct platform_device *op) { - struct uctrl_driver *driver = &drv; - int len, i; - struct linux_prom_irqs tmp_irq[2]; - unsigned int vaddr[2] = { 0, 0 }; - int tmpnode, uctrlnode = prom_getchild(prom_root_node); - - tmpnode = prom_searchsiblings(uctrlnode, "obio"); + struct uctrl_driver *p; + int err = -ENOMEM; - if (tmpnode) - uctrlnode = prom_getchild(tmpnode); + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) { + printk(KERN_ERR "uctrl: Unable to allocate device struct.\n"); + goto out; + } - uctrlnode = prom_searchsiblings(uctrlnode, "uctrl"); + p->regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), + "uctrl"); + if (!p->regs) { + printk(KERN_ERR "uctrl: Unable to map registers.\n"); + goto out_free; + } - if (!uctrlnode) - return -ENODEV; + p->irq = op->archdata.irqs[0]; + err = request_irq(p->irq, uctrl_interrupt, 0, "uctrl", p); + if (err) { + printk(KERN_ERR "uctrl: Unable to register irq.\n"); + goto out_iounmap; + } - /* the prom mapped it for us */ - len = prom_getproperty(uctrlnode, "address", (void *) vaddr, - sizeof(vaddr)); - driver->regs = (struct uctrl_regs *)vaddr[0]; + err = misc_register(&uctrl_dev); + if (err) { + printk(KERN_ERR "uctrl: Unable to register misc device.\n"); + goto out_free_irq; + } - len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq, - sizeof(tmp_irq)); + sbus_writel(UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK, &p->regs->uctrl_intr); + printk(KERN_INFO "%s: uctrl regs[0x%p] (irq %d)\n", + op->dev.of_node->full_name, p->regs, p->irq); + uctrl_get_event_status(p); + uctrl_get_external_status(p); - /* Flush device */ - READUCTLDATA(len); + dev_set_drvdata(&op->dev, p); + global_driver = p; - if(!driver->irq) - driver->irq = tmp_irq[0].pri; +out: + return err; - request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver); +out_free_irq: + free_irq(p->irq, p); - if (misc_register(&uctrl_dev)) { - printk("%s: unable to get misc minor %d\n", - __FUNCTION__, uctrl_dev.minor); - free_irq(driver->irq, driver); - return -ENODEV; - } +out_iounmap: + of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0])); - driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK; - printk("uctrl: 0x%x (irq %d)\n", driver->regs, driver->irq); - uctrl_get_event_status(); - uctrl_get_external_status(); - return 0; +out_free: + kfree(p); + goto out; } -static void __exit ts102_uctrl_cleanup(void) +static int uctrl_remove(struct platform_device *op) { - struct uctrl_driver *driver = &drv; + struct uctrl_driver *p = dev_get_drvdata(&op->dev); - misc_deregister(&uctrl_dev); - if (driver->irq) - free_irq(driver->irq, driver); - if (driver->regs) - driver->regs = NULL; + if (p) { + misc_deregister(&uctrl_dev); + free_irq(p->irq, p); + of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0])); + kfree(p); + } + return 0; } -module_init(ts102_uctrl_init); -module_exit(ts102_uctrl_cleanup); +static const struct of_device_id uctrl_match[] = { + { + .name = "uctrl", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, uctrl_match); + +static struct platform_driver uctrl_driver = { + .driver = { + .name = "uctrl", + .owner = THIS_MODULE, + .of_match_table = uctrl_match, + }, + .probe = uctrl_probe, + .remove = uctrl_remove, +}; + + +module_platform_driver(uctrl_driver); + MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h deleted file mode 100644 index 63941a259b9..00000000000 --- a/drivers/sbus/char/vfc.h +++ /dev/null @@ -1,175 +0,0 @@ -#ifndef _LINUX_VFC_H_ -#define _LINUX_VFC_H_ - -/* - * The control register for the vfc is at offset 0x4000 - * The first field ram bank is located at offset 0x5000 - * The second field ram bank is at offset 0x7000 - * i2c_reg address the Phillips PCF8584(see notes in vfc_i2c.c) - * data and transmit register. - * i2c_s1 controls register s1 of the PCF8584 - * i2c_write seems to be similar to i2c_write but I am not - * quite sure why sun uses it - * - * I am also not sure whether or not you can read the fram bank as a - * whole or whether you must read each word individually from offset - * 0x5000 as soon as I figure it out I will update this file */ - -struct vfc_regs { - char pad1[0x4000]; - unsigned int control; /* Offset 0x4000 */ - char pad2[0xffb]; /* from offset 0x4004 to 0x5000 */ - unsigned int fram_bank1; /* Offset 0x5000 */ - char pad3[0xffb]; /* from offset 0x5004 to 0x6000 */ - unsigned int i2c_reg; /* Offset 0x6000 */ - unsigned int i2c_magic2; /* Offset 0x6004 */ - unsigned int i2c_s1; /* Offset 0x6008 */ - unsigned int i2c_write; /* Offset 0x600c */ - char pad4[0xff0]; /* from offset 0x6010 to 0x7000 */ - unsigned int fram_bank2; /* Offset 0x7000 */ - char pad5[0x1000]; -}; - -#define VFC_SAA9051_NR (13) -#define VFC_SAA9051_ADDR (0x8a) - /* The saa9051 returns the following for its status - * bit 0 - 0 - * bit 1 - SECAM color detected (1=found,0=not found) - * bit 2 - COLOR detected (1=found,0=not found) - * bit 3 - 0 - * bit 4 - Field frequency bit (1=60Hz (NTSC), 0=50Hz (PAL)) - * bit 5 - 1 - * bit 6 - horizontal frequency lock (1=transmitter found, - * 0=no transmitter) - * bit 7 - Power on reset bit (1=reset,0=at least one successful - * read of the status byte) - */ - -#define VFC_SAA9051_PONRES (0x80) -#define VFC_SAA9051_HLOCK (0x40) -#define VFC_SAA9051_FD (0x10) -#define VFC_SAA9051_CD (0x04) -#define VFC_SAA9051_CS (0x02) - - -/* The various saa9051 sub addresses */ - -#define VFC_SAA9051_IDEL (0) -#define VFC_SAA9051_HSY_START (1) -#define VFC_SAA9051_HSY_STOP (2) -#define VFC_SAA9051_HC_START (3) -#define VFC_SAA9051_HC_STOP (4) -#define VFC_SAA9051_HS_START (5) -#define VFC_SAA9051_HORIZ_PEAK (6) -#define VFC_SAA9051_HUE (7) -#define VFC_SAA9051_C1 (8) -#define VFC_SAA9051_C2 (9) -#define VFC_SAA9051_C3 (0xa) -#define VFC_SAA9051_SECAM_DELAY (0xb) - - -/* Bit settings for saa9051 sub address 0x06 */ - -#define VFC_SAA9051_AP1 (0x01) -#define VFC_SAA9051_AP2 (0x02) -#define VFC_SAA9051_COR1 (0x04) -#define VFC_SAA9051_COR2 (0x08) -#define VFC_SAA9051_BP1 (0x10) -#define VFC_SAA9051_BP2 (0x20) -#define VFC_SAA9051_PF (0x40) -#define VFC_SAA9051_BY (0x80) - - -/* Bit settings for saa9051 sub address 0x08 */ - -#define VFC_SAA9051_CCFR0 (0x01) -#define VFC_SAA9051_CCFR1 (0x02) -#define VFC_SAA9051_YPN (0x04) -#define VFC_SAA9051_ALT (0x08) -#define VFC_SAA9051_CO (0x10) -#define VFC_SAA9051_VTR (0x20) -#define VFC_SAA9051_FS (0x40) -#define VFC_SAA9051_HPLL (0x80) - - -/* Bit settings for saa9051 sub address 9 */ - -#define VFC_SAA9051_SS0 (0x01) -#define VFC_SAA9051_SS1 (0x02) -#define VFC_SAA9051_AFCC (0x04) -#define VFC_SAA9051_CI (0x08) -#define VFC_SAA9051_SA9D4 (0x10) /* Don't care bit */ -#define VFC_SAA9051_OEC (0x20) -#define VFC_SAA9051_OEY (0x40) -#define VFC_SAA9051_VNL (0x80) - - -/* Bit settings for saa9051 sub address 0x0A */ - -#define VFC_SAA9051_YDL0 (0x01) -#define VFC_SAA9051_YDL1 (0x02) -#define VFC_SAA9051_YDL2 (0x04) -#define VFC_SAA9051_SS2 (0x08) -#define VFC_SAA9051_SS3 (0x10) -#define VFC_SAA9051_YC (0x20) -#define VFC_SAA9051_CT (0x40) -#define VFC_SAA9051_SYC (0x80) - - -#define VFC_SAA9051_SA(a,b) ((a)->saa9051_state_array[(b)+1]) -#define vfc_update_saa9051(a) (vfc_i2c_sendbuf((a),VFC_SAA9051_ADDR,\ - (a)->saa9051_state_array,\ - VFC_SAA9051_NR)) - - -struct vfc_dev { - volatile struct vfc_regs __iomem *regs; - struct vfc_regs *phys_regs; - unsigned int control_reg; - struct semaphore device_lock_sem; - int instance; - int busy; - unsigned long which_io; - unsigned char saa9051_state_array[VFC_SAA9051_NR]; -}; - -extern struct vfc_dev **vfc_dev_lst; - -void captstat_reset(struct vfc_dev *); -void memptr_reset(struct vfc_dev *); - -int vfc_pcf8584_init(struct vfc_dev *); -void vfc_i2c_delay_no_busy(struct vfc_dev *, unsigned long); -void vfc_i2c_delay(struct vfc_dev *); -int vfc_i2c_sendbuf(struct vfc_dev *, unsigned char, char *, int) ; -int vfc_i2c_recvbuf(struct vfc_dev *, unsigned char, char *, int) ; -int vfc_i2c_reset_bus(struct vfc_dev *); -int vfc_init_i2c_bus(struct vfc_dev *); -void vfc_lock_device(struct vfc_dev *); -void vfc_unlock_device(struct vfc_dev *); - -#define VFC_CONTROL_DIAGMODE 0x10000000 -#define VFC_CONTROL_MEMPTR 0x20000000 -#define VFC_CONTROL_CAPTURE 0x02000000 -#define VFC_CONTROL_CAPTRESET 0x04000000 - -#define VFC_STATUS_CAPTURE 0x08000000 - -#ifdef VFC_IOCTL_DEBUG -#define VFC_IOCTL_DEBUG_PRINTK(a) printk a -#else -#define VFC_IOCTL_DEBUG_PRINTK(a) -#endif - -#ifdef VFC_I2C_DEBUG -#define VFC_I2C_DEBUG_PRINTK(a) printk a -#else -#define VFC_I2C_DEBUG_PRINTK(a) -#endif - -#endif /* _LINUX_VFC_H_ */ - - - - - diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c deleted file mode 100644 index 55b2b31bd7a..00000000000 --- a/drivers/sbus/char/vfc_dev.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * drivers/sbus/char/vfc_dev.c - * - * Driver for the Videopix Frame Grabber. - * - * In order to use the VFC you need to program the video controller - * chip. This chip is the Phillips SAA9051. You need to call their - * documentation ordering line to get the docs. - * - * There is very little documentation on the VFC itself. There is - * some useful info that can be found in the manuals that come with - * the card. I will hopefully write some better docs at a later date. - * - * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) - * */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/smp_lock.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/mm.h> - -#include <asm/openprom.h> -#include <asm/oplib.h> -#include <asm/io.h> -#include <asm/system.h> -#include <asm/sbus.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/uaccess.h> - -#define VFC_MAJOR (60) - -#if 0 -#define VFC_IOCTL_DEBUG -#endif - -#include "vfc.h" -#include <asm/vfc_ioctls.h> - -static struct file_operations vfc_fops; -struct vfc_dev **vfc_dev_lst; -static char vfcstr[]="vfc"; -static unsigned char saa9051_init_array[VFC_SAA9051_NR] = { - 0x00, 0x64, 0x72, 0x52, - 0x36, 0x18, 0xff, 0x20, - 0xfc, 0x77, 0xe3, 0x50, - 0x3e -}; - -void vfc_lock_device(struct vfc_dev *dev) -{ - down(&dev->device_lock_sem); -} - -void vfc_unlock_device(struct vfc_dev *dev) -{ - up(&dev->device_lock_sem); -} - - -void vfc_captstat_reset(struct vfc_dev *dev) -{ - dev->control_reg |= VFC_CONTROL_CAPTRESET; - sbus_writel(dev->control_reg, &dev->regs->control); - dev->control_reg &= ~VFC_CONTROL_CAPTRESET; - sbus_writel(dev->control_reg, &dev->regs->control); - dev->control_reg |= VFC_CONTROL_CAPTRESET; - sbus_writel(dev->control_reg, &dev->regs->control); -} - -void vfc_memptr_reset(struct vfc_dev *dev) -{ - dev->control_reg |= VFC_CONTROL_MEMPTR; - sbus_writel(dev->control_reg, &dev->regs->control); - dev->control_reg &= ~VFC_CONTROL_MEMPTR; - sbus_writel(dev->control_reg, &dev->regs->control); - dev->control_reg |= VFC_CONTROL_MEMPTR; - sbus_writel(dev->control_reg, &dev->regs->control); -} - -int vfc_csr_init(struct vfc_dev *dev) -{ - dev->control_reg = 0x80000000; - sbus_writel(dev->control_reg, &dev->regs->control); - udelay(200); - dev->control_reg &= ~0x80000000; - sbus_writel(dev->control_reg, &dev->regs->control); - udelay(100); - sbus_writel(0x0f000000, &dev->regs->i2c_magic2); - - vfc_memptr_reset(dev); - - dev->control_reg &= ~VFC_CONTROL_DIAGMODE; - dev->control_reg &= ~VFC_CONTROL_CAPTURE; - dev->control_reg |= 0x40000000; - sbus_writel(dev->control_reg, &dev->regs->control); - - vfc_captstat_reset(dev); - - return 0; -} - -int vfc_saa9051_init(struct vfc_dev *dev) -{ - int i; - - for (i = 0; i < VFC_SAA9051_NR; i++) - dev->saa9051_state_array[i] = saa9051_init_array[i]; - - vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR, - dev->saa9051_state_array, VFC_SAA9051_NR); - return 0; -} - -int init_vfc_hw(struct vfc_dev *dev) -{ - vfc_lock_device(dev); - vfc_csr_init(dev); - - vfc_pcf8584_init(dev); - vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic - sun code above*/ - vfc_saa9051_init(dev); - vfc_unlock_device(dev); - return 0; -} - -int init_vfc_devstruct(struct vfc_dev *dev, int instance) -{ - dev->instance=instance; - init_MUTEX(&dev->device_lock_sem); - dev->control_reg=0; - dev->busy=0; - return 0; -} - -int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance) -{ - if(dev == NULL) { - printk(KERN_ERR "VFC: Bogus pointer passed\n"); - return -ENOMEM; - } - printk("Initializing vfc%d\n",instance); - dev->regs = NULL; - dev->regs = (volatile struct vfc_regs __iomem *) - sbus_ioremap(&sdev->resource[0], 0, - sizeof(struct vfc_regs), vfcstr); - dev->which_io = sdev->reg_addrs[0].which_io; - dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr; - if (dev->regs == NULL) - return -EIO; - - printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n", - instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs); - - if (init_vfc_devstruct(dev, instance)) - return -EINVAL; - if (init_vfc_hw(dev)) - return -EIO; - return 0; -} - - -struct vfc_dev *vfc_get_dev_ptr(int instance) -{ - return vfc_dev_lst[instance]; -} - -static DEFINE_SPINLOCK(vfc_dev_lock); - -static int vfc_open(struct inode *inode, struct file *file) -{ - struct vfc_dev *dev; - - spin_lock(&vfc_dev_lock); - dev = vfc_get_dev_ptr(iminor(inode)); - if (dev == NULL) { - spin_unlock(&vfc_dev_lock); - return -ENODEV; - } - if (dev->busy) { - spin_unlock(&vfc_dev_lock); - return -EBUSY; - } - - dev->busy = 1; - spin_unlock(&vfc_dev_lock); - - vfc_lock_device(dev); - - vfc_csr_init(dev); - vfc_pcf8584_init(dev); - vfc_init_i2c_bus(dev); - vfc_saa9051_init(dev); - vfc_memptr_reset(dev); - vfc_captstat_reset(dev); - - vfc_unlock_device(dev); - return 0; -} - -static int vfc_release(struct inode *inode,struct file *file) -{ - struct vfc_dev *dev; - - spin_lock(&vfc_dev_lock); - dev = vfc_get_dev_ptr(iminor(inode)); - if (!dev || !dev->busy) { - spin_unlock(&vfc_dev_lock); - return -EINVAL; - } - dev->busy = 0; - spin_unlock(&vfc_dev_lock); - return 0; -} - -static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp) -{ - struct vfc_debug_inout inout; - unsigned char *buffer; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - switch(cmd) { - case VFC_I2C_SEND: - if(copy_from_user(&inout, argp, sizeof(inout))) - return -EFAULT; - - buffer = kmalloc(inout.len, GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; - - if(copy_from_user(buffer, inout.buffer, inout.len)) { - kfree(buffer); - return -EFAULT; - } - - - vfc_lock_device(dev); - inout.ret= - vfc_i2c_sendbuf(dev,inout.addr & 0xff, - buffer,inout.len); - - if (copy_to_user(argp,&inout,sizeof(inout))) { - kfree(buffer); - return -EFAULT; - } - vfc_unlock_device(dev); - - break; - case VFC_I2C_RECV: - if (copy_from_user(&inout, argp, sizeof(inout))) - return -EFAULT; - - buffer = kmalloc(inout.len, GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; - - memset(buffer,0,inout.len); - vfc_lock_device(dev); - inout.ret= - vfc_i2c_recvbuf(dev,inout.addr & 0xff - ,buffer,inout.len); - vfc_unlock_device(dev); - - if (copy_to_user(inout.buffer, buffer, inout.len)) { - kfree(buffer); - return -EFAULT; - } - if (copy_to_user(argp,&inout,sizeof(inout))) { - kfree(buffer); - return -EFAULT; - } - kfree(buffer); - break; - default: - return -EINVAL; - }; - - return 0; -} - -int vfc_capture_start(struct vfc_dev *dev) -{ - vfc_captstat_reset(dev); - dev->control_reg = sbus_readl(&dev->regs->control); - if((dev->control_reg & VFC_STATUS_CAPTURE)) { - printk(KERN_ERR "vfc%d: vfc capture status not reset\n", - dev->instance); - return -EIO; - } - - vfc_lock_device(dev); - dev->control_reg &= ~VFC_CONTROL_CAPTURE; - sbus_writel(dev->control_reg, &dev->regs->control); - dev->control_reg |= VFC_CONTROL_CAPTURE; - sbus_writel(dev->control_reg, &dev->regs->control); - dev->control_reg &= ~VFC_CONTROL_CAPTURE; - sbus_writel(dev->control_reg, &dev->regs->control); - vfc_unlock_device(dev); - - return 0; -} - -int vfc_capture_poll(struct vfc_dev *dev) -{ - int timeout = 1000; - - while (!timeout--) { - if (sbus_readl(&dev->regs->control) & VFC_STATUS_CAPTURE) - break; - vfc_i2c_delay_no_busy(dev, 100); - } - if(!timeout) { - printk(KERN_WARNING "vfc%d: capture timed out\n", - dev->instance); - return -ETIMEDOUT; - } - return 0; -} - - - -static int vfc_set_control_ioctl(struct inode *inode, struct file *file, - struct vfc_dev *dev, unsigned long arg) -{ - int setcmd, ret = 0; - - if (copy_from_user(&setcmd,(void __user *)arg,sizeof(unsigned int))) - return -EFAULT; - - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", - dev->instance,setcmd)); - - switch(setcmd) { - case MEMPRST: - vfc_lock_device(dev); - vfc_memptr_reset(dev); - vfc_unlock_device(dev); - ret=0; - break; - case CAPTRCMD: - vfc_capture_start(dev); - vfc_capture_poll(dev); - break; - case DIAGMODE: - if(capable(CAP_SYS_ADMIN)) { - vfc_lock_device(dev); - dev->control_reg |= VFC_CONTROL_DIAGMODE; - sbus_writel(dev->control_reg, &dev->regs->control); - vfc_unlock_device(dev); - ret = 0; - } else { - ret = -EPERM; - } - break; - case NORMMODE: - vfc_lock_device(dev); - dev->control_reg &= ~VFC_CONTROL_DIAGMODE; - sbus_writel(dev->control_reg, &dev->regs->control); - vfc_unlock_device(dev); - ret = 0; - break; - case CAPTRSTR: - vfc_capture_start(dev); - ret = 0; - break; - case CAPTRWAIT: - vfc_capture_poll(dev); - ret = 0; - break; - default: - ret = -EINVAL; - break; - }; - - return ret; -} - - -int vfc_port_change_ioctl(struct inode *inode, struct file *file, - struct vfc_dev *dev, unsigned long arg) -{ - int ret = 0; - int cmd; - - if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " - "vfc_port_change_ioctl\n", - dev->instance)); - return -EFAULT; - } - - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", - dev->instance, cmd)); - - switch(cmd) { - case 1: - case 2: - VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x72; - VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x52; - VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0x36; - VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0x18; - VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BP2; - VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_CT | VFC_SAA9051_SS3; - VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0x3e; - break; - case 3: - VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x3a; - VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17; - VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa; - VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde; - VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = - VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2; - VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC; - VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0; - VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= - ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); - break; - default: - ret = -EINVAL; - return ret; - break; - } - - switch(cmd) { - case 1: - VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= - (VFC_SAA9051_SS0 | VFC_SAA9051_SS1); - break; - case 2: - VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= - ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); - VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0; - break; - case 3: - break; - default: - ret = -EINVAL; - return ret; - break; - } - VFC_SAA9051_SA(dev,VFC_SAA9051_C3) &= ~(VFC_SAA9051_SS2); - ret=vfc_update_saa9051(dev); - udelay(500); - VFC_SAA9051_SA(dev,VFC_SAA9051_C3) |= (VFC_SAA9051_SS2); - ret=vfc_update_saa9051(dev); - return ret; -} - -int vfc_set_video_ioctl(struct inode *inode, struct file *file, - struct vfc_dev *dev, unsigned long arg) -{ - int ret = 0; - int cmd; - - if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " - "vfc_set_video_ioctl\n", - dev->instance)); - return ret; - } - - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", - dev->instance, cmd)); - switch(cmd) { - case STD_NTSC: - VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT; - VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN | - VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS; - ret = vfc_update_saa9051(dev); - break; - case STD_PAL: - VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN | - VFC_SAA9051_CCFR1 | - VFC_SAA9051_CCFR0 | - VFC_SAA9051_FS); - VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT; - ret = vfc_update_saa9051(dev); - break; - - case COLOR_ON: - VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO; - VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &= - ~(VFC_SAA9051_BY | VFC_SAA9051_PF); - ret = vfc_update_saa9051(dev); - break; - case MONO: - VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO); - VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |= - (VFC_SAA9051_BY | VFC_SAA9051_PF); - ret = vfc_update_saa9051(dev); - break; - default: - ret = -EINVAL; - break; - }; - - return ret; -} - -int vfc_get_video_ioctl(struct inode *inode, struct file *file, - struct vfc_dev *dev, unsigned long arg) -{ - int ret = 0; - unsigned int status = NO_LOCK; - unsigned char buf[1]; - - if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) { - printk(KERN_ERR "vfc%d: Unable to get status\n", - dev->instance); - return -EIO; - } - - if(buf[0] & VFC_SAA9051_HLOCK) { - status = NO_LOCK; - } else if(buf[0] & VFC_SAA9051_FD) { - if(buf[0] & VFC_SAA9051_CD) - status = NTSC_COLOR; - else - status = NTSC_NOCOLOR; - } else { - if(buf[0] & VFC_SAA9051_CD) - status = PAL_COLOR; - else - status = PAL_NOCOLOR; - } - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; " - "buf[0]=%x\n", dev->instance, status, buf[0])); - - if (copy_to_user((void __user *)arg,&status,sizeof(unsigned int))) { - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " - "vfc_get_video_ioctl\n", - dev->instance)); - return ret; - } - return ret; -} - -static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - int ret = 0; - unsigned int tmp; - struct vfc_dev *dev; - void __user *argp = (void __user *)arg; - - dev = vfc_get_dev_ptr(iminor(inode)); - if(dev == NULL) - return -ENODEV; - - switch(cmd & 0x0000ffff) { - case VFCGCTRL: -#if 0 - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n", dev->instance)); -#endif - tmp = sbus_readl(&dev->regs->control); - if(copy_to_user(argp, &tmp, sizeof(unsigned int))) { - ret = -EFAULT; - break; - } - ret = 0; - break; - case VFCSCTRL: - ret = vfc_set_control_ioctl(inode, file, dev, arg); - break; - case VFCGVID: - ret = vfc_get_video_ioctl(inode, file, dev, arg); - break; - case VFCSVID: - ret = vfc_set_video_ioctl(inode, file, dev, arg); - break; - case VFCHUE: - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance)); - if(copy_from_user(&tmp,argp,sizeof(unsigned int))) { - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " - "to IOCTL(VFCHUE)", dev->instance)); - ret = -EFAULT; - } else { - VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp; - vfc_update_saa9051(dev); - ret = 0; - } - break; - case VFCPORTCHG: - ret = vfc_port_change_ioctl(inode, file, dev, arg); - break; - case VFCRDINFO: - ret = -EINVAL; - VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance)); - break; - default: - ret = vfc_debug(vfc_get_dev_ptr(iminor(inode)), cmd, argp); - break; - }; - - return ret; -} - -static int vfc_mmap(struct file *file, struct vm_area_struct *vma) -{ - unsigned int map_size, ret, map_offset; - struct vfc_dev *dev; - - dev = vfc_get_dev_ptr(iminor(file->f_dentry->d_inode)); - if(dev == NULL) - return -ENODEV; - - map_size = vma->vm_end - vma->vm_start; - if(map_size > sizeof(struct vfc_regs)) - map_size = sizeof(struct vfc_regs); - - vma->vm_flags |= - (VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE); - map_offset = (unsigned int) (long)dev->phys_regs; - ret = io_remap_pfn_range(vma, vma->vm_start, - MK_IOSPACE_PFN(dev->which_io, - map_offset >> PAGE_SHIFT), - map_size, vma->vm_page_prot); - - if(ret) - return -EAGAIN; - - return 0; -} - - -static struct file_operations vfc_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = vfc_ioctl, - .mmap = vfc_mmap, - .open = vfc_open, - .release = vfc_release, -}; - -static int vfc_probe(void) -{ - struct sbus_bus *sbus; - struct sbus_dev *sdev = NULL; - int ret; - int instance = 0, cards = 0; - - for_all_sbusdev(sdev, sbus) { - if (strcmp(sdev->prom_name, "vfc") == 0) { - cards++; - continue; - } - } - - if (!cards) - return -ENODEV; - - vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) * - (cards+1), - GFP_KERNEL); - if (vfc_dev_lst == NULL) - return -ENOMEM; - memset(vfc_dev_lst, 0, sizeof(struct vfc_dev *) * (cards + 1)); - vfc_dev_lst[cards] = NULL; - - ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops); - if(ret) { - printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR); - kfree(vfc_dev_lst); - return -EIO; - } - instance = 0; - for_all_sbusdev(sdev, sbus) { - if (strcmp(sdev->prom_name, "vfc") == 0) { - vfc_dev_lst[instance]=(struct vfc_dev *) - kmalloc(sizeof(struct vfc_dev), GFP_KERNEL); - if (vfc_dev_lst[instance] == NULL) - return -ENOMEM; - ret = init_vfc_device(sdev, - vfc_dev_lst[instance], - instance); - if(ret) { - printk(KERN_ERR "Unable to initialize" - " vfc%d device\n", - instance); - } else { - } - - instance++; - continue; - } - } - - return 0; -} - -#ifdef MODULE -int init_module(void) -#else -int vfc_init(void) -#endif -{ - return vfc_probe(); -} - -#ifdef MODULE -static void deinit_vfc_device(struct vfc_dev *dev) -{ - if(dev == NULL) - return; - sbus_iounmap(dev->regs, sizeof(struct vfc_regs)); - kfree(dev); -} - -void cleanup_module(void) -{ - struct vfc_dev **devp; - - unregister_chrdev(VFC_MAJOR,vfcstr); - - for (devp = vfc_dev_lst; *devp; devp++) - deinit_vfc_device(*devp); - - kfree(vfc_dev_lst); - return; -} -#endif - -MODULE_LICENSE("GPL"); - diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c deleted file mode 100644 index ceec30648f4..00000000000 --- a/drivers/sbus/char/vfc_i2c.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * drivers/sbus/char/vfc_i2c.c - * - * Driver for the Videopix Frame Grabber. - * - * Functions that support the Phillips i2c(I squared C) bus on the vfc - * Documentation for the Phillips I2C bus can be found on the - * phillips home page - * - * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) - * - */ - -/* NOTE: It seems to me that the documentation regarding the -pcd8584t/pcf8584 does not show the correct way to address the i2c bus. -Based on the information on the I2C bus itself and the remainder of -the Phillips docs the following algorithims apper to be correct. I am -fairly certain that the flowcharts in the phillips docs are wrong. */ - - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/wait.h> -#include <linux/delay.h> -#include <asm/openprom.h> -#include <asm/oplib.h> -#include <asm/io.h> -#include <asm/system.h> -#include <asm/sbus.h> - -#if 0 -#define VFC_I2C_DEBUG -#endif - -#include "vfc.h" -#include "vfc_i2c.h" - -#define WRITE_S1(__val) \ - sbus_writel(__val, &dev->regs->i2c_s1) -#define WRITE_REG(__val) \ - sbus_writel(__val, &dev->regs->i2c_reg) - -#define VFC_I2C_READ (0x1) -#define VFC_I2C_WRITE (0x0) - -/****** - The i2c bus controller chip on the VFC is a pcd8584t, but - phillips claims it doesn't exist. As far as I can tell it is - identical to the PCF8584 so I treat it like it is the pcf8584. - - NOTE: The pcf8584 only cares - about the msb of the word you feed it -*****/ - -int vfc_pcf8584_init(struct vfc_dev *dev) -{ - /* This will also choose register S0_OWN so we can set it. */ - WRITE_S1(RESET); - - /* The pcf8584 shifts this value left one bit and uses - * it as its i2c bus address. - */ - WRITE_REG(0x55000000); - - /* This will set the i2c bus at the same speed sun uses, - * and set another magic bit. - */ - WRITE_S1(SELECT(S2)); - WRITE_REG(0x14000000); - - /* Enable the serial port, idle the i2c bus and set - * the data reg to s0. - */ - WRITE_S1(CLEAR_I2C_BUS); - udelay(100); - return 0; -} - -void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) -{ - schedule_timeout_uninterruptible(usecs_to_jiffies(usecs)); -} - -void inline vfc_i2c_delay(struct vfc_dev *dev) -{ - vfc_i2c_delay_no_busy(dev, 100); -} - -int vfc_init_i2c_bus(struct vfc_dev *dev) -{ - WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK); - vfc_i2c_reset_bus(dev); - return 0; -} - -int vfc_i2c_reset_bus(struct vfc_dev *dev) -{ - VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", - dev->instance)); - if(dev == NULL) - return -EINVAL; - if(dev->regs == NULL) - return -EINVAL; - WRITE_S1(SEND_I2C_STOP); - WRITE_S1(SEND_I2C_STOP | ACK); - vfc_i2c_delay(dev); - WRITE_S1(CLEAR_I2C_BUS); - VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", - dev->instance, - sbus_readl(&dev->regs->i2c_s1))); - return 0; -} - -int vfc_i2c_wait_for_bus(struct vfc_dev *dev) -{ - int timeout = 1000; - - while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) { - if(!(timeout--)) - return -ETIMEDOUT; - vfc_i2c_delay(dev); - } - return 0; -} - -int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack) -{ - int timeout = 1000; - int s1; - - while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) { - if (!(timeout--)) - return -ETIMEDOUT; - vfc_i2c_delay(dev); - } - if (ack == VFC_I2C_ACK_CHECK) { - if(s1 & LRB) - return -EIO; - } - return 0; -} - -#define SHIFT(a) ((a) << 24) -int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode) -{ - int ret, raddr; -#if 1 - WRITE_S1(SEND_I2C_STOP | ACK); - WRITE_S1(SELECT(S0) | ENABLE_SERIAL); - vfc_i2c_delay(dev); -#endif - - switch(mode) { - case VFC_I2C_READ: - raddr = SHIFT(((unsigned int)addr | 0x1)); - WRITE_REG(raddr); - VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", - dev->instance, addr | 0x1)); - break; - case VFC_I2C_WRITE: - raddr = SHIFT((unsigned int)addr & ~0x1); - WRITE_REG(raddr); - VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", - dev->instance, addr & ~0x1)); - break; - default: - return -EINVAL; - }; - - WRITE_S1(SEND_I2C_START); - vfc_i2c_delay(dev); - ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait - for the - i2c send - to finish - here but - Sun - doesn't, - hmm */ - if (ret) { - printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", - dev->instance); - return ret; - } else if (mode == VFC_I2C_READ) { - if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { - printk(KERN_WARNING - "vfc%d: returned slave address " - "mismatch(%x,%x)\n", - dev->instance, raddr, ret); - } - } - return 0; -} - -int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) -{ - int ret; - u32 val = SHIFT((unsigned int)*byte); - - WRITE_REG(val); - - ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); - switch(ret) { - case -ETIMEDOUT: - printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n", - dev->instance); - break; - case -EIO: - ret = XMIT_LAST_BYTE; - break; - default: - break; - }; - - return ret; -} - -int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last) -{ - int ret; - - if (last) { - WRITE_REG(NEGATIVE_ACK); - VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", - dev->instance)); - } else { - WRITE_S1(ACK); - } - - ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); - if(ret) { - printk(KERN_ERR "vfc%d: " - "VFC recv byte timed out\n", - dev->instance); - } - *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; - return ret; -} - -int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, - char *buf, int count) -{ - int ret, last; - - if(!(count && buf && dev && dev->regs) ) - return -EINVAL; - - if ((ret = vfc_i2c_wait_for_bus(dev))) { - printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); - return ret; - } - - if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) { - WRITE_S1(SEND_I2C_STOP); - vfc_i2c_delay(dev); - return ret; - } - - last = 0; - while (count--) { - if (!count) - last = 1; - if ((ret = vfc_i2c_recv_byte(dev, buf, last))) { - printk(KERN_ERR "vfc%d: " - "VFC error while receiving byte\n", - dev->instance); - WRITE_S1(SEND_I2C_STOP); - ret = -EINVAL; - } - buf++; - } - WRITE_S1(SEND_I2C_STOP | ACK); - vfc_i2c_delay(dev); - return ret; -} - -int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, - char *buf, int count) -{ - int ret; - - if (!(buf && dev && dev->regs)) - return -EINVAL; - - if ((ret = vfc_i2c_wait_for_bus(dev))) { - printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); - return ret; - } - - if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { - WRITE_S1(SEND_I2C_STOP); - vfc_i2c_delay(dev); - return ret; - } - - while(count--) { - ret = vfc_i2c_xmit_byte(dev, buf); - switch(ret) { - case XMIT_LAST_BYTE: - VFC_I2C_DEBUG_PRINTK(("vfc%d: " - "Receiver ended transmission with " - " %d bytes remaining\n", - dev->instance, count)); - ret = 0; - goto done; - break; - case 0: - break; - default: - printk(KERN_ERR "vfc%d: " - "VFC error while sending byte\n", dev->instance); - break; - }; - - buf++; - } -done: - WRITE_S1(SEND_I2C_STOP | ACK); - vfc_i2c_delay(dev); - return ret; -} - - - - - - - - - diff --git a/drivers/sbus/char/vfc_i2c.h b/drivers/sbus/char/vfc_i2c.h deleted file mode 100644 index a2e6973209d..00000000000 --- a/drivers/sbus/char/vfc_i2c.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _LINUX_VFC_I2C_H_ -#define _LINUX_VFC_I2C_H_ - -/* control bits */ -#define PIN (0x80000000) -#define ESO (0x40000000) -#define ES1 (0x20000000) -#define ES2 (0x10000000) -#define ENI (0x08000000) -#define STA (0x04000000) -#define STO (0x02000000) -#define ACK (0x01000000) - -/* status bits */ -#define STS (0x20000000) -#define BER (0x10000000) -#define LRB (0x08000000) -#define AAS (0x04000000) -#define LAB (0x02000000) -#define BB (0x01000000) - -#define SEND_I2C_START (PIN | ESO | STA) -#define SEND_I2C_STOP (PIN | ESO | STO) -#define CLEAR_I2C_BUS (PIN | ESO | ACK) -#define NEGATIVE_ACK ((ESO) & ~ACK) - -#define SELECT(a) (a) -#define S0 (PIN | ESO | ES1) -#define S0_OWN (PIN) -#define S2 (PIN | ES1) -#define S3 (PIN | ES2) - -#define ENABLE_SERIAL (PIN | ESO) -#define DISABLE_SERIAL (PIN) -#define RESET (PIN) - -#define XMIT_LAST_BYTE (1) -#define VFC_I2C_ACK_CHECK (1) -#define VFC_I2C_NO_ACK_CHECK (0) - -#endif /* _LINUX_VFC_I2C_H_ */ - - - diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c deleted file mode 100644 index 57e1526746a..00000000000 --- a/drivers/sbus/dvma.c +++ /dev/null @@ -1,136 +0,0 @@ -/* dvma.c: Routines that are used to access DMA on the Sparc SBus. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/delay.h> - -#include <asm/oplib.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/sbus.h> - -struct sbus_dma *dma_chain; - -void __init init_one_dvma(struct sbus_dma *dma, int num_dma) -{ - printk("dma%d: ", num_dma); - - dma->next = NULL; - dma->running = 0; /* No transfers going on as of yet */ - dma->allocated = 0; /* No one has allocated us yet */ - switch(sbus_readl(dma->regs + DMA_CSR)&DMA_DEVICE_ID) { - case DMA_VERS0: - dma->revision = dvmarev0; - printk("Revision 0 "); - break; - case DMA_ESCV1: - dma->revision = dvmaesc1; - printk("ESC Revision 1 "); - break; - case DMA_VERS1: - dma->revision = dvmarev1; - printk("Revision 1 "); - break; - case DMA_VERS2: - dma->revision = dvmarev2; - printk("Revision 2 "); - break; - case DMA_VERHME: - dma->revision = dvmahme; - printk("HME DVMA gate array "); - break; - case DMA_VERSPLUS: - dma->revision = dvmarevplus; - printk("Revision 1 PLUS "); - break; - default: - printk("unknown dma version %08x", - sbus_readl(dma->regs + DMA_CSR) & DMA_DEVICE_ID); - dma->allocated = 1; - break; - } - printk("\n"); -} - -/* Probe this SBus DMA module(s) */ -void __init dvma_init(struct sbus_bus *sbus) -{ - struct sbus_dev *this_dev; - struct sbus_dma *dma; - struct sbus_dma *dchain; - static int num_dma = 0; - - for_each_sbusdev(this_dev, sbus) { - char *name = this_dev->prom_name; - int hme = 0; - - if(!strcmp(name, "SUNW,fas")) - hme = 1; - else if(strcmp(name, "dma") && - strcmp(name, "ledma") && - strcmp(name, "espdma")) - continue; - - /* Found one... */ - dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); - - dma->sdev = this_dev; - - /* Put at end of dma chain */ - dchain = dma_chain; - if(dchain) { - while(dchain->next) - dchain = dchain->next; - dchain->next = dma; - } else { - /* We're the first in line */ - dma_chain = dma; - } - - dma->regs = sbus_ioremap(&dma->sdev->resource[0], 0, - dma->sdev->resource[0].end - dma->sdev->resource[0].start + 1, - "dma"); - - dma->node = dma->sdev->prom_node; - - init_one_dvma(dma, num_dma++); - } -} - -#ifdef CONFIG_SUN4 - -#include <asm/sun4paddr.h> - -void __init sun4_dvma_init(void) -{ - struct sbus_dma *dma; - struct resource r; - - if(sun4_dma_physaddr) { - dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); - - /* No SBUS */ - dma->sdev = NULL; - - /* Only one DMA device */ - dma_chain = dma; - - memset(&r, 0, sizeof(r)); - r.start = sun4_dma_physaddr; - dma->regs = sbus_ioremap(&r, 0, PAGE_SIZE, "dma"); - - /* No prom node */ - dma->node = 0x0; - - init_one_dvma(dma, 0); - } else { - dma_chain = NULL; - } -} - -#endif diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c deleted file mode 100644 index 935952ef88f..00000000000 --- a/drivers/sbus/sbus.c +++ /dev/null @@ -1,287 +0,0 @@ -/* sbus.c: SBus support routines. - * - * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/pci.h> - -#include <asm/system.h> -#include <asm/sbus.h> -#include <asm/dma.h> -#include <asm/oplib.h> -#include <asm/prom.h> -#include <asm/of_device.h> -#include <asm/bpp.h> -#include <asm/irq.h> - -struct sbus_bus *sbus_root; - -static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) -{ - unsigned long base; - void *pval; - int len; - - sdev->prom_node = dp->node; - strcpy(sdev->prom_name, dp->name); - - pval = of_get_property(dp, "reg", &len); - sdev->num_registers = 0; - if (pval) { - memcpy(sdev->reg_addrs, pval, len); - - sdev->num_registers = - len / sizeof(struct linux_prom_registers); - - base = (unsigned long) sdev->reg_addrs[0].phys_addr; - - /* Compute the slot number. */ - if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) - sdev->slot = sbus_dev_slot(base); - else - sdev->slot = sdev->reg_addrs[0].which_io; - } - - pval = of_get_property(dp, "ranges", &len); - sdev->num_device_ranges = 0; - if (pval) { - memcpy(sdev->device_ranges, pval, len); - sdev->num_device_ranges = - len / sizeof(struct linux_prom_ranges); - } - - sbus_fill_device_irq(sdev); - - sdev->ofdev.node = dp; - if (sdev->parent) - sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; - else - sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; - sdev->ofdev.dev.bus = &sbus_bus_type; - strcpy(sdev->ofdev.dev.bus_id, dp->path_component_name); - - if (of_device_register(&sdev->ofdev) != 0) - printk(KERN_DEBUG "sbus: device registration error for %s!\n", - sdev->ofdev.dev.bus_id); -} - -static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) -{ - void *pval; - int len; - - pval = of_get_property(dp, "ranges", &len); - sbus->num_sbus_ranges = 0; - if (pval) { - memcpy(sbus->sbus_ranges, pval, len); - sbus->num_sbus_ranges = - len / sizeof(struct linux_prom_ranges); - - sbus_arch_bus_ranges_init(dp->parent, sbus); - } -} - -static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, - int num_ranges, - struct linux_prom_registers *regs, - int num_regs) -{ - if (num_ranges) { - int regnum; - - for (regnum = 0; regnum < num_regs; regnum++) { - int rngnum; - - for (rngnum = 0; rngnum < num_ranges; rngnum++) { - if (regs[regnum].which_io == ranges[rngnum].ot_child_space) - break; - } - if (rngnum == num_ranges) { - /* We used to flag this as an error. Actually - * some devices do not report the regs as we expect. - * For example, see SUNW,pln device. In that case - * the reg property is in a format internal to that - * node, ie. it is not in the SBUS register space - * per se. -DaveM - */ - return; - } - regs[regnum].which_io = ranges[rngnum].ot_parent_space; - regs[regnum].phys_addr -= ranges[rngnum].ot_child_base; - regs[regnum].phys_addr += ranges[rngnum].ot_parent_base; - } - } -} - -static void __init __fixup_regs_sdev(struct sbus_dev *sdev) -{ - if (sdev->num_registers != 0) { - struct sbus_dev *parent = sdev->parent; - int i; - - while (parent != NULL) { - __apply_ranges_to_regs(parent->device_ranges, - parent->num_device_ranges, - sdev->reg_addrs, - sdev->num_registers); - - parent = parent->parent; - } - - __apply_ranges_to_regs(sdev->bus->sbus_ranges, - sdev->bus->num_sbus_ranges, - sdev->reg_addrs, - sdev->num_registers); - - for (i = 0; i < sdev->num_registers; i++) { - struct resource *res = &sdev->resource[i]; - - res->start = sdev->reg_addrs[i].phys_addr; - res->end = (res->start + - (unsigned long)sdev->reg_addrs[i].reg_size - 1UL); - res->flags = IORESOURCE_IO | - (sdev->reg_addrs[i].which_io & 0xff); - } - } -} - -static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev) -{ - struct sbus_dev *sdev; - - for (sdev = first_sdev; sdev; sdev = sdev->next) { - if (sdev->child) - sbus_fixup_all_regs(sdev->child); - __fixup_regs_sdev(sdev); - } -} - -/* We preserve the "probe order" of these bus and device lists to give - * the same ordering as the old code. - */ -static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root) -{ - while (*root) - root = &(*root)->next; - *root = sbus; - sbus->next = NULL; -} - -static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root) -{ - while (*root) - root = &(*root)->next; - *root = sdev; - sdev->next = NULL; -} - -static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus) -{ - dp = dp->child; - while (dp) { - struct sbus_dev *sdev; - - sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - if (sdev) { - sdev_insert(sdev, &parent->child); - - sdev->bus = sbus; - sdev->parent = parent; - - fill_sbus_device(dp, sdev); - - walk_children(dp, sdev, sbus); - } - dp = dp->sibling; - } -} - -static void __init build_one_sbus(struct device_node *dp, int num_sbus) -{ - struct sbus_bus *sbus; - unsigned int sbus_clock; - struct device_node *dev_dp; - - sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC); - if (!sbus) - return; - - sbus_insert(sbus, &sbus_root); - sbus->prom_node = dp->node; - - sbus_setup_iommu(sbus, dp); - - printk("sbus%d: ", num_sbus); - - sbus_clock = of_getintprop_default(dp, "clock-frequency", - (25*1000*1000)); - sbus->clock_freq = sbus_clock; - - printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), - (int) (((sbus_clock/1000)%1000 != 0) ? - (((sbus_clock/1000)%1000) + 1000) : 0)); - - strcpy(sbus->prom_name, dp->name); - - sbus_setup_arch_props(sbus, dp); - - sbus_bus_ranges_init(dp, sbus); - - sbus->ofdev.node = dp; - sbus->ofdev.dev.parent = NULL; - sbus->ofdev.dev.bus = &sbus_bus_type; - sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus); - - if (of_device_register(&sbus->ofdev) != 0) - printk(KERN_DEBUG "sbus: device registration error for %s!\n", - sbus->ofdev.dev.bus_id); - - dev_dp = dp->child; - while (dev_dp) { - struct sbus_dev *sdev; - - sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); - if (sdev) { - sdev_insert(sdev, &sbus->devices); - - sdev->bus = sbus; - sdev->parent = NULL; - fill_sbus_device(dev_dp, sdev); - - walk_children(dev_dp, sdev, sbus); - } - dev_dp = dev_dp->sibling; - } - - sbus_fixup_all_regs(sbus->devices); - - dvma_init(sbus); -} - -static int __init sbus_init(void) -{ - struct device_node *dp; - const char *sbus_name = "sbus"; - int num_sbus = 0; - - if (sbus_arch_preinit()) - return 0; - - if (sparc_cpu_model == sun4d) - sbus_name = "sbi"; - - for_each_node_by_name(dp, sbus_name) { - build_one_sbus(dp, num_sbus); - num_sbus++; - - } - - sbus_arch_postinit(); - - return 0; -} - -subsys_initcall(sbus_init); |
