From d1d4b10cdafb8dd4044a3b67b05f759047612fdc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 23 May 2010 16:39:09 +0000 Subject: serial: sh-sci: fix handling of SCIFB sh-mobile ports SCIFB ports have a slightly different register layout and a different FIFO size from SCIFA ports, in DMA mode they have to be treated just like SCIFA. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 42 ++++++++++++++++++++++++++++++++++-------- drivers/serial/sh-sci.h | 29 +++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 14 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 4f73fb756745..aaef223df676 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -346,6 +346,27 @@ static int scif_rxfill(struct uart_port *port) return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; } } +#elif defined(CONFIG_ARCH_SH7372) +static int scif_txfill(struct uart_port *port) +{ + if (port->type == PORT_SCIFA) + return sci_in(port, SCFDR) >> 8; + else + return sci_in(port, SCTFDR); +} + +static int scif_txroom(struct uart_port *port) +{ + return port->fifosize - scif_txfill(port); +} + +static int scif_rxfill(struct uart_port *port) +{ + if (port->type == PORT_SCIFA) + return sci_in(port, SCFDR) & SCIF_RFDC_MASK; + else + return sci_in(port, SCRFDR); +} #else static int scif_txfill(struct uart_port *port) { @@ -683,7 +704,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) u16 ssr = sci_in(port, SCxSR); /* Disable future Rx interrupts */ - if (port->type == PORT_SCIFA) { + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { disable_irq_nosync(irq); scr |= 0x4000; } else { @@ -928,7 +949,7 @@ static void sci_dma_tx_complete(void *arg) if (!uart_circ_empty(xmit)) { schedule_work(&s->work_tx); - } else if (port->type == PORT_SCIFA) { + } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { u16 ctrl = sci_in(port, SCSCR); sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); } @@ -1183,7 +1204,7 @@ static void sci_start_tx(struct uart_port *port) unsigned short ctrl; #ifdef CONFIG_SERIAL_SH_SCI_DMA - if (port->type == PORT_SCIFA) { + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { u16 new, scr = sci_in(port, SCSCR); if (s->chan_tx) new = scr | 0x8000; @@ -1196,7 +1217,7 @@ static void sci_start_tx(struct uart_port *port) s->cookie_tx < 0) schedule_work(&s->work_tx); #endif - if (!s->chan_tx || port->type == PORT_SCIFA) { + if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); @@ -1209,7 +1230,7 @@ static void sci_stop_tx(struct uart_port *port) /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); - if (port->type == PORT_SCIFA) + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x8000; ctrl &= ~SCI_CTRL_FLAGS_TIE; sci_out(port, SCSCR, ctrl); @@ -1221,7 +1242,7 @@ static void sci_start_rx(struct uart_port *port) /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ ctrl |= sci_in(port, SCSCR); - if (port->type == PORT_SCIFA) + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x4000; sci_out(port, SCSCR, ctrl); } @@ -1232,7 +1253,7 @@ static void sci_stop_rx(struct uart_port *port) /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); - if (port->type == PORT_SCIFA) + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) ctrl &= ~0x4000; ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); sci_out(port, SCSCR, ctrl); @@ -1270,7 +1291,7 @@ static void rx_timer_fn(unsigned long arg) struct uart_port *port = &s->port; u16 scr = sci_in(port, SCSCR); - if (port->type == PORT_SCIFA) { + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { scr &= ~0x4000; enable_irq(s->irqs[1]); } @@ -1523,6 +1544,8 @@ static const char *sci_type(struct uart_port *port) return "scif"; case PORT_SCIFA: return "scifa"; + case PORT_SCIFB: + return "scifb"; } return NULL; @@ -1611,6 +1634,9 @@ static int __devinit sci_init_single(struct platform_device *dev, port->line = index; switch (p->type) { + case PORT_SCIFB: + port->fifosize = 256; + break; case PORT_SCIFA: port->fifosize = 64; break; diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f70c49f915fa..9b52f77a9305 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -322,7 +322,7 @@ #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ static inline unsigned int sci_##name##_in(struct uart_port *port) \ { \ - if (port->type == PORT_SCIF) { \ + if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \ SCI_IN(scif_size, scif_offset) \ } else { /* PORT_SCI or PORT_SCIFA */ \ SCI_IN(sci_size, sci_offset); \ @@ -330,7 +330,7 @@ } \ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ { \ - if (port->type == PORT_SCIF) { \ + if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \ SCI_OUT(scif_size, scif_offset, value) \ } else { /* PORT_SCI or PORT_SCIFA */ \ SCI_OUT(sci_size, sci_offset, value); \ @@ -384,8 +384,12 @@ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ defined(CONFIG_ARCH_SH7367) || \ - defined(CONFIG_ARCH_SH7377) || \ - defined(CONFIG_ARCH_SH7372) + defined(CONFIG_ARCH_SH7377) +#define SCIF_FNS(name, scif_offset, scif_size) \ + CPU_SCIF_FNS(name, scif_offset, scif_size) +#elif defined(CONFIG_ARCH_SH7372) +#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \ + CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) #define SCIF_FNS(name, scif_offset, scif_size) \ CPU_SCIF_FNS(name, scif_offset, scif_size) #else @@ -422,8 +426,7 @@ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ defined(CONFIG_ARCH_SH7367) || \ - defined(CONFIG_ARCH_SH7377) || \ - defined(CONFIG_ARCH_SH7372) + defined(CONFIG_ARCH_SH7377) SCIF_FNS(SCSMR, 0x00, 16) SCIF_FNS(SCBRR, 0x04, 8) @@ -436,6 +439,20 @@ SCIF_FNS(SCFDR, 0x1c, 16) SCIF_FNS(SCxTDR, 0x20, 8) SCIF_FNS(SCxRDR, 0x24, 8) SCIF_FNS(SCLSR, 0x00, 0) +#elif defined(CONFIG_ARCH_SH7372) +SCIF_FNS(SCSMR, 0x00, 16) +SCIF_FNS(SCBRR, 0x04, 8) +SCIF_FNS(SCSCR, 0x08, 16) +SCIF_FNS(SCTDSR, 0x0c, 16) +SCIF_FNS(SCFER, 0x10, 16) +SCIF_FNS(SCxSR, 0x14, 16) +SCIF_FNS(SCFCR, 0x18, 16) +SCIF_FNS(SCFDR, 0x1c, 16) +SCIF_FNS(SCTFDR, 0x38, 16) +SCIF_FNS(SCRFDR, 0x3c, 16) +SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8) +SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8) +SCIF_FNS(SCLSR, 0x00, 0) #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ defined(CONFIG_CPU_SUBTYPE_SH7724) SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) -- cgit v1.2.3 From 8b526ae4ddd7a62397d99856079b59eda5d09360 Mon Sep 17 00:00:00 2001 From: Jongpill Lee Date: Fri, 16 Jul 2010 10:19:41 +0900 Subject: ARM: SAMSUNG: serial: Add FRACVAL support for newer UART Add support for the FRACVAL register on the newer UART blocks which provides the same function as UDIVSLOT register but the FRACVAL is easier to implement. To support UDIVSLOT register, UDIVSLOT table search is necessary though supporting FRACVAL only needs the index value of UDIVSLOT table. Signed-off-by: Jongpill Lee Acked-by: Changhwan Youn Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/include/plat/regs-serial.h | 2 ++ drivers/serial/samsung.c | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/serial') diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h index a6eba8496b24..788837e99cb3 100644 --- a/arch/arm/plat-samsung/include/plat/regs-serial.h +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h @@ -259,6 +259,8 @@ struct s3c2410_uartcfg { unsigned short flags; upf_t uart_flags; /* default uart flags */ + unsigned int has_fracval; + unsigned long ucon; /* value of ucon for port */ unsigned long ulcon; /* value of ulcon for port */ unsigned long ufcon; /* value of ufcon for port */ diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index a9d6c5626a0a..b1156ba8ad14 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -705,8 +705,13 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, if (ourport->info->has_divslot) { unsigned int div = ourport->baudclk_rate / baud; - udivslot = udivslot_table[div & 15]; - dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); + if (cfg->has_fracval) { + udivslot = (div & 15); + dbg("fracval = %04x\n", udivslot); + } else { + udivslot = udivslot_table[div & 15]; + dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); + } } switch (termios->c_cflag & CSIZE) { -- cgit v1.2.3 From acfdc56d541517266eeeeca3a4e5baafaa01c2a1 Mon Sep 17 00:00:00 2001 From: Jongpill Lee Date: Fri, 16 Jul 2010 15:07:37 +0900 Subject: ARM: S5PV310: Add serial port support This patch adds UART serial port support for S5PV310. In the case of that serial device has just one clock source, driver can not control clock source. So add check function in get_clksrc and set_clksrc. Signed-off-by: Jongpill Lee Acked-by: Changhwan Youn Signed-off-by: Kukjin Kim --- drivers/serial/Kconfig | 4 ++-- drivers/serial/s5pv210.c | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 8b23165bc5dc..aa220108cece 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -544,8 +544,8 @@ config SERIAL_S3C6400 config SERIAL_S5PV210 tristate "Samsung S5PV210 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442) - select SERIAL_SAMSUNG_UARTS_4 if CPU_S5PV210 + depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_S5PV310) + select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_S5PV310) default y help Serial port support for Samsung's S5P Family of SoC's diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c index 4a789e5361a4..6ebccd70a707 100644 --- a/drivers/serial/s5pv210.c +++ b/drivers/serial/s5pv210.c @@ -28,8 +28,12 @@ static int s5pv210_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *clk) { + struct s3c2410_uartcfg *cfg = port->dev->platform_data; unsigned long ucon = rd_regl(port, S3C2410_UCON); + if ((cfg->clocks_size) == 1) + return 0; + if (strcmp(clk->name, "pclk") == 0) ucon &= ~S5PV210_UCON_CLKMASK; else if (strcmp(clk->name, "uclk1") == 0) @@ -47,10 +51,14 @@ static int s5pv210_serial_setsource(struct uart_port *port, static int s5pv210_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *clk) { + struct s3c2410_uartcfg *cfg = port->dev->platform_data; u32 ucon = rd_regl(port, S3C2410_UCON); clk->divisor = 1; + if ((cfg->clocks_size) == 1) + return 0; + switch (ucon & S5PV210_UCON_CLKMASK) { case S5PV210_UCON_PCLK: clk->name = "pclk"; -- cgit v1.2.3 From 2dc11581376829303b98eadb2de253bee065a56a Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 6 Aug 2010 09:25:50 -0600 Subject: of/device: Replace struct of_device with struct platform_device of_device is just an alias for platform_device, so remove it entirely. Also replace to_of_device() with to_platform_device() and update comment blocks. This patch was initially generated from the following semantic patch, and then edited by hand to pick up the bits that coccinelle didn't catch. @@ @@ -struct of_device +struct platform_device Signed-off-by: Grant Likely Reviewed-by: David S. Miller --- arch/powerpc/platforms/83xx/mpc837x_mds.c | 2 +- arch/powerpc/platforms/83xx/mpc837x_rdb.c | 2 +- arch/powerpc/sysdev/fsl_rio.c | 2 +- drivers/ata/pata_mpc52xx.c | 8 ++--- drivers/ata/pata_of_platform.c | 4 +-- drivers/ata/sata_fsl.c | 8 ++--- drivers/atm/fore200e.c | 26 ++++++++-------- drivers/block/xsysace.c | 4 +-- drivers/char/hw_random/n2-drv.c | 4 +-- drivers/char/hw_random/n2rng.h | 2 +- drivers/char/hw_random/pasemi-rng.c | 4 +-- drivers/char/ipmi/ipmi_si_intf.c | 4 +-- drivers/char/rtc.c | 2 +- drivers/char/xilinx_hwicap/xilinx_hwicap.c | 4 +-- drivers/crypto/amcc/crypto4xx_core.c | 4 +-- drivers/crypto/amcc/crypto4xx_core.h | 2 +- drivers/crypto/n2_core.c | 22 +++++++------- drivers/crypto/talitos.c | 6 ++-- drivers/dma/fsldma.c | 4 +-- drivers/dma/mpc512x_dma.c | 4 +-- drivers/dma/ppc4xx/adma.c | 8 ++--- drivers/edac/mpc85xx_edac.c | 12 ++++---- drivers/edac/ppc4xx_edac.c | 12 ++++---- drivers/hwmon/ams/ams.h | 2 +- drivers/hwmon/ultra45_env.c | 4 +-- drivers/i2c/busses/i2c-cpm.c | 8 ++--- drivers/i2c/busses/i2c-ibm_iic.c | 6 ++-- drivers/i2c/busses/i2c-mpc.c | 4 +-- drivers/infiniband/hw/ehca/ehca_classes.h | 2 +- drivers/infiniband/hw/ehca/ehca_main.c | 4 +-- drivers/input/misc/sparcspkr.c | 10 +++--- drivers/input/serio/i8042-sparcio.h | 8 ++--- drivers/input/serio/xilinx_ps2.c | 4 +-- drivers/leds/leds-gpio.c | 4 +-- drivers/macintosh/macio_sysfs.c | 6 ++-- drivers/macintosh/smu.c | 6 ++-- drivers/macintosh/therm_adt746x.c | 2 +- drivers/macintosh/therm_pm72.c | 6 ++-- drivers/macintosh/therm_windtunnel.c | 6 ++-- drivers/media/video/fsl-viu.c | 8 ++--- drivers/mmc/host/sdhci-of-core.c | 8 ++--- drivers/mtd/maps/physmap_of.c | 8 ++--- drivers/mtd/maps/sun_uflash.c | 6 ++-- drivers/mtd/nand/fsl_elbc_nand.c | 4 +-- drivers/mtd/nand/fsl_upm.c | 4 +-- drivers/mtd/nand/mpc5121_nfc.c | 4 +-- drivers/mtd/nand/ndfc.c | 6 ++-- drivers/mtd/nand/pasemi_nand.c | 4 +-- drivers/mtd/nand/socrates_nand.c | 4 +-- drivers/net/can/mscan/mpc5xxx_can.c | 18 +++++------ drivers/net/can/sja1000/sja1000_of_platform.c | 4 +-- drivers/net/ehea/ehea.h | 4 +-- drivers/net/ehea/ehea_main.c | 12 ++++---- drivers/net/fec_mpc52xx.c | 8 ++--- drivers/net/fec_mpc52xx_phy.c | 4 +-- drivers/net/fs_enet/fs_enet-main.c | 4 +-- drivers/net/fs_enet/mac-fcc.c | 2 +- drivers/net/fs_enet/mac-fec.c | 2 +- drivers/net/fs_enet/mac-scc.c | 2 +- drivers/net/fs_enet/mii-bitbang.c | 4 +-- drivers/net/fs_enet/mii-fec.c | 4 +-- drivers/net/fsl_pq_mdio.c | 4 +-- drivers/net/gianfar.c | 10 +++--- drivers/net/gianfar.h | 2 +- drivers/net/greth.c | 4 +-- drivers/net/greth.h | 2 +- drivers/net/ibm_newemac/core.c | 6 ++-- drivers/net/ibm_newemac/core.h | 12 ++++---- drivers/net/ibm_newemac/mal.c | 4 +-- drivers/net/ibm_newemac/mal.h | 2 +- drivers/net/ibm_newemac/rgmii.c | 18 +++++------ drivers/net/ibm_newemac/rgmii.h | 16 +++++----- drivers/net/ibm_newemac/tah.c | 14 ++++----- drivers/net/ibm_newemac/tah.h | 12 ++++---- drivers/net/ibm_newemac/zmii.c | 18 +++++------ drivers/net/ibm_newemac/zmii.h | 16 +++++----- drivers/net/ll_temac_main.c | 8 ++--- drivers/net/myri_sbus.c | 4 +-- drivers/net/myri_sbus.h | 2 +- drivers/net/niu.c | 8 ++--- drivers/net/phy/mdio-gpio.c | 4 +-- drivers/net/sunbmac.c | 18 +++++------ drivers/net/sunbmac.h | 4 +-- drivers/net/sunhme.c | 22 +++++++------- drivers/net/sunhme.h | 2 +- drivers/net/sunlance.c | 20 ++++++------ drivers/net/sunqe.c | 16 +++++----- drivers/net/sunqe.h | 4 +-- drivers/net/ucc_geth.c | 8 ++--- drivers/net/xilinx_emaclite.c | 6 ++-- drivers/of/device.c | 2 +- drivers/parport/parport_sunbpp.c | 4 +-- drivers/pcmcia/electra_cf.c | 6 ++-- drivers/pcmcia/m8xx_pcmcia.c | 4 +-- drivers/rtc/rtc-mpc5121.c | 4 +-- drivers/sbus/char/bbc_envctrl.c | 6 ++-- drivers/sbus/char/bbc_i2c.c | 18 +++++------ drivers/sbus/char/bbc_i2c.h | 10 +++--- drivers/sbus/char/display7seg.c | 4 +-- drivers/sbus/char/envctrl.c | 4 +-- drivers/sbus/char/flash.c | 4 +-- drivers/sbus/char/uctrl.c | 4 +-- drivers/scsi/qlogicpti.c | 14 ++++----- drivers/scsi/qlogicpti.h | 2 +- drivers/scsi/sun_esp.c | 44 +++++++++++++-------------- drivers/serial/apbuart.c | 2 +- drivers/serial/cpm_uart/cpm_uart_core.c | 4 +-- drivers/serial/mpc52xx_uart.c | 8 ++--- drivers/serial/nwpserial.c | 2 +- drivers/serial/of_serial.c | 6 ++-- drivers/serial/sunhv.c | 4 +-- drivers/serial/sunsab.c | 8 ++--- drivers/serial/sunsu.c | 8 ++--- drivers/serial/sunzilog.c | 6 ++-- drivers/serial/uartlite.c | 4 +-- drivers/serial/ucc_uart.c | 4 +-- drivers/spi/mpc512x_psc_spi.c | 4 +-- drivers/spi/mpc52xx_psc_spi.c | 4 +-- drivers/spi/mpc52xx_spi.c | 4 +-- drivers/spi/spi_mpc8xxx.c | 4 +-- drivers/spi/spi_ppc4xx.c | 6 ++-- drivers/spi/xilinx_spi_of.c | 6 ++-- drivers/usb/gadget/fsl_qe_udc.c | 10 +++--- drivers/usb/host/ehci-ppc-of.c | 6 ++-- drivers/usb/host/ehci-xilinx-of.c | 12 ++++---- drivers/usb/host/fhci-hcd.c | 4 +-- drivers/usb/host/isp1760-if.c | 4 +-- drivers/usb/host/ohci-ppc-of.c | 6 ++-- drivers/video/bw2.c | 4 +-- drivers/video/cg14.c | 6 ++-- drivers/video/cg3.c | 4 +-- drivers/video/cg6.c | 6 ++-- drivers/video/ffb.c | 4 +-- drivers/video/fsl-diu-fb.c | 8 ++--- drivers/video/leo.c | 6 ++-- drivers/video/mb862xx/mb862xxfb.c | 4 +-- drivers/video/p9100.c | 4 +-- drivers/video/platinumfb.c | 4 +-- drivers/video/sunxvr1000.c | 4 +-- drivers/video/tcx.c | 6 ++-- drivers/video/xilinxfb.c | 4 +-- drivers/watchdog/cpwd.c | 4 +-- drivers/watchdog/gef_wdt.c | 2 +- drivers/watchdog/mpc8xxx_wdt.c | 4 +-- drivers/watchdog/riowd.c | 4 +-- include/linux/of_device.h | 16 ---------- include/linux/of_platform.h | 14 +++++++-- sound/aoa/soundbus/core.c | 2 +- sound/aoa/soundbus/soundbus.h | 2 +- sound/aoa/soundbus/sysfs.c | 2 +- sound/soc/fsl/mpc5200_dma.c | 4 +-- sound/soc/fsl/mpc5200_dma.h | 4 +-- sound/soc/fsl/mpc5200_psc_ac97.c | 4 +-- sound/soc/fsl/mpc5200_psc_i2s.c | 4 +-- sound/soc/fsl/mpc8610_hpcd.c | 4 +-- sound/sparc/amd7930.c | 8 ++--- sound/sparc/cs4231.c | 18 +++++------ sound/sparc/dbri.c | 8 ++--- 158 files changed, 519 insertions(+), 527 deletions(-) (limited to 'drivers/serial') diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index 51df7e754698..f9751c8905be 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c @@ -102,7 +102,7 @@ static struct of_device_id mpc837x_ids[] = { static int __init mpc837x_declare_of_platform_devices(void) { - /* Publish of_device */ + /* Publish platform_device */ of_platform_bus_probe(NULL, mpc837x_ids, NULL); return 0; diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c index e00801c42540..910caa6b5810 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c @@ -78,7 +78,7 @@ static struct of_device_id mpc837x_ids[] = { static int __init mpc837x_declare_of_platform_devices(void) { - /* Publish of_device */ + /* Publish platform_device */ of_platform_bus_probe(NULL, mpc837x_ids, NULL); return 0; diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 8bd86530ee25..6425abe5b7db 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1332,7 +1332,7 @@ static inline void fsl_rio_info(struct device *dev, u32 ccsr) /** * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface - * @dev: of_device pointer + * @dev: platform_device pointer * * Initializes MPC85xx RapidIO hardware interface, configures * master port with system-specific info, and registers the diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index f087ab55b1df..8cc536e49a0a 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -680,7 +680,7 @@ mpc52xx_ata_remove_one(struct device *dev) /* ======================================================================== */ static int __devinit -mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) +mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match) { unsigned int ipb_freq; struct resource res_mem; @@ -821,7 +821,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) } static int -mpc52xx_ata_remove(struct of_device *op) +mpc52xx_ata_remove(struct platform_device *op) { struct mpc52xx_ata_priv *priv; int task_irq; @@ -848,7 +848,7 @@ mpc52xx_ata_remove(struct of_device *op) #ifdef CONFIG_PM static int -mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) +mpc52xx_ata_suspend(struct platform_device *op, pm_message_t state) { struct ata_host *host = dev_get_drvdata(&op->dev); @@ -856,7 +856,7 @@ mpc52xx_ata_suspend(struct of_device *op, pm_message_t state) } static int -mpc52xx_ata_resume(struct of_device *op) +mpc52xx_ata_resume(struct platform_device *op) { struct ata_host *host = dev_get_drvdata(&op->dev); struct mpc52xx_ata_priv *priv = host->private_data; diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 5a1b82c08be9..480e043ce6b8 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c @@ -14,7 +14,7 @@ #include #include -static int __devinit pata_of_platform_probe(struct of_device *ofdev, +static int __devinit pata_of_platform_probe(struct platform_device *ofdev, const struct of_device_id *match) { int ret; @@ -78,7 +78,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev, reg_shift, pio_mask); } -static int __devexit pata_of_platform_remove(struct of_device *ofdev) +static int __devexit pata_of_platform_remove(struct platform_device *ofdev) { return __pata_platform_remove(&ofdev->dev); } diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 61c89b54ea23..4e4d42f1186a 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -1296,7 +1296,7 @@ static const struct ata_port_info sata_fsl_port_info[] = { }, }; -static int sata_fsl_probe(struct of_device *ofdev, +static int sata_fsl_probe(struct platform_device *ofdev, const struct of_device_id *match) { int retval = -ENXIO; @@ -1370,7 +1370,7 @@ error_exit_with_cleanup: return retval; } -static int sata_fsl_remove(struct of_device *ofdev) +static int sata_fsl_remove(struct platform_device *ofdev) { struct ata_host *host = dev_get_drvdata(&ofdev->dev); struct sata_fsl_host_priv *host_priv = host->private_data; @@ -1387,13 +1387,13 @@ static int sata_fsl_remove(struct of_device *ofdev) } #ifdef CONFIG_PM -static int sata_fsl_suspend(struct of_device *op, pm_message_t state) +static int sata_fsl_suspend(struct platform_device *op, pm_message_t state) { struct ata_host *host = dev_get_drvdata(&op->dev); return ata_host_suspend(host, state); } -static int sata_fsl_resume(struct of_device *op) +static int sata_fsl_resume(struct platform_device *op) { struct ata_host *host = dev_get_drvdata(&op->dev); struct sata_fsl_host_priv *host_priv = host->private_data; diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index b7385e077717..c8fc69c85a06 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -674,7 +674,7 @@ static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; u32 dma_addr; dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); @@ -687,7 +687,7 @@ static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction); @@ -697,7 +697,7 @@ static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); @@ -706,7 +706,7 @@ static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_add static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); @@ -719,7 +719,7 @@ static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, int size, int nbr, int alignment) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; chunk->alloc_size = chunk->align_size = size * nbr; @@ -738,7 +738,7 @@ static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk /* free a DVMA consistent chunk of memory */ static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; dma_free_coherent(&op->dev, chunk->alloc_size, chunk->alloc_addr, chunk->dma_addr); @@ -770,7 +770,7 @@ static void fore200e_sba_reset(struct fore200e *fore200e) static int __init fore200e_sba_map(struct fore200e *fore200e) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; unsigned int bursts; /* gain access to the SBA specific registers */ @@ -800,7 +800,7 @@ static int __init fore200e_sba_map(struct fore200e *fore200e) static void fore200e_sba_unmap(struct fore200e *fore200e) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); @@ -816,7 +816,7 @@ static int __init fore200e_sba_configure(struct fore200e *fore200e) static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; const u8 *prop; int len; @@ -840,7 +840,7 @@ static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_ static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) { - struct of_device *op = fore200e->bus_dev; + struct platform_device *op = fore200e->bus_dev; const struct linux_prom_registers *regs; regs = of_get_property(op->dev.of_node, "reg", NULL); @@ -2513,7 +2513,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) device = &((struct pci_dev *) fore200e->bus_dev)->dev; #ifdef CONFIG_SBUS else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) - device = &((struct of_device *) fore200e->bus_dev)->dev; + device = &((struct platform_device *) fore200e->bus_dev)->dev; #endif else return err; @@ -2643,7 +2643,7 @@ fore200e_init(struct fore200e* fore200e) } #ifdef CONFIG_SBUS -static int __devinit fore200e_sba_probe(struct of_device *op, +static int __devinit fore200e_sba_probe(struct platform_device *op, const struct of_device_id *match) { const struct fore200e_bus *bus = match->data; @@ -2675,7 +2675,7 @@ static int __devinit fore200e_sba_probe(struct of_device *op, return 0; } -static int __devexit fore200e_sba_remove(struct of_device *op) +static int __devexit fore200e_sba_remove(struct platform_device *op) { struct fore200e *fore200e = dev_get_drvdata(&op->dev); diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index a7b83c0a7eb5..d7cb69db3067 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1188,7 +1188,7 @@ static struct platform_driver ace_platform_driver = { #if defined(CONFIG_OF) static int __devinit -ace_of_probe(struct of_device *op, const struct of_device_id *match) +ace_of_probe(struct platform_device *op, const struct of_device_id *match) { struct resource res; resource_size_t physaddr; @@ -1220,7 +1220,7 @@ ace_of_probe(struct of_device *op, const struct of_device_id *match) return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width); } -static int __devexit ace_of_remove(struct of_device *op) +static int __devexit ace_of_remove(struct platform_device *op) { ace_free(&op->dev); return 0; diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 7a4f080f8356..1acdb2509511 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -619,7 +619,7 @@ static void __devinit n2rng_driver_version(void) pr_info("%s", version); } -static int __devinit n2rng_probe(struct of_device *op, +static int __devinit n2rng_probe(struct platform_device *op, const struct of_device_id *match) { int victoria_falls = (match->data != NULL); @@ -714,7 +714,7 @@ out: return err; } -static int __devexit n2rng_remove(struct of_device *op) +static int __devexit n2rng_remove(struct platform_device *op) { struct n2rng *np = dev_get_drvdata(&op->dev); diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h index a2b81e7bfc18..4bea07f30978 100644 --- a/drivers/char/hw_random/n2rng.h +++ b/drivers/char/hw_random/n2rng.h @@ -65,7 +65,7 @@ struct n2rng_unit { }; struct n2rng { - struct of_device *op; + struct platform_device *op; unsigned long flags; #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 261ba8f22b8b..a31c830ca8cd 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c @@ -94,7 +94,7 @@ static struct hwrng pasemi_rng = { .data_read = pasemi_rng_data_read, }; -static int __devinit rng_probe(struct of_device *ofdev, +static int __devinit rng_probe(struct platform_device *ofdev, const struct of_device_id *match) { void __iomem *rng_regs; @@ -123,7 +123,7 @@ static int __devinit rng_probe(struct of_device *ofdev, return err; } -static int __devexit rng_remove(struct of_device *dev) +static int __devexit rng_remove(struct platform_device *dev) { void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 094bdc355b1f..b532d613fb5b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2502,7 +2502,7 @@ static struct pci_driver ipmi_pci_driver = { #ifdef CONFIG_PPC_OF -static int __devinit ipmi_of_probe(struct of_device *dev, +static int __devinit ipmi_of_probe(struct platform_device *dev, const struct of_device_id *match) { struct smi_info *info; @@ -2576,7 +2576,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev, return add_smi(info); } -static int __devexit ipmi_of_remove(struct of_device *dev) +static int __devexit ipmi_of_remove(struct platform_device *dev) { cleanup_one_si(dev_get_drvdata(&dev->dev)); return 0; diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 95acb8c880f4..dfa8b3062fda 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -961,7 +961,7 @@ static int __init rtc_init(void) #endif #ifdef CONFIG_SPARC32 struct device_node *ebus_dp; - struct of_device *op; + struct platform_device *op; #else void *r; #ifdef RTC_IRQ diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index ed8a9cec2a05..0ed763cd2e77 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -761,7 +761,7 @@ static struct platform_driver hwicap_platform_driver = { #if defined(CONFIG_OF) static int __devinit -hwicap_of_probe(struct of_device *op, const struct of_device_id *match) +hwicap_of_probe(struct platform_device *op, const struct of_device_id *match) { struct resource res; const unsigned int *id; @@ -798,7 +798,7 @@ hwicap_of_probe(struct of_device *op, const struct of_device_id *match) regs); } -static int __devexit hwicap_of_remove(struct of_device *op) +static int __devexit hwicap_of_remove(struct platform_device *op) { return hwicap_remove(&op->dev); } diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 983530ba04a7..2b1baee525bc 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -1150,7 +1150,7 @@ struct crypto4xx_alg_common crypto4xx_alg[] = { /** * Module Initialization Routine */ -static int __init crypto4xx_probe(struct of_device *ofdev, +static int __init crypto4xx_probe(struct platform_device *ofdev, const struct of_device_id *match) { int rc; @@ -1258,7 +1258,7 @@ err_alloc_dev: return rc; } -static int __exit crypto4xx_remove(struct of_device *ofdev) +static int __exit crypto4xx_remove(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h index da9cbe3b9fc3..bac0bdeb4b5f 100644 --- a/drivers/crypto/amcc/crypto4xx_core.h +++ b/drivers/crypto/amcc/crypto4xx_core.h @@ -104,7 +104,7 @@ struct crypto4xx_device { struct crypto4xx_core_device { struct device *device; - struct of_device *ofdev; + struct platform_device *ofdev; struct crypto4xx_device *dev; u32 int_status; u32 irq; diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 26af2dd5d831..931fdd471d6d 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -1552,7 +1552,7 @@ static void __exit n2_unregister_algs(void) /* To map CWQ queues to interrupt sources, the hypervisor API provides * a devino. This isn't very useful to us because all of the - * interrupts listed in the of_device node have been translated to + * interrupts listed in the device_node have been translated to * Linux virtual IRQ cookie numbers. * * So we have to back-translate, going through the 'intr' and 'ino' @@ -1560,7 +1560,7 @@ static void __exit n2_unregister_algs(void) * 'interrupts' property entries, in order to to figure out which * devino goes to which already-translated IRQ. */ -static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, +static int find_devino_index(struct platform_device *dev, struct spu_mdesc_info *ip, unsigned long dev_ino) { const unsigned int *dev_intrs; @@ -1588,7 +1588,7 @@ static int find_devino_index(struct of_device *dev, struct spu_mdesc_info *ip, return -ENODEV; } -static int spu_map_ino(struct of_device *dev, struct spu_mdesc_info *ip, +static int spu_map_ino(struct platform_device *dev, struct spu_mdesc_info *ip, const char *irq_name, struct spu_queue *p, irq_handler_t handler) { @@ -1736,7 +1736,7 @@ static void spu_list_destroy(struct list_head *list) * gathering cpu membership information. */ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, - struct of_device *dev, + struct platform_device *dev, u64 node, struct spu_queue *p, struct spu_queue **table) { @@ -1763,7 +1763,7 @@ static int spu_mdesc_walk_arcs(struct mdesc_handle *mdesc, /* Process an 'exec-unit' MDESC node of type 'cwq'. */ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, - struct of_device *dev, struct mdesc_handle *mdesc, + struct platform_device *dev, struct mdesc_handle *mdesc, u64 node, const char *iname, unsigned long q_type, irq_handler_t handler, struct spu_queue **table) { @@ -1794,7 +1794,7 @@ static int handle_exec_unit(struct spu_mdesc_info *ip, struct list_head *list, return spu_map_ino(dev, ip, iname, p, handler); } -static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct of_device *dev, +static int spu_mdesc_scan(struct mdesc_handle *mdesc, struct platform_device *dev, struct spu_mdesc_info *ip, struct list_head *list, const char *exec_name, unsigned long q_type, irq_handler_t handler, struct spu_queue **table) @@ -1855,7 +1855,7 @@ static int __devinit get_irq_props(struct mdesc_handle *mdesc, u64 node, } static int __devinit grab_mdesc_irq_props(struct mdesc_handle *mdesc, - struct of_device *dev, + struct platform_device *dev, struct spu_mdesc_info *ip, const char *node_name) { @@ -2004,7 +2004,7 @@ static void __devinit n2_spu_driver_version(void) pr_info("%s", version); } -static int __devinit n2_crypto_probe(struct of_device *dev, +static int __devinit n2_crypto_probe(struct platform_device *dev, const struct of_device_id *match) { struct mdesc_handle *mdesc; @@ -2081,7 +2081,7 @@ out_free_n2cp: return err; } -static int __devexit n2_crypto_remove(struct of_device *dev) +static int __devexit n2_crypto_remove(struct platform_device *dev) { struct n2_crypto *np = dev_get_drvdata(&dev->dev); @@ -2116,7 +2116,7 @@ static void free_ncp(struct n2_mau *mp) kfree(mp); } -static int __devinit n2_mau_probe(struct of_device *dev, +static int __devinit n2_mau_probe(struct platform_device *dev, const struct of_device_id *match) { struct mdesc_handle *mdesc; @@ -2184,7 +2184,7 @@ out_free_ncp: return err; } -static int __devexit n2_mau_remove(struct of_device *dev) +static int __devexit n2_mau_remove(struct platform_device *dev) { struct n2_mau *mp = dev_get_drvdata(&dev->dev); diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 97f4af1d8a64..4bcd825b5739 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -118,7 +118,7 @@ struct talitos_channel { struct talitos_private { struct device *dev; - struct of_device *ofdev; + struct platform_device *ofdev; void __iomem *reg; int irq; @@ -2308,7 +2308,7 @@ static int hw_supports(struct device *dev, __be32 desc_hdr_template) return ret; } -static int talitos_remove(struct of_device *ofdev) +static int talitos_remove(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct talitos_private *priv = dev_get_drvdata(dev); @@ -2401,7 +2401,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, return t_alg; } -static int talitos_probe(struct of_device *ofdev, +static int talitos_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device *dev = &ofdev->dev; diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index f0fd6db6063c..cea08bed9cf9 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1297,7 +1297,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan) kfree(chan); } -static int __devinit fsldma_of_probe(struct of_device *op, +static int __devinit fsldma_of_probe(struct platform_device *op, const struct of_device_id *match) { struct fsldma_device *fdev; @@ -1382,7 +1382,7 @@ out_return: return err; } -static int fsldma_of_remove(struct of_device *op) +static int fsldma_of_remove(struct platform_device *op) { struct fsldma_device *fdev; unsigned int i; diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c index 14a8c0f1698e..4e9cbf300594 100644 --- a/drivers/dma/mpc512x_dma.c +++ b/drivers/dma/mpc512x_dma.c @@ -627,7 +627,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, return &mdesc->desc; } -static int __devinit mpc_dma_probe(struct of_device *op, +static int __devinit mpc_dma_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; @@ -753,7 +753,7 @@ static int __devinit mpc_dma_probe(struct of_device *op, return retval; } -static int __devexit mpc_dma_remove(struct of_device *op) +static int __devexit mpc_dma_remove(struct platform_device *op) { struct device *dev = &op->dev; struct mpc_dma *mdma = dev_get_drvdata(dev); diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c index 7c3747902a37..0d58a4a4487f 100644 --- a/drivers/dma/ppc4xx/adma.c +++ b/drivers/dma/ppc4xx/adma.c @@ -4257,11 +4257,11 @@ static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev, struct ppc440spe_adma_chan *chan, int *initcode) { - struct of_device *ofdev; + struct platform_device *ofdev; struct device_node *np; int ret; - ofdev = container_of(adev->dev, struct of_device, dev); + ofdev = container_of(adev->dev, struct platform_device, dev); np = ofdev->dev.of_node; if (adev->id != PPC440SPE_XOR_ID) { adev->err_irq = irq_of_parse_and_map(np, 1); @@ -4393,7 +4393,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev, /** * ppc440spe_adma_probe - probe the asynch device */ -static int __devinit ppc440spe_adma_probe(struct of_device *ofdev, +static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -4625,7 +4625,7 @@ out: /** * ppc440spe_adma_remove - remove the asynch device */ -static int __devexit ppc440spe_adma_remove(struct of_device *ofdev) +static int __devexit ppc440spe_adma_remove(struct platform_device *ofdev) { struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev); struct device_node *np = ofdev->dev.of_node; diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 1052340e6802..8ea07b019543 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -200,7 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mpc85xx_pci_err_probe(struct of_device *op, +static int __devinit mpc85xx_pci_err_probe(struct platform_device *op, const struct of_device_id *match) { struct edac_pci_ctl_info *pci; @@ -305,7 +305,7 @@ err: return res; } -static int mpc85xx_pci_err_remove(struct of_device *op) +static int mpc85xx_pci_err_remove(struct platform_device *op) { struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); struct mpc85xx_pci_pdata *pdata = pci->pvt_info; @@ -503,7 +503,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mpc85xx_l2_err_probe(struct of_device *op, +static int __devinit mpc85xx_l2_err_probe(struct platform_device *op, const struct of_device_id *match) { struct edac_device_ctl_info *edac_dev; @@ -613,7 +613,7 @@ err: return res; } -static int mpc85xx_l2_err_remove(struct of_device *op) +static int mpc85xx_l2_err_remove(struct platform_device *op) { struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; @@ -953,7 +953,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) } } -static int __devinit mpc85xx_mc_err_probe(struct of_device *op, +static int __devinit mpc85xx_mc_err_probe(struct platform_device *op, const struct of_device_id *match) { struct mem_ctl_info *mci; @@ -1085,7 +1085,7 @@ err: return res; } -static int mpc85xx_mc_err_remove(struct of_device *op) +static int mpc85xx_mc_err_remove(struct platform_device *op) { struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index e78839e89a06..070cea41b661 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -184,9 +184,9 @@ struct ppc4xx_ecc_status { /* Function Prototypes */ -static int ppc4xx_edac_probe(struct of_device *device, +static int ppc4xx_edac_probe(struct platform_device *device, const struct of_device_id *device_id); -static int ppc4xx_edac_remove(struct of_device *device); +static int ppc4xx_edac_remove(struct platform_device *device); /* Global Variables */ @@ -1014,7 +1014,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) */ static int __devinit ppc4xx_edac_mc_init(struct mem_ctl_info *mci, - struct of_device *op, + struct platform_device *op, const struct of_device_id *match, const dcr_host_t *dcr_host, u32 mcopt1) @@ -1108,7 +1108,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, * mapped and assigned. */ static int __devinit -ppc4xx_edac_register_irq(struct of_device *op, struct mem_ctl_info *mci) +ppc4xx_edac_register_irq(struct platform_device *op, struct mem_ctl_info *mci) { int status = 0; int ded_irq, sec_irq; @@ -1238,7 +1238,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host) * driver; otherwise, < 0 on error. */ static int __devinit -ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) +ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match) { int status = 0; u32 mcopt1, memcheck; @@ -1359,7 +1359,7 @@ ppc4xx_edac_probe(struct of_device *op, const struct of_device_id *match) * Unconditionally returns 0. */ static int -ppc4xx_edac_remove(struct of_device *op) +ppc4xx_edac_remove(struct platform_device *op) { struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct ppc4xx_edac_pdata *pdata = mci->pvt_info; diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h index b28d7e27a031..90f094d45450 100644 --- a/drivers/hwmon/ams/ams.h +++ b/drivers/hwmon/ams/ams.h @@ -23,7 +23,7 @@ struct ams { /* General properties */ struct device_node *of_node; - struct of_device *of_dev; + struct platform_device *of_dev; char has_device; char vflag; u32 orient1; diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index 89643261ccdb..d863e13a50b8 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c @@ -234,7 +234,7 @@ static const struct attribute_group env_group = { .attrs = env_attributes, }; -static int __devinit env_probe(struct of_device *op, +static int __devinit env_probe(struct platform_device *op, const struct of_device_id *match) { struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -276,7 +276,7 @@ out_free: goto out; } -static int __devexit env_remove(struct of_device *op) +static int __devexit env_remove(struct platform_device *op) { struct env *p = dev_get_drvdata(&op->dev); diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index e591de1bc704..f7bd2613cecc 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -105,7 +105,7 @@ struct i2c_reg { struct cpm_i2c { char *base; - struct of_device *ofdev; + struct platform_device *ofdev; struct i2c_adapter adap; uint dp_addr; int version; /* CPM1=1, CPM2=2 */ @@ -428,7 +428,7 @@ static const struct i2c_adapter cpm_ops = { static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) { - struct of_device *ofdev = cpm->ofdev; + struct platform_device *ofdev = cpm->ofdev; const u32 *data; int len, ret, i; void __iomem *i2c_base; @@ -634,7 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm) cpm_muram_free(cpm->i2c_addr); } -static int __devinit cpm_i2c_probe(struct of_device *ofdev, +static int __devinit cpm_i2c_probe(struct platform_device *ofdev, const struct of_device_id *match) { int result, len; @@ -687,7 +687,7 @@ out_free: return result; } -static int __devexit cpm_i2c_remove(struct of_device *ofdev) +static int __devexit cpm_i2c_remove(struct platform_device *ofdev) { struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 1168d61418c9..43ca32fddde2 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -661,7 +661,7 @@ static inline u8 iic_clckdiv(unsigned int opb) return (u8)((opb + 9) / 10 - 1); } -static int __devinit iic_request_irq(struct of_device *ofdev, +static int __devinit iic_request_irq(struct platform_device *ofdev, struct ibm_iic_private *dev) { struct device_node *np = ofdev->dev.of_node; @@ -692,7 +692,7 @@ static int __devinit iic_request_irq(struct of_device *ofdev, /* * Register single IIC interface */ -static int __devinit iic_probe(struct of_device *ofdev, +static int __devinit iic_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -780,7 +780,7 @@ error_cleanup: /* * Cleanup initialized IIC interface */ -static int __devexit iic_remove(struct of_device *ofdev) +static int __devexit iic_remove(struct platform_device *ofdev) { struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 6545d1c99b61..a1c419a716af 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -560,7 +560,7 @@ static struct i2c_adapter mpc_ops = { .timeout = HZ, }; -static int __devinit fsl_i2c_probe(struct of_device *op, +static int __devinit fsl_i2c_probe(struct platform_device *op, const struct of_device_id *match) { struct mpc_i2c *i2c; @@ -646,7 +646,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op, return result; }; -static int __devexit fsl_i2c_remove(struct of_device *op) +static int __devexit fsl_i2c_remove(struct platform_device *op) { struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 0136abd50dd4..aaf6023a4835 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -112,7 +112,7 @@ struct ehca_sport { struct ehca_shca { struct ib_device ib_device; - struct of_device *ofdev; + struct platform_device *ofdev; u8 num_ports; int hw_level; struct list_head shca_list; diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index ecb51b396c42..67c4534fb941 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -712,7 +712,7 @@ static struct attribute_group ehca_dev_attr_grp = { .attrs = ehca_dev_attrs }; -static int __devinit ehca_probe(struct of_device *dev, +static int __devinit ehca_probe(struct platform_device *dev, const struct of_device_id *id) { struct ehca_shca *shca; @@ -878,7 +878,7 @@ probe1: return -EINVAL; } -static int __devexit ehca_remove(struct of_device *dev) +static int __devexit ehca_remove(struct platform_device *dev) { struct ehca_shca *shca = dev_get_drvdata(&dev->dev); unsigned long flags; diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index f3bb92e9755f..8e130bf7d32b 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -173,7 +173,7 @@ static int __devinit sparcspkr_probe(struct device *dev) return 0; } -static int sparcspkr_shutdown(struct of_device *dev) +static int sparcspkr_shutdown(struct platform_device *dev) { struct sparcspkr_state *state = dev_get_drvdata(&dev->dev); struct input_dev *input_dev = state->input_dev; @@ -184,7 +184,7 @@ static int sparcspkr_shutdown(struct of_device *dev) return 0; } -static int __devinit bbc_beep_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match) { struct sparcspkr_state *state; struct bbc_beep_info *info; @@ -231,7 +231,7 @@ out_err: return err; } -static int __devexit bbc_remove(struct of_device *op) +static int __devexit bbc_remove(struct platform_device *op) { struct sparcspkr_state *state = dev_get_drvdata(&op->dev); struct input_dev *input_dev = state->input_dev; @@ -269,7 +269,7 @@ static struct of_platform_driver bbc_beep_driver = { .shutdown = sparcspkr_shutdown, }; -static int __devinit grover_beep_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match) { struct sparcspkr_state *state; struct grover_beep_info *info; @@ -312,7 +312,7 @@ out_err: return err; } -static int __devexit grover_remove(struct of_device *op) +static int __devexit grover_remove(struct platform_device *op) { struct sparcspkr_state *state = dev_get_drvdata(&op->dev); struct grover_beep_info *info = &state->u.grover; diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index cb2a24b94746..c5cc4508d6df 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) #define OBP_PS2MS_NAME1 "kdmouse" #define OBP_PS2MS_NAME2 "mouse" -static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -57,7 +57,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev while (dp) { if (!strcmp(dp->name, OBP_PS2KBD_NAME1) || !strcmp(dp->name, OBP_PS2KBD_NAME2)) { - struct of_device *kbd = of_find_device_by_node(dp); + struct platform_device *kbd = of_find_device_by_node(dp); unsigned int irq = kbd->archdata.irqs[0]; if (irq == 0xffffffff) irq = op->archdata.irqs[0]; @@ -67,7 +67,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev kbd_res = &kbd->resource[0]; } else if (!strcmp(dp->name, OBP_PS2MS_NAME1) || !strcmp(dp->name, OBP_PS2MS_NAME2)) { - struct of_device *ms = of_find_device_by_node(dp); + struct platform_device *ms = of_find_device_by_node(dp); unsigned int irq = ms->archdata.irqs[0]; if (irq == 0xffffffff) irq = op->archdata.irqs[0]; @@ -80,7 +80,7 @@ static int __devinit sparc_i8042_probe(struct of_device *op, const struct of_dev return 0; } -static int __devexit sparc_i8042_remove(struct of_device *op) +static int __devexit sparc_i8042_remove(struct platform_device *op) { of_iounmap(kbd_res, kbd_iobase, 8); diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index e2c028d2638f..bb14449fb022 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -232,7 +232,7 @@ static void sxps2_close(struct serio *pserio) * It returns 0, if the driver is bound to the PS/2 device, or a negative * value if there is an error. */ -static int __devinit xps2_of_probe(struct of_device *ofdev, +static int __devinit xps2_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct resource r_irq; /* Interrupt resources */ @@ -332,7 +332,7 @@ failed1: * if the driver module is being unloaded. It frees any resources allocated to * the device. */ -static int __devexit xps2_of_remove(struct of_device *of_dev) +static int __devexit xps2_of_remove(struct platform_device *of_dev) { struct device *dev = &of_dev->dev; struct xps2data *drvdata = dev_get_drvdata(dev); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index cc22eeefa10b..ea57e05d08f3 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -224,7 +224,7 @@ struct gpio_led_of_platform_data { struct gpio_led_data led_data[]; }; -static int __devinit of_gpio_leds_probe(struct of_device *ofdev, +static int __devinit of_gpio_leds_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node, *child; @@ -283,7 +283,7 @@ err: return ret; } -static int __devexit of_gpio_leds_remove(struct of_device *ofdev) +static int __devexit of_gpio_leds_remove(struct platform_device *ofdev) { struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev); int i; diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 6024038a5b9d..8eb40afbd0f5 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c @@ -15,7 +15,7 @@ field##_show (struct device *dev, struct device_attribute *attr, \ static ssize_t compatible_show (struct device *dev, struct device_attribute *attr, char *buf) { - struct of_device *of; + struct platform_device *of; const char *compat; int cplen; int length = 0; @@ -52,9 +52,9 @@ static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, static ssize_t devspec_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct of_device *ofdev; + struct platform_device *ofdev; - ofdev = to_of_device(dev); + ofdev = to_platform_device(dev); return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); } diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 2506c957712e..e58c3d33e035 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -75,7 +75,7 @@ struct smu_cmd_buf { struct smu_device { spinlock_t lock; struct device_node *of_node; - struct of_device *of_dev; + struct platform_device *of_dev; int doorbell; /* doorbell gpio */ u32 __iomem *db_buf; /* doorbell buffer */ struct device_node *db_node; @@ -645,7 +645,7 @@ static void smu_expose_childs(struct work_struct *unused) static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); -static int smu_platform_probe(struct of_device* dev, +static int smu_platform_probe(struct platform_device* dev, const struct of_device_id *match) { if (!smu) @@ -695,7 +695,7 @@ static int __init smu_init_sysfs(void) device_initcall(smu_init_sysfs); -struct of_device *smu_get_ofdev(void) +struct platform_device *smu_get_ofdev(void) { if (!smu) return NULL; diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index c42eeb43042d..d0d221332db0 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -84,7 +84,7 @@ struct thermostat { static enum {ADT7460, ADT7467} therm_type; static int therm_bus, therm_address; -static struct of_device * of_dev; +static struct platform_device * of_dev; static struct thermostat* thermostat; static struct task_struct *thread_therm = NULL; diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index e60605bd0ea9..44549272333c 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -148,7 +148,7 @@ * Driver statics */ -static struct of_device * of_dev; +static struct platform_device * of_dev; static struct i2c_adapter * u3_0; static struct i2c_adapter * u3_1; static struct i2c_adapter * k2; @@ -2210,7 +2210,7 @@ static void fcu_lookup_fans(struct device_node *fcu_node) } } -static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) +static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match) { state = state_detached; @@ -2221,7 +2221,7 @@ static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) return i2c_add_driver(&therm_pm72_driver); } -static int fcu_of_remove(struct of_device* dev) +static int fcu_of_remove(struct platform_device* dev) { i2c_del_driver(&therm_pm72_driver); diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 5c9367acf0cf..133f195de1fd 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -52,7 +52,7 @@ static struct { struct task_struct *poll_task; struct mutex lock; - struct of_device *of_dev; + struct platform_device *of_dev; struct i2c_client *thermostat; struct i2c_client *fan; @@ -444,13 +444,13 @@ static struct i2c_driver g4fan_driver = { /************************************************************************/ static int -therm_of_probe( struct of_device *dev, const struct of_device_id *match ) +therm_of_probe( struct platform_device *dev, const struct of_device_id *match ) { return i2c_add_driver( &g4fan_driver ); } static int -therm_of_remove( struct of_device *dev ) +therm_of_remove( struct platform_device *dev ) { i2c_del_driver( &g4fan_driver ); return 0; diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 8f1c94f7e00c..43d208f1f586 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c @@ -1418,7 +1418,7 @@ static struct video_device viu_template = { .current_norm = V4L2_STD_NTSC_M, }; -static int __devinit viu_of_probe(struct of_device *op, +static int __devinit viu_of_probe(struct platform_device *op, const struct of_device_id *match) { struct viu_dev *viu_dev; @@ -1549,7 +1549,7 @@ err: return ret; } -static int __devexit viu_of_remove(struct of_device *op) +static int __devexit viu_of_remove(struct platform_device *op) { struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); @@ -1570,7 +1570,7 @@ static int __devexit viu_of_remove(struct of_device *op) } #ifdef CONFIG_PM -static int viu_suspend(struct of_device *op, pm_message_t state) +static int viu_suspend(struct platform_device *op, pm_message_t state) { struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); @@ -1579,7 +1579,7 @@ static int viu_suspend(struct of_device *op, pm_message_t state) return 0; } -static int viu_resume(struct of_device *op) +static int viu_resume(struct platform_device *op) { struct v4l2_device *v4l2_dev = dev_get_drvdata(&op->dev); struct viu_dev *dev = container_of(v4l2_dev, struct viu_dev, v4l2_dev); diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c index a2e9820cd42f..a6bd448a3b46 100644 --- a/drivers/mmc/host/sdhci-of-core.c +++ b/drivers/mmc/host/sdhci-of-core.c @@ -85,14 +85,14 @@ void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) #ifdef CONFIG_PM -static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state) +static int sdhci_of_suspend(struct platform_device *ofdev, pm_message_t state) { struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); return mmc_suspend_host(host->mmc); } -static int sdhci_of_resume(struct of_device *ofdev) +static int sdhci_of_resume(struct platform_device *ofdev) { struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); @@ -115,7 +115,7 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np) return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); } -static int __devinit sdhci_of_probe(struct of_device *ofdev, +static int __devinit sdhci_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -179,7 +179,7 @@ err_addr_map: return ret; } -static int __devexit sdhci_of_remove(struct of_device *ofdev) +static int __devexit sdhci_of_remove(struct platform_device *ofdev) { struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index ba124baa646d..8f9bab8dc8da 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c @@ -43,7 +43,7 @@ struct of_flash { #ifdef CONFIG_MTD_PARTITIONS #define OF_FLASH_PARTS(info) ((info)->parts) -static int parse_obsolete_partitions(struct of_device *dev, +static int parse_obsolete_partitions(struct platform_device *dev, struct of_flash *info, struct device_node *dp) { @@ -93,7 +93,7 @@ static int parse_obsolete_partitions(struct of_device *dev, #define parse_partitions(info, dev) (0) #endif /* MTD_PARTITIONS */ -static int of_flash_remove(struct of_device *dev) +static int of_flash_remove(struct platform_device *dev) { struct of_flash *info; int i; @@ -140,7 +140,7 @@ static int of_flash_remove(struct of_device *dev) /* Helper function to handle probing of the obsolete "direct-mapped" * compatible binding, which has an extra "probe-type" property * describing the type of flash probe necessary. */ -static struct mtd_info * __devinit obsolete_probe(struct of_device *dev, +static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev, struct map_info *map) { struct device_node *dp = dev->dev.of_node; @@ -215,7 +215,7 @@ static void __devinit of_free_probes(const char **probes) } #endif -static int __devinit of_flash_probe(struct of_device *dev, +static int __devinit of_flash_probe(struct platform_device *dev, const struct of_device_id *match) { #ifdef CONFIG_MTD_PARTITIONS diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 8984236a8d0a..3582ba1f9b09 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c @@ -48,7 +48,7 @@ struct map_info uflash_map_templ = { .bankwidth = UFLASH_BUSWIDTH, }; -int uflash_devinit(struct of_device *op, struct device_node *dp) +int uflash_devinit(struct platform_device *op, struct device_node *dp) { struct uflash_dev *up; @@ -108,7 +108,7 @@ int uflash_devinit(struct of_device *op, struct device_node *dp) return 0; } -static int __devinit uflash_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit uflash_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -121,7 +121,7 @@ static int __devinit uflash_probe(struct of_device *op, const struct of_device_i return uflash_devinit(op, dp); } -static int __devexit uflash_remove(struct of_device *op) +static int __devexit uflash_remove(struct platform_device *op) { struct uflash_dev *up = dev_get_drvdata(&op->dev); diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 5084cc517944..80de0bff6c3a 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -958,7 +958,7 @@ static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) return 0; } -static int fsl_elbc_ctrl_remove(struct of_device *ofdev) +static int fsl_elbc_ctrl_remove(struct platform_device *ofdev) { struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); int i; @@ -1013,7 +1013,7 @@ static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) * in the chip probe function. */ -static int __devinit fsl_elbc_ctrl_probe(struct of_device *ofdev, +static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *child; diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 1312eda57ba6..4eff8b25e5af 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -217,7 +217,7 @@ err: return ret; } -static int __devinit fun_probe(struct of_device *ofdev, +static int __devinit fun_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct fsl_upm_nand *fun; @@ -335,7 +335,7 @@ err1: return ret; } -static int __devexit fun_remove(struct of_device *ofdev) +static int __devexit fun_remove(struct platform_device *ofdev) { struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); int i; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 0a130dcaa129..df0c1da4ff49 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -647,7 +647,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) iounmap(prv->csreg); } -static int __devinit mpc5121_nfc_probe(struct of_device *op, +static int __devinit mpc5121_nfc_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *rootnode, *dn = op->dev.of_node; @@ -869,7 +869,7 @@ error: return retval; } -static int __devexit mpc5121_nfc_remove(struct of_device *op) +static int __devexit mpc5121_nfc_remove(struct platform_device *op) { struct device *dev = &op->dev; struct mtd_info *mtd = dev_get_drvdata(dev); diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 98fd2bdf8be1..510554e6c115 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -35,7 +35,7 @@ struct ndfc_controller { - struct of_device *ofdev; + struct platform_device *ofdev; void __iomem *ndfcbase; struct mtd_info mtd; struct nand_chip chip; @@ -225,7 +225,7 @@ err: return ret; } -static int __devinit ndfc_probe(struct of_device *ofdev, +static int __devinit ndfc_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct ndfc_controller *ndfc = &ndfc_ctrl; @@ -277,7 +277,7 @@ static int __devinit ndfc_probe(struct of_device *ofdev, return 0; } -static int __devexit ndfc_remove(struct of_device *ofdev) +static int __devexit ndfc_remove(struct platform_device *ofdev) { struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index f02af24d033a..6ddb2461d740 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -89,7 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd) return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR); } -static int __devinit pasemi_nand_probe(struct of_device *ofdev, +static int __devinit pasemi_nand_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct pci_dev *pdev; @@ -185,7 +185,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev, return err; } -static int __devexit pasemi_nand_remove(struct of_device *ofdev) +static int __devexit pasemi_nand_remove(struct platform_device *ofdev) { struct nand_chip *chip; diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index cc728b12de82..a8e403eebedb 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -162,7 +162,7 @@ static const char *part_probes[] = { "cmdlinepart", NULL }; /* * Probe for the NAND device. */ -static int __devinit socrates_nand_probe(struct of_device *ofdev, +static int __devinit socrates_nand_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct socrates_nand_host *host; @@ -276,7 +276,7 @@ out: /* * Remove a NAND device. */ -static int __devexit socrates_nand_remove(struct of_device *ofdev) +static int __devexit socrates_nand_remove(struct platform_device *ofdev) { struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev); struct mtd_info *mtd = &host->mtd; diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index af753936e835..b1bdc909090f 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -38,7 +38,7 @@ struct mpc5xxx_can_data { unsigned int type; - u32 (*get_clock)(struct of_device *ofdev, const char *clock_name, + u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc); }; @@ -48,7 +48,7 @@ static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = { {} }; -static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -101,7 +101,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, return freq; } #else /* !CONFIG_PPC_MPC52xx */ -static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -129,7 +129,7 @@ static struct of_device_id __devinitdata mpc512x_clock_ids[] = { {} }; -static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -239,7 +239,7 @@ exit_unmap: return freq; } #else /* !CONFIG_PPC_MPC512x */ -static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, +static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, const char *clock_name, int *mscan_clksrc) { @@ -247,7 +247,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, } #endif /* CONFIG_PPC_MPC512x */ -static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, +static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; @@ -317,7 +317,7 @@ exit_unmap_mem: return err; } -static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) +static int __devexit mpc5xxx_can_remove(struct platform_device *ofdev) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct mscan_priv *priv = netdev_priv(dev); @@ -334,7 +334,7 @@ static int __devexit mpc5xxx_can_remove(struct of_device *ofdev) #ifdef CONFIG_PM static struct mscan_regs saved_regs; -static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) +static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct mscan_priv *priv = netdev_priv(dev); @@ -345,7 +345,7 @@ static int mpc5xxx_can_suspend(struct of_device *ofdev, pm_message_t state) return 0; } -static int mpc5xxx_can_resume(struct of_device *ofdev) +static int mpc5xxx_can_resume(struct platform_device *ofdev) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct mscan_priv *priv = netdev_priv(dev); diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index ac1a83d7c204..5bfccfdf3bbb 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -67,7 +67,7 @@ static void sja1000_ofp_write_reg(const struct sja1000_priv *priv, out_8(priv->reg_base + reg, val); } -static int __devexit sja1000_ofp_remove(struct of_device *ofdev) +static int __devexit sja1000_ofp_remove(struct platform_device *ofdev) { struct net_device *dev = dev_get_drvdata(&ofdev->dev); struct sja1000_priv *priv = netdev_priv(dev); @@ -87,7 +87,7 @@ static int __devexit sja1000_ofp_remove(struct of_device *ofdev) return 0; } -static int __devinit sja1000_ofp_probe(struct of_device *ofdev, +static int __devinit sja1000_ofp_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct device_node *np = ofdev->dev.of_node; diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0060e422f171..99a929964e3c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -413,7 +413,7 @@ struct ehea_port_res { struct ehea_adapter { u64 handle; - struct of_device *ofdev; + struct platform_device *ofdev; struct ehea_port *port[EHEA_MAX_PORTS]; struct ehea_eq *neq; /* notification event queue */ struct tasklet_struct neq_tasklet; @@ -465,7 +465,7 @@ struct ehea_port { struct net_device *netdev; struct net_device_stats stats; struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; - struct of_device ofdev; /* Open Firmware Device */ + struct platform_device ofdev; /* Open Firmware Device */ struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ struct vlan_group *vgrp; struct ehea_eq *qp_eq; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 3beba70b7dea..897719b49f96 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -107,10 +107,10 @@ struct ehea_fw_handle_array ehea_fw_handles; struct ehea_bcmc_reg_array ehea_bcmc_regs; -static int __devinit ehea_probe_adapter(struct of_device *dev, +static int __devinit ehea_probe_adapter(struct platform_device *dev, const struct of_device_id *id); -static int __devexit ehea_remove(struct of_device *dev); +static int __devexit ehea_remove(struct platform_device *dev); static struct of_device_id ehea_device_table[] = { { @@ -3376,7 +3376,7 @@ static ssize_t ehea_remove_port(struct device *dev, static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); -int ehea_create_device_sysfs(struct of_device *dev) +int ehea_create_device_sysfs(struct platform_device *dev) { int ret = device_create_file(&dev->dev, &dev_attr_probe_port); if (ret) @@ -3387,13 +3387,13 @@ out: return ret; } -void ehea_remove_device_sysfs(struct of_device *dev) +void ehea_remove_device_sysfs(struct platform_device *dev) { device_remove_file(&dev->dev, &dev_attr_probe_port); device_remove_file(&dev->dev, &dev_attr_remove_port); } -static int __devinit ehea_probe_adapter(struct of_device *dev, +static int __devinit ehea_probe_adapter(struct platform_device *dev, const struct of_device_id *id) { struct ehea_adapter *adapter; @@ -3492,7 +3492,7 @@ out: return ret; } -static int __devexit ehea_remove(struct of_device *dev) +static int __devexit ehea_remove(struct platform_device *dev) { struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); int i; diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index d1a5b17b2a95..e3e10b4add9c 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -850,7 +850,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = { /* ======================================================================== */ static int __devinit -mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) +mpc52xx_fec_probe(struct platform_device *op, const struct of_device_id *match) { int rv; struct net_device *ndev; @@ -995,7 +995,7 @@ err_netdev: } static int -mpc52xx_fec_remove(struct of_device *op) +mpc52xx_fec_remove(struct platform_device *op) { struct net_device *ndev; struct mpc52xx_fec_priv *priv; @@ -1025,7 +1025,7 @@ mpc52xx_fec_remove(struct of_device *op) } #ifdef CONFIG_PM -static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) +static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) { struct net_device *dev = dev_get_drvdata(&op->dev); @@ -1035,7 +1035,7 @@ static int mpc52xx_fec_of_suspend(struct of_device *op, pm_message_t state) return 0; } -static int mpc52xx_fec_of_resume(struct of_device *op) +static int mpc52xx_fec_of_resume(struct platform_device *op) { struct net_device *dev = dev_get_drvdata(&op->dev); diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index dbaf72cbb233..0b4cb6f15984 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c @@ -61,7 +61,7 @@ static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, data | FEC_MII_WRITE_FRAME); } -static int mpc52xx_fec_mdio_probe(struct of_device *of, +static int mpc52xx_fec_mdio_probe(struct platform_device *of, const struct of_device_id *match) { struct device *dev = &of->dev; @@ -122,7 +122,7 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, return err; } -static int mpc52xx_fec_mdio_remove(struct of_device *of) +static int mpc52xx_fec_mdio_remove(struct platform_device *of) { struct device *dev = &of->dev; struct mii_bus *bus = dev_get_drvdata(dev); diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index f08cff9020bd..d6e3111959ab 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -997,7 +997,7 @@ static const struct net_device_ops fs_enet_netdev_ops = { #endif }; -static int __devinit fs_enet_probe(struct of_device *ofdev, +static int __devinit fs_enet_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct net_device *ndev; @@ -1105,7 +1105,7 @@ out_free_fpi: return ret; } -static int fs_enet_remove(struct of_device *ofdev) +static int fs_enet_remove(struct platform_device *ofdev) { struct net_device *ndev = dev_get_drvdata(&ofdev->dev); struct fs_enet_private *fep = netdev_priv(ndev); diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 48e91b6242ce..7a84e45487e8 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -84,7 +84,7 @@ static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op) static int do_pd_setup(struct fs_enet_private *fep) { - struct of_device *ofdev = to_of_device(fep->dev); + struct platform_device *ofdev = to_platform_device(fep->dev); struct fs_platform_info *fpi = fep->fpi; int ret = -EINVAL; diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 7ca1642276d0..61035fc5599b 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -96,7 +96,7 @@ static int whack_reset(struct fec __iomem *fecp) static int do_pd_setup(struct fs_enet_private *fep) { - struct of_device *ofdev = to_of_device(fep->dev); + struct platform_device *ofdev = to_platform_device(fep->dev); fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); if (fep->interrupt == NO_IRQ) diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index a3c44544846d..22a02a767069 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -96,7 +96,7 @@ static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op) static int do_pd_setup(struct fs_enet_private *fep) { - struct of_device *ofdev = to_of_device(fep->dev); + struct platform_device *ofdev = to_platform_device(fep->dev); fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); if (fep->interrupt == NO_IRQ) diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 3607340f3da7..3cda2b515471 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c @@ -150,7 +150,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus, return 0; } -static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, +static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct mii_bus *new_bus; @@ -200,7 +200,7 @@ out: return ret; } -static int fs_enet_mdio_remove(struct of_device *ofdev) +static int fs_enet_mdio_remove(struct platform_device *ofdev) { struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); struct bb_info *bitbang = bus->priv; diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index bddffd169b93..dbb9c48623df 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -101,7 +101,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus) return 0; } -static int __devinit fs_enet_mdio_probe(struct of_device *ofdev, +static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct resource res; @@ -192,7 +192,7 @@ out: return ret; } -static int fs_enet_mdio_remove(struct of_device *ofdev) +static int fs_enet_mdio_remove(struct platform_device *ofdev) { struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); struct fec_info *fec = bus->priv; diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c index f53f850b6418..d4bf91aac25f 100644 --- a/drivers/net/fsl_pq_mdio.c +++ b/drivers/net/fsl_pq_mdio.c @@ -265,7 +265,7 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) #endif -static int fsl_pq_mdio_probe(struct of_device *ofdev, +static int fsl_pq_mdio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -425,7 +425,7 @@ err_free_priv: } -static int fsl_pq_mdio_remove(struct of_device *ofdev) +static int fsl_pq_mdio_remove(struct platform_device *ofdev) { struct device *device = &ofdev->dev; struct mii_bus *bus = dev_get_drvdata(device); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a1b6301bc674..4f7c3f3ca234 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -122,9 +122,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id); static void adjust_link(struct net_device *dev); static void init_registers(struct net_device *dev); static int init_phy(struct net_device *dev); -static int gfar_probe(struct of_device *ofdev, +static int gfar_probe(struct platform_device *ofdev, const struct of_device_id *match); -static int gfar_remove(struct of_device *ofdev); +static int gfar_remove(struct platform_device *ofdev); static void free_skb_resources(struct gfar_private *priv); static void gfar_set_multi(struct net_device *dev); static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); @@ -605,7 +605,7 @@ static int gfar_parse_group(struct device_node *np, return 0; } -static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev) +static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) { const char *model; const char *ctype; @@ -959,7 +959,7 @@ static void gfar_detect_errata(struct gfar_private *priv) /* Set up the ethernet device structure, private data, * and anything else we need before we start */ -static int gfar_probe(struct of_device *ofdev, +static int gfar_probe(struct platform_device *ofdev, const struct of_device_id *match) { u32 tempval; @@ -1238,7 +1238,7 @@ register_fail: return err; } -static int gfar_remove(struct of_device *ofdev) +static int gfar_remove(struct platform_device *ofdev) { struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 710810e2adb4..68984eb88ae0 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -1054,7 +1054,7 @@ struct gfar_private { struct device_node *node; struct net_device *ndev; - struct of_device *ofdev; + struct platform_device *ofdev; enum gfar_errata errata; struct gfar_priv_grp gfargrp[MAXGROUPS]; diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 4d09eab3548e..9ec4b7f28ca4 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -1373,7 +1373,7 @@ error: } /* Initialize the GRETH MAC */ -static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_device_id *match) +static int __devinit greth_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct net_device *dev; struct greth_private *greth; @@ -1572,7 +1572,7 @@ error1: return err; } -static int __devexit greth_of_remove(struct of_device *of_dev) +static int __devexit greth_of_remove(struct platform_device *of_dev) { struct net_device *ndev = dev_get_drvdata(&of_dev->dev); struct greth_private *greth = netdev_priv(ndev); diff --git a/drivers/net/greth.h b/drivers/net/greth.h index 973388d6abca..03ad903cd676 100644 --- a/drivers/net/greth.h +++ b/drivers/net/greth.h @@ -118,7 +118,7 @@ struct greth_private { int irq; - struct device *dev; /* Pointer to of_device->dev */ + struct device *dev; /* Pointer to platform_device->dev */ struct net_device *netdev; struct napi_struct napi; spinlock_t devlock; diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index eeec7bc2ce74..3506fd6ad726 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2245,7 +2245,7 @@ static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) struct emac_depentry { u32 phandle; struct device_node *node; - struct of_device *ofdev; + struct platform_device *ofdev; void *drvdata; }; @@ -2719,7 +2719,7 @@ static const struct net_device_ops emac_gige_netdev_ops = { .ndo_change_mtu = emac_change_mtu, }; -static int __devinit emac_probe(struct of_device *ofdev, +static int __devinit emac_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct net_device *ndev; @@ -2941,7 +2941,7 @@ static int __devinit emac_probe(struct of_device *ofdev, return err; } -static int __devexit emac_remove(struct of_device *ofdev) +static int __devexit emac_remove(struct platform_device *ofdev) { struct emac_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index b1cbe6fdfc7a..9e37e3d9c51d 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h @@ -170,12 +170,12 @@ struct emac_instance { struct net_device *ndev; struct resource rsrc_regs; struct emac_regs __iomem *emacp; - struct of_device *ofdev; + struct platform_device *ofdev; struct device_node **blist; /* bootlist entry */ /* MAL linkage */ u32 mal_ph; - struct of_device *mal_dev; + struct platform_device *mal_dev; u32 mal_rx_chan; u32 mal_tx_chan; struct mal_instance *mal; @@ -196,24 +196,24 @@ struct emac_instance { /* Shared MDIO if any */ u32 mdio_ph; - struct of_device *mdio_dev; + struct platform_device *mdio_dev; struct emac_instance *mdio_instance; struct mutex mdio_lock; /* ZMII infos if any */ u32 zmii_ph; u32 zmii_port; - struct of_device *zmii_dev; + struct platform_device *zmii_dev; /* RGMII infos if any */ u32 rgmii_ph; u32 rgmii_port; - struct of_device *rgmii_dev; + struct platform_device *rgmii_dev; /* TAH infos if any */ u32 tah_ph; u32 tah_port; - struct of_device *tah_dev; + struct platform_device *tah_dev; /* IRQs */ int wol_irq; diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index fcff9e0bd382..d5717e2123e1 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c @@ -517,7 +517,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf) return regs + 1; } -static int __devinit mal_probe(struct of_device *ofdev, +static int __devinit mal_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct mal_instance *mal; @@ -730,7 +730,7 @@ static int __devinit mal_probe(struct of_device *ofdev, return err; } -static int __devexit mal_remove(struct of_device *ofdev) +static int __devexit mal_remove(struct platform_device *ofdev) { struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 9ededfbf0726..66084214bf45 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h @@ -210,7 +210,7 @@ struct mal_instance { dma_addr_t bd_dma; struct mal_descriptor *bd_virt; - struct of_device *ofdev; + struct platform_device *ofdev; int index; spinlock_t lock; diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 108919bcdf13..dd61798897ac 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c @@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input) } } -int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) +int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -122,7 +122,7 @@ int __devinit rgmii_attach(struct of_device *ofdev, int input, int mode) return 0; } -void rgmii_set_speed(struct of_device *ofdev, int input, int speed) +void rgmii_set_speed(struct platform_device *ofdev, int input, int speed) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -144,7 +144,7 @@ void rgmii_set_speed(struct of_device *ofdev, int input, int speed) mutex_unlock(&dev->lock); } -void rgmii_get_mdio(struct of_device *ofdev, int input) +void rgmii_get_mdio(struct platform_device *ofdev, int input) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -165,7 +165,7 @@ void rgmii_get_mdio(struct of_device *ofdev, int input) DBG2(dev, " fer = 0x%08x\n", fer); } -void rgmii_put_mdio(struct of_device *ofdev, int input) +void rgmii_put_mdio(struct platform_device *ofdev, int input) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p = dev->base; @@ -186,7 +186,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) mutex_unlock(&dev->lock); } -void rgmii_detach(struct of_device *ofdev, int input) +void rgmii_detach(struct platform_device *ofdev, int input) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct rgmii_regs __iomem *p; @@ -206,13 +206,13 @@ void rgmii_detach(struct of_device *ofdev, int input) mutex_unlock(&dev->lock); } -int rgmii_get_regs_len(struct of_device *ofdev) +int rgmii_get_regs_len(struct platform_device *ofdev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct rgmii_regs); } -void *rgmii_dump_regs(struct of_device *ofdev, void *buf) +void *rgmii_dump_regs(struct platform_device *ofdev, void *buf) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct emac_ethtool_regs_subhdr *hdr = buf; @@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct of_device *ofdev, void *buf) } -static int __devinit rgmii_probe(struct of_device *ofdev, +static int __devinit rgmii_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -293,7 +293,7 @@ static int __devinit rgmii_probe(struct of_device *ofdev, return rc; } -static int __devexit rgmii_remove(struct of_device *ofdev) +static int __devexit rgmii_remove(struct platform_device *ofdev) { struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/rgmii.h b/drivers/net/ibm_newemac/rgmii.h index c4a4b358a270..d69799049865 100644 --- a/drivers/net/ibm_newemac/rgmii.h +++ b/drivers/net/ibm_newemac/rgmii.h @@ -51,20 +51,20 @@ struct rgmii_instance { int users; /* OF device instance */ - struct of_device *ofdev; + struct platform_device *ofdev; }; #ifdef CONFIG_IBM_NEW_EMAC_RGMII extern int rgmii_init(void); extern void rgmii_exit(void); -extern int rgmii_attach(struct of_device *ofdev, int input, int mode); -extern void rgmii_detach(struct of_device *ofdev, int input); -extern void rgmii_get_mdio(struct of_device *ofdev, int input); -extern void rgmii_put_mdio(struct of_device *ofdev, int input); -extern void rgmii_set_speed(struct of_device *ofdev, int input, int speed); -extern int rgmii_get_regs_len(struct of_device *ofdev); -extern void *rgmii_dump_regs(struct of_device *ofdev, void *buf); +extern int rgmii_attach(struct platform_device *ofdev, int input, int mode); +extern void rgmii_detach(struct platform_device *ofdev, int input); +extern void rgmii_get_mdio(struct platform_device *ofdev, int input); +extern void rgmii_put_mdio(struct platform_device *ofdev, int input); +extern void rgmii_set_speed(struct platform_device *ofdev, int input, int speed); +extern int rgmii_get_regs_len(struct platform_device *ofdev); +extern void *rgmii_dump_regs(struct platform_device *ofdev, void *buf); #else diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c index 044637144c43..299aa49490c0 100644 --- a/drivers/net/ibm_newemac/tah.c +++ b/drivers/net/ibm_newemac/tah.c @@ -23,7 +23,7 @@ #include "emac.h" #include "core.h" -int __devinit tah_attach(struct of_device *ofdev, int channel) +int __devinit tah_attach(struct platform_device *ofdev, int channel) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel) return 0; } -void tah_detach(struct of_device *ofdev, int channel) +void tah_detach(struct platform_device *ofdev, int channel) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -44,7 +44,7 @@ void tah_detach(struct of_device *ofdev, int channel) mutex_unlock(&dev->lock); } -void tah_reset(struct of_device *ofdev) +void tah_reset(struct platform_device *ofdev) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); struct tah_regs __iomem *p = dev->base; @@ -66,13 +66,13 @@ void tah_reset(struct of_device *ofdev) TAH_MR_DIG); } -int tah_get_regs_len(struct of_device *ofdev) +int tah_get_regs_len(struct platform_device *ofdev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct tah_regs); } -void *tah_dump_regs(struct of_device *ofdev, void *buf) +void *tah_dump_regs(struct platform_device *ofdev, void *buf) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); struct emac_ethtool_regs_subhdr *hdr = buf; @@ -87,7 +87,7 @@ void *tah_dump_regs(struct of_device *ofdev, void *buf) return regs + 1; } -static int __devinit tah_probe(struct of_device *ofdev, +static int __devinit tah_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -139,7 +139,7 @@ static int __devinit tah_probe(struct of_device *ofdev, return rc; } -static int __devexit tah_remove(struct of_device *ofdev) +static int __devexit tah_remove(struct platform_device *ofdev) { struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/tah.h b/drivers/net/ibm_newemac/tah.h index a068b5658dad..61dbeca006d1 100644 --- a/drivers/net/ibm_newemac/tah.h +++ b/drivers/net/ibm_newemac/tah.h @@ -48,7 +48,7 @@ struct tah_instance { int users; /* OF device instance */ - struct of_device *ofdev; + struct platform_device *ofdev; }; @@ -74,11 +74,11 @@ struct tah_instance { extern int tah_init(void); extern void tah_exit(void); -extern int tah_attach(struct of_device *ofdev, int channel); -extern void tah_detach(struct of_device *ofdev, int channel); -extern void tah_reset(struct of_device *ofdev); -extern int tah_get_regs_len(struct of_device *ofdev); -extern void *tah_dump_regs(struct of_device *ofdev, void *buf); +extern int tah_attach(struct platform_device *ofdev, int channel); +extern void tah_detach(struct platform_device *ofdev, int channel); +extern void tah_reset(struct platform_device *ofdev); +extern int tah_get_regs_len(struct platform_device *ofdev); +extern void *tah_dump_regs(struct platform_device *ofdev, void *buf); #else diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c index 046dcd069c45..34ed6ee8ca8a 100644 --- a/drivers/net/ibm_newemac/zmii.c +++ b/drivers/net/ibm_newemac/zmii.c @@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input) } } -int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) +int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct zmii_regs __iomem *p = dev->base; @@ -148,7 +148,7 @@ int __devinit zmii_attach(struct of_device *ofdev, int input, int *mode) return 0; } -void zmii_get_mdio(struct of_device *ofdev, int input) +void zmii_get_mdio(struct platform_device *ofdev, int input) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); u32 fer; @@ -161,7 +161,7 @@ void zmii_get_mdio(struct of_device *ofdev, int input) out_be32(&dev->base->fer, fer | ZMII_FER_MDI(input)); } -void zmii_put_mdio(struct of_device *ofdev, int input) +void zmii_put_mdio(struct platform_device *ofdev, int input) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -170,7 +170,7 @@ void zmii_put_mdio(struct of_device *ofdev, int input) } -void zmii_set_speed(struct of_device *ofdev, int input, int speed) +void zmii_set_speed(struct platform_device *ofdev, int input, int speed) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); u32 ssr; @@ -191,7 +191,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed) mutex_unlock(&dev->lock); } -void zmii_detach(struct of_device *ofdev, int input) +void zmii_detach(struct platform_device *ofdev, int input) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); @@ -210,13 +210,13 @@ void zmii_detach(struct of_device *ofdev, int input) mutex_unlock(&dev->lock); } -int zmii_get_regs_len(struct of_device *ofdev) +int zmii_get_regs_len(struct platform_device *ofdev) { return sizeof(struct emac_ethtool_regs_subhdr) + sizeof(struct zmii_regs); } -void *zmii_dump_regs(struct of_device *ofdev, void *buf) +void *zmii_dump_regs(struct platform_device *ofdev, void *buf) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); struct emac_ethtool_regs_subhdr *hdr = buf; @@ -231,7 +231,7 @@ void *zmii_dump_regs(struct of_device *ofdev, void *buf) return regs + 1; } -static int __devinit zmii_probe(struct of_device *ofdev, +static int __devinit zmii_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -286,7 +286,7 @@ static int __devinit zmii_probe(struct of_device *ofdev, return rc; } -static int __devexit zmii_remove(struct of_device *ofdev) +static int __devexit zmii_remove(struct platform_device *ofdev) { struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/net/ibm_newemac/zmii.h b/drivers/net/ibm_newemac/zmii.h index 6c9beba0c4b6..1333fa2b2781 100644 --- a/drivers/net/ibm_newemac/zmii.h +++ b/drivers/net/ibm_newemac/zmii.h @@ -48,20 +48,20 @@ struct zmii_instance { u32 fer_save; /* OF device instance */ - struct of_device *ofdev; + struct platform_device *ofdev; }; #ifdef CONFIG_IBM_NEW_EMAC_ZMII extern int zmii_init(void); extern void zmii_exit(void); -extern int zmii_attach(struct of_device *ofdev, int input, int *mode); -extern void zmii_detach(struct of_device *ofdev, int input); -extern void zmii_get_mdio(struct of_device *ofdev, int input); -extern void zmii_put_mdio(struct of_device *ofdev, int input); -extern void zmii_set_speed(struct of_device *ofdev, int input, int speed); -extern int zmii_get_regs_len(struct of_device *ocpdev); -extern void *zmii_dump_regs(struct of_device *ofdev, void *buf); +extern int zmii_attach(struct platform_device *ofdev, int input, int *mode); +extern void zmii_detach(struct platform_device *ofdev, int input); +extern void zmii_get_mdio(struct platform_device *ofdev, int input); +extern void zmii_put_mdio(struct platform_device *ofdev, int input); +extern void zmii_set_speed(struct platform_device *ofdev, int input, int speed); +extern int zmii_get_regs_len(struct platform_device *ocpdev); +extern void *zmii_dump_regs(struct platform_device *ofdev, void *buf); #else # define zmii_init() 0 diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 4eea3f70c5cf..c7b624711f5e 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -159,7 +159,7 @@ static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value) * temac_dcr_setup - If the DMA is DCR based, then setup the address and * I/O functions */ -static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, +static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, struct device_node *np) { unsigned int dcrs; @@ -184,7 +184,7 @@ static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, * temac_dcr_setup - This is a stub for when DCR is not supported, * such as with MicroBlaze */ -static int temac_dcr_setup(struct temac_local *lp, struct of_device *op, +static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, struct device_node *np) { return -1; @@ -952,7 +952,7 @@ static const struct attribute_group temac_attr_group = { }; static int __init -temac_of_probe(struct of_device *op, const struct of_device_id *match) +temac_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *np; struct temac_local *lp; @@ -1094,7 +1094,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) return rc; } -static int __devexit temac_of_remove(struct of_device *op) +static int __devexit temac_of_remove(struct platform_device *op) { struct net_device *ndev = dev_get_drvdata(&op->dev); struct temac_local *lp = netdev_priv(ndev); diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 04e552aa14ec..617f898ba5f0 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -926,7 +926,7 @@ static const struct net_device_ops myri_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit myri_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; static unsigned version_printed; @@ -1124,7 +1124,7 @@ err: return -ENODEV; } -static int __devexit myri_sbus_remove(struct of_device *op) +static int __devexit myri_sbus_remove(struct platform_device *op) { struct myri_eth *mp = dev_get_drvdata(&op->dev); struct net_device *net_dev = mp->dev; diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index ff363e95d9cf..80a2fa5cf757 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h @@ -288,7 +288,7 @@ struct myri_eth { struct myri_eeprom eeprom; /* Local copy of EEPROM. */ unsigned int reg_size; /* Size of register space. */ unsigned int shmem_base; /* Offset to shared ram. */ - struct of_device *myri_op; /* Our OF device struct. */ + struct platform_device *myri_op; /* Our OF device struct. */ }; /* We use this to acquire receive skb's that we can DMA directly into. */ diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 404f2d552888..bc695d53cdcc 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -9103,7 +9103,7 @@ retry: static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map) { #ifdef CONFIG_SPARC64 - struct of_device *op = np->op; + struct platform_device *op = np->op; const u32 *int_prop; int i; @@ -9688,7 +9688,7 @@ static void __devinit niu_driver_version(void) static struct net_device * __devinit niu_alloc_and_init( struct device *gen_dev, struct pci_dev *pdev, - struct of_device *op, const struct niu_ops *ops, + struct platform_device *op, const struct niu_ops *ops, u8 port) { struct net_device *dev; @@ -10064,7 +10064,7 @@ static const struct niu_ops niu_phys_ops = { .unmap_single = niu_phys_unmap_single, }; -static int __devinit niu_of_probe(struct of_device *op, +static int __devinit niu_of_probe(struct platform_device *op, const struct of_device_id *match) { union niu_parent_id parent_id; @@ -10179,7 +10179,7 @@ err_out: return err; } -static int __devexit niu_of_remove(struct of_device *op) +static int __devexit niu_of_remove(struct platform_device *op) { struct net_device *dev = dev_get_drvdata(&op->dev); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index fc5fef2a8175..f62c7b717bc8 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -188,7 +188,7 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev) #ifdef CONFIG_OF_GPIO -static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, +static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct mdio_gpio_platform_data *pdata; @@ -224,7 +224,7 @@ out_free: return -ENODEV; } -static int __devexit mdio_ofgpio_remove(struct of_device *ofdev) +static int __devexit mdio_ofgpio_remove(struct platform_device *ofdev) { mdio_gpio_bus_destroy(&ofdev->dev); kfree(ofdev->dev.platform_data); diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 09c071bd6ad4..618643e3ca3e 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -97,7 +97,7 @@ static int qec_global_reset(void __iomem *gregs) static void qec_init(struct bigmac *bp) { - struct of_device *qec_op = bp->qec_op; + struct platform_device *qec_op = bp->qec_op; void __iomem *gregs = bp->gregs; u8 bsizes = bp->bigmac_bursts; u32 regval; @@ -1083,8 +1083,8 @@ static const struct net_device_ops bigmac_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit bigmac_ether_init(struct of_device *op, - struct of_device *qec_op) +static int __devinit bigmac_ether_init(struct platform_device *op, + struct platform_device *qec_op) { static int version_printed; struct net_device *dev; @@ -1242,25 +1242,25 @@ fail_and_cleanup: /* QEC can be the parent of either QuadEthernet or a BigMAC. We want * the latter. */ -static int __devinit bigmac_sbus_probe(struct of_device *op, +static int __devinit bigmac_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device *parent = op->dev.parent; - struct of_device *qec_op; + struct platform_device *qec_op; - qec_op = to_of_device(parent); + qec_op = to_platform_device(parent); return bigmac_ether_init(op, qec_op); } -static int __devexit bigmac_sbus_remove(struct of_device *op) +static int __devexit bigmac_sbus_remove(struct platform_device *op) { struct bigmac *bp = dev_get_drvdata(&op->dev); struct device *parent = op->dev.parent; struct net_device *net_dev = bp->dev; - struct of_device *qec_op; + struct platform_device *qec_op; - qec_op = to_of_device(parent); + qec_op = to_platform_device(parent); unregister_netdev(net_dev); diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index 8840bc0b840b..8db88945b889 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h @@ -329,8 +329,8 @@ struct bigmac { unsigned int timer_ticks; struct net_device_stats enet_stats; - struct of_device *qec_op; - struct of_device *bigmac_op; + struct platform_device *qec_op; + struct platform_device *bigmac_op; struct net_device *dev; }; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index eec443f64079..bd0df1c14955 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1591,7 +1591,7 @@ static int happy_meal_init(struct happy_meal *hp) */ #ifdef CONFIG_SBUS if ((hp->happy_flags & HFLAG_PCI) == 0) { - struct of_device *op = hp->happy_dev; + struct platform_device *op = hp->happy_dev; if (sbus_can_dma_64bit()) { sbus_set_sbus64(&op->dev, hp->happy_bursts); @@ -2480,7 +2480,7 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info #ifdef CONFIG_SBUS else { const struct linux_prom_registers *regs; - struct of_device *op = hp->happy_dev; + struct platform_device *op = hp->happy_dev; regs = of_get_property(op->dev.of_node, "regs", NULL); if (regs) sprintf(info->bus_info, "SBUS:%d", @@ -2515,13 +2515,13 @@ static int hme_version_printed; * * Return NULL on failure. */ -static struct quattro * __devinit quattro_sbus_find(struct of_device *child) +static struct quattro * __devinit quattro_sbus_find(struct platform_device *child) { struct device *parent = child->dev.parent; - struct of_device *op; + struct platform_device *op; struct quattro *qp; - op = to_of_device(parent); + op = to_platform_device(parent); qp = dev_get_drvdata(&op->dev); if (qp) return qp; @@ -2551,7 +2551,7 @@ static int __init quattro_sbus_register_irqs(void) struct quattro *qp; for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - struct of_device *op = qp->quattro_dev; + struct platform_device *op = qp->quattro_dev; int err, qfe_slot, skip = 0; for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { @@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void) struct quattro *qp; for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { - struct of_device *op = qp->quattro_dev; + struct platform_device *op = qp->quattro_dev; int qfe_slot, skip = 0; for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) { @@ -2639,7 +2639,7 @@ static const struct net_device_ops hme_netdev_ops = { }; #ifdef CONFIG_SBUS -static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) +static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe) { struct device_node *dp = op->dev.of_node, *sbus_dp; struct quattro *qp = NULL; @@ -2648,7 +2648,7 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) int i, qfe_slot = -1; int err = -ENODEV; - sbus_dp = to_of_device(op->dev.parent)->dev.of_node; + sbus_dp = op->dev.parent->of_node; /* We can match PCI devices too, do not accept those here. */ if (strcmp(sbus_dp->name, "sbus")) @@ -3235,7 +3235,7 @@ static void happy_meal_pci_exit(void) #endif #ifdef CONFIG_SBUS -static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit hme_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; const char *model = of_get_property(dp, "model", NULL); @@ -3247,7 +3247,7 @@ static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device return happy_meal_sbus_probe_one(op, is_qfe); } -static int __devexit hme_sbus_remove(struct of_device *op) +static int __devexit hme_sbus_remove(struct platform_device *op) { struct happy_meal *hp = dev_get_drvdata(&op->dev); struct net_device *net_dev = hp->dev; diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index efd2ca0fcad3..756b5bf3aa89 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h @@ -407,7 +407,7 @@ struct happy_meal { void (*write_rxd)(struct happy_meal_rxd *, u32, u32); #endif - /* This is either an of_device or a pci_dev. */ + /* This is either an platform_device or a pci_dev. */ void *happy_dev; struct device *dma_dev; diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index ee364fa75634..8dcb858f2168 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -250,7 +250,7 @@ struct lance_private { int rx_new, tx_new; int rx_old, tx_old; - struct of_device *ledma; /* If set this points to ledma */ + struct platform_device *ledma; /* If set this points to ledma */ char tpe; /* cable-selection is TPE */ char auto_select; /* cable-selection by carrier */ char burst_sizes; /* ledma SBus burst sizes */ @@ -265,8 +265,8 @@ struct lance_private { char *name; dma_addr_t init_block_dvma; struct net_device *dev; /* Backpointer */ - struct of_device *op; - struct of_device *lebuffer; + struct platform_device *op; + struct platform_device *lebuffer; struct timer_list multicast_timer; }; @@ -1272,7 +1272,7 @@ static void lance_free_hwresources(struct lance_private *lp) if (lp->lregs) of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); if (lp->dregs) { - struct of_device *ledma = lp->ledma; + struct platform_device *ledma = lp->ledma; of_iounmap(&ledma->resource[0], lp->dregs, resource_size(&ledma->resource[0])); @@ -1319,9 +1319,9 @@ static const struct net_device_ops sparc_lance_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit sparc_lance_probe_one(struct of_device *op, - struct of_device *ledma, - struct of_device *lebuffer) +static int __devinit sparc_lance_probe_one(struct platform_device *op, + struct platform_device *ledma, + struct platform_device *lebuffer) { struct device_node *dp = op->dev.of_node; static unsigned version_printed; @@ -1503,9 +1503,9 @@ fail: return -ENODEV; } -static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit sunlance_sbus_probe(struct platform_device *op, const struct of_device_id *match) { - struct of_device *parent = to_of_device(op->dev.parent); + struct platform_device *parent = to_platform_device(op->dev.parent); struct device_node *parent_dp = parent->dev.of_node; int err; @@ -1519,7 +1519,7 @@ static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_d return err; } -static int __devexit sunlance_sbus_remove(struct of_device *op) +static int __devexit sunlance_sbus_remove(struct platform_device *op) { struct lance_private *lp = dev_get_drvdata(&op->dev); struct net_device *net_dev = lp->dev; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 5f84a5dadedd..72e65d4666ef 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -689,7 +689,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { const struct linux_prom_registers *regs; struct sunqe *qep = netdev_priv(dev); - struct of_device *op; + struct platform_device *op; strcpy(info->driver, "sunqe"); strcpy(info->version, "3.0"); @@ -720,7 +720,7 @@ static const struct ethtool_ops qe_ethtool_ops = { }; /* This is only called once at boot time for each card probed. */ -static void qec_init_once(struct sunqec *qecp, struct of_device *op) +static void qec_init_once(struct sunqec *qecp, struct platform_device *op) { u8 bsizes = qecp->qec_bursts; @@ -770,9 +770,9 @@ static u8 __devinit qec_get_burst(struct device_node *dp) return bsizes; } -static struct sunqec * __devinit get_qec(struct of_device *child) +static struct sunqec * __devinit get_qec(struct platform_device *child) { - struct of_device *op = to_of_device(child->dev.parent); + struct platform_device *op = to_platform_device(child->dev.parent); struct sunqec *qecp; qecp = dev_get_drvdata(&op->dev); @@ -836,7 +836,7 @@ static const struct net_device_ops qec_ops = { .ndo_validate_addr = eth_validate_addr, }; -static int __devinit qec_ether_init(struct of_device *op) +static int __devinit qec_ether_init(struct platform_device *op) { static unsigned version_printed; struct net_device *dev; @@ -941,12 +941,12 @@ fail: return res; } -static int __devinit qec_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit qec_sbus_probe(struct platform_device *op, const struct of_device_id *match) { return qec_ether_init(op); } -static int __devexit qec_sbus_remove(struct of_device *op) +static int __devexit qec_sbus_remove(struct platform_device *op) { struct sunqe *qp = dev_get_drvdata(&op->dev); struct net_device *net_dev = qp->dev; @@ -997,7 +997,7 @@ static void __exit qec_exit(void) while (root_qec_dev) { struct sunqec *next = root_qec_dev->next_module; - struct of_device *op = root_qec_dev->op; + struct platform_device *op = root_qec_dev->op; free_irq(op->archdata.irqs[0], (void *) root_qec_dev); of_iounmap(&op->resource[0], root_qec_dev->gregs, diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h index 5813a7b2faa5..581781b6b2fa 100644 --- a/drivers/net/sunqe.h +++ b/drivers/net/sunqe.h @@ -314,7 +314,7 @@ struct sunqec { void __iomem *gregs; /* QEC Global Registers */ struct sunqe *qes[4]; /* Each child MACE */ unsigned int qec_bursts; /* Support burst sizes */ - struct of_device *op; /* QEC's OF device */ + struct platform_device *op; /* QEC's OF device */ struct sunqec *next_module; /* List of all QECs in system */ }; @@ -342,7 +342,7 @@ struct sunqe { __u32 buffers_dvma; /* DVMA visible address. */ struct sunqec *parent; u8 mconfig; /* Base MACE mconfig value */ - struct of_device *op; /* QE's OF device struct */ + struct platform_device *op; /* QE's OF device struct */ struct net_device *dev; /* QE's netdevice struct */ int channel; /* Who am I? */ }; diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8d532f9b50d0..a4c3f5708246 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3601,7 +3601,7 @@ static void ucc_geth_timeout(struct net_device *dev) #ifdef CONFIG_PM -static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) +static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) { struct net_device *ndev = dev_get_drvdata(&ofdev->dev); struct ucc_geth_private *ugeth = netdev_priv(ndev); @@ -3629,7 +3629,7 @@ static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) return 0; } -static int ucc_geth_resume(struct of_device *ofdev) +static int ucc_geth_resume(struct platform_device *ofdev) { struct net_device *ndev = dev_get_drvdata(&ofdev->dev); struct ucc_geth_private *ugeth = netdev_priv(ndev); @@ -3732,7 +3732,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = { #endif }; -static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) +static int ucc_geth_probe(struct platform_device* ofdev, const struct of_device_id *match) { struct device *device = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; @@ -3954,7 +3954,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma return 0; } -static int ucc_geth_remove(struct of_device* ofdev) +static int ucc_geth_remove(struct platform_device* ofdev) { struct device *device = &ofdev->dev; struct net_device *dev = dev_get_drvdata(device); diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index b2c2f391b29d..ecbbb688eba0 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -1086,7 +1086,7 @@ static void xemaclite_remove_ndev(struct net_device *ndev) * * Return: Value of the parameter if the parameter is found, or 0 otherwise */ -static bool get_bool(struct of_device *ofdev, const char *s) +static bool get_bool(struct platform_device *ofdev, const char *s) { u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL); @@ -1115,7 +1115,7 @@ static struct net_device_ops xemaclite_netdev_ops; * Return: 0, if the driver is bound to the Emaclite device, or * a negative error if there is failure. */ -static int __devinit xemaclite_of_probe(struct of_device *ofdev, +static int __devinit xemaclite_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct resource r_irq; /* Interrupt resources */ @@ -1240,7 +1240,7 @@ error2: * * Return: 0, always. */ -static int __devexit xemaclite_of_remove(struct of_device *of_dev) +static int __devexit xemaclite_of_remove(struct platform_device *of_dev) { struct device *dev = &of_dev->dev; struct net_device *ndev = dev_get_drvdata(dev); diff --git a/drivers/of/device.c b/drivers/of/device.c index 0d8a0644f540..92de0eb74aea 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -14,7 +14,7 @@ * @ids: array of of device match structures to search in * @dev: the of device structure to match against * - * Used by a driver to check whether an of_device present in the + * Used by a driver to check whether an platform_device present in the * system is in its list of supported devices. */ const struct of_device_id *of_match_device(const struct of_device_id *matches, diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 210a6441a066..55ba118f1cf1 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c @@ -286,7 +286,7 @@ static struct parport_operations parport_sunbpp_ops = .owner = THIS_MODULE, }; -static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match) { struct parport_operations *ops; struct bpp_regs __iomem *regs; @@ -351,7 +351,7 @@ out_unmap: return err; } -static int __devexit bpp_remove(struct of_device *op) +static int __devexit bpp_remove(struct platform_device *op) { struct parport *p = dev_get_drvdata(&op->dev); struct parport_operations *ops = p->ops; diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index f94d8281cfb0..546d3024b6f0 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c @@ -44,7 +44,7 @@ struct electra_cf_socket { unsigned present:1; unsigned active:1; - struct of_device *ofdev; + struct platform_device *ofdev; unsigned long mem_phys; void __iomem * mem_base; unsigned long mem_size; @@ -181,7 +181,7 @@ static struct pccard_operations electra_cf_ops = { .set_mem_map = electra_cf_set_mem_map, }; -static int __devinit electra_cf_probe(struct of_device *ofdev, +static int __devinit electra_cf_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device *device = &ofdev->dev; @@ -325,7 +325,7 @@ fail1: } -static int __devexit electra_cf_remove(struct of_device *ofdev) +static int __devexit electra_cf_remove(struct platform_device *ofdev) { struct device *device = &ofdev->dev; struct electra_cf_socket *cf; diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 25e5e30a18af..84a70a59ef95 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c @@ -1150,7 +1150,7 @@ static struct pccard_operations m8xx_services = { .set_mem_map = m8xx_set_mem_map, }; -static int __init m8xx_probe(struct of_device *ofdev, +static int __init m8xx_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct pcmcia_win *w; @@ -1250,7 +1250,7 @@ static int __init m8xx_probe(struct of_device *ofdev, return 0; } -static int m8xx_remove(struct of_device *ofdev) +static int m8xx_remove(struct platform_device *ofdev) { u32 m, i; struct pcmcia_win *w; diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index db5d8c416d26..dfcdf0901d21 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -268,7 +268,7 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { .update_irq_enable = mpc5121_rtc_update_irq_enable, }; -static int __devinit mpc5121_rtc_probe(struct of_device *op, +static int __devinit mpc5121_rtc_probe(struct platform_device *op, const struct of_device_id *match) { struct mpc5121_rtc_data *rtc; @@ -338,7 +338,7 @@ out_free: return err; } -static int __devexit mpc5121_rtc_remove(struct of_device *op) +static int __devexit mpc5121_rtc_remove(struct platform_device *op) { struct mpc5121_rtc_data *rtc = dev_get_drvdata(&op->dev); struct mpc5121_rtc_regs __iomem *regs = rtc->regs; diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 103fdf6b0b89..160e7510aca6 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -443,7 +443,7 @@ static int kenvctrld(void *__unused) return 0; } -static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, +static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op, int temp_idx) { struct bbc_cpu_temperature *tp; @@ -488,7 +488,7 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, tp->fan_todo[FAN_CPU] = FAN_SAME; } -static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op, +static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op, int fan_idx) { struct bbc_fan_control *fp; @@ -559,7 +559,7 @@ static void destroy_all_fans(struct bbc_i2c_bus *bp) int bbc_envctrl_init(struct bbc_i2c_bus *bp) { - struct of_device *op; + struct platform_device *op; int temp_index = 0; int fan_index = 0; int devidx = 0; diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 3e89c313e98d..614a5e114a19 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -51,7 +51,7 @@ * The second controller also connects to the smartcard reader, if present. */ -static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val) +static void set_device_claimage(struct bbc_i2c_bus *bp, struct platform_device *op, int val) { int i; @@ -66,9 +66,9 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, in #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) -struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) +struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) { - struct of_device *op = NULL; + struct platform_device *op = NULL; int curidx = 0, i; for (i = 0; i < NUM_CHILDREN; i++) { @@ -86,7 +86,7 @@ out: return NULL; } -struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op) +struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *op) { struct bbc_i2c_client *client; const u32 *reg; @@ -114,7 +114,7 @@ struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device * void bbc_i2c_detach(struct bbc_i2c_client *client) { struct bbc_i2c_bus *bp = client->bp; - struct of_device *op = client->op; + struct platform_device *op = client->op; release_device(bp, op); kfree(client); @@ -297,7 +297,7 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); } -static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index) +static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, int index) { struct bbc_i2c_bus *bp; struct device_node *dp; @@ -330,7 +330,7 @@ static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int inde for (dp = op->dev.of_node->child; dp && entry < 8; dp = dp->sibling, entry++) { - struct of_device *child_op; + struct platform_device *child_op; child_op = of_find_device_by_node(dp); bp->devs[entry].device = child_op; @@ -361,7 +361,7 @@ fail: extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); -static int __devinit bbc_i2c_probe(struct of_device *op, +static int __devinit bbc_i2c_probe(struct platform_device *op, const struct of_device_id *match) { struct bbc_i2c_bus *bp; @@ -386,7 +386,7 @@ static int __devinit bbc_i2c_probe(struct of_device *op, return err; } -static int __devexit bbc_i2c_remove(struct of_device *op) +static int __devexit bbc_i2c_remove(struct platform_device *op) { struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h index 83c4811b7b5e..4b4531066e75 100644 --- a/drivers/sbus/char/bbc_i2c.h +++ b/drivers/sbus/char/bbc_i2c.h @@ -7,7 +7,7 @@ struct bbc_i2c_client { struct bbc_i2c_bus *bp; - struct of_device *op; + struct platform_device *op; int bus; int address; }; @@ -64,16 +64,16 @@ struct bbc_i2c_bus { struct list_head temps; struct list_head fans; - struct of_device *op; + struct platform_device *op; struct { - struct of_device *device; + struct platform_device *device; int client_claimed; } devs[NUM_CHILDREN]; }; /* Probing and attachment. */ -extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); -extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *); +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/display7seg.c b/drivers/sbus/char/display7seg.c index 47db97583ea7..1690e53fb84a 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -170,7 +170,7 @@ static struct miscdevice d7s_miscdev = { .fops = &d7s_fops }; -static int __devinit d7s_probe(struct of_device *op, +static int __devinit d7s_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *opts; @@ -236,7 +236,7 @@ out_free: goto out; } -static int __devexit d7s_remove(struct of_device *op) +static int __devexit d7s_remove(struct platform_device *op) { struct d7s *p = dev_get_drvdata(&op->dev); u8 regs = readb(p->regs); diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 3c27f45e2b6d..078e5f4520ef 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1027,7 +1027,7 @@ static int kenvctrld(void *__unused) return 0; } -static int __devinit envctrl_probe(struct of_device *op, +static int __devinit envctrl_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp; @@ -1104,7 +1104,7 @@ out_iounmap: return err; } -static int __devexit envctrl_remove(struct of_device *op) +static int __devexit envctrl_remove(struct platform_device *op) { int index; diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 8bb31c584b64..2b4b4b613c48 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -160,7 +160,7 @@ static const struct file_operations flash_fops = { static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; -static int __devinit flash_probe(struct of_device *op, +static int __devinit flash_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -192,7 +192,7 @@ static int __devinit flash_probe(struct of_device *op, return misc_register(&flash_dev); } -static int __devexit flash_remove(struct of_device *op) +static int __devexit flash_remove(struct platform_device *op) { misc_deregister(&flash_dev); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 41eb6725ff5f..1b345be5cc02 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -348,7 +348,7 @@ static void uctrl_get_external_status(struct uctrl_driver *driver) } -static int __devinit uctrl_probe(struct of_device *op, +static int __devinit uctrl_probe(struct platform_device *op, const struct of_device_id *match) { struct uctrl_driver *p; @@ -404,7 +404,7 @@ out_free: goto out; } -static int __devexit uctrl_remove(struct of_device *op) +static int __devexit uctrl_remove(struct platform_device *op) { struct uctrl_driver *p = dev_get_drvdata(&op->dev); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 53d7ed0dc169..f8c561cf751e 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -704,7 +704,7 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) static int __devinit qpti_map_regs(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; qpti->qregs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), @@ -727,7 +727,7 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) static int __devinit qpti_register_irq(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; @@ -752,7 +752,7 @@ fail: static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; struct device_node *dp; dp = op->dev.of_node; @@ -773,7 +773,7 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) static void qpti_get_bursts(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; u8 bursts, bmask; bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); @@ -806,7 +806,7 @@ static void qpti_get_clock(struct qlogicpti *qpti) */ static int __devinit qpti_map_queues(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) qpti->res_cpu = dma_alloc_coherent(&op->dev, @@ -1290,7 +1290,7 @@ static struct scsi_host_template qpti_template = { .use_clustering = ENABLE_CLUSTERING, }; -static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct scsi_host_template *tpnt = match->data; struct device_node *dp = op->dev.of_node; @@ -1401,7 +1401,7 @@ fail_unlink: return -ENODEV; } -static int __devexit qpti_sbus_remove(struct of_device *op) +static int __devexit qpti_sbus_remove(struct platform_device *op) { struct qlogicpti *qpti = dev_get_drvdata(&op->dev); diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index e3c74d1ee2db..4377e87ee79c 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h @@ -342,7 +342,7 @@ struct qlogicpti { u_int req_in_ptr; /* index of next request slot */ u_int res_out_ptr; /* index of next result slot */ long send_marker; /* must we send a marker? */ - struct of_device *op; + struct platform_device *op; unsigned long __pad; int cmd_count[MAX_TARGETS]; diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 89ba6fe02f80..193b37ba1834 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c @@ -44,7 +44,7 @@ enum dvma_rev { }; static int __devinit esp_sbus_setup_dma(struct esp *esp, - struct of_device *dma_of) + struct platform_device *dma_of) { esp->dma = dma_of; @@ -81,7 +81,7 @@ static int __devinit esp_sbus_setup_dma(struct esp *esp, static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct resource *res; /* On HME, two reg sets exist, first is DVMA, @@ -101,7 +101,7 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) static int __devinit esp_sbus_map_command_block(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; esp->command_block = dma_alloc_coherent(&op->dev, 16, &esp->command_block_dma, @@ -114,15 +114,15 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp) static int __devinit esp_sbus_register_irq(struct esp *esp) { struct Scsi_Host *host = esp->host; - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; host->irq = op->archdata.irqs[0]; return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); } -static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma) +static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; dp = op->dev.of_node; @@ -144,7 +144,7 @@ done: static void __devinit esp_get_differential(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; dp = op->dev.of_node; @@ -156,7 +156,7 @@ static void __devinit esp_get_differential(struct esp *esp) static void __devinit esp_get_clock_params(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *bus_dp, *dp; int fmhz; @@ -170,10 +170,10 @@ static void __devinit esp_get_clock_params(struct esp *esp) esp->cfreq = fmhz; } -static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) +static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of) { struct device_node *dma_dp = dma_of->dev.of_node; - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; u8 bursts, val; @@ -195,7 +195,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) esp->bursts = bursts; } -static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) +static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma) { esp_get_scsi_id(esp, espdma); esp_get_differential(esp); @@ -216,7 +216,7 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg) static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, size_t sz, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; return dma_map_single(&op->dev, buf, sz, dir); } @@ -224,7 +224,7 @@ static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; return dma_map_sg(&op->dev, sg, num_sg, dir); } @@ -232,7 +232,7 @@ static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, size_t sz, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; dma_unmap_single(&op->dev, addr, sz, dir); } @@ -240,7 +240,7 @@ static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; dma_unmap_sg(&op->dev, sg, num_sg, dir); } @@ -256,7 +256,7 @@ static void sbus_esp_reset_dma(struct esp *esp) { int can_do_burst16, can_do_burst32, can_do_burst64; int can_do_sbus64, lim; - struct of_device *op; + struct platform_device *op; u32 val; can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; @@ -487,8 +487,8 @@ static const struct esp_driver_ops sbus_esp_ops = { .dma_error = sbus_esp_dma_error, }; -static int __devinit esp_sbus_probe_one(struct of_device *op, - struct of_device *espdma, +static int __devinit esp_sbus_probe_one(struct platform_device *op, + struct platform_device *espdma, int hme) { struct scsi_host_template *tpnt = &scsi_esp_template; @@ -562,11 +562,11 @@ fail: return err; } -static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dma_node = NULL; struct device_node *dp = op->dev.of_node; - struct of_device *dma_of = NULL; + struct platform_device *dma_of = NULL; int hme = 0; if (dp->parent && @@ -585,10 +585,10 @@ static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device return esp_sbus_probe_one(op, dma_of, hme); } -static int __devexit esp_sbus_remove(struct of_device *op) +static int __devexit esp_sbus_remove(struct platform_device *op) { struct esp *esp = dev_get_drvdata(&op->dev); - struct of_device *dma_of = esp->dma; + struct platform_device *dma_of = esp->dma; unsigned int irq = esp->host->irq; bool is_hme; u32 val; diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c index 0099b8692b60..cc01c650a144 100644 --- a/drivers/serial/apbuart.c +++ b/drivers/serial/apbuart.c @@ -551,7 +551,7 @@ static struct uart_driver grlib_apbuart_driver = { /* OF Platform Driver */ /* ======================================================================== */ -static int __devinit apbuart_probe(struct of_device *op, +static int __devinit apbuart_probe(struct platform_device *op, const struct of_device_id *match) { int i = -1; diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 6016179db533..f2b8adcc6c92 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -1340,7 +1340,7 @@ static struct uart_driver cpm_reg = { static int probe_index; -static int __devinit cpm_uart_probe(struct of_device *ofdev, +static int __devinit cpm_uart_probe(struct platform_device *ofdev, const struct of_device_id *match) { int index = probe_index++; @@ -1364,7 +1364,7 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev, return uart_add_one_port(&cpm_reg, &pinfo->port); } -static int __devexit cpm_uart_remove(struct of_device *ofdev) +static int __devexit cpm_uart_remove(struct platform_device *ofdev) { struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); return uart_remove_one_port(&cpm_reg, &pinfo->port); diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 1a88b363005c..8dedb266f143 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -1298,7 +1298,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { }; static int __devinit -mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) +mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match) { int idx = -1; unsigned int uartclk; @@ -1369,7 +1369,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) } static int -mpc52xx_uart_of_remove(struct of_device *op) +mpc52xx_uart_of_remove(struct platform_device *op) { struct uart_port *port = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); @@ -1382,7 +1382,7 @@ mpc52xx_uart_of_remove(struct of_device *op) #ifdef CONFIG_PM static int -mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) +mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) { struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); @@ -1393,7 +1393,7 @@ mpc52xx_uart_of_suspend(struct of_device *op, pm_message_t state) } static int -mpc52xx_uart_of_resume(struct of_device *op) +mpc52xx_uart_of_resume(struct platform_device *op) { struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c index e65b0d9202a5..de173671e3d0 100644 --- a/drivers/serial/nwpserial.c +++ b/drivers/serial/nwpserial.c @@ -344,7 +344,7 @@ int nwpserial_register_port(struct uart_port *port) mutex_lock(&nwpserial_mutex); - dn = to_of_device(port->dev)->dev.of_node; + dn = port->dev->of_node; if (dn == NULL) goto out; diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index a48d9080f552..659a695bdad6 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c @@ -27,7 +27,7 @@ struct of_serial_info { /* * Fill a struct uart_port for a given device node */ -static int __devinit of_platform_serial_setup(struct of_device *ofdev, +static int __devinit of_platform_serial_setup(struct platform_device *ofdev, int type, struct uart_port *port) { struct resource resource; @@ -80,7 +80,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, /* * Try to register a serial port */ -static int __devinit of_platform_serial_probe(struct of_device *ofdev, +static int __devinit of_platform_serial_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct of_serial_info *info; @@ -134,7 +134,7 @@ out: /* * Release a line */ -static int of_platform_serial_remove(struct of_device *ofdev) +static int of_platform_serial_remove(struct platform_device *ofdev) { struct of_serial_info *info = dev_get_drvdata(&ofdev->dev); switch (info->type) { diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index a779e22d213e..c9014868297d 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -519,7 +519,7 @@ static struct console sunhv_console = { .data = &sunhv_reg, }; -static int __devinit hv_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit hv_probe(struct platform_device *op, const struct of_device_id *match) { struct uart_port *port; unsigned long minor; @@ -598,7 +598,7 @@ out_free_port: return err; } -static int __devexit hv_remove(struct of_device *dev) +static int __devexit hv_remove(struct platform_device *dev) { struct uart_port *port = dev_get_drvdata(&dev->dev); diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 9845fb1cfb1f..5b246b18f42f 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -883,7 +883,7 @@ static int sunsab_console_setup(struct console *con, char *options) printk("Console: ttyS%d (SAB82532)\n", (sunsab_reg.minor - 64) + con->index); - sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); + sunserial_console_termios(con, up->port.dev->of_node); switch (con->cflag & CBAUD) { case B150: baud = 150; break; @@ -954,7 +954,7 @@ static inline struct console *SUNSAB_CONSOLE(void) #endif static int __devinit sunsab_init_one(struct uart_sunsab_port *up, - struct of_device *op, + struct platform_device *op, unsigned long offset, int line) { @@ -1006,7 +1006,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up, return 0; } -static int __devinit sab_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit sab_probe(struct platform_device *op, const struct of_device_id *match) { static int inst; struct uart_sunsab_port *up; @@ -1062,7 +1062,7 @@ out: return err; } -static int __devexit sab_remove(struct of_device *op) +static int __devexit sab_remove(struct platform_device *op) { struct uart_sunsab_port *up = dev_get_drvdata(&op->dev); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 3cdf74822db5..551ebfe3ccbb 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1200,7 +1200,7 @@ static int __devinit sunsu_kbd_ms_init(struct uart_sunsu_port *up) return -ENODEV; printk("%s: %s port at %llx, irq %u\n", - to_of_device(up->port.dev)->dev.of_node->full_name, + up->port.dev->of_node->full_name, (up->su_type == SU_PORT_KBD) ? "Keyboard" : "Mouse", (unsigned long long) up->port.mapbase, up->port.irq); @@ -1352,7 +1352,7 @@ static int __init sunsu_console_setup(struct console *co, char *options) spin_lock_init(&port->lock); /* Get firmware console settings. */ - sunserial_console_termios(co, to_of_device(port->dev)->dev.of_node); + sunserial_console_termios(co, port->dev->of_node); memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = co->cflag; @@ -1406,7 +1406,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp) return SU_PORT_PORT; } -static int __devinit su_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match) { static int inst; struct device_node *dp = op->dev.of_node; @@ -1497,7 +1497,7 @@ out_unmap: return err; } -static int __devexit su_remove(struct of_device *op) +static int __devexit su_remove(struct platform_device *op) { struct uart_sunsu_port *up = dev_get_drvdata(&op->dev); bool kbdms = false; diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index d1e6bcb59546..c1967ac1c07f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1230,7 +1230,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) (sunzilog_reg.minor - 64) + con->index, con->index); /* Get firmware console settings. */ - sunserial_console_termios(con, to_of_device(up->port.dev)->dev.of_node); + sunserial_console_termios(con, up->port.dev->of_node); /* Firmware console speed is limited to 150-->38400 baud so * this hackish cflag thing is OK. @@ -1399,7 +1399,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) static int zilog_irq = -1; -static int __devinit zs_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit zs_probe(struct platform_device *op, const struct of_device_id *match) { static int kbm_inst, uart_inst; int inst; @@ -1516,7 +1516,7 @@ static void __devexit zs_remove_one(struct uart_sunzilog_port *up) uart_remove_one_port(&sunzilog_reg, &up->port); } -static int __devexit zs_remove(struct of_device *op) +static int __devexit zs_remove(struct platform_device *op) { struct uart_sunzilog_port *up = dev_get_drvdata(&op->dev); struct zilog_layout __iomem *regs; diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index caf085d3a76a..9b03d7b3e456 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -584,7 +584,7 @@ static struct platform_driver ulite_platform_driver = { */ #if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE)) static int __devinit -ulite_of_probe(struct of_device *op, const struct of_device_id *match) +ulite_of_probe(struct platform_device *op, const struct of_device_id *match) { struct resource res; const unsigned int *id; @@ -605,7 +605,7 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match) return ulite_assign(&op->dev, id ? *id : -1, res.start, irq); } -static int __devexit ulite_of_remove(struct of_device *op) +static int __devexit ulite_of_remove(struct platform_device *op) { return ulite_release(&op->dev); } diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index 907b06f5c447..3f4848e2174a 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c @@ -1194,7 +1194,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context) release_firmware(fw); } -static int ucc_uart_probe(struct of_device *ofdev, +static int ucc_uart_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -1462,7 +1462,7 @@ static int ucc_uart_probe(struct of_device *ofdev, return 0; } -static int ucc_uart_remove(struct of_device *ofdev) +static int ucc_uart_remove(struct platform_device *ofdev) { struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev); diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c index 10baac3f8ea5..cddbfceb324f 100644 --- a/drivers/spi/mpc512x_psc_spi.c +++ b/drivers/spi/mpc512x_psc_spi.c @@ -507,7 +507,7 @@ static int __exit mpc512x_psc_spi_do_remove(struct device *dev) return 0; } -static int __init mpc512x_psc_spi_of_probe(struct of_device *op, +static int __init mpc512x_psc_spi_of_probe(struct platform_device *op, const struct of_device_id *match) { const u32 *regaddr_p; @@ -539,7 +539,7 @@ static int __init mpc512x_psc_spi_of_probe(struct of_device *op, irq_of_parse_and_map(op->dev.of_node, 0), id); } -static int __exit mpc512x_psc_spi_of_remove(struct of_device *op) +static int __exit mpc512x_psc_spi_of_remove(struct platform_device *op) { return mpc512x_psc_spi_do_remove(&op->dev); } diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 66d170147dcc..983fbbfce76e 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -465,7 +465,7 @@ static int __exit mpc52xx_psc_spi_do_remove(struct device *dev) return 0; } -static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, +static int __init mpc52xx_psc_spi_of_probe(struct platform_device *op, const struct of_device_id *match) { const u32 *regaddr_p; @@ -495,7 +495,7 @@ static int __init mpc52xx_psc_spi_of_probe(struct of_device *op, irq_of_parse_and_map(op->dev.of_node, 0), id); } -static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op) +static int __exit mpc52xx_psc_spi_of_remove(struct platform_device *op) { return mpc52xx_psc_spi_do_remove(&op->dev); } diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c index 56136ff00e01..ec9f0b1bf864 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/mpc52xx_spi.c @@ -390,7 +390,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m) /* * OF Platform Bus Binding */ -static int __devinit mpc52xx_spi_probe(struct of_device *op, +static int __devinit mpc52xx_spi_probe(struct platform_device *op, const struct of_device_id *match) { struct spi_master *master; @@ -530,7 +530,7 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op, return rc; } -static int __devexit mpc52xx_spi_remove(struct of_device *op) +static int __devexit mpc52xx_spi_remove(struct platform_device *op) { struct spi_master *master = dev_get_drvdata(&op->dev); struct mpc52xx_spi *ms = spi_master_get_devdata(master); diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index aad9ae1b9c69..d31b57f7baaf 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -1236,7 +1236,7 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev) return 0; } -static int __devinit of_mpc8xxx_spi_probe(struct of_device *ofdev, +static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct device *dev = &ofdev->dev; @@ -1308,7 +1308,7 @@ err_clk: return ret; } -static int __devexit of_mpc8xxx_spi_remove(struct of_device *ofdev) +static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev) { int ret; diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c index 0f5fa7e2a550..80e172d3e72a 100644 --- a/drivers/spi/spi_ppc4xx.c +++ b/drivers/spi/spi_ppc4xx.c @@ -388,9 +388,9 @@ static void free_gpios(struct ppc4xx_spi *hw) } /* - * of_device layer stuff... + * platform_device layer stuff... */ -static int __init spi_ppc4xx_of_probe(struct of_device *op, +static int __init spi_ppc4xx_of_probe(struct platform_device *op, const struct of_device_id *match) { struct ppc4xx_spi *hw; @@ -565,7 +565,7 @@ free_master: return ret; } -static int __exit spi_ppc4xx_of_remove(struct of_device *op) +static int __exit spi_ppc4xx_of_remove(struct platform_device *op) { struct spi_master *master = dev_get_drvdata(&op->dev); struct ppc4xx_spi *hw = spi_master_get_devdata(master); diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c index f53d3f6b9f61..b66c2dbf20a5 100644 --- a/drivers/spi/xilinx_spi_of.c +++ b/drivers/spi/xilinx_spi_of.c @@ -38,7 +38,7 @@ #include "xilinx_spi.h" -static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, +static int __devinit xilinx_spi_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct spi_master *master; @@ -84,7 +84,7 @@ static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, return 0; } -static int __devexit xilinx_spi_remove(struct of_device *ofdev) +static int __devexit xilinx_spi_remove(struct platform_device *ofdev) { xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev)); dev_set_drvdata(&ofdev->dev, 0); @@ -93,7 +93,7 @@ static int __devexit xilinx_spi_remove(struct of_device *ofdev) return 0; } -static int __exit xilinx_spi_of_remove(struct of_device *op) +static int __exit xilinx_spi_of_remove(struct platform_device *op) { return xilinx_spi_remove(op); } diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 9648b75f0283..a5ea2c1d8c93 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2398,7 +2398,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) EXPORT_SYMBOL(usb_gadget_unregister_driver); /* udc structure's alloc and setup, include ep-param alloc */ -static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev) +static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev) { struct qe_udc *udc; struct device_node *np = ofdev->dev.of_node; @@ -2523,7 +2523,7 @@ static void qe_udc_release(struct device *dev) } /* Driver probe functions */ -static int __devinit qe_udc_probe(struct of_device *ofdev, +static int __devinit qe_udc_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -2679,18 +2679,18 @@ err1: } #ifdef CONFIG_PM -static int qe_udc_suspend(struct of_device *dev, pm_message_t state) +static int qe_udc_suspend(struct platform_device *dev, pm_message_t state) { return -ENOTSUPP; } -static int qe_udc_resume(struct of_device *dev) +static int qe_udc_resume(struct platform_device *dev) { return -ENOTSUPP; } #endif -static int __devexit qe_udc_remove(struct of_device *ofdev) +static int __devexit qe_udc_remove(struct platform_device *ofdev) { struct qe_ep *ep; unsigned int size; diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 5aec92866ab3..335ee699fd85 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -106,7 +106,7 @@ ppc44x_enable_bmt(struct device_node *dn) static int __devinit -ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) +ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -210,7 +210,7 @@ err_rmr: } -static int ehci_hcd_ppc_of_remove(struct of_device *op) +static int ehci_hcd_ppc_of_remove(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -253,7 +253,7 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) } -static int ehci_hcd_ppc_of_shutdown(struct of_device *op) +static int ehci_hcd_ppc_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 4899f451add9..6c8076ad821d 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -140,7 +140,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { /** * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller - * @op: pointer to the of_device to which the host controller bound + * @op: pointer to the platform_device bound to the host controller * @match: pointer to of_device_id structure, not used * * This function requests resources and sets up appropriate properties for the @@ -149,7 +149,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { * entry, and sets an appropriate value for hcd->has_tt. */ static int __devinit -ehci_hcd_xilinx_of_probe(struct of_device *op, const struct of_device_id *match) +ehci_hcd_xilinx_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -242,12 +242,12 @@ err_rmr: /** * ehci_hcd_xilinx_of_remove - shutdown hcd and release resources - * @op: pointer to of_device structure that is to be removed + * @op: pointer to platform_device structure that is to be removed * * Remove the hcd structure, and release resources that has been requested * during probe. */ -static int ehci_hcd_xilinx_of_remove(struct of_device *op) +static int ehci_hcd_xilinx_of_remove(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); @@ -266,11 +266,11 @@ static int ehci_hcd_xilinx_of_remove(struct of_device *op) /** * ehci_hcd_xilinx_of_shutdown - shutdown the hcd - * @op: pointer to of_device structure that is to be removed + * @op: pointer to platform_device structure that is to be removed * * Properly shutdown the hcd, call driver's shutdown routine. */ -static int ehci_hcd_xilinx_of_shutdown(struct of_device *op) +static int ehci_hcd_xilinx_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index c7c8392a88b9..20092a27a1e8 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = { .hub_control = fhci_hub_control, }; -static int __devinit of_fhci_probe(struct of_device *ofdev, +static int __devinit of_fhci_probe(struct platform_device *ofdev, const struct of_device_id *ofid) { struct device *dev = &ofdev->dev; @@ -801,7 +801,7 @@ static int __devexit fhci_remove(struct device *dev) return 0; } -static int __devexit of_fhci_remove(struct of_device *ofdev) +static int __devexit of_fhci_remove(struct platform_device *ofdev) { return fhci_remove(&ofdev->dev); } diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index ec85d0c3cc3e..3b28dbfca058 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -27,7 +27,7 @@ #endif #ifdef CONFIG_PPC_OF -static int of_isp1760_probe(struct of_device *dev, +static int of_isp1760_probe(struct platform_device *dev, const struct of_device_id *match) { struct usb_hcd *hcd; @@ -95,7 +95,7 @@ release_reg: return ret; } -static int of_isp1760_remove(struct of_device *dev) +static int of_isp1760_remove(struct platform_device *dev) { struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index df165917412a..b2c2dbf08766 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { static int __devinit -ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) +ohci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -183,7 +183,7 @@ err_rmr: return rv; } -static int ohci_hcd_ppc_of_remove(struct of_device *op) +static int ohci_hcd_ppc_of_remove(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); @@ -201,7 +201,7 @@ static int ohci_hcd_ppc_of_remove(struct of_device *op) return 0; } -static int ohci_hcd_ppc_of_shutdown(struct of_device *op) +static int ohci_hcd_ppc_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index c7796637bafd..4dc13467281d 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par, return 0; } -static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; struct fb_info *info; @@ -350,7 +350,7 @@ out_err: return err; } -static int __devexit bw2_remove(struct of_device *op) +static int __devexit bw2_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct bw2_par *par = info->par; diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index d09fde8beb69..24249535ac86 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -446,7 +446,7 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = { { .size = 0 } }; -static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, +static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info, struct cg14_par *par) { if (par->regs) @@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, info->screen_base, info->fix.smem_len); } -static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; struct fb_info *info; @@ -570,7 +570,7 @@ out_err: return err; } -static int __devexit cg14_remove(struct of_device *op) +static int __devexit cg14_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct cg14_par *par = info->par; diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 64aa29809fb9..09c0c3c42482 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par) return 0; } -static int __devinit cg3_probe(struct of_device *op, +static int __devinit cg3_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -433,7 +433,7 @@ out_err: return err; } -static int __devexit cg3_remove(struct of_device *op) +static int __devexit cg3_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct cg3_par *par = info->par; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 2389a719dcc7..2b5a97058b08 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -718,7 +718,7 @@ static void __devinit cg6_chip_init(struct fb_info *info) sbus_writel(info->var.yres - 1, &fbc->clipmaxy); } -static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, +static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info, struct cg6_par *par) { if (par->fbc) @@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, info->fix.smem_len); } -static int __devinit cg6_probe(struct of_device *op, +static int __devinit cg6_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -827,7 +827,7 @@ out_err: return err; } -static int __devexit cg6_remove(struct of_device *op) +static int __devexit cg6_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct cg6_par *par = info->par; diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index f6ecfab296d3..6739b2af3bc0 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info) info->fix.accel = FB_ACCEL_SUN_CREATOR; } -static int __devinit ffb_probe(struct of_device *op, +static int __devinit ffb_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -1023,7 +1023,7 @@ out_err: return err; } -static int __devexit ffb_remove(struct of_device *op) +static int __devexit ffb_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct ffb_par *par = info->par; diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index e38ad2224540..8bbbf08fa3ce 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1393,7 +1393,7 @@ static void free_irq_local(int irq) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) +static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state) { struct fsl_diu_data *machine_data; @@ -1403,7 +1403,7 @@ static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) return 0; } -static int fsl_diu_resume(struct of_device *ofdev) +static int fsl_diu_resume(struct platform_device *ofdev) { struct fsl_diu_data *machine_data; @@ -1487,7 +1487,7 @@ static ssize_t show_monitor(struct device *device, return diu_ops.show_monitor_port(machine_data->monitor_port, buf); } -static int __devinit fsl_diu_probe(struct of_device *ofdev, +static int __devinit fsl_diu_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -1667,7 +1667,7 @@ error2: } -static int fsl_diu_remove(struct of_device *ofdev) +static int fsl_diu_remove(struct platform_device *ofdev) { struct fsl_diu_data *machine_data; int i; diff --git a/drivers/video/leo.c b/drivers/video/leo.c index ad677637ffbb..b599e5e36ced 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -529,7 +529,7 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) var->transp.length = 0; } -static void leo_unmap_regs(struct of_device *op, struct fb_info *info, +static void leo_unmap_regs(struct platform_device *op, struct fb_info *info, struct leo_par *par) { if (par->lc_ss0_usr) @@ -547,7 +547,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info, of_iounmap(&op->resource[0], info->screen_base, 0x800000); } -static int __devinit leo_probe(struct of_device *op, +static int __devinit leo_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -637,7 +637,7 @@ out_err: return err; } -static int __devexit leo_remove(struct of_device *op) +static int __devexit leo_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct leo_par *par = info->par; diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index 4e2b8cc3d460..b1c4374cf940 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c @@ -550,7 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par) return 0; } -static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, +static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev, const struct of_device_id *id) { struct device_node *np = ofdev->dev.of_node; @@ -669,7 +669,7 @@ fbrel: return ret; } -static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) +static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev) { struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); struct mb862xxfb_par *par = fbi->par; diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 688b055abab2..b6c3fc2db632 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no info->fix.accel = FB_ACCEL_SUN_CGTHREE; } -static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; struct fb_info *info; @@ -326,7 +326,7 @@ out_err: return err; } -static int __devexit p9100_remove(struct of_device *op) +static int __devexit p9100_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct p9100_par *par = info->par; diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 72a1f4c04732..a50e1977b316 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -533,7 +533,7 @@ static int __init platinumfb_setup(char *options) #define invalidate_cache(addr) #endif -static int __devinit platinumfb_probe(struct of_device* odev, +static int __devinit platinumfb_probe(struct platform_device* odev, const struct of_device_id *match) { struct device_node *dp = odev->dev.of_node; @@ -646,7 +646,7 @@ static int __devinit platinumfb_probe(struct of_device* odev, return rc; } -static int __devexit platinumfb_remove(struct of_device* odev) +static int __devexit platinumfb_remove(struct platform_device* odev) { struct fb_info *info = dev_get_drvdata(&odev->dev); struct fb_info_platinum *pinfo = info->par; diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c index 7288934c0d49..5dbe06af2226 100644 --- a/drivers/video/sunxvr1000.c +++ b/drivers/video/sunxvr1000.c @@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp) return 0; } -static int __devinit gfb_probe(struct of_device *op, +static int __devinit gfb_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -172,7 +172,7 @@ err_out: return err; } -static int __devexit gfb_remove(struct of_device *op) +static int __devexit gfb_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct gfb_info *gp = info->par; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index f375e0db6776..77ad27955cf0 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -342,7 +342,7 @@ tcx_init_fix(struct fb_info *info, int linebytes) info->fix.accel = FB_ACCEL_SUN_TCX; } -static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, +static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info, struct tcx_par *par) { if (par->tec) @@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, info->screen_base, info->fix.smem_len); } -static int __devinit tcx_probe(struct of_device *op, +static int __devinit tcx_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dp = op->dev.of_node; @@ -486,7 +486,7 @@ out_err: return err; } -static int __devexit tcx_remove(struct of_device *op) +static int __devexit tcx_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct tcx_par *par = info->par; diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 29b5daacc217..0c9ce88e95e8 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -397,7 +397,7 @@ static int xilinxfb_release(struct device *dev) */ static int __devinit -xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) +xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match) { const u32 *prop; u32 *p; @@ -477,7 +477,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match) return -ENODEV; } -static int __devexit xilinxfb_of_remove(struct of_device *op) +static int __devexit xilinxfb_of_remove(struct platform_device *op) { return xilinxfb_release(&op->dev); } diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 30a2512fd52e..566343b3c131 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -526,7 +526,7 @@ static const struct file_operations cpwd_fops = { .release = cpwd_release, }; -static int __devinit cpwd_probe(struct of_device *op, +static int __devinit cpwd_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *options; @@ -639,7 +639,7 @@ out_free: goto out; } -static int __devexit cpwd_remove(struct of_device *op) +static int __devexit cpwd_remove(struct platform_device *op) { struct cpwd *p = dev_get_drvdata(&op->dev); int i; diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index 1df284f9c2a1..9c21d19043a6 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -260,7 +260,7 @@ static struct miscdevice gef_wdt_miscdev = { }; -static int __devinit gef_wdt_probe(struct of_device *dev, +static int __devinit gef_wdt_probe(struct platform_device *dev, const struct of_device_id *match) { int timeout = 10; diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index 4cda64dd309c..8fa213cdb499 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -185,7 +185,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = { .fops = &mpc8xxx_wdt_fops, }; -static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, +static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev, const struct of_device_id *match) { int ret; @@ -238,7 +238,7 @@ err_unmap: return ret; } -static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) +static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev) { mpc8xxx_wdt_pr_warn("watchdog removed"); del_timer_sync(&wdt_timer); diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 4082b4ace1fc..3faee1ae64bd 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -172,7 +172,7 @@ static struct miscdevice riowd_miscdev = { .fops = &riowd_fops }; -static int __devinit riowd_probe(struct of_device *op, +static int __devinit riowd_probe(struct platform_device *op, const struct of_device_id *match) { struct riowd *p; @@ -219,7 +219,7 @@ out: return err; } -static int __devexit riowd_remove(struct of_device *op) +static int __devexit riowd_remove(struct platform_device *op) { struct riowd *p = dev_get_drvdata(&op->dev); diff --git a/include/linux/of_device.h b/include/linux/of_device.h index 35aa44ad9f2c..835f85ecd2de 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -1,20 +1,6 @@ #ifndef _LINUX_OF_DEVICE_H #define _LINUX_OF_DEVICE_H -/* - * The of_device *was* a kind of "base class" that was a superset of - * struct device for use by devices attached to an OF node and probed - * using OF properties. However, the important bit of OF-style - * probing, namely the device node pointer, has been moved into the - * common struct device when CONFIG_OF is set to make OF-style probing - * available to all bus types. So now, just make of_device and - * platform_device equivalent so that current of_platform bus users - * can be transparently migrated over to using the platform bus. - * - * This line will go away once all references to of_device are removed - * from the kernel. - */ -#define of_device platform_device #include #include /* temporary until merge */ @@ -23,8 +9,6 @@ #include #include -#define to_of_device(d) container_of(d, struct of_device, dev) - extern const struct of_device_id *of_match_device( const struct of_device_id *matches, const struct device *dev); extern void of_device_make_bus_id(struct device *dev); diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 4e6d989c06df..a68716ad38ce 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -19,9 +19,17 @@ #include #include -/* - * An of_platform_driver driver is attached to a basic of_device on - * the "platform bus" (platform_bus_type). +/** + * of_platform_driver - Legacy of-aware driver for platform devices. + * + * An of_platform_driver driver is attached to a basic platform_device on + * ether the "platform bus" (platform_bus_type), or the ibm ebus + * (ibmebus_bus_type). + * + * of_platform_driver is being phased out when used with the platform_bus_type, + * and regular platform_drivers should be used instead. When the transition + * is complete, only ibmebus will be using this structure, and the + * platform_driver member of this structure will be removed. */ struct of_platform_driver { diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c index 99ca7120e269..7487eb76e034 100644 --- a/sound/aoa/soundbus/core.c +++ b/sound/aoa/soundbus/core.c @@ -59,7 +59,7 @@ static int soundbus_probe(struct device *dev) static int soundbus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct soundbus_dev * soundbus_dev; - struct of_device * of; + struct platform_device * of; const char *compat; int retval = 0; int cplen, seen = 0; diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h index a0f223c13f66..adecbf36f4f6 100644 --- a/sound/aoa/soundbus/soundbus.h +++ b/sound/aoa/soundbus/soundbus.h @@ -141,7 +141,7 @@ struct soundbus_dev { struct list_head onbuslist; /* the of device it represents */ - struct of_device ofdev; + struct platform_device ofdev; /* what modules go by */ char modalias[32]; diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c index 6496e754f00a..e0980b5c2cd8 100644 --- a/sound/aoa/soundbus/sysfs.c +++ b/sound/aoa/soundbus/sysfs.c @@ -16,7 +16,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { struct soundbus_dev *sdev = to_soundbus_device(dev); - struct of_device *of = &sdev->ofdev; + struct platform_device *of = &sdev->ofdev; int length; if (*sdev->modalias) { diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 1d4e7164e80a..3dcd1469f283 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -369,7 +369,7 @@ struct snd_soc_platform mpc5200_audio_dma_platform = { }; EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform); -int mpc5200_audio_dma_create(struct of_device *op) +int mpc5200_audio_dma_create(struct platform_device *op) { phys_addr_t fifo; struct psc_dma *psc_dma; @@ -488,7 +488,7 @@ out_unmap: } EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); -int mpc5200_audio_dma_destroy(struct of_device *op) +int mpc5200_audio_dma_destroy(struct platform_device *op) { struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index e1ec6d91ea38..ca99586f2ad9 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h @@ -81,8 +81,8 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) return &psc_dma->playback; } -int mpc5200_audio_dma_create(struct of_device *op); -int mpc5200_audio_dma_destroy(struct of_device *op); +int mpc5200_audio_dma_create(struct platform_device *op); +int mpc5200_audio_dma_destroy(struct platform_device *op); extern struct snd_soc_platform mpc5200_audio_dma_platform; diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index e2ee220bfb7e..a0310170a170 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -263,7 +263,7 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai); * - Probe/remove operations * - OF device match table */ -static int __devinit psc_ac97_of_probe(struct of_device *op, +static int __devinit psc_ac97_of_probe(struct platform_device *op, const struct of_device_id *match) { int rc, i; @@ -303,7 +303,7 @@ static int __devinit psc_ac97_of_probe(struct of_device *op, return 0; } -static int __devexit psc_ac97_of_remove(struct of_device *op) +static int __devexit psc_ac97_of_remove(struct platform_device *op) { return mpc5200_audio_dma_destroy(op); } diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 4f455bd6851f..9aee748eca7d 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -153,7 +153,7 @@ EXPORT_SYMBOL_GPL(psc_i2s_dai); * - Probe/remove operations * - OF device match table */ -static int __devinit psc_i2s_of_probe(struct of_device *op, +static int __devinit psc_i2s_of_probe(struct platform_device *op, const struct of_device_id *match) { int rc; @@ -206,7 +206,7 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, } -static int __devexit psc_i2s_of_remove(struct of_device *op) +static int __devexit psc_i2s_of_remove(struct platform_device *op) { return mpc5200_audio_dma_destroy(op); } diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 3a501062c244..3b13b8d65262 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -200,7 +200,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = { * SSI devices. We also probably aren't compatible with the generic Elo DMA * device driver. */ -static int mpc8610_hpcd_probe(struct of_device *ofdev, +static int mpc8610_hpcd_probe(struct platform_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; @@ -534,7 +534,7 @@ error: * * This function is called when the OF device is removed. */ -static int mpc8610_hpcd_remove(struct of_device *ofdev) +static int mpc8610_hpcd_remove(struct platform_device *ofdev) { struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); struct mpc8610_hpcd_data *machine_data = diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 9eb1a4e0363b..f8bcfc30f800 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -336,7 +336,7 @@ struct snd_amd7930 { int pgain; int mgain; - struct of_device *op; + struct platform_device *op; unsigned int irq; struct snd_amd7930 *next; }; @@ -906,7 +906,7 @@ static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) static int snd_amd7930_free(struct snd_amd7930 *amd) { - struct of_device *op = amd->op; + struct platform_device *op = amd->op; amd7930_idle(amd); @@ -934,7 +934,7 @@ static struct snd_device_ops snd_amd7930_dev_ops = { }; static int __devinit snd_amd7930_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int irq, int dev, struct snd_amd7930 **ramd) { @@ -1002,7 +1002,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card, return 0; } -static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit amd7930_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct resource *rp = &op->resource[0]; static int dev_num; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 68570ee2c9bb..c276086c3b57 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -111,7 +111,7 @@ struct snd_cs4231 { struct mutex mce_mutex; /* mutex for mce register */ struct mutex open_mutex; /* mutex for ALSA open/close */ - struct of_device *op; + struct platform_device *op; unsigned int irq[2]; unsigned int regs_size; struct snd_cs4231 *next; @@ -1771,7 +1771,7 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) { - struct of_device *op = chip->op; + struct platform_device *op = chip->op; if (chip->irq[0]) free_irq(chip->irq[0], chip); @@ -1794,7 +1794,7 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { }; static int __devinit snd_cs4231_sbus_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int dev) { struct snd_cs4231 *chip = card->private_data; @@ -1856,7 +1856,7 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card, return 0; } -static int __devinit cs4231_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cs4231_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct resource *rp = &op->resource[0]; struct snd_card *card; @@ -1931,7 +1931,7 @@ static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) { - struct of_device *op = chip->op; + struct platform_device *op = chip->op; if (chip->c_dma.ebus_info.regs) { ebus_dma_unregister(&chip->c_dma.ebus_info); @@ -1960,7 +1960,7 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { }; static int __devinit snd_cs4231_ebus_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int dev) { struct snd_cs4231 *chip = card->private_data; @@ -2048,7 +2048,7 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card, return 0; } -static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cs4231_ebus_probe(struct platform_device *op, const struct of_device_id *match) { struct snd_card *card; int err; @@ -2072,7 +2072,7 @@ static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_dev } #endif -static int __devinit cs4231_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit cs4231_probe(struct platform_device *op, const struct of_device_id *match) { #ifdef EBUS_SUPPORT if (!strcmp(op->dev.of_node->parent->name, "ebus")) @@ -2086,7 +2086,7 @@ static int __devinit cs4231_probe(struct of_device *op, const struct of_device_i return -ENODEV; } -static int __devexit cs4231_remove(struct of_device *op) +static int __devexit cs4231_remove(struct platform_device *op) { struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index c421901c48d0..39cd5d69d051 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -299,7 +299,7 @@ struct dbri_streaminfo { /* This structure holds the information for both chips (DBRI & CS4215) */ struct snd_dbri { int regs_size, irq; /* Needed for unload */ - struct of_device *op; /* OF device info */ + struct platform_device *op; /* OF device info */ spinlock_t lock; struct dbri_dma *dma; /* Pointer to our DMA block */ @@ -2523,7 +2523,7 @@ static void __devinit snd_dbri_proc(struct snd_card *card) static void snd_dbri_free(struct snd_dbri *dbri); static int __devinit snd_dbri_create(struct snd_card *card, - struct of_device *op, + struct platform_device *op, int irq, int dev) { struct snd_dbri *dbri = card->private_data; @@ -2592,7 +2592,7 @@ static void snd_dbri_free(struct snd_dbri *dbri) (void *)dbri->dma, dbri->dma_dvma); } -static int __devinit dbri_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit dbri_probe(struct platform_device *op, const struct of_device_id *match) { struct snd_dbri *dbri; struct resource *rp; @@ -2662,7 +2662,7 @@ _err: return err; } -static int __devexit dbri_remove(struct of_device *op) +static int __devexit dbri_remove(struct platform_device *op) { struct snd_card *card = dev_get_drvdata(&op->dev); -- cgit v1.2.3 From f1d23ed8218ca5afaf178a6495253dbb7fc98f57 Mon Sep 17 00:00:00 2001 From: Claudio Scordino Date: Mon, 31 May 2010 10:19:09 +0200 Subject: CRIS: ioctl for getting RS485 information Add ioctl to CRIS serial driver to get RS485 data from user-space. Signed-off-by: Claudio Scordino Signed-off-by: Jesper Nilsson --- arch/cris/include/asm/ioctls.h | 1 + drivers/serial/crisv10.c | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'drivers/serial') diff --git a/arch/cris/include/asm/ioctls.h b/arch/cris/include/asm/ioctls.h index 35bbc181598a..076c07824eb6 100644 --- a/arch/cris/include/asm/ioctls.h +++ b/arch/cris/include/asm/ioctls.h @@ -77,6 +77,7 @@ #define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */ #define TIOCSERWRRS485 0x5462 /* write rs-485 */ #define TIOCSRS485 0x5463 /* enable rs-485 */ +#define TIOCGRS485 0x542E /* get rs-485 */ /* Used for packet mode */ #define TIOCPKT_DATA 0 diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 31f172397af3..30626440a062 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -3724,6 +3724,17 @@ rs_ioctl(struct tty_struct *tty, struct file * file, return e100_enable_rs485(tty, &rs485data); } + case TIOCGRS485: + { + struct serial_rs485 *rs485data = + &(((struct e100_serial *)tty->driver_data)->rs485); + /* This is the ioctl to get RS485 data from user-space */ + if (copy_to_user((struct serial_rs485 *) arg, + rs485data, + sizeof(serial_rs485))) + return -EFAULT; + break; + } case TIOCSERWRRS485: { -- cgit v1.2.3 From 690b781b327a1c986c33fb2c51dd966c38222943 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 26 May 2010 15:33:43 +0200 Subject: serial: There's no config CONSOLE as there's no config CONSOLE (never has been as far as I can tell) and noone has ever missed that piece of code, it should be safe to remove it making the kernel a tiny bit less complex. Signed-off-by: Christoph Egger Acked-by: Greg Ungerer Signed-off-by: Greg Kroah-Hartman --- drivers/serial/68328serial.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 30463862603b..9330edb323e2 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -78,10 +78,6 @@ struct m68k_serial *m68k_consinfo = 0; #define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */ -#ifdef CONFIG_CONSOLE -extern wait_queue_head_t keypress_wait; -#endif - struct tty_driver *serial_driver; /* number of characters left in xmit buffer before we ask for more */ @@ -300,10 +296,6 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx) return; #endif /* CONFIG_MAGIC_SYSRQ */ } - /* It is a 'keyboard interrupt' ;-) */ -#ifdef CONFIG_CONSOLE - wake_up(&keypress_wait); -#endif } if(!tty) -- cgit v1.2.3 From 7a56aa45982bb87bfca98a2832b5ae782c03364a Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Wed, 16 Jun 2010 16:29:55 +0200 Subject: serial: add UART_CAP_EFR and UART_CAP_SLEEP flags to 16C950 UARTs definition Adding UART_CAP_EFR and UART_CAP_SLEEP flags will enable sleep mode and automatic CTS flow control for 16C950 UARTs. It will also avoid capabilities detection warning like this: "ttyS0: detected caps 00000700 should be 00000100" Signed-off-by: Yegor Yefremov Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 09ef57034c9c..bc8ed4be9073 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -241,7 +241,7 @@ static const struct serial8250_config uart_config[] = { .fifo_size = 128, .tx_loadsz = 128, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO, + .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, }, [PORT_16654] = { .name = "ST16654", -- cgit v1.2.3 From 225109957a74c571c49e860fcc4e81fa6df1079d Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Wed, 16 Jun 2010 14:46:09 +0100 Subject: mrst_max3110: add UART driver for Max3110 on Moorestown This driver enable the max3110 device, it can be used as a system console. the IRQ needs be enabled if user want a better performance. MRST max3110 works in 3.684MHz clock, which supports 230400 as its maximum rate. Signed-off-by: Feng Tang Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/Kconfig | 17 + drivers/serial/Makefile | 1 + drivers/serial/mrst_max3110.c | 844 ++++++++++++++++++++++++++++++++++++++++++ drivers/serial/mrst_max3110.h | 59 +++ 4 files changed, 921 insertions(+) create mode 100644 drivers/serial/mrst_max3110.c create mode 100644 drivers/serial/mrst_max3110.h (limited to 'drivers/serial') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index e437ce8c1748..964634e79c16 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -690,6 +690,23 @@ config SERIAL_SA1100_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_MRST_MAX3110 + tristate "SPI UART driver for Max3110" + depends on SPI_DW_PCI + select SERIAL_CORE + select SERIAL_CORE_CONSOLE + help + This is the UART protocol driver for the MAX3110 device on + the Intel Moorestown platform. On other systems use the max3100 + driver. + +config MRST_MAX3110_IRQ + boolean "Enable GPIO IRQ for Max3110 over Moorestown" + default n + depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL + help + This has to be enabled after Moorestown GPIO driver is loaded + config SERIAL_BFIN tristate "Blackfin serial port support" depends on BLACKFIN diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 208a85572c32..a5edb49c7303 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -84,3 +84,4 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o +obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c new file mode 100644 index 000000000000..273e7cbe74cd --- /dev/null +++ b/drivers/serial/mrst_max3110.c @@ -0,0 +1,844 @@ +/* + * max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown + * + * Copyright (C) Intel 2008 Feng Tang + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Note: + * 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has + * 1 word. If SPI master controller doesn't support sclk frequency change, + * then the char need be sent out one by one with some delay + * + * 2. Currently only RX availabe interrrupt is used, no need for waiting TXE + * interrupt for a low speed UART device + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mrst_max3110.h" + +#define PR_FMT "mrst_max3110: " + +struct uart_max3110 { + struct uart_port port; + struct spi_device *spi; + char *name; + + wait_queue_head_t wq; + struct task_struct *main_thread; + struct task_struct *read_thread; + int mthread_up; + spinlock_t lock; + + u32 baud; + u16 cur_conf; + u8 clock; + u8 parity, word_7bits; + + atomic_t uart_tx_need; + + /* console related */ + struct circ_buf con_xmit; + atomic_t con_tx_need; + + /* irq related */ + u16 irq; + atomic_t irq_pending; +}; + +/* global data structure, may need be removed */ +struct uart_max3110 *pmax; +static inline void receive_char(struct uart_max3110 *max, u8 ch); +static void receive_chars(struct uart_max3110 *max, + unsigned char *str, int len); +static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf); +static void max3110_console_receive(struct uart_max3110 *max); + +int max3110_write_then_read(struct uart_max3110 *max, + const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast) +{ + struct spi_device *spi = max->spi; + struct spi_message message; + struct spi_transfer x; + int ret; + + if (!txbuf || !rxbuf) + return -EINVAL; + + spi_message_init(&message); + memset(&x, 0, sizeof x); + x.len = len; + x.tx_buf = txbuf; + x.rx_buf = rxbuf; + spi_message_add_tail(&x, &message); + + if (always_fast) + x.speed_hz = 3125000; + else if (max->baud) + x.speed_hz = max->baud; + + /* Do the i/o */ + ret = spi_sync(spi, &message); + return ret; +} + +/* Write a u16 to the device, and return one u16 read back */ +int max3110_out(struct uart_max3110 *max, const u16 out) +{ + u16 tmp; + int ret; + + ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1); + if (ret) + return ret; + + /* If some valid data is read back */ + if (tmp & MAX3110_READ_DATA_AVAILABLE) + receive_char(max, (tmp & 0xff)); + + return ret; +} + +#define MAX_READ_LEN 20 +/* + * This is usually used to read data from SPIC RX FIFO, which doesn't + * need any delay like flushing character out. It returns how many + * valide bytes are read back + */ +static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf) +{ + u16 out[MAX_READ_LEN], in[MAX_READ_LEN]; + u8 *pbuf, valid_str[MAX_READ_LEN]; + int i, j, bytelen; + + if (len > MAX_READ_LEN) { + pr_err(PR_FMT "read len %d is too large\n", len); + return 0; + } + + bytelen = len * 2; + memset(out, 0, bytelen); + memset(in, 0, bytelen); + + if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1)) + return 0; + + /* If caller don't provide a buffer, then handle received char */ + pbuf = buf ? buf : valid_str; + + for (i = 0, j = 0; i < len; i++) { + if (in[i] & MAX3110_READ_DATA_AVAILABLE) + pbuf[j++] = (u8)(in[i] & 0xff); + } + + if (j && (pbuf == valid_str)) + receive_chars(max, valid_str, j); + + return j; +} + +static void serial_m3110_con_putchar(struct uart_port *port, int ch) +{ + struct uart_max3110 *max = + container_of(port, struct uart_max3110, port); + struct circ_buf *xmit = &max->con_xmit; + + if (uart_circ_chars_free(xmit)) { + xmit->buf[xmit->head] = (char)ch; + xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1); + } + + if (!atomic_read(&max->con_tx_need)) { + atomic_set(&max->con_tx_need, 1); + wake_up_process(max->main_thread); + } +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +static void serial_m3110_con_write(struct console *co, + const char *s, unsigned int count) +{ + if (!pmax) + return; + + uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); +} + +static int __init +serial_m3110_con_setup(struct console *co, char *options) +{ + struct uart_max3110 *max = pmax; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + pr_info(PR_FMT "setting up console\n"); + + if (!max) { + pr_err(PR_FMT "pmax is NULL, return"); + return -ENODEV; + } + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(&max->port, co, baud, parity, bits, flow); +} + +static struct tty_driver *serial_m3110_con_device(struct console *co, + int *index) +{ + struct uart_driver *p = co->data; + *index = co->index; + return p->tty_driver; +} + +static struct uart_driver serial_m3110_reg; +static struct console serial_m3110_console = { + .name = "ttyS", + .write = serial_m3110_con_write, + .device = serial_m3110_con_device, + .setup = serial_m3110_con_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &serial_m3110_reg, +}; + +#define MRST_CONSOLE (&serial_m3110_console) + +static unsigned int serial_m3110_tx_empty(struct uart_port *port) +{ + return 1; +} + +static void serial_m3110_stop_tx(struct uart_port *port) +{ + return; +} + +/* stop_rx will be called in spin_lock env */ +static void serial_m3110_stop_rx(struct uart_port *port) +{ + return; +} + +#define WORDS_PER_XFER 128 +static inline void send_circ_buf(struct uart_max3110 *max, + struct circ_buf *xmit) +{ + int len, left = 0; + u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER]; + u8 valid_str[WORDS_PER_XFER]; + int i, j; + + while (!uart_circ_empty(xmit)) { + left = uart_circ_chars_pending(xmit); + while (left) { + len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left; + + memset(obuf, 0, len * 2); + memset(ibuf, 0, len * 2); + for (i = 0; i < len; i++) { + obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG; + xmit->tail = (xmit->tail + 1) & + (UART_XMIT_SIZE - 1); + } + max3110_write_then_read(max, (u8 *)obuf, + (u8 *)ibuf, len * 2, 0); + + for (i = 0, j = 0; i < len; i++) { + if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) + valid_str[j++] = (u8)(ibuf[i] & 0xff); + } + + if (j) + receive_chars(max, valid_str, j); + + max->port.icount.tx += len; + left -= len; + } + } +} + +static void transmit_char(struct uart_max3110 *max) +{ + struct uart_port *port = &max->port; + struct circ_buf *xmit = &port->state->xmit; + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + return; + + send_circ_buf(max, xmit); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (uart_circ_empty(xmit)) + serial_m3110_stop_tx(port); +} + +/* This will be called by uart_write() and tty_write, can't + * go to sleep */ +static void serial_m3110_start_tx(struct uart_port *port) +{ + struct uart_max3110 *max = + container_of(port, struct uart_max3110, port); + + if (!atomic_read(&max->uart_tx_need)) { + atomic_set(&max->uart_tx_need, 1); + wake_up_process(max->main_thread); + } +} + +static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) +{ + struct uart_port *port = &max->port; + struct tty_struct *tty; + int usable; + + /* If uart is not opened, just return */ + if (!port->state) + return; + + tty = port->state->port.tty; + if (!tty) + return; /* receive some char before the tty is opened */ + + while (len) { + usable = tty_buffer_request_room(tty, len); + if (usable) { + tty_insert_flip_string(tty, str, usable); + str += usable; + port->icount.rx += usable; + tty_flip_buffer_push(tty); + } + len -= usable; + } +} + +static inline void receive_char(struct uart_max3110 *max, u8 ch) +{ + receive_chars(max, &ch, 1); +} + +static void max3110_console_receive(struct uart_max3110 *max) +{ + int loop = 1, num, total = 0; + u8 recv_buf[512], *pbuf; + + pbuf = recv_buf; + do { + num = max3110_read_multi(max, 8, pbuf); + + if (num) { + loop = 10; + pbuf += num; + total += num; + + if (total >= 500) { + receive_chars(max, recv_buf, total); + pbuf = recv_buf; + total = 0; + } + } + } while (--loop); + + if (total) + receive_chars(max, recv_buf, total); +} + +static int max3110_main_thread(void *_max) +{ + struct uart_max3110 *max = _max; + wait_queue_head_t *wq = &max->wq; + int ret = 0; + struct circ_buf *xmit = &max->con_xmit; + + init_waitqueue_head(wq); + pr_info(PR_FMT "start main thread\n"); + + do { + wait_event_interruptible(*wq, (atomic_read(&max->irq_pending) || + atomic_read(&max->con_tx_need) || + atomic_read(&max->uart_tx_need)) || + kthread_should_stop()); + max->mthread_up = 1; + +#ifdef CONFIG_MRST_MAX3110_IRQ + if (atomic_read(&max->irq_pending)) { + max3110_console_receive(max); + atomic_set(&max->irq_pending, 0); + } +#endif + + /* first handle console output */ + if (atomic_read(&max->con_tx_need)) { + send_circ_buf(max, xmit); + atomic_set(&max->con_tx_need, 0); + } + + /* handle uart output */ + if (atomic_read(&max->uart_tx_need)) { + transmit_char(max); + atomic_set(&max->uart_tx_need, 0); + } + max->mthread_up = 0; + } while (!kthread_should_stop()); + + return ret; +} + +#ifdef CONFIG_MRST_MAX3110_IRQ +static irqreturn_t serial_m3110_irq(int irq, void *dev_id) +{ + struct uart_max3110 *max = dev_id; + + /* max3110's irq is a falling edge, not level triggered, + * so no need to disable the irq */ + if (!atomic_read(&max->irq_pending)) { + atomic_inc(&max->irq_pending); + wake_up_process(max->main_thread); + } + return IRQ_HANDLED; +} +#else +/* if don't use RX IRQ, then need a thread to polling read */ +static int max3110_read_thread(void *_max) +{ + struct uart_max3110 *max = _max; + + pr_info(PR_FMT "start read thread\n"); + do { + if (!max->mthread_up) + max3110_console_receive(max); + + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 20); + } while (!kthread_should_stop()); + + return 0; +} +#endif + +static int serial_m3110_startup(struct uart_port *port) +{ + struct uart_max3110 *max = + container_of(port, struct uart_max3110, port); + u16 config = 0; + int ret = 0; + + if (port->line != 0) + pr_err(PR_FMT "uart port startup failed\n"); + + /* firstly disable all IRQ and config it to 115200, 8n1 */ + config = WC_TAG | WC_FIFO_ENABLE + | WC_1_STOPBITS + | WC_8BIT_WORD + | WC_BAUD_DR2; + ret = max3110_out(max, config); + + /* as we use thread to handle tx/rx, need set low latency */ + port->state->port.tty->low_latency = 1; + +#ifdef CONFIG_MRST_MAX3110_IRQ + ret = request_irq(max->irq, serial_m3110_irq, + IRQ_TYPE_EDGE_FALLING, "max3110", max); + if (ret) + return ret; + + /* enable RX IRQ only */ + config |= WC_RXA_IRQ_ENABLE; + max3110_out(max, config); +#else + /* if IRQ is disabled, start a read thread for input data */ + max->read_thread = + kthread_run(max3110_read_thread, max, "max3110_read"); +#endif + + max->cur_conf = config; + return 0; +} + +static void serial_m3110_shutdown(struct uart_port *port) +{ + struct uart_max3110 *max = + container_of(port, struct uart_max3110, port); + u16 config; + + if (max->read_thread) { + kthread_stop(max->read_thread); + max->read_thread = NULL; + } + +#ifdef CONFIG_MRST_MAX3110_IRQ + free_irq(max->irq, max); +#endif + + /* Disable interrupts from this port */ + config = WC_TAG | WC_SW_SHDI; + max3110_out(max, config); +} + +static void serial_m3110_release_port(struct uart_port *port) +{ +} + +static int serial_m3110_request_port(struct uart_port *port) +{ + return 0; +} + +static void serial_m3110_config_port(struct uart_port *port, int flags) +{ + /* give it fake type */ + port->type = PORT_PXA; +} + +static int +serial_m3110_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + /* we don't want the core code to modify any port params */ + return -EINVAL; +} + + +static const char *serial_m3110_type(struct uart_port *port) +{ + struct uart_max3110 *max = + container_of(port, struct uart_max3110, port); + return max->name; +} + +static void +serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + struct uart_max3110 *max = + container_of(port, struct uart_max3110, port); + unsigned char cval; + unsigned int baud, parity = 0; + int clk_div = -1; + u16 new_conf = max->cur_conf; + + switch (termios->c_cflag & CSIZE) { + case CS7: + cval = UART_LCR_WLEN7; + new_conf |= WC_7BIT_WORD; + break; + default: + case CS8: + cval = UART_LCR_WLEN8; + new_conf |= WC_8BIT_WORD; + break; + } + + baud = uart_get_baud_rate(port, termios, old, 0, 230400); + + /* first calc the div for 1.8MHZ clock case */ + switch (baud) { + case 300: + clk_div = WC_BAUD_DR384; + break; + case 600: + clk_div = WC_BAUD_DR192; + break; + case 1200: + clk_div = WC_BAUD_DR96; + break; + case 2400: + clk_div = WC_BAUD_DR48; + break; + case 4800: + clk_div = WC_BAUD_DR24; + break; + case 9600: + clk_div = WC_BAUD_DR12; + break; + case 19200: + clk_div = WC_BAUD_DR6; + break; + case 38400: + clk_div = WC_BAUD_DR3; + break; + case 57600: + clk_div = WC_BAUD_DR2; + break; + case 115200: + clk_div = WC_BAUD_DR1; + break; + case 230400: + if (max->clock & MAX3110_HIGH_CLK) + break; + default: + /* pick the previous baud rate */ + baud = max->baud; + clk_div = max->cur_conf & WC_BAUD_DIV_MASK; + tty_termios_encode_baud_rate(termios, baud, baud); + } + + if (max->clock & MAX3110_HIGH_CLK) { + clk_div += 1; + /* high clk version max3110 doesn't support B300 */ + if (baud == 300) + baud = 600; + if (baud == 230400) + clk_div = WC_BAUD_DR1; + tty_termios_encode_baud_rate(termios, baud, baud); + } + + new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div; + if (termios->c_cflag & CSTOPB) + new_conf |= WC_2_STOPBITS; + else + new_conf &= ~WC_2_STOPBITS; + + if (termios->c_cflag & PARENB) { + new_conf |= WC_PARITY_ENABLE; + parity |= UART_LCR_PARITY; + } else + new_conf &= ~WC_PARITY_ENABLE; + + if (!(termios->c_cflag & PARODD)) + parity |= UART_LCR_EPAR; + max->parity = parity; + + uart_update_timeout(port, termios->c_cflag, baud); + + new_conf |= WC_TAG; + if (new_conf != max->cur_conf) { + max3110_out(max, new_conf); + max->cur_conf = new_conf; + max->baud = baud; + } +} + +/* don't handle hw handshaking */ +static unsigned int serial_m3110_get_mctrl(struct uart_port *port) +{ + return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR; +} + +static void serial_m3110_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ +} + +static void serial_m3110_break_ctl(struct uart_port *port, int break_state) +{ +} + +static void serial_m3110_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ +} + +static void serial_m3110_enable_ms(struct uart_port *port) +{ +} + +struct uart_ops serial_m3110_ops = { + .tx_empty = serial_m3110_tx_empty, + .set_mctrl = serial_m3110_set_mctrl, + .get_mctrl = serial_m3110_get_mctrl, + .stop_tx = serial_m3110_stop_tx, + .start_tx = serial_m3110_start_tx, + .stop_rx = serial_m3110_stop_rx, + .enable_ms = serial_m3110_enable_ms, + .break_ctl = serial_m3110_break_ctl, + .startup = serial_m3110_startup, + .shutdown = serial_m3110_shutdown, + .set_termios = serial_m3110_set_termios, /* must have */ + .pm = serial_m3110_pm, + .type = serial_m3110_type, + .release_port = serial_m3110_release_port, + .request_port = serial_m3110_request_port, + .config_port = serial_m3110_config_port, + .verify_port = serial_m3110_verify_port, +}; + +static struct uart_driver serial_m3110_reg = { + .owner = THIS_MODULE, + .driver_name = "MRST serial", + .dev_name = "ttyS", + .major = TTY_MAJOR, + .minor = 64, + .nr = 1, + .cons = MRST_CONSOLE, +}; + +static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state) +{ + return 0; +} + +static int serial_m3110_resume(struct spi_device *spi) +{ + return 0; +} + +static struct dw_spi_chip spi0_uart = { + .poll_mode = 1, + .enable_dma = 0, + .type = SPI_FRF_SPI, +}; + +static int serial_m3110_probe(struct spi_device *spi) +{ + struct uart_max3110 *max; + int ret; + unsigned char *buffer; + + max = kzalloc(sizeof(*max), GFP_KERNEL); + if (!max) + return -ENOMEM; + + /* set spi info */ + spi->mode = SPI_MODE_0; + spi->bits_per_word = 16; + max->clock = MAX3110_HIGH_CLK; + spi->controller_data = &spi0_uart; + + spi_setup(spi); + + max->port.type = PORT_PXA; /* need apply for a max3110 type */ + max->port.fifosize = 2; /* only have 16b buffer */ + max->port.ops = &serial_m3110_ops; + max->port.line = 0; + max->port.dev = &spi->dev; + max->port.uartclk = 115200; + + max->spi = spi; + max->name = spi->modalias; /* use spi name as the name */ + max->irq = (u16)spi->irq; + + spin_lock_init(&max->lock); + + max->word_7bits = 0; + max->parity = 0; + max->baud = 0; + + max->cur_conf = 0; + atomic_set(&max->irq_pending, 0); + + buffer = (unsigned char *)__get_free_page(GFP_KERNEL); + if (!buffer) { + ret = -ENOMEM; + goto err_get_page; + } + max->con_xmit.buf = (unsigned char *)buffer; + max->con_xmit.head = max->con_xmit.tail = 0; + + max->main_thread = kthread_run(max3110_main_thread, + max, "max3110_main"); + if (IS_ERR(max->main_thread)) { + ret = PTR_ERR(max->main_thread); + goto err_kthread; + } + + pmax = max; + /* give membase a psudo value to pass serial_core's check */ + max->port.membase = (void *)0xff110000; + uart_add_one_port(&serial_m3110_reg, &max->port); + + return 0; + +err_kthread: + free_page((unsigned long)buffer); +err_get_page: + pmax = NULL; + kfree(max); + return ret; +} + +static int max3110_remove(struct spi_device *dev) +{ + struct uart_max3110 *max = pmax; + + if (!pmax) + return 0; + + pmax = NULL; + uart_remove_one_port(&serial_m3110_reg, &max->port); + + free_page((unsigned long)max->con_xmit.buf); + + if (max->main_thread) + kthread_stop(max->main_thread); + + kfree(max); + return 0; +} + +static struct spi_driver uart_max3110_driver = { + .driver = { + .name = "spi_max3111", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = serial_m3110_probe, + .remove = __devexit_p(max3110_remove), + .suspend = serial_m3110_suspend, + .resume = serial_m3110_resume, +}; + + +int __init serial_m3110_init(void) +{ + int ret = 0; + + ret = uart_register_driver(&serial_m3110_reg); + if (ret) + return ret; + + ret = spi_register_driver(&uart_max3110_driver); + if (ret) + uart_unregister_driver(&serial_m3110_reg); + + return ret; +} + +void __exit serial_m3110_exit(void) +{ + spi_unregister_driver(&uart_max3110_driver); + uart_unregister_driver(&serial_m3110_reg); +} + +module_init(serial_m3110_init); +module_exit(serial_m3110_exit); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("max3110-uart"); diff --git a/drivers/serial/mrst_max3110.h b/drivers/serial/mrst_max3110.h new file mode 100644 index 000000000000..363478acb2c3 --- /dev/null +++ b/drivers/serial/mrst_max3110.h @@ -0,0 +1,59 @@ +#ifndef _MRST_MAX3110_H +#define _MRST_MAX3110_H + +#define MAX3110_HIGH_CLK 0x1 /* 3.6864 MHZ */ +#define MAX3110_LOW_CLK 0x0 /* 1.8432 MHZ */ + +/* status bits for all 4 MAX3110 operate modes */ +#define MAX3110_READ_DATA_AVAILABLE (1 << 15) +#define MAX3110_WRITE_BUF_EMPTY (1 << 14) + +#define WC_TAG (3 << 14) +#define RC_TAG (1 << 14) +#define WD_TAG (2 << 14) +#define RD_TAG (0 << 14) + +/* bits def for write configuration */ +#define WC_FIFO_ENABLE_MASK (1 << 13) +#define WC_FIFO_ENABLE (0 << 13) + +#define WC_SW_SHDI (1 << 12) + +#define WC_IRQ_MASK (0xF << 8) +#define WC_TXE_IRQ_ENABLE (1 << 11) /* TX empty irq */ +#define WC_RXA_IRQ_ENABLE (1 << 10) /* RX availabe irq */ +#define WC_PAR_HIGH_IRQ_ENABLE (1 << 9) +#define WC_REC_ACT_IRQ_ENABLE (1 << 8) + +#define WC_IRDA_ENABLE (1 << 7) + +#define WC_STOPBITS_MASK (1 << 6) +#define WC_2_STOPBITS (1 << 6) +#define WC_1_STOPBITS (0 << 6) + +#define WC_PARITY_ENABLE_MASK (1 << 5) +#define WC_PARITY_ENABLE (1 << 5) + +#define WC_WORDLEN_MASK (1 << 4) +#define WC_7BIT_WORD (1 << 4) +#define WC_8BIT_WORD (0 << 4) + +#define WC_BAUD_DIV_MASK (0xF) +#define WC_BAUD_DR1 (0x0) +#define WC_BAUD_DR2 (0x1) +#define WC_BAUD_DR4 (0x2) +#define WC_BAUD_DR8 (0x3) +#define WC_BAUD_DR16 (0x4) +#define WC_BAUD_DR32 (0x5) +#define WC_BAUD_DR64 (0x6) +#define WC_BAUD_DR128 (0x7) +#define WC_BAUD_DR3 (0x8) +#define WC_BAUD_DR6 (0x9) +#define WC_BAUD_DR12 (0xA) +#define WC_BAUD_DR24 (0xB) +#define WC_BAUD_DR48 (0xC) +#define WC_BAUD_DR96 (0xD) +#define WC_BAUD_DR192 (0xE) +#define WC_BAUD_DR384 (0xF) + +#endif -- cgit v1.2.3 From 99dd3f6b7e2ef5179f67503a401a99141708687a Mon Sep 17 00:00:00 2001 From: jianwei.yang Date: Wed, 16 Jun 2010 14:46:49 +0100 Subject: max3110 sanity check a register MAX3111 is the SPI/UART IC installed on the MRST SPI Port Card as a serial debug goal, and the SPI Port Card will be frequently mounted and unmounted from the main board by developers depending whether debug serial is required or not. As the MAX3111 has no subvendor or product id registers available, the patch will try to access one register to decide if this IC is present or not. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/mrst_max3110.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c index 273e7cbe74cd..f9c01aeb6f80 100644 --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c @@ -721,7 +721,7 @@ static int serial_m3110_probe(struct spi_device *spi) struct uart_max3110 *max; int ret; unsigned char *buffer; - + u16 res; max = kzalloc(sizeof(*max), GFP_KERNEL); if (!max) return -ENOMEM; @@ -753,7 +753,16 @@ static int serial_m3110_probe(struct spi_device *spi) max->cur_conf = 0; atomic_set(&max->irq_pending, 0); - + /* Check if reading configuration register returns something sane */ + + res = RC_TAG; + ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0); + if (ret < 0 || res == 0 || res == 0xffff) { + printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)", + res); + ret = -ENODEV; + goto err_get_page; + } buffer = (unsigned char *)__get_free_page(GFP_KERNEL); if (!buffer) { ret = -ENOMEM; -- cgit v1.2.3 From 68c16b4117cc746a91897d629b61e5f2af18c225 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 17 Jun 2010 11:02:06 +0100 Subject: serial: replace open coded mutex with a real mutex in mrst_max3110.c The mrst_max3110.c driver uses an open coded, non atomic variable to create exclusion between two of its worker threads. More than that, while the main thread does a proper set-work-clear sequence, the other thread only does a test, with the result that no actual exclusion is happening. this patch replaces this open coded variable with a proper mutex in addition, the 'lock' spinlock is removed from the per adapter structure, the lock was only ever initialized but never used Signed-off-by: Arjan van de Ven Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/mrst_max3110.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c index f9c01aeb6f80..0341853e0c28 100644 --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c @@ -56,8 +56,7 @@ struct uart_max3110 { wait_queue_head_t wq; struct task_struct *main_thread; struct task_struct *read_thread; - int mthread_up; - spinlock_t lock; + struct mutex thread_mutex;; u32 baud; u16 cur_conf; @@ -397,7 +396,8 @@ static int max3110_main_thread(void *_max) atomic_read(&max->con_tx_need) || atomic_read(&max->uart_tx_need)) || kthread_should_stop()); - max->mthread_up = 1; + + mutex_lock(&max->thread_mutex); #ifdef CONFIG_MRST_MAX3110_IRQ if (atomic_read(&max->irq_pending)) { @@ -417,7 +417,7 @@ static int max3110_main_thread(void *_max) transmit_char(max); atomic_set(&max->uart_tx_need, 0); } - max->mthread_up = 0; + mutex_unlock(&max->thread_mutex); } while (!kthread_should_stop()); return ret; @@ -444,8 +444,9 @@ static int max3110_read_thread(void *_max) pr_info(PR_FMT "start read thread\n"); do { - if (!max->mthread_up) - max3110_console_receive(max); + mutex_lock(&max->thread_mutex); + max3110_console_receive(max); + mutex_unlock(&max->thread_mutex); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 20); @@ -745,7 +746,7 @@ static int serial_m3110_probe(struct spi_device *spi) max->name = spi->modalias; /* use spi name as the name */ max->irq = (u16)spi->irq; - spin_lock_init(&max->lock); + mutex_init(&max->thread_mutex); max->word_7bits = 0; max->parity = 0; -- cgit v1.2.3 From d6e679b474c096f1125087e789e7af8886de39d3 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 17 Jun 2010 11:02:15 +0100 Subject: serial: fix wakup races in the mrst_max3110 driver The mrst_max3110 driver had a set of unsafe wakeup sequences along the following line: if (!atomic_read(&foo)) { atomic_set(&foo, 1); wake_up(worker_thread); } and the worker thread would do if (atomic_read(&foo)) { do_work(); atomic_set(&foo, 0); } which can result in various missed wakups due to test-then-set races, as well as due to clear-after-work instead of clear-before-work. This patch fixes these races by using the proper bit test-and-set operations, and by doing clear-before-work. Signed-off-by: Arjan van de Ven Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/mrst_max3110.c | 46 +++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c index 0341853e0c28..f6ad1ecbff79 100644 --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c @@ -48,6 +48,10 @@ #define PR_FMT "mrst_max3110: " +#define UART_TX_NEEDED 1 +#define CON_TX_NEEDED 2 +#define BIT_IRQ_PENDING 3 + struct uart_max3110 { struct uart_port port; struct spi_device *spi; @@ -63,15 +67,13 @@ struct uart_max3110 { u8 clock; u8 parity, word_7bits; - atomic_t uart_tx_need; + unsigned long uart_flags; /* console related */ struct circ_buf con_xmit; - atomic_t con_tx_need; /* irq related */ u16 irq; - atomic_t irq_pending; }; /* global data structure, may need be removed */ @@ -176,10 +178,9 @@ static void serial_m3110_con_putchar(struct uart_port *port, int ch) xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1); } - if (!atomic_read(&max->con_tx_need)) { - atomic_set(&max->con_tx_need, 1); + + if (!test_and_set_bit(CON_TX_NEEDED, &max->uart_flags)) wake_up_process(max->main_thread); - } } /* @@ -318,10 +319,8 @@ static void serial_m3110_start_tx(struct uart_port *port) struct uart_max3110 *max = container_of(port, struct uart_max3110, port); - if (!atomic_read(&max->uart_tx_need)) { - atomic_set(&max->uart_tx_need, 1); + if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) wake_up_process(max->main_thread); - } } static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) @@ -392,32 +391,23 @@ static int max3110_main_thread(void *_max) pr_info(PR_FMT "start main thread\n"); do { - wait_event_interruptible(*wq, (atomic_read(&max->irq_pending) || - atomic_read(&max->con_tx_need) || - atomic_read(&max->uart_tx_need)) || - kthread_should_stop()); + wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop()); mutex_lock(&max->thread_mutex); -#ifdef CONFIG_MRST_MAX3110_IRQ - if (atomic_read(&max->irq_pending)) { + if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags)) max3110_console_receive(max); - atomic_set(&max->irq_pending, 0); - } -#endif /* first handle console output */ - if (atomic_read(&max->con_tx_need)) { + if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags)) send_circ_buf(max, xmit); - atomic_set(&max->con_tx_need, 0); - } /* handle uart output */ - if (atomic_read(&max->uart_tx_need)) { + if (test_and_clear_bit(UART_TX_NEEDED, &max->uart_flags)) transmit_char(max); - atomic_set(&max->uart_tx_need, 0); - } + mutex_unlock(&max->thread_mutex); + } while (!kthread_should_stop()); return ret; @@ -430,10 +420,9 @@ static irqreturn_t serial_m3110_irq(int irq, void *dev_id) /* max3110's irq is a falling edge, not level triggered, * so no need to disable the irq */ - if (!atomic_read(&max->irq_pending)) { - atomic_inc(&max->irq_pending); + if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) wake_up_process(max->main_thread); - } + return IRQ_HANDLED; } #else @@ -753,7 +742,8 @@ static int serial_m3110_probe(struct spi_device *spi) max->baud = 0; max->cur_conf = 0; - atomic_set(&max->irq_pending, 0); + max->uart_flags = 0; + /* Check if reading configuration register returns something sane */ res = RC_TAG; -- cgit v1.2.3 From 192251352f912bccfb942ea35801d2357f11f592 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Jun 2010 22:52:51 +0200 Subject: tty: serial - fix various misuses/mishandlings of port->tty Make it robust against hang up events. In most cases we can do this simply by passing the right things in the first place. Signed-off-by: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 109 ++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 49 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 7f2830709512..12ee7e0f99ce 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -58,7 +58,7 @@ static struct lock_class_key port_lock_key; #define uart_console(port) (0) #endif -static void uart_change_speed(struct uart_state *state, +static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); static void uart_change_pm(struct uart_state *state, int pm_state); @@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) * Startup the port. This will be called once per open. All calls * will be serialised by the per-port mutex. */ -static int uart_startup(struct uart_state *state, int init_hw) +static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw) { struct uart_port *uport = state->uart_port; struct tty_port *port = &state->port; @@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw) * once we have successfully opened the port. Also set * up the tty->alt_speed kludge */ - set_bit(TTY_IO_ERROR, &port->tty->flags); + set_bit(TTY_IO_ERROR, &tty->flags); if (uport->type == PORT_UNKNOWN) return 0; @@ -177,26 +177,26 @@ static int uart_startup(struct uart_state *state, int init_hw) /* * Initialise the hardware port settings. */ - uart_change_speed(state, NULL); + uart_change_speed(tty, state, NULL); /* * Setup the RTS and DTR signals once the * port is open and ready to respond. */ - if (port->tty->termios->c_cflag & CBAUD) + if (tty->termios->c_cflag & CBAUD) uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); } if (port->flags & ASYNC_CTS_FLOW) { spin_lock_irq(&uport->lock); if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) - port->tty->hw_stopped = 1; + tty->hw_stopped = 1; spin_unlock_irq(&uport->lock); } set_bit(ASYNCB_INITIALIZED, &port->flags); - clear_bit(TTY_IO_ERROR, &port->tty->flags); + clear_bit(TTY_IO_ERROR, &tty->flags); } if (retval && capable(CAP_SYS_ADMIN)) @@ -210,11 +210,10 @@ static int uart_startup(struct uart_state *state, int init_hw) * DTR is dropped if the hangup on close termio flag is on. Calls to * uart_shutdown are serialised by the per-port semaphore. */ -static void uart_shutdown(struct uart_state *state) +static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) { struct uart_port *uport = state->uart_port; struct tty_port *port = &state->port; - struct tty_struct *tty = port->tty; /* * Set the TTY IO error marker @@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) EXPORT_SYMBOL(uart_get_divisor); /* FIXME: Consistent locking policy */ -static void -uart_change_speed(struct uart_state *state, struct ktermios *old_termios) +static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, + struct ktermios *old_termios) { struct tty_port *port = &state->port; - struct tty_struct *tty = port->tty; struct uart_port *uport = state->uart_port; struct ktermios *termios; @@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) uport->ops->set_termios(uport, termios, old_termios); } -static inline int -__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) +static inline int __uart_put_char(struct uart_port *port, + struct circ_buf *circ, unsigned char c) { unsigned long flags; int ret = 0; @@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_struct *tty) uart_start(tty); } -static int -uart_write(struct tty_struct *tty, const unsigned char *buf, int count) +static int uart_write(struct tty_struct *tty, + const unsigned char *buf, int count) { struct uart_state *state = tty->driver_data; struct uart_port *port; @@ -675,7 +673,7 @@ static int uart_get_info(struct uart_state *state, return 0; } -static int uart_set_info(struct uart_state *state, +static int uart_set_info(struct tty_struct *tty, struct uart_state *state, struct serial_struct __user *newinfo) { struct serial_struct new_serial; @@ -770,7 +768,7 @@ static int uart_set_info(struct uart_state *state, * We need to shutdown the serial port at the old * port/type/irq combination. */ - uart_shutdown(state); + uart_shutdown(tty, state); } if (change_port) { @@ -869,25 +867,27 @@ static int uart_set_info(struct uart_state *state, "is deprecated.\n", current->comm, tty_name(port->tty, buf)); } - uart_change_speed(state, NULL); + uart_change_speed(tty, state, NULL); } } else - retval = uart_startup(state, 1); + retval = uart_startup(tty, state, 1); exit: mutex_unlock(&port->mutex); return retval; } - -/* - * uart_get_lsr_info - get line status register info. - * Note: uart_ioctl protects us against hangups. +/** + * uart_get_lsr_info - get line status register info + * @tty: tty associated with the UART + * @state: UART being queried + * @value: returned modem value + * + * Note: uart_ioctl protects us against hangups. */ -static int uart_get_lsr_info(struct uart_state *state, - unsigned int __user *value) +static int uart_get_lsr_info(struct tty_struct *tty, + struct uart_state *state, unsigned int __user *value) { struct uart_port *uport = state->uart_port; - struct tty_port *port = &state->port; unsigned int result; result = uport->ops->tx_empty(uport); @@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart_state *state, */ if (uport->x_char || ((uart_circ_chars_pending(&state->xmit) > 0) && - !port->tty->stopped && !port->tty->hw_stopped)) + !tty->stopped && !tty->hw_stopped)) result &= ~TIOCSER_TEMT; return put_user(result, value); @@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) return 0; } -static int uart_do_autoconfig(struct uart_state *state) +static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state) { struct uart_port *uport = state->uart_port; struct tty_port *port = &state->port; @@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uart_state *state) ret = -EBUSY; if (tty_port_users(port) == 1) { - uart_shutdown(state); + uart_shutdown(tty, state); /* * If we already have a port type configured, @@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uart_state *state) */ uport->ops->config_port(uport, flags); - ret = uart_startup(state, 1); + ret = uart_startup(tty, state, 1); } mutex_unlock(&port->mutex); return ret; @@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, break; case TIOCSSERIAL: - ret = uart_set_info(state, uarg); + ret = uart_set_info(tty, state, uarg); break; case TIOCSERCONFIG: - ret = uart_do_autoconfig(state); + ret = uart_do_autoconfig(tty, state); break; case TIOCSERGWILD: /* obsolete */ @@ -1172,7 +1172,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, */ switch (cmd) { case TIOCSERGETLSR: /* Get line status register */ - ret = uart_get_lsr_info(state, uarg); + ret = uart_get_lsr_info(tty, state, uarg); break; default: { @@ -1219,7 +1219,7 @@ static void uart_set_termios(struct tty_struct *tty, return; } - uart_change_speed(state, old_termios); + uart_change_speed(tty, state, old_termios); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) @@ -1335,7 +1335,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) uart_wait_until_sent(tty, uport->timeout); } - uart_shutdown(state); + uart_shutdown(tty, state); uart_flush_buffer(tty); tty_ldisc_flush(tty); @@ -1436,7 +1436,7 @@ static void uart_hangup(struct tty_struct *tty) mutex_lock(&port->mutex); if (port->flags & ASYNC_NORMAL_ACTIVE) { uart_flush_buffer(tty); - uart_shutdown(state); + uart_shutdown(tty, state); port->count = 0; clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); tty_port_tty_set(port, NULL); @@ -1446,15 +1446,19 @@ static void uart_hangup(struct tty_struct *tty) mutex_unlock(&port->mutex); } -/* - * Copy across the serial console cflag setting into the termios settings - * for the initial open of the port. This allows continuity between the - * kernel settings, and the settings init adopts when it opens the port - * for the first time. +/** + * uart_update_termios - update the terminal hw settings + * @tty: tty associated with UART + * @state: UART to update + * + * Copy across the serial console cflag setting into the termios settings + * for the initial open of the port. This allows continuity between the + * kernel settings, and the settings init adopts when it opens the port + * for the first time. */ -static void uart_update_termios(struct uart_state *state) +static void uart_update_termios(struct tty_struct *tty, + struct uart_state *state) { - struct tty_struct *tty = state->port.tty; struct uart_port *port = state->uart_port; if (uart_console(port) && port->cons->cflag) { @@ -1471,7 +1475,7 @@ static void uart_update_termios(struct uart_state *state) /* * Make termios settings take effect. */ - uart_change_speed(state, NULL); + uart_change_speed(tty, state, NULL); /* * And finally enable the RTS and DTR signals. @@ -1668,7 +1672,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * Start up the serial port. */ - retval = uart_startup(state, 0); + retval = uart_startup(tty, state, 0); /* * If we succeeded, wait until the port is ready. @@ -1683,7 +1687,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) { set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); - uart_update_termios(state); + uart_update_termios(tty, state); } fail: @@ -2010,9 +2014,13 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) struct tty_port *port = &state->port; struct device *tty_dev; struct uart_match match = {uport, drv}; + struct tty_struct *tty; mutex_lock(&port->mutex); + /* Must be inside the mutex lock until we convert to tty_port */ + tty = port->tty; + tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (device_may_wakeup(tty_dev)) { enable_irq_wake(uport->irq); @@ -2105,9 +2113,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) ops->set_mctrl(uport, 0); spin_unlock_irq(&uport->lock); if (console_suspend_enabled || !uart_console(uport)) { + /* Protected by port mutex for now */ + struct tty_struct *tty = port->tty; ret = ops->startup(uport); if (ret == 0) { - uart_change_speed(state, NULL); + if (tty) + uart_change_speed(tty, state, NULL); spin_lock_irq(&uport->lock); ops->set_mctrl(uport, uport->mctrl); ops->start_tx(uport); @@ -2119,7 +2130,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) * Clear the "initialized" flag so we won't try * to call the low level drivers shutdown method. */ - uart_shutdown(state); + uart_shutdown(tty, state); } } -- cgit v1.2.3 From eab4f5af6b07009d1fc48bac5f3215c0cbfb2fc3 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Jun 2010 22:52:52 +0200 Subject: tty: serial - fix tty back references in termios One or two drivers go poking back into the tty from the termios setting routine in unsafe ways. We don't need to pass the tty down because the [ab]users are just using it to get at things they can get at anyway. This leaves low_latency setting to sort out along with set_ldisc use. Signed-off-by: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/serial/21285.c | 10 +++------- drivers/serial/imx.c | 10 ++++------ drivers/serial/ioc3_serial.c | 9 +++++---- drivers/serial/ioc4_serial.c | 9 +++++---- drivers/serial/max3100.c | 7 ++----- 5 files changed, 19 insertions(+), 26 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 8681f1345056..d89aa38c5cf0 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -216,7 +216,7 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; - unsigned int baud, quot, h_lcr; + unsigned int baud, quot, h_lcr, b; /* * We don't support modem control lines. @@ -234,12 +234,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); - - if (port->state && port->state->port.tty) { - struct tty_struct *tty = port->state->port.tty; - unsigned int b = port->uartclk / (16 * quot); - tty_encode_baud_rate(tty, b, b); - } + b = port->uartclk / (16 * quot); + tty_termios_encode_baud_rate(termios, b, b); switch (termios->c_cflag & CSIZE) { case CS5: diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index eacb588a9345..66ecc7ab6dab 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -909,13 +909,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, rational_best_approximation(16 * div * baud, sport->port.uartclk, 1 << 16, 1 << 16, &num, &denom); - if (port->state && port->state->port.tty) { - tdiv64 = sport->port.uartclk; - tdiv64 *= num; - do_div(tdiv64, denom * 16 * div); - tty_encode_baud_rate(sport->port.state->port.tty, + tdiv64 = sport->port.uartclk; + tdiv64 *= num; + do_div(tdiv64, denom * 16 * div); + tty_termios_encode_baud_rate(termios, (speed_t)tdiv64, (speed_t)tdiv64); - } num -= 1; denom -= 1; diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index f164ba4eba02..93de907b1208 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c @@ -954,12 +954,13 @@ ioc3_change_speed(struct uart_port *the_port, struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc3_port *port = get_ioc3_port(the_port); - unsigned int cflag; + unsigned int cflag, iflag; int baud; int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; struct uart_state *state = the_port->state; cflag = new_termios->c_cflag; + iflag = new_termios->c_iflag; switch (cflag & CSIZE) { case CS5: @@ -1000,12 +1001,12 @@ ioc3_change_speed(struct uart_port *the_port, state->port.tty->low_latency = 1; - if (I_IGNPAR(state->port.tty)) + if (iflag & IGNPAR) the_port->ignore_status_mask &= ~(N_PARITY_ERROR | N_FRAMING_ERROR); - if (I_IGNBRK(state->port.tty)) { + if (iflag & IGNBRK) { the_port->ignore_status_mask &= ~N_BREAK; - if (I_IGNPAR(state->port.tty)) + if (iflag & IGNPAR) the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; } if (!(cflag & CREAD)) { diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 8ad28fc64926..fcfe82653ac8 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -1685,11 +1685,12 @@ ioc4_change_speed(struct uart_port *the_port, { struct ioc4_port *port = get_ioc4_port(the_port, 0); int baud, bits; - unsigned cflag; + unsigned cflag, iflag; int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; struct uart_state *state = the_port->state; cflag = new_termios->c_cflag; + iflag = new_termios->c_iflag; switch (cflag & CSIZE) { case CS5: @@ -1741,12 +1742,12 @@ ioc4_change_speed(struct uart_port *the_port, state->port.tty->low_latency = 1; - if (I_IGNPAR(state->port.tty)) + if (iflag & IGNPAR) the_port->ignore_status_mask &= ~(N_PARITY_ERROR | N_FRAMING_ERROR); - if (I_IGNBRK(state->port.tty)) { + if (iflag & IGNBRK) { the_port->ignore_status_mask &= ~N_BREAK; - if (I_IGNPAR(state->port.tty)) + if (iflag & IGNPAR) the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; } if (!(cflag & CREAD)) { diff --git a/drivers/serial/max3100.c b/drivers/serial/max3100.c index 3351c3bd59e4..beb1afa27d8d 100644 --- a/drivers/serial/max3100.c +++ b/drivers/serial/max3100.c @@ -430,17 +430,14 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, int baud = 0; unsigned cflag; u32 param_new, param_mask, parity = 0; - struct tty_struct *tty = s->port.state->port.tty; dev_dbg(&s->spi->dev, "%s\n", __func__); - if (!tty) - return; cflag = termios->c_cflag; param_new = 0; param_mask = 0; - baud = tty_get_baud_rate(tty); + baud = tty_termios_baud_rate(termios); param_new = s->conf & MAX3100_BAUD; switch (baud) { case 300: @@ -485,7 +482,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, default: baud = s->baud; } - tty_encode_baud_rate(tty, baud, baud); + tty_termios_encode_baud_rate(termios, baud, baud); s->baud = baud; param_mask |= MAX3100_BAUD; -- cgit v1.2.3 From d87d9b7d19f04b16c4406d3c0feeca10090e0ada Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Jun 2010 22:52:53 +0200 Subject: tty: serial - fix tty referencing in set_ldisc Pass down the ldisc number so that the drivers don't have to peek into the tty object themselves. This lets us get rid of another case of back referencing port to tty which we don't want (because of races versus hangup/close). Signed-off-by: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/serial/bfin_5xx.c | 7 ++----- drivers/serial/serial_core.c | 2 +- include/linux/serial_core.h | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 511cbf687877..a9eff2b18eab 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -957,15 +957,12 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser) * Enable the IrDA function if tty->ldisc.num is N_IRDA. * In other cases, disable IrDA function. */ -static void bfin_serial_set_ldisc(struct uart_port *port) +static void bfin_serial_set_ldisc(struct uart_port *port, int ld) { int line = port->line; unsigned short val; - if (line >= port->state->port.tty->driver->num) - return; - - switch (port->state->port.tty->termios->c_line) { + switch (ld) { case N_IRDA: val = UART_GET_GCTL(&bfin_serial_ports[line]); val |= (IREN | RPOLC); diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 12ee7e0f99ce..570dca2935e2 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1194,7 +1194,7 @@ static void uart_set_ldisc(struct tty_struct *tty) struct uart_port *uport = state->uart_port; if (uport->ops->set_ldisc) - uport->ops->set_ldisc(uport); + uport->ops->set_ldisc(uport, tty->termios->c_line); } static void uart_set_termios(struct tty_struct *tty, diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f10db6e5f3b5..32928161fab6 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -220,7 +220,7 @@ struct uart_ops { void (*flush_buffer)(struct uart_port *); void (*set_termios)(struct uart_port *, struct ktermios *new, struct ktermios *old); - void (*set_ldisc)(struct uart_port *); + void (*set_ldisc)(struct uart_port *, int new); void (*pm)(struct uart_port *, unsigned int state, unsigned int oldstate); int (*set_wake)(struct uart_port *, unsigned int state); -- cgit v1.2.3 From 61cd8a21d8a9fb4b11111270cf2d3aa919c20624 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Jun 2010 22:52:57 +0200 Subject: serial: Change the wait for carrier locking We want to push the lock/unlock into the helper functions so that we can prepare to move to using the tty_port helper. The expansion initially comes out a bit ugly but its worth the temporary expansion IMHO just so we can produce a nice testable series of changes. Signed-off-by: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 570dca2935e2..424b1c7e50c4 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1272,6 +1272,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) struct uart_state *state = tty->driver_data; struct tty_port *port; struct uart_port *uport; + unsigned long flags; BUG_ON(!kernel_locked()); @@ -1284,9 +1285,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp) pr_debug("uart_close(%d) called\n", uport->line); mutex_lock(&port->mutex); + spin_lock_irqsave(&port->lock, flags); - if (tty_hung_up_p(filp)) + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&port->lock, flags); goto done; + } if ((tty->count == 1) && (port->count != 1)) { /* @@ -1305,8 +1309,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty->name, port->count); port->count = 0; } - if (port->count) + if (port->count) { + spin_unlock_irqrestore(&port->lock, flags); goto done; + } /* * Now we wait for the transmit buffer to clear; and we notify @@ -1314,6 +1320,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * setting tty->closing. */ tty->closing = 1; + spin_unlock_irqrestore(&port->lock, flags); if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait)); @@ -1340,20 +1347,26 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty_ldisc_flush(tty); - tty->closing = 0; tty_port_tty_set(port, NULL); + spin_lock_irqsave(&port->lock, flags); + tty->closing = 0; if (port->blocked_open) { + spin_unlock_irqrestore(&port->lock, flags); if (port->close_delay) msleep_interruptible(port->close_delay); + spin_lock_irqsave(&port->lock, flags); } else if (!uart_console(uport)) { + spin_unlock_irqrestore(&port->lock, flags); uart_change_pm(state, 3); + spin_lock_irqsave(&port->lock, flags); } /* * Wake up anyone trying to open this port. */ clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); + spin_unlock_irqrestore(&port->lock, flags); wake_up_interruptible(&port->open_wait); done: @@ -1429,6 +1442,7 @@ static void uart_hangup(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; struct tty_port *port = &state->port; + unsigned long flags; BUG_ON(!kernel_locked()); pr_debug("uart_hangup(%d)\n", state->uart_port->line); @@ -1437,8 +1451,10 @@ static void uart_hangup(struct tty_struct *tty) if (port->flags & ASYNC_NORMAL_ACTIVE) { uart_flush_buffer(tty); uart_shutdown(tty, state); + spin_lock_irqsave(&port->lock, flags); port->count = 0; clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); + spin_unlock_irqrestore(&port->lock, flags); tty_port_tty_set(port, NULL); wake_up_interruptible(&port->open_wait); wake_up_interruptible(&port->delta_msr_wait); @@ -1496,9 +1512,13 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) struct uart_port *uport = state->uart_port; struct tty_port *port = &state->port; unsigned int mctrl; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) + port->count--; port->blocked_open++; - port->count--; + spin_unlock_irqrestore(&port->lock, flags); add_wait_queue(&port->open_wait, &wait); while (1) { @@ -1535,23 +1555,26 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) * not set RTS here - we want to make sure we catch * the data from the modem. */ - if (port->tty->termios->c_cflag & CBAUD) + if (port->tty->termios->c_cflag & CBAUD) { + mutex_lock(&port->mutex); uart_set_mctrl(uport, TIOCM_DTR); + mutex_unlock(&port->mutex); + } /* * and wait for the carrier to indicate that the * modem is ready for us. */ + mutex_lock(&port->mutex); spin_lock_irq(&uport->lock); uport->ops->enable_ms(uport); mctrl = uport->ops->get_mctrl(uport); spin_unlock_irq(&uport->lock); + mutex_unlock(&port->mutex); if (mctrl & TIOCM_CAR) break; - mutex_unlock(&port->mutex); schedule(); - mutex_lock(&port->mutex); if (signal_pending(current)) break; @@ -1559,8 +1582,11 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) set_current_state(TASK_RUNNING); remove_wait_queue(&port->open_wait, &wait); - port->count++; + spin_lock_irqsave(&port->lock, flags); + if (!tty_hung_up_p(filp)) + port->count++; port->blocked_open--; + spin_unlock_irqrestore(&port->lock, flags); if (signal_pending(current)) return -ERESTARTSYS; @@ -1677,9 +1703,9 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * If we succeeded, wait until the port is ready. */ + mutex_unlock(&port->mutex); if (retval == 0) retval = uart_block_til_ready(filp, state); - mutex_unlock(&port->mutex); /* * If this is the first open to succeed, adjust things to suit. -- cgit v1.2.3 From de0c8cb314cc737c47a00de33cd6246accf94192 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Jun 2010 22:52:58 +0200 Subject: serial: add port helpers We can make this the same as the ones that will be needed by the tty_port helper logic that we want to move to but still call them from the existing code base. Signed-off-by: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 51 ++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 14 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 424b1c7e50c4..2379045e0871 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1501,6 +1501,34 @@ static void uart_update_termios(struct tty_struct *tty, } } +static int uart_carrier_raised(struct tty_port *port) +{ + struct uart_state *state = container_of(port, struct uart_state, port); + struct uart_port *uport = state->uart_port; + int mctrl; + mutex_lock(&port->mutex); + spin_lock_irq(&uport->lock); + uport->ops->enable_ms(uport); + mctrl = uport->ops->get_mctrl(uport); + spin_unlock_irq(&uport->lock); + mutex_unlock(&port->mutex); + if (mctrl & TIOCM_CAR) + return 1; + return 0; +} + +static void uart_dtr_rts(struct tty_port *port, int onoff) +{ + struct uart_state *state = container_of(port, struct uart_state, port); + struct uart_port *uport = state->uart_port; + mutex_lock(&port->mutex); + if (onoff) + uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); + else + uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); + mutex_unlock(&port->mutex); +} + /* * Block the open until the port is ready. We must be called with * the per-port semaphore held. @@ -1509,9 +1537,7 @@ static int uart_block_til_ready(struct file *filp, struct uart_state *state) { DECLARE_WAITQUEUE(wait, current); - struct uart_port *uport = state->uart_port; struct tty_port *port = &state->port; - unsigned int mctrl; unsigned long flags; spin_lock_irqsave(&port->lock, flags); @@ -1555,23 +1581,14 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) * not set RTS here - we want to make sure we catch * the data from the modem. */ - if (port->tty->termios->c_cflag & CBAUD) { - mutex_lock(&port->mutex); - uart_set_mctrl(uport, TIOCM_DTR); - mutex_unlock(&port->mutex); - } + if (port->tty->termios->c_cflag & CBAUD) + tty_port_raise_dtr_rts(port); /* * and wait for the carrier to indicate that the * modem is ready for us. */ - mutex_lock(&port->mutex); - spin_lock_irq(&uport->lock); - uport->ops->enable_ms(uport); - mctrl = uport->ops->get_mctrl(uport); - spin_unlock_irq(&uport->lock); - mutex_unlock(&port->mutex); - if (mctrl & TIOCM_CAR) + if (tty_port_carrier_raised(port)) break; schedule(); @@ -2349,6 +2366,11 @@ static const struct tty_operations uart_ops = { #endif }; +static const struct tty_port_operations uart_port_ops = { + .carrier_raised = uart_carrier_raised, + .dtr_rts = uart_dtr_rts, +}; + /** * uart_register_driver - register a driver with the uart core layer * @drv: low level driver structure @@ -2405,6 +2427,7 @@ int uart_register_driver(struct uart_driver *drv) struct tty_port *port = &state->port; tty_port_init(port); + port->ops = &uart_port_ops; port->close_delay = 500; /* .5 seconds */ port->closing_wait = 30000; /* 30 seconds */ tasklet_init(&state->tlet, uart_tasklet_action, -- cgit v1.2.3 From 24fcc7c8cd0fcabcf37d455abe3501b3196fcf64 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Jun 2010 22:52:59 +0200 Subject: serial: trim locking on the helpers The port mutex protects port->tty, but these paths never need to walk from port->tty. They do need the low level lock as the API expects that but they already also take it. Thus we can drop the extra mutex lock calls here. Signed-off-by: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 2379045e0871..0603e0d46d33 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1506,12 +1506,10 @@ static int uart_carrier_raised(struct tty_port *port) struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; int mctrl; - mutex_lock(&port->mutex); spin_lock_irq(&uport->lock); uport->ops->enable_ms(uport); mctrl = uport->ops->get_mctrl(uport); spin_unlock_irq(&uport->lock); - mutex_unlock(&port->mutex); if (mctrl & TIOCM_CAR) return 1; return 0; @@ -1521,12 +1519,11 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) { struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; - mutex_lock(&port->mutex); + if (onoff) uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); else uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); - mutex_unlock(&port->mutex); } /* -- cgit v1.2.3 From 74c2107759dc6efaa1b9127014be58a742a1e7ac Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 1 Jun 2010 22:53:00 +0200 Subject: serial: Use block_til_ready helper Our code now rather closely resembles the helper, so switch to it. Signed-off-by: Alan Cox Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 87 +------------------------------------------- 1 file changed, 1 insertion(+), 86 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0603e0d46d33..a55751a12c38 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1526,91 +1526,6 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); } -/* - * Block the open until the port is ready. We must be called with - * the per-port semaphore held. - */ -static int -uart_block_til_ready(struct file *filp, struct uart_state *state) -{ - DECLARE_WAITQUEUE(wait, current); - struct tty_port *port = &state->port; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) - port->count--; - port->blocked_open++; - spin_unlock_irqrestore(&port->lock, flags); - - add_wait_queue(&port->open_wait, &wait); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - - /* - * If we have been hung up, tell userspace/restart open. - */ - if (tty_hung_up_p(filp) || port->tty == NULL) - break; - - /* - * If the port has been closed, tell userspace/restart open. - */ - if (!(port->flags & ASYNC_INITIALIZED)) - break; - - /* - * If non-blocking mode is set, or CLOCAL mode is set, - * we don't want to wait for the modem status lines to - * indicate that the port is ready. - * - * Also, if the port is not enabled/configured, we want - * to allow the open to succeed here. Note that we will - * have set TTY_IO_ERROR for a non-existant port. - */ - if ((filp->f_flags & O_NONBLOCK) || - (port->tty->termios->c_cflag & CLOCAL) || - (port->tty->flags & (1 << TTY_IO_ERROR))) - break; - - /* - * Set DTR to allow modem to know we're waiting. Do - * not set RTS here - we want to make sure we catch - * the data from the modem. - */ - if (port->tty->termios->c_cflag & CBAUD) - tty_port_raise_dtr_rts(port); - - /* - * and wait for the carrier to indicate that the - * modem is ready for us. - */ - if (tty_port_carrier_raised(port)) - break; - - schedule(); - - if (signal_pending(current)) - break; - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - - spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) - port->count++; - port->blocked_open--; - spin_unlock_irqrestore(&port->lock, flags); - - if (signal_pending(current)) - return -ERESTARTSYS; - - if (!port->tty || tty_hung_up_p(filp)) - return -EAGAIN; - - return 0; -} - static struct uart_state *uart_get(struct uart_driver *drv, int line) { struct uart_state *state; @@ -1719,7 +1634,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) */ mutex_unlock(&port->mutex); if (retval == 0) - retval = uart_block_til_ready(filp, state); + retval = tty_port_block_til_ready(port, tty, filp); /* * If this is the first open to succeed, adjust things to suit. -- cgit v1.2.3 From 3f582b8c11014e4ce310d9839fb335164195333f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 29 Jun 2010 22:31:40 +0200 Subject: serial: fix termios settings in open Move termios initialization in open into uart_dtr_rts to make sure it always gets called when necessary. Based on a suggestion from Alan Cox. Alan writes: Ok this sort of makes sense. Something isn't getting initialised and both getty and minicom will do a termios set which is sorting it out. This is occurring because the generic block_til_ready sets ASYNCB_NORMAL_ACTIVE so the termios updating gets skipped. This patch should cure it and then we can think about doing it more elegantly by getting the serial layer to use tty_port_open, kfifo and the like and removing the tons of repeated crap in all the drivers. Signed-off-by: Arnd Bergmann Reported-by: Tony Luck Cc: Alan Cox Cc: Tony Luck Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index a55751a12c38..3d2acc2265f7 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1520,8 +1520,16 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; - if (onoff) + if (onoff) { uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); + + /* + * If this is the first open to succeed, + * adjust things to suit. + */ + if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags)) + uart_update_termios(port->tty, state); + } else uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); } @@ -1636,15 +1644,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) if (retval == 0) retval = tty_port_block_til_ready(port, tty, filp); - /* - * If this is the first open to succeed, adjust things to suit. - */ - if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) { - set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); - - uart_update_termios(tty, state); - } - fail: return retval; } -- cgit v1.2.3 From ec79d6056de58511d8e46d9ae59d3878f958dc3e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:01 +0200 Subject: tty: replace BKL with a new tty_lock As a preparation for replacing the big kernel lock in the TTY layer, wrap all the callers in new macros tty_lock, tty_lock_nested and tty_unlock. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/amiserial.c | 16 +++--- drivers/char/briq_panel.c | 6 +-- drivers/char/n_hdlc.c | 16 +++--- drivers/char/n_r3964.c | 8 +-- drivers/char/pty.c | 4 +- drivers/char/selection.c | 4 +- drivers/char/serial167.c | 4 +- drivers/char/sx.c | 12 ++--- drivers/char/tty_io.c | 115 +++++++++++++++++++++++------------------ drivers/char/tty_ldisc.c | 24 +++++---- drivers/char/vc_screen.c | 4 +- drivers/char/vt_ioctl.c | 10 ++-- drivers/serial/68360serial.c | 4 +- drivers/serial/crisv10.c | 4 +- drivers/serial/serial_core.c | 10 ++-- drivers/video/console/vgacon.c | 4 +- include/linux/tty.h | 31 +++++++++++ 17 files changed, 161 insertions(+), 115 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 4f8d60c25a98..1b21a7adeb58 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info, if (!retinfo) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); - lock_kernel(); + tty_lock(); tmp.type = state->type; tmp.line = state->line; tmp.port = state->port; @@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info, tmp.close_delay = state->close_delay; tmp.closing_wait = state->closing_wait; tmp.custom_divisor = state->custom_divisor; - unlock_kernel(); + tty_unlock(); if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) return -EFAULT; return 0; @@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info, if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; - lock_kernel(); + tty_lock(); state = info->state; old_state = *state; change_irq = new_serial.irq != state->irq; change_port = (new_serial.port != state->port); if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { - unlock_kernel(); + tty_unlock(); return -EINVAL; } @@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info, } if (new_serial.baud_base < 9600) { - unlock_kernel(); + tty_unlock(); return -EINVAL; } @@ -1163,7 +1163,7 @@ check_and_exit: } } else retval = startup(info); - unlock_kernel(); + tty_unlock(); return retval; } @@ -1538,7 +1538,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) orig_jiffies = jiffies; - lock_kernel(); + tty_lock_nested(); /* tty_wait_until_sent is called from lots of places */ /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check @@ -1579,7 +1579,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) break; } __set_current_state(TASK_RUNNING); - unlock_kernel(); + tty_unlock(); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); #endif diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 555cd93c2ee5..d5fa113afe37 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c @@ -67,15 +67,15 @@ static void set_led(char state) static int briq_panel_open(struct inode *ino, struct file *filep) { - lock_kernel(); + tty_lock(); /* enforce single access, vfd_is_open is protected by BKL */ if (vfd_is_open) { - unlock_kernel(); + tty_unlock(); return -EBUSY; } vfd_is_open = 1; - unlock_kernel(); + tty_unlock(); return 0; } diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index c68118efad84..47d32281032c 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, return -EFAULT; } - lock_kernel(); + tty_lock(); for (;;) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { - unlock_kernel(); + tty_unlock(); return -EIO; } n_hdlc = tty2n_hdlc (tty); if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || tty != n_hdlc->tty) { - unlock_kernel(); + tty_unlock(); return 0; } @@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, /* no data */ if (file->f_flags & O_NONBLOCK) { - unlock_kernel(); + tty_unlock(); return -EAGAIN; } interruptible_sleep_on (&tty->read_wait); if (signal_pending(current)) { - unlock_kernel(); + tty_unlock(); return -EINTR; } } @@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, kfree(rbuf); else n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); - unlock_kernel(); + tty_unlock(); return ret; } /* end of n_hdlc_tty_read() */ @@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, count = maxframe; } - lock_kernel(); + tty_lock(); add_wait_queue(&tty->write_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); n_hdlc_send_frames(n_hdlc,tty); } - unlock_kernel(); + tty_unlock(); return error; } /* end of n_hdlc_tty_write() */ diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index c1d8b54c816d..f4bd2591e39f 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, TRACE_L("read()"); - lock_kernel(); + tty_lock(); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, } ret = -EPERM; unlock: - unlock_kernel(); + tty_unlock(); return ret; } @@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, pHeader->locks = 0; pHeader->owner = NULL; - lock_kernel(); + tty_lock(); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, add_tx_queue(pInfo, pHeader); trigger_transmit(pInfo); - unlock_kernel(); + tty_unlock(); return 0; } diff --git a/drivers/char/pty.c b/drivers/char/pty.c index b640ef29be1c..622e21ca9a5c 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -692,9 +692,9 @@ static int ptmx_open(struct inode *inode, struct file *filp) { int ret; - lock_kernel(); + tty_lock(); ret = __ptmx_open(inode, filp); - unlock_kernel(); + tty_unlock(); return ret; } diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 6e79340d732f..85211a3a5811 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -313,7 +313,7 @@ int paste_selection(struct tty_struct *tty) struct tty_ldisc *ld; DECLARE_WAITQUEUE(wait, current); - lock_kernel(); + tty_lock_nested(); /* always called with BTM from vt_ioctl */ acquire_console_sem(); poke_blanked_console(); @@ -338,6 +338,6 @@ int paste_selection(struct tty_struct *tty) __set_current_state(TASK_RUNNING); tty_ldisc_deref(ld); - unlock_kernel(); + tty_unlock(); return 0; } diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index ecbe479c7d68..90b3ec0aabdd 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ #endif - lock_kernel(); + tty_lock(); switch (cmd) { case CYGETMON: @@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, default: ret_val = -ENOIOCTLCMD; } - unlock_kernel(); + tty_unlock(); #ifdef SERIAL_DEBUG_OTHER printk("cy_ioctl done\n"); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a81ec4fcf6ff..5b24db4ff7f1 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, if (!capable(CAP_SYS_RAWIO)) return -EPERM; - lock_kernel(); + tty_lock(); sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); @@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, break; } out: - unlock_kernel(); + tty_unlock(); func_exit(); return rc; } @@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag) int rv; func_enter(); - lock_kernel(); + tty_lock(); if (flag) rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); @@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag) if (rv != 1) printk(KERN_ERR "sx: couldn't send break (%x).\n", read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); - unlock_kernel(); + tty_unlock(); func_exit(); return 0; } @@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, /* func_enter2(); */ rc = 0; - lock_kernel(); + tty_lock(); switch (cmd) { case TIOCGSERIAL: rc = gs_getserial(&port->gs, argp); @@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, rc = -ENOIOCTLCMD; break; } - unlock_kernel(); + tty_unlock(); /* func_exit(); */ return rc; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 507441ac6edb..5ee9081a560f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, #else #define tty_compat_ioctl NULL #endif +static int __tty_fasync(int fd, struct file *filp, int on); static int tty_fasync(int fd, struct file *filp, int on); static void release_tty(struct tty_struct *tty, int idx); static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); @@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); * remains intact. * * Locking: - * BKL + * BTM * redirect lock for undoing redirection * file list lock for manipulating list of ttys * tty_ldisc_lock from called functions @@ -513,8 +514,11 @@ static void do_tty_hangup(struct work_struct *work) } spin_unlock(&redirect_lock); - /* inuse_filps is protected by the single kernel lock */ - lock_kernel(); + /* inuse_filps is protected by the single tty lock, + this really needs to change if we want to flush the + workqueue with the lock held */ + tty_lock_nested(); /* called with BTM held from pty_close and + others */ check_tty_count(tty, "do_tty_hangup"); file_list_lock(); @@ -525,7 +529,7 @@ static void do_tty_hangup(struct work_struct *work) if (filp->f_op->write != tty_write) continue; closecount++; - tty_fasync(-1, filp, 0); /* can't block */ + __tty_fasync(-1, filp, 0); /* can't block */ filp->f_op = &hung_up_tty_fops; } file_list_unlock(); @@ -594,7 +598,7 @@ static void do_tty_hangup(struct work_struct *work) */ set_bit(TTY_HUPPED, &tty->flags); tty_ldisc_enable(tty); - unlock_kernel(); + tty_unlock(); if (f) fput(f); } @@ -696,7 +700,8 @@ static void session_clear_tty(struct pid *session) * exiting; it is 0 if called by the ioctl TIOCNOTTY. * * Locking: - * BKL is taken for hysterical raisins + * BTM is taken for hysterical raisins, and held when + * called from no_tty(). * tty_mutex is taken to protect tty * ->siglock is taken to protect ->signal/->sighand * tasklist_lock is taken to walk process list for sessions @@ -714,10 +719,10 @@ void disassociate_ctty(int on_exit) tty = get_current_tty(); if (tty) { tty_pgrp = get_pid(tty->pgrp); - lock_kernel(); + tty_lock_nested(); /* see above */ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); - unlock_kernel(); + tty_unlock(); tty_kref_put(tty); } else if (on_exit) { struct pid *old_pgrp; @@ -774,9 +779,9 @@ void disassociate_ctty(int on_exit) void no_tty(void) { struct task_struct *tsk = current; - lock_kernel(); + tty_lock(); disassociate_ctty(0); - unlock_kernel(); + tty_unlock(); proc_clear_tty(tsk); } @@ -1013,19 +1018,19 @@ out: * We don't put it into the syslog queue right now maybe in the future if * really needed. * - * We must still hold the BKL and test the CLOSING flag for the moment. + * We must still hold the BTM and test the CLOSING flag for the moment. */ void tty_write_message(struct tty_struct *tty, char *msg) { if (tty) { mutex_lock(&tty->atomic_write_lock); - lock_kernel(); + tty_lock(); if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { - unlock_kernel(); + tty_unlock(); tty->ops->write(tty, msg, strlen(msg)); } else - unlock_kernel(); + tty_unlock(); tty_write_unlock(tty); } return; @@ -1208,18 +1213,18 @@ static int tty_driver_install_tty(struct tty_driver *driver, int ret; if (driver->ops->install) { - lock_kernel(); + tty_lock_nested(); /* already called with BTM held */ ret = driver->ops->install(driver, tty); - unlock_kernel(); + tty_unlock(); return ret; } if (tty_init_termios(tty) == 0) { - lock_kernel(); + tty_lock_nested(); tty_driver_kref_get(driver); tty->count++; driver->ttys[idx] = tty; - unlock_kernel(); + tty_unlock(); return 0; } return -ENOMEM; @@ -1312,14 +1317,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, struct tty_struct *tty; int retval; - lock_kernel(); + tty_lock_nested(); /* always called with tty lock held already */ + /* Check if pty master is being opened multiple times */ if (driver->subtype == PTY_TYPE_MASTER && (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { - unlock_kernel(); + tty_unlock(); return ERR_PTR(-EIO); } - unlock_kernel(); + tty_unlock(); /* * First time open is complex, especially for PTY devices. @@ -1363,9 +1369,9 @@ release_mem_out: if (printk_ratelimit()) printk(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); - lock_kernel(); + tty_lock_nested(); release_tty(tty, idx); - unlock_kernel(); + tty_unlock(); return ERR_PTR(retval); } @@ -1512,10 +1518,10 @@ int tty_release(struct inode *inode, struct file *filp) if (tty_paranoia_check(tty, inode, "tty_release_dev")) return 0; - lock_kernel(); + tty_lock(); check_tty_count(tty, "tty_release_dev"); - tty_fasync(-1, filp, 0); + __tty_fasync(-1, filp, 0); idx = tty->index; pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && @@ -1527,18 +1533,18 @@ int tty_release(struct inode *inode, struct file *filp) if (idx < 0 || idx >= tty->driver->num) { printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " "free (%s)\n", tty->name); - unlock_kernel(); + tty_unlock(); return 0; } if (!devpts) { if (tty != tty->driver->ttys[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " "for (%s)\n", idx, tty->name); return 0; } if (tty->termios != tty->driver->termios[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " "for (%s)\n", idx, tty->name); @@ -1556,21 +1562,21 @@ int tty_release(struct inode *inode, struct file *filp) if (tty->driver->other && !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { if (o_tty != tty->driver->other->ttys[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: other->table[%d] " "not o_tty for (%s)\n", idx, tty->name); return 0 ; } if (o_tty->termios != tty->driver->other->termios[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " "not o_termios for (%s)\n", idx, tty->name); return 0; } if (o_tty->link != tty) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); return 0; } @@ -1579,7 +1585,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty->ops->close) tty->ops->close(tty, filp); - unlock_kernel(); + tty_unlock(); /* * Sanity check: if tty->count is going to zero, there shouldn't be * any waiters on tty->read_wait or tty->write_wait. We test the @@ -1602,7 +1608,7 @@ int tty_release(struct inode *inode, struct file *filp) opens on /dev/tty */ mutex_lock(&tty_mutex); - lock_kernel(); + tty_lock(); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1633,7 +1639,7 @@ int tty_release(struct inode *inode, struct file *filp) printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " "active!\n", tty_name(tty, buf)); - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); schedule(); } @@ -1698,7 +1704,7 @@ int tty_release(struct inode *inode, struct file *filp) /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) { - unlock_kernel(); + tty_unlock(); return 0; } @@ -1718,7 +1724,7 @@ int tty_release(struct inode *inode, struct file *filp) /* Make this pty number available for reallocation */ if (devpts) devpts_kill_index(inode, idx); - unlock_kernel(); + tty_unlock(); return 0; } @@ -1760,12 +1766,12 @@ retry_open: retval = 0; mutex_lock(&tty_mutex); - lock_kernel(); + tty_lock(); if (device == MKDEV(TTYAUX_MAJOR, 0)) { tty = get_current_tty(); if (!tty) { - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return -ENXIO; } @@ -1797,14 +1803,14 @@ retry_open: goto got_driver; } } - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return -ENODEV; } driver = get_tty_driver(device, &index); if (!driver) { - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return -ENODEV; } @@ -1814,7 +1820,7 @@ got_driver: tty = tty_driver_lookup_tty(driver, inode, index); if (IS_ERR(tty)) { - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return PTR_ERR(tty); } @@ -1830,7 +1836,7 @@ got_driver: mutex_unlock(&tty_mutex); tty_driver_kref_put(driver); if (IS_ERR(tty)) { - unlock_kernel(); + tty_unlock(); return PTR_ERR(tty); } @@ -1862,11 +1868,11 @@ got_driver: #endif tty_release(inode, filp); if (retval != -ERESTARTSYS) { - unlock_kernel(); + tty_unlock(); return retval; } if (signal_pending(current)) { - unlock_kernel(); + tty_unlock(); return retval; } schedule(); @@ -1875,14 +1881,14 @@ got_driver: */ if (filp->f_op == &hung_up_tty_fops) filp->f_op = &tty_fops; - unlock_kernel(); + tty_unlock(); goto retry_open; } - unlock_kernel(); + tty_unlock(); mutex_lock(&tty_mutex); - lock_kernel(); + tty_lock(); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && @@ -1890,7 +1896,7 @@ got_driver: tty->session == NULL) __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return 0; } @@ -1926,13 +1932,12 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) return ret; } -static int tty_fasync(int fd, struct file *filp, int on) +static int __tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty; unsigned long flags; int retval = 0; - lock_kernel(); tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) goto out; @@ -1966,7 +1971,15 @@ static int tty_fasync(int fd, struct file *filp, int on) } retval = 0; out: - unlock_kernel(); + return retval; +} + +static int tty_fasync(int fd, struct file *filp, int on) +{ + int retval; + tty_lock(); + retval = __tty_fasync(fd, filp, on); + tty_unlock(); return retval; } diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 500e740ec5e4..97681ffd6cbd 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) * * A helper opening method. Also a convenient debugging and check * point. + * + * Locking: always called with BTM already held. */ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) @@ -447,10 +449,10 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); if (ld->ops->open) { int ret; - /* BKL here locks verus a hangup event */ - lock_kernel(); + /* BTM here locks versus a hangup event */ + tty_lock_nested(); /* always held here already */ ret = ld->ops->open(tty); - unlock_kernel(); + tty_unlock(); return ret; } return 0; @@ -553,7 +555,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); - lock_kernel(); + tty_lock(); /* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel. @@ -567,12 +569,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) */ if (tty->ldisc->ops->num == ldisc) { - unlock_kernel(); + tty_unlock(); tty_ldisc_put(new_ldisc); return 0; } - unlock_kernel(); + tty_unlock(); /* * Problem: What do we do if this blocks ? * We could deadlock here @@ -594,7 +596,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) mutex_lock(&tty->ldisc_mutex); } - lock_kernel(); + tty_lock(); set_bit(TTY_LDISC_CHANGING, &tty->flags); @@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) o_ldisc = tty->ldisc; - unlock_kernel(); + tty_unlock(); /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit @@ -633,14 +635,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) flush_scheduled_work(); mutex_lock(&tty->ldisc_mutex); - lock_kernel(); + tty_lock(); if (test_bit(TTY_HUPPED, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ clear_bit(TTY_LDISC_CHANGING, &tty->flags); mutex_unlock(&tty->ldisc_mutex); tty_ldisc_put(new_ldisc); - unlock_kernel(); + tty_unlock(); return -EIO; } @@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (o_work) schedule_delayed_work(&o_tty->buf.work, 1); mutex_unlock(&tty->ldisc_mutex); - unlock_kernel(); + tty_unlock(); return retval; } diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index c1791a63d99d..bcce46c96b88 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp) unsigned int currcons = iminor(inode) & 127; int ret = 0; - lock_kernel(); + tty_lock(); if(currcons && !vc_cons_allocated(currcons-1)) ret = -ENXIO; - unlock_kernel(); + tty_unlock(); return ret; } diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 72dcfb2dc126..cf87c5336229 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, console = vc->vc_num; - lock_kernel(); + tty_lock(); if (!vc_cons_allocated(console)) { /* impossible? */ ret = -ENOIOCTLCMD; @@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ret = -ENOIOCTLCMD; } out: - unlock_kernel(); + tty_unlock(); return ret; eperm: ret = -EPERM; @@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, console = vc->vc_num; - lock_kernel(); + tty_lock(); if (!vc_cons_allocated(console)) { /* impossible? */ ret = -ENOIOCTLCMD; @@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, goto fallback; } out: - unlock_kernel(); + tty_unlock(); return ret; fallback: - unlock_kernel(); + tty_unlock(); return vt_ioctl(tty, file, cmd, arg); } diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 768612f8e41e..16f5f2fab032 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1705,7 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) printk("jiff=%lu...", jiffies); #endif - lock_kernel(); + tty_lock_nested(); /* always held already since we come from ->close */ /* We go through the loop at least once because we can't tell * exactly when the last character exits the shifter. There can * be at least two characters waiting to be sent after the buffers @@ -1734,7 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) bdp--; } while (bdp->status & BD_SC_READY); current->state = TASK_RUNNING; - unlock_kernel(); + tty_unlock(); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); #endif diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 30626440a062..f848e188deae 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -3935,7 +3935,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) */ - lock_kernel(); + tty_lock_nested(); /* locked already when coming from close */ orig_jiffies = jiffies; while (info->xmit.head != info->xmit.tail || /* More in send queue */ (*info->ostatusadr & 0x007f) || /* more in FIFO */ @@ -3952,7 +3952,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) curr_time_usec - info->last_tx_active_usec; } set_current_state(TASK_RUNNING); - unlock_kernel(); + tty_unlock(); } /* diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 3d2acc2265f7..851d7c29132b 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1274,7 +1274,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) struct uart_port *uport; unsigned long flags; - BUG_ON(!kernel_locked()); + BUG_ON(!tty_locked()); if (!state) return; @@ -1382,7 +1382,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) if (port->type == PORT_UNKNOWN || port->fifosize == 0) return; - lock_kernel(); + tty_lock_nested(); /* already locked when coming from close */ /* * Set the check interval to be 1/5 of the estimated time to @@ -1429,7 +1429,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) break; } set_current_state(TASK_RUNNING); /* might not be needed */ - unlock_kernel(); + tty_unlock(); } /* @@ -1444,7 +1444,7 @@ static void uart_hangup(struct tty_struct *tty) struct tty_port *port = &state->port; unsigned long flags; - BUG_ON(!kernel_locked()); + BUG_ON(!tty_locked()); pr_debug("uart_hangup(%d)\n", state->uart_port->line); mutex_lock(&port->mutex); @@ -1578,7 +1578,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) struct tty_port *port; int retval, line = tty->index; - BUG_ON(!kernel_locked()); + BUG_ON(!tty_locked()); pr_debug("uart_open(%d) called\n", line); /* diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 182dd6f8aadd..71970057c118 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1108,7 +1108,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) charmap += 4 * cmapsz; #endif - unlock_kernel(); + tty_unlock(); spin_lock_irq(&vga_lock); /* First, the Sequencer */ vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); @@ -1192,7 +1192,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); } spin_unlock_irq(&vga_lock); - lock_kernel(); + tty_lock(); return 0; } diff --git a/include/linux/tty.h b/include/linux/tty.h index 2df60e4ff40e..6ead6b60c743 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -576,5 +577,35 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file, extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); +/* functions for preparation of BKL removal */ + +/* + * tty_lock_nested get the tty_lock while potentially holding it + * + * The Big TTY Mutex is a recursive lock, meaning you can take it + * from a thread that is already holding it. + * This is bad for a number of reasons, so tty_lock_nested should + * really be used as rarely as possible. If a code location can + * be shown to never get called with this held already, it should + * use tty_lock() instead. + */ +static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock) +{ + lock_kernel(); +} +static inline void tty_lock(void) __acquires(kernel_lock) +{ +#ifdef CONFIG_LOCK_KERNEL + /* kernel_locked is 1 for !CONFIG_LOCK_KERNEL */ + WARN_ON(kernel_locked()); +#endif + lock_kernel(); +} +static inline void tty_unlock(void) __releases(kernel_lock) +{ + unlock_kernel(); +} +#define tty_locked() (kernel_locked()) + #endif /* __KERNEL__ */ #endif -- cgit v1.2.3 From be1bc2889a4db4961ef69f47fb471ecae9f23ade Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:05 +0200 Subject: tty: introduce wait_event_interruptible_tty Calling wait_event_interruptible implicitly releases the BKL when it sleeps, but we need to do this explcitly when we have converted it to a mutex. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/cyclades.c | 2 +- drivers/char/istallion.c | 12 ++++++++---- drivers/char/n_r3964.c | 2 +- drivers/char/tty_port.c | 2 +- drivers/char/vt_ioctl.c | 5 ++++- drivers/serial/crisv10.c | 4 ++-- include/linux/tty.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 59 insertions(+), 10 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 51acfe39a438..27aad9422332 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -1607,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { - wait_event_interruptible(info->port.close_wait, + wait_event_interruptible_tty(info->port.close_wait, !(info->port.flags & ASYNC_CLOSING)); return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; } diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 5e9a81d8ebcf..be28391adb79 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -954,7 +954,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l * order of opens and closes may not be preserved across shared * memory, so we must wait until it is complete. */ - wait_event_interruptible(portp->raw_wait, + wait_event_interruptible_tty(portp->raw_wait, !test_bit(ST_CLOSING, &portp->state)); if (signal_pending(current)) { return -ERESTARTSYS; @@ -989,7 +989,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l set_bit(ST_OPENING, &portp->state); spin_unlock_irqrestore(&brd_lock, flags); - wait_event_interruptible(portp->raw_wait, + wait_event_interruptible_tty(portp->raw_wait, !test_bit(ST_OPENING, &portp->state)); if (signal_pending(current)) rc = -ERESTARTSYS; @@ -1020,7 +1020,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned * occurs on this port. */ if (wait) { - wait_event_interruptible(portp->raw_wait, + wait_event_interruptible_tty(portp->raw_wait, !test_bit(ST_CLOSING, &portp->state)); if (signal_pending(current)) { return -ERESTARTSYS; @@ -1052,7 +1052,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned * to come back. */ rc = 0; - wait_event_interruptible(portp->raw_wait, + wait_event_interruptible_tty(portp->raw_wait, !test_bit(ST_CLOSING, &portp->state)); if (signal_pending(current)) rc = -ERESTARTSYS; @@ -1073,6 +1073,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) { + /* + * no need for wait_event_tty because clearing ST_CMDING cannot block + * on BTM + */ wait_event_interruptible(portp->raw_wait, !test_bit(ST_CMDING, &portp->state)); if (signal_pending(current)) diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index f4bd2591e39f..a98290d7a2c5 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, goto unlock; } /* block until there is a message: */ - wait_event_interruptible(pInfo->read_wait, + wait_event_interruptible_tty(pInfo->read_wait, (pMsg = remove_msg(pInfo, pClient))); } diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index a3bd1d0b66cf..35eb30402f18 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c @@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port, /* block if port is in the process of being closed */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - wait_event_interruptible(port->close_wait, + wait_event_interruptible_tty(port->close_wait, !(port->flags & ASYNC_CLOSING)); if (port->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index cf87c5336229..2bbeaaea46e9 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw) list_add(&vw->list, &vt_events); spin_unlock_irqrestore(&vt_event_lock, flags); /* Wait for it to pass */ - wait_event_interruptible(vt_event_waitqueue, vw->done); + wait_event_interruptible_tty(vt_event_waitqueue, vw->done); /* Dequeue it */ spin_lock_irqsave(&vt_event_lock, flags); list_del(&vw->list); @@ -1761,10 +1761,13 @@ int vt_move_to_console(unsigned int vt, int alloc) return -EIO; } release_console_sem(); + tty_lock(); if (vt_waitactive(vt + 1)) { pr_debug("Suspend: Can't switch VCs."); + tty_unlock(); return -EINTR; } + tty_unlock(); return prev; } diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index f848e188deae..94bfb9f238e1 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -3992,7 +3992,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible(info->close_wait, + wait_event_interruptible_tty(info->close_wait, !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) @@ -4150,7 +4150,7 @@ rs_open(struct tty_struct *tty, struct file * filp) */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible(info->close_wait, + wait_event_interruptible_tty(info->close_wait, !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? diff --git a/include/linux/tty.h b/include/linux/tty.h index 6ead6b60c743..955d72ea71c0 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -607,5 +607,47 @@ static inline void tty_unlock(void) __releases(kernel_lock) } #define tty_locked() (kernel_locked()) +/* + * wait_event_interruptible_tty -- wait for a condition with the tty lock held + * + * The condition we are waiting for might take a long time to + * become true, or might depend on another thread taking the + * BTM. In either case, we need to drop the BTM to guarantee + * forward progress. This is a leftover from the conversion + * from the BKL and should eventually get removed as the BTM + * falls out of use. + * + * Do not use in new code. + */ +#define wait_event_interruptible_tty(wq, condition) \ +({ \ + int __ret = 0; \ + if (!(condition)) { \ + __wait_event_interruptible_tty(wq, condition, __ret); \ + } \ + __ret; \ +}) + +#define __wait_event_interruptible_tty(wq, condition, ret) \ +do { \ + DEFINE_WAIT(__wait); \ + \ + for (;;) { \ + prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (!signal_pending(current)) { \ + tty_unlock(); \ + schedule(); \ + tty_lock(); \ + continue; \ + } \ + ret = -ERESTARTSYS; \ + break; \ + } \ + finish_wait(&wq, &__wait); \ +} while (0) + + #endif /* __KERNEL__ */ #endif -- cgit v1.2.3 From 203652192634c1fce5e79df0a8ff2fabfaefd3ab Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:07 +0200 Subject: tty: untangle locking of wait_until_sent Some wait_until_sent versions require the big tty mutex, others don't and some callers of wait_until_sent already hold it while other don't. That leads to recursive use of the BTM in these functions, which we're trying to get rid of. This turns all cleans up the locking there so that the driver's wait_until_sent function never takes the BTM itself if it is already called with that lock held. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/amiserial.c | 11 +++++++++-- drivers/serial/68360serial.c | 2 -- drivers/serial/crisv10.c | 2 -- drivers/serial/serial_core.c | 31 ++++++++++++++++++++++--------- 4 files changed, 31 insertions(+), 15 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 1b21a7adeb58..8228e61bb54d 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1528,6 +1528,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) { struct async_struct * info = tty->driver_data; unsigned long orig_jiffies, char_time; + int tty_was_locked = tty_locked(); int lsr; if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) @@ -1538,7 +1539,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) orig_jiffies = jiffies; - tty_lock_nested(); /* tty_wait_until_sent is called from lots of places */ + /* + * tty_wait_until_sent is called from lots of places, + * with or without the BTM. + */ + if (!tty_was_locked) + tty_lock(); /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check @@ -1579,7 +1585,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) break; } __set_current_state(TASK_RUNNING); - tty_unlock(); + if (!tty_was_locked) + tty_unlock(); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); #endif diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 16f5f2fab032..edcf1cc089d1 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1705,7 +1705,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) printk("jiff=%lu...", jiffies); #endif - tty_lock_nested(); /* always held already since we come from ->close */ /* We go through the loop at least once because we can't tell * exactly when the last character exits the shifter. There can * be at least two characters waiting to be sent after the buffers @@ -1734,7 +1733,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) bdp--; } while (bdp->status & BD_SC_READY); current->state = TASK_RUNNING; - tty_unlock(); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); #endif diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 94bfb9f238e1..8e356c5eeae0 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -3935,7 +3935,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) */ - tty_lock_nested(); /* locked already when coming from close */ orig_jiffies = jiffies; while (info->xmit.head != info->xmit.tail || /* More in send queue */ (*info->ostatusadr & 0x007f) || /* more in FIFO */ @@ -3952,7 +3951,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) curr_time_usec - info->last_tx_active_usec; } set_current_state(TASK_RUNNING); - tty_unlock(); } /* diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 851d7c29132b..cd8511298bcb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -60,7 +60,7 @@ static struct lock_class_key port_lock_key; static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, struct ktermios *old_termios); -static void uart_wait_until_sent(struct tty_struct *tty, int timeout); +static void __uart_wait_until_sent(struct uart_port *port, int timeout); static void uart_change_pm(struct uart_state *state, int pm_state); /* @@ -1322,8 +1322,16 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty->closing = 1; spin_unlock_irqrestore(&port->lock, flags); - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait)); + if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) { + /* + * hack: open-coded tty_wait_until_sent to avoid + * recursive tty_lock + */ + long timeout = msecs_to_jiffies(port->closing_wait); + if (wait_event_interruptible_timeout(tty->write_wait, + !tty_chars_in_buffer(tty), timeout) >= 0) + __uart_wait_until_sent(uport, timeout); + } /* * At this point, we stop accepting input. To do this, we @@ -1339,7 +1347,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * has completely drained; this is especially * important if there is a transmit FIFO! */ - uart_wait_until_sent(tty, uport->timeout); + __uart_wait_until_sent(uport, uport->timeout); } uart_shutdown(tty, state); @@ -1373,17 +1381,13 @@ done: mutex_unlock(&port->mutex); } -static void uart_wait_until_sent(struct tty_struct *tty, int timeout) +static void __uart_wait_until_sent(struct uart_port *port, int timeout) { - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->uart_port; unsigned long char_time, expire; if (port->type == PORT_UNKNOWN || port->fifosize == 0) return; - tty_lock_nested(); /* already locked when coming from close */ - /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check @@ -1429,6 +1433,15 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) break; } set_current_state(TASK_RUNNING); /* might not be needed */ +} + +static void uart_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->uart_port; + + tty_lock(); + __uart_wait_until_sent(port, timeout); tty_unlock(); } -- cgit v1.2.3 From e142a31da34b42458e10026b554e66127739cf23 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:10 +0200 Subject: tty: release BTM while sleeping in block_til_ready Most tty drivers may block while opening a device. Since this possibly depends on another thread closing it first and both threads may need the BTM, we need to release it here. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/amiserial.c | 2 ++ drivers/char/ip2/ip2main.c | 4 ++++ drivers/char/serial167.c | 4 +++- drivers/char/specialix.c | 2 ++ drivers/char/synclink.c | 2 ++ drivers/char/synclink_gt.c | 2 ++ drivers/char/synclinkmp.c | 2 ++ drivers/char/tty_port.c | 2 ++ drivers/serial/68328serial.c | 2 ++ drivers/serial/68360serial.c | 2 ++ drivers/serial/crisv10.c | 2 ++ 11 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 8228e61bb54d..a11c8c9ca3d4 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1710,7 +1710,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready blocking: ttys%d, count = %d\n", info->line, state->count); #endif + tty_unlock(); schedule(); + tty_lock(); } __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 911e1da6def2..07f3ea38b582 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -1486,7 +1486,9 @@ ip2_open( PTTY tty, struct file *pFile ) if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { if ( pCh->flags & ASYNC_CLOSING ) { + tty_unlock(); schedule(); + tty_lock(); } if ( tty_hung_up_p(pFile) ) { set_current_state( TASK_RUNNING ); @@ -1548,7 +1550,9 @@ ip2_open( PTTY tty, struct file *pFile ) rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); break; } + tty_unlock(); schedule(); + tty_lock(); } set_current_state( TASK_RUNNING ); remove_wait_queue(&pCh->open_wait, &wait); diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 90b3ec0aabdd..f646725bd567 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1786,7 +1786,9 @@ block_til_ready(struct tty_struct *tty, struct file *filp, tty->name, info->count); /**/ #endif - schedule(); + tty_unlock(); + schedule(); + tty_lock(); } __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 7be456f760c9..9f8495b4fc8f 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -1365,7 +1365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, retval = -ERESTARTSYS; break; } + tty_unlock(); schedule(); + tty_lock(); } set_current_state(TASK_RUNNING); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 2b03d4d47350..a2a58004e188 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -3349,7 +3349,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, printk("%s(%d):block_til_ready blocking on %s count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); + tty_unlock(); schedule(); + tty_lock(); } set_current_state(TASK_RUNNING); diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 5a602eb7cd2d..fef80cfcab5c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -3244,7 +3244,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, } DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); + tty_unlock(); schedule(); + tty_lock(); } set_current_state(TASK_RUNNING); diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index ac447c7eb572..e56caf7d82aa 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -3365,7 +3365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, printk("%s(%d):%s block_til_ready() count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); + tty_unlock(); schedule(); + tty_lock(); } set_current_state(TASK_RUNNING); diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index 35eb30402f18..33d37d230f8f 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c @@ -294,7 +294,9 @@ int tty_port_block_til_ready(struct tty_port *port, retval = -ERESTARTSYS; break; } + tty_unlock(); schedule(); + tty_lock(); } finish_wait(&port->open_wait, &wait); diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 9330edb323e2..d8204f4ebbb4 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -1235,7 +1235,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, retval = -ERESTARTSYS; break; } + tty_unlock(); schedule(); + tty_lock(); } current->state = TASK_RUNNING; remove_wait_queue(&info->open_wait, &wait); diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index edcf1cc089d1..0dff3bbddc8b 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1860,7 +1860,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready blocking: ttys%d, count = %d\n", info->line, state->count); #endif + tty_unlock(); schedule(); + tty_lock(); } current->state = TASK_RUNNING; remove_wait_queue(&info->open_wait, &wait); diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 8e356c5eeae0..5696710b6f2d 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -4066,7 +4066,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready blocking: ttyS%d, count = %d\n", info->line, info->count); #endif + tty_unlock(); schedule(); + tty_lock(); } set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); -- cgit v1.2.3 From a0821df6e57c8af0053963d0d08c8d5198ea077d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:11 +0200 Subject: 8250: fix set_ldisc operation The ldisc number now gets passed into ->set_ldisc. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index bc8ed4be9073..355148dc085e 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2404,14 +2404,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, } static void -serial8250_set_ldisc(struct uart_port *port) +serial8250_set_ldisc(struct uart_port *port, int new) { - int line = port->line; - - if (line >= port->state->port.tty->driver->num) - return; - - if (port->state->port.tty->ldisc->ops->num == N_PPS) { + if (new == N_PPS) { port->flags |= UPF_HARDPPS_CD; serial8250_enable_ms(port); } else -- cgit v1.2.3 From 44318feb93327e36108b2a9cf94ac9f7ccabf047 Mon Sep 17 00:00:00 2001 From: jianwei.yang Date: Wed, 30 Jun 2010 17:57:12 +0100 Subject: serial: max3107: introduce a max3107 driver This device is used by some of the Intel MID platforms. It's not similar enough to the MAX3100 to use the same driver. At this point the driver is specific to the platform and not generalised. We will fix that later. Signed-off-by: jianwei.yang Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/Kconfig | 8 + drivers/serial/Makefile | 1 + drivers/serial/max3107.c | 1442 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/serial/max3107.h | 358 ++++++++++++ 4 files changed, 1809 insertions(+) create mode 100644 drivers/serial/max3107.c create mode 100644 drivers/serial/max3107.h (limited to 'drivers/serial') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 964634e79c16..fd406273cb71 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -542,6 +542,14 @@ config SERIAL_S5PV210 help Serial port support for Samsung's S5P Family of SoC's +config SERIAL_MAX3107 + tristate "MAX3107 support" + depends on SPI && GPIOLIB + select SERIAL_CORE + default y + help + MAX3107 chip support + config SERIAL_MAX3100 tristate "MAX3100 support" depends on SPI diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index a5edb49c7303..4cd0c0694917 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o +obj-$(CONFIG_SERIAL_MAX3107) += max3107.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c new file mode 100644 index 000000000000..a96ddd388ffd --- /dev/null +++ b/drivers/serial/max3107.c @@ -0,0 +1,1442 @@ +/* + * max3107.c - spi uart protocol driver for Maxim 3107 + * Based on max3100.c + * by Christian Pellegrin + * and max3110.c + * by Feng Tang + * + * Copyright (C) Aavamobile 2009 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "max3107.h" + +struct baud_table { + int baud; + u32 new_brg; +}; + +struct max3107_port { + /* UART port structure */ + struct uart_port port; + + /* SPI device structure */ + struct spi_device *spi; + + /* GPIO chip stucture */ + struct gpio_chip chip; + + /* Workqueue that does all the magic */ + struct workqueue_struct *workqueue; + struct work_struct work; + + /* Lock for shared data */ + spinlock_t data_lock; + + /* Device configuration */ + int ext_clk; /* 1 if external clock used */ + int loopback; /* Current loopback mode state */ + int baud; /* Current baud rate */ + + /* State flags */ + int suspended; /* Indicates suspend mode */ + int tx_fifo_empty; /* Flag for TX FIFO state */ + int rx_enabled; /* Flag for receiver state */ + int tx_enabled; /* Flag for transmitter state */ + + u16 irqen_reg; /* Current IRQ enable register value */ + /* Shared data */ + u16 mode1_reg; /* Current mode1 register value*/ + int mode1_commit; /* Flag for setting new mode1 register value */ + u16 lcr_reg; /* Current LCR register value */ + int lcr_commit; /* Flag for setting new LCR register value */ + u32 brg_cfg; /* Current Baud rate generator config */ + int brg_commit; /* Flag for setting new baud rate generator + * config + */ + struct baud_table *baud_tbl; + int handle_irq; /* Indicates that IRQ should be handled */ + + /* Rx buffer and str*/ + u16 *rxbuf; + u8 *rxstr; + /* Tx buffer*/ + u16 *txbuf; +}; + +/* Platform data structure */ +struct max3107_plat { + /* Loopback mode enable */ + int loopback; + /* External clock enable */ + int ext_clk; + /* HW suspend function */ + void (*max3107_hw_suspend) (struct max3107_port *s, int suspend); + /* Polling mode enable */ + int polled_mode; + /* Polling period if polling mode enabled */ + int poll_time; +}; + +static struct baud_table brg13_ext[] = { + { 300, MAX3107_BRG13_B300 }, + { 600, MAX3107_BRG13_B600 }, + { 1200, MAX3107_BRG13_B1200 }, + { 2400, MAX3107_BRG13_B2400 }, + { 4800, MAX3107_BRG13_B4800 }, + { 9600, MAX3107_BRG13_B9600 }, + { 19200, MAX3107_BRG13_B19200 }, + { 57600, MAX3107_BRG13_B57600 }, + { 115200, MAX3107_BRG13_B115200 }, + { 230400, MAX3107_BRG13_B230400 }, + { 460800, MAX3107_BRG13_B460800 }, + { 921600, MAX3107_BRG13_B921600 }, + { 0, 0 } +}; + +static struct baud_table brg26_ext[] = { + { 300, MAX3107_BRG26_B300 }, + { 600, MAX3107_BRG26_B600 }, + { 1200, MAX3107_BRG26_B1200 }, + { 2400, MAX3107_BRG26_B2400 }, + { 4800, MAX3107_BRG26_B4800 }, + { 9600, MAX3107_BRG26_B9600 }, + { 19200, MAX3107_BRG26_B19200 }, + { 57600, MAX3107_BRG26_B57600 }, + { 115200, MAX3107_BRG26_B115200 }, + { 230400, MAX3107_BRG26_B230400 }, + { 460800, MAX3107_BRG26_B460800 }, + { 921600, MAX3107_BRG26_B921600 }, + { 0, 0 } +}; + +static struct baud_table brg13_int[] = { + { 300, MAX3107_BRG13_IB300 }, + { 600, MAX3107_BRG13_IB600 }, + { 1200, MAX3107_BRG13_IB1200 }, + { 2400, MAX3107_BRG13_IB2400 }, + { 4800, MAX3107_BRG13_IB4800 }, + { 9600, MAX3107_BRG13_IB9600 }, + { 19200, MAX3107_BRG13_IB19200 }, + { 57600, MAX3107_BRG13_IB57600 }, + { 115200, MAX3107_BRG13_IB115200 }, + { 230400, MAX3107_BRG13_IB230400 }, + { 460800, MAX3107_BRG13_IB460800 }, + { 921600, MAX3107_BRG13_IB921600 }, + { 0, 0 } +}; + +static u32 get_new_brg(int baud, struct max3107_port *s) +{ + int i; + struct baud_table *baud_tbl = s->baud_tbl; + + for (i = 0; i < 13; i++) { + if (baud == baud_tbl[i].baud) + return baud_tbl[i].new_brg; + } + + return 0; +} + +/* Perform SPI transfer for write/read of device register(s) */ +static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len) +{ + struct spi_message spi_msg; + struct spi_transfer spi_xfer; + + /* Initialize SPI ,message */ + spi_message_init(&spi_msg); + + /* Initialize SPI transfer */ + memset(&spi_xfer, 0, sizeof spi_xfer); + spi_xfer.len = len; + spi_xfer.tx_buf = tx; + spi_xfer.rx_buf = rx; + spi_xfer.speed_hz = MAX3107_SPI_SPEED; + + /* Add SPI transfer to SPI message */ + spi_message_add_tail(&spi_xfer, &spi_msg); + +#ifdef DBG_TRACE_SPI_DATA + { + int i; + pr_info("tx len %d:\n", spi_xfer.len); + for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) + pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]); + pr_info("\n"); + } +#endif + + /* Perform synchronous SPI transfer */ + if (spi_sync(s->spi, &spi_msg)) { + dev_err(&s->spi->dev, "spi_sync failure\n"); + return -EIO; + } + +#ifdef DBG_TRACE_SPI_DATA + if (spi_xfer.rx_buf) { + int i; + pr_info("rx len %d:\n", spi_xfer.len); + for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) + pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]); + pr_info("\n"); + } +#endif + return 0; +} + +/* Puts received data to circular buffer */ +static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data, + int len) +{ + struct uart_port *port = &s->port; + struct tty_struct *tty; + + if (!port->state) + return; + + tty = port->state->port.tty; + if (!tty) + return; + + /* Insert received data */ + tty_insert_flip_string(tty, data, len); + /* Update RX counter */ + port->icount.rx += len; +} + +/* Handle data receiving */ +static void max3107_handlerx(struct max3107_port *s, u16 rxlvl) +{ + int i; + int j; + int len; /* SPI transfer buffer length */ + u16 *buf; + u8 *valid_str; + + if (!s->rx_enabled) + /* RX is disabled */ + return; + + if (rxlvl == 0) { + /* RX fifo is empty */ + return; + } else if (rxlvl >= MAX3107_RX_FIFO_SIZE) { + dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl); + /* Ensure sanity of RX level */ + rxlvl = MAX3107_RX_FIFO_SIZE; + } + if ((s->rxbuf == 0) || (s->rxstr == 0)) { + dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n"); + return; + } + buf = s->rxbuf; + valid_str = s->rxstr; + while (rxlvl) { + pr_debug("rxlvl %d\n", rxlvl); + /* Clear buffer */ + memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2)); + len = 0; + if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) { + /* First disable RX FIFO interrupt */ + pr_debug("Disabling RX INT\n"); + buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT; + buf[0] |= s->irqen_reg; + len++; + } + /* Just increase the length by amount of words in FIFO since + * buffer was zeroed and SPI transfer of 0x0000 means reading + * from RX FIFO + */ + len += rxlvl; + /* Append RX level query */ + buf[len] = MAX3107_RXFIFOLVL_REG; + len++; + + /* Perform the SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) { + dev_err(&s->spi->dev, "SPI transfer for RX h failed\n"); + return; + } + + /* Skip RX FIFO interrupt disabling word if it was added */ + j = ((len - 1) - rxlvl); + /* Read received words */ + for (i = 0; i < rxlvl; i++, j++) + valid_str[i] = (u8)buf[j]; + put_data_to_circ_buf(s, valid_str, rxlvl); + /* Get new RX level */ + rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK); + } + + if (s->rx_enabled) { + /* RX still enabled, re-enable RX FIFO interrupt */ + pr_debug("Enabling RX INT\n"); + buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; + buf[0] |= s->irqen_reg; + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n"); + } + + /* Push the received data to receivers */ + if (s->port.state->port.tty) + tty_flip_buffer_push(s->port.state->port.tty); +} + + +/* Handle data sending */ +static void max3107_handletx(struct max3107_port *s) +{ + struct circ_buf *xmit = &s->port.state->xmit; + int i; + unsigned long flags; + int len; /* SPI transfer buffer length */ + u16 *buf; + + if (!s->tx_fifo_empty) + /* Don't send more data before previous data is sent */ + return; + + if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port)) + /* No data to send or TX is stopped */ + return; + + if (!s->txbuf) { + dev_warn(&s->spi->dev, "Txbuf isn't ready\n"); + return; + } + buf = s->txbuf; + /* Get length of data pending in circular buffer */ + len = uart_circ_chars_pending(xmit); + if (len) { + /* Limit to size of TX FIFO */ + if (len > MAX3107_TX_FIFO_SIZE) + len = MAX3107_TX_FIFO_SIZE; + + pr_debug("txlen %d\n", len); + + /* Update TX counter */ + s->port.icount.tx += len; + + /* TX FIFO will no longer be empty */ + s->tx_fifo_empty = 0; + + i = 0; + if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) { + /* First disable TX empty interrupt */ + pr_debug("Disabling TE INT\n"); + buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT; + buf[i] |= s->irqen_reg; + i++; + len++; + } + /* Add data to send */ + spin_lock_irqsave(&s->port.lock, flags); + for ( ; i < len ; i++) { + buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG); + buf[i] |= ((u16)xmit->buf[xmit->tail] & + MAX3107_SPI_TX_DATA_MASK); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } + spin_unlock_irqrestore(&s->port.lock, flags); + if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) { + /* Enable TX empty interrupt */ + pr_debug("Enabling TE INT\n"); + buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); + s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT; + buf[i] |= s->irqen_reg; + i++; + len++; + } + if (!s->tx_enabled) { + /* Enable TX */ + pr_debug("Enable TX\n"); + buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + spin_lock_irqsave(&s->data_lock, flags); + s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT; + buf[i] |= s->mode1_reg; + spin_unlock_irqrestore(&s->data_lock, flags); + s->tx_enabled = 1; + i++; + len++; + } + + /* Perform the SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, len*2)) { + dev_err(&s->spi->dev, + "SPI transfer TX handling failed\n"); + return; + } + } + + /* Indicate wake up if circular buffer is getting low on data */ + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&s->port); + +} + +/* Handle interrupts + * Also reads and returns current RX FIFO level + */ +static u16 handle_interrupt(struct max3107_port *s) +{ + u16 buf[4]; /* Buffer for SPI transfers */ + u8 irq_status; + u16 rx_level; + unsigned long flags; + + /* Read IRQ status register */ + buf[0] = MAX3107_IRQSTS_REG; + /* Read status IRQ status register */ + buf[1] = MAX3107_STS_IRQSTS_REG; + /* Read LSR IRQ status register */ + buf[2] = MAX3107_LSR_IRQSTS_REG; + /* Query RX level */ + buf[3] = MAX3107_RXFIFOLVL_REG; + + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) { + dev_err(&s->spi->dev, + "SPI transfer for INTR handling failed\n"); + return 0; + } + + irq_status = (u8)buf[0]; + pr_debug("IRQSTS %x\n", irq_status); + rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK); + + if (irq_status & MAX3107_IRQ_LSR_BIT) { + /* LSR interrupt */ + if (buf[2] & MAX3107_LSR_RXTO_BIT) + /* RX timeout interrupt, + * handled by normal RX handling + */ + pr_debug("RX TO INT\n"); + } + + if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) { + /* Tx empty interrupt, + * disable TX and set tx_fifo_empty flag + */ + pr_debug("TE INT, disabling TX\n"); + buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + spin_lock_irqsave(&s->data_lock, flags); + s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; + buf[0] |= s->mode1_reg; + spin_unlock_irqrestore(&s->data_lock, flags); + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "SPI transfer TX dis failed\n"); + s->tx_enabled = 0; + s->tx_fifo_empty = 1; + } + + if (irq_status & MAX3107_IRQ_RXFIFO_BIT) + /* RX FIFO interrupt, + * handled by normal RX handling + */ + pr_debug("RFIFO INT\n"); + + /* Return RX level */ + return rx_level; +} + +/* Trigger work thread*/ +static void max3107_dowork(struct max3107_port *s) +{ + if (!work_pending(&s->work) && !freezing(current) && !s->suspended) + queue_work(s->workqueue, &s->work); + else + dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n"); +} + +/* Work thread */ +static void max3107_work(struct work_struct *w) +{ + struct max3107_port *s = container_of(w, struct max3107_port, work); + u16 rxlvl = 0; + int len; /* SPI transfer buffer length */ + u16 buf[5]; /* Buffer for SPI transfers */ + unsigned long flags; + + /* Start by reading current RX FIFO level */ + buf[0] = MAX3107_RXFIFOLVL_REG; + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer RX lev failed\n"); + rxlvl = 0; + } else { + rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK); + } + + do { + pr_debug("rxlvl %d\n", rxlvl); + + /* Handle RX */ + max3107_handlerx(s, rxlvl); + rxlvl = 0; + + if (s->handle_irq) { + /* Handle pending interrupts + * We also get new RX FIFO level since new data may + * have been received while pushing received data to + * receivers + */ + s->handle_irq = 0; + rxlvl = handle_interrupt(s); + } + + /* Handle TX */ + max3107_handletx(s); + + /* Handle configuration changes */ + len = 0; + spin_lock_irqsave(&s->data_lock, flags); + if (s->mode1_commit) { + pr_debug("mode1_commit\n"); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + buf[len++] |= s->mode1_reg; + s->mode1_commit = 0; + } + if (s->lcr_commit) { + pr_debug("lcr_commit\n"); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG); + buf[len++] |= s->lcr_reg; + s->lcr_commit = 0; + } + if (s->brg_commit) { + pr_debug("brg_commit\n"); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG); + buf[len++] |= ((s->brg_cfg >> 16) & + MAX3107_SPI_TX_DATA_MASK); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG); + buf[len++] |= ((s->brg_cfg >> 8) & + MAX3107_SPI_TX_DATA_MASK); + buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG); + buf[len++] |= ((s->brg_cfg) & 0xff); + s->brg_commit = 0; + } + spin_unlock_irqrestore(&s->data_lock, flags); + + if (len > 0) { + if (max3107_rw(s, (u8 *)buf, NULL, len * 2)) + dev_err(&s->spi->dev, + "SPI transfer config failed\n"); + } + + /* Reloop if interrupt handling indicated data in RX FIFO */ + } while (rxlvl); + +} + +/* Set sleep mode */ +static void max3107_set_sleep(struct max3107_port *s, int mode) +{ + u16 buf[1]; /* Buffer for SPI transfer */ + unsigned long flags; + pr_debug("enter, mode %d\n", mode); + + buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); + spin_lock_irqsave(&s->data_lock, flags); + switch (mode) { + case MAX3107_DISABLE_FORCED_SLEEP: + s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT; + break; + case MAX3107_ENABLE_FORCED_SLEEP: + s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT; + break; + case MAX3107_DISABLE_AUTOSLEEP: + s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT; + break; + case MAX3107_ENABLE_AUTOSLEEP: + s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT; + break; + default: + spin_unlock_irqrestore(&s->data_lock, flags); + dev_warn(&s->spi->dev, "invalid sleep mode\n"); + return; + } + buf[0] |= s->mode1_reg; + spin_unlock_irqrestore(&s->data_lock, flags); + + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n"); + + if (mode == MAX3107_DISABLE_AUTOSLEEP || + mode == MAX3107_DISABLE_FORCED_SLEEP) + msleep(MAX3107_WAKEUP_DELAY); +} + +/* Perform full register initialization */ +static void max3107_register_init(struct max3107_port *s) +{ + u16 buf[11]; /* Buffer for SPI transfers */ + + /* 1. Configure baud rate, 9600 as default */ + s->baud = 9600; + /* the below is default*/ + if (s->ext_clk) { + s->brg_cfg = MAX3107_BRG26_B9600; + s->baud_tbl = (struct baud_table *)brg26_ext; + } else { + s->brg_cfg = MAX3107_BRG13_IB9600; + s->baud_tbl = (struct baud_table *)brg13_int; + } +#if 0 + /*override for AAVA SC specific*/ + if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { + if (get_koski_build_id() <= KOSKI_EV2) + if (s->ext_clk) { + s->brg_cfg = MAX3107_BRG13_B9600; + s->baud_tbl = (struct baud_table *)brg13_ext; + } + } +#endif + buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG) + | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK); + buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG) + | ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK); + buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG) + | ((s->brg_cfg) & 0xff); + + /* 2. Configure LCR register, 8N1 mode by default */ + s->lcr_reg = MAX3107_LCR_WORD_LEN_8; + buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG) + | s->lcr_reg; + + /* 3. Configure MODE 1 register */ + s->mode1_reg = 0; + /* Enable IRQ pin */ + s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT; + /* Disable TX */ + s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; + s->tx_enabled = 0; + /* RX is enabled */ + s->rx_enabled = 1; + buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG) + | s->mode1_reg; + + /* 4. Configure MODE 2 register */ + buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); + if (s->loopback) { + /* Enable loopback */ + buf[5] |= MAX3107_MODE2_LOOPBACK_BIT; + } + /* Reset FIFOs */ + buf[5] |= MAX3107_MODE2_FIFORST_BIT; + s->tx_fifo_empty = 1; + + /* 5. Configure FIFO trigger level register */ + buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG); + /* RX FIFO trigger for 16 words, TX FIFO trigger not used */ + buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0)); + + /* 6. Configure flow control levels */ + buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG); + /* Flow control halt level 96, resume level 48 */ + buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96)); + + /* 7. Configure flow control */ + buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG); + /* Enable auto CTS and auto RTS flow control */ + buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT); + + /* 8. Configure RX timeout register */ + buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG); + /* Timeout after 48 character intervals */ + buf[9] |= 0x0030; + + /* 9. Configure LSR interrupt enable register */ + buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG); + /* Enable RX timeout interrupt */ + buf[10] |= MAX3107_LSR_RXTO_BIT; + + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 22)) + dev_err(&s->spi->dev, "SPI transfer for init failed\n"); + + /* 10. Clear IRQ status register by reading it */ + buf[0] = MAX3107_IRQSTS_REG; + + /* 11. Configure interrupt enable register */ + /* Enable LSR interrupt */ + s->irqen_reg = MAX3107_IRQ_LSR_BIT; + /* Enable RX FIFO interrupt */ + s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; + buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG) + | s->irqen_reg; + + /* 12. Clear FIFO reset that was set in step 6 */ + buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); + if (s->loopback) { + /* Keep loopback enabled */ + buf[2] |= MAX3107_MODE2_LOOPBACK_BIT; + } + + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6)) + dev_err(&s->spi->dev, "SPI transfer for init failed\n"); + +} + +/* IRQ handler */ +static irqreturn_t max3107_irq(int irqno, void *dev_id) +{ + struct max3107_port *s = dev_id; + + if (irqno != s->spi->irq) { + /* Unexpected IRQ */ + return IRQ_NONE; + } + + /* Indicate irq */ + s->handle_irq = 1; + + /* Trigger work thread */ + max3107_dowork(s); + + return IRQ_HANDLED; +} + +/* HW suspension function + * + * Currently autosleep is used to decrease current consumption, alternative + * approach would be to set the chip to reset mode if UART is not being + * used but that would mess the GPIOs + * + */ +static void max3107_hw_susp(struct max3107_port *s, int suspend) +{ + pr_debug("enter, suspend %d\n", suspend); + + if (suspend) { + /* Suspend requested, + * enable autosleep to decrease current consumption + */ + s->suspended = 1; + max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP); + } else { + /* Resume requested, + * disable autosleep + */ + s->suspended = 0; + max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP); + } +} + +/* Modem status IRQ enabling */ +static void max3107_enable_ms(struct uart_port *port) +{ + /* Modem status not supported */ +} + +/* Data send function */ +static void max3107_start_tx(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + /* Trigger work thread for sending data */ + max3107_dowork(s); +} + +/* Function for checking that there is no pending transfers */ +static unsigned int max3107_tx_empty(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + pr_debug("returning %d\n", + (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit))); + return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit); +} + +/* Function for stopping RX */ +static void max3107_stop_rx(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + unsigned long flags; + + /* Set RX disabled in MODE 1 register */ + spin_lock_irqsave(&s->data_lock, flags); + s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT; + s->mode1_commit = 1; + spin_unlock_irqrestore(&s->data_lock, flags); + /* Set RX disabled */ + s->rx_enabled = 0; + /* Trigger work thread for doing the actual configuration change */ + max3107_dowork(s); +} + +/* Function for returning control pin states */ +static unsigned int max3107_get_mctrl(struct uart_port *port) +{ + /* DCD and DSR are not wired and CTS/RTS is handled automatically + * so just indicate DSR and CAR asserted + */ + return TIOCM_DSR | TIOCM_CAR; +} + +/* Function for setting control pin states */ +static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* DCD and DSR are not wired and CTS/RTS is hadnled automatically + * so do nothing + */ +} + +/* Function for configuring UART parameters */ +static void max3107_set_termios(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + struct tty_struct *tty; + int baud; + u16 new_lcr = 0; + u32 new_brg = 0; + unsigned long flags; + + if (!port->state) + return; + + tty = port->state->port.tty; + if (!tty) + return; + + /* Get new LCR register values */ + /* Word size */ + if ((termios->c_cflag & CSIZE) == CS7) + new_lcr |= MAX3107_LCR_WORD_LEN_7; + else + new_lcr |= MAX3107_LCR_WORD_LEN_8; + + /* Parity */ + if (termios->c_cflag & PARENB) { + new_lcr |= MAX3107_LCR_PARITY_BIT; + if (!(termios->c_cflag & PARODD)) + new_lcr |= MAX3107_LCR_EVENPARITY_BIT; + } + + /* Stop bits */ + if (termios->c_cflag & CSTOPB) { + /* 2 stop bits */ + new_lcr |= MAX3107_LCR_STOPLEN_BIT; + } + + /* Mask termios capabilities we don't support */ + termios->c_cflag &= ~CMSPAR; + + /* Set status ignore mask */ + s->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + s->port.ignore_status_mask |= MAX3107_ALL_ERRORS; + + /* Set low latency to immediately handle pushed data */ + s->port.state->port.tty->low_latency = 1; + + /* Get new baud rate generator configuration */ + baud = tty_get_baud_rate(tty); + + spin_lock_irqsave(&s->data_lock, flags); + new_brg = get_new_brg(baud, s); + /* if can't find the corrent config, use previous */ + if (!new_brg) { + baud = s->baud; + new_brg = s->brg_cfg; + } + spin_unlock_irqrestore(&s->data_lock, flags); + tty_termios_encode_baud_rate(termios, baud, baud); + s->baud = baud; + + /* Update timeout according to new baud rate */ + uart_update_timeout(port, termios->c_cflag, baud); + + spin_lock_irqsave(&s->data_lock, flags); + if (s->lcr_reg != new_lcr) { + s->lcr_reg = new_lcr; + s->lcr_commit = 1; + } + if (s->brg_cfg != new_brg) { + s->brg_cfg = new_brg; + s->brg_commit = 1; + } + spin_unlock_irqrestore(&s->data_lock, flags); + + /* Trigger work thread for doing the actual configuration change */ + max3107_dowork(s); +} + +/* Port shutdown function */ +static void max3107_shutdown(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + if (s->suspended) { + /* Resume HW */ + max3107_hw_susp(s, 0); + } + + /* Free the interrupt */ + free_irq(s->spi->irq, s); + + if (s->workqueue) { + /* Flush and destroy work queue */ + flush_workqueue(s->workqueue); + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + } + + /* Suspend HW */ + max3107_hw_susp(s, 1); +} + +/* Port startup function */ +static int max3107_startup(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + /* Initialize work queue */ + s->workqueue = create_freezeable_workqueue("max3107"); + if (!s->workqueue) { + dev_err(&s->spi->dev, "Workqueue creation failed\n"); + return -EBUSY; + } + INIT_WORK(&s->work, max3107_work); + + /* Setup IRQ */ + if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING, + "max3107", s)) { + dev_err(&s->spi->dev, "IRQ reguest failed\n"); + destroy_workqueue(s->workqueue); + s->workqueue = NULL; + return -EBUSY; + } + + /* Resume HW */ + max3107_hw_susp(s, 0); + + /* Init registers */ + max3107_register_init(s); + + return 0; +} + +/* Port type function */ +static const char *max3107_type(struct uart_port *port) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + return s->spi->modalias; +} + +/* Port release function */ +static void max3107_release_port(struct uart_port *port) +{ + /* Do nothing */ +} + +/* Port request function */ +static int max3107_request_port(struct uart_port *port) +{ + /* Do nothing */ + return 0; +} + +/* Port config function */ +static void max3107_config_port(struct uart_port *port, int flags) +{ + struct max3107_port *s = container_of(port, struct max3107_port, port); + + /* Use PORT_MAX3100 since we are at least int the same series */ + s->port.type = PORT_MAX3100; +} + +/* Port verify function */ +static int max3107_verify_port(struct uart_port *port, + struct serial_struct *ser) +{ + if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100) + return 0; + + return -EINVAL; +} + +/* Port stop TX function */ +static void max3107_stop_tx(struct uart_port *port) +{ + /* Do nothing */ +} + +/* Port break control function */ +static void max3107_break_ctl(struct uart_port *port, int break_state) +{ + /* We don't support break control, do nothing */ +} + +/* GPIO direction to input function */ +static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[1]; /* Buffer for SPI transfer */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return -EINVAL; + } + + /* Read current GPIO configuration register */ + buf[0] = MAX3107_GPIOCFG_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); + return -EIO; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + + /* Set GPIO to input */ + buf[0] &= ~(0x0001 << offset); + + /* Write new GPIO configuration register value */ + buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 2)) { + dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); + return -EIO; + } + return 0; +} + +/* GPIO direction to output function */ +static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[2]; /* Buffer for SPI transfers */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return -EINVAL; + } + + /* Read current GPIO configuration and data registers */ + buf[0] = MAX3107_GPIOCFG_REG; + buf[1] = MAX3107_GPIODATA_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { + dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); + return -EIO; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + buf[1] &= MAX3107_SPI_RX_DATA_MASK; + + /* Set GPIO to output */ + buf[0] |= (0x0001 << offset); + /* Set value */ + if (value) + buf[1] |= (0x0001 << offset); + else + buf[1] &= ~(0x0001 << offset); + + /* Write new GPIO configuration and data register values */ + buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); + buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 4)) { + dev_err(&s->spi->dev, + "SPI transfer for GPIO conf data w failed\n"); + return -EIO; + } + return 0; +} + +/* GPIO value query function */ +static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[1]; /* Buffer for SPI transfer */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return -EINVAL; + } + + /* Read current GPIO data register */ + buf[0] = MAX3107_GPIODATA_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); + return -EIO; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + + /* Return value */ + return buf[0] & (0x0001 << offset); +} + +/* GPIO value set function */ +static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[2]; /* Buffer for SPI transfers */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return; + } + + /* Read current GPIO configuration registers*/ + buf[0] = MAX3107_GPIODATA_REG; + buf[1] = MAX3107_GPIOCFG_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { + dev_err(&s->spi->dev, + "SPI transfer for GPIO data and config read failed\n"); + return; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + buf[1] &= MAX3107_SPI_RX_DATA_MASK; + + if (!(buf[1] & (0x0001 << offset))) { + /* Configured as input, can't set value */ + dev_warn(&s->spi->dev, + "Trying to set value for input GPIO\n"); + return; + } + + /* Set value */ + if (value) + buf[0] |= (0x0001 << offset); + else + buf[0] &= ~(0x0001 << offset); + + /* Write new GPIO data register value */ + buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); +} + +/* Platform data */ +static struct max3107_plat max3107_plat_data = { + .loopback = 0, + .ext_clk = 1, + .max3107_hw_suspend = &max3107_hw_susp, + .polled_mode = 0, + .poll_time = 0, +}; + +/* Port functions */ +static struct uart_ops max3107_ops = { + .tx_empty = max3107_tx_empty, + .set_mctrl = max3107_set_mctrl, + .get_mctrl = max3107_get_mctrl, + .stop_tx = max3107_stop_tx, + .start_tx = max3107_start_tx, + .stop_rx = max3107_stop_rx, + .enable_ms = max3107_enable_ms, + .break_ctl = max3107_break_ctl, + .startup = max3107_startup, + .shutdown = max3107_shutdown, + .set_termios = max3107_set_termios, + .type = max3107_type, + .release_port = max3107_release_port, + .request_port = max3107_request_port, + .config_port = max3107_config_port, + .verify_port = max3107_verify_port, +}; + +/* UART driver data */ +static struct uart_driver max3107_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "ttyMAX", + .dev_name = "ttyMAX", + .nr = 1, +}; + +/* GPIO chip data */ +static struct gpio_chip max3107_gpio_chip = { + .owner = THIS_MODULE, + .direction_input = max3107_gpio_direction_in, + .direction_output = max3107_gpio_direction_out, + .get = max3107_gpio_get, + .set = max3107_gpio_set, + .can_sleep = 1, + .base = MAX3107_GPIO_BASE, + .ngpio = MAX3107_GPIO_COUNT, +}; +/* Device probe function */ +static int __devinit max3107_probe(struct spi_device *spi) +{ + struct max3107_port *s; + struct max3107_plat *pdata = &max3107_plat_data; + u16 buf[2]; /* Buffer for SPI transfers */ + int retval; + + pr_info("enter max3107 probe\n"); + + /* Reset the chip */ + if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { + pr_err("Requesting RESET GPIO failed\n"); + return -EIO; + } + if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { + pr_err("Setting RESET GPIO to 0 failed\n"); + gpio_free(MAX3107_RESET_GPIO); + return -EIO; + } + msleep(MAX3107_RESET_DELAY); + if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { + pr_err("Setting RESET GPIO to 1 failed\n"); + gpio_free(MAX3107_RESET_GPIO); + return -EIO; + } + gpio_free(MAX3107_RESET_GPIO); + msleep(MAX3107_WAKEUP_DELAY); + + /* Allocate port structure */ + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) { + pr_err("Allocating port structure failed\n"); + return -ENOMEM; + } + /* SPI Rx buffer + * +2 for RX FIFO interrupt + * disabling and RX level query + */ + s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL); + if (!s->rxbuf) { + pr_err("Allocating RX buffer failed\n"); + return -ENOMEM; + } + s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL); + if (!s->rxstr) { + pr_err("Allocating RX buffer failed\n"); + return -ENOMEM; + } + /* SPI Tx buffer + * SPI transfer buffer + * +3 for TX FIFO empty + * interrupt disabling and + * enabling and TX enabling + */ + s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL); + if (!s->txbuf) { + pr_err("Allocating TX buffer failed\n"); + return -ENOMEM; + } + /* Initialize shared data lock */ + spin_lock_init(&s->data_lock); + + /* SPI intializations */ + dev_set_drvdata(&spi->dev, s); + spi->mode = SPI_MODE_0; + spi->dev.platform_data = pdata; + spi->bits_per_word = 16; + s->ext_clk = pdata->ext_clk; + s->loopback = pdata->loopback; + spi_setup(spi); + s->spi = spi; + + /* Check REV ID to ensure we are talking to what we expect */ + buf[0] = MAX3107_REVID_REG; + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n"); + return -EIO; + } + if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 && + (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) { + dev_err(&s->spi->dev, "REVID %x does not match\n", + (buf[0] & MAX3107_SPI_RX_DATA_MASK)); + return -ENODEV; + } + + /* Disable all interrupts */ + buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000); + buf[0] |= 0x0000; + + /* Configure clock source */ + buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG); + if (s->ext_clk) { + /* External clock */ + buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT; + } + + /* PLL bypass ON */ + buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT; + + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 4)) { + dev_err(&s->spi->dev, "SPI transfer for init failed\n"); + return -EIO; + } + + /* Register UART driver */ + retval = uart_register_driver(&max3107_uart_driver); + if (retval) { + dev_err(&s->spi->dev, "Registering UART driver failed\n"); + return retval; + } + + /* Initialize UART port data */ + s->port.fifosize = 128; + s->port.ops = &max3107_ops; + s->port.line = 0; + s->port.dev = &spi->dev; + s->port.uartclk = 9600; + s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + s->port.irq = s->spi->irq; + /* Use PORT_MAX3100 since we are at least in the same series */ + s->port.type = PORT_MAX3100; + + /* Add UART port */ + retval = uart_add_one_port(&max3107_uart_driver, &s->port); + if (retval < 0) { + dev_err(&s->spi->dev, "Adding UART port failed\n"); + return retval; + } + + /* Initialize GPIO chip data */ + s->chip = max3107_gpio_chip; + s->chip.label = spi->modalias; + s->chip.dev = &spi->dev; + + /* Add GPIO chip */ + retval = gpiochip_add(&s->chip); + if (retval) { + dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); + return retval; + } + + /* Temporary fix for EV2 boot problems, set modem reset to 0 */ + max3107_gpio_direction_out(&s->chip, 3, 0); + + /* Go to suspend mode */ + max3107_hw_susp(s, 1); + + return 0; +} + +/* Driver remove function */ +static int __devexit max3107_remove(struct spi_device *spi) +{ + struct max3107_port *s = dev_get_drvdata(&spi->dev); + + pr_info("enter max3107 remove\n"); + + /* Remove GPIO chip */ + if (gpiochip_remove(&s->chip)) + dev_warn(&s->spi->dev, "Removing GPIO chip failed\n"); + + /* Remove port */ + if (uart_remove_one_port(&max3107_uart_driver, &s->port)) + dev_warn(&s->spi->dev, "Removing UART port failed\n"); + + /* Unregister UART driver */ + uart_unregister_driver(&max3107_uart_driver); + + /* Free TxRx buffer */ + kfree(s->rxbuf); + kfree(s->rxstr); + kfree(s->txbuf); + + /* Free port structure */ + kfree(s); + + return 0; +} + +/* Driver suspend function */ +static int max3107_suspend(struct spi_device *spi, pm_message_t state) +{ +#ifdef CONFIG_PM + struct max3107_port *s = dev_get_drvdata(&spi->dev); + + pr_debug("enter suspend\n"); + + /* Suspend UART port */ + uart_suspend_port(&max3107_uart_driver, &s->port); + + /* Go to suspend mode */ + max3107_hw_susp(s, 1); +#endif /* CONFIG_PM */ + return 0; +} + +/* Driver resume function */ +static int max3107_resume(struct spi_device *spi) +{ +#ifdef CONFIG_PM + struct max3107_port *s = dev_get_drvdata(&spi->dev); + + pr_debug("enter resume\n"); + + /* Resume from suspend */ + max3107_hw_susp(s, 0); + + /* Resume UART port */ + uart_resume_port(&max3107_uart_driver, &s->port); +#endif /* CONFIG_PM */ + return 0; +} + +/* Spi driver data */ +static struct spi_driver max3107_driver = { + .driver = { + .name = "max3107", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = max3107_probe, + .remove = __devexit_p(max3107_remove), + .suspend = max3107_suspend, + .resume = max3107_resume, +}; + +/* Driver init function */ +static int __init max3107_init(void) +{ + pr_info("enter max3107 init\n"); + return spi_register_driver(&max3107_driver); +} + +/* Driver exit function */ +static void __exit max3107_exit(void) +{ + pr_info("enter max3107 exit\n"); + spi_unregister_driver(&max3107_driver); +} + +module_init(max3107_init); +module_exit(max3107_exit); + +MODULE_DESCRIPTION("MAX3107 driver"); +MODULE_AUTHOR("Aavamobile"); +MODULE_ALIAS("max3107-spi-uart"); +MODULE_LICENSE("GPLv2"); diff --git a/drivers/serial/max3107.h b/drivers/serial/max3107.h new file mode 100644 index 000000000000..a5625d1f263d --- /dev/null +++ b/drivers/serial/max3107.h @@ -0,0 +1,358 @@ +/* + * max3107.h - spi uart protocol driver header for Maxim 3107 + * + * Copyright (C) Aavamobile 2009 + * Based on serial_max3100.h by Christian Pellegrin + * + * 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. + */ + +#ifndef _LINUX_SERIAL_MAX3107_H +#define _LINUX_SERIAL_MAX3107_H + +/* Serial error status definitions */ +#define MAX3107_PARITY_ERROR 1 +#define MAX3107_FRAME_ERROR 2 +#define MAX3107_OVERRUN_ERROR 4 +#define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \ + MAX3107_FRAME_ERROR | \ + MAX3107_OVERRUN_ERROR) + +/* GPIO definitions */ +#define MAX3107_GPIO_BASE 88 +#define MAX3107_GPIO_COUNT 4 + + +/* GPIO connected to chip's reset pin */ +#define MAX3107_RESET_GPIO 87 + + +/* Chip reset delay */ +#define MAX3107_RESET_DELAY 10 + +/* Chip wakeup delay */ +#define MAX3107_WAKEUP_DELAY 50 + + +/* Sleep mode definitions */ +#define MAX3107_DISABLE_FORCED_SLEEP 0 +#define MAX3107_ENABLE_FORCED_SLEEP 1 +#define MAX3107_DISABLE_AUTOSLEEP 2 +#define MAX3107_ENABLE_AUTOSLEEP 3 + + +/* Definitions for register access with SPI transfers + * + * SPI transfer format: + * + * Master to slave bits xzzzzzzzyyyyyyyy + * Slave to master bits aaaaaaaabbbbbbbb + * + * where: + * x = 0 for reads, 1 for writes + * z = register address + * y = new register value if write, 0 if read + * a = unspecified + * b = register value if read, unspecified if write + */ + +/* SPI speed */ +#define MAX3107_SPI_SPEED (3125000 * 2) + +/* Write bit */ +#define MAX3107_WRITE_BIT (1 << 15) + +/* SPI TX data mask */ +#define MAX3107_SPI_RX_DATA_MASK (0x00ff) + +/* SPI RX data mask */ +#define MAX3107_SPI_TX_DATA_MASK (0x00ff) + +/* Register access masks */ +#define MAX3107_RHR_REG (0x0000) /* RX FIFO */ +#define MAX3107_THR_REG (0x0000) /* TX FIFO */ +#define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */ +#define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */ +#define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */ +#define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */ +#define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */ +#define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */ +#define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */ +#define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */ +#define MAX3107_MODE1_REG (0x0900) /* MODE1 */ +#define MAX3107_MODE2_REG (0x0a00) /* MODE2 */ +#define MAX3107_LCR_REG (0x0b00) /* LCR */ +#define MAX3107_RXTO_REG (0x0c00) /* RX timeout */ +#define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */ +#define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */ +#define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */ +#define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */ +#define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */ +#define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */ +#define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */ +#define MAX3107_XON1_REG (0x1400) /* XON1 character */ +#define MAX3107_XON2_REG (0x1500) /* XON2 character */ +#define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */ +#define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */ +#define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */ +#define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */ +#define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */ +#define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */ +#define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */ +#define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */ +#define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */ +#define MAX3107_REVID_REG (0x1f00) /* Revision identification */ + +/* IRQ register bits */ +#define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ +#define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ +#define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */ +#define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */ +#define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */ +#define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */ +#define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */ +#define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */ + +/* LSR register bits */ +#define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */ +#define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */ +#define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */ +#define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */ +#define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */ +#define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */ +#define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */ + +/* Special character register bits */ +#define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */ +#define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */ +#define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */ +#define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */ +#define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */ +#define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */ +#define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* Status register bits */ +#define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */ +#define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */ +#define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */ +#define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */ +#define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */ +#define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */ +#define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */ +#define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* MODE1 register bits */ +#define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */ +#define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */ +#define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */ +#define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */ +#define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */ +#define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */ +#define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */ +#define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */ + +/* MODE2 register bits */ +#define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */ +#define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */ +#define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */ +#define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */ +#define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */ +#define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */ +#define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */ +#define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */ + +/* LCR register bits */ +#define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */ +#define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1 + * + * Word length bits table: + * 00 -> 5 bit words + * 01 -> 6 bit words + * 10 -> 7 bit words + * 11 -> 8 bit words + */ +#define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit + * + * STOP length bit table: + * 0 -> 1 stop bit + * 1 -> 1-1.5 stop bits if + * word length is 5, + * 2 stop bits otherwise + */ +#define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */ +#define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */ +#define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */ +#define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */ +#define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */ +#define MAX3107_LCR_WORD_LEN_5 (0x0000) +#define MAX3107_LCR_WORD_LEN_6 (0x0001) +#define MAX3107_LCR_WORD_LEN_7 (0x0002) +#define MAX3107_LCR_WORD_LEN_8 (0x0003) + + +/* IRDA register bits */ +#define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */ +#define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ +#define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */ +#define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */ +#define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */ +#define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */ +#define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* Flow control trigger level register masks */ +#define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */ +#define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */ +#define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f) +#define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4) + +/* FIFO interrupt trigger level register masks */ +#define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */ +#define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */ +#define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f) +#define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4) + +/* Flow control register bits */ +#define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */ +#define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */ +#define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs + * are used in conjunction with + * XOFF2 for definition of + * special character */ +#define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ +#define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ +#define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 + * + * SWFLOW bits 1 & 0 table: + * 00 -> no transmitter flow + * control + * 01 -> receiver compares + * XON2 and XOFF2 + * and controls + * transmitter + * 10 -> receiver compares + * XON1 and XOFF1 + * and controls + * transmitter + * 11 -> receiver compares + * XON1, XON2, XOFF1 and + * XOFF2 and controls + * transmitter + */ +#define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */ +#define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3 + * + * SWFLOW bits 3 & 2 table: + * 00 -> no received flow + * control + * 01 -> transmitter generates + * XON2 and XOFF2 + * 10 -> transmitter generates + * XON1 and XOFF1 + * 11 -> transmitter generates + * XON1, XON2, XOFF1 and + * XOFF2 + */ + +/* GPIO configuration register bits */ +#define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */ +#define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */ +#define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */ +#define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */ +#define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */ +#define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */ +#define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */ +#define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */ + +/* GPIO DATA register bits */ +#define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */ +#define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */ +#define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */ +#define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */ +#define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */ +#define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */ +#define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */ +#define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */ + +/* PLL configuration register masks */ +#define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */ +#define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */ + +/* Baud rate generator configuration register masks and bits */ +#define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of + * Baud rate generator divisor + */ +#define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ +#define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */ +#define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */ + +/* Clock source register bits */ +#define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */ +#define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */ +#define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */ +#define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */ +#define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */ +#define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */ +#define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */ +#define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */ + + +/* HW definitions */ +#define MAX3107_RX_FIFO_SIZE 128 +#define MAX3107_TX_FIFO_SIZE 128 +#define MAX3107_REVID1 0x00a0 +#define MAX3107_REVID2 0x00a1 + + +/* Baud rate generator configuration values for external clock 13MHz */ +#define MAX3107_BRG13_B300 (0x0A9400 | 0x05) +#define MAX3107_BRG13_B600 (0x054A00 | 0x03) +#define MAX3107_BRG13_B1200 (0x02A500 | 0x01) +#define MAX3107_BRG13_B2400 (0x015200 | 0x09) +#define MAX3107_BRG13_B4800 (0x00A900 | 0x04) +#define MAX3107_BRG13_B9600 (0x005400 | 0x0A) +#define MAX3107_BRG13_B19200 (0x002A00 | 0x05) +#define MAX3107_BRG13_B38400 (0x001500 | 0x03) +#define MAX3107_BRG13_B57600 (0x000E00 | 0x02) +#define MAX3107_BRG13_B115200 (0x000700 | 0x01) +#define MAX3107_BRG13_B230400 (0x000300 | 0x08) +#define MAX3107_BRG13_B460800 (0x000100 | 0x0c) +#define MAX3107_BRG13_B921600 (0x000100 | 0x1c) + +/* Baud rate generator configuration values for external clock 26MHz */ +#define MAX3107_BRG26_B300 (0x152800 | 0x0A) +#define MAX3107_BRG26_B600 (0x0A9400 | 0x05) +#define MAX3107_BRG26_B1200 (0x054A00 | 0x03) +#define MAX3107_BRG26_B2400 (0x02A500 | 0x01) +#define MAX3107_BRG26_B4800 (0x015200 | 0x09) +#define MAX3107_BRG26_B9600 (0x00A900 | 0x04) +#define MAX3107_BRG26_B19200 (0x005400 | 0x0A) +#define MAX3107_BRG26_B38400 (0x002A00 | 0x05) +#define MAX3107_BRG26_B57600 (0x001C00 | 0x03) +#define MAX3107_BRG26_B115200 (0x000E00 | 0x02) +#define MAX3107_BRG26_B230400 (0x000700 | 0x01) +#define MAX3107_BRG26_B460800 (0x000300 | 0x08) +#define MAX3107_BRG26_B921600 (0x000100 | 0x0C) + +/* Baud rate generator configuration values for internal clock */ +#define MAX3107_BRG13_IB300 (0x008000 | 0x00) +#define MAX3107_BRG13_IB600 (0x004000 | 0x00) +#define MAX3107_BRG13_IB1200 (0x002000 | 0x00) +#define MAX3107_BRG13_IB2400 (0x001000 | 0x00) +#define MAX3107_BRG13_IB4800 (0x000800 | 0x00) +#define MAX3107_BRG13_IB9600 (0x000400 | 0x00) +#define MAX3107_BRG13_IB19200 (0x000200 | 0x00) +#define MAX3107_BRG13_IB38400 (0x000100 | 0x00) +#define MAX3107_BRG13_IB57600 (0x000000 | 0x0B) +#define MAX3107_BRG13_IB115200 (0x000000 | 0x05) +#define MAX3107_BRG13_IB230400 (0x000000 | 0x03) +#define MAX3107_BRG13_IB460800 (0x000000 | 0x00) +#define MAX3107_BRG13_IB921600 (0x000000 | 0x00) + +#endif /* _LINUX_SERIAL_MAX3107_H */ -- cgit v1.2.3 From 61fd15262bb9c88a05fd89af22add9317dc1b1f4 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 30 Jun 2010 17:58:38 +0100 Subject: serial: max3107: Abstract out the platform specific bits At the moment there is only one platform type supported and there is is hard wired, but with these changes the infrastructure is now there for anyone else to provide methods for their hardware. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/Kconfig | 21 ++- drivers/serial/Makefile | 1 + drivers/serial/max3107-aava.c | 344 +++++++++++++++++++++++++++++++++++ drivers/serial/max3107.c | 413 +++++++++--------------------------------- drivers/serial/max3107.h | 85 ++++++++- include/linux/serial_core.h | 4 + 6 files changed, 531 insertions(+), 337 deletions(-) create mode 100644 drivers/serial/max3107-aava.c (limited to 'drivers/serial') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index fd406273cb71..c34c217878b3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -542,20 +542,29 @@ config SERIAL_S5PV210 help Serial port support for Samsung's S5P Family of SoC's + +config SERIAL_MAX3100 + tristate "MAX3100 support" + depends on SPI + select SERIAL_CORE + help + MAX3100 chip support + config SERIAL_MAX3107 tristate "MAX3107 support" - depends on SPI && GPIOLIB + depends on SPI select SERIAL_CORE - default y help MAX3107 chip support -config SERIAL_MAX3100 - tristate "MAX3100 support" - depends on SPI +config SERIAL_MAX3107_AAVA + tristate "MAX3107 AAVA platform support" + depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB select SERIAL_CORE help - MAX3100 chip support + Support for the MAX3107 chip configuration found on the AAVA + platform. Includes the extra initialisation and GPIO support + neded for this device. config SERIAL_DZ bool "DECstation DZ serial driver" diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 4cd0c0694917..424067ac3347 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX3107) += max3107.o +obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o diff --git a/drivers/serial/max3107-aava.c b/drivers/serial/max3107-aava.c new file mode 100644 index 000000000000..a1fe304f2f52 --- /dev/null +++ b/drivers/serial/max3107-aava.c @@ -0,0 +1,344 @@ +/* + * max3107.c - spi uart protocol driver for Maxim 3107 + * Based on max3100.c + * by Christian Pellegrin + * and max3110.c + * by Feng Tang + * + * Copyright (C) Aavamobile 2009 + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "max3107.h" + +/* GPIO direction to input function */ +static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[1]; /* Buffer for SPI transfer */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return -EINVAL; + } + + /* Read current GPIO configuration register */ + buf[0] = MAX3107_GPIOCFG_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); + return -EIO; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + + /* Set GPIO to input */ + buf[0] &= ~(0x0001 << offset); + + /* Write new GPIO configuration register value */ + buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 2)) { + dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); + return -EIO; + } + return 0; +} + +/* GPIO direction to output function */ +static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[2]; /* Buffer for SPI transfers */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return -EINVAL; + } + + /* Read current GPIO configuration and data registers */ + buf[0] = MAX3107_GPIOCFG_REG; + buf[1] = MAX3107_GPIODATA_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { + dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); + return -EIO; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + buf[1] &= MAX3107_SPI_RX_DATA_MASK; + + /* Set GPIO to output */ + buf[0] |= (0x0001 << offset); + /* Set value */ + if (value) + buf[1] |= (0x0001 << offset); + else + buf[1] &= ~(0x0001 << offset); + + /* Write new GPIO configuration and data register values */ + buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); + buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 4)) { + dev_err(&s->spi->dev, + "SPI transfer for GPIO conf data w failed\n"); + return -EIO; + } + return 0; +} + +/* GPIO value query function */ +static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[1]; /* Buffer for SPI transfer */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return -EINVAL; + } + + /* Read current GPIO data register */ + buf[0] = MAX3107_GPIODATA_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { + dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); + return -EIO; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + + /* Return value */ + return buf[0] & (0x0001 << offset); +} + +/* GPIO value set function */ +static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct max3107_port *s = container_of(chip, struct max3107_port, chip); + u16 buf[2]; /* Buffer for SPI transfers */ + + if (offset >= MAX3107_GPIO_COUNT) { + dev_err(&s->spi->dev, "Invalid GPIO\n"); + return; + } + + /* Read current GPIO configuration registers*/ + buf[0] = MAX3107_GPIODATA_REG; + buf[1] = MAX3107_GPIOCFG_REG; + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { + dev_err(&s->spi->dev, + "SPI transfer for GPIO data and config read failed\n"); + return; + } + buf[0] &= MAX3107_SPI_RX_DATA_MASK; + buf[1] &= MAX3107_SPI_RX_DATA_MASK; + + if (!(buf[1] & (0x0001 << offset))) { + /* Configured as input, can't set value */ + dev_warn(&s->spi->dev, + "Trying to set value for input GPIO\n"); + return; + } + + /* Set value */ + if (value) + buf[0] |= (0x0001 << offset); + else + buf[0] &= ~(0x0001 << offset); + + /* Write new GPIO data register value */ + buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); + /* Perform SPI transfer */ + if (max3107_rw(s, (u8 *)buf, NULL, 2)) + dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); +} + +/* GPIO chip data */ +static struct gpio_chip max3107_gpio_chip = { + .owner = THIS_MODULE, + .direction_input = max3107_gpio_direction_in, + .direction_output = max3107_gpio_direction_out, + .get = max3107_gpio_get, + .set = max3107_gpio_set, + .can_sleep = 1, + .base = MAX3107_GPIO_BASE, + .ngpio = MAX3107_GPIO_COUNT, +}; + +/** + * max3107_aava_reset - reset on AAVA systems + * @spi: The SPI device we are probing + * + * Reset the device ready for probing. + */ + +static int max3107_aava_reset(struct spi_device *spi) +{ + /* Reset the chip */ + if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { + pr_err("Requesting RESET GPIO failed\n"); + return -EIO; + } + if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { + pr_err("Setting RESET GPIO to 0 failed\n"); + gpio_free(MAX3107_RESET_GPIO); + return -EIO; + } + msleep(MAX3107_RESET_DELAY); + if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { + pr_err("Setting RESET GPIO to 1 failed\n"); + gpio_free(MAX3107_RESET_GPIO); + return -EIO; + } + gpio_free(MAX3107_RESET_GPIO); + msleep(MAX3107_WAKEUP_DELAY); + return 0; +} + +static int max3107_aava_configure(struct max3107_port *s) +{ + int retval; + + /* Initialize GPIO chip data */ + s->chip = max3107_gpio_chip; + s->chip.label = s->spi->modalias; + s->chip.dev = &s->spi->dev; + + /* Add GPIO chip */ + retval = gpiochip_add(&s->chip); + if (retval) { + dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); + return retval; + } + + /* Temporary fix for EV2 boot problems, set modem reset to 0 */ + max3107_gpio_direction_out(&s->chip, 3, 0); + return 0; +} + +#if 0 +/* This will get enabled once we have the board stuff merged for this + specific case */ + +static const struct baud_table brg13_ext[] = { + { 300, MAX3107_BRG13_B300 }, + { 600, MAX3107_BRG13_B600 }, + { 1200, MAX3107_BRG13_B1200 }, + { 2400, MAX3107_BRG13_B2400 }, + { 4800, MAX3107_BRG13_B4800 }, + { 9600, MAX3107_BRG13_B9600 }, + { 19200, MAX3107_BRG13_B19200 }, + { 57600, MAX3107_BRG13_B57600 }, + { 115200, MAX3107_BRG13_B115200 }, + { 230400, MAX3107_BRG13_B230400 }, + { 460800, MAX3107_BRG13_B460800 }, + { 921600, MAX3107_BRG13_B921600 }, + { 0, 0 } +}; + +static void max3107_aava_init(struct max3107_port *s) +{ + /*override for AAVA SC specific*/ + if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { + if (get_koski_build_id() <= KOSKI_EV2) + if (s->ext_clk) { + s->brg_cfg = MAX3107_BRG13_B9600; + s->baud_tbl = (struct baud_table *)brg13_ext; + } + } +} +#endif + +static int __devexit max3107_aava_remove(struct spi_device *spi) +{ + struct max3107_port *s = dev_get_drvdata(&spi->dev); + + /* Remove GPIO chip */ + if (gpiochip_remove(&s->chip)) + dev_warn(&spi->dev, "Removing GPIO chip failed\n"); + + /* Then do the default remove */ + return max3107_remove(spi); +} + +/* Platform data */ +static struct max3107_plat aava_plat_data = { + .loopback = 0, + .ext_clk = 1, +/* .init = max3107_aava_init, */ + .configure = max3107_aava_configure, + .hw_suspend = max3107_hw_susp, + .polled_mode = 0, + .poll_time = 0, +}; + + +static int __devinit max3107_probe_aava(struct spi_device *spi) +{ + int err = max3107_aava_reset(spi); + if (err < 0) + return err; + return max3107_probe(spi, &aava_plat_data); +} + +/* Spi driver data */ +static struct spi_driver max3107_driver = { + .driver = { + .name = "aava-max3107", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = max3107_probe_aava, + .remove = __devexit_p(max3107_aava_remove), + .suspend = max3107_suspend, + .resume = max3107_resume, +}; + +/* Driver init function */ +static int __init max3107_init(void) +{ + return spi_register_driver(&max3107_driver); +} + +/* Driver exit function */ +static void __exit max3107_exit(void) +{ + spi_unregister_driver(&max3107_driver); +} + +module_init(max3107_init); +module_exit(max3107_exit); + +MODULE_DESCRIPTION("MAX3107 driver"); +MODULE_AUTHOR("Aavamobile"); +MODULE_ALIAS("aava-max3107-spi"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c index a96ddd388ffd..67283c1a57ff 100644 --- a/drivers/serial/max3107.c +++ b/drivers/serial/max3107.c @@ -31,98 +31,12 @@ #include #include #include +#include #include #include -#include -#include -#include -#include #include "max3107.h" -struct baud_table { - int baud; - u32 new_brg; -}; - -struct max3107_port { - /* UART port structure */ - struct uart_port port; - - /* SPI device structure */ - struct spi_device *spi; - - /* GPIO chip stucture */ - struct gpio_chip chip; - - /* Workqueue that does all the magic */ - struct workqueue_struct *workqueue; - struct work_struct work; - - /* Lock for shared data */ - spinlock_t data_lock; - - /* Device configuration */ - int ext_clk; /* 1 if external clock used */ - int loopback; /* Current loopback mode state */ - int baud; /* Current baud rate */ - - /* State flags */ - int suspended; /* Indicates suspend mode */ - int tx_fifo_empty; /* Flag for TX FIFO state */ - int rx_enabled; /* Flag for receiver state */ - int tx_enabled; /* Flag for transmitter state */ - - u16 irqen_reg; /* Current IRQ enable register value */ - /* Shared data */ - u16 mode1_reg; /* Current mode1 register value*/ - int mode1_commit; /* Flag for setting new mode1 register value */ - u16 lcr_reg; /* Current LCR register value */ - int lcr_commit; /* Flag for setting new LCR register value */ - u32 brg_cfg; /* Current Baud rate generator config */ - int brg_commit; /* Flag for setting new baud rate generator - * config - */ - struct baud_table *baud_tbl; - int handle_irq; /* Indicates that IRQ should be handled */ - - /* Rx buffer and str*/ - u16 *rxbuf; - u8 *rxstr; - /* Tx buffer*/ - u16 *txbuf; -}; - -/* Platform data structure */ -struct max3107_plat { - /* Loopback mode enable */ - int loopback; - /* External clock enable */ - int ext_clk; - /* HW suspend function */ - void (*max3107_hw_suspend) (struct max3107_port *s, int suspend); - /* Polling mode enable */ - int polled_mode; - /* Polling period if polling mode enabled */ - int poll_time; -}; - -static struct baud_table brg13_ext[] = { - { 300, MAX3107_BRG13_B300 }, - { 600, MAX3107_BRG13_B600 }, - { 1200, MAX3107_BRG13_B1200 }, - { 2400, MAX3107_BRG13_B2400 }, - { 4800, MAX3107_BRG13_B4800 }, - { 9600, MAX3107_BRG13_B9600 }, - { 19200, MAX3107_BRG13_B19200 }, - { 57600, MAX3107_BRG13_B57600 }, - { 115200, MAX3107_BRG13_B115200 }, - { 230400, MAX3107_BRG13_B230400 }, - { 460800, MAX3107_BRG13_B460800 }, - { 921600, MAX3107_BRG13_B921600 }, - { 0, 0 } -}; - -static struct baud_table brg26_ext[] = { +static const struct baud_table brg26_ext[] = { { 300, MAX3107_BRG26_B300 }, { 600, MAX3107_BRG26_B600 }, { 1200, MAX3107_BRG26_B1200 }, @@ -138,7 +52,7 @@ static struct baud_table brg26_ext[] = { { 0, 0 } }; -static struct baud_table brg13_int[] = { +static const struct baud_table brg13_int[] = { { 300, MAX3107_BRG13_IB300 }, { 600, MAX3107_BRG13_IB600 }, { 1200, MAX3107_BRG13_IB1200 }, @@ -157,7 +71,7 @@ static struct baud_table brg13_int[] = { static u32 get_new_brg(int baud, struct max3107_port *s) { int i; - struct baud_table *baud_tbl = s->baud_tbl; + const struct baud_table *baud_tbl = s->baud_tbl; for (i = 0; i < 13; i++) { if (baud == baud_tbl[i].baud) @@ -168,7 +82,7 @@ static u32 get_new_brg(int baud, struct max3107_port *s) } /* Perform SPI transfer for write/read of device register(s) */ -static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len) +int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len) { struct spi_message spi_msg; struct spi_transfer spi_xfer; @@ -213,6 +127,7 @@ static int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len) #endif return 0; } +EXPORT_SYMBOL_GPL(max3107_rw); /* Puts received data to circular buffer */ static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data, @@ -611,16 +526,10 @@ static void max3107_register_init(struct max3107_port *s) s->brg_cfg = MAX3107_BRG13_IB9600; s->baud_tbl = (struct baud_table *)brg13_int; } -#if 0 - /*override for AAVA SC specific*/ - if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { - if (get_koski_build_id() <= KOSKI_EV2) - if (s->ext_clk) { - s->brg_cfg = MAX3107_BRG13_B9600; - s->baud_tbl = (struct baud_table *)brg13_ext; - } - } -#endif + + if (s->pdata->init) + s->pdata->init(s); + buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG) | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK); buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG) @@ -734,7 +643,7 @@ static irqreturn_t max3107_irq(int irqno, void *dev_id) * used but that would mess the GPIOs * */ -static void max3107_hw_susp(struct max3107_port *s, int suspend) +void max3107_hw_susp(struct max3107_port *s, int suspend) { pr_debug("enter, suspend %d\n", suspend); @@ -752,6 +661,7 @@ static void max3107_hw_susp(struct max3107_port *s, int suspend) max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP); } } +EXPORT_SYMBOL_GPL(max3107_hw_susp); /* Modem status IRQ enabling */ static void max3107_enable_ms(struct uart_port *port) @@ -899,10 +809,8 @@ static void max3107_shutdown(struct uart_port *port) { struct max3107_port *s = container_of(port, struct max3107_port, port); - if (s->suspended) { - /* Resume HW */ - max3107_hw_susp(s, 0); - } + if (s->suspended && s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 0); /* Free the interrupt */ free_irq(s->spi->irq, s); @@ -915,7 +823,8 @@ static void max3107_shutdown(struct uart_port *port) } /* Suspend HW */ - max3107_hw_susp(s, 1); + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 1); } /* Port startup function */ @@ -941,7 +850,8 @@ static int max3107_startup(struct uart_port *port) } /* Resume HW */ - max3107_hw_susp(s, 0); + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 0); /* Init registers */ max3107_register_init(s); @@ -973,16 +883,14 @@ static int max3107_request_port(struct uart_port *port) static void max3107_config_port(struct uart_port *port, int flags) { struct max3107_port *s = container_of(port, struct max3107_port, port); - - /* Use PORT_MAX3100 since we are at least int the same series */ - s->port.type = PORT_MAX3100; + s->port.type = PORT_MAX3107; } /* Port verify function */ static int max3107_verify_port(struct uart_port *port, struct serial_struct *ser) { - if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3100) + if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107) return 0; return -EINVAL; @@ -1000,157 +908,6 @@ static void max3107_break_ctl(struct uart_port *port, int break_state) /* We don't support break control, do nothing */ } -/* GPIO direction to input function */ -static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[1]; /* Buffer for SPI transfer */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO configuration register */ - buf[0] = MAX3107_GPIOCFG_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - - /* Set GPIO to input */ - buf[0] &= ~(0x0001 << offset); - - /* Write new GPIO configuration register value */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); - return -EIO; - } - return 0; -} - -/* GPIO direction to output function */ -static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[2]; /* Buffer for SPI transfers */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO configuration and data registers */ - buf[0] = MAX3107_GPIOCFG_REG; - buf[1] = MAX3107_GPIODATA_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { - dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - buf[1] &= MAX3107_SPI_RX_DATA_MASK; - - /* Set GPIO to output */ - buf[0] |= (0x0001 << offset); - /* Set value */ - if (value) - buf[1] |= (0x0001 << offset); - else - buf[1] &= ~(0x0001 << offset); - - /* Write new GPIO configuration and data register values */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); - buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 4)) { - dev_err(&s->spi->dev, - "SPI transfer for GPIO conf data w failed\n"); - return -EIO; - } - return 0; -} - -/* GPIO value query function */ -static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[1]; /* Buffer for SPI transfer */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return -EINVAL; - } - - /* Read current GPIO data register */ - buf[0] = MAX3107_GPIODATA_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { - dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); - return -EIO; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - - /* Return value */ - return buf[0] & (0x0001 << offset); -} - -/* GPIO value set function */ -static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct max3107_port *s = container_of(chip, struct max3107_port, chip); - u16 buf[2]; /* Buffer for SPI transfers */ - - if (offset >= MAX3107_GPIO_COUNT) { - dev_err(&s->spi->dev, "Invalid GPIO\n"); - return; - } - - /* Read current GPIO configuration registers*/ - buf[0] = MAX3107_GPIODATA_REG; - buf[1] = MAX3107_GPIOCFG_REG; - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { - dev_err(&s->spi->dev, - "SPI transfer for GPIO data and config read failed\n"); - return; - } - buf[0] &= MAX3107_SPI_RX_DATA_MASK; - buf[1] &= MAX3107_SPI_RX_DATA_MASK; - - if (!(buf[1] & (0x0001 << offset))) { - /* Configured as input, can't set value */ - dev_warn(&s->spi->dev, - "Trying to set value for input GPIO\n"); - return; - } - - /* Set value */ - if (value) - buf[0] |= (0x0001 << offset); - else - buf[0] &= ~(0x0001 << offset); - - /* Write new GPIO data register value */ - buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); - /* Perform SPI transfer */ - if (max3107_rw(s, (u8 *)buf, NULL, 2)) - dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); -} - -/* Platform data */ -static struct max3107_plat max3107_plat_data = { - .loopback = 0, - .ext_clk = 1, - .max3107_hw_suspend = &max3107_hw_susp, - .polled_mode = 0, - .poll_time = 0, -}; /* Port functions */ static struct uart_ops max3107_ops = { @@ -1180,52 +937,48 @@ static struct uart_driver max3107_uart_driver = { .nr = 1, }; -/* GPIO chip data */ -static struct gpio_chip max3107_gpio_chip = { - .owner = THIS_MODULE, - .direction_input = max3107_gpio_direction_in, - .direction_output = max3107_gpio_direction_out, - .get = max3107_gpio_get, - .set = max3107_gpio_set, - .can_sleep = 1, - .base = MAX3107_GPIO_BASE, - .ngpio = MAX3107_GPIO_COUNT, +static int driver_registered = 0; + + + +/* 'Generic' platform data */ +static struct max3107_plat generic_plat_data = { + .loopback = 0, + .ext_clk = 1, + .hw_suspend = max3107_hw_susp, + .polled_mode = 0, + .poll_time = 0, }; -/* Device probe function */ -static int __devinit max3107_probe(struct spi_device *spi) + + +/*******************************************************************/ + +/** + * max3107_probe - SPI bus probe entry point + * @spi: the spi device + * + * SPI wants us to probe this device and if appropriate claim it. + * Perform any platform specific requirements and then initialise + * the device. + */ + +int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) { struct max3107_port *s; - struct max3107_plat *pdata = &max3107_plat_data; u16 buf[2]; /* Buffer for SPI transfers */ int retval; pr_info("enter max3107 probe\n"); - /* Reset the chip */ - if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { - pr_err("Requesting RESET GPIO failed\n"); - return -EIO; - } - if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { - pr_err("Setting RESET GPIO to 0 failed\n"); - gpio_free(MAX3107_RESET_GPIO); - return -EIO; - } - msleep(MAX3107_RESET_DELAY); - if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { - pr_err("Setting RESET GPIO to 1 failed\n"); - gpio_free(MAX3107_RESET_GPIO); - return -EIO; - } - gpio_free(MAX3107_RESET_GPIO); - msleep(MAX3107_WAKEUP_DELAY); - /* Allocate port structure */ s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) { pr_err("Allocating port structure failed\n"); return -ENOMEM; } + + s->pdata = pdata; + /* SPI Rx buffer * +2 for RX FIFO interrupt * disabling and RX level query @@ -1298,10 +1051,13 @@ static int __devinit max3107_probe(struct spi_device *spi) } /* Register UART driver */ - retval = uart_register_driver(&max3107_uart_driver); - if (retval) { - dev_err(&s->spi->dev, "Registering UART driver failed\n"); - return retval; + if (!driver_registered) { + retval = uart_register_driver(&max3107_uart_driver); + if (retval) { + dev_err(&s->spi->dev, "Registering UART driver failed\n"); + return retval; + } + driver_registered = 1; } /* Initialize UART port data */ @@ -1312,8 +1068,7 @@ static int __devinit max3107_probe(struct spi_device *spi) s->port.uartclk = 9600; s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; s->port.irq = s->spi->irq; - /* Use PORT_MAX3100 since we are at least in the same series */ - s->port.type = PORT_MAX3100; + s->port.type = PORT_MAX3107; /* Add UART port */ retval = uart_add_one_port(&max3107_uart_driver, &s->port); @@ -1322,44 +1077,31 @@ static int __devinit max3107_probe(struct spi_device *spi) return retval; } - /* Initialize GPIO chip data */ - s->chip = max3107_gpio_chip; - s->chip.label = spi->modalias; - s->chip.dev = &spi->dev; - - /* Add GPIO chip */ - retval = gpiochip_add(&s->chip); - if (retval) { - dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); - return retval; + if (pdata->configure) { + retval = pdata->configure(s); + if (retval < 0) + return retval; } - /* Temporary fix for EV2 boot problems, set modem reset to 0 */ - max3107_gpio_direction_out(&s->chip, 3, 0); - /* Go to suspend mode */ - max3107_hw_susp(s, 1); + if (pdata->hw_suspend) + pdata->hw_suspend(s, 1); return 0; } +EXPORT_SYMBOL_GPL(max3107_probe); /* Driver remove function */ -static int __devexit max3107_remove(struct spi_device *spi) +int max3107_remove(struct spi_device *spi) { struct max3107_port *s = dev_get_drvdata(&spi->dev); pr_info("enter max3107 remove\n"); - /* Remove GPIO chip */ - if (gpiochip_remove(&s->chip)) - dev_warn(&s->spi->dev, "Removing GPIO chip failed\n"); - /* Remove port */ if (uart_remove_one_port(&max3107_uart_driver, &s->port)) dev_warn(&s->spi->dev, "Removing UART port failed\n"); - /* Unregister UART driver */ - uart_unregister_driver(&max3107_uart_driver); /* Free TxRx buffer */ kfree(s->rxbuf); @@ -1371,9 +1113,10 @@ static int __devexit max3107_remove(struct spi_device *spi) return 0; } +EXPORT_SYMBOL_GPL(max3107_remove); /* Driver suspend function */ -static int max3107_suspend(struct spi_device *spi, pm_message_t state) +int max3107_suspend(struct spi_device *spi, pm_message_t state) { #ifdef CONFIG_PM struct max3107_port *s = dev_get_drvdata(&spi->dev); @@ -1384,13 +1127,15 @@ static int max3107_suspend(struct spi_device *spi, pm_message_t state) uart_suspend_port(&max3107_uart_driver, &s->port); /* Go to suspend mode */ - max3107_hw_susp(s, 1); + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 1); #endif /* CONFIG_PM */ return 0; } +EXPORT_SYMBOL_GPL(max3107_suspend); /* Driver resume function */ -static int max3107_resume(struct spi_device *spi) +int max3107_resume(struct spi_device *spi) { #ifdef CONFIG_PM struct max3107_port *s = dev_get_drvdata(&spi->dev); @@ -1398,13 +1143,20 @@ static int max3107_resume(struct spi_device *spi) pr_debug("enter resume\n"); /* Resume from suspend */ - max3107_hw_susp(s, 0); + if (s->pdata->hw_suspend) + s->pdata->hw_suspend(s, 0); /* Resume UART port */ uart_resume_port(&max3107_uart_driver, &s->port); #endif /* CONFIG_PM */ return 0; } +EXPORT_SYMBOL_GPL(max3107_resume); + +static int max3107_probe_generic(struct spi_device *spi) +{ + return max3107_probe(spi, &generic_plat_data); +} /* Spi driver data */ static struct spi_driver max3107_driver = { @@ -1413,7 +1165,7 @@ static struct spi_driver max3107_driver = { .bus = &spi_bus_type, .owner = THIS_MODULE, }, - .probe = max3107_probe, + .probe = max3107_probe_generic, .remove = __devexit_p(max3107_remove), .suspend = max3107_suspend, .resume = max3107_resume, @@ -1430,6 +1182,9 @@ static int __init max3107_init(void) static void __exit max3107_exit(void) { pr_info("enter max3107 exit\n"); + /* Unregister UART driver */ + if (driver_registered) + uart_unregister_driver(&max3107_uart_driver); spi_unregister_driver(&max3107_driver); } @@ -1438,5 +1193,5 @@ module_exit(max3107_exit); MODULE_DESCRIPTION("MAX3107 driver"); MODULE_AUTHOR("Aavamobile"); -MODULE_ALIAS("max3107-spi-uart"); -MODULE_LICENSE("GPLv2"); +MODULE_ALIAS("max3107-spi"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/serial/max3107.h b/drivers/serial/max3107.h index a5625d1f263d..72b30415f417 100644 --- a/drivers/serial/max3107.h +++ b/drivers/serial/max3107.h @@ -10,8 +10,8 @@ * (at your option) any later version. */ -#ifndef _LINUX_SERIAL_MAX3107_H -#define _LINUX_SERIAL_MAX3107_H +#ifndef _MAX3107_H +#define _MAX3107_H /* Serial error status definitions */ #define MAX3107_PARITY_ERROR 1 @@ -355,4 +355,85 @@ #define MAX3107_BRG13_IB460800 (0x000000 | 0x00) #define MAX3107_BRG13_IB921600 (0x000000 | 0x00) + +struct baud_table { + int baud; + u32 new_brg; +}; + +struct max3107_port { + /* UART port structure */ + struct uart_port port; + + /* SPI device structure */ + struct spi_device *spi; + + /* GPIO chip stucture */ + struct gpio_chip chip; + + /* Workqueue that does all the magic */ + struct workqueue_struct *workqueue; + struct work_struct work; + + /* Lock for shared data */ + spinlock_t data_lock; + + /* Device configuration */ + int ext_clk; /* 1 if external clock used */ + int loopback; /* Current loopback mode state */ + int baud; /* Current baud rate */ + + /* State flags */ + int suspended; /* Indicates suspend mode */ + int tx_fifo_empty; /* Flag for TX FIFO state */ + int rx_enabled; /* Flag for receiver state */ + int tx_enabled; /* Flag for transmitter state */ + + u16 irqen_reg; /* Current IRQ enable register value */ + /* Shared data */ + u16 mode1_reg; /* Current mode1 register value*/ + int mode1_commit; /* Flag for setting new mode1 register value */ + u16 lcr_reg; /* Current LCR register value */ + int lcr_commit; /* Flag for setting new LCR register value */ + u32 brg_cfg; /* Current Baud rate generator config */ + int brg_commit; /* Flag for setting new baud rate generator + * config + */ + struct baud_table *baud_tbl; + int handle_irq; /* Indicates that IRQ should be handled */ + + /* Rx buffer and str*/ + u16 *rxbuf; + u8 *rxstr; + /* Tx buffer*/ + u16 *txbuf; + + struct max3107_plat *pdata; /* Platform data */ +}; + +/* Platform data structure */ +struct max3107_plat { + /* Loopback mode enable */ + int loopback; + /* External clock enable */ + int ext_clk; + /* Called during the register initialisation */ + void (*init)(struct max3107_port *s); + /* Called when the port is found and configured */ + int (*configure)(struct max3107_port *s); + /* HW suspend function */ + void (*hw_suspend) (struct max3107_port *s, int suspend); + /* Polling mode enable */ + int polled_mode; + /* Polling period if polling mode enabled */ + int poll_time; +}; + +extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len); +extern void max3107_hw_susp(struct max3107_port *s, int suspend); +extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata); +extern int max3107_remove(struct spi_device *spi); +extern int max3107_suspend(struct spi_device *spi, pm_message_t state); +extern int max3107_resume(struct spi_device *spi); + #endif /* _LINUX_SERIAL_MAX3107_H */ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 32928161fab6..9ddc866ccc09 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -186,6 +186,10 @@ #define PORT_ALTERA_JTAGUART 91 #define PORT_ALTERA_UART 92 +/* MAX3107 */ +#define PORT_MAX3107 94 + + #ifdef __KERNEL__ #include -- cgit v1.2.3 From 078dee2d298d003f19203b120b7438beea681e60 Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Wed, 14 Jul 2010 22:04:42 +0400 Subject: serial: crisv10: formatting of pointers in printk() Use %p instead of %08x in printk(). Signed-off-by: Kulikov Vasiliy Signed-off-by: Greg Kroah-Hartman --- drivers/serial/crisv10.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 5696710b6f2d..c856905bb3bd 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -4533,8 +4533,8 @@ static int __init rs_init(void) INIT_WORK(&info->work, do_softint); if (info->enabled) { - printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", - serial_driver->name, info->line, (unsigned int)info->ioport); + printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n", + serial_driver->name, info->line, info->ioport); } } #ifdef CONFIG_ETRAX_FAST_TIMER -- cgit v1.2.3 From e8dd4757a6cf0a8909148a61b89fa3a6d4f9b3ee Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 20 Jul 2010 15:26:10 -0700 Subject: serial: "altera_uart: simplify altera_uart_console_putc()" checkpatch fixes ERROR: code indent should use tabs where possible #32: FILE: drivers/serial/altera_uart.c:397: +^I ALTERA_UART_STATUS_TRDY_MSK))$ total: 1 errors, 0 warnings, 39 lines checked ./patches/altera_uart-simplify-altera_uart_console_putc.patch has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. Please run checkpatch prior to sending patches This fix got lost when someone merged "altera_uart: simplify altera_uart_console_putc()". Please don't lose fixes. Please don't write of mere patches which have trivial checkpatch errors. Cc: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/altera_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/serial') diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 0f1189605d21..f8d8a00554da 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -394,7 +394,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) static void altera_uart_console_putc(struct uart_port *port, const char c) { while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & - ALTERA_UART_STATUS_TRDY_MSK)) + ALTERA_UART_STATUS_TRDY_MSK)) cpu_relax(); writel(c, port->membase + ALTERA_UART_TXDATA_REG); -- cgit v1.2.3 From 1b6331848b69d1ed165a6bdc75c4046d68767563 Mon Sep 17 00:00:00 2001 From: Claudio Scordino Date: Tue, 20 Jul 2010 15:26:47 -0700 Subject: serial: general fixes in the serial_rs485 structure Fix several issues related to the RS485 interface: - It adds the flag SER_RS485_RTS_BEFORE_SEND that was missing from the serial_rs485 structure (even if "delay_rts_before_send" was existing) - It adds a further "delay_rts_after_send" field for those drivers that can have a delay after send (e.g., atmel_serial) - It fixes the usage of the structure in the atmel_serial driver (where "delay_rts_before_send" should be used instead of "delay_rts_after_send"). Signed-off-by: Claudio Scordino Signed-off-by: Bernhard Roth Cc: Philippe De Muyter Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/atmel_serial.c | 11 ++++++++--- include/linux/serial.h | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index a182def7007d..3892666b5fbd 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -217,7 +217,8 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) if (rs485conf->flags & SER_RS485_ENABLED) { dev_dbg(port->dev, "Setting UART to RS485\n"); atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; - UART_PUT_TTGR(port, rs485conf->delay_rts_before_send); + if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) + UART_PUT_TTGR(port, rs485conf->delay_rts_after_send); mode |= ATMEL_US_USMODE_RS485; } else { dev_dbg(port->dev, "Setting UART to RS232\n"); @@ -292,7 +293,9 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) if (atmel_port->rs485.flags & SER_RS485_ENABLED) { dev_dbg(port->dev, "Setting UART to RS485\n"); - UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); + if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + UART_PUT_TTGR(port, + atmel_port->rs485.delay_rts_after_send); mode |= ATMEL_US_USMODE_RS485; } else { dev_dbg(port->dev, "Setting UART to RS232\n"); @@ -1211,7 +1214,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, if (atmel_port->rs485.flags & SER_RS485_ENABLED) { dev_dbg(port->dev, "Setting UART to RS485\n"); - UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); + if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) + UART_PUT_TTGR(port, + atmel_port->rs485.delay_rts_after_send); mode |= ATMEL_US_USMODE_RS485; } else { dev_dbg(port->dev, "Setting UART to RS232\n"); diff --git a/include/linux/serial.h b/include/linux/serial.h index c3b45add494d..ef914061511e 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -210,8 +210,10 @@ struct serial_rs485 { #define SER_RS485_ENABLED (1 << 0) #define SER_RS485_RTS_ON_SEND (1 << 1) #define SER_RS485_RTS_AFTER_SEND (1 << 2) +#define SER_RS485_RTS_BEFORE_SEND (1 << 3) __u32 delay_rts_before_send; /* Milliseconds */ - __u32 padding[6]; /* Memory is cheap, new structs + __u32 delay_rts_after_send; /* Milliseconds */ + __u32 padding[5]; /* Memory is cheap, new structs are a royal PITA .. */ }; -- cgit v1.2.3 From 0ac8382e9cfdd723445692fc97aaa4643929750d Mon Sep 17 00:00:00 2001 From: Yury Georgievskiy Date: Tue, 20 Jul 2010 15:26:50 -0700 Subject: serial: mcf: don't take spinlocks in already protected functions Don't take the port spinlock in uart functions where the serial core already takes care of locking/unlocking them. The code would actually lock up on architectures where spinlocks are implemented. Also protect calling mcf_rx_chars/mcf_tx_chars in the interrupt handler by the port spinlock and use IRQ_RETVAL to return from isr. [akpm@linux-foundation.org: make irq-handler return value more explicit] Signed-off-by: Yury Georgievskiy Cc: Alan Cox Acked-by: Greg Ungerer Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/mcf.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c index b5aaef965f24..3394b7cc1722 100644 --- a/drivers/serial/mcf.c +++ b/drivers/serial/mcf.c @@ -70,16 +70,14 @@ static unsigned int mcf_tx_empty(struct uart_port *port) static unsigned int mcf_get_mctrl(struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); - unsigned long flags; unsigned int sigs; - spin_lock_irqsave(&port->lock, flags); sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS; sigs |= (pp->sigs & TIOCM_RTS); sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); - spin_unlock_irqrestore(&port->lock, flags); + return sigs; } @@ -88,16 +86,13 @@ static unsigned int mcf_get_mctrl(struct uart_port *port) static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); pp->sigs = sigs; mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); if (sigs & TIOCM_RTS) writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); else writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); - spin_unlock_irqrestore(&port->lock, flags); } /****************************************************************************/ @@ -105,12 +100,9 @@ static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) static void mcf_start_tx(struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); pp->imr |= MCFUART_UIR_TXREADY; writeb(pp->imr, port->membase + MCFUART_UIMR); - spin_unlock_irqrestore(&port->lock, flags); } /****************************************************************************/ @@ -118,12 +110,9 @@ static void mcf_start_tx(struct uart_port *port) static void mcf_stop_tx(struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); pp->imr &= ~MCFUART_UIR_TXREADY; writeb(pp->imr, port->membase + MCFUART_UIMR); - spin_unlock_irqrestore(&port->lock, flags); } /****************************************************************************/ @@ -131,12 +120,9 @@ static void mcf_stop_tx(struct uart_port *port) static void mcf_stop_rx(struct uart_port *port) { struct mcf_uart *pp = container_of(port, struct mcf_uart, port); - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); pp->imr &= ~MCFUART_UIR_RXREADY; writeb(pp->imr, port->membase + MCFUART_UIMR); - spin_unlock_irqrestore(&port->lock, flags); } /****************************************************************************/ @@ -366,13 +352,22 @@ static irqreturn_t mcf_interrupt(int irq, void *data) struct uart_port *port = data; struct mcf_uart *pp = container_of(port, struct mcf_uart, port); unsigned int isr; + irqreturn_t ret = IRQ_NONE; isr = readb(port->membase + MCFUART_UISR) & pp->imr; - if (isr & MCFUART_UIR_RXREADY) + + spin_lock(&port->lock); + if (isr & MCFUART_UIR_RXREADY) { mcf_rx_chars(pp); - if (isr & MCFUART_UIR_TXREADY) + ret = IRQ_HANDLED; + } + if (isr & MCFUART_UIR_TXREADY) { mcf_tx_chars(pp); - return IRQ_HANDLED; + ret = IRQ_HANDLED; + } + spin_unlock(&port->lock); + + return ret; } /****************************************************************************/ -- cgit v1.2.3 From 1917ac76e023339c73844bec775375b147f57ac7 Mon Sep 17 00:00:00 2001 From: Samium Gromoff Date: Tue, 20 Jul 2010 15:26:51 -0700 Subject: serial: MMIO32 support for 8250_early.c Provide MMIO32 support in 8250_early (aka earlycon) [randy.dunlap@oracle.com: fix printk format warnings] [akpm@linux-foundation.org: fix printk args some more] Signed-off-by: Samium Gromoff <_deepfire@feelingofgreen.ru> Signed-off-by: Randy Dunlap Cc: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 3 ++ drivers/serial/8250_early.c | 57 +++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 15 deletions(-) (limited to 'drivers/serial') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 44f6b19c50bb..d529b1363e95 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -681,8 +681,11 @@ and is between 256 and 4096 characters. It is defined in the file earlycon= [KNL] Output early console device and options. uart[8250],io,[,options] uart[8250],mmio,[,options] + uart[8250],mmio32,[,options] Start an early, polled-mode console on the 8250/16550 UART at the specified I/O port or MMIO address. + MMIO inter-register address stride is either 8bit (mmio) + or 32bit (mmio32). The options are the same as for ttyS, above. earlyprintk= [X86,SH,BLACKFIN] diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index f279745e9fef..b745792ec25a 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -19,9 +19,11 @@ * The user can specify the device directly, e.g., * earlycon=uart8250,io,0x3f8,9600n8 * earlycon=uart8250,mmio,0xff5e0000,115200n8 + * earlycon=uart8250,mmio32,0xff5e0000,115200n8 * or * console=uart8250,io,0x3f8,9600n8 * console=uart8250,mmio,0xff5e0000,115200n8 + * console=uart8250,mmio32,0xff5e0000,115200n8 */ #include @@ -48,18 +50,31 @@ static struct early_serial8250_device early_device; static unsigned int __init serial_in(struct uart_port *port, int offset) { - if (port->iotype == UPIO_MEM) + switch (port->iotype) { + case UPIO_MEM: return readb(port->membase + offset); - else + case UPIO_MEM32: + return readl(port->membase + (offset << 2)); + case UPIO_PORT: return inb(port->iobase + offset); + default: + return 0; + } } static void __init serial_out(struct uart_port *port, int offset, int value) { - if (port->iotype == UPIO_MEM) + switch (port->iotype) { + case UPIO_MEM: writeb(value, port->membase + offset); - else + break; + case UPIO_MEM32: + writel(value, port->membase + (offset << 2)); + break; + case UPIO_PORT: outb(value, port->iobase + offset); + break; + } } #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) @@ -137,15 +152,21 @@ static int __init parse_options(struct early_serial8250_device *device, char *options) { struct uart_port *port = &device->port; - int mmio, length; + int mmio, mmio32, length; if (!options) return -ENODEV; port->uartclk = BASE_BAUD * 16; - if (!strncmp(options, "mmio,", 5)) { - port->iotype = UPIO_MEM; - port->mapbase = simple_strtoul(options + 5, &options, 0); + + mmio = !strncmp(options, "mmio,", 5); + mmio32 = !strncmp(options, "mmio32,", 7); + if (mmio || mmio32) { + port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32); + port->mapbase = simple_strtoul(options + (mmio ? 5 : 7), + &options, 0); + if (mmio32) + port->regshift = 2; #ifdef CONFIG_FIX_EARLYCON_MEM set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK); @@ -157,11 +178,10 @@ static int __init parse_options(struct early_serial8250_device *device, if (!port->membase) { printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n", __func__, - (unsigned long long)port->mapbase); + (unsigned long long) port->mapbase); return -ENOMEM; } #endif - mmio = 1; } else if (!strncmp(options, "io,", 3)) { port->iotype = UPIO_PORT; port->iobase = simple_strtoul(options + 3, &options, 0); @@ -181,11 +201,18 @@ static int __init parse_options(struct early_serial8250_device *device, device->baud); } - printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n", - mmio ? "MMIO" : "I/O port", - mmio ? (unsigned long long) port->mapbase - : (unsigned long long) port->iobase, - device->options); + if (mmio || mmio32) + printk(KERN_INFO + "Early serial console at MMIO%s 0x%llu (options '%s')\n", + mmio32 ? "32" : "", + (unsigned long long)port->mapbase, + device->options); + else + printk(KERN_INFO + "Early serial console at I/O port 0x%lu (options '%s')\n", + port->iobase, + device->options); + return 0; } -- cgit v1.2.3 From b1a6f24394d44b7bd2c8ec3f301a5eda72ce462f Mon Sep 17 00:00:00 2001 From: Richard Röjfors Date: Tue, 20 Jul 2010 15:26:53 -0700 Subject: timbuart: use __devinit and __devexit macros for probe and remove Move the probe and remove functions to the devinit and devexit sections. Signed-off-by: Richard Röjfors Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/timbuart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c index 67ca642713b8..1f36b7eb7351 100644 --- a/drivers/serial/timbuart.c +++ b/drivers/serial/timbuart.c @@ -423,7 +423,7 @@ static struct uart_driver timbuart_driver = { .nr = 1 }; -static int timbuart_probe(struct platform_device *dev) +static int __devinit timbuart_probe(struct platform_device *dev) { int err, irq; struct timbuart_port *uart; @@ -489,7 +489,7 @@ err_mem: return err; } -static int timbuart_remove(struct platform_device *dev) +static int __devexit timbuart_remove(struct platform_device *dev) { struct timbuart_port *uart = platform_get_drvdata(dev); @@ -507,7 +507,7 @@ static struct platform_driver timbuart_platform_driver = { .owner = THIS_MODULE, }, .probe = timbuart_probe, - .remove = timbuart_remove, + .remove = __devexit_p(timbuart_remove), }; /*--------------------------------------------------------------------------*/ -- cgit v1.2.3 From f5e92c3f9ca148181f1baaec8db271845b2420f0 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Tue, 20 Jul 2010 15:26:54 -0700 Subject: serial: 68328serial.c: remove dead (ALMA_ANS | DRAGONIXVZ | M68EZ328ADS) (ALMA_ANS | DRAGONIXVZ | M68EZ328ADS) doesn't exist in Kconfig, therefore remove all references to it from the source code. Signed-off-by: Christoph Egger Acked-by: Greg Ungerer Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/68328serial.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index d8204f4ebbb4..7356a56ac458 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -98,19 +98,13 @@ static void change_speed(struct m68k_serial *info); * Setup for console. Argument comes from the boot command line. */ -#if defined(CONFIG_M68EZ328ADS) || defined(CONFIG_ALMA_ANS) || defined(CONFIG_DRAGONIXVZ) -#define CONSOLE_BAUD_RATE 115200 -#define DEFAULT_CBAUD B115200 -#else - /* (es) */ - /* note: this is messy, but it works, again, perhaps defined somewhere else?*/ - #ifdef CONFIG_M68VZ328 - #define CONSOLE_BAUD_RATE 19200 - #define DEFAULT_CBAUD B19200 - #endif - /* (/es) */ +/* note: this is messy, but it works, again, perhaps defined somewhere else?*/ +#ifdef CONFIG_M68VZ328 +#define CONSOLE_BAUD_RATE 19200 +#define DEFAULT_CBAUD B19200 #endif + #ifndef CONSOLE_BAUD_RATE #define CONSOLE_BAUD_RATE 9600 #define DEFAULT_CBAUD B9600 -- cgit v1.2.3 From e847003f00d5eca3e3b3a6a1199f82b51293faf6 Mon Sep 17 00:00:00 2001 From: Lytochkin Boris Date: Mon, 26 Jul 2010 10:02:26 +0400 Subject: serial: add support for OX16PCI958 card Signed-off-by: Lytochkin Boris Tested-by: Lytochkin Boris Signed-off-by: Alexander Beregalov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250_pci.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 746a44621d91..53be4d35a0aa 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -994,6 +994,7 @@ static int skip_tx_en_setup(struct serial_private *priv, #define PCI_DEVICE_ID_TITAN_800E 0xA014 #define PCI_DEVICE_ID_TITAN_200EI 0xA016 #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 +#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 @@ -1542,6 +1543,8 @@ enum pci_board_num_t { pbn_b2_4_921600, pbn_b2_8_921600, + pbn_b2_8_1152000, + pbn_b2_bt_1_115200, pbn_b2_bt_2_115200, pbn_b2_bt_4_115200, @@ -1960,6 +1963,13 @@ static struct pciserial_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b2_8_1152000] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 1152000, + .uart_offset = 8, + }, + [pbn_b2_bt_1_115200] = { .flags = FL_BASE2|FL_BASE_BARS, .num_ports = 1, @@ -2875,6 +2885,9 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, + PCI_ANY_ID , PCI_ANY_ID, 0, 0, + pbn_b2_8_1152000 }, /* * Oxford Semiconductor Inc. Tornado PCI express device range. -- cgit v1.2.3 From d843fc6e9dc9bee7061b6833594860ea93ad98e1 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 27 Jul 2010 08:20:22 +0100 Subject: hsu: driver for Medfield High Speed UART device This is a PCI & UART driver, which suppors both PIO and DMA mode UART operation. It has 3 identical UART ports and one internal DMA controller. Current FW will export 4 pci devices for hsu: 3 uart ports and 1 dma controller, each has one IRQ line. And we need to discuss the device model, one PCI device covering whole HSU should be a better model, but there is a problem of how to export the 4 IRQs info Current driver set the highest baud rate to 2746800bps, which is easy to scale down to 115200/230400.... To suport higher baud rate, we need add special process, change DLAB/DLH/PS/DIV/MUL registers all together. 921600 is the highest baud rate that has been tested with Bluetooth modem connected to HSU port 0. Will test more when there is right BT firmware. Current version contains several work around for A0's Silicon bugs Signed-off-by: Feng Tang Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/Kconfig | 10 + drivers/serial/Makefile | 1 + drivers/serial/mfd.c | 1488 +++++++++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 2 + include/linux/serial_mfd.h | 47 ++ include/linux/serial_reg.h | 16 + 6 files changed, 1564 insertions(+) create mode 100644 drivers/serial/mfd.c create mode 100644 include/linux/serial_mfd.h (limited to 'drivers/serial') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index c34c217878b3..a22e60c06f48 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -724,6 +724,16 @@ config MRST_MAX3110_IRQ help This has to be enabled after Moorestown GPIO driver is loaded +config SERIAL_MFD_HSU + tristate "Medfield High Speed UART support" + depends on PCI + select SERIAL_CORE + +config SERIAL_MFD_HSU_CONSOLE + boolean "Medfile HSU serial console support" + depends on SERIAL_MFD_HSU=y + select SERIAL_CORE_CONSOLE + config SERIAL_BFIN tristate "Blackfin serial port support" depends on BLACKFIN diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 424067ac3347..1ca4fd599ffe 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -87,3 +87,4 @@ obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o +obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c new file mode 100644 index 000000000000..300dcb134e07 --- /dev/null +++ b/drivers/serial/mfd.c @@ -0,0 +1,1488 @@ +/* + * mfd.c: driver for High Speed UART device of Intel Medfield platform + * + * Refer pxa.c, 8250.c and some other drivers in drivers/serial/ + * + * (C) Copyright 2009 Intel Corporation + * + * 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; version 2 + * of the License. + */ + + +/* Notes: + * 1. there should be 2 types of register access method, one for + * UART ports, the other for the general purpose registers + * + * 2. It used to have a Irda port, but was defeatured recently + * + * 3. Based on the info from HSU MAS, 0/1 channel are assigned to + * port0, 2/3 chan to port 1, 4/5 chan to port 3. Even number + * chan will be read, odd chan for write + * + * 4. HUS supports both the 64B and 16B FIFO version, but this driver + * will only use 64B version + * + * 5. In A0 stepping, UART will not support TX half empty flag, thus + * need add a #ifdef judgement + * + * 6. One more bug for A0, the loopback mode won't support AFC + * auto-flow control + * + * 7. HSU has some special FCR control bits, we add it to serial_reg.h + * + * 8. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always asserted, + * only when the HW is reset the DDCD and DDSR will be triggered + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MFD_HSU_A0_STEPPING 1 + +#define HSU_DMA_BUF_SIZE 2048 + +#define chan_readl(chan, offset) readl(chan->reg + offset) +#define chan_writel(chan, offset, val) writel(val, chan->reg + offset) + +#define mfd_readl(obj, offset) readl(obj->reg + offset) +#define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) + +struct hsu_dma_buffer { + u8 *buf; + dma_addr_t dma_addr; + u32 dma_size; + u32 ofs; +}; + +struct hsu_dma_chan { + u32 id; + u32 dirt; /* to or from device */ + struct uart_hsu_port *uport; + void __iomem *reg; +}; + +struct uart_hsu_port { + struct uart_port port; + unsigned char ier; + unsigned char lcr; + unsigned char mcr; + unsigned int lsr_break_flag; + char name[12]; + int index; + struct device *dev; + + struct hsu_dma_chan *txc; + struct hsu_dma_chan *rxc; + struct hsu_dma_buffer txbuf; + struct hsu_dma_buffer rxbuf; + int use_dma; /* flag for DMA/PIO */ + int running; + int dma_tx_on; +}; + +/* Top level data structure of HSU */ +struct hsu_port { + struct pci_device *pdev; + + void __iomem *reg; + unsigned long paddr; + unsigned long iolen; + u32 irq; + + struct uart_hsu_port port[3]; + struct hsu_dma_chan chans[10]; + +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs; +#endif +}; + +static inline void hexdump(char *str, u8 *addr, int cnt) +{ + int i; + + for (i = 0; i < cnt; i += 8) { + printk("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + addr[i], addr[i+1], addr[i+2], addr[i+3], + addr[i+4], addr[i+5], addr[i+6], addr[i+7]); + printk("\n"); + } +} + +static inline unsigned int serial_in(struct uart_hsu_port *up, int offset) +{ + unsigned int val; + + if (offset > UART_MSR) { + offset <<= 2; + val = readl(up->port.membase + offset); + } else + val = (unsigned int)readb(up->port.membase + offset); + + return val; +} + +static inline void serial_out(struct uart_hsu_port *up, int offset, int value) +{ + if (offset > UART_MSR) { + offset <<= 2; + writel(value, up->port.membase + offset); + } else { + unsigned char val = value & 0xff; + writeb(val, up->port.membase + offset); + } +} + +#ifdef CONFIG_DEBUG_FS + +#define HSU_REGS_BUFSIZE 1024 + +static int hsu_show_regs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t port_show_regs(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct uart_hsu_port *up = file->private_data; + char *buf; + u32 len = 0; + ssize_t ret; + + buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL); + if (!buf) + return 0; + + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "MFD HSU port[%d] regs:\n", up->index); + + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "=================================\n"); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "IER: \t\t0x%08x\n", serial_in(up, UART_IER)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "PS: \t\t0x%08x\n", serial_in(up, UART_PS)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV)); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + return ret; +} + +static ssize_t dma_show_regs(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct hsu_dma_chan *chan = file->private_data; + char *buf; + u32 len = 0; + ssize_t ret; + + buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL); + if (!buf) + return 0; + + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "MFD HSU DMA channel [%d] regs:\n", chan->id); + + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "=================================\n"); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR)); + len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, + "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR)); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + return ret; +} + +static const struct file_operations port_regs_ops = { + .owner = THIS_MODULE, + .open = hsu_show_regs_open, + .read = port_show_regs, +}; + +static const struct file_operations dma_regs_ops = { + .owner = THIS_MODULE, + .open = hsu_show_regs_open, + .read = dma_show_regs, +}; + +static int hsu_debugfs_init(struct hsu_port *hsu) +{ + int i; + char name[32]; + + hsu->debugfs = debugfs_create_dir("hsu", NULL); + if (!hsu->debugfs) + return -ENOMEM; + + for (i = 0; i < 3; i++) { + snprintf(name, sizeof(name), "port_%d_regs", i); + debugfs_create_file(name, S_IFREG | S_IRUGO, + hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops); + } + + for (i = 0; i < 6; i++) { + snprintf(name, sizeof(name), "dma_chan_%d_regs", i); + debugfs_create_file(name, S_IFREG | S_IRUGO, + hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops); + } + + return 0; +} + +static void hsu_debugfs_remove(struct hsu_port *hsu) +{ + if (hsu->debugfs) + debugfs_remove_recursive(hsu->debugfs); +} + +#else +static inline int hsu_debugfs_init(struct hsu_port *hsu) +{ + return 0; +} + +static inline void hsu_debugfs_remove(struct hsu_port *hsu) +{ +} +#endif /* CONFIG_DEBUG_FS */ + +static void serial_hsu_enable_ms(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + + up->ier |= UART_IER_MSI; + serial_out(up, UART_IER, up->ier); +} + +void hsu_dma_tx(struct uart_hsu_port *up) +{ + struct circ_buf *xmit = &up->port.state->xmit; + struct hsu_dma_buffer *dbuf = &up->txbuf; + int count; + + /* test_and_set_bit may be better, but anyway it's in lock protected mode */ + if (up->dma_tx_on) + return; + + /* Update the circ buf info */ + xmit->tail += dbuf->ofs; + xmit->tail &= UART_XMIT_SIZE - 1; + + up->port.icount.tx += dbuf->ofs; + dbuf->ofs = 0; + + /* Disable the channel */ + chan_writel(up->txc, HSU_CH_CR, 0x0); + + if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) { + dma_sync_single_for_device(up->port.dev, + dbuf->dma_addr, + dbuf->dma_size, + DMA_TO_DEVICE); + + count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); + dbuf->ofs = count; + + /* Reprogram the channel */ + chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail); + chan_writel(up->txc, HSU_CH_D0TSR, count); + + /* Reenable the channel */ + chan_writel(up->txc, HSU_CH_DCR, 0x1 + | (0x1 << 8) + | (0x1 << 16) + | (0x1 << 24)); + + WARN(chan_readl(up->txc, HSU_CH_CR) & 0x1, + "TX channel has already be started!!\n"); + up->dma_tx_on = 1; + chan_writel(up->txc, HSU_CH_CR, 0x1); + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); +} + +/* The buffer is already cache coherent */ +void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) +{ + /* Need start RX dma channel here */ + dbuf->ofs = 0; + + chan_writel(rxc, HSU_CH_BSR, 32); + chan_writel(rxc, HSU_CH_MOTSR, 4); + + chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr); + chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size); + chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8) + | (0x1 << 16) + | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ + ); + chan_writel(rxc, HSU_CH_CR, 0x3); +} + +/* Protected by spin_lock_irqsave(port->lock) */ +static void serial_hsu_start_tx(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + + if (up->use_dma) { + hsu_dma_tx(up); + } else if (!(up->ier & UART_IER_THRI)) { + up->ier |= UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + } +} + +static void serial_hsu_stop_tx(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + struct hsu_dma_chan *txc = up->txc; + + if (up->use_dma) + chan_writel(txc, HSU_CH_CR, 0x0); + else if (up->ier & UART_IER_THRI) { + up->ier &= ~UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + } +} + +/* This is always called in spinlock protected mode, so + * modify timeout timer is safe here */ +void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) +{ + struct hsu_dma_buffer *dbuf = &up->rxbuf; + struct hsu_dma_chan *chan = up->rxc; + struct uart_port *port = &up->port; + struct tty_struct *tty = port->state->port.tty; + int count; + + if (!tty) + return; + + /* + * first need to know how many is already transferred, + * then check if its a timeout DMA irq, and return + * the trail bytes out, push them up and reenable the + * channel, better to use 2 descriptors at the same time + */ + + /* timeout IRQ, need wait some time, see Errata 2 */ + if (int_sts & 0xf00) + udelay(2); + + /* Stop the channel */ + chan_writel(chan, HSU_CH_CR, 0x0); + + /* We can use 2 ways to calc the actual transfer len */ + count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; + + if (!count) + return; + + dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, + dbuf->dma_size, DMA_FROM_DEVICE); + + /* + * head will only wrap around when we recycle + * the DMA buffer, and when that happens, we + * explicitly set tail to 0. So head will + * always be greater than tail. + */ + tty_insert_flip_string(tty, dbuf->buf, count); + port->icount.rx += count; + + dma_sync_single_for_device(up->port.dev, dbuf->dma_addr, + dbuf->dma_size, DMA_FROM_DEVICE); + + /* Reprogram the channel */ + chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr); + chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size); + chan_writel(chan, HSU_CH_DCR, 0x1 + | (0x1 << 8) + | (0x1 << 16) + | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ + ); + chan_writel(chan, HSU_CH_CR, 0x3); + + tty_flip_buffer_push(tty); +} + +static void serial_hsu_stop_rx(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + struct hsu_dma_chan *chan = up->rxc; + + if (up->use_dma) + chan_writel(chan, HSU_CH_CR, 0x2); + else { + up->ier &= ~UART_IER_RLSI; + up->port.read_status_mask &= ~UART_LSR_DR; + serial_out(up, UART_IER, up->ier); + } +} + +/* + * if there is error flag, should we just reset the FIFO or keeps + * working on it + */ +static inline void receive_chars(struct uart_hsu_port *up, int *status) +{ + struct tty_struct *tty = up->port.state->port.tty; + unsigned int ch, flag; + unsigned int max_count = 256; + + if (!tty) + return; + + do { + ch = serial_in(up, UART_RX); + flag = TTY_NORMAL; + up->port.icount.rx++; + + if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE))) { + + dev_warn(up->dev, "We really rush into ERR/BI case" + "status = 0x%02x", *status); + /* For statistics only */ + if (*status & UART_LSR_BI) { + *status &= ~(UART_LSR_FE | UART_LSR_PE); + up->port.icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(&up->port)) + goto ignore_char; + } else if (*status & UART_LSR_PE) + up->port.icount.parity++; + else if (*status & UART_LSR_FE) + up->port.icount.frame++; + if (*status & UART_LSR_OE) + up->port.icount.overrun++; + + /* Mask off conditions which should be ignored. */ + *status &= up->port.read_status_mask; + +#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE + if (up->port.cons && + up->port.cons->index == up->port.line) { + /* Recover the break flag from console xmit */ + *status |= up->lsr_break_flag; + up->lsr_break_flag = 0; + } +#endif + if (*status & UART_LSR_BI) { + flag = TTY_BREAK; + } else if (*status & UART_LSR_PE) + flag = TTY_PARITY; + else if (*status & UART_LSR_FE) + flag = TTY_FRAME; + } + + if (uart_handle_sysrq_char(&up->port, ch)) + goto ignore_char; + + uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); + ignore_char: + *status = serial_in(up, UART_LSR); + } while ((*status & UART_LSR_DR) && max_count--); + tty_flip_buffer_push(tty); +} + +static void transmit_chars(struct uart_hsu_port *up) +{ + struct circ_buf *xmit = &up->port.state->xmit; + int count; + int i = 0; /* for debug use */ + + if (up->port.x_char) { + serial_out(up, UART_TX, up->port.x_char); + up->port.icount.tx++; + up->port.x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { + serial_hsu_stop_tx(&up->port); + return; + } + +#ifndef MFD_HSU_A0_STEPPING + count = up->port.fifosize / 2; +#else + /* + * A0 only supports fully empty IRQ, and the first char written + * into it won't clear the EMPT bit, so we may need be cautious + * by useing a shorter buffer + */ + /* count = up->port.fifosize; */ + count = up->port.fifosize - 4; +#endif + do { + serial_out(up, UART_TX, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + i++; + + up->port.icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + + if (uart_circ_empty(xmit)) + serial_hsu_stop_tx(&up->port); +} + +static inline void check_modem_status(struct uart_hsu_port *up) +{ + int status; + + status = serial_in(up, UART_MSR); + + if ((status & UART_MSR_ANY_DELTA) == 0) + return; + + if (status & UART_MSR_TERI) + up->port.icount.rng++; + if (status & UART_MSR_DDSR) + up->port.icount.dsr++; + /* We may only get DDCD when HW init and reset */ + if (status & UART_MSR_DDCD) + uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); + /* will start/stop_tx accordingly */ + if (status & UART_MSR_DCTS) + uart_handle_cts_change(&up->port, status & UART_MSR_CTS); + + wake_up_interruptible(&up->port.state->port.delta_msr_wait); +} + +/* + * This handles the interrupt from one port. + */ +static irqreturn_t port_irq(int irq, void *dev_id) +{ + struct uart_hsu_port *up = dev_id; + unsigned int iir, lsr; + unsigned long flags; + + if (unlikely(!up->running)) + return IRQ_NONE; + + if (up->use_dma) { + lsr = serial_in(up, UART_LSR); + if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE))) + dev_warn(up->dev, + "Got lsr irq while using DMA, lsr = 0x%2x\n", + lsr); + check_modem_status(up); + return IRQ_HANDLED; + } + + spin_lock_irqsave(&up->port.lock, flags); + iir = serial_in(up, UART_IIR); + if (iir & UART_IIR_NO_INT) { + spin_unlock_irqrestore(&up->port.lock, flags); + return IRQ_NONE; + } + + lsr = serial_in(up, UART_LSR); + + if (lsr & UART_LSR_DR) + receive_chars(up, &lsr); + + /* lsr will be renewed during the receive_chars */ + if (lsr & UART_LSR_THRE) + transmit_chars(up); + + spin_unlock_irqrestore(&up->port.lock, flags); + return IRQ_HANDLED; +} + +static inline void dma_chan_irq(struct hsu_dma_chan *chan) +{ + struct uart_hsu_port *up = chan->uport; + unsigned long flags; + u32 int_sts; + + spin_lock_irqsave(&up->port.lock, flags); + + if (!up->use_dma || !up->running) + goto exit; + + /* + * No matter what situation, need read clear the IRQ status + * There is a bug, see Errata 5, HSD 2900918 + */ + int_sts = chan_readl(chan, HSU_CH_SR); + + /* Rx channel */ + if (chan->dirt == DMA_FROM_DEVICE) + hsu_dma_rx(up, int_sts); + + /* Tx channel */ + if (chan->dirt == DMA_TO_DEVICE) { + /* dma for irq should be done */ + chan_writel(chan, HSU_CH_CR, 0x0); + up->dma_tx_on = 0; + hsu_dma_tx(up); + } + +exit: + spin_unlock_irqrestore(&up->port.lock, flags); + return; +} + +static irqreturn_t dma_irq(int irq, void *dev_id) +{ + struct hsu_port *hsu = dev_id; + u32 int_sts, i; + + int_sts = mfd_readl(hsu, HSU_GBL_DMAISR); + + /* Currently we only have 6 channels may be used */ + for (i = 0; i < 6; i++) { + if (int_sts & 0x1) + dma_chan_irq(&hsu->chans[i]); + int_sts >>= 1; + } + + return IRQ_HANDLED; +} + +static unsigned int serial_hsu_tx_empty(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + unsigned long flags; + unsigned int ret; + + spin_lock_irqsave(&up->port.lock, flags); + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; + spin_unlock_irqrestore(&up->port.lock, flags); + + return ret; +} + +static unsigned int serial_hsu_get_mctrl(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + unsigned char status; + unsigned int ret; + + status = serial_in(up, UART_MSR); + + ret = 0; + if (status & UART_MSR_DCD) + ret |= TIOCM_CAR; + if (status & UART_MSR_RI) + ret |= TIOCM_RNG; + if (status & UART_MSR_DSR) + ret |= TIOCM_DSR; + if (status & UART_MSR_CTS) + ret |= TIOCM_CTS; + return ret; +} + +static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + unsigned char mcr = 0; + + if (mctrl & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (mctrl & TIOCM_DTR) + mcr |= UART_MCR_DTR; + if (mctrl & TIOCM_OUT1) + mcr |= UART_MCR_OUT1; + if (mctrl & TIOCM_OUT2) + mcr |= UART_MCR_OUT2; + if (mctrl & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + + mcr |= up->mcr; + + serial_out(up, UART_MCR, mcr); +} + +static void serial_hsu_break_ctl(struct uart_port *port, int break_state) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_out(up, UART_LCR, up->lcr); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +/* + * What special to do: + * 1. chose the 64B fifo mode + * 2. make sure not to select half empty mode for A0 stepping + * 3. start dma or pio depends on configuration + * 4. we only allocate dma memory when needed + */ +static int serial_hsu_startup(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + unsigned long flags; + + /* + * Clear the FIFO buffers and disable them. + * (they will be reenabled in set_termios()) + */ + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial_out(up, UART_FCR, 0); + + /* Clear the interrupt registers. */ + (void) serial_in(up, UART_LSR); + (void) serial_in(up, UART_RX); + (void) serial_in(up, UART_IIR); + (void) serial_in(up, UART_MSR); + + /* Now, initialize the UART, default is 8n1 */ + serial_out(up, UART_LCR, UART_LCR_WLEN8); + + spin_lock_irqsave(&up->port.lock, flags); + + up->port.mctrl |= TIOCM_OUT2; + serial_hsu_set_mctrl(&up->port, up->port.mctrl); + + /* + * Finally, enable interrupts. Note: Modem status interrupts + * are set via set_termios(), which will be occurring imminently + * anyway, so we don't enable them here. + */ + if (!up->use_dma) + up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE; + else + up->ier = 0; + serial_out(up, UART_IER, up->ier); + + spin_unlock_irqrestore(&up->port.lock, flags); + + /* DMA init */ + /* When use DMA, TX/RX's FIFO and IRQ should be disabled */ + if (up->use_dma) { + struct hsu_dma_buffer *dbuf; + struct circ_buf *xmit = &port->state->xmit; + + up->dma_tx_on = 0; + + /* First allocate the RX buffer */ + dbuf = &up->rxbuf; + dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL); + if (!dbuf->buf) { + up->use_dma = 0; + goto exit; + } + dbuf->dma_addr = dma_map_single(port->dev, + dbuf->buf, + HSU_DMA_BUF_SIZE, + DMA_FROM_DEVICE); + dbuf->dma_size = HSU_DMA_BUF_SIZE; + + /* Start the RX channel right now */ + hsu_dma_start_rx_chan(up->rxc, dbuf); + + /* Next init the TX DMA */ + dbuf = &up->txbuf; + dbuf->buf = xmit->buf; + dbuf->dma_addr = dma_map_single(port->dev, + dbuf->buf, + UART_XMIT_SIZE, + DMA_TO_DEVICE); + dbuf->dma_size = UART_XMIT_SIZE; + + /* This should not be changed all around */ + chan_writel(up->txc, HSU_CH_BSR, 32); + chan_writel(up->txc, HSU_CH_MOTSR, 4); + dbuf->ofs = 0; + } + +exit: + /* And clear the interrupt registers again for luck. */ + (void) serial_in(up, UART_LSR); + (void) serial_in(up, UART_RX); + (void) serial_in(up, UART_IIR); + (void) serial_in(up, UART_MSR); + + up->running = 1; + return 0; +} + +static void serial_hsu_shutdown(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + unsigned long flags; + + /* Disable interrupts from this port */ + up->ier = 0; + serial_out(up, UART_IER, 0); + up->running = 0; + + spin_lock_irqsave(&up->port.lock, flags); + up->port.mctrl &= ~TIOCM_OUT2; + serial_hsu_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + + /* Disable break condition and FIFOs */ + serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT); + serial_out(up, UART_FCR, 0); +} + +static void +serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + struct tty_struct *tty = port->state->port.tty; + unsigned char cval, fcr = 0; + unsigned long flags; + unsigned int baud, quot; + u32 mul = 0x3600; + u32 ps = 0x10; + + switch (termios->c_cflag & CSIZE) { + case CS5: + cval = UART_LCR_WLEN5; + break; + case CS6: + cval = UART_LCR_WLEN6; + break; + case CS7: + cval = UART_LCR_WLEN7; + break; + default: + case CS8: + cval = UART_LCR_WLEN8; + break; + } + + /* CMSPAR isn't supported by this driver */ + if (tty) + tty->termios->c_cflag &= ~CMSPAR; + + if (termios->c_cflag & CSTOPB) + cval |= UART_LCR_STOP; + if (termios->c_cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(termios->c_cflag & PARODD)) + cval |= UART_LCR_EPAR; + + /* + * For those basic low baud rate we can get the direct + * scalar from 2746800, like 115200 = 2746800/24, for those + * higher baud rate, we have to handle them case by case, + * but DIV reg is never touched as its default value 0x3d09 + */ + baud = uart_get_baud_rate(port, termios, old, 0, 4000000); + quot = uart_get_divisor(port, baud); + + switch (baud) { + case 3500000: + mul = 0x3345; + ps = 0xC; + quot = 1; + break; + case 2500000: + mul = 0x2710; + ps = 0x10; + quot = 1; + break; + case 18432000: + mul = 0x2400; + ps = 0x10; + quot = 1; + break; + case 1500000: + mul = 0x1D4C; + ps = 0xc; + quot = 1; + break; + default: + ; + } + + if ((up->port.uartclk / quot) < (2400 * 16)) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B; + else if ((up->port.uartclk / quot) < (230400 * 16)) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B; + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B; + + fcr |= UART_FCR_HSU_64B_FIFO; +#ifdef MFD_HSU_A0_STEPPING + /* A0 doesn't support half empty IRQ */ + fcr |= UART_FCR_FULL_EMPT_TXI; +#endif + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&up->port.lock, flags); + + /* Update the per-port timeout */ + uart_update_timeout(port, termios->c_cflag, baud); + + up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (termios->c_iflag & INPCK) + up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (termios->c_iflag & (BRKINT | PARMRK)) + up->port.read_status_mask |= UART_LSR_BI; + + /* Characters to ignore */ + up->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (termios->c_iflag & IGNBRK) { + up->port.ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_OE; + } + + /* Ignore all characters if CREAD is not set */ + if ((termios->c_cflag & CREAD) == 0) + up->port.ignore_status_mask |= UART_LSR_DR; + + /* + * CTS flow control flag and modem status interrupts, disable + * MSI by default + */ + up->ier &= ~UART_IER_MSI; + if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + up->ier |= UART_IER_MSI; + + serial_out(up, UART_IER, up->ier); + + if (termios->c_cflag & CRTSCTS) + up->mcr |= UART_MCR_AFE | UART_MCR_RTS; + else + up->mcr &= ~UART_MCR_AFE; + + serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ + serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ + serial_out(up, UART_LCR, cval); /* reset DLAB */ + serial_out(up, UART_MUL, mul); /* set MUL */ + serial_out(up, UART_PS, ps); /* set PS */ + up->lcr = cval; /* Save LCR */ + serial_hsu_set_mctrl(&up->port, up->port.mctrl); + serial_out(up, UART_FCR, fcr); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static void +serial_hsu_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ +} + +static void serial_hsu_release_port(struct uart_port *port) +{ +} + +static int serial_hsu_request_port(struct uart_port *port) +{ + return 0; +} + +static void serial_hsu_config_port(struct uart_port *port, int flags) +{ +#if 0 + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + up->port.type = PORT_MFD; +#endif +} + +static int +serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + /* We don't want the core code to modify any port params */ + return -EINVAL; +} + +static const char * +serial_hsu_type(struct uart_port *port) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + return up->name; +} + +/* Mainly for uart console use */ +static struct uart_hsu_port *serial_hsu_ports[3]; +static struct uart_driver serial_hsu_reg; + +#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +/* Wait for transmitter & holding register to empty */ +static inline void wait_for_xmitr(struct uart_hsu_port *up) +{ + unsigned int status, tmout = 1000; + + /* Wait up to 1ms for the character to be sent. */ + do { + status = serial_in(up, UART_LSR); + + if (status & UART_LSR_BI) + up->lsr_break_flag = UART_LSR_BI; + + if (--tmout == 0) + break; + udelay(1); + } while (!(status & BOTH_EMPTY)); + + /* Wait up to 1s for flow control if necessary */ + if (up->port.flags & UPF_CONS_FLOW) { + tmout = 1000000; + while (--tmout && + ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) + udelay(1); + } +} + +static void serial_hsu_console_putchar(struct uart_port *port, int ch) +{ + struct uart_hsu_port *up = + container_of(port, struct uart_hsu_port, port); + + wait_for_xmitr(up); + serial_out(up, UART_TX, ch); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +static void +serial_hsu_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_hsu_port *up = serial_hsu_ports[co->index]; + unsigned long flags; + unsigned int ier; + int locked = 1; + + local_irq_save(flags); + if (up->port.sysrq) + locked = 0; + else if (oops_in_progress) { + locked = spin_trylock(&up->port.lock); + } else + spin_lock(&up->port.lock); + + /* First save the IER then disable the interrupts */ + ier = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0); + + uart_console_write(&up->port, s, count, serial_hsu_console_putchar); + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(up); + serial_out(up, UART_IER, ier); + + if (locked) + spin_unlock(&up->port.lock); + local_irq_restore(flags); +} + +static struct console serial_hsu_console; + +static int __init +serial_hsu_console_setup(struct console *co, char *options) +{ + struct uart_hsu_port *up; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + int ret; + + if (co->index == -1 || co->index >= serial_hsu_reg.nr) + co->index = 0; + up = serial_hsu_ports[co->index]; + if (!up) + return -ENODEV; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + ret = uart_set_options(&up->port, co, baud, parity, bits, flow); + + return ret; +} + +static struct console serial_hsu_console = { + .name = "ttyMFD", + .write = serial_hsu_console_write, + .device = uart_console_device, + .setup = serial_hsu_console_setup, + .flags = CON_PRINTBUFFER, + .index = 2, + .data = &serial_hsu_reg, +}; +#endif + +struct uart_ops serial_hsu_pops = { + .tx_empty = serial_hsu_tx_empty, + .set_mctrl = serial_hsu_set_mctrl, + .get_mctrl = serial_hsu_get_mctrl, + .stop_tx = serial_hsu_stop_tx, + .start_tx = serial_hsu_start_tx, + .stop_rx = serial_hsu_stop_rx, + .enable_ms = serial_hsu_enable_ms, + .break_ctl = serial_hsu_break_ctl, + .startup = serial_hsu_startup, + .shutdown = serial_hsu_shutdown, + .set_termios = serial_hsu_set_termios, + .pm = serial_hsu_pm, + .type = serial_hsu_type, + .release_port = serial_hsu_release_port, + .request_port = serial_hsu_request_port, + .config_port = serial_hsu_config_port, + .verify_port = serial_hsu_verify_port, +}; + +static struct uart_driver serial_hsu_reg = { + .owner = THIS_MODULE, + .driver_name = "MFD serial", + .dev_name = "ttyMFD", + .major = TTY_MAJOR, + .minor = 128, + .nr = 3, +}; + +#ifdef CONFIG_PM +static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct uart_hsu_port *up; + + up = pci_get_drvdata(pdev); + if (!up) + return 0; + + uart_suspend_port(&serial_hsu_reg, &up->port); + + return 0; +} + +static int serial_hsu_resume(struct pci_dev *pdev) +{ + struct uart_hsu_port *up; + + up = pci_get_drvdata(pdev); + if (!up) + return 0; + uart_resume_port(&serial_hsu_reg, &up->port); + return 0; +} +#else +#define serial_hsu_suspend NULL +#define serial_hsu_resume NULL +#endif + +/* temp global pointer before we settle down on using one or four PCI dev */ +static struct hsu_port *phsu; + +static int serial_hsu_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct uart_hsu_port *uport; + int index, ret; + + printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n", + pdev->vendor, pdev->device); + + switch (pdev->device) { + case 0x081B: + index = 0; + break; + case 0x081C: + index = 1; + break; + case 0x081D: + index = 2; + break; + case 0x081E: + /* internal DMA controller */ + index = 3; + break; + default: + dev_err(&pdev->dev, "HSU: out of index!"); + return -ENODEV; + } + + ret = pci_enable_device(pdev); + if (ret) + return ret; + + if (index == 3) { + /* DMA controller */ + ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu); + if (ret) { + dev_err(&pdev->dev, "can not get IRQ\n"); + goto err_disable; + } + pci_set_drvdata(pdev, phsu); + } else { + /* UART port 0~2 */ + uport = &phsu->port[index]; + uport->port.irq = pdev->irq; + uport->port.dev = &pdev->dev; + uport->dev = &pdev->dev; + + ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport); + if (ret) { + dev_err(&pdev->dev, "can not get IRQ\n"); + goto err_disable; + } + uart_add_one_port(&serial_hsu_reg, &uport->port); + +#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE + if (index == 2) { + register_console(&serial_hsu_console); + uport->port.cons = &serial_hsu_console; + } +#endif + pci_set_drvdata(pdev, uport); + } + + return 0; + +err_disable: + pci_disable_device(pdev); + return ret; +} + +static void hsu_global_init(void) +{ + struct hsu_port *hsu; + struct uart_hsu_port *uport; + struct hsu_dma_chan *dchan; + int i, ret; + + hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL); + if (!hsu) + return; + + /* Get basic io resource and map it */ + hsu->paddr = 0xffa28000; + hsu->iolen = 0x1000; + + if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global"))) + pr_warning("HSU: error in request mem region\n"); + + hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen); + if (!hsu->reg) { + pr_err("HSU: error in ioremap\n"); + ret = -ENOMEM; + goto err_free_region; + } + + /* Initialise the 3 UART ports */ + uport = hsu->port; + for (i = 0; i < 3; i++) { + uport->port.type = PORT_MFD; + uport->port.iotype = UPIO_MEM; + uport->port.mapbase = (resource_size_t)hsu->paddr + + HSU_PORT_REG_OFFSET + + i * HSU_PORT_REG_LENGTH; + uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET + + i * HSU_PORT_REG_LENGTH; + + sprintf(uport->name, "hsu_port%d", i); + uport->port.fifosize = 64; + uport->port.ops = &serial_hsu_pops; + uport->port.line = i; + uport->port.flags = UPF_IOREMAP; + /* make the maxim support rate to 2746800 bps */ + uport->port.uartclk = 115200 * 24 * 16; + + uport->running = 0; + uport->txc = &hsu->chans[i * 2]; + uport->rxc = &hsu->chans[i * 2 + 1]; + + serial_hsu_ports[i] = uport; + uport->index = i; + uport++; + } + + /* Initialise 6 dma channels */ + dchan = hsu->chans; + for (i = 0; i < 6; i++) { + dchan->id = i; + dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + dchan->uport = &hsu->port[i/2]; + dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + + i * HSU_DMA_CHANS_REG_LENGTH; + dchan++; + } + + phsu = hsu; + + hsu_debugfs_init(hsu); + return; + +err_free_region: + release_mem_region(hsu->paddr, hsu->iolen); + kfree(hsu); + return; +} + +static void serial_hsu_remove(struct pci_dev *pdev) +{ + struct hsu_port *hsu; + int i; + + hsu = pci_get_drvdata(pdev); + if (!hsu) + return; + + for (i = 0; i < 3; i++) + uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port); + + pci_set_drvdata(pdev, NULL); + free_irq(hsu->irq, hsu); + pci_disable_device(pdev); +} + +/* First 3 are UART ports, and the 4th is the DMA */ +static const struct pci_device_id pci_ids[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) }, + {}, +}; + +static struct pci_driver hsu_pci_driver = { + .name = "HSU serial", + .id_table = pci_ids, + .probe = serial_hsu_probe, + .remove = __devexit_p(serial_hsu_remove), + .suspend = serial_hsu_suspend, + .resume = serial_hsu_resume, +}; + +static int __init hsu_pci_init(void) +{ + int ret; + + hsu_global_init(); + + ret = uart_register_driver(&serial_hsu_reg); + if (ret) + return ret; + + return pci_register_driver(&hsu_pci_driver); +} + +static void __exit hsu_pci_exit(void) +{ + pci_unregister_driver(&hsu_pci_driver); + uart_unregister_driver(&serial_hsu_reg); + + hsu_debugfs_remove(phsu); + + kfree(phsu); +} + +module_init(hsu_pci_init); +module_exit(hsu_pci_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:medfield-hsu"); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9ddc866ccc09..f8fce351463d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -189,6 +189,8 @@ /* MAX3107 */ #define PORT_MAX3107 94 +/* High Speed UART for Medfield */ +#define PORT_MFD 95 #ifdef __KERNEL__ diff --git a/include/linux/serial_mfd.h b/include/linux/serial_mfd.h new file mode 100644 index 000000000000..2b071e0b034d --- /dev/null +++ b/include/linux/serial_mfd.h @@ -0,0 +1,47 @@ +#ifndef _SERIAL_MFD_H_ +#define _SERIAL_MFD_H_ + +/* HW register offset definition */ +#define UART_FOR 0x08 +#define UART_PS 0x0C +#define UART_MUL 0x0D +#define UART_DIV 0x0E + +#define HSU_GBL_IEN 0x0 +#define HSU_GBL_IST 0x4 + +#define HSU_GBL_INT_BIT_PORT0 0x0 +#define HSU_GBL_INT_BIT_PORT1 0x1 +#define HSU_GBL_INT_BIT_PORT2 0x2 +#define HSU_GBL_INT_BIT_IRI 0x3 +#define HSU_GBL_INT_BIT_HDLC 0x4 +#define HSU_GBL_INT_BIT_DMA 0x5 + +#define HSU_GBL_ISR 0x8 +#define HSU_GBL_DMASR 0x400 +#define HSU_GBL_DMAISR 0x404 + +#define HSU_PORT_REG_OFFSET 0x80 +#define HSU_PORT0_REG_OFFSET 0x80 +#define HSU_PORT1_REG_OFFSET 0x100 +#define HSU_PORT2_REG_OFFSET 0x180 +#define HSU_PORT_REG_LENGTH 0x80 + +#define HSU_DMA_CHANS_REG_OFFSET 0x500 +#define HSU_DMA_CHANS_REG_LENGTH 0x40 + +#define HSU_CH_SR 0x0 /* channel status reg */ +#define HSU_CH_CR 0x4 /* control reg */ +#define HSU_CH_DCR 0x8 /* descriptor control reg */ +#define HSU_CH_BSR 0x10 /* max fifo buffer size reg */ +#define HSU_CH_MOTSR 0x14 /* minimum ocp transfer size */ +#define HSU_CH_D0SAR 0x20 /* desc 0 start addr */ +#define HSU_CH_D0TSR 0x24 /* desc 0 transfer size */ +#define HSU_CH_D1SAR 0x28 +#define HSU_CH_D1TSR 0x2C +#define HSU_CH_D2SAR 0x30 +#define HSU_CH_D2TSR 0x34 +#define HSU_CH_D3SAR 0x38 +#define HSU_CH_D3TSR 0x3C + +#endif diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index cf9327c051ad..c7a0ce11cd47 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h @@ -221,8 +221,24 @@ #define UART_FCR_PXAR16 0x80 /* receive FIFO threshold = 16 */ #define UART_FCR_PXAR32 0xc0 /* receive FIFO threshold = 32 */ +/* + * Intel MID on-chip HSU (High Speed UART) defined bits + */ +#define UART_FCR_HSU_64_1B 0x00 /* receive FIFO treshold = 1 */ +#define UART_FCR_HSU_64_16B 0x40 /* receive FIFO treshold = 16 */ +#define UART_FCR_HSU_64_32B 0x80 /* receive FIFO treshold = 32 */ +#define UART_FCR_HSU_64_56B 0xc0 /* receive FIFO treshold = 56 */ + +#define UART_FCR_HSU_16_1B 0x00 /* receive FIFO treshold = 1 */ +#define UART_FCR_HSU_16_4B 0x40 /* receive FIFO treshold = 4 */ +#define UART_FCR_HSU_16_8B 0x80 /* receive FIFO treshold = 8 */ +#define UART_FCR_HSU_16_14B 0xc0 /* receive FIFO treshold = 14 */ +#define UART_FCR_HSU_64B_FIFO 0x20 /* chose 64 bytes FIFO */ +#define UART_FCR_HSU_16B_FIFO 0x00 /* chose 16 bytes FIFO */ +#define UART_FCR_HALF_EMPT_TXI 0x00 /* trigger TX_EMPT IRQ for half empty */ +#define UART_FCR_FULL_EMPT_TXI 0x08 /* trigger TX_EMPT IRQ for full empty */ /* * These register definitions are for the 16C950 -- cgit v1.2.3 From 669b7a0938e759097c150400cd36bd49befaf5bb Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 27 Jul 2010 08:20:32 +0100 Subject: hsu: add a periodic timer to check dma rx channel A general problem for uart rx dma channel is you never know when and how much data will be received, so usually preset it a DMA descriptor with a big size, and rely on DMA RX timeout IRQ to know there is some data in rx channel. For a RX data size of multiple of MOTSR, there will be no timeout IRQ issued, thus OS will never be notified about that. This is a work around for that, current timer frequency is 5 times per second, it should vary according to the baud rate When future silicon version fix the problem, this workaround need be removed Signed-off-by: Feng Tang Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/mfd.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index 300dcb134e07..ed2bf6b14a4a 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c @@ -64,6 +64,8 @@ #define mfd_readl(obj, offset) readl(obj->reg + offset) #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) +#define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10) + struct hsu_dma_buffer { u8 *buf; dma_addr_t dma_addr; @@ -75,7 +77,8 @@ struct hsu_dma_chan { u32 id; u32 dirt; /* to or from device */ struct uart_hsu_port *uport; - void __iomem *reg; + void __iomem *reg; + struct timer_list rx_timer; /* only needed by RX channel */ }; struct uart_hsu_port { @@ -377,6 +380,8 @@ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ ); chan_writel(rxc, HSU_CH_CR, 0x3); + + mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); } /* Protected by spin_lock_irqsave(port->lock) */ @@ -437,8 +442,13 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) /* We can use 2 ways to calc the actual transfer len */ count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; - if (!count) + if (!count) { + /* restart the channel before we leave */ + chan_writel(chan, HSU_CH_CR, 0x3); return; + } + + del_timer(&chan->rx_timer); dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, dbuf->dma_size, DMA_FROM_DEVICE); @@ -463,9 +473,12 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | (0x1 << 16) | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ ); + tty_flip_buffer_push(tty); + chan_writel(chan, HSU_CH_CR, 0x3); + chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ; + add_timer(&chan->rx_timer); - tty_flip_buffer_push(tty); } static void serial_hsu_stop_rx(struct uart_port *port) @@ -893,6 +906,8 @@ static void serial_hsu_shutdown(struct uart_port *port) container_of(port, struct uart_hsu_port, port); unsigned long flags; + del_timer_sync(&up->rxc->rx_timer); + /* Disable interrupts from this port */ up->ier = 0; serial_out(up, UART_IER, 0); @@ -1348,6 +1363,28 @@ err_disable: return ret; } +static void hsu_dma_rx_timeout(unsigned long data) +{ + struct hsu_dma_chan *chan = (void *)data; + struct uart_hsu_port *up = chan->uport; + struct hsu_dma_buffer *dbuf = &up->rxbuf; + int count = 0; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + + count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; + + if (!count) { + mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); + goto exit; + } + + hsu_dma_rx(up, 0); +exit: + spin_unlock_irqrestore(&up->port.lock, flags); +} + static void hsu_global_init(void) { struct hsu_port *hsu; @@ -1409,6 +1446,13 @@ static void hsu_global_init(void) dchan->uport = &hsu->port[i/2]; dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + i * HSU_DMA_CHANS_REG_LENGTH; + + /* Work around for RX */ + if (dchan->dirt == DMA_FROM_DEVICE) { + init_timer(&dchan->rx_timer); + dchan->rx_timer.function = hsu_dma_rx_timeout; + dchan->rx_timer.data = (unsigned long)dchan; + } dchan++; } -- cgit v1.2.3 From 06c77e21ae7c199435097116b8212b0761fc8ba8 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 27 Jul 2010 08:20:42 +0100 Subject: hsu: some code cleanup Major changes are: * refine the comments in the driver * remove unused member from structure "hsu_port" * extended spin_lock protoction for dma mode in port_irq() Signed-off-by: Feng Tang Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/mfd.c | 85 ++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 66 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index ed2bf6b14a4a..f5e7569c1773 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c @@ -3,7 +3,7 @@ * * Refer pxa.c, 8250.c and some other drivers in drivers/serial/ * - * (C) Copyright 2009 Intel Corporation + * (C) Copyright 2010 Intel Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,30 +11,16 @@ * of the License. */ - /* Notes: - * 1. there should be 2 types of register access method, one for - * UART ports, the other for the general purpose registers - * - * 2. It used to have a Irda port, but was defeatured recently - * - * 3. Based on the info from HSU MAS, 0/1 channel are assigned to - * port0, 2/3 chan to port 1, 4/5 chan to port 3. Even number - * chan will be read, odd chan for write - * - * 4. HUS supports both the 64B and 16B FIFO version, but this driver - * will only use 64B version + * 1. DMA channel allocation: 0/1 channel are assigned to port 0, + * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans + * are used for RX, odd chans for TX * - * 5. In A0 stepping, UART will not support TX half empty flag, thus - * need add a #ifdef judgement + * 2. In A0 stepping, UART will not support TX half empty flag * - * 6. One more bug for A0, the loopback mode won't support AFC - * auto-flow control - * - * 7. HSU has some special FCR control bits, we add it to serial_reg.h - * - * 8. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always asserted, - * only when the HW is reset the DDCD and DDSR will be triggered + * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always + * asserted, only when the HW is reset the DDCD and DDSR will + * be triggered */ #include @@ -75,7 +61,7 @@ struct hsu_dma_buffer { struct hsu_dma_chan { u32 id; - u32 dirt; /* to or from device */ + enum dma_data_direction dirt; struct uart_hsu_port *uport; void __iomem *reg; struct timer_list rx_timer; /* only needed by RX channel */ @@ -102,8 +88,6 @@ struct uart_hsu_port { /* Top level data structure of HSU */ struct hsu_port { - struct pci_device *pdev; - void __iomem *reg; unsigned long paddr; unsigned long iolen; @@ -112,23 +96,9 @@ struct hsu_port { struct uart_hsu_port port[3]; struct hsu_dma_chan chans[10]; -#ifdef CONFIG_DEBUG_FS struct dentry *debugfs; -#endif }; -static inline void hexdump(char *str, u8 *addr, int cnt) -{ - int i; - - for (i = 0; i < cnt; i += 8) { - printk("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", - addr[i], addr[i+1], addr[i+2], addr[i+3], - addr[i+4], addr[i+5], addr[i+6], addr[i+7]); - printk("\n"); - } -} - static inline unsigned int serial_in(struct uart_hsu_port *up, int offset) { unsigned int val; @@ -353,9 +323,6 @@ void hsu_dma_tx(struct uart_hsu_port *up) | (0x1 << 8) | (0x1 << 16) | (0x1 << 24)); - - WARN(chan_readl(up->txc, HSU_CH_CR) & 0x1, - "TX channel has already be started!!\n"); up->dma_tx_on = 1; chan_writel(up->txc, HSU_CH_CR, 0x1); } @@ -367,7 +334,6 @@ void hsu_dma_tx(struct uart_hsu_port *up) /* The buffer is already cache coherent */ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) { - /* Need start RX dma channel here */ dbuf->ofs = 0; chan_writel(rxc, HSU_CH_BSR, 32); @@ -426,35 +392,32 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) return; /* - * first need to know how many is already transferred, + * First need to know how many is already transferred, * then check if its a timeout DMA irq, and return * the trail bytes out, push them up and reenable the - * channel, better to use 2 descriptors at the same time + * channel */ - /* timeout IRQ, need wait some time, see Errata 2 */ + /* Timeout IRQ, need wait some time, see Errata 2 */ if (int_sts & 0xf00) udelay(2); /* Stop the channel */ chan_writel(chan, HSU_CH_CR, 0x0); - /* We can use 2 ways to calc the actual transfer len */ count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; - if (!count) { - /* restart the channel before we leave */ + /* Restart the channel before we leave */ chan_writel(chan, HSU_CH_CR, 0x3); return; } - del_timer(&chan->rx_timer); dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, dbuf->dma_size, DMA_FROM_DEVICE); /* - * head will only wrap around when we recycle + * Head will only wrap around when we recycle * the DMA buffer, and when that happens, we * explicitly set tail to 0. So head will * always be greater than tail. @@ -496,10 +459,6 @@ static void serial_hsu_stop_rx(struct uart_port *port) } } -/* - * if there is error flag, should we just reset the FIFO or keeps - * working on it - */ static inline void receive_chars(struct uart_hsu_port *up, int *status) { struct tty_struct *tty = up->port.state->port.tty; @@ -571,7 +530,6 @@ static void transmit_chars(struct uart_hsu_port *up) { struct circ_buf *xmit = &up->port.state->xmit; int count; - int i = 0; /* for debug use */ if (up->port.x_char) { serial_out(up, UART_TX, up->port.x_char); @@ -592,13 +550,11 @@ static void transmit_chars(struct uart_hsu_port *up) * into it won't clear the EMPT bit, so we may need be cautious * by useing a shorter buffer */ - /* count = up->port.fifosize; */ count = up->port.fifosize - 4; #endif do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - i++; up->port.icount.tx++; if (uart_circ_empty(xmit)) @@ -628,7 +584,7 @@ static inline void check_modem_status(struct uart_hsu_port *up) /* We may only get DDCD when HW init and reset */ if (status & UART_MSR_DDCD) uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); - /* will start/stop_tx accordingly */ + /* Will start/stop_tx accordingly */ if (status & UART_MSR_DCTS) uart_handle_cts_change(&up->port, status & UART_MSR_CTS); @@ -647,6 +603,7 @@ static irqreturn_t port_irq(int irq, void *dev_id) if (unlikely(!up->running)) return IRQ_NONE; + spin_lock_irqsave(&up->port.lock, flags); if (up->use_dma) { lsr = serial_in(up, UART_LSR); if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | @@ -655,10 +612,10 @@ static irqreturn_t port_irq(int irq, void *dev_id) "Got lsr irq while using DMA, lsr = 0x%2x\n", lsr); check_modem_status(up); + spin_unlock_irqrestore(&up->port.lock, flags); return IRQ_HANDLED; } - spin_lock_irqsave(&up->port.lock, flags); iir = serial_in(up, UART_IIR); if (iir & UART_IIR_NO_INT) { spin_unlock_irqrestore(&up->port.lock, flags); @@ -666,9 +623,9 @@ static irqreturn_t port_irq(int irq, void *dev_id) } lsr = serial_in(up, UART_LSR); - if (lsr & UART_LSR_DR) receive_chars(up, &lsr); + check_modem_status(up); /* lsr will be renewed during the receive_chars */ if (lsr & UART_LSR_THRE) @@ -701,7 +658,6 @@ static inline void dma_chan_irq(struct hsu_dma_chan *chan) /* Tx channel */ if (chan->dirt == DMA_TO_DEVICE) { - /* dma for irq should be done */ chan_writel(chan, HSU_CH_CR, 0x0); up->dma_tx_on = 0; hsu_dma_tx(up); @@ -851,7 +807,6 @@ static int serial_hsu_startup(struct uart_port *port) spin_unlock_irqrestore(&up->port.lock, flags); /* DMA init */ - /* When use DMA, TX/RX's FIFO and IRQ should be disabled */ if (up->use_dma) { struct hsu_dma_buffer *dbuf; struct circ_buf *xmit = &port->state->xmit; @@ -1090,11 +1045,9 @@ static int serial_hsu_request_port(struct uart_port *port) static void serial_hsu_config_port(struct uart_port *port, int flags) { -#if 0 struct uart_hsu_port *up = container_of(port, struct uart_hsu_port, port); up->port.type = PORT_MFD; -#endif } static int @@ -1426,7 +1379,7 @@ static void hsu_global_init(void) uport->port.ops = &serial_hsu_pops; uport->port.line = i; uport->port.flags = UPF_IOREMAP; - /* make the maxim support rate to 2746800 bps */ + /* set the scalable maxim support rate to 2746800 bps */ uport->port.uartclk = 115200 * 24 * 16; uport->running = 0; -- cgit v1.2.3 From 3c4108c82f7769fcd265dc77a5bb0c6d8bcea25f Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Tue, 27 Jul 2010 08:20:52 +0100 Subject: hsu: call PCI pm hooks in suspend/resume function Also add check for dma controller or the uart ports. Signed-off-by: Feng Tang Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/mfd.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index f5e7569c1773..bc9af503907f 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c @@ -1217,25 +1217,38 @@ static struct uart_driver serial_hsu_reg = { #ifdef CONFIG_PM static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state) { + void *priv = pci_get_drvdata(pdev); struct uart_hsu_port *up; - up = pci_get_drvdata(pdev); - if (!up) - return 0; - - uart_suspend_port(&serial_hsu_reg, &up->port); + /* Make sure this is not the internal dma controller */ + if (priv && (pdev->device != 0x081E)) { + up = priv; + uart_suspend_port(&serial_hsu_reg, &up->port); + } + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } static int serial_hsu_resume(struct pci_dev *pdev) { + void *priv = pci_get_drvdata(pdev); struct uart_hsu_port *up; + int ret; - up = pci_get_drvdata(pdev); - if (!up) - return 0; - uart_resume_port(&serial_hsu_reg, &up->port); + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + ret = pci_enable_device(pdev); + if (ret) + dev_warn(&pdev->dev, + "HSU: can't re-enable device, try to continue\n"); + + if (priv && (pdev->device != 0x081E)) { + up = priv; + uart_resume_port(&serial_hsu_reg, &up->port); + } return 0; } #else -- cgit v1.2.3 From e38018be3e7c03dd7e8f4ab0e1d55407cebbf89d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 27 Jul 2010 08:16:05 +0100 Subject: serial: max3107: Fix gpiolib support Because of the way gpiolib works we actually need to ifdef this in our header file Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/max3107.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/max3107.h b/drivers/serial/max3107.h index 72b30415f417..7ab632392502 100644 --- a/drivers/serial/max3107.h +++ b/drivers/serial/max3107.h @@ -368,8 +368,10 @@ struct max3107_port { /* SPI device structure */ struct spi_device *spi; +#if defined(CONFIG_GPIOLIB) /* GPIO chip stucture */ struct gpio_chip chip; +#endif /* Workqueue that does all the magic */ struct workqueue_struct *workqueue; -- cgit v1.2.3 From 235dae5d094c415fcf0fc79fa637f1901bc8afe2 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 29 Jul 2010 17:13:57 +0200 Subject: U6715 16550A serial driver support UART Features extract from STEricsson U6715 data-sheet (arm926 SoC for mobile phone): * Fully compatible with industry standard 16C550 and 16C450 from various manufacturers * RX and TX 64 byte FIFO reduces CPU interrupts * Full double buffering * Modem control signals include CTS, RTS, (and DSR, DTR on UART1 only) * Automatic baud rate selection * Manual or automatic RTS/CTS smart hardware flow control * Programmable serial characteristics: – Baud rate generation (50 to 3.25M baud) – 5, 6, 7 or 8-bit characters – Even, odd or no-parity bit generation and detection – 1, 1.5 or 2 stop bit generation * Independent control of transmit, receive, line status, data set interrupts and FIFOs * Full status-reporting capabilities * Separate DMA signaling for RX and TX * Timed interrupt to spread receive interrupt on known duration * DMA time-out interrupt to allow detection of end of reception * Carkit pulse coding and decoding compliant with USB carkit control interface [40] In 16550A auto-configuration, if the fifo size is 64 then it's an U6 16550A port Add set_termios hook & export serial8250_do_set_termios to change uart clock following baudrate Signed-off-by: Philippe Langlais Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250.c | 37 ++++++++++++++++++++++++++++++++++--- include/linux/serial.h | 3 ++- include/linux/serial_8250.h | 5 +++++ include/linux/serial_core.h | 3 +++ 4 files changed, 44 insertions(+), 4 deletions(-) (limited to 'drivers/serial') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 355148dc085e..24110f6f61e0 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -300,6 +300,13 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, + [PORT_U6_16550A] = { + .name = "U6_16550A", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, }; #if defined(CONFIG_MIPS_ALCHEMY) @@ -1070,6 +1077,15 @@ static void autoconfig_16550a(struct uart_8250_port *up) DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); } serial_outp(up, UART_IER, iersave); + + /* + * We distinguish between 16550A and U6 16550A by counting + * how many bytes are in the FIFO. + */ + if (up->port.type == PORT_16550A && size_fifo(up) == 64) { + up->port.type = PORT_U6_16550A; + up->capabilities |= UART_CAP_AFE; + } } /* @@ -2224,9 +2240,9 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int return quot; } -static void -serial8250_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) +void +serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char cval, fcr = 0; @@ -2402,6 +2418,17 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); } +EXPORT_SYMBOL(serial8250_do_set_termios); + +static void +serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + if (port->set_termios) + port->set_termios(port, termios, old); + else + serial8250_do_set_termios(port, termios, old); +} static void serial8250_set_ldisc(struct uart_port *port, int new) @@ -2982,6 +3009,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) port.type = p->type; port.serial_in = p->serial_in; port.serial_out = p->serial_out; + port.set_termios = p->set_termios; port.dev = &dev->dev; port.irqflags |= irqflag; ret = serial8250_register_port(&port); @@ -3145,6 +3173,9 @@ int serial8250_register_port(struct uart_port *port) uart->port.serial_in = port->serial_in; if (port->serial_out) uart->port.serial_out = port->serial_out; + /* Possibly override set_termios call */ + if (port->set_termios) + uart->port.set_termios = port->set_termios; ret = uart_add_one_port(&serial8250_reg, &uart->port); if (ret == 0) diff --git a/include/linux/serial.h b/include/linux/serial.h index ef914061511e..1ebc694a6d52 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -77,7 +77,8 @@ struct serial_struct { #define PORT_16654 11 #define PORT_16850 12 #define PORT_RSA 13 /* RSA-DV II/S card */ -#define PORT_MAX 13 +#define PORT_U6_16550A 14 +#define PORT_MAX 14 #define SERIAL_IO_PORT 0 #define SERIAL_IO_HUB6 1 diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index fb46aba11fb5..7638deaaba65 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -32,6 +32,9 @@ struct plat_serial8250_port { unsigned int type; /* If UPF_FIXED_TYPE */ unsigned int (*serial_in)(struct uart_port *, int); void (*serial_out)(struct uart_port *, int, int); + void (*set_termios)(struct uart_port *, + struct ktermios *new, + struct ktermios *old); }; /* @@ -71,5 +74,7 @@ extern int early_serial_setup(struct uart_port *port); extern int serial8250_find_port(struct uart_port *p); extern int serial8250_find_port_for_earlycon(void); extern int setup_early_serial8250_console(char *cmdline); +extern void serial8250_do_set_termios(struct uart_port *port, + struct ktermios *termios, struct ktermios *old); #endif diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f8fce351463d..8129ca2d57e3 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -282,6 +282,9 @@ struct uart_port { unsigned char __iomem *membase; /* read/write[bwl] */ unsigned int (*serial_in)(struct uart_port *, int); void (*serial_out)(struct uart_port *, int, int); + void (*set_termios)(struct uart_port *, + struct ktermios *new, + struct ktermios *old); unsigned int irq; /* irq number */ unsigned long irqflags; /* irq flags */ unsigned int uartclk; /* base uart clock */ -- cgit v1.2.3